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