linux/net/batman-adv/bat_v.c
<<
>>
Prefs
   1/* Copyright (C) 2013-2016 B.A.T.M.A.N. contributors:
   2 *
   3 * Linus Lüssing, Marek Lindner
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of version 2 of the GNU General Public
   7 * License as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but
  10 * WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12 * General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18#include "bat_v.h"
  19#include "main.h"
  20
  21#include <linux/atomic.h>
  22#include <linux/bug.h>
  23#include <linux/cache.h>
  24#include <linux/errno.h>
  25#include <linux/if_ether.h>
  26#include <linux/init.h>
  27#include <linux/jiffies.h>
  28#include <linux/kernel.h>
  29#include <linux/kref.h>
  30#include <linux/netdevice.h>
  31#include <linux/netlink.h>
  32#include <linux/rculist.h>
  33#include <linux/rcupdate.h>
  34#include <linux/seq_file.h>
  35#include <linux/stddef.h>
  36#include <linux/types.h>
  37#include <linux/workqueue.h>
  38#include <net/genetlink.h>
  39#include <net/netlink.h>
  40#include <uapi/linux/batman_adv.h>
  41
  42#include "bat_algo.h"
  43#include "bat_v_elp.h"
  44#include "bat_v_ogm.h"
  45#include "gateway_client.h"
  46#include "gateway_common.h"
  47#include "hard-interface.h"
  48#include "hash.h"
  49#include "log.h"
  50#include "netlink.h"
  51#include "originator.h"
  52#include "packet.h"
  53
  54struct sk_buff;
  55
  56static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface)
  57{
  58        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
  59        struct batadv_hard_iface *primary_if;
  60
  61        primary_if = batadv_primary_if_get_selected(bat_priv);
  62
  63        if (primary_if) {
  64                batadv_v_elp_iface_activate(primary_if, hard_iface);
  65                batadv_hardif_put(primary_if);
  66        }
  67
  68        /* B.A.T.M.A.N. V does not use any queuing mechanism, therefore it can
  69         * set the interface as ACTIVE right away, without any risk of race
  70         * condition
  71         */
  72        if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED)
  73                hard_iface->if_status = BATADV_IF_ACTIVE;
  74}
  75
  76static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
  77{
  78        int ret;
  79
  80        ret = batadv_v_elp_iface_enable(hard_iface);
  81        if (ret < 0)
  82                return ret;
  83
  84        ret = batadv_v_ogm_iface_enable(hard_iface);
  85        if (ret < 0)
  86                batadv_v_elp_iface_disable(hard_iface);
  87
  88        return ret;
  89}
  90
  91static void batadv_v_iface_disable(struct batadv_hard_iface *hard_iface)
  92{
  93        batadv_v_elp_iface_disable(hard_iface);
  94}
  95
  96static void batadv_v_primary_iface_set(struct batadv_hard_iface *hard_iface)
  97{
  98        batadv_v_elp_primary_iface_set(hard_iface);
  99        batadv_v_ogm_primary_iface_set(hard_iface);
 100}
 101
 102/**
 103 * batadv_v_iface_update_mac - react to hard-interface MAC address change
 104 * @hard_iface: the modified interface
 105 *
 106 * If the modified interface is the primary one, update the originator
 107 * address in the ELP and OGM messages to reflect the new MAC address.
 108 */
 109static void batadv_v_iface_update_mac(struct batadv_hard_iface *hard_iface)
 110{
 111        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 112        struct batadv_hard_iface *primary_if;
 113
 114        primary_if = batadv_primary_if_get_selected(bat_priv);
 115        if (primary_if != hard_iface)
 116                goto out;
 117
 118        batadv_v_primary_iface_set(hard_iface);
 119out:
 120        if (primary_if)
 121                batadv_hardif_put(primary_if);
 122}
 123
 124static void
 125batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
 126{
 127        ewma_throughput_init(&hardif_neigh->bat_v.throughput);
 128        INIT_WORK(&hardif_neigh->bat_v.metric_work,
 129                  batadv_v_elp_throughput_metric_update);
 130}
 131
 132#ifdef CONFIG_BATMAN_ADV_DEBUGFS
 133/**
 134 * batadv_v_orig_print_neigh - print neighbors for the originator table
 135 * @orig_node: the orig_node for which the neighbors are printed
 136 * @if_outgoing: outgoing interface for these entries
 137 * @seq: debugfs table seq_file struct
 138 *
 139 * Must be called while holding an rcu lock.
 140 */
 141static void
 142batadv_v_orig_print_neigh(struct batadv_orig_node *orig_node,
 143                          struct batadv_hard_iface *if_outgoing,
 144                          struct seq_file *seq)
 145{
 146        struct batadv_neigh_node *neigh_node;
 147        struct batadv_neigh_ifinfo *n_ifinfo;
 148
 149        hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
 150                n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
 151                if (!n_ifinfo)
 152                        continue;
 153
 154                seq_printf(seq, " %pM (%9u.%1u)",
 155                           neigh_node->addr,
 156                           n_ifinfo->bat_v.throughput / 10,
 157                           n_ifinfo->bat_v.throughput % 10);
 158
 159                batadv_neigh_ifinfo_put(n_ifinfo);
 160        }
 161}
 162
 163/**
 164 * batadv_v_hardif_neigh_print - print a single ELP neighbour node
 165 * @seq: neighbour table seq_file struct
 166 * @hardif_neigh: hardif neighbour information
 167 */
 168static void
 169batadv_v_hardif_neigh_print(struct seq_file *seq,
 170                            struct batadv_hardif_neigh_node *hardif_neigh)
 171{
 172        int last_secs, last_msecs;
 173        u32 throughput;
 174
 175        last_secs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) / 1000;
 176        last_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen) % 1000;
 177        throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
 178
 179        seq_printf(seq, "%pM %4i.%03is (%9u.%1u) [%10s]\n",
 180                   hardif_neigh->addr, last_secs, last_msecs, throughput / 10,
 181                   throughput % 10, hardif_neigh->if_incoming->net_dev->name);
 182}
 183
 184/**
 185 * batadv_v_neigh_print - print the single hop neighbour list
 186 * @bat_priv: the bat priv with all the soft interface information
 187 * @seq: neighbour table seq_file struct
 188 */
 189static void batadv_v_neigh_print(struct batadv_priv *bat_priv,
 190                                 struct seq_file *seq)
 191{
 192        struct net_device *net_dev = (struct net_device *)seq->private;
 193        struct batadv_hardif_neigh_node *hardif_neigh;
 194        struct batadv_hard_iface *hard_iface;
 195        int batman_count = 0;
 196
 197        seq_puts(seq,
 198                 "  Neighbor        last-seen ( throughput) [        IF]\n");
 199
 200        rcu_read_lock();
 201        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
 202                if (hard_iface->soft_iface != net_dev)
 203                        continue;
 204
 205                hlist_for_each_entry_rcu(hardif_neigh,
 206                                         &hard_iface->neigh_list, list) {
 207                        batadv_v_hardif_neigh_print(seq, hardif_neigh);
 208                        batman_count++;
 209                }
 210        }
 211        rcu_read_unlock();
 212
 213        if (batman_count == 0)
 214                seq_puts(seq, "No batman nodes in range ...\n");
 215}
 216#endif
 217
 218/**
 219 * batadv_v_neigh_dump_neigh - Dump a neighbour into a message
 220 * @msg: Netlink message to dump into
 221 * @portid: Port making netlink request
 222 * @seq: Sequence number of netlink message
 223 * @hardif_neigh: Neighbour to dump
 224 *
 225 * Return: Error code, or 0 on success
 226 */
 227static int
 228batadv_v_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
 229                          struct batadv_hardif_neigh_node *hardif_neigh)
 230{
 231        void *hdr;
 232        unsigned int last_seen_msecs;
 233        u32 throughput;
 234
 235        last_seen_msecs = jiffies_to_msecs(jiffies - hardif_neigh->last_seen);
 236        throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
 237        throughput = throughput * 100;
 238
 239        hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
 240                          BATADV_CMD_GET_NEIGHBORS);
 241        if (!hdr)
 242                return -ENOBUFS;
 243
 244        if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
 245                    hardif_neigh->addr) ||
 246            nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
 247                        hardif_neigh->if_incoming->net_dev->ifindex) ||
 248            nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
 249                        last_seen_msecs) ||
 250            nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput))
 251                goto nla_put_failure;
 252
 253        genlmsg_end(msg, hdr);
 254        return 0;
 255
 256 nla_put_failure:
 257        genlmsg_cancel(msg, hdr);
 258        return -EMSGSIZE;
 259}
 260
 261/**
 262 * batadv_v_neigh_dump_hardif - Dump the  neighbours of a hard interface  into
 263 *  a message
 264 * @msg: Netlink message to dump into
 265 * @portid: Port making netlink request
 266 * @seq: Sequence number of netlink message
 267 * @bat_priv: The bat priv with all the soft interface information
 268 * @hard_iface: The hard interface to be dumped
 269 * @idx_s: Entries to be skipped
 270 *
 271 * This function assumes the caller holds rcu_read_lock().
 272 *
 273 * Return: Error code, or 0 on success
 274 */
 275static int
 276batadv_v_neigh_dump_hardif(struct sk_buff *msg, u32 portid, u32 seq,
 277                           struct batadv_priv *bat_priv,
 278                           struct batadv_hard_iface *hard_iface,
 279                           int *idx_s)
 280{
 281        struct batadv_hardif_neigh_node *hardif_neigh;
 282        int idx = 0;
 283
 284        hlist_for_each_entry_rcu(hardif_neigh,
 285                                 &hard_iface->neigh_list, list) {
 286                if (idx++ < *idx_s)
 287                        continue;
 288
 289                if (batadv_v_neigh_dump_neigh(msg, portid, seq, hardif_neigh)) {
 290                        *idx_s = idx - 1;
 291                        return -EMSGSIZE;
 292                }
 293        }
 294
 295        *idx_s = 0;
 296        return 0;
 297}
 298
 299/**
 300 * batadv_v_neigh_dump - Dump the neighbours of a hard interface  into a
 301 *  message
 302 * @msg: Netlink message to dump into
 303 * @cb: Control block containing additional options
 304 * @bat_priv: The bat priv with all the soft interface information
 305 * @single_hardif: Limit dumping to this hard interface
 306 */
 307static void
 308batadv_v_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
 309                    struct batadv_priv *bat_priv,
 310                    struct batadv_hard_iface *single_hardif)
 311{
 312        struct batadv_hard_iface *hard_iface;
 313        int i_hardif = 0;
 314        int i_hardif_s = cb->args[0];
 315        int idx = cb->args[1];
 316        int portid = NETLINK_CB(cb->skb).portid;
 317
 318        rcu_read_lock();
 319        if (single_hardif) {
 320                if (i_hardif_s == 0) {
 321                        if (batadv_v_neigh_dump_hardif(msg, portid,
 322                                                       cb->nlh->nlmsg_seq,
 323                                                       bat_priv, single_hardif,
 324                                                       &idx) == 0)
 325                                i_hardif++;
 326                }
 327        } else {
 328                list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
 329                        if (hard_iface->soft_iface != bat_priv->soft_iface)
 330                                continue;
 331
 332                        if (i_hardif++ < i_hardif_s)
 333                                continue;
 334
 335                        if (batadv_v_neigh_dump_hardif(msg, portid,
 336                                                       cb->nlh->nlmsg_seq,
 337                                                       bat_priv, hard_iface,
 338                                                       &idx)) {
 339                                i_hardif--;
 340                                break;
 341                        }
 342                }
 343        }
 344        rcu_read_unlock();
 345
 346        cb->args[0] = i_hardif;
 347        cb->args[1] = idx;
 348}
 349
 350#ifdef CONFIG_BATMAN_ADV_DEBUGFS
 351/**
 352 * batadv_v_orig_print - print the originator table
 353 * @bat_priv: the bat priv with all the soft interface information
 354 * @seq: debugfs table seq_file struct
 355 * @if_outgoing: the outgoing interface for which this should be printed
 356 */
 357static void batadv_v_orig_print(struct batadv_priv *bat_priv,
 358                                struct seq_file *seq,
 359                                struct batadv_hard_iface *if_outgoing)
 360{
 361        struct batadv_neigh_node *neigh_node;
 362        struct batadv_hashtable *hash = bat_priv->orig_hash;
 363        int last_seen_msecs, last_seen_secs;
 364        struct batadv_orig_node *orig_node;
 365        struct batadv_neigh_ifinfo *n_ifinfo;
 366        unsigned long last_seen_jiffies;
 367        struct hlist_head *head;
 368        int batman_count = 0;
 369        u32 i;
 370
 371        seq_puts(seq,
 372                 "  Originator      last-seen ( throughput)           Nexthop [outgoingIF]:   Potential nexthops ...\n");
 373
 374        for (i = 0; i < hash->size; i++) {
 375                head = &hash->table[i];
 376
 377                rcu_read_lock();
 378                hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
 379                        neigh_node = batadv_orig_router_get(orig_node,
 380                                                            if_outgoing);
 381                        if (!neigh_node)
 382                                continue;
 383
 384                        n_ifinfo = batadv_neigh_ifinfo_get(neigh_node,
 385                                                           if_outgoing);
 386                        if (!n_ifinfo)
 387                                goto next;
 388
 389                        last_seen_jiffies = jiffies - orig_node->last_seen;
 390                        last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
 391                        last_seen_secs = last_seen_msecs / 1000;
 392                        last_seen_msecs = last_seen_msecs % 1000;
 393
 394                        seq_printf(seq, "%pM %4i.%03is (%9u.%1u) %pM [%10s]:",
 395                                   orig_node->orig, last_seen_secs,
 396                                   last_seen_msecs,
 397                                   n_ifinfo->bat_v.throughput / 10,
 398                                   n_ifinfo->bat_v.throughput % 10,
 399                                   neigh_node->addr,
 400                                   neigh_node->if_incoming->net_dev->name);
 401
 402                        batadv_v_orig_print_neigh(orig_node, if_outgoing, seq);
 403                        seq_puts(seq, "\n");
 404                        batman_count++;
 405
 406next:
 407                        batadv_neigh_node_put(neigh_node);
 408                        if (n_ifinfo)
 409                                batadv_neigh_ifinfo_put(n_ifinfo);
 410                }
 411                rcu_read_unlock();
 412        }
 413
 414        if (batman_count == 0)
 415                seq_puts(seq, "No batman nodes in range ...\n");
 416}
 417#endif
 418
 419/**
 420 * batadv_v_orig_dump_subentry - Dump an originator subentry into a
 421 *  message
 422 * @msg: Netlink message to dump into
 423 * @portid: Port making netlink request
 424 * @seq: Sequence number of netlink message
 425 * @bat_priv: The bat priv with all the soft interface information
 426 * @if_outgoing: Limit dump to entries with this outgoing interface
 427 * @orig_node: Originator to dump
 428 * @neigh_node: Single hops neighbour
 429 * @best: Is the best originator
 430 *
 431 * Return: Error code, or 0 on success
 432 */
 433static int
 434batadv_v_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
 435                            struct batadv_priv *bat_priv,
 436                            struct batadv_hard_iface *if_outgoing,
 437                            struct batadv_orig_node *orig_node,
 438                            struct batadv_neigh_node *neigh_node,
 439                            bool best)
 440{
 441        struct batadv_neigh_ifinfo *n_ifinfo;
 442        unsigned int last_seen_msecs;
 443        u32 throughput;
 444        void *hdr;
 445
 446        n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
 447        if (!n_ifinfo)
 448                return 0;
 449
 450        throughput = n_ifinfo->bat_v.throughput * 100;
 451
 452        batadv_neigh_ifinfo_put(n_ifinfo);
 453
 454        last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_seen);
 455
 456        if (if_outgoing != BATADV_IF_DEFAULT &&
 457            if_outgoing != neigh_node->if_incoming)
 458                return 0;
 459
 460        hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
 461                          BATADV_CMD_GET_ORIGINATORS);
 462        if (!hdr)
 463                return -ENOBUFS;
 464
 465        if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) ||
 466            nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
 467                    neigh_node->addr) ||
 468            nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
 469                        neigh_node->if_incoming->net_dev->ifindex) ||
 470            nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput) ||
 471            nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
 472                        last_seen_msecs))
 473                goto nla_put_failure;
 474
 475        if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
 476                goto nla_put_failure;
 477
 478        genlmsg_end(msg, hdr);
 479        return 0;
 480
 481 nla_put_failure:
 482        genlmsg_cancel(msg, hdr);
 483        return -EMSGSIZE;
 484}
 485
 486/**
 487 * batadv_v_orig_dump_entry - Dump an originator entry into a message
 488 * @msg: Netlink message to dump into
 489 * @portid: Port making netlink request
 490 * @seq: Sequence number of netlink message
 491 * @bat_priv: The bat priv with all the soft interface information
 492 * @if_outgoing: Limit dump to entries with this outgoing interface
 493 * @orig_node: Originator to dump
 494 * @sub_s: Number of sub entries to skip
 495 *
 496 * This function assumes the caller holds rcu_read_lock().
 497 *
 498 * Return: Error code, or 0 on success
 499 */
 500static int
 501batadv_v_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
 502                         struct batadv_priv *bat_priv,
 503                         struct batadv_hard_iface *if_outgoing,
 504                         struct batadv_orig_node *orig_node, int *sub_s)
 505{
 506        struct batadv_neigh_node *neigh_node_best;
 507        struct batadv_neigh_node *neigh_node;
 508        int sub = 0;
 509        bool best;
 510
 511        neigh_node_best = batadv_orig_router_get(orig_node, if_outgoing);
 512        if (!neigh_node_best)
 513                goto out;
 514
 515        hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
 516                if (sub++ < *sub_s)
 517                        continue;
 518
 519                best = (neigh_node == neigh_node_best);
 520
 521                if (batadv_v_orig_dump_subentry(msg, portid, seq, bat_priv,
 522                                                if_outgoing, orig_node,
 523                                                neigh_node, best)) {
 524                        batadv_neigh_node_put(neigh_node_best);
 525
 526                        *sub_s = sub - 1;
 527                        return -EMSGSIZE;
 528                }
 529        }
 530
 531 out:
 532        if (neigh_node_best)
 533                batadv_neigh_node_put(neigh_node_best);
 534
 535        *sub_s = 0;
 536        return 0;
 537}
 538
 539/**
 540 * batadv_v_orig_dump_bucket - Dump an originator bucket into a
 541 *  message
 542 * @msg: Netlink message to dump into
 543 * @portid: Port making netlink request
 544 * @seq: Sequence number of netlink message
 545 * @bat_priv: The bat priv with all the soft interface information
 546 * @if_outgoing: Limit dump to entries with this outgoing interface
 547 * @head: Bucket to be dumped
 548 * @idx_s: Number of entries to be skipped
 549 * @sub: Number of sub entries to be skipped
 550 *
 551 * Return: Error code, or 0 on success
 552 */
 553static int
 554batadv_v_orig_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
 555                          struct batadv_priv *bat_priv,
 556                          struct batadv_hard_iface *if_outgoing,
 557                          struct hlist_head *head, int *idx_s, int *sub)
 558{
 559        struct batadv_orig_node *orig_node;
 560        int idx = 0;
 561
 562        rcu_read_lock();
 563        hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
 564                if (idx++ < *idx_s)
 565                        continue;
 566
 567                if (batadv_v_orig_dump_entry(msg, portid, seq, bat_priv,
 568                                             if_outgoing, orig_node, sub)) {
 569                        rcu_read_unlock();
 570                        *idx_s = idx - 1;
 571                        return -EMSGSIZE;
 572                }
 573        }
 574        rcu_read_unlock();
 575
 576        *idx_s = 0;
 577        *sub = 0;
 578        return 0;
 579}
 580
 581/**
 582 * batadv_v_orig_dump - Dump the originators into a message
 583 * @msg: Netlink message to dump into
 584 * @cb: Control block containing additional options
 585 * @bat_priv: The bat priv with all the soft interface information
 586 * @if_outgoing: Limit dump to entries with this outgoing interface
 587 */
 588static void
 589batadv_v_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
 590                   struct batadv_priv *bat_priv,
 591                   struct batadv_hard_iface *if_outgoing)
 592{
 593        struct batadv_hashtable *hash = bat_priv->orig_hash;
 594        struct hlist_head *head;
 595        int bucket = cb->args[0];
 596        int idx = cb->args[1];
 597        int sub = cb->args[2];
 598        int portid = NETLINK_CB(cb->skb).portid;
 599
 600        while (bucket < hash->size) {
 601                head = &hash->table[bucket];
 602
 603                if (batadv_v_orig_dump_bucket(msg, portid,
 604                                              cb->nlh->nlmsg_seq,
 605                                              bat_priv, if_outgoing, head, &idx,
 606                                              &sub))
 607                        break;
 608
 609                bucket++;
 610        }
 611
 612        cb->args[0] = bucket;
 613        cb->args[1] = idx;
 614        cb->args[2] = sub;
 615}
 616
 617static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
 618                              struct batadv_hard_iface *if_outgoing1,
 619                              struct batadv_neigh_node *neigh2,
 620                              struct batadv_hard_iface *if_outgoing2)
 621{
 622        struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
 623        int ret = 0;
 624
 625        ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
 626        if (WARN_ON(!ifinfo1))
 627                goto err_ifinfo1;
 628
 629        ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
 630        if (WARN_ON(!ifinfo2))
 631                goto err_ifinfo2;
 632
 633        ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput;
 634
 635        batadv_neigh_ifinfo_put(ifinfo2);
 636err_ifinfo2:
 637        batadv_neigh_ifinfo_put(ifinfo1);
 638err_ifinfo1:
 639        return ret;
 640}
 641
 642static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
 643                                  struct batadv_hard_iface *if_outgoing1,
 644                                  struct batadv_neigh_node *neigh2,
 645                                  struct batadv_hard_iface *if_outgoing2)
 646{
 647        struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
 648        u32 threshold;
 649        bool ret = false;
 650
 651        ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
 652        if (WARN_ON(!ifinfo1))
 653                goto err_ifinfo1;
 654
 655        ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
 656        if (WARN_ON(!ifinfo2))
 657                goto err_ifinfo2;
 658
 659        threshold = ifinfo1->bat_v.throughput / 4;
 660        threshold = ifinfo1->bat_v.throughput - threshold;
 661
 662        ret = ifinfo2->bat_v.throughput > threshold;
 663
 664        batadv_neigh_ifinfo_put(ifinfo2);
 665err_ifinfo2:
 666        batadv_neigh_ifinfo_put(ifinfo1);
 667err_ifinfo1:
 668        return ret;
 669}
 670
 671static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv,
 672                                        char *buff, size_t count)
 673{
 674        u32 old_class, class;
 675
 676        if (!batadv_parse_throughput(bat_priv->soft_iface, buff,
 677                                     "B.A.T.M.A.N. V GW selection class",
 678                                     &class))
 679                return -EINVAL;
 680
 681        old_class = atomic_read(&bat_priv->gw.sel_class);
 682        atomic_set(&bat_priv->gw.sel_class, class);
 683
 684        if (old_class != class)
 685                batadv_gw_reselect(bat_priv);
 686
 687        return count;
 688}
 689
 690static ssize_t batadv_v_show_sel_class(struct batadv_priv *bat_priv, char *buff)
 691{
 692        u32 class = atomic_read(&bat_priv->gw.sel_class);
 693
 694        return sprintf(buff, "%u.%u MBit\n", class / 10, class % 10);
 695}
 696
 697/**
 698 * batadv_v_gw_throughput_get - retrieve the GW-bandwidth for a given GW
 699 * @gw_node: the GW to retrieve the metric for
 700 * @bw: the pointer where the metric will be stored. The metric is computed as
 701 *  the minimum between the GW advertised throughput and the path throughput to
 702 *  it in the mesh
 703 *
 704 * Return: 0 on success, -1 on failure
 705 */
 706static int batadv_v_gw_throughput_get(struct batadv_gw_node *gw_node, u32 *bw)
 707{
 708        struct batadv_neigh_ifinfo *router_ifinfo = NULL;
 709        struct batadv_orig_node *orig_node;
 710        struct batadv_neigh_node *router;
 711        int ret = -1;
 712
 713        orig_node = gw_node->orig_node;
 714        router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
 715        if (!router)
 716                goto out;
 717
 718        router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
 719        if (!router_ifinfo)
 720                goto out;
 721
 722        /* the GW metric is computed as the minimum between the path throughput
 723         * to reach the GW itself and the advertised bandwidth.
 724         * This gives us an approximation of the effective throughput that the
 725         * client can expect via this particular GW node
 726         */
 727        *bw = router_ifinfo->bat_v.throughput;
 728        *bw = min_t(u32, *bw, gw_node->bandwidth_down);
 729
 730        ret = 0;
 731out:
 732        if (router)
 733                batadv_neigh_node_put(router);
 734        if (router_ifinfo)
 735                batadv_neigh_ifinfo_put(router_ifinfo);
 736
 737        return ret;
 738}
 739
 740/**
 741 * batadv_v_gw_get_best_gw_node - retrieve the best GW node
 742 * @bat_priv: the bat priv with all the soft interface information
 743 *
 744 * Return: the GW node having the best GW-metric, NULL if no GW is known
 745 */
 746static struct batadv_gw_node *
 747batadv_v_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 748{
 749        struct batadv_gw_node *gw_node, *curr_gw = NULL;
 750        u32 max_bw = 0, bw;
 751
 752        rcu_read_lock();
 753        hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
 754                if (!kref_get_unless_zero(&gw_node->refcount))
 755                        continue;
 756
 757                if (batadv_v_gw_throughput_get(gw_node, &bw) < 0)
 758                        goto next;
 759
 760                if (curr_gw && (bw <= max_bw))
 761                        goto next;
 762
 763                if (curr_gw)
 764                        batadv_gw_node_put(curr_gw);
 765
 766                curr_gw = gw_node;
 767                kref_get(&curr_gw->refcount);
 768                max_bw = bw;
 769
 770next:
 771                batadv_gw_node_put(gw_node);
 772        }
 773        rcu_read_unlock();
 774
 775        return curr_gw;
 776}
 777
 778/**
 779 * batadv_v_gw_is_eligible - check if a originator would be selected as GW
 780 * @bat_priv: the bat priv with all the soft interface information
 781 * @curr_gw_orig: originator representing the currently selected GW
 782 * @orig_node: the originator representing the new candidate
 783 *
 784 * Return: true if orig_node can be selected as current GW, false otherwise
 785 */
 786static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv,
 787                                    struct batadv_orig_node *curr_gw_orig,
 788                                    struct batadv_orig_node *orig_node)
 789{
 790        struct batadv_gw_node *curr_gw, *orig_gw = NULL;
 791        u32 gw_throughput, orig_throughput, threshold;
 792        bool ret = false;
 793
 794        threshold = atomic_read(&bat_priv->gw.sel_class);
 795
 796        curr_gw = batadv_gw_node_get(bat_priv, curr_gw_orig);
 797        if (!curr_gw) {
 798                ret = true;
 799                goto out;
 800        }
 801
 802        if (batadv_v_gw_throughput_get(curr_gw, &gw_throughput) < 0) {
 803                ret = true;
 804                goto out;
 805        }
 806
 807        orig_gw = batadv_gw_node_get(bat_priv, orig_node);
 808        if (!orig_node)
 809                goto out;
 810
 811        if (batadv_v_gw_throughput_get(orig_gw, &orig_throughput) < 0)
 812                goto out;
 813
 814        if (orig_throughput < gw_throughput)
 815                goto out;
 816
 817        if ((orig_throughput - gw_throughput) < threshold)
 818                goto out;
 819
 820        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 821                   "Restarting gateway selection: better gateway found (throughput curr: %u, throughput new: %u)\n",
 822                   gw_throughput, orig_throughput);
 823
 824        ret = true;
 825out:
 826        if (curr_gw)
 827                batadv_gw_node_put(curr_gw);
 828        if (orig_gw)
 829                batadv_gw_node_put(orig_gw);
 830
 831        return ret;
 832}
 833
 834#ifdef CONFIG_BATMAN_ADV_DEBUGFS
 835/* fails if orig_node has no router */
 836static int batadv_v_gw_write_buffer_text(struct batadv_priv *bat_priv,
 837                                         struct seq_file *seq,
 838                                         const struct batadv_gw_node *gw_node)
 839{
 840        struct batadv_gw_node *curr_gw;
 841        struct batadv_neigh_node *router;
 842        struct batadv_neigh_ifinfo *router_ifinfo = NULL;
 843        int ret = -1;
 844
 845        router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
 846        if (!router)
 847                goto out;
 848
 849        router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
 850        if (!router_ifinfo)
 851                goto out;
 852
 853        curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 854
 855        seq_printf(seq, "%s %pM (%9u.%1u) %pM [%10s]: %u.%u/%u.%u MBit\n",
 856                   (curr_gw == gw_node ? "=>" : "  "),
 857                   gw_node->orig_node->orig,
 858                   router_ifinfo->bat_v.throughput / 10,
 859                   router_ifinfo->bat_v.throughput % 10, router->addr,
 860                   router->if_incoming->net_dev->name,
 861                   gw_node->bandwidth_down / 10,
 862                   gw_node->bandwidth_down % 10,
 863                   gw_node->bandwidth_up / 10,
 864                   gw_node->bandwidth_up % 10);
 865        ret = seq_has_overflowed(seq) ? -1 : 0;
 866
 867        if (curr_gw)
 868                batadv_gw_node_put(curr_gw);
 869out:
 870        if (router_ifinfo)
 871                batadv_neigh_ifinfo_put(router_ifinfo);
 872        if (router)
 873                batadv_neigh_node_put(router);
 874        return ret;
 875}
 876
 877/**
 878 * batadv_v_gw_print - print the gateway list
 879 * @bat_priv: the bat priv with all the soft interface information
 880 * @seq: gateway table seq_file struct
 881 */
 882static void batadv_v_gw_print(struct batadv_priv *bat_priv,
 883                              struct seq_file *seq)
 884{
 885        struct batadv_gw_node *gw_node;
 886        int gw_count = 0;
 887
 888        seq_puts(seq,
 889                 "      Gateway        ( throughput)           Nexthop [outgoingIF]: advertised uplink bandwidth\n");
 890
 891        rcu_read_lock();
 892        hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
 893                /* fails if orig_node has no router */
 894                if (batadv_v_gw_write_buffer_text(bat_priv, seq, gw_node) < 0)
 895                        continue;
 896
 897                gw_count++;
 898        }
 899        rcu_read_unlock();
 900
 901        if (gw_count == 0)
 902                seq_puts(seq, "No gateways in range ...\n");
 903}
 904#endif
 905
 906/**
 907 * batadv_v_gw_dump_entry - Dump a gateway into a message
 908 * @msg: Netlink message to dump into
 909 * @portid: Port making netlink request
 910 * @seq: Sequence number of netlink message
 911 * @bat_priv: The bat priv with all the soft interface information
 912 * @gw_node: Gateway to be dumped
 913 *
 914 * Return: Error code, or 0 on success
 915 */
 916static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
 917                                  struct batadv_priv *bat_priv,
 918                                  struct batadv_gw_node *gw_node)
 919{
 920        struct batadv_neigh_ifinfo *router_ifinfo = NULL;
 921        struct batadv_neigh_node *router;
 922        struct batadv_gw_node *curr_gw;
 923        int ret = -EINVAL;
 924        void *hdr;
 925
 926        router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
 927        if (!router)
 928                goto out;
 929
 930        router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
 931        if (!router_ifinfo)
 932                goto out;
 933
 934        curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 935
 936        hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
 937                          NLM_F_MULTI, BATADV_CMD_GET_GATEWAYS);
 938        if (!hdr) {
 939                ret = -ENOBUFS;
 940                goto out;
 941        }
 942
 943        ret = -EMSGSIZE;
 944
 945        if (curr_gw == gw_node) {
 946                if (nla_put_flag(msg, BATADV_ATTR_FLAG_BEST)) {
 947                        genlmsg_cancel(msg, hdr);
 948                        goto out;
 949                }
 950        }
 951
 952        if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
 953                    gw_node->orig_node->orig)) {
 954                genlmsg_cancel(msg, hdr);
 955                goto out;
 956        }
 957
 958        if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT,
 959                        router_ifinfo->bat_v.throughput)) {
 960                genlmsg_cancel(msg, hdr);
 961                goto out;
 962        }
 963
 964        if (nla_put(msg, BATADV_ATTR_ROUTER, ETH_ALEN, router->addr)) {
 965                genlmsg_cancel(msg, hdr);
 966                goto out;
 967        }
 968
 969        if (nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
 970                           router->if_incoming->net_dev->name)) {
 971                genlmsg_cancel(msg, hdr);
 972                goto out;
 973        }
 974
 975        if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN,
 976                        gw_node->bandwidth_down)) {
 977                genlmsg_cancel(msg, hdr);
 978                goto out;
 979        }
 980
 981        if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_UP, gw_node->bandwidth_up)) {
 982                genlmsg_cancel(msg, hdr);
 983                goto out;
 984        }
 985
 986        genlmsg_end(msg, hdr);
 987        ret = 0;
 988
 989out:
 990        if (router_ifinfo)
 991                batadv_neigh_ifinfo_put(router_ifinfo);
 992        if (router)
 993                batadv_neigh_node_put(router);
 994        return ret;
 995}
 996
 997/**
 998 * batadv_v_gw_dump - Dump gateways into a message
 999 * @msg: Netlink message to dump into
1000 * @cb: Control block containing additional options
1001 * @bat_priv: The bat priv with all the soft interface information
1002 */
1003static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
1004                             struct batadv_priv *bat_priv)
1005{
1006        int portid = NETLINK_CB(cb->skb).portid;
1007        struct batadv_gw_node *gw_node;
1008        int idx_skip = cb->args[0];
1009        int idx = 0;
1010
1011        rcu_read_lock();
1012        hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
1013                if (idx++ < idx_skip)
1014                        continue;
1015
1016                if (batadv_v_gw_dump_entry(msg, portid, cb->nlh->nlmsg_seq,
1017                                           bat_priv, gw_node)) {
1018                        idx_skip = idx - 1;
1019                        goto unlock;
1020                }
1021        }
1022
1023        idx_skip = idx;
1024unlock:
1025        rcu_read_unlock();
1026
1027        cb->args[0] = idx_skip;
1028}
1029
1030static struct batadv_algo_ops batadv_batman_v __read_mostly = {
1031        .name = "BATMAN_V",
1032        .iface = {
1033                .activate = batadv_v_iface_activate,
1034                .enable = batadv_v_iface_enable,
1035                .disable = batadv_v_iface_disable,
1036                .update_mac = batadv_v_iface_update_mac,
1037                .primary_set = batadv_v_primary_iface_set,
1038        },
1039        .neigh = {
1040                .hardif_init = batadv_v_hardif_neigh_init,
1041                .cmp = batadv_v_neigh_cmp,
1042                .is_similar_or_better = batadv_v_neigh_is_sob,
1043#ifdef CONFIG_BATMAN_ADV_DEBUGFS
1044                .print = batadv_v_neigh_print,
1045#endif
1046                .dump = batadv_v_neigh_dump,
1047        },
1048        .orig = {
1049#ifdef CONFIG_BATMAN_ADV_DEBUGFS
1050                .print = batadv_v_orig_print,
1051#endif
1052                .dump = batadv_v_orig_dump,
1053        },
1054        .gw = {
1055                .store_sel_class = batadv_v_store_sel_class,
1056                .show_sel_class = batadv_v_show_sel_class,
1057                .get_best_gw_node = batadv_v_gw_get_best_gw_node,
1058                .is_eligible = batadv_v_gw_is_eligible,
1059#ifdef CONFIG_BATMAN_ADV_DEBUGFS
1060                .print = batadv_v_gw_print,
1061#endif
1062                .dump = batadv_v_gw_dump,
1063        },
1064};
1065
1066/**
1067 * batadv_v_hardif_init - initialize the algorithm specific fields in the
1068 *  hard-interface object
1069 * @hard_iface: the hard-interface to initialize
1070 */
1071void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface)
1072{
1073        /* enable link throughput auto-detection by setting the throughput
1074         * override to zero
1075         */
1076        atomic_set(&hard_iface->bat_v.throughput_override, 0);
1077        atomic_set(&hard_iface->bat_v.elp_interval, 500);
1078}
1079
1080/**
1081 * batadv_v_mesh_init - initialize the B.A.T.M.A.N. V private resources for a
1082 *  mesh
1083 * @bat_priv: the object representing the mesh interface to initialise
1084 *
1085 * Return: 0 on success or a negative error code otherwise
1086 */
1087int batadv_v_mesh_init(struct batadv_priv *bat_priv)
1088{
1089        int ret = 0;
1090
1091        ret = batadv_v_ogm_init(bat_priv);
1092        if (ret < 0)
1093                return ret;
1094
1095        /* set default throughput difference threshold to 5Mbps */
1096        atomic_set(&bat_priv->gw.sel_class, 50);
1097
1098        return 0;
1099}
1100
1101/**
1102 * batadv_v_mesh_free - free the B.A.T.M.A.N. V private resources for a mesh
1103 * @bat_priv: the object representing the mesh interface to free
1104 */
1105void batadv_v_mesh_free(struct batadv_priv *bat_priv)
1106{
1107        batadv_v_ogm_free(bat_priv);
1108}
1109
1110/**
1111 * batadv_v_init - B.A.T.M.A.N. V initialization function
1112 *
1113 * Description: Takes care of initializing all the subcomponents.
1114 * It is invoked upon module load only.
1115 *
1116 * Return: 0 on success or a negative error code otherwise
1117 */
1118int __init batadv_v_init(void)
1119{
1120        int ret;
1121
1122        /* B.A.T.M.A.N. V echo location protocol packet  */
1123        ret = batadv_recv_handler_register(BATADV_ELP,
1124                                           batadv_v_elp_packet_recv);
1125        if (ret < 0)
1126                return ret;
1127
1128        ret = batadv_recv_handler_register(BATADV_OGM2,
1129                                           batadv_v_ogm_packet_recv);
1130        if (ret < 0)
1131                goto elp_unregister;
1132
1133        ret = batadv_algo_register(&batadv_batman_v);
1134        if (ret < 0)
1135                goto ogm_unregister;
1136
1137        return ret;
1138
1139ogm_unregister:
1140        batadv_recv_handler_unregister(BATADV_OGM2);
1141
1142elp_unregister:
1143        batadv_recv_handler_unregister(BATADV_ELP);
1144
1145        return ret;
1146}
1147