root/net/batman-adv/bat_v.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. batadv_v_iface_activate
  2. batadv_v_iface_enable
  3. batadv_v_iface_disable
  4. batadv_v_primary_iface_set
  5. batadv_v_iface_update_mac
  6. batadv_v_hardif_neigh_init
  7. batadv_v_orig_print_neigh
  8. batadv_v_hardif_neigh_print
  9. batadv_v_neigh_print
  10. batadv_v_neigh_dump_neigh
  11. batadv_v_neigh_dump_hardif
  12. batadv_v_neigh_dump
  13. batadv_v_orig_print
  14. batadv_v_orig_dump_subentry
  15. batadv_v_orig_dump_entry
  16. batadv_v_orig_dump_bucket
  17. batadv_v_orig_dump
  18. batadv_v_neigh_cmp
  19. batadv_v_neigh_is_sob
  20. batadv_v_init_sel_class
  21. batadv_v_store_sel_class
  22. batadv_v_show_sel_class
  23. batadv_v_gw_throughput_get
  24. batadv_v_gw_get_best_gw_node
  25. batadv_v_gw_is_eligible
  26. batadv_v_gw_write_buffer_text
  27. batadv_v_gw_print
  28. batadv_v_gw_dump_entry
  29. batadv_v_gw_dump
  30. batadv_v_hardif_init
  31. batadv_v_mesh_init
  32. batadv_v_mesh_free
  33. batadv_v_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright (C) 2013-2019  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 
  45 static 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 
  65 static 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 
  80 static 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 
  86 static 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  */
  99 static 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);
 109 out:
 110         if (primary_if)
 111                 batadv_hardif_put(primary_if);
 112 }
 113 
 114 static void
 115 batadv_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  */
 131 static void
 132 batadv_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  */
 158 static void
 159 batadv_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  */
 179 static 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  */
 217 static int
 218 batadv_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  */
 265 static int
 266 batadv_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  */
 297 static void
 298 batadv_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  */
 347 static 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 
 396 next:
 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  */
 422 static int
 423 batadv_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  */
 489 static int
 490 batadv_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  */
 541 static int
 542 batadv_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  */
 576 static void
 577 batadv_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 
 605 static 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);
 624 err_ifinfo2:
 625         batadv_neigh_ifinfo_put(ifinfo1);
 626 err_ifinfo1:
 627         return ret;
 628 }
 629 
 630 static 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);
 653 err_ifinfo2:
 654         batadv_neigh_ifinfo_put(ifinfo1);
 655 err_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  */
 663 static 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 
 669 static 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 
 688 static 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  */
 704 static 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;
 729 out:
 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  */
 744 static struct batadv_gw_node *
 745 batadv_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 
 768 next:
 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  */
 784 static 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;
 823 out:
 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 */
 834 static 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);
 867 out:
 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  */
 880 static 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  */
 914 static 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 
 991 out:
 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  */
1007 static 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;
1030 unlock:
1031         spin_unlock_bh(&bat_priv->gw.list_lock);
1032 
1033         cb->args[0] = idx_skip;
1034 }
1035 
1036 static 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  */
1078 void 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         spin_lock_init(&hard_iface->bat_v.aggr_list_lock);
1089         INIT_DELAYED_WORK(&hard_iface->bat_v.aggr_wq,
1090                           batadv_v_ogm_aggr_work);
1091 }
1092 
1093 /**
1094  * batadv_v_mesh_init() - initialize the B.A.T.M.A.N. V private resources for a
1095  *  mesh
1096  * @bat_priv: the object representing the mesh interface to initialise
1097  *
1098  * Return: 0 on success or a negative error code otherwise
1099  */
1100 int batadv_v_mesh_init(struct batadv_priv *bat_priv)
1101 {
1102         int ret = 0;
1103 
1104         ret = batadv_v_ogm_init(bat_priv);
1105         if (ret < 0)
1106                 return ret;
1107 
1108         return 0;
1109 }
1110 
1111 /**
1112  * batadv_v_mesh_free() - free the B.A.T.M.A.N. V private resources for a mesh
1113  * @bat_priv: the object representing the mesh interface to free
1114  */
1115 void batadv_v_mesh_free(struct batadv_priv *bat_priv)
1116 {
1117         batadv_v_ogm_free(bat_priv);
1118 }
1119 
1120 /**
1121  * batadv_v_init() - B.A.T.M.A.N. V initialization function
1122  *
1123  * Description: Takes care of initializing all the subcomponents.
1124  * It is invoked upon module load only.
1125  *
1126  * Return: 0 on success or a negative error code otherwise
1127  */
1128 int __init batadv_v_init(void)
1129 {
1130         int ret;
1131 
1132         /* B.A.T.M.A.N. V echo location protocol packet  */
1133         ret = batadv_recv_handler_register(BATADV_ELP,
1134                                            batadv_v_elp_packet_recv);
1135         if (ret < 0)
1136                 return ret;
1137 
1138         ret = batadv_recv_handler_register(BATADV_OGM2,
1139                                            batadv_v_ogm_packet_recv);
1140         if (ret < 0)
1141                 goto elp_unregister;
1142 
1143         ret = batadv_algo_register(&batadv_batman_v);
1144         if (ret < 0)
1145                 goto ogm_unregister;
1146 
1147         return ret;
1148 
1149 ogm_unregister:
1150         batadv_recv_handler_unregister(BATADV_OGM2);
1151 
1152 elp_unregister:
1153         batadv_recv_handler_unregister(BATADV_ELP);
1154 
1155         return ret;
1156 }

/* [<][>][^][v][top][bottom][index][help] */