linux/net/batman-adv/bat_v.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) 2013-2018  B.A.T.M.A.N. contributors:
   3 *
   4 * Linus Lüssing, Marek Lindner
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of version 2 of the GNU General Public
   8 * License as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13 * General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
  17 */
  18
  19#include "bat_v.h"
  20#include "main.h"
  21
  22#include <linux/atomic.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/batadv_packet.h>
  41#include <uapi/linux/batman_adv.h>
  42
  43#include "bat_algo.h"
  44#include "bat_v_elp.h"
  45#include "bat_v_ogm.h"
  46#include "gateway_client.h"
  47#include "gateway_common.h"
  48#include "hard-interface.h"
  49#include "hash.h"
  50#include "log.h"
  51#include "netlink.h"
  52#include "originator.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_putc(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 message
 421 * @msg: Netlink message to dump into
 422 * @portid: Port making netlink request
 423 * @seq: Sequence number of netlink message
 424 * @bat_priv: The bat priv with all the soft interface information
 425 * @if_outgoing: Limit dump to entries with this outgoing interface
 426 * @orig_node: Originator to dump
 427 * @neigh_node: Single hops neighbour
 428 * @best: Is the best originator
 429 *
 430 * Return: Error code, or 0 on success
 431 */
 432static int
 433batadv_v_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
 434                            struct batadv_priv *bat_priv,
 435                            struct batadv_hard_iface *if_outgoing,
 436                            struct batadv_orig_node *orig_node,
 437                            struct batadv_neigh_node *neigh_node,
 438                            bool best)
 439{
 440        struct batadv_neigh_ifinfo *n_ifinfo;
 441        unsigned int last_seen_msecs;
 442        u32 throughput;
 443        void *hdr;
 444
 445        n_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
 446        if (!n_ifinfo)
 447                return 0;
 448
 449        throughput = n_ifinfo->bat_v.throughput * 100;
 450
 451        batadv_neigh_ifinfo_put(n_ifinfo);
 452
 453        last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_seen);
 454
 455        if (if_outgoing != BATADV_IF_DEFAULT &&
 456            if_outgoing != neigh_node->if_incoming)
 457                return 0;
 458
 459        hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
 460                          BATADV_CMD_GET_ORIGINATORS);
 461        if (!hdr)
 462                return -ENOBUFS;
 463
 464        if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) ||
 465            nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
 466                    neigh_node->addr) ||
 467            nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
 468                        neigh_node->if_incoming->net_dev->ifindex) ||
 469            nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput) ||
 470            nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
 471                        last_seen_msecs))
 472                goto nla_put_failure;
 473
 474        if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
 475                goto nla_put_failure;
 476
 477        genlmsg_end(msg, hdr);
 478        return 0;
 479
 480 nla_put_failure:
 481        genlmsg_cancel(msg, hdr);
 482        return -EMSGSIZE;
 483}
 484
 485/**
 486 * batadv_v_orig_dump_entry() - Dump an originator entry into a message
 487 * @msg: Netlink message to dump into
 488 * @portid: Port making netlink request
 489 * @seq: Sequence number of netlink message
 490 * @bat_priv: The bat priv with all the soft interface information
 491 * @if_outgoing: Limit dump to entries with this outgoing interface
 492 * @orig_node: Originator to dump
 493 * @sub_s: Number of sub entries to skip
 494 *
 495 * This function assumes the caller holds rcu_read_lock().
 496 *
 497 * Return: Error code, or 0 on success
 498 */
 499static int
 500batadv_v_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
 501                         struct batadv_priv *bat_priv,
 502                         struct batadv_hard_iface *if_outgoing,
 503                         struct batadv_orig_node *orig_node, int *sub_s)
 504{
 505        struct batadv_neigh_node *neigh_node_best;
 506        struct batadv_neigh_node *neigh_node;
 507        int sub = 0;
 508        bool best;
 509
 510        neigh_node_best = batadv_orig_router_get(orig_node, if_outgoing);
 511        if (!neigh_node_best)
 512                goto out;
 513
 514        hlist_for_each_entry_rcu(neigh_node, &orig_node->neigh_list, list) {
 515                if (sub++ < *sub_s)
 516                        continue;
 517
 518                best = (neigh_node == neigh_node_best);
 519
 520                if (batadv_v_orig_dump_subentry(msg, portid, seq, bat_priv,
 521                                                if_outgoing, orig_node,
 522                                                neigh_node, best)) {
 523                        batadv_neigh_node_put(neigh_node_best);
 524
 525                        *sub_s = sub - 1;
 526                        return -EMSGSIZE;
 527                }
 528        }
 529
 530 out:
 531        if (neigh_node_best)
 532                batadv_neigh_node_put(neigh_node_best);
 533
 534        *sub_s = 0;
 535        return 0;
 536}
 537
 538/**
 539 * batadv_v_orig_dump_bucket() - Dump an originator bucket into a message
 540 * @msg: Netlink message to dump into
 541 * @portid: Port making netlink request
 542 * @seq: Sequence number of netlink message
 543 * @bat_priv: The bat priv with all the soft interface information
 544 * @if_outgoing: Limit dump to entries with this outgoing interface
 545 * @head: Bucket to be dumped
 546 * @idx_s: Number of entries to be skipped
 547 * @sub: Number of sub entries to be skipped
 548 *
 549 * Return: Error code, or 0 on success
 550 */
 551static int
 552batadv_v_orig_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
 553                          struct batadv_priv *bat_priv,
 554                          struct batadv_hard_iface *if_outgoing,
 555                          struct hlist_head *head, int *idx_s, int *sub)
 556{
 557        struct batadv_orig_node *orig_node;
 558        int idx = 0;
 559
 560        rcu_read_lock();
 561        hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
 562                if (idx++ < *idx_s)
 563                        continue;
 564
 565                if (batadv_v_orig_dump_entry(msg, portid, seq, bat_priv,
 566                                             if_outgoing, orig_node, sub)) {
 567                        rcu_read_unlock();
 568                        *idx_s = idx - 1;
 569                        return -EMSGSIZE;
 570                }
 571        }
 572        rcu_read_unlock();
 573
 574        *idx_s = 0;
 575        *sub = 0;
 576        return 0;
 577}
 578
 579/**
 580 * batadv_v_orig_dump() - Dump the originators into a message
 581 * @msg: Netlink message to dump into
 582 * @cb: Control block containing additional options
 583 * @bat_priv: The bat priv with all the soft interface information
 584 * @if_outgoing: Limit dump to entries with this outgoing interface
 585 */
 586static void
 587batadv_v_orig_dump(struct sk_buff *msg, struct netlink_callback *cb,
 588                   struct batadv_priv *bat_priv,
 589                   struct batadv_hard_iface *if_outgoing)
 590{
 591        struct batadv_hashtable *hash = bat_priv->orig_hash;
 592        struct hlist_head *head;
 593        int bucket = cb->args[0];
 594        int idx = cb->args[1];
 595        int sub = cb->args[2];
 596        int portid = NETLINK_CB(cb->skb).portid;
 597
 598        while (bucket < hash->size) {
 599                head = &hash->table[bucket];
 600
 601                if (batadv_v_orig_dump_bucket(msg, portid,
 602                                              cb->nlh->nlmsg_seq,
 603                                              bat_priv, if_outgoing, head, &idx,
 604                                              &sub))
 605                        break;
 606
 607                bucket++;
 608        }
 609
 610        cb->args[0] = bucket;
 611        cb->args[1] = idx;
 612        cb->args[2] = sub;
 613}
 614
 615static int batadv_v_neigh_cmp(struct batadv_neigh_node *neigh1,
 616                              struct batadv_hard_iface *if_outgoing1,
 617                              struct batadv_neigh_node *neigh2,
 618                              struct batadv_hard_iface *if_outgoing2)
 619{
 620        struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
 621        int ret = 0;
 622
 623        ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
 624        if (!ifinfo1)
 625                goto err_ifinfo1;
 626
 627        ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
 628        if (!ifinfo2)
 629                goto err_ifinfo2;
 630
 631        ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput;
 632
 633        batadv_neigh_ifinfo_put(ifinfo2);
 634err_ifinfo2:
 635        batadv_neigh_ifinfo_put(ifinfo1);
 636err_ifinfo1:
 637        return ret;
 638}
 639
 640static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
 641                                  struct batadv_hard_iface *if_outgoing1,
 642                                  struct batadv_neigh_node *neigh2,
 643                                  struct batadv_hard_iface *if_outgoing2)
 644{
 645        struct batadv_neigh_ifinfo *ifinfo1, *ifinfo2;
 646        u32 threshold;
 647        bool ret = false;
 648
 649        ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
 650        if (!ifinfo1)
 651                goto err_ifinfo1;
 652
 653        ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
 654        if (!ifinfo2)
 655                goto err_ifinfo2;
 656
 657        threshold = ifinfo1->bat_v.throughput / 4;
 658        threshold = ifinfo1->bat_v.throughput - threshold;
 659
 660        ret = ifinfo2->bat_v.throughput > threshold;
 661
 662        batadv_neigh_ifinfo_put(ifinfo2);
 663err_ifinfo2:
 664        batadv_neigh_ifinfo_put(ifinfo1);
 665err_ifinfo1:
 666        return ret;
 667}
 668
 669/**
 670 * batadv_v_init_sel_class() - initialize GW selection class
 671 * @bat_priv: the bat priv with all the soft interface information
 672 */
 673static void batadv_v_init_sel_class(struct batadv_priv *bat_priv)
 674{
 675        /* set default throughput difference threshold to 5Mbps */
 676        atomic_set(&bat_priv->gw.sel_class, 50);
 677}
 678
 679static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv,
 680                                        char *buff, size_t count)
 681{
 682        u32 old_class, class;
 683
 684        if (!batadv_parse_throughput(bat_priv->soft_iface, buff,
 685                                     "B.A.T.M.A.N. V GW selection class",
 686                                     &class))
 687                return -EINVAL;
 688
 689        old_class = atomic_read(&bat_priv->gw.sel_class);
 690        atomic_set(&bat_priv->gw.sel_class, class);
 691
 692        if (old_class != class)
 693                batadv_gw_reselect(bat_priv);
 694
 695        return count;
 696}
 697
 698static ssize_t batadv_v_show_sel_class(struct batadv_priv *bat_priv, char *buff)
 699{
 700        u32 class = atomic_read(&bat_priv->gw.sel_class);
 701
 702        return sprintf(buff, "%u.%u MBit\n", class / 10, class % 10);
 703}
 704
 705/**
 706 * batadv_v_gw_throughput_get() - retrieve the GW-bandwidth for a given GW
 707 * @gw_node: the GW to retrieve the metric for
 708 * @bw: the pointer where the metric will be stored. The metric is computed as
 709 *  the minimum between the GW advertised throughput and the path throughput to
 710 *  it in the mesh
 711 *
 712 * Return: 0 on success, -1 on failure
 713 */
 714static int batadv_v_gw_throughput_get(struct batadv_gw_node *gw_node, u32 *bw)
 715{
 716        struct batadv_neigh_ifinfo *router_ifinfo = NULL;
 717        struct batadv_orig_node *orig_node;
 718        struct batadv_neigh_node *router;
 719        int ret = -1;
 720
 721        orig_node = gw_node->orig_node;
 722        router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
 723        if (!router)
 724                goto out;
 725
 726        router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
 727        if (!router_ifinfo)
 728                goto out;
 729
 730        /* the GW metric is computed as the minimum between the path throughput
 731         * to reach the GW itself and the advertised bandwidth.
 732         * This gives us an approximation of the effective throughput that the
 733         * client can expect via this particular GW node
 734         */
 735        *bw = router_ifinfo->bat_v.throughput;
 736        *bw = min_t(u32, *bw, gw_node->bandwidth_down);
 737
 738        ret = 0;
 739out:
 740        if (router)
 741                batadv_neigh_node_put(router);
 742        if (router_ifinfo)
 743                batadv_neigh_ifinfo_put(router_ifinfo);
 744
 745        return ret;
 746}
 747
 748/**
 749 * batadv_v_gw_get_best_gw_node() - retrieve the best GW node
 750 * @bat_priv: the bat priv with all the soft interface information
 751 *
 752 * Return: the GW node having the best GW-metric, NULL if no GW is known
 753 */
 754static struct batadv_gw_node *
 755batadv_v_gw_get_best_gw_node(struct batadv_priv *bat_priv)
 756{
 757        struct batadv_gw_node *gw_node, *curr_gw = NULL;
 758        u32 max_bw = 0, bw;
 759
 760        rcu_read_lock();
 761        hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
 762                if (!kref_get_unless_zero(&gw_node->refcount))
 763                        continue;
 764
 765                if (batadv_v_gw_throughput_get(gw_node, &bw) < 0)
 766                        goto next;
 767
 768                if (curr_gw && bw <= max_bw)
 769                        goto next;
 770
 771                if (curr_gw)
 772                        batadv_gw_node_put(curr_gw);
 773
 774                curr_gw = gw_node;
 775                kref_get(&curr_gw->refcount);
 776                max_bw = bw;
 777
 778next:
 779                batadv_gw_node_put(gw_node);
 780        }
 781        rcu_read_unlock();
 782
 783        return curr_gw;
 784}
 785
 786/**
 787 * batadv_v_gw_is_eligible() - check if a originator would be selected as GW
 788 * @bat_priv: the bat priv with all the soft interface information
 789 * @curr_gw_orig: originator representing the currently selected GW
 790 * @orig_node: the originator representing the new candidate
 791 *
 792 * Return: true if orig_node can be selected as current GW, false otherwise
 793 */
 794static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv,
 795                                    struct batadv_orig_node *curr_gw_orig,
 796                                    struct batadv_orig_node *orig_node)
 797{
 798        struct batadv_gw_node *curr_gw, *orig_gw = NULL;
 799        u32 gw_throughput, orig_throughput, threshold;
 800        bool ret = false;
 801
 802        threshold = atomic_read(&bat_priv->gw.sel_class);
 803
 804        curr_gw = batadv_gw_node_get(bat_priv, curr_gw_orig);
 805        if (!curr_gw) {
 806                ret = true;
 807                goto out;
 808        }
 809
 810        if (batadv_v_gw_throughput_get(curr_gw, &gw_throughput) < 0) {
 811                ret = true;
 812                goto out;
 813        }
 814
 815        orig_gw = batadv_gw_node_get(bat_priv, orig_node);
 816        if (!orig_gw)
 817                goto out;
 818
 819        if (batadv_v_gw_throughput_get(orig_gw, &orig_throughput) < 0)
 820                goto out;
 821
 822        if (orig_throughput < gw_throughput)
 823                goto out;
 824
 825        if ((orig_throughput - gw_throughput) < threshold)
 826                goto out;
 827
 828        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 829                   "Restarting gateway selection: better gateway found (throughput curr: %u, throughput new: %u)\n",
 830                   gw_throughput, orig_throughput);
 831
 832        ret = true;
 833out:
 834        if (curr_gw)
 835                batadv_gw_node_put(curr_gw);
 836        if (orig_gw)
 837                batadv_gw_node_put(orig_gw);
 838
 839        return ret;
 840}
 841
 842#ifdef CONFIG_BATMAN_ADV_DEBUGFS
 843/* fails if orig_node has no router */
 844static int batadv_v_gw_write_buffer_text(struct batadv_priv *bat_priv,
 845                                         struct seq_file *seq,
 846                                         const struct batadv_gw_node *gw_node)
 847{
 848        struct batadv_gw_node *curr_gw;
 849        struct batadv_neigh_node *router;
 850        struct batadv_neigh_ifinfo *router_ifinfo = NULL;
 851        int ret = -1;
 852
 853        router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
 854        if (!router)
 855                goto out;
 856
 857        router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
 858        if (!router_ifinfo)
 859                goto out;
 860
 861        curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 862
 863        seq_printf(seq, "%s %pM (%9u.%1u) %pM [%10s]: %u.%u/%u.%u MBit\n",
 864                   (curr_gw == gw_node ? "=>" : "  "),
 865                   gw_node->orig_node->orig,
 866                   router_ifinfo->bat_v.throughput / 10,
 867                   router_ifinfo->bat_v.throughput % 10, router->addr,
 868                   router->if_incoming->net_dev->name,
 869                   gw_node->bandwidth_down / 10,
 870                   gw_node->bandwidth_down % 10,
 871                   gw_node->bandwidth_up / 10,
 872                   gw_node->bandwidth_up % 10);
 873        ret = seq_has_overflowed(seq) ? -1 : 0;
 874
 875        if (curr_gw)
 876                batadv_gw_node_put(curr_gw);
 877out:
 878        if (router_ifinfo)
 879                batadv_neigh_ifinfo_put(router_ifinfo);
 880        if (router)
 881                batadv_neigh_node_put(router);
 882        return ret;
 883}
 884
 885/**
 886 * batadv_v_gw_print() - print the gateway list
 887 * @bat_priv: the bat priv with all the soft interface information
 888 * @seq: gateway table seq_file struct
 889 */
 890static void batadv_v_gw_print(struct batadv_priv *bat_priv,
 891                              struct seq_file *seq)
 892{
 893        struct batadv_gw_node *gw_node;
 894        int gw_count = 0;
 895
 896        seq_puts(seq,
 897                 "      Gateway        ( throughput)           Nexthop [outgoingIF]: advertised uplink bandwidth\n");
 898
 899        rcu_read_lock();
 900        hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
 901                /* fails if orig_node has no router */
 902                if (batadv_v_gw_write_buffer_text(bat_priv, seq, gw_node) < 0)
 903                        continue;
 904
 905                gw_count++;
 906        }
 907        rcu_read_unlock();
 908
 909        if (gw_count == 0)
 910                seq_puts(seq, "No gateways in range ...\n");
 911}
 912#endif
 913
 914/**
 915 * batadv_v_gw_dump_entry() - Dump a gateway into a message
 916 * @msg: Netlink message to dump into
 917 * @portid: Port making netlink request
 918 * @seq: Sequence number of netlink message
 919 * @bat_priv: The bat priv with all the soft interface information
 920 * @gw_node: Gateway to be dumped
 921 *
 922 * Return: Error code, or 0 on success
 923 */
 924static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
 925                                  struct batadv_priv *bat_priv,
 926                                  struct batadv_gw_node *gw_node)
 927{
 928        struct batadv_neigh_ifinfo *router_ifinfo = NULL;
 929        struct batadv_neigh_node *router;
 930        struct batadv_gw_node *curr_gw = NULL;
 931        int ret = 0;
 932        void *hdr;
 933
 934        router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
 935        if (!router)
 936                goto out;
 937
 938        router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
 939        if (!router_ifinfo)
 940                goto out;
 941
 942        curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
 943
 944        hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
 945                          NLM_F_MULTI, BATADV_CMD_GET_GATEWAYS);
 946        if (!hdr) {
 947                ret = -ENOBUFS;
 948                goto out;
 949        }
 950
 951        ret = -EMSGSIZE;
 952
 953        if (curr_gw == gw_node) {
 954                if (nla_put_flag(msg, BATADV_ATTR_FLAG_BEST)) {
 955                        genlmsg_cancel(msg, hdr);
 956                        goto out;
 957                }
 958        }
 959
 960        if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
 961                    gw_node->orig_node->orig)) {
 962                genlmsg_cancel(msg, hdr);
 963                goto out;
 964        }
 965
 966        if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT,
 967                        router_ifinfo->bat_v.throughput)) {
 968                genlmsg_cancel(msg, hdr);
 969                goto out;
 970        }
 971
 972        if (nla_put(msg, BATADV_ATTR_ROUTER, ETH_ALEN, router->addr)) {
 973                genlmsg_cancel(msg, hdr);
 974                goto out;
 975        }
 976
 977        if (nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
 978                           router->if_incoming->net_dev->name)) {
 979                genlmsg_cancel(msg, hdr);
 980                goto out;
 981        }
 982
 983        if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN,
 984                        gw_node->bandwidth_down)) {
 985                genlmsg_cancel(msg, hdr);
 986                goto out;
 987        }
 988
 989        if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_UP, gw_node->bandwidth_up)) {
 990                genlmsg_cancel(msg, hdr);
 991                goto out;
 992        }
 993
 994        genlmsg_end(msg, hdr);
 995        ret = 0;
 996
 997out:
 998        if (curr_gw)
 999                batadv_gw_node_put(curr_gw);
1000        if (router_ifinfo)
1001                batadv_neigh_ifinfo_put(router_ifinfo);
1002        if (router)
1003                batadv_neigh_node_put(router);
1004        return ret;
1005}
1006
1007/**
1008 * batadv_v_gw_dump() - Dump gateways into a message
1009 * @msg: Netlink message to dump into
1010 * @cb: Control block containing additional options
1011 * @bat_priv: The bat priv with all the soft interface information
1012 */
1013static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
1014                             struct batadv_priv *bat_priv)
1015{
1016        int portid = NETLINK_CB(cb->skb).portid;
1017        struct batadv_gw_node *gw_node;
1018        int idx_skip = cb->args[0];
1019        int idx = 0;
1020
1021        rcu_read_lock();
1022        hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
1023                if (idx++ < idx_skip)
1024                        continue;
1025
1026                if (batadv_v_gw_dump_entry(msg, portid, cb->nlh->nlmsg_seq,
1027                                           bat_priv, gw_node)) {
1028                        idx_skip = idx - 1;
1029                        goto unlock;
1030                }
1031        }
1032
1033        idx_skip = idx;
1034unlock:
1035        rcu_read_unlock();
1036
1037        cb->args[0] = idx_skip;
1038}
1039
1040static struct batadv_algo_ops batadv_batman_v __read_mostly = {
1041        .name = "BATMAN_V",
1042        .iface = {
1043                .activate = batadv_v_iface_activate,
1044                .enable = batadv_v_iface_enable,
1045                .disable = batadv_v_iface_disable,
1046                .update_mac = batadv_v_iface_update_mac,
1047                .primary_set = batadv_v_primary_iface_set,
1048        },
1049        .neigh = {
1050                .hardif_init = batadv_v_hardif_neigh_init,
1051                .cmp = batadv_v_neigh_cmp,
1052                .is_similar_or_better = batadv_v_neigh_is_sob,
1053#ifdef CONFIG_BATMAN_ADV_DEBUGFS
1054                .print = batadv_v_neigh_print,
1055#endif
1056                .dump = batadv_v_neigh_dump,
1057        },
1058        .orig = {
1059#ifdef CONFIG_BATMAN_ADV_DEBUGFS
1060                .print = batadv_v_orig_print,
1061#endif
1062                .dump = batadv_v_orig_dump,
1063        },
1064        .gw = {
1065                .init_sel_class = batadv_v_init_sel_class,
1066                .store_sel_class = batadv_v_store_sel_class,
1067                .show_sel_class = batadv_v_show_sel_class,
1068                .get_best_gw_node = batadv_v_gw_get_best_gw_node,
1069                .is_eligible = batadv_v_gw_is_eligible,
1070#ifdef CONFIG_BATMAN_ADV_DEBUGFS
1071                .print = batadv_v_gw_print,
1072#endif
1073                .dump = batadv_v_gw_dump,
1074        },
1075};
1076
1077/**
1078 * batadv_v_hardif_init() - initialize the algorithm specific fields in the
1079 *  hard-interface object
1080 * @hard_iface: the hard-interface to initialize
1081 */
1082void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface)
1083{
1084        /* enable link throughput auto-detection by setting the throughput
1085         * override to zero
1086         */
1087        atomic_set(&hard_iface->bat_v.throughput_override, 0);
1088        atomic_set(&hard_iface->bat_v.elp_interval, 500);
1089}
1090
1091/**
1092 * batadv_v_mesh_init() - initialize the B.A.T.M.A.N. V private resources for a
1093 *  mesh
1094 * @bat_priv: the object representing the mesh interface to initialise
1095 *
1096 * Return: 0 on success or a negative error code otherwise
1097 */
1098int batadv_v_mesh_init(struct batadv_priv *bat_priv)
1099{
1100        int ret = 0;
1101
1102        ret = batadv_v_ogm_init(bat_priv);
1103        if (ret < 0)
1104                return ret;
1105
1106        return 0;
1107}
1108
1109/**
1110 * batadv_v_mesh_free() - free the B.A.T.M.A.N. V private resources for a mesh
1111 * @bat_priv: the object representing the mesh interface to free
1112 */
1113void batadv_v_mesh_free(struct batadv_priv *bat_priv)
1114{
1115        batadv_v_ogm_free(bat_priv);
1116}
1117
1118/**
1119 * batadv_v_init() - B.A.T.M.A.N. V initialization function
1120 *
1121 * Description: Takes care of initializing all the subcomponents.
1122 * It is invoked upon module load only.
1123 *
1124 * Return: 0 on success or a negative error code otherwise
1125 */
1126int __init batadv_v_init(void)
1127{
1128        int ret;
1129
1130        /* B.A.T.M.A.N. V echo location protocol packet  */
1131        ret = batadv_recv_handler_register(BATADV_ELP,
1132                                           batadv_v_elp_packet_recv);
1133        if (ret < 0)
1134                return ret;
1135
1136        ret = batadv_recv_handler_register(BATADV_OGM2,
1137                                           batadv_v_ogm_packet_recv);
1138        if (ret < 0)
1139                goto elp_unregister;
1140
1141        ret = batadv_algo_register(&batadv_batman_v);
1142        if (ret < 0)
1143                goto ogm_unregister;
1144
1145        return ret;
1146
1147ogm_unregister:
1148        batadv_recv_handler_unregister(BATADV_OGM2);
1149
1150elp_unregister:
1151        batadv_recv_handler_unregister(BATADV_ELP);
1152
1153        return ret;
1154}
1155