linux/net/batman-adv/bat_v_elp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) B.A.T.M.A.N. contributors:
   3 *
   4 * Linus Lüssing, Marek Lindner
   5 */
   6
   7#include "bat_v_elp.h"
   8#include "main.h"
   9
  10#include <linux/atomic.h>
  11#include <linux/bitops.h>
  12#include <linux/byteorder/generic.h>
  13#include <linux/errno.h>
  14#include <linux/etherdevice.h>
  15#include <linux/ethtool.h>
  16#include <linux/gfp.h>
  17#include <linux/if_ether.h>
  18#include <linux/jiffies.h>
  19#include <linux/kernel.h>
  20#include <linux/kref.h>
  21#include <linux/minmax.h>
  22#include <linux/netdevice.h>
  23#include <linux/nl80211.h>
  24#include <linux/prandom.h>
  25#include <linux/random.h>
  26#include <linux/rculist.h>
  27#include <linux/rcupdate.h>
  28#include <linux/rtnetlink.h>
  29#include <linux/skbuff.h>
  30#include <linux/stddef.h>
  31#include <linux/string.h>
  32#include <linux/types.h>
  33#include <linux/workqueue.h>
  34#include <net/cfg80211.h>
  35#include <uapi/linux/batadv_packet.h>
  36
  37#include "bat_algo.h"
  38#include "bat_v_ogm.h"
  39#include "hard-interface.h"
  40#include "log.h"
  41#include "originator.h"
  42#include "routing.h"
  43#include "send.h"
  44
  45/**
  46 * batadv_v_elp_start_timer() - restart timer for ELP periodic work
  47 * @hard_iface: the interface for which the timer has to be reset
  48 */
  49static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
  50{
  51        unsigned int msecs;
  52
  53        msecs = atomic_read(&hard_iface->bat_v.elp_interval) - BATADV_JITTER;
  54        msecs += prandom_u32_max(2 * BATADV_JITTER);
  55
  56        queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.elp_wq,
  57                           msecs_to_jiffies(msecs));
  58}
  59
  60/**
  61 * batadv_v_elp_get_throughput() - get the throughput towards a neighbour
  62 * @neigh: the neighbour for which the throughput has to be obtained
  63 *
  64 * Return: The throughput towards the given neighbour in multiples of 100kpbs
  65 *         (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
  66 */
  67static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
  68{
  69        struct batadv_hard_iface *hard_iface = neigh->if_incoming;
  70        struct ethtool_link_ksettings link_settings;
  71        struct net_device *real_netdev;
  72        struct station_info sinfo;
  73        u32 throughput;
  74        int ret;
  75
  76        /* if the user specified a customised value for this interface, then
  77         * return it directly
  78         */
  79        throughput =  atomic_read(&hard_iface->bat_v.throughput_override);
  80        if (throughput != 0)
  81                return throughput;
  82
  83        /* if this is a wireless device, then ask its throughput through
  84         * cfg80211 API
  85         */
  86        if (batadv_is_wifi_hardif(hard_iface)) {
  87                if (!batadv_is_cfg80211_hardif(hard_iface))
  88                        /* unsupported WiFi driver version */
  89                        goto default_throughput;
  90
  91                real_netdev = batadv_get_real_netdev(hard_iface->net_dev);
  92                if (!real_netdev)
  93                        goto default_throughput;
  94
  95                ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo);
  96
  97                if (!ret) {
  98                        /* free the TID stats immediately */
  99                        cfg80211_sinfo_release_content(&sinfo);
 100                }
 101
 102                dev_put(real_netdev);
 103                if (ret == -ENOENT) {
 104                        /* Node is not associated anymore! It would be
 105                         * possible to delete this neighbor. For now set
 106                         * the throughput metric to 0.
 107                         */
 108                        return 0;
 109                }
 110                if (ret)
 111                        goto default_throughput;
 112
 113                if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))
 114                        return sinfo.expected_throughput / 100;
 115
 116                /* try to estimate the expected throughput based on reported tx
 117                 * rates
 118                 */
 119                if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
 120                        return cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
 121
 122                goto default_throughput;
 123        }
 124
 125        /* if not a wifi interface, check if this device provides data via
 126         * ethtool (e.g. an Ethernet adapter)
 127         */
 128        memset(&link_settings, 0, sizeof(link_settings));
 129        rtnl_lock();
 130        ret = __ethtool_get_link_ksettings(hard_iface->net_dev, &link_settings);
 131        rtnl_unlock();
 132        if (ret == 0) {
 133                /* link characteristics might change over time */
 134                if (link_settings.base.duplex == DUPLEX_FULL)
 135                        hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
 136                else
 137                        hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
 138
 139                throughput = link_settings.base.speed;
 140                if (throughput && throughput != SPEED_UNKNOWN)
 141                        return throughput * 10;
 142        }
 143
 144default_throughput:
 145        if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) {
 146                batadv_info(hard_iface->soft_iface,
 147                            "WiFi driver or ethtool info does not provide information about link speeds on interface %s, therefore defaulting to hardcoded throughput values of %u.%1u Mbps. Consider overriding the throughput manually or checking your driver.\n",
 148                            hard_iface->net_dev->name,
 149                            BATADV_THROUGHPUT_DEFAULT_VALUE / 10,
 150                            BATADV_THROUGHPUT_DEFAULT_VALUE % 10);
 151                hard_iface->bat_v.flags |= BATADV_WARNING_DEFAULT;
 152        }
 153
 154        /* if none of the above cases apply, return the base_throughput */
 155        return BATADV_THROUGHPUT_DEFAULT_VALUE;
 156}
 157
 158/**
 159 * batadv_v_elp_throughput_metric_update() - worker updating the throughput
 160 *  metric of a single hop neighbour
 161 * @work: the work queue item
 162 */
 163void batadv_v_elp_throughput_metric_update(struct work_struct *work)
 164{
 165        struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
 166        struct batadv_hardif_neigh_node *neigh;
 167
 168        neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
 169                                   metric_work);
 170        neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
 171                             bat_v);
 172
 173        ewma_throughput_add(&neigh->bat_v.throughput,
 174                            batadv_v_elp_get_throughput(neigh));
 175
 176        /* decrement refcounter to balance increment performed before scheduling
 177         * this task
 178         */
 179        batadv_hardif_neigh_put(neigh);
 180}
 181
 182/**
 183 * batadv_v_elp_wifi_neigh_probe() - send link probing packets to a neighbour
 184 * @neigh: the neighbour to probe
 185 *
 186 * Sends a predefined number of unicast wifi packets to a given neighbour in
 187 * order to trigger the throughput estimation on this link by the RC algorithm.
 188 * Packets are sent only if there is not enough payload unicast traffic towards
 189 * this neighbour..
 190 *
 191 * Return: True on success and false in case of error during skb preparation.
 192 */
 193static bool
 194batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
 195{
 196        struct batadv_hard_iface *hard_iface = neigh->if_incoming;
 197        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 198        unsigned long last_tx_diff;
 199        struct sk_buff *skb;
 200        int probe_len, i;
 201        int elp_skb_len;
 202
 203        /* this probing routine is for Wifi neighbours only */
 204        if (!batadv_is_wifi_hardif(hard_iface))
 205                return true;
 206
 207        /* probe the neighbor only if no unicast packets have been sent
 208         * to it in the last 100 milliseconds: this is the rate control
 209         * algorithm sampling interval (minstrel). In this way, if not
 210         * enough traffic has been sent to the neighbor, batman-adv can
 211         * generate 2 probe packets and push the RC algorithm to perform
 212         * the sampling
 213         */
 214        last_tx_diff = jiffies_to_msecs(jiffies - neigh->bat_v.last_unicast_tx);
 215        if (last_tx_diff <= BATADV_ELP_PROBE_MAX_TX_DIFF)
 216                return true;
 217
 218        probe_len = max_t(int, sizeof(struct batadv_elp_packet),
 219                          BATADV_ELP_MIN_PROBE_SIZE);
 220
 221        for (i = 0; i < BATADV_ELP_PROBES_PER_NODE; i++) {
 222                elp_skb_len = hard_iface->bat_v.elp_skb->len;
 223                skb = skb_copy_expand(hard_iface->bat_v.elp_skb, 0,
 224                                      probe_len - elp_skb_len,
 225                                      GFP_ATOMIC);
 226                if (!skb)
 227                        return false;
 228
 229                /* Tell the skb to get as big as the allocated space (we want
 230                 * the packet to be exactly of that size to make the link
 231                 * throughput estimation effective.
 232                 */
 233                skb_put_zero(skb, probe_len - hard_iface->bat_v.elp_skb->len);
 234
 235                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 236                           "Sending unicast (probe) ELP packet on interface %s to %pM\n",
 237                           hard_iface->net_dev->name, neigh->addr);
 238
 239                batadv_send_skb_packet(skb, hard_iface, neigh->addr);
 240        }
 241
 242        return true;
 243}
 244
 245/**
 246 * batadv_v_elp_periodic_work() - ELP periodic task per interface
 247 * @work: work queue item
 248 *
 249 * Emits broadcast ELP messages in regular intervals.
 250 */
 251static void batadv_v_elp_periodic_work(struct work_struct *work)
 252{
 253        struct batadv_hardif_neigh_node *hardif_neigh;
 254        struct batadv_hard_iface *hard_iface;
 255        struct batadv_hard_iface_bat_v *bat_v;
 256        struct batadv_elp_packet *elp_packet;
 257        struct batadv_priv *bat_priv;
 258        struct sk_buff *skb;
 259        u32 elp_interval;
 260        bool ret;
 261
 262        bat_v = container_of(work, struct batadv_hard_iface_bat_v, elp_wq.work);
 263        hard_iface = container_of(bat_v, struct batadv_hard_iface, bat_v);
 264        bat_priv = netdev_priv(hard_iface->soft_iface);
 265
 266        if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
 267                goto out;
 268
 269        /* we are in the process of shutting this interface down */
 270        if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
 271            hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
 272                goto out;
 273
 274        /* the interface was enabled but may not be ready yet */
 275        if (hard_iface->if_status != BATADV_IF_ACTIVE)
 276                goto restart_timer;
 277
 278        skb = skb_copy(hard_iface->bat_v.elp_skb, GFP_ATOMIC);
 279        if (!skb)
 280                goto restart_timer;
 281
 282        elp_packet = (struct batadv_elp_packet *)skb->data;
 283        elp_packet->seqno = htonl(atomic_read(&hard_iface->bat_v.elp_seqno));
 284        elp_interval = atomic_read(&hard_iface->bat_v.elp_interval);
 285        elp_packet->elp_interval = htonl(elp_interval);
 286
 287        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 288                   "Sending broadcast ELP packet on interface %s, seqno %u\n",
 289                   hard_iface->net_dev->name,
 290                   atomic_read(&hard_iface->bat_v.elp_seqno));
 291
 292        batadv_send_broadcast_skb(skb, hard_iface);
 293
 294        atomic_inc(&hard_iface->bat_v.elp_seqno);
 295
 296        /* The throughput metric is updated on each sent packet. This way, if a
 297         * node is dead and no longer sends packets, batman-adv is still able to
 298         * react timely to its death.
 299         *
 300         * The throughput metric is updated by following these steps:
 301         * 1) if the hard_iface is wifi => send a number of unicast ELPs for
 302         *    probing/sampling to each neighbor
 303         * 2) update the throughput metric value of each neighbor (note that the
 304         *    value retrieved in this step might be 100ms old because the
 305         *    probing packets at point 1) could still be in the HW queue)
 306         */
 307        rcu_read_lock();
 308        hlist_for_each_entry_rcu(hardif_neigh, &hard_iface->neigh_list, list) {
 309                if (!batadv_v_elp_wifi_neigh_probe(hardif_neigh))
 310                        /* if something goes wrong while probing, better to stop
 311                         * sending packets immediately and reschedule the task
 312                         */
 313                        break;
 314
 315                if (!kref_get_unless_zero(&hardif_neigh->refcount))
 316                        continue;
 317
 318                /* Reading the estimated throughput from cfg80211 is a task that
 319                 * may sleep and that is not allowed in an rcu protected
 320                 * context. Therefore schedule a task for that.
 321                 */
 322                ret = queue_work(batadv_event_workqueue,
 323                                 &hardif_neigh->bat_v.metric_work);
 324
 325                if (!ret)
 326                        batadv_hardif_neigh_put(hardif_neigh);
 327        }
 328        rcu_read_unlock();
 329
 330restart_timer:
 331        batadv_v_elp_start_timer(hard_iface);
 332out:
 333        return;
 334}
 335
 336/**
 337 * batadv_v_elp_iface_enable() - setup the ELP interface private resources
 338 * @hard_iface: interface for which the data has to be prepared
 339 *
 340 * Return: 0 on success or a -ENOMEM in case of failure.
 341 */
 342int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
 343{
 344        static const size_t tvlv_padding = sizeof(__be32);
 345        struct batadv_elp_packet *elp_packet;
 346        unsigned char *elp_buff;
 347        u32 random_seqno;
 348        size_t size;
 349        int res = -ENOMEM;
 350
 351        size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN + tvlv_padding;
 352        hard_iface->bat_v.elp_skb = dev_alloc_skb(size);
 353        if (!hard_iface->bat_v.elp_skb)
 354                goto out;
 355
 356        skb_reserve(hard_iface->bat_v.elp_skb, ETH_HLEN + NET_IP_ALIGN);
 357        elp_buff = skb_put_zero(hard_iface->bat_v.elp_skb,
 358                                BATADV_ELP_HLEN + tvlv_padding);
 359        elp_packet = (struct batadv_elp_packet *)elp_buff;
 360
 361        elp_packet->packet_type = BATADV_ELP;
 362        elp_packet->version = BATADV_COMPAT_VERSION;
 363
 364        /* randomize initial seqno to avoid collision */
 365        get_random_bytes(&random_seqno, sizeof(random_seqno));
 366        atomic_set(&hard_iface->bat_v.elp_seqno, random_seqno);
 367
 368        /* assume full-duplex by default */
 369        hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
 370
 371        /* warn the user (again) if there is no throughput data is available */
 372        hard_iface->bat_v.flags &= ~BATADV_WARNING_DEFAULT;
 373
 374        if (batadv_is_wifi_hardif(hard_iface))
 375                hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
 376
 377        INIT_DELAYED_WORK(&hard_iface->bat_v.elp_wq,
 378                          batadv_v_elp_periodic_work);
 379        batadv_v_elp_start_timer(hard_iface);
 380        res = 0;
 381
 382out:
 383        return res;
 384}
 385
 386/**
 387 * batadv_v_elp_iface_disable() - release ELP interface private resources
 388 * @hard_iface: interface for which the resources have to be released
 389 */
 390void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface)
 391{
 392        cancel_delayed_work_sync(&hard_iface->bat_v.elp_wq);
 393
 394        dev_kfree_skb(hard_iface->bat_v.elp_skb);
 395        hard_iface->bat_v.elp_skb = NULL;
 396}
 397
 398/**
 399 * batadv_v_elp_iface_activate() - update the ELP buffer belonging to the given
 400 *  hard-interface
 401 * @primary_iface: the new primary interface
 402 * @hard_iface: interface holding the to-be-updated buffer
 403 */
 404void batadv_v_elp_iface_activate(struct batadv_hard_iface *primary_iface,
 405                                 struct batadv_hard_iface *hard_iface)
 406{
 407        struct batadv_elp_packet *elp_packet;
 408        struct sk_buff *skb;
 409
 410        if (!hard_iface->bat_v.elp_skb)
 411                return;
 412
 413        skb = hard_iface->bat_v.elp_skb;
 414        elp_packet = (struct batadv_elp_packet *)skb->data;
 415        ether_addr_copy(elp_packet->orig,
 416                        primary_iface->net_dev->dev_addr);
 417}
 418
 419/**
 420 * batadv_v_elp_primary_iface_set() - change internal data to reflect the new
 421 *  primary interface
 422 * @primary_iface: the new primary interface
 423 */
 424void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface)
 425{
 426        struct batadv_hard_iface *hard_iface;
 427
 428        /* update orig field of every elp iface belonging to this mesh */
 429        rcu_read_lock();
 430        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
 431                if (primary_iface->soft_iface != hard_iface->soft_iface)
 432                        continue;
 433
 434                batadv_v_elp_iface_activate(primary_iface, hard_iface);
 435        }
 436        rcu_read_unlock();
 437}
 438
 439/**
 440 * batadv_v_elp_neigh_update() - update an ELP neighbour node
 441 * @bat_priv: the bat priv with all the soft interface information
 442 * @neigh_addr: the neighbour interface address
 443 * @if_incoming: the interface the packet was received through
 444 * @elp_packet: the received ELP packet
 445 *
 446 * Updates the ELP neighbour node state with the data received within the new
 447 * ELP packet.
 448 */
 449static void batadv_v_elp_neigh_update(struct batadv_priv *bat_priv,
 450                                      u8 *neigh_addr,
 451                                      struct batadv_hard_iface *if_incoming,
 452                                      struct batadv_elp_packet *elp_packet)
 453
 454{
 455        struct batadv_neigh_node *neigh;
 456        struct batadv_orig_node *orig_neigh;
 457        struct batadv_hardif_neigh_node *hardif_neigh;
 458        s32 seqno_diff;
 459        s32 elp_latest_seqno;
 460
 461        orig_neigh = batadv_v_ogm_orig_get(bat_priv, elp_packet->orig);
 462        if (!orig_neigh)
 463                return;
 464
 465        neigh = batadv_neigh_node_get_or_create(orig_neigh,
 466                                                if_incoming, neigh_addr);
 467        if (!neigh)
 468                goto orig_free;
 469
 470        hardif_neigh = batadv_hardif_neigh_get(if_incoming, neigh_addr);
 471        if (!hardif_neigh)
 472                goto neigh_free;
 473
 474        elp_latest_seqno = hardif_neigh->bat_v.elp_latest_seqno;
 475        seqno_diff = ntohl(elp_packet->seqno) - elp_latest_seqno;
 476
 477        /* known or older sequence numbers are ignored. However always adopt
 478         * if the router seems to have been restarted.
 479         */
 480        if (seqno_diff < 1 && seqno_diff > -BATADV_ELP_MAX_AGE)
 481                goto hardif_free;
 482
 483        neigh->last_seen = jiffies;
 484        hardif_neigh->last_seen = jiffies;
 485        hardif_neigh->bat_v.elp_latest_seqno = ntohl(elp_packet->seqno);
 486        hardif_neigh->bat_v.elp_interval = ntohl(elp_packet->elp_interval);
 487
 488hardif_free:
 489        batadv_hardif_neigh_put(hardif_neigh);
 490neigh_free:
 491        batadv_neigh_node_put(neigh);
 492orig_free:
 493        batadv_orig_node_put(orig_neigh);
 494}
 495
 496/**
 497 * batadv_v_elp_packet_recv() - main ELP packet handler
 498 * @skb: the received packet
 499 * @if_incoming: the interface this packet was received through
 500 *
 501 * Return: NET_RX_SUCCESS and consumes the skb if the packet was properly
 502 * processed or NET_RX_DROP in case of failure.
 503 */
 504int batadv_v_elp_packet_recv(struct sk_buff *skb,
 505                             struct batadv_hard_iface *if_incoming)
 506{
 507        struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 508        struct batadv_elp_packet *elp_packet;
 509        struct batadv_hard_iface *primary_if;
 510        struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
 511        bool res;
 512        int ret = NET_RX_DROP;
 513
 514        res = batadv_check_management_packet(skb, if_incoming, BATADV_ELP_HLEN);
 515        if (!res)
 516                goto free_skb;
 517
 518        if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
 519                goto free_skb;
 520
 521        /* did we receive a B.A.T.M.A.N. V ELP packet on an interface
 522         * that does not have B.A.T.M.A.N. V ELP enabled ?
 523         */
 524        if (strcmp(bat_priv->algo_ops->name, "BATMAN_V") != 0)
 525                goto free_skb;
 526
 527        elp_packet = (struct batadv_elp_packet *)skb->data;
 528
 529        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
 530                   "Received ELP packet from %pM seqno %u ORIG: %pM\n",
 531                   ethhdr->h_source, ntohl(elp_packet->seqno),
 532                   elp_packet->orig);
 533
 534        primary_if = batadv_primary_if_get_selected(bat_priv);
 535        if (!primary_if)
 536                goto free_skb;
 537
 538        batadv_v_elp_neigh_update(bat_priv, ethhdr->h_source, if_incoming,
 539                                  elp_packet);
 540
 541        ret = NET_RX_SUCCESS;
 542        batadv_hardif_put(primary_if);
 543
 544free_skb:
 545        if (ret == NET_RX_SUCCESS)
 546                consume_skb(skb);
 547        else
 548                kfree_skb(skb);
 549
 550        return ret;
 551}
 552