linux/net/batman-adv/bat_v_ogm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) 2013-2018  B.A.T.M.A.N. contributors:
   3 *
   4 * Antonio Quartulli
   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_ogm.h"
  20#include "main.h"
  21
  22#include <linux/atomic.h>
  23#include <linux/byteorder/generic.h>
  24#include <linux/errno.h>
  25#include <linux/etherdevice.h>
  26#include <linux/gfp.h>
  27#include <linux/if_ether.h>
  28#include <linux/jiffies.h>
  29#include <linux/kernel.h>
  30#include <linux/kref.h>
  31#include <linux/list.h>
  32#include <linux/netdevice.h>
  33#include <linux/random.h>
  34#include <linux/rculist.h>
  35#include <linux/rcupdate.h>
  36#include <linux/skbuff.h>
  37#include <linux/slab.h>
  38#include <linux/stddef.h>
  39#include <linux/string.h>
  40#include <linux/types.h>
  41#include <linux/workqueue.h>
  42#include <uapi/linux/batadv_packet.h>
  43
  44#include "bat_algo.h"
  45#include "hard-interface.h"
  46#include "hash.h"
  47#include "log.h"
  48#include "originator.h"
  49#include "routing.h"
  50#include "send.h"
  51#include "translation-table.h"
  52#include "tvlv.h"
  53
  54/**
  55 * batadv_v_ogm_orig_get() - retrieve and possibly create an originator node
  56 * @bat_priv: the bat priv with all the soft interface information
  57 * @addr: the address of the originator
  58 *
  59 * Return: the orig_node corresponding to the specified address. If such object
  60 * does not exist it is allocated here. In case of allocation failure returns
  61 * NULL.
  62 */
  63struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv,
  64                                               const u8 *addr)
  65{
  66        struct batadv_orig_node *orig_node;
  67        int hash_added;
  68
  69        orig_node = batadv_orig_hash_find(bat_priv, addr);
  70        if (orig_node)
  71                return orig_node;
  72
  73        orig_node = batadv_orig_node_new(bat_priv, addr);
  74        if (!orig_node)
  75                return NULL;
  76
  77        kref_get(&orig_node->refcount);
  78        hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
  79                                     batadv_choose_orig, orig_node,
  80                                     &orig_node->hash_entry);
  81        if (hash_added != 0) {
  82                /* remove refcnt for newly created orig_node and hash entry */
  83                batadv_orig_node_put(orig_node);
  84                batadv_orig_node_put(orig_node);
  85                orig_node = NULL;
  86        }
  87
  88        return orig_node;
  89}
  90
  91/**
  92 * batadv_v_ogm_start_timer() - restart the OGM sending timer
  93 * @bat_priv: the bat priv with all the soft interface information
  94 */
  95static void batadv_v_ogm_start_timer(struct batadv_priv *bat_priv)
  96{
  97        unsigned long msecs;
  98        /* this function may be invoked in different contexts (ogm rescheduling
  99         * or hard_iface activation), but the work timer should not be reset
 100         */
 101        if (delayed_work_pending(&bat_priv->bat_v.ogm_wq))
 102                return;
 103
 104        msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
 105        msecs += prandom_u32() % (2 * BATADV_JITTER);
 106        queue_delayed_work(batadv_event_workqueue, &bat_priv->bat_v.ogm_wq,
 107                           msecs_to_jiffies(msecs));
 108}
 109
 110/**
 111 * batadv_v_ogm_send_to_if() - send a batman ogm using a given interface
 112 * @skb: the OGM to send
 113 * @hard_iface: the interface to use to send the OGM
 114 */
 115static void batadv_v_ogm_send_to_if(struct sk_buff *skb,
 116                                    struct batadv_hard_iface *hard_iface)
 117{
 118        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 119
 120        if (hard_iface->if_status != BATADV_IF_ACTIVE)
 121                return;
 122
 123        batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_TX);
 124        batadv_add_counter(bat_priv, BATADV_CNT_MGMT_TX_BYTES,
 125                           skb->len + ETH_HLEN);
 126
 127        batadv_send_broadcast_skb(skb, hard_iface);
 128}
 129
 130/**
 131 * batadv_v_ogm_send() - periodic worker broadcasting the own OGM
 132 * @work: work queue item
 133 */
 134static void batadv_v_ogm_send(struct work_struct *work)
 135{
 136        struct batadv_hard_iface *hard_iface;
 137        struct batadv_priv_bat_v *bat_v;
 138        struct batadv_priv *bat_priv;
 139        struct batadv_ogm2_packet *ogm_packet;
 140        struct sk_buff *skb, *skb_tmp;
 141        unsigned char *ogm_buff;
 142        int ogm_buff_len;
 143        u16 tvlv_len = 0;
 144        int ret;
 145
 146        bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
 147        bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
 148
 149        if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
 150                goto out;
 151
 152        ogm_buff = bat_priv->bat_v.ogm_buff;
 153        ogm_buff_len = bat_priv->bat_v.ogm_buff_len;
 154        /* tt changes have to be committed before the tvlv data is
 155         * appended as it may alter the tt tvlv container
 156         */
 157        batadv_tt_local_commit_changes(bat_priv);
 158        tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, &ogm_buff,
 159                                                    &ogm_buff_len,
 160                                                    BATADV_OGM2_HLEN);
 161
 162        bat_priv->bat_v.ogm_buff = ogm_buff;
 163        bat_priv->bat_v.ogm_buff_len = ogm_buff_len;
 164
 165        skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + ogm_buff_len);
 166        if (!skb)
 167                goto reschedule;
 168
 169        skb_reserve(skb, ETH_HLEN);
 170        skb_put_data(skb, ogm_buff, ogm_buff_len);
 171
 172        ogm_packet = (struct batadv_ogm2_packet *)skb->data;
 173        ogm_packet->seqno = htonl(atomic_read(&bat_priv->bat_v.ogm_seqno));
 174        atomic_inc(&bat_priv->bat_v.ogm_seqno);
 175        ogm_packet->tvlv_len = htons(tvlv_len);
 176
 177        /* broadcast on every interface */
 178        rcu_read_lock();
 179        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
 180                if (hard_iface->soft_iface != bat_priv->soft_iface)
 181                        continue;
 182
 183                if (!kref_get_unless_zero(&hard_iface->refcount))
 184                        continue;
 185
 186                ret = batadv_hardif_no_broadcast(hard_iface, NULL, NULL);
 187                if (ret) {
 188                        char *type;
 189
 190                        switch (ret) {
 191                        case BATADV_HARDIF_BCAST_NORECIPIENT:
 192                                type = "no neighbor";
 193                                break;
 194                        case BATADV_HARDIF_BCAST_DUPFWD:
 195                                type = "single neighbor is source";
 196                                break;
 197                        case BATADV_HARDIF_BCAST_DUPORIG:
 198                                type = "single neighbor is originator";
 199                                break;
 200                        default:
 201                                type = "unknown";
 202                        }
 203
 204                        batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "OGM2 from ourselves on %s suppressed: %s\n",
 205                                   hard_iface->net_dev->name, type);
 206
 207                        batadv_hardif_put(hard_iface);
 208                        continue;
 209                }
 210
 211                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 212                           "Sending own OGM2 packet (originator %pM, seqno %u, throughput %u, TTL %d) on interface %s [%pM]\n",
 213                           ogm_packet->orig, ntohl(ogm_packet->seqno),
 214                           ntohl(ogm_packet->throughput), ogm_packet->ttl,
 215                           hard_iface->net_dev->name,
 216                           hard_iface->net_dev->dev_addr);
 217
 218                /* this skb gets consumed by batadv_v_ogm_send_to_if() */
 219                skb_tmp = skb_clone(skb, GFP_ATOMIC);
 220                if (!skb_tmp) {
 221                        batadv_hardif_put(hard_iface);
 222                        break;
 223                }
 224
 225                batadv_v_ogm_send_to_if(skb_tmp, hard_iface);
 226                batadv_hardif_put(hard_iface);
 227        }
 228        rcu_read_unlock();
 229
 230        consume_skb(skb);
 231
 232reschedule:
 233        batadv_v_ogm_start_timer(bat_priv);
 234out:
 235        return;
 236}
 237
 238/**
 239 * batadv_v_ogm_iface_enable() - prepare an interface for B.A.T.M.A.N. V
 240 * @hard_iface: the interface to prepare
 241 *
 242 * Takes care of scheduling own OGM sending routine for this interface.
 243 *
 244 * Return: 0 on success or a negative error code otherwise
 245 */
 246int batadv_v_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
 247{
 248        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 249
 250        batadv_v_ogm_start_timer(bat_priv);
 251
 252        return 0;
 253}
 254
 255/**
 256 * batadv_v_ogm_primary_iface_set() - set a new primary interface
 257 * @primary_iface: the new primary interface
 258 */
 259void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
 260{
 261        struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
 262        struct batadv_ogm2_packet *ogm_packet;
 263
 264        if (!bat_priv->bat_v.ogm_buff)
 265                return;
 266
 267        ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
 268        ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
 269}
 270
 271/**
 272 * batadv_v_forward_penalty() - apply a penalty to the throughput metric
 273 *  forwarded with B.A.T.M.A.N. V OGMs
 274 * @bat_priv: the bat priv with all the soft interface information
 275 * @if_incoming: the interface where the OGM has been received
 276 * @if_outgoing: the interface where the OGM has to be forwarded to
 277 * @throughput: the current throughput
 278 *
 279 * Apply a penalty on the current throughput metric value based on the
 280 * characteristic of the interface where the OGM has been received. The return
 281 * value is computed as follows:
 282 * - throughput * 50%          if the incoming and outgoing interface are the
 283 *                             same WiFi interface and the throughput is above
 284 *                             1MBit/s
 285 * - throughput                if the outgoing interface is the default
 286 *                             interface (i.e. this OGM is processed for the
 287 *                             internal table and not forwarded)
 288 * - throughput * hop penalty  otherwise
 289 *
 290 * Return: the penalised throughput metric.
 291 */
 292static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
 293                                    struct batadv_hard_iface *if_incoming,
 294                                    struct batadv_hard_iface *if_outgoing,
 295                                    u32 throughput)
 296{
 297        int hop_penalty = atomic_read(&bat_priv->hop_penalty);
 298        int hop_penalty_max = BATADV_TQ_MAX_VALUE;
 299
 300        /* Don't apply hop penalty in default originator table. */
 301        if (if_outgoing == BATADV_IF_DEFAULT)
 302                return throughput;
 303
 304        /* Forwarding on the same WiFi interface cuts the throughput in half
 305         * due to the store & forward characteristics of WIFI.
 306         * Very low throughput values are the exception.
 307         */
 308        if (throughput > 10 &&
 309            if_incoming == if_outgoing &&
 310            !(if_incoming->bat_v.flags & BATADV_FULL_DUPLEX))
 311                return throughput / 2;
 312
 313        /* hop penalty of 255 equals 100% */
 314        return throughput * (hop_penalty_max - hop_penalty) / hop_penalty_max;
 315}
 316
 317/**
 318 * batadv_v_ogm_forward() - check conditions and forward an OGM to the given
 319 *  outgoing interface
 320 * @bat_priv: the bat priv with all the soft interface information
 321 * @ogm_received: previously received OGM to be forwarded
 322 * @orig_node: the originator which has been updated
 323 * @neigh_node: the neigh_node through with the OGM has been received
 324 * @if_incoming: the interface on which this OGM was received on
 325 * @if_outgoing: the interface to which the OGM has to be forwarded to
 326 *
 327 * Forward an OGM to an interface after having altered the throughput metric and
 328 * the TTL value contained in it. The original OGM isn't modified.
 329 */
 330static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
 331                                 const struct batadv_ogm2_packet *ogm_received,
 332                                 struct batadv_orig_node *orig_node,
 333                                 struct batadv_neigh_node *neigh_node,
 334                                 struct batadv_hard_iface *if_incoming,
 335                                 struct batadv_hard_iface *if_outgoing)
 336{
 337        struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
 338        struct batadv_orig_ifinfo *orig_ifinfo = NULL;
 339        struct batadv_neigh_node *router = NULL;
 340        struct batadv_ogm2_packet *ogm_forward;
 341        unsigned char *skb_buff;
 342        struct sk_buff *skb;
 343        size_t packet_len;
 344        u16 tvlv_len;
 345
 346        /* only forward for specific interfaces, not for the default one. */
 347        if (if_outgoing == BATADV_IF_DEFAULT)
 348                goto out;
 349
 350        orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
 351        if (!orig_ifinfo)
 352                goto out;
 353
 354        /* acquire possibly updated router */
 355        router = batadv_orig_router_get(orig_node, if_outgoing);
 356
 357        /* strict rule: forward packets coming from the best next hop only */
 358        if (neigh_node != router)
 359                goto out;
 360
 361        /* don't forward the same seqno twice on one interface */
 362        if (orig_ifinfo->last_seqno_forwarded == ntohl(ogm_received->seqno))
 363                goto out;
 364
 365        orig_ifinfo->last_seqno_forwarded = ntohl(ogm_received->seqno);
 366
 367        if (ogm_received->ttl <= 1) {
 368                batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
 369                goto out;
 370        }
 371
 372        neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
 373        if (!neigh_ifinfo)
 374                goto out;
 375
 376        tvlv_len = ntohs(ogm_received->tvlv_len);
 377
 378        packet_len = BATADV_OGM2_HLEN + tvlv_len;
 379        skb = netdev_alloc_skb_ip_align(if_outgoing->net_dev,
 380                                        ETH_HLEN + packet_len);
 381        if (!skb)
 382                goto out;
 383
 384        skb_reserve(skb, ETH_HLEN);
 385        skb_buff = skb_put_data(skb, ogm_received, packet_len);
 386
 387        /* apply forward penalty */
 388        ogm_forward = (struct batadv_ogm2_packet *)skb_buff;
 389        ogm_forward->throughput = htonl(neigh_ifinfo->bat_v.throughput);
 390        ogm_forward->ttl--;
 391
 392        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 393                   "Forwarding OGM2 packet on %s: throughput %u, ttl %u, received via %s\n",
 394                   if_outgoing->net_dev->name, ntohl(ogm_forward->throughput),
 395                   ogm_forward->ttl, if_incoming->net_dev->name);
 396
 397        batadv_v_ogm_send_to_if(skb, if_outgoing);
 398
 399out:
 400        if (orig_ifinfo)
 401                batadv_orig_ifinfo_put(orig_ifinfo);
 402        if (router)
 403                batadv_neigh_node_put(router);
 404        if (neigh_ifinfo)
 405                batadv_neigh_ifinfo_put(neigh_ifinfo);
 406}
 407
 408/**
 409 * batadv_v_ogm_metric_update() - update route metric based on OGM
 410 * @bat_priv: the bat priv with all the soft interface information
 411 * @ogm2: OGM2 structure
 412 * @orig_node: Originator structure for which the OGM has been received
 413 * @neigh_node: the neigh_node through with the OGM has been received
 414 * @if_incoming: the interface where this packet was received
 415 * @if_outgoing: the interface for which the packet should be considered
 416 *
 417 * Return:
 418 *  1  if the OGM is new,
 419 *  0  if it is not new but valid,
 420 *  <0 on error (e.g. old OGM)
 421 */
 422static int batadv_v_ogm_metric_update(struct batadv_priv *bat_priv,
 423                                      const struct batadv_ogm2_packet *ogm2,
 424                                      struct batadv_orig_node *orig_node,
 425                                      struct batadv_neigh_node *neigh_node,
 426                                      struct batadv_hard_iface *if_incoming,
 427                                      struct batadv_hard_iface *if_outgoing)
 428{
 429        struct batadv_orig_ifinfo *orig_ifinfo;
 430        struct batadv_neigh_ifinfo *neigh_ifinfo = NULL;
 431        bool protection_started = false;
 432        int ret = -EINVAL;
 433        u32 path_throughput;
 434        s32 seq_diff;
 435
 436        orig_ifinfo = batadv_orig_ifinfo_new(orig_node, if_outgoing);
 437        if (!orig_ifinfo)
 438                goto out;
 439
 440        seq_diff = ntohl(ogm2->seqno) - orig_ifinfo->last_real_seqno;
 441
 442        if (!hlist_empty(&orig_node->neigh_list) &&
 443            batadv_window_protected(bat_priv, seq_diff,
 444                                    BATADV_OGM_MAX_AGE,
 445                                    &orig_ifinfo->batman_seqno_reset,
 446                                    &protection_started)) {
 447                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 448                           "Drop packet: packet within window protection time from %pM\n",
 449                           ogm2->orig);
 450                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 451                           "Last reset: %ld, %ld\n",
 452                           orig_ifinfo->batman_seqno_reset, jiffies);
 453                goto out;
 454        }
 455
 456        /* drop packets with old seqnos, however accept the first packet after
 457         * a host has been rebooted.
 458         */
 459        if (seq_diff < 0 && !protection_started)
 460                goto out;
 461
 462        neigh_node->last_seen = jiffies;
 463
 464        orig_node->last_seen = jiffies;
 465
 466        orig_ifinfo->last_real_seqno = ntohl(ogm2->seqno);
 467        orig_ifinfo->last_ttl = ogm2->ttl;
 468
 469        neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing);
 470        if (!neigh_ifinfo)
 471                goto out;
 472
 473        path_throughput = batadv_v_forward_penalty(bat_priv, if_incoming,
 474                                                   if_outgoing,
 475                                                   ntohl(ogm2->throughput));
 476        neigh_ifinfo->bat_v.throughput = path_throughput;
 477        neigh_ifinfo->bat_v.last_seqno = ntohl(ogm2->seqno);
 478        neigh_ifinfo->last_ttl = ogm2->ttl;
 479
 480        if (seq_diff > 0 || protection_started)
 481                ret = 1;
 482        else
 483                ret = 0;
 484out:
 485        if (orig_ifinfo)
 486                batadv_orig_ifinfo_put(orig_ifinfo);
 487        if (neigh_ifinfo)
 488                batadv_neigh_ifinfo_put(neigh_ifinfo);
 489
 490        return ret;
 491}
 492
 493/**
 494 * batadv_v_ogm_route_update() - update routes based on OGM
 495 * @bat_priv: the bat priv with all the soft interface information
 496 * @ethhdr: the Ethernet header of the OGM2
 497 * @ogm2: OGM2 structure
 498 * @orig_node: Originator structure for which the OGM has been received
 499 * @neigh_node: the neigh_node through with the OGM has been received
 500 * @if_incoming: the interface where this packet was received
 501 * @if_outgoing: the interface for which the packet should be considered
 502 *
 503 * Return: true if the packet should be forwarded, false otherwise
 504 */
 505static bool batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
 506                                      const struct ethhdr *ethhdr,
 507                                      const struct batadv_ogm2_packet *ogm2,
 508                                      struct batadv_orig_node *orig_node,
 509                                      struct batadv_neigh_node *neigh_node,
 510                                      struct batadv_hard_iface *if_incoming,
 511                                      struct batadv_hard_iface *if_outgoing)
 512{
 513        struct batadv_neigh_node *router = NULL;
 514        struct batadv_orig_node *orig_neigh_node;
 515        struct batadv_neigh_node *orig_neigh_router = NULL;
 516        struct batadv_neigh_ifinfo *router_ifinfo = NULL, *neigh_ifinfo = NULL;
 517        u32 router_throughput, neigh_throughput;
 518        u32 router_last_seqno;
 519        u32 neigh_last_seqno;
 520        s32 neigh_seq_diff;
 521        bool forward = false;
 522
 523        orig_neigh_node = batadv_v_ogm_orig_get(bat_priv, ethhdr->h_source);
 524        if (!orig_neigh_node)
 525                goto out;
 526
 527        orig_neigh_router = batadv_orig_router_get(orig_neigh_node,
 528                                                   if_outgoing);
 529
 530        /* drop packet if sender is not a direct neighbor and if we
 531         * don't route towards it
 532         */
 533        router = batadv_orig_router_get(orig_node, if_outgoing);
 534        if (router && router->orig_node != orig_node && !orig_neigh_router) {
 535                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 536                           "Drop packet: OGM via unknown neighbor!\n");
 537                goto out;
 538        }
 539
 540        /* Mark the OGM to be considered for forwarding, and update routes
 541         * if needed.
 542         */
 543        forward = true;
 544
 545        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 546                   "Searching and updating originator entry of received packet\n");
 547
 548        /* if this neighbor already is our next hop there is nothing
 549         * to change
 550         */
 551        if (router == neigh_node)
 552                goto out;
 553
 554        /* don't consider neighbours with worse throughput.
 555         * also switch route if this seqno is BATADV_V_MAX_ORIGDIFF newer than
 556         * the last received seqno from our best next hop.
 557         */
 558        if (router) {
 559                router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing);
 560                neigh_ifinfo = batadv_neigh_ifinfo_get(neigh_node, if_outgoing);
 561
 562                /* if these are not allocated, something is wrong. */
 563                if (!router_ifinfo || !neigh_ifinfo)
 564                        goto out;
 565
 566                neigh_last_seqno = neigh_ifinfo->bat_v.last_seqno;
 567                router_last_seqno = router_ifinfo->bat_v.last_seqno;
 568                neigh_seq_diff = neigh_last_seqno - router_last_seqno;
 569                router_throughput = router_ifinfo->bat_v.throughput;
 570                neigh_throughput = neigh_ifinfo->bat_v.throughput;
 571
 572                if (neigh_seq_diff < BATADV_OGM_MAX_ORIGDIFF &&
 573                    router_throughput >= neigh_throughput)
 574                        goto out;
 575        }
 576
 577        batadv_update_route(bat_priv, orig_node, if_outgoing, neigh_node);
 578out:
 579        if (router)
 580                batadv_neigh_node_put(router);
 581        if (orig_neigh_router)
 582                batadv_neigh_node_put(orig_neigh_router);
 583        if (orig_neigh_node)
 584                batadv_orig_node_put(orig_neigh_node);
 585        if (router_ifinfo)
 586                batadv_neigh_ifinfo_put(router_ifinfo);
 587        if (neigh_ifinfo)
 588                batadv_neigh_ifinfo_put(neigh_ifinfo);
 589
 590        return forward;
 591}
 592
 593/**
 594 * batadv_v_ogm_process_per_outif() - process a batman v OGM for an outgoing if
 595 * @bat_priv: the bat priv with all the soft interface information
 596 * @ethhdr: the Ethernet header of the OGM2
 597 * @ogm2: OGM2 structure
 598 * @orig_node: Originator structure for which the OGM has been received
 599 * @neigh_node: the neigh_node through with the OGM has been received
 600 * @if_incoming: the interface where this packet was received
 601 * @if_outgoing: the interface for which the packet should be considered
 602 */
 603static void
 604batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
 605                               const struct ethhdr *ethhdr,
 606                               const struct batadv_ogm2_packet *ogm2,
 607                               struct batadv_orig_node *orig_node,
 608                               struct batadv_neigh_node *neigh_node,
 609                               struct batadv_hard_iface *if_incoming,
 610                               struct batadv_hard_iface *if_outgoing)
 611{
 612        int seqno_age;
 613        bool forward;
 614
 615        /* first, update the metric with according sanity checks */
 616        seqno_age = batadv_v_ogm_metric_update(bat_priv, ogm2, orig_node,
 617                                               neigh_node, if_incoming,
 618                                               if_outgoing);
 619
 620        /* outdated sequence numbers are to be discarded */
 621        if (seqno_age < 0)
 622                return;
 623
 624        /* only unknown & newer OGMs contain TVLVs we are interested in */
 625        if (seqno_age > 0 && if_outgoing == BATADV_IF_DEFAULT)
 626                batadv_tvlv_containers_process(bat_priv, true, orig_node,
 627                                               NULL, NULL,
 628                                               (unsigned char *)(ogm2 + 1),
 629                                               ntohs(ogm2->tvlv_len));
 630
 631        /* if the metric update went through, update routes if needed */
 632        forward = batadv_v_ogm_route_update(bat_priv, ethhdr, ogm2, orig_node,
 633                                            neigh_node, if_incoming,
 634                                            if_outgoing);
 635
 636        /* if the routes have been processed correctly, check and forward */
 637        if (forward)
 638                batadv_v_ogm_forward(bat_priv, ogm2, orig_node, neigh_node,
 639                                     if_incoming, if_outgoing);
 640}
 641
 642/**
 643 * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated
 644 * @buff_pos: current position in the skb
 645 * @packet_len: total length of the skb
 646 * @tvlv_len: tvlv length of the previously considered OGM
 647 *
 648 * Return: true if there is enough space for another OGM, false otherwise.
 649 */
 650static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
 651                                     __be16 tvlv_len)
 652{
 653        int next_buff_pos = 0;
 654
 655        next_buff_pos += buff_pos + BATADV_OGM2_HLEN;
 656        next_buff_pos += ntohs(tvlv_len);
 657
 658        return (next_buff_pos <= packet_len) &&
 659               (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
 660}
 661
 662/**
 663 * batadv_v_ogm_process() - process an incoming batman v OGM
 664 * @skb: the skb containing the OGM
 665 * @ogm_offset: offset to the OGM which should be processed (for aggregates)
 666 * @if_incoming: the interface where this packet was receved
 667 */
 668static void batadv_v_ogm_process(const struct sk_buff *skb, int ogm_offset,
 669                                 struct batadv_hard_iface *if_incoming)
 670{
 671        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 672        struct ethhdr *ethhdr;
 673        struct batadv_orig_node *orig_node = NULL;
 674        struct batadv_hardif_neigh_node *hardif_neigh = NULL;
 675        struct batadv_neigh_node *neigh_node = NULL;
 676        struct batadv_hard_iface *hard_iface;
 677        struct batadv_ogm2_packet *ogm_packet;
 678        u32 ogm_throughput, link_throughput, path_throughput;
 679        int ret;
 680
 681        ethhdr = eth_hdr(skb);
 682        ogm_packet = (struct batadv_ogm2_packet *)(skb->data + ogm_offset);
 683
 684        ogm_throughput = ntohl(ogm_packet->throughput);
 685
 686        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 687                   "Received OGM2 packet via NB: %pM, IF: %s [%pM] (from OG: %pM, seqno %u, throughput %u, TTL %u, V %u, tvlv_len %u)\n",
 688                   ethhdr->h_source, if_incoming->net_dev->name,
 689                   if_incoming->net_dev->dev_addr, ogm_packet->orig,
 690                   ntohl(ogm_packet->seqno), ogm_throughput, ogm_packet->ttl,
 691                   ogm_packet->version, ntohs(ogm_packet->tvlv_len));
 692
 693        /* If the throughput metric is 0, immediately drop the packet. No need
 694         * to create orig_node / neigh_node for an unusable route.
 695         */
 696        if (ogm_throughput == 0) {
 697                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 698                           "Drop packet: originator packet with throughput metric of 0\n");
 699                return;
 700        }
 701
 702        /* require ELP packets be to received from this neighbor first */
 703        hardif_neigh = batadv_hardif_neigh_get(if_incoming, ethhdr->h_source);
 704        if (!hardif_neigh) {
 705                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 706                           "Drop packet: OGM via unknown neighbor!\n");
 707                goto out;
 708        }
 709
 710        orig_node = batadv_v_ogm_orig_get(bat_priv, ogm_packet->orig);
 711        if (!orig_node)
 712                return;
 713
 714        neigh_node = batadv_neigh_node_get_or_create(orig_node, if_incoming,
 715                                                     ethhdr->h_source);
 716        if (!neigh_node)
 717                goto out;
 718
 719        /* Update the received throughput metric to match the link
 720         * characteristic:
 721         *  - If this OGM traveled one hop so far (emitted by single hop
 722         *    neighbor) the path throughput metric equals the link throughput.
 723         *  - For OGMs traversing more than hop the path throughput metric is
 724         *    the smaller of the path throughput and the link throughput.
 725         */
 726        link_throughput = ewma_throughput_read(&hardif_neigh->bat_v.throughput);
 727        path_throughput = min_t(u32, link_throughput, ogm_throughput);
 728        ogm_packet->throughput = htonl(path_throughput);
 729
 730        batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet, orig_node,
 731                                       neigh_node, if_incoming,
 732                                       BATADV_IF_DEFAULT);
 733
 734        rcu_read_lock();
 735        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
 736                if (hard_iface->if_status != BATADV_IF_ACTIVE)
 737                        continue;
 738
 739                if (hard_iface->soft_iface != bat_priv->soft_iface)
 740                        continue;
 741
 742                if (!kref_get_unless_zero(&hard_iface->refcount))
 743                        continue;
 744
 745                ret = batadv_hardif_no_broadcast(hard_iface,
 746                                                 ogm_packet->orig,
 747                                                 hardif_neigh->orig);
 748
 749                if (ret) {
 750                        char *type;
 751
 752                        switch (ret) {
 753                        case BATADV_HARDIF_BCAST_NORECIPIENT:
 754                                type = "no neighbor";
 755                                break;
 756                        case BATADV_HARDIF_BCAST_DUPFWD:
 757                                type = "single neighbor is source";
 758                                break;
 759                        case BATADV_HARDIF_BCAST_DUPORIG:
 760                                type = "single neighbor is originator";
 761                                break;
 762                        default:
 763                                type = "unknown";
 764                        }
 765
 766                        batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "OGM2 packet from %pM on %s suppressed: %s\n",
 767                                   ogm_packet->orig, hard_iface->net_dev->name,
 768                                   type);
 769
 770                        batadv_hardif_put(hard_iface);
 771                        continue;
 772                }
 773
 774                batadv_v_ogm_process_per_outif(bat_priv, ethhdr, ogm_packet,
 775                                               orig_node, neigh_node,
 776                                               if_incoming, hard_iface);
 777
 778                batadv_hardif_put(hard_iface);
 779        }
 780        rcu_read_unlock();
 781out:
 782        if (orig_node)
 783                batadv_orig_node_put(orig_node);
 784        if (neigh_node)
 785                batadv_neigh_node_put(neigh_node);
 786        if (hardif_neigh)
 787                batadv_hardif_neigh_put(hardif_neigh);
 788}
 789
 790/**
 791 * batadv_v_ogm_packet_recv() - OGM2 receiving handler
 792 * @skb: the received OGM
 793 * @if_incoming: the interface where this OGM has been received
 794 *
 795 * Return: NET_RX_SUCCESS and consume the skb on success or returns NET_RX_DROP
 796 * (without freeing the skb) on failure
 797 */
 798int batadv_v_ogm_packet_recv(struct sk_buff *skb,
 799                             struct batadv_hard_iface *if_incoming)
 800{
 801        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 802        struct batadv_ogm2_packet *ogm_packet;
 803        struct ethhdr *ethhdr = eth_hdr(skb);
 804        int ogm_offset;
 805        u8 *packet_pos;
 806        int ret = NET_RX_DROP;
 807
 808        /* did we receive a OGM2 packet on an interface that does not have
 809         * B.A.T.M.A.N. V enabled ?
 810         */
 811        if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0)
 812                goto free_skb;
 813
 814        if (!batadv_check_management_packet(skb, if_incoming, BATADV_OGM2_HLEN))
 815                goto free_skb;
 816
 817        if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
 818                goto free_skb;
 819
 820        ogm_packet = (struct batadv_ogm2_packet *)skb->data;
 821
 822        if (batadv_is_my_mac(bat_priv, ogm_packet->orig))
 823                goto free_skb;
 824
 825        batadv_inc_counter(bat_priv, BATADV_CNT_MGMT_RX);
 826        batadv_add_counter(bat_priv, BATADV_CNT_MGMT_RX_BYTES,
 827                           skb->len + ETH_HLEN);
 828
 829        ogm_offset = 0;
 830        ogm_packet = (struct batadv_ogm2_packet *)skb->data;
 831
 832        while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
 833                                        ogm_packet->tvlv_len)) {
 834                batadv_v_ogm_process(skb, ogm_offset, if_incoming);
 835
 836                ogm_offset += BATADV_OGM2_HLEN;
 837                ogm_offset += ntohs(ogm_packet->tvlv_len);
 838
 839                packet_pos = skb->data + ogm_offset;
 840                ogm_packet = (struct batadv_ogm2_packet *)packet_pos;
 841        }
 842
 843        ret = NET_RX_SUCCESS;
 844
 845free_skb:
 846        if (ret == NET_RX_SUCCESS)
 847                consume_skb(skb);
 848        else
 849                kfree_skb(skb);
 850
 851        return ret;
 852}
 853
 854/**
 855 * batadv_v_ogm_init() - initialise the OGM2 engine
 856 * @bat_priv: the bat priv with all the soft interface information
 857 *
 858 * Return: 0 on success or a negative error code in case of failure
 859 */
 860int batadv_v_ogm_init(struct batadv_priv *bat_priv)
 861{
 862        struct batadv_ogm2_packet *ogm_packet;
 863        unsigned char *ogm_buff;
 864        u32 random_seqno;
 865
 866        bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN;
 867        ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC);
 868        if (!ogm_buff)
 869                return -ENOMEM;
 870
 871        bat_priv->bat_v.ogm_buff = ogm_buff;
 872        ogm_packet = (struct batadv_ogm2_packet *)ogm_buff;
 873        ogm_packet->packet_type = BATADV_OGM2;
 874        ogm_packet->version = BATADV_COMPAT_VERSION;
 875        ogm_packet->ttl = BATADV_TTL;
 876        ogm_packet->flags = BATADV_NO_FLAGS;
 877        ogm_packet->throughput = htonl(BATADV_THROUGHPUT_MAX_VALUE);
 878
 879        /* randomize initial seqno to avoid collision */
 880        get_random_bytes(&random_seqno, sizeof(random_seqno));
 881        atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno);
 882        INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send);
 883
 884        return 0;
 885}
 886
 887/**
 888 * batadv_v_ogm_free() - free OGM private resources
 889 * @bat_priv: the bat priv with all the soft interface information
 890 */
 891void batadv_v_ogm_free(struct batadv_priv *bat_priv)
 892{
 893        cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq);
 894
 895        kfree(bat_priv->bat_v.ogm_buff);
 896        bat_priv->bat_v.ogm_buff = NULL;
 897        bat_priv->bat_v.ogm_buff_len = 0;
 898}
 899