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