linux/net/core/link_watch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Linux network device link state notification
   4 *
   5 * Author:
   6 *     Stefan Rompf <sux@loplof.de>
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/netdevice.h>
  11#include <linux/if.h>
  12#include <net/sock.h>
  13#include <net/pkt_sched.h>
  14#include <linux/rtnetlink.h>
  15#include <linux/jiffies.h>
  16#include <linux/spinlock.h>
  17#include <linux/workqueue.h>
  18#include <linux/bitops.h>
  19#include <linux/types.h>
  20
  21
  22enum lw_bits {
  23        LW_URGENT = 0,
  24};
  25
  26static unsigned long linkwatch_flags;
  27static unsigned long linkwatch_nextevent;
  28
  29static void linkwatch_event(struct work_struct *dummy);
  30static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
  31
  32static LIST_HEAD(lweventlist);
  33static DEFINE_SPINLOCK(lweventlist_lock);
  34
  35static unsigned char default_operstate(const struct net_device *dev)
  36{
  37        if (netif_testing(dev))
  38                return IF_OPER_TESTING;
  39
  40        if (!netif_carrier_ok(dev))
  41                return (dev->ifindex != dev_get_iflink(dev) ?
  42                        IF_OPER_LOWERLAYERDOWN : IF_OPER_DOWN);
  43
  44        if (netif_dormant(dev))
  45                return IF_OPER_DORMANT;
  46
  47        return IF_OPER_UP;
  48}
  49
  50
  51static void rfc2863_policy(struct net_device *dev)
  52{
  53        unsigned char operstate = default_operstate(dev);
  54
  55        if (operstate == dev->operstate)
  56                return;
  57
  58        write_lock_bh(&dev_base_lock);
  59
  60        switch(dev->link_mode) {
  61        case IF_LINK_MODE_TESTING:
  62                if (operstate == IF_OPER_UP)
  63                        operstate = IF_OPER_TESTING;
  64                break;
  65
  66        case IF_LINK_MODE_DORMANT:
  67                if (operstate == IF_OPER_UP)
  68                        operstate = IF_OPER_DORMANT;
  69                break;
  70        case IF_LINK_MODE_DEFAULT:
  71        default:
  72                break;
  73        }
  74
  75        dev->operstate = operstate;
  76
  77        write_unlock_bh(&dev_base_lock);
  78}
  79
  80
  81void linkwatch_init_dev(struct net_device *dev)
  82{
  83        /* Handle pre-registration link state changes */
  84        if (!netif_carrier_ok(dev) || netif_dormant(dev) ||
  85            netif_testing(dev))
  86                rfc2863_policy(dev);
  87}
  88
  89
  90static bool linkwatch_urgent_event(struct net_device *dev)
  91{
  92        if (!netif_running(dev))
  93                return false;
  94
  95        if (dev->ifindex != dev_get_iflink(dev))
  96                return true;
  97
  98        if (netif_is_lag_port(dev) || netif_is_lag_master(dev))
  99                return true;
 100
 101        return netif_carrier_ok(dev) && qdisc_tx_changing(dev);
 102}
 103
 104
 105static void linkwatch_add_event(struct net_device *dev)
 106{
 107        unsigned long flags;
 108
 109        spin_lock_irqsave(&lweventlist_lock, flags);
 110        if (list_empty(&dev->link_watch_list)) {
 111                list_add_tail(&dev->link_watch_list, &lweventlist);
 112                dev_hold(dev);
 113        }
 114        spin_unlock_irqrestore(&lweventlist_lock, flags);
 115}
 116
 117
 118static void linkwatch_schedule_work(int urgent)
 119{
 120        unsigned long delay = linkwatch_nextevent - jiffies;
 121
 122        if (test_bit(LW_URGENT, &linkwatch_flags))
 123                return;
 124
 125        /* Minimise down-time: drop delay for up event. */
 126        if (urgent) {
 127                if (test_and_set_bit(LW_URGENT, &linkwatch_flags))
 128                        return;
 129                delay = 0;
 130        }
 131
 132        /* If we wrap around we'll delay it by at most HZ. */
 133        if (delay > HZ)
 134                delay = 0;
 135
 136        /*
 137         * If urgent, schedule immediate execution; otherwise, don't
 138         * override the existing timer.
 139         */
 140        if (test_bit(LW_URGENT, &linkwatch_flags))
 141                mod_delayed_work(system_wq, &linkwatch_work, 0);
 142        else
 143                schedule_delayed_work(&linkwatch_work, delay);
 144}
 145
 146
 147static void linkwatch_do_dev(struct net_device *dev)
 148{
 149        /*
 150         * Make sure the above read is complete since it can be
 151         * rewritten as soon as we clear the bit below.
 152         */
 153        smp_mb__before_atomic();
 154
 155        /* We are about to handle this device,
 156         * so new events can be accepted
 157         */
 158        clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
 159
 160        rfc2863_policy(dev);
 161        if (dev->flags & IFF_UP) {
 162                if (netif_carrier_ok(dev))
 163                        dev_activate(dev);
 164                else
 165                        dev_deactivate(dev);
 166
 167                netdev_state_change(dev);
 168        }
 169        dev_put(dev);
 170}
 171
 172static void __linkwatch_run_queue(int urgent_only)
 173{
 174#define MAX_DO_DEV_PER_LOOP     100
 175
 176        int do_dev = MAX_DO_DEV_PER_LOOP;
 177        struct net_device *dev;
 178        LIST_HEAD(wrk);
 179
 180        /* Give urgent case more budget */
 181        if (urgent_only)
 182                do_dev += MAX_DO_DEV_PER_LOOP;
 183
 184        /*
 185         * Limit the number of linkwatch events to one
 186         * per second so that a runaway driver does not
 187         * cause a storm of messages on the netlink
 188         * socket.  This limit does not apply to up events
 189         * while the device qdisc is down.
 190         */
 191        if (!urgent_only)
 192                linkwatch_nextevent = jiffies + HZ;
 193        /* Limit wrap-around effect on delay. */
 194        else if (time_after(linkwatch_nextevent, jiffies + HZ))
 195                linkwatch_nextevent = jiffies;
 196
 197        clear_bit(LW_URGENT, &linkwatch_flags);
 198
 199        spin_lock_irq(&lweventlist_lock);
 200        list_splice_init(&lweventlist, &wrk);
 201
 202        while (!list_empty(&wrk) && do_dev > 0) {
 203
 204                dev = list_first_entry(&wrk, struct net_device, link_watch_list);
 205                list_del_init(&dev->link_watch_list);
 206
 207                if (!netif_device_present(dev) ||
 208                    (urgent_only && !linkwatch_urgent_event(dev))) {
 209                        list_add_tail(&dev->link_watch_list, &lweventlist);
 210                        continue;
 211                }
 212                spin_unlock_irq(&lweventlist_lock);
 213                linkwatch_do_dev(dev);
 214                do_dev--;
 215                spin_lock_irq(&lweventlist_lock);
 216        }
 217
 218        /* Add the remaining work back to lweventlist */
 219        list_splice_init(&wrk, &lweventlist);
 220
 221        if (!list_empty(&lweventlist))
 222                linkwatch_schedule_work(0);
 223        spin_unlock_irq(&lweventlist_lock);
 224}
 225
 226void linkwatch_forget_dev(struct net_device *dev)
 227{
 228        unsigned long flags;
 229        int clean = 0;
 230
 231        spin_lock_irqsave(&lweventlist_lock, flags);
 232        if (!list_empty(&dev->link_watch_list)) {
 233                list_del_init(&dev->link_watch_list);
 234                clean = 1;
 235        }
 236        spin_unlock_irqrestore(&lweventlist_lock, flags);
 237        if (clean)
 238                linkwatch_do_dev(dev);
 239}
 240
 241
 242/* Must be called with the rtnl semaphore held */
 243void linkwatch_run_queue(void)
 244{
 245        __linkwatch_run_queue(0);
 246}
 247
 248
 249static void linkwatch_event(struct work_struct *dummy)
 250{
 251        rtnl_lock();
 252        __linkwatch_run_queue(time_after(linkwatch_nextevent, jiffies));
 253        rtnl_unlock();
 254}
 255
 256
 257void linkwatch_fire_event(struct net_device *dev)
 258{
 259        bool urgent = linkwatch_urgent_event(dev);
 260
 261        if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
 262                linkwatch_add_event(dev);
 263        } else if (!urgent)
 264                return;
 265
 266        linkwatch_schedule_work(urgent);
 267}
 268EXPORT_SYMBOL(linkwatch_fire_event);
 269