Blame view
net/core/netpoll.c
21.3 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 |
/* * Common framework for low-level network console, dump, and debugger code * * Sep 8 2003 Matt Mackall <mpm@selenic.com> * * based on the netconsole code from: * * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com> * Copyright (C) 2002 Red Hat, Inc. */ |
bff38771e netpoll: Introduc... |
11 |
#include <linux/moduleparam.h> |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 |
#include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/string.h> |
14c850212 [INET_SOCK]: Move... |
15 |
#include <linux/if_arp.h> |
1da177e4c Linux-2.6.12-rc2 |
16 17 18 19 20 21 22 23 |
#include <linux/inetdevice.h> #include <linux/inet.h> #include <linux/interrupt.h> #include <linux/netpoll.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/rcupdate.h> #include <linux/workqueue.h> |
5a0e3ad6a include cleanup: ... |
24 |
#include <linux/slab.h> |
bc3b2d7fb net: Add export.h... |
25 |
#include <linux/export.h> |
1da177e4c Linux-2.6.12-rc2 |
26 27 28 |
#include <net/tcp.h> #include <net/udp.h> #include <asm/unaligned.h> |
9cbc1cb8c Merge branch 'mas... |
29 |
#include <trace/events/napi.h> |
1da177e4c Linux-2.6.12-rc2 |
30 31 32 33 34 35 36 37 |
/* * We maintain a small pool of fully-sized skbs, to make sure the * message gets out even in extreme OOM situations. */ #define MAX_UDP_CHUNK 1460 #define MAX_SKBS 32 |
1da177e4c Linux-2.6.12-rc2 |
38 |
|
a1bcfacd0 netpoll: private ... |
39 |
static struct sk_buff_head skb_pool; |
1da177e4c Linux-2.6.12-rc2 |
40 41 |
static atomic_t trapped; |
2bdfe0bae netpoll retry cle... |
42 |
#define USEC_PER_POLL 50 |
d9452e9f8 [NETPOLL]: Revert... |
43 44 |
#define NETPOLL_RX_ENABLED 1 #define NETPOLL_RX_DROP 2 |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 48 |
#define MAX_SKB_SIZE \ (MAX_UDP_CHUNK + sizeof(struct udphdr) + \ sizeof(struct iphdr) + sizeof(struct ethhdr)) |
3578b0c8a Revert "net: remo... |
49 |
static void zap_completion_queue(void); |
068c6e98b [NET] netpoll: br... |
50 |
static void arp_reply(struct sk_buff *skb); |
1da177e4c Linux-2.6.12-rc2 |
51 |
|
bff38771e netpoll: Introduc... |
52 53 |
static unsigned int carrier_timeout = 4; module_param(carrier_timeout, uint, 0644); |
c4028958b WorkStruct: make ... |
54 |
static void queue_process(struct work_struct *work) |
1da177e4c Linux-2.6.12-rc2 |
55 |
{ |
4c1ac1b49 Merge branch 'mas... |
56 57 |
struct netpoll_info *npinfo = container_of(work, struct netpoll_info, tx_work.work); |
1da177e4c Linux-2.6.12-rc2 |
58 |
struct sk_buff *skb; |
3640543df [PATCH] netpoll: ... |
59 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
60 |
|
6c43ff18f netpoll deferred ... |
61 62 |
while ((skb = skb_dequeue(&npinfo->txq))) { struct net_device *dev = skb->dev; |
008298231 netdev: add more ... |
63 |
const struct net_device_ops *ops = dev->netdev_ops; |
fd2ea0a79 net: Use queue aw... |
64 |
struct netdev_queue *txq; |
1da177e4c Linux-2.6.12-rc2 |
65 |
|
6c43ff18f netpoll deferred ... |
66 67 68 69 |
if (!netif_device_present(dev) || !netif_running(dev)) { __kfree_skb(skb); continue; } |
1da177e4c Linux-2.6.12-rc2 |
70 |
|
fd2ea0a79 net: Use queue aw... |
71 |
txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); |
3640543df [PATCH] netpoll: ... |
72 |
local_irq_save(flags); |
fd2ea0a79 net: Use queue aw... |
73 |
__netif_tx_lock(txq, smp_processor_id()); |
734664982 net: Add queue st... |
74 |
if (netif_xmit_frozen_or_stopped(txq) || |
008298231 netdev: add more ... |
75 |
ops->ndo_start_xmit(skb, dev) != NETDEV_TX_OK) { |
6c43ff18f netpoll deferred ... |
76 |
skb_queue_head(&npinfo->txq, skb); |
fd2ea0a79 net: Use queue aw... |
77 |
__netif_tx_unlock(txq); |
3640543df [PATCH] netpoll: ... |
78 |
local_irq_restore(flags); |
1da177e4c Linux-2.6.12-rc2 |
79 |
|
25442cafb [NETPOLL]: Fixups... |
80 |
schedule_delayed_work(&npinfo->tx_work, HZ/10); |
6c43ff18f netpoll deferred ... |
81 82 |
return; } |
fd2ea0a79 net: Use queue aw... |
83 |
__netif_tx_unlock(txq); |
3640543df [PATCH] netpoll: ... |
84 |
local_irq_restore(flags); |
1da177e4c Linux-2.6.12-rc2 |
85 |
} |
1da177e4c Linux-2.6.12-rc2 |
86 |
} |
b51655b95 [NET]: Annotate _... |
87 88 |
static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, unsigned short ulen, __be32 saddr, __be32 daddr) |
1da177e4c Linux-2.6.12-rc2 |
89 |
{ |
d6f5493c1 [NET]: Annotate c... |
90 |
__wsum psum; |
fb286bb29 [NET]: Detect har... |
91 |
|
604763722 [NET]: Treat CHEC... |
92 |
if (uh->check == 0 || skb_csum_unnecessary(skb)) |
1da177e4c Linux-2.6.12-rc2 |
93 |
return 0; |
fb286bb29 [NET]: Detect har... |
94 |
psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); |
84fa7933a [NET]: Replace CH... |
95 |
if (skb->ip_summed == CHECKSUM_COMPLETE && |
d3bc23e7e [NET]: Annotate c... |
96 |
!csum_fold(csum_add(psum, skb->csum))) |
fb286bb29 [NET]: Detect har... |
97 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
98 |
|
fb286bb29 [NET]: Detect har... |
99 |
skb->csum = psum; |
1da177e4c Linux-2.6.12-rc2 |
100 |
|
fb286bb29 [NET]: Detect har... |
101 |
return __skb_checksum_complete(skb); |
1da177e4c Linux-2.6.12-rc2 |
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
} /* * Check whether delayed processing was scheduled for our NIC. If so, * we attempt to grab the poll lock and use ->poll() to pump the card. * If this fails, either we've recursed in ->poll() or it's already * running on another CPU. * * Note: we don't mask interrupts with this lock because we're using * trylock here and interrupts are already disabled in the softirq * case. Further, we test the poll_owner to avoid recursion on UP * systems where the lock doesn't exist. * * In cases where there is bi-directional communications, reading only * one message at a time can lead to packets being dropped by the * network adapter, forcing superfluous retries and possibly timeouts. * Thus, we set our budget to greater than 1. */ |
0a7606c12 [NET]: Fix race b... |
120 121 122 123 124 125 126 127 128 129 130 |
static int poll_one_napi(struct netpoll_info *npinfo, struct napi_struct *napi, int budget) { int work; /* net_rx_action's ->poll() invocations and our's are * synchronized by this test which is only made while * holding the napi->poll_lock. */ if (!test_bit(NAPI_STATE_SCHED, &napi->state)) return budget; |
d9452e9f8 [NETPOLL]: Revert... |
131 |
npinfo->rx_flags |= NETPOLL_RX_DROP; |
0a7606c12 [NET]: Fix race b... |
132 |
atomic_inc(&trapped); |
7b363e440 netpoll: fix race... |
133 |
set_bit(NAPI_STATE_NPSVC, &napi->state); |
0a7606c12 [NET]: Fix race b... |
134 135 |
work = napi->poll(napi, budget); |
7d18f1148 net: Fix arg to t... |
136 |
trace_napi_poll(napi); |
0a7606c12 [NET]: Fix race b... |
137 |
|
7b363e440 netpoll: fix race... |
138 |
clear_bit(NAPI_STATE_NPSVC, &napi->state); |
0a7606c12 [NET]: Fix race b... |
139 |
atomic_dec(&trapped); |
d9452e9f8 [NETPOLL]: Revert... |
140 |
npinfo->rx_flags &= ~NETPOLL_RX_DROP; |
0a7606c12 [NET]: Fix race b... |
141 142 143 |
return budget - work; } |
5106930bd [NETPOLL]: netpol... |
144 |
static void poll_napi(struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
145 |
{ |
bea3348ee [NET]: Make NAPI ... |
146 |
struct napi_struct *napi; |
1da177e4c Linux-2.6.12-rc2 |
147 |
int budget = 16; |
f13d493d9 netpoll: Revert n... |
148 |
list_for_each_entry(napi, &dev->napi_list, dev_list) { |
0a7606c12 [NET]: Fix race b... |
149 |
if (napi->poll_owner != smp_processor_id() && |
bea3348ee [NET]: Make NAPI ... |
150 |
spin_trylock(&napi->poll_lock)) { |
5106930bd [NETPOLL]: netpol... |
151 |
budget = poll_one_napi(dev->npinfo, napi, budget); |
bea3348ee [NET]: Make NAPI ... |
152 |
spin_unlock(&napi->poll_lock); |
0a7606c12 [NET]: Fix race b... |
153 154 155 |
if (!budget) break; |
bea3348ee [NET]: Make NAPI ... |
156 |
} |
1da177e4c Linux-2.6.12-rc2 |
157 158 |
} } |
068c6e98b [NET] netpoll: br... |
159 160 |
static void service_arp_queue(struct netpoll_info *npi) { |
5106930bd [NETPOLL]: netpol... |
161 162 |
if (npi) { struct sk_buff *skb; |
068c6e98b [NET] netpoll: br... |
163 |
|
5106930bd [NETPOLL]: netpol... |
164 165 |
while ((skb = skb_dequeue(&npi->arp_tx))) arp_reply(skb); |
068c6e98b [NET] netpoll: br... |
166 |
} |
068c6e98b [NET] netpoll: br... |
167 |
} |
234b921db netpoll: Remove u... |
168 |
static void netpoll_poll_dev(struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
169 |
{ |
5e392739d netpoll: don't de... |
170 |
const struct net_device_ops *ops; |
5106930bd [NETPOLL]: netpol... |
171 |
|
5e392739d netpoll: don't de... |
172 173 174 175 176 |
if (!dev || !netif_running(dev)) return; ops = dev->netdev_ops; if (!ops->ndo_poll_controller) |
1da177e4c Linux-2.6.12-rc2 |
177 178 179 |
return; /* Process pending work on NIC */ |
d314774cf netdev: network d... |
180 |
ops->ndo_poll_controller(dev); |
5106930bd [NETPOLL]: netpol... |
181 182 |
poll_napi(dev); |
1da177e4c Linux-2.6.12-rc2 |
183 |
|
5a698af53 bond: service net... |
184 185 186 187 188 189 190 191 192 193 |
if (dev->priv_flags & IFF_SLAVE) { if (dev->npinfo) { struct net_device *bond_dev = dev->master; struct sk_buff *skb; while ((skb = skb_dequeue(&dev->npinfo->arp_tx))) { skb->dev = bond_dev; skb_queue_tail(&bond_dev->npinfo->arp_tx, skb); } } } |
5106930bd [NETPOLL]: netpol... |
194 |
service_arp_queue(dev->npinfo); |
068c6e98b [NET] netpoll: br... |
195 |
|
3578b0c8a Revert "net: remo... |
196 |
zap_completion_queue(); |
1da177e4c Linux-2.6.12-rc2 |
197 198 199 200 201 202 |
} static void refill_skbs(void) { struct sk_buff *skb; unsigned long flags; |
a1bcfacd0 netpoll: private ... |
203 204 |
spin_lock_irqsave(&skb_pool.lock, flags); while (skb_pool.qlen < MAX_SKBS) { |
1da177e4c Linux-2.6.12-rc2 |
205 206 207 |
skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC); if (!skb) break; |
a1bcfacd0 netpoll: private ... |
208 |
__skb_queue_tail(&skb_pool, skb); |
1da177e4c Linux-2.6.12-rc2 |
209 |
} |
a1bcfacd0 netpoll: private ... |
210 |
spin_unlock_irqrestore(&skb_pool.lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
211 |
} |
3578b0c8a Revert "net: remo... |
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
static void zap_completion_queue(void) { unsigned long flags; struct softnet_data *sd = &get_cpu_var(softnet_data); if (sd->completion_queue) { struct sk_buff *clist; local_irq_save(flags); clist = sd->completion_queue; sd->completion_queue = NULL; local_irq_restore(flags); while (clist != NULL) { struct sk_buff *skb = clist; clist = clist->next; if (skb->destructor) { atomic_inc(&skb->users); dev_kfree_skb_any(skb); /* put this one back */ } else { __kfree_skb(skb); } } } put_cpu_var(softnet_data); } |
a1bcfacd0 netpoll: private ... |
239 |
static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve) |
1da177e4c Linux-2.6.12-rc2 |
240 |
{ |
a1bcfacd0 netpoll: private ... |
241 242 |
int count = 0; struct sk_buff *skb; |
1da177e4c Linux-2.6.12-rc2 |
243 |
|
3578b0c8a Revert "net: remo... |
244 |
zap_completion_queue(); |
a1bcfacd0 netpoll: private ... |
245 |
refill_skbs(); |
1da177e4c Linux-2.6.12-rc2 |
246 |
repeat: |
1da177e4c Linux-2.6.12-rc2 |
247 248 |
skb = alloc_skb(len, GFP_ATOMIC); |
a1bcfacd0 netpoll: private ... |
249 250 |
if (!skb) skb = skb_dequeue(&skb_pool); |
1da177e4c Linux-2.6.12-rc2 |
251 252 |
if (!skb) { |
a1bcfacd0 netpoll: private ... |
253 |
if (++count < 10) { |
2a49e001c netpoll: Remove w... |
254 |
netpoll_poll_dev(np->dev); |
a1bcfacd0 netpoll: private ... |
255 |
goto repeat; |
1da177e4c Linux-2.6.12-rc2 |
256 |
} |
a1bcfacd0 netpoll: private ... |
257 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
258 259 260 261 262 263 |
} atomic_set(&skb->users, 1); skb_reserve(skb, reserve); return skb; } |
bea3348ee [NET]: Make NAPI ... |
264 265 266 267 268 269 270 271 272 273 |
static int netpoll_owner_active(struct net_device *dev) { struct napi_struct *napi; list_for_each_entry(napi, &dev->napi_list, dev_list) { if (napi->poll_owner == smp_processor_id()) return 1; } return 0; } |
c2355e1ab bonding: Fix bond... |
274 275 |
void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
276 |
{ |
2bdfe0bae netpoll retry cle... |
277 278 |
int status = NETDEV_TX_BUSY; unsigned long tries; |
008298231 netdev: add more ... |
279 |
const struct net_device_ops *ops = dev->netdev_ops; |
de85d99eb netpoll: Fix RCU ... |
280 |
/* It is up to the caller to keep npinfo alive. */ |
4ec93edb1 [NET] CORE: Fix w... |
281 |
struct netpoll_info *npinfo = np->dev->npinfo; |
2bdfe0bae netpoll retry cle... |
282 |
|
4ec93edb1 [NET] CORE: Fix w... |
283 284 285 286 |
if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { __kfree_skb(skb); return; } |
2bdfe0bae netpoll retry cle... |
287 288 |
/* don't get messages out of order, and no recursion */ |
bea3348ee [NET]: Make NAPI ... |
289 |
if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) { |
fd2ea0a79 net: Use queue aw... |
290 |
struct netdev_queue *txq; |
a49f99ffc [NETPOLL]: Fix lo... |
291 |
unsigned long flags; |
fd2ea0a79 net: Use queue aw... |
292 |
txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); |
a49f99ffc [NETPOLL]: Fix lo... |
293 |
local_irq_save(flags); |
0db3dc73f [NETPOLL]: tx loc... |
294 295 296 |
/* try until next clock tick */ for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) { |
fd2ea0a79 net: Use queue aw... |
297 |
if (__netif_tx_trylock(txq)) { |
734664982 net: Add queue st... |
298 |
if (!netif_xmit_stopped(txq)) { |
008298231 netdev: add more ... |
299 |
status = ops->ndo_start_xmit(skb, dev); |
08baf5610 net: txq_trans_up... |
300 301 302 |
if (status == NETDEV_TX_OK) txq_trans_update(txq); } |
fd2ea0a79 net: Use queue aw... |
303 |
__netif_tx_unlock(txq); |
e37b8d931 [NETPOLL]: Make s... |
304 305 306 |
if (status == NETDEV_TX_OK) break; |
e37b8d931 [NETPOLL]: Make s... |
307 |
} |
0db3dc73f [NETPOLL]: tx loc... |
308 309 |
/* tickle device maybe there is some cleanup */ |
2a49e001c netpoll: Remove w... |
310 |
netpoll_poll_dev(np->dev); |
0db3dc73f [NETPOLL]: tx loc... |
311 312 |
udelay(USEC_PER_POLL); |
0db1d6fc1 [NETPOLL]: add re... |
313 |
} |
79b1bee88 netpoll: warning ... |
314 315 316 317 318 |
WARN_ONCE(!irqs_disabled(), "netpoll_send_skb(): %s enabled interrupts in poll (%pF) ", dev->name, ops->ndo_start_xmit); |
a49f99ffc [NETPOLL]: Fix lo... |
319 |
local_irq_restore(flags); |
1da177e4c Linux-2.6.12-rc2 |
320 |
} |
1da177e4c Linux-2.6.12-rc2 |
321 |
|
2bdfe0bae netpoll retry cle... |
322 |
if (status != NETDEV_TX_OK) { |
5de4a473b netpoll queue cle... |
323 |
skb_queue_tail(&npinfo->txq, skb); |
4c1ac1b49 Merge branch 'mas... |
324 |
schedule_delayed_work(&npinfo->tx_work,0); |
1da177e4c Linux-2.6.12-rc2 |
325 |
} |
1da177e4c Linux-2.6.12-rc2 |
326 |
} |
c2355e1ab bonding: Fix bond... |
327 |
EXPORT_SYMBOL(netpoll_send_skb_on_dev); |
1da177e4c Linux-2.6.12-rc2 |
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
void netpoll_send_udp(struct netpoll *np, const char *msg, int len) { int total_len, eth_len, ip_len, udp_len; struct sk_buff *skb; struct udphdr *udph; struct iphdr *iph; struct ethhdr *eth; udp_len = len + sizeof(*udph); ip_len = eth_len = udp_len + sizeof(*iph); total_len = eth_len + ETH_HLEN + NET_IP_ALIGN; skb = find_skb(np, total_len, total_len - len); if (!skb) return; |
27d7ff46a [SK_BUFF]: Introd... |
344 |
skb_copy_to_linear_data(skb, msg, len); |
1da177e4c Linux-2.6.12-rc2 |
345 |
skb->len += len; |
4bedb4520 [SK_BUFF]: Introd... |
346 347 348 |
skb_push(skb, sizeof(*udph)); skb_reset_transport_header(skb); udph = udp_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
349 350 351 352 |
udph->source = htons(np->local_port); udph->dest = htons(np->remote_port); udph->len = htons(udp_len); udph->check = 0; |
e7557af56 netpoll: store lo... |
353 354 |
udph->check = csum_tcpudp_magic(np->local_ip, np->remote_ip, |
8e365eec0 [NETPOLL]: Comput... |
355 |
udp_len, IPPROTO_UDP, |
07f0757a6 include/net net/ ... |
356 |
csum_partial(udph, udp_len, 0)); |
8e365eec0 [NETPOLL]: Comput... |
357 |
if (udph->check == 0) |
5e57dff2c [NETPOLL]: Anothe... |
358 |
udph->check = CSUM_MANGLED_0; |
1da177e4c Linux-2.6.12-rc2 |
359 |
|
e2d1bca7e [SK_BUFF]: Use sk... |
360 361 |
skb_push(skb, sizeof(*iph)); skb_reset_network_header(skb); |
eddc9ec53 [SK_BUFF]: Introd... |
362 |
iph = ip_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
363 364 365 366 367 368 369 370 371 372 |
/* iph->version = 4; iph->ihl = 5; */ put_unaligned(0x45, (unsigned char *)iph); iph->tos = 0; put_unaligned(htons(ip_len), &(iph->tot_len)); iph->id = 0; iph->frag_off = 0; iph->ttl = 64; iph->protocol = IPPROTO_UDP; iph->check = 0; |
e7557af56 netpoll: store lo... |
373 374 |
put_unaligned(np->local_ip, &(iph->saddr)); put_unaligned(np->remote_ip, &(iph->daddr)); |
1da177e4c Linux-2.6.12-rc2 |
375 376 377 |
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); |
459a98ed8 [SK_BUFF]: Introd... |
378 |
skb_reset_mac_header(skb); |
206daaf77 [NETPOLL]: initia... |
379 |
skb->protocol = eth->h_proto = htons(ETH_P_IP); |
095386416 [NETPOLL]: no nee... |
380 381 |
memcpy(eth->h_source, np->dev->dev_addr, ETH_ALEN); memcpy(eth->h_dest, np->remote_mac, ETH_ALEN); |
1da177e4c Linux-2.6.12-rc2 |
382 383 384 385 386 |
skb->dev = np->dev; netpoll_send_skb(np, skb); } |
9e34a5b51 net/core: EXPORT_... |
387 |
EXPORT_SYMBOL(netpoll_send_udp); |
1da177e4c Linux-2.6.12-rc2 |
388 389 390 |
static void arp_reply(struct sk_buff *skb) { |
115c1d6e6 [NETPOLL]: Introd... |
391 |
struct netpoll_info *npinfo = skb->dev->npinfo; |
1da177e4c Linux-2.6.12-rc2 |
392 393 394 |
struct arphdr *arp; unsigned char *arp_ptr; int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; |
252e33467 [NET] net/core: A... |
395 |
__be32 sip, tip; |
47bbec028 [NETPOLL]: make a... |
396 |
unsigned char *sha; |
1da177e4c Linux-2.6.12-rc2 |
397 |
struct sk_buff *send_skb; |
508e14b4a netpoll: allow ex... |
398 399 |
struct netpoll *np, *tmp; unsigned long flags; |
ae641949d net: Remove all u... |
400 |
int hlen, tlen; |
508e14b4a netpoll: allow ex... |
401 402 403 404 405 406 407 408 409 410 411 412 413 |
int hits = 0; if (list_empty(&npinfo->rx_np)) return; /* Before checking the packet, we do some early inspection whether this is interesting at all */ spin_lock_irqsave(&npinfo->rx_lock, flags); list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { if (np->dev == skb->dev) hits++; } spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
414 |
|
508e14b4a netpoll: allow ex... |
415 416 |
/* No netpoll struct is using this dev */ if (!hits) |
115c1d6e6 [NETPOLL]: Introd... |
417 |
return; |
1da177e4c Linux-2.6.12-rc2 |
418 419 420 421 |
/* No arp on this interface */ if (skb->dev->flags & IFF_NOARP) return; |
988b70507 [ARP]: Introduce ... |
422 |
if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) |
1da177e4c Linux-2.6.12-rc2 |
423 |
return; |
c1d2bbe1c [SK_BUFF]: Introd... |
424 |
skb_reset_network_header(skb); |
badff6d01 [SK_BUFF]: Introd... |
425 |
skb_reset_transport_header(skb); |
d0a92be05 [SK_BUFF]: Introd... |
426 |
arp = arp_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
427 428 429 430 431 432 |
if ((arp->ar_hrd != htons(ARPHRD_ETHER) && arp->ar_hrd != htons(ARPHRD_IEEE802)) || arp->ar_pro != htons(ETH_P_IP) || arp->ar_op != htons(ARPOP_REQUEST)) return; |
47bbec028 [NETPOLL]: make a... |
433 434 435 436 |
arp_ptr = (unsigned char *)(arp+1); /* save the location of the src hw addr */ sha = arp_ptr; arp_ptr += skb->dev->addr_len; |
1da177e4c Linux-2.6.12-rc2 |
437 |
memcpy(&sip, arp_ptr, 4); |
47bbec028 [NETPOLL]: make a... |
438 |
arp_ptr += 4; |
508e14b4a netpoll: allow ex... |
439 440 |
/* If we actually cared about dst hw addr, it would get copied here */ |
47bbec028 [NETPOLL]: make a... |
441 |
arp_ptr += skb->dev->addr_len; |
1da177e4c Linux-2.6.12-rc2 |
442 443 444 |
memcpy(&tip, arp_ptr, 4); /* Should we ignore arp? */ |
508e14b4a netpoll: allow ex... |
445 |
if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) |
1da177e4c Linux-2.6.12-rc2 |
446 |
return; |
988b70507 [ARP]: Introduce ... |
447 |
size = arp_hdr_len(skb->dev); |
1da177e4c Linux-2.6.12-rc2 |
448 |
|
508e14b4a netpoll: allow ex... |
449 450 451 452 |
spin_lock_irqsave(&npinfo->rx_lock, flags); list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { if (tip != np->local_ip) continue; |
1da177e4c Linux-2.6.12-rc2 |
453 |
|
ae641949d net: Remove all u... |
454 455 456 |
hlen = LL_RESERVED_SPACE(np->dev); tlen = np->dev->needed_tailroom; send_skb = find_skb(np, size + hlen + tlen, hlen); |
508e14b4a netpoll: allow ex... |
457 458 |
if (!send_skb) continue; |
1da177e4c Linux-2.6.12-rc2 |
459 |
|
508e14b4a netpoll: allow ex... |
460 461 462 463 |
skb_reset_network_header(send_skb); arp = (struct arphdr *) skb_put(send_skb, size); send_skb->dev = skb->dev; send_skb->protocol = htons(ETH_P_ARP); |
1da177e4c Linux-2.6.12-rc2 |
464 |
|
508e14b4a netpoll: allow ex... |
465 466 467 468 469 470 471 |
/* Fill the device header for the ARP frame */ if (dev_hard_header(send_skb, skb->dev, ptype, sha, np->dev->dev_addr, send_skb->len) < 0) { kfree_skb(send_skb); continue; } |
1da177e4c Linux-2.6.12-rc2 |
472 |
|
508e14b4a netpoll: allow ex... |
473 474 475 476 477 478 479 |
/* * Fill out the arp protocol part. * * we only support ethernet device type, * which (according to RFC 1390) should * always equal 1 (Ethernet). */ |
1da177e4c Linux-2.6.12-rc2 |
480 |
|
508e14b4a netpoll: allow ex... |
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 |
arp->ar_hrd = htons(np->dev->type); arp->ar_pro = htons(ETH_P_IP); arp->ar_hln = np->dev->addr_len; arp->ar_pln = 4; arp->ar_op = htons(type); arp_ptr = (unsigned char *)(arp + 1); memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len); arp_ptr += np->dev->addr_len; memcpy(arp_ptr, &tip, 4); arp_ptr += 4; memcpy(arp_ptr, sha, np->dev->addr_len); arp_ptr += np->dev->addr_len; memcpy(arp_ptr, &sip, 4); netpoll_send_skb(np, send_skb); /* If there are several rx_hooks for the same address, we're fine by sending a single reply */ break; } spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
503 504 505 506 507 |
} int __netpoll_rx(struct sk_buff *skb) { int proto, len, ulen; |
508e14b4a netpoll: allow ex... |
508 |
int hits = 0; |
b71d1d426 inet: constify ip... |
509 |
const struct iphdr *iph; |
1da177e4c Linux-2.6.12-rc2 |
510 |
struct udphdr *uh; |
508e14b4a netpoll: allow ex... |
511 512 |
struct netpoll_info *npinfo = skb->dev->npinfo; struct netpoll *np, *tmp; |
068c6e98b [NET] netpoll: br... |
513 |
|
508e14b4a netpoll: allow ex... |
514 |
if (list_empty(&npinfo->rx_np)) |
1da177e4c Linux-2.6.12-rc2 |
515 |
goto out; |
508e14b4a netpoll: allow ex... |
516 |
|
1da177e4c Linux-2.6.12-rc2 |
517 518 |
if (skb->dev->type != ARPHRD_ETHER) goto out; |
d9452e9f8 [NETPOLL]: Revert... |
519 |
/* check if netpoll clients need ARP */ |
724800d61 [NET] CORE: Use h... |
520 |
if (skb->protocol == htons(ETH_P_ARP) && |
1da177e4c Linux-2.6.12-rc2 |
521 |
atomic_read(&trapped)) { |
508e14b4a netpoll: allow ex... |
522 |
skb_queue_tail(&npinfo->arp_tx, skb); |
1da177e4c Linux-2.6.12-rc2 |
523 524 525 526 527 528 529 530 531 532 |
return 1; } proto = ntohs(eth_hdr(skb)->h_proto); if (proto != ETH_P_IP) goto out; if (skb->pkt_type == PACKET_OTHERHOST) goto out; if (skb_shared(skb)) goto out; |
1da177e4c Linux-2.6.12-rc2 |
533 534 |
if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto out; |
e9278a475 netpoll: fix inco... |
535 |
iph = (struct iphdr *)skb->data; |
1da177e4c Linux-2.6.12-rc2 |
536 537 538 539 |
if (iph->ihl < 5 || iph->version != 4) goto out; if (!pskb_may_pull(skb, iph->ihl*4)) goto out; |
e9278a475 netpoll: fix inco... |
540 |
iph = (struct iphdr *)skb->data; |
1da177e4c Linux-2.6.12-rc2 |
541 542 543 544 545 546 |
if (ip_fast_csum((u8 *)iph, iph->ihl) != 0) goto out; len = ntohs(iph->tot_len); if (skb->len < len || len < iph->ihl*4) goto out; |
5e7d7fa57 [NET]: Fix UDP ch... |
547 548 549 550 551 552 |
/* * Our transport medium may have padded the buffer out. * Now We trim to the true length of the frame. */ if (pskb_trim_rcsum(skb, len)) goto out; |
e9278a475 netpoll: fix inco... |
553 |
iph = (struct iphdr *)skb->data; |
1da177e4c Linux-2.6.12-rc2 |
554 555 556 557 558 559 560 561 562 |
if (iph->protocol != IPPROTO_UDP) goto out; len -= iph->ihl*4; uh = (struct udphdr *)(((char *)iph) + iph->ihl*4); ulen = ntohs(uh->len); if (ulen != len) goto out; |
fb286bb29 [NET]: Detect har... |
563 |
if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr)) |
1da177e4c Linux-2.6.12-rc2 |
564 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
565 |
|
508e14b4a netpoll: allow ex... |
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { if (np->local_ip && np->local_ip != iph->daddr) continue; if (np->remote_ip && np->remote_ip != iph->saddr) continue; if (np->local_port && np->local_port != ntohs(uh->dest)) continue; np->rx_hook(np, ntohs(uh->source), (char *)(uh+1), ulen - sizeof(struct udphdr)); hits++; } if (!hits) goto out; |
1da177e4c Linux-2.6.12-rc2 |
582 583 584 585 586 587 588 589 590 591 592 593 |
kfree_skb(skb); return 1; out: if (atomic_read(&trapped)) { kfree_skb(skb); return 1; } return 0; } |
0bcc18161 [NET] netconsole:... |
594 595 596 597 598 |
void netpoll_print_options(struct netpoll *np) { printk(KERN_INFO "%s: local port %d ", np->name, np->local_port); |
e7557af56 netpoll: store lo... |
599 600 601 |
printk(KERN_INFO "%s: local IP %pI4 ", np->name, &np->local_ip); |
5fc05f876 netpoll: warn whe... |
602 603 |
printk(KERN_INFO "%s: interface '%s' ", |
0bcc18161 [NET] netconsole:... |
604 605 606 607 |
np->name, np->dev_name); printk(KERN_INFO "%s: remote port %d ", np->name, np->remote_port); |
e7557af56 netpoll: store lo... |
608 609 610 |
printk(KERN_INFO "%s: remote IP %pI4 ", np->name, &np->remote_ip); |
e174961ca net: convert prin... |
611 612 613 |
printk(KERN_INFO "%s: remote ethernet address %pM ", np->name, np->remote_mac); |
0bcc18161 [NET] netconsole:... |
614 |
} |
9e34a5b51 net/core: EXPORT_... |
615 |
EXPORT_SYMBOL(netpoll_print_options); |
0bcc18161 [NET] netconsole:... |
616 |
|
1da177e4c Linux-2.6.12-rc2 |
617 618 619 |
int netpoll_parse_options(struct netpoll *np, char *opt) { char *cur=opt, *delim; |
c68b90702 [NETPOLL]: Minor ... |
620 |
if (*cur != '@') { |
1da177e4c Linux-2.6.12-rc2 |
621 622 |
if ((delim = strchr(cur, '@')) == NULL) goto parse_failed; |
c68b90702 [NETPOLL]: Minor ... |
623 624 625 |
*delim = 0; np->local_port = simple_strtol(cur, NULL, 10); cur = delim; |
1da177e4c Linux-2.6.12-rc2 |
626 627 |
} cur++; |
1da177e4c Linux-2.6.12-rc2 |
628 |
|
c68b90702 [NETPOLL]: Minor ... |
629 |
if (*cur != '/') { |
1da177e4c Linux-2.6.12-rc2 |
630 631 |
if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; |
c68b90702 [NETPOLL]: Minor ... |
632 |
*delim = 0; |
e7557af56 netpoll: store lo... |
633 |
np->local_ip = in_aton(cur); |
c68b90702 [NETPOLL]: Minor ... |
634 |
cur = delim; |
1da177e4c Linux-2.6.12-rc2 |
635 636 |
} cur++; |
c68b90702 [NETPOLL]: Minor ... |
637 |
if (*cur != ',') { |
1da177e4c Linux-2.6.12-rc2 |
638 639 640 |
/* parse out dev name */ if ((delim = strchr(cur, ',')) == NULL) goto parse_failed; |
c68b90702 [NETPOLL]: Minor ... |
641 |
*delim = 0; |
1da177e4c Linux-2.6.12-rc2 |
642 |
strlcpy(np->dev_name, cur, sizeof(np->dev_name)); |
c68b90702 [NETPOLL]: Minor ... |
643 |
cur = delim; |
1da177e4c Linux-2.6.12-rc2 |
644 645 |
} cur++; |
c68b90702 [NETPOLL]: Minor ... |
646 |
if (*cur != '@') { |
1da177e4c Linux-2.6.12-rc2 |
647 648 649 |
/* dst port */ if ((delim = strchr(cur, '@')) == NULL) goto parse_failed; |
c68b90702 [NETPOLL]: Minor ... |
650 |
*delim = 0; |
5fc05f876 netpoll: warn whe... |
651 652 653 654 |
if (*cur == ' ' || *cur == '\t') printk(KERN_INFO "%s: warning: whitespace" "is not allowed ", np->name); |
c68b90702 [NETPOLL]: Minor ... |
655 656 |
np->remote_port = simple_strtol(cur, NULL, 10); cur = delim; |
1da177e4c Linux-2.6.12-rc2 |
657 658 |
} cur++; |
1da177e4c Linux-2.6.12-rc2 |
659 660 661 662 |
/* dst ip */ if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; |
c68b90702 [NETPOLL]: Minor ... |
663 |
*delim = 0; |
e7557af56 netpoll: store lo... |
664 |
np->remote_ip = in_aton(cur); |
c68b90702 [NETPOLL]: Minor ... |
665 |
cur = delim + 1; |
1da177e4c Linux-2.6.12-rc2 |
666 |
|
c68b90702 [NETPOLL]: Minor ... |
667 |
if (*cur != 0) { |
1da177e4c Linux-2.6.12-rc2 |
668 |
/* MAC address */ |
4940fc889 net: add mac_pton... |
669 |
if (!mac_pton(cur, np->remote_mac)) |
1da177e4c Linux-2.6.12-rc2 |
670 |
goto parse_failed; |
1da177e4c Linux-2.6.12-rc2 |
671 |
} |
0bcc18161 [NET] netconsole:... |
672 |
netpoll_print_options(np); |
1da177e4c Linux-2.6.12-rc2 |
673 674 675 676 |
return 0; parse_failed: |
5fc05f876 netpoll: warn whe... |
677 678 |
printk(KERN_INFO "%s: couldn't parse config at '%s'! ", |
1da177e4c Linux-2.6.12-rc2 |
679 680 681 |
np->name, cur); return -1; } |
9e34a5b51 net/core: EXPORT_... |
682 |
EXPORT_SYMBOL(netpoll_parse_options); |
1da177e4c Linux-2.6.12-rc2 |
683 |
|
8fdd95ec1 netpoll: Allow ne... |
684 |
int __netpoll_setup(struct netpoll *np) |
1da177e4c Linux-2.6.12-rc2 |
685 |
{ |
8fdd95ec1 netpoll: Allow ne... |
686 |
struct net_device *ndev = np->dev; |
115c1d6e6 [NETPOLL]: Introd... |
687 |
struct netpoll_info *npinfo; |
4247e161b netpoll: Add ndo_... |
688 |
const struct net_device_ops *ops; |
fbeec2e15 [NETPOLL]: allow ... |
689 |
unsigned long flags; |
b41848b61 netpoll setup err... |
690 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
691 |
|
8fdd95ec1 netpoll: Allow ne... |
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 |
if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) || !ndev->netdev_ops->ndo_poll_controller) { printk(KERN_ERR "%s: %s doesn't support polling, aborting. ", np->name, np->dev_name); err = -ENOTSUPP; goto out; } if (!ndev->npinfo) { npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); if (!npinfo) { err = -ENOMEM; goto out; } npinfo->rx_flags = 0; INIT_LIST_HEAD(&npinfo->rx_np); spin_lock_init(&npinfo->rx_lock); skb_queue_head_init(&npinfo->arp_tx); skb_queue_head_init(&npinfo->txq); INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); atomic_set(&npinfo->refcnt, 1); ops = np->dev->netdev_ops; if (ops->ndo_netpoll_setup) { err = ops->ndo_netpoll_setup(ndev, npinfo); if (err) goto free_npinfo; } } else { npinfo = ndev->npinfo; atomic_inc(&npinfo->refcnt); } npinfo->netpoll = np; if (np->rx_hook) { spin_lock_irqsave(&npinfo->rx_lock, flags); npinfo->rx_flags |= NETPOLL_RX_ENABLED; list_add_tail(&np->rx, &npinfo->rx_np); spin_unlock_irqrestore(&npinfo->rx_lock, flags); } /* last thing to do is link it to the net device structure */ |
cf778b00e net: reintroduce ... |
739 |
rcu_assign_pointer(ndev->npinfo, npinfo); |
8fdd95ec1 netpoll: Allow ne... |
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 |
return 0; free_npinfo: kfree(npinfo); out: return err; } EXPORT_SYMBOL_GPL(__netpoll_setup); int netpoll_setup(struct netpoll *np) { struct net_device *ndev = NULL; struct in_device *in_dev; int err; |
1da177e4c Linux-2.6.12-rc2 |
755 |
if (np->dev_name) |
881d966b4 [NET]: Make the d... |
756 |
ndev = dev_get_by_name(&init_net, np->dev_name); |
1da177e4c Linux-2.6.12-rc2 |
757 758 759 760 |
if (!ndev) { printk(KERN_ERR "%s: %s doesn't exist, aborting. ", np->name, np->dev_name); |
b41848b61 netpoll setup err... |
761 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
762 |
} |
0c1ad04ae netpoll: prevent ... |
763 764 765 766 |
if (ndev->master) { printk(KERN_ERR "%s: %s is a slave device, aborting. ", np->name, np->dev_name); |
83fe32de6 netpoll: call dev... |
767 768 |
err = -EBUSY; goto put; |
0c1ad04ae netpoll: prevent ... |
769 |
} |
1da177e4c Linux-2.6.12-rc2 |
770 771 772 773 774 775 |
if (!netif_running(ndev)) { unsigned long atmost, atleast; printk(KERN_INFO "%s: device %s not up yet, forcing it ", np->name, np->dev_name); |
6756ae4b4 [NET]: Convert RT... |
776 |
rtnl_lock(); |
b41848b61 netpoll setup err... |
777 778 779 780 |
err = dev_open(ndev); rtnl_unlock(); if (err) { |
1da177e4c Linux-2.6.12-rc2 |
781 782 |
printk(KERN_ERR "%s: failed to open %s ", |
b41848b61 netpoll setup err... |
783 |
np->name, ndev->name); |
dbaa15417 netpoll: Add lock... |
784 |
goto put; |
1da177e4c Linux-2.6.12-rc2 |
785 |
} |
1da177e4c Linux-2.6.12-rc2 |
786 787 |
atleast = jiffies + HZ/10; |
bff38771e netpoll: Introduc... |
788 |
atmost = jiffies + carrier_timeout * HZ; |
1da177e4c Linux-2.6.12-rc2 |
789 790 791 792 793 794 795 796 |
while (!netif_carrier_ok(ndev)) { if (time_after(jiffies, atmost)) { printk(KERN_NOTICE "%s: timeout waiting for carrier ", np->name); break; } |
1b614fb9a netpoll: Fix carr... |
797 |
msleep(1); |
1da177e4c Linux-2.6.12-rc2 |
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 |
} /* If carrier appears to come up instantly, we don't * trust it and pause so that we don't pump all our * queued console messages into the bitbucket. */ if (time_before(jiffies, atleast)) { printk(KERN_NOTICE "%s: carrier detect appears" " untrustworthy, waiting 4 seconds ", np->name); msleep(4000); } } |
1da177e4c Linux-2.6.12-rc2 |
813 814 |
if (!np->local_ip) { rcu_read_lock(); |
e5ed63991 [IPV4]: Replace _... |
815 |
in_dev = __in_dev_get_rcu(ndev); |
1da177e4c Linux-2.6.12-rc2 |
816 817 818 819 820 821 |
if (!in_dev || !in_dev->ifa_list) { rcu_read_unlock(); printk(KERN_ERR "%s: no IP address for %s, aborting ", np->name, np->dev_name); |
b41848b61 netpoll setup err... |
822 |
err = -EDESTADDRREQ; |
dbaa15417 netpoll: Add lock... |
823 |
goto put; |
1da177e4c Linux-2.6.12-rc2 |
824 |
} |
e7557af56 netpoll: store lo... |
825 |
np->local_ip = in_dev->ifa_list->ifa_local; |
1da177e4c Linux-2.6.12-rc2 |
826 |
rcu_read_unlock(); |
e7557af56 netpoll: store lo... |
827 828 |
printk(KERN_INFO "%s: local IP %pI4 ", np->name, &np->local_ip); |
1da177e4c Linux-2.6.12-rc2 |
829 |
} |
dbaa15417 netpoll: Add lock... |
830 831 832 833 834 835 |
np->dev = ndev; /* fill up the skb queue */ refill_skbs(); rtnl_lock(); |
8fdd95ec1 netpoll: Allow ne... |
836 |
err = __netpoll_setup(np); |
dbaa15417 netpoll: Add lock... |
837 |
rtnl_unlock(); |
53fb95d3c [NETPOLL]: fix in... |
838 |
|
8fdd95ec1 netpoll: Allow ne... |
839 840 |
if (err) goto put; |
1da177e4c Linux-2.6.12-rc2 |
841 |
return 0; |
21edbb223 NET: netpoll, fix... |
842 |
put: |
1da177e4c Linux-2.6.12-rc2 |
843 |
dev_put(ndev); |
b41848b61 netpoll setup err... |
844 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
845 |
} |
9e34a5b51 net/core: EXPORT_... |
846 |
EXPORT_SYMBOL(netpoll_setup); |
1da177e4c Linux-2.6.12-rc2 |
847 |
|
c68b90702 [NETPOLL]: Minor ... |
848 849 |
static int __init netpoll_init(void) { |
a1bcfacd0 netpoll: private ... |
850 851 852 853 |
skb_queue_head_init(&skb_pool); return 0; } core_initcall(netpoll_init); |
8fdd95ec1 netpoll: Allow ne... |
854 |
void __netpoll_cleanup(struct netpoll *np) |
1da177e4c Linux-2.6.12-rc2 |
855 |
{ |
fbeec2e15 [NETPOLL]: allow ... |
856 857 |
struct netpoll_info *npinfo; unsigned long flags; |
8fdd95ec1 netpoll: Allow ne... |
858 859 |
npinfo = np->dev->npinfo; if (!npinfo) |
dbaa15417 netpoll: Add lock... |
860 |
return; |
93ec2c723 netpoll info leak |
861 |
|
8fdd95ec1 netpoll: Allow ne... |
862 863 864 865 866 867 868 |
if (!list_empty(&npinfo->rx_np)) { spin_lock_irqsave(&npinfo->rx_lock, flags); list_del(&np->rx); if (list_empty(&npinfo->rx_np)) npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; spin_unlock_irqrestore(&npinfo->rx_lock, flags); } |
de85d99eb netpoll: Fix RCU ... |
869 |
|
8fdd95ec1 netpoll: Allow ne... |
870 871 |
if (atomic_dec_and_test(&npinfo->refcnt)) { const struct net_device_ops *ops; |
de85d99eb netpoll: Fix RCU ... |
872 |
|
8fdd95ec1 netpoll: Allow ne... |
873 874 875 |
ops = np->dev->netdev_ops; if (ops->ndo_netpoll_cleanup) ops->ndo_netpoll_cleanup(np->dev); |
de85d99eb netpoll: Fix RCU ... |
876 |
|
a9b3cd7f3 rcu: convert uses... |
877 |
RCU_INIT_POINTER(np->dev->npinfo, NULL); |
de85d99eb netpoll: Fix RCU ... |
878 |
|
dbaa15417 netpoll: Add lock... |
879 880 |
/* avoid racing with NAPI reading npinfo */ synchronize_rcu_bh(); |
93ec2c723 netpoll info leak |
881 |
|
dbaa15417 netpoll: Add lock... |
882 883 |
skb_queue_purge(&npinfo->arp_tx); skb_queue_purge(&npinfo->txq); |
afe2c511f workqueue: conver... |
884 |
cancel_delayed_work_sync(&npinfo->tx_work); |
93ec2c723 netpoll info leak |
885 |
|
dbaa15417 netpoll: Add lock... |
886 887 888 |
/* clean after last, unfinished work */ __skb_queue_purge(&npinfo->txq); kfree(npinfo); |
115c1d6e6 [NETPOLL]: Introd... |
889 |
} |
8fdd95ec1 netpoll: Allow ne... |
890 891 |
} EXPORT_SYMBOL_GPL(__netpoll_cleanup); |
fbeec2e15 [NETPOLL]: allow ... |
892 |
|
8fdd95ec1 netpoll: Allow ne... |
893 894 895 896 |
void netpoll_cleanup(struct netpoll *np) { if (!np->dev) return; |
dbaa15417 netpoll: Add lock... |
897 |
|
8fdd95ec1 netpoll: Allow ne... |
898 899 900 901 902 |
rtnl_lock(); __netpoll_cleanup(np); rtnl_unlock(); dev_put(np->dev); |
1da177e4c Linux-2.6.12-rc2 |
903 904 |
np->dev = NULL; } |
9e34a5b51 net/core: EXPORT_... |
905 |
EXPORT_SYMBOL(netpoll_cleanup); |
1da177e4c Linux-2.6.12-rc2 |
906 907 908 909 910 |
int netpoll_trap(void) { return atomic_read(&trapped); } |
9e34a5b51 net/core: EXPORT_... |
911 |
EXPORT_SYMBOL(netpoll_trap); |
1da177e4c Linux-2.6.12-rc2 |
912 913 914 915 916 917 918 919 |
void netpoll_set_trap(int trap) { if (trap) atomic_inc(&trapped); else atomic_dec(&trapped); } |
1da177e4c Linux-2.6.12-rc2 |
920 |
EXPORT_SYMBOL(netpoll_set_trap); |