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