Whamcloud - gitweb
b=4336
[fs/lustre-release.git] / lustre / kernel_patches / patches / netpoll-core.patch
1  l-mpm/arch/i386/kernel/irq.c    |   15 
2  l-mpm/include/asm-i386/irq.h         |    1 
3  l-mpm/include/linux/netdevice.h |   22 -
4  l-mpm/include/linux/netpoll.h   |   37 ++
5  l-mpm/net/Kconfig               |    3 
6  l-mpm/net/core/Makefile         |    1 
7  l-mpm/net/core/dev.c            |   22 -
8  l-mpm/net/core/netpoll.c        |  632 ++++++++++++++++++++++++++++++++++++++++
9  8 files changed, 707 insertions(+), 26 deletions(-)
10
11 Index: linux-2.6.0-test6/net/core/netpoll.c
12 ===================================================================
13 --- linux-2.6.0-test6.orig/net/core/netpoll.c   2003-10-07 16:08:51.000000000 +0800
14 +++ linux-2.6.0-test6/net/core/netpoll.c        2003-10-09 20:40:07.769057232 +0800
15 @@ -0,0 +1,633 @@
16 +/*
17 + * Common framework for low-level network console, dump, and debugger code
18 + *
19 + * Sep 8 2003  Matt Mackall <mpm@selenic.com>
20 + */
21 +
22 +#include <linux/smp_lock.h>
23 +#include <linux/netdevice.h>
24 +#include <linux/etherdevice.h>
25 +#include <linux/string.h>
26 +#include <linux/inetdevice.h>
27 +#include <linux/inet.h>
28 +#include <linux/interrupt.h>
29 +#include <linux/netpoll.h>
30 +#include <linux/sched.h>
31 +#include <net/tcp.h>
32 +#include <net/udp.h>
33 +
34 +/*
35 + * We maintain a small pool of fully-sized skbs, to make sure the
36 + * message gets out even in extreme OOM situations.
37 + */
38 +
39 +#define MAX_SKBS 32
40 +#define MAX_UDP_CHUNK 1460
41 +
42 +static spinlock_t skb_list_lock = SPIN_LOCK_UNLOCKED;
43 +static int nr_skbs;
44 +static struct sk_buff *skbs;
45 +
46 +static spinlock_t rx_list_lock = SPIN_LOCK_UNLOCKED;
47 +static LIST_HEAD(rx_list);
48 +
49 +static int trapped;
50 +
51 +#define MAX_SKB_SIZE \
52 +               (MAX_UDP_CHUNK + sizeof(struct udphdr) + \
53 +                               sizeof(struct iphdr) + sizeof(struct ethhdr))
54 +
55 +static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
56 +                            unsigned short ulen, u32 saddr, u32 daddr)
57 +{
58 +       if (uh->check == 0)
59 +               return 0;
60 +
61 +       if (skb->ip_summed == CHECKSUM_HW)
62 +               return csum_tcpudp_magic(
63 +                       saddr, daddr, ulen, IPPROTO_UDP, skb->csum);
64 +
65 +       skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
66 +
67 +       return csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
68 +}
69 +
70 +void netpoll_poll(struct netpoll *np)
71 +{
72 +       int budget = 1;
73 +
74 +       if(!np || !np->dev || !(np->dev->flags & IFF_UP))
75 +               return;
76 +
77 +       disable_irq(np->dev->irq);
78 +
79 +       /* Process pending work on NIC */
80 +       np->irqfunc(np->dev->irq, np->dev, 0);
81 +
82 +       /* If scheduling is stopped, tickle NAPI bits */
83 +       if(trapped && np->dev->poll &&
84 +          test_bit(__LINK_STATE_RX_SCHED, &np->dev->state))
85 +               np->dev->poll(np->dev, &budget);
86 +
87 +       enable_irq(np->dev->irq);
88 +}
89 +
90 +static void refill_skbs(void)
91 +{
92 +       struct sk_buff *skb;
93 +       unsigned long flags;
94 +
95 +       spin_lock_irqsave(&skb_list_lock, flags);
96 +       while (nr_skbs < MAX_SKBS) {
97 +               skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
98 +               if (!skb)
99 +                       break;
100 +
101 +               skb->next = skbs;
102 +               skbs = skb;
103 +               nr_skbs++;
104 +       }
105 +       spin_unlock_irqrestore(&skb_list_lock, flags);
106 +}
107 +
108 +static void zap_completion_queue(void)
109 +{
110 +       unsigned long flags;
111 +       struct softnet_data *sd = &get_cpu_var(softnet_data);
112 +
113 +       if (sd->completion_queue) {
114 +               struct sk_buff *clist;
115 +
116 +               local_irq_save(flags);
117 +               clist = sd->completion_queue;
118 +               sd->completion_queue = NULL;
119 +               local_irq_restore(flags);
120 +
121 +               while (clist != NULL) {
122 +                       struct sk_buff *skb = clist;
123 +                       clist = clist->next;
124 +                       __kfree_skb(skb);
125 +               }
126 +       }
127 +
128 +       put_cpu_var(softnet_data);
129 +}
130 +
131 +static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve)
132 +{
133 +       int once = 1, count = 0;
134 +       unsigned long flags;
135 +       struct sk_buff *skb = NULL;
136 +
137 +repeat:
138 +       zap_completion_queue();
139 +       if (nr_skbs < MAX_SKBS)
140 +               refill_skbs();
141 +
142 +       skb = alloc_skb(len, GFP_ATOMIC);
143 +
144 +       if (!skb) {
145 +               spin_lock_irqsave(&skb_list_lock, flags);
146 +               skb = skbs;
147 +               if (skb)
148 +                       skbs = skb->next;
149 +               skb->next = NULL;
150 +               nr_skbs--;
151 +               spin_unlock_irqrestore(&skb_list_lock, flags);
152 +       }
153 +
154 +       if(!skb) {
155 +               count++;
156 +               if (once && (count == 1000000)) {
157 +                       printk("out of netpoll skbs!\n");
158 +                       once = 0;
159 +               }
160 +               netpoll_poll(np);
161 +               goto repeat;
162 +       }
163 +
164 +       atomic_set(&skb->users, 1);
165 +       skb_reserve(skb, reserve);
166 +       return skb;
167 +}
168 +
169 +void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
170 +{
171 +       int status;
172 +
173 +repeat:
174 +       if(!np || !np->dev || !(np->dev->flags & IFF_UP)) {
175 +               __kfree_skb(skb);
176 +               return;
177 +       }
178 +
179 +       spin_lock(&np->dev->xmit_lock);
180 +       np->dev->xmit_lock_owner = smp_processor_id();
181 +
182 +       if (netif_queue_stopped(np->dev)) {
183 +               np->dev->xmit_lock_owner = -1;
184 +               spin_unlock(&np->dev->xmit_lock);
185 +
186 +               netpoll_poll(np);
187 +               zap_completion_queue();
188 +               goto repeat;
189 +       }
190 +
191 +       status = np->dev->hard_start_xmit(skb, np->dev);
192 +       np->dev->xmit_lock_owner = -1;
193 +       spin_unlock(&np->dev->xmit_lock);
194 +
195 +       /* transmit busy */
196 +       if(status)
197 +               goto repeat;
198 +}
199 +
200 +void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
201 +{
202 +       int total_len, eth_len, ip_len, udp_len;
203 +       struct sk_buff *skb;
204 +       struct udphdr *udph;
205 +       struct iphdr *iph;
206 +       struct ethhdr *eth;
207 +
208 +       udp_len = len + sizeof(*udph);
209 +       ip_len = eth_len = udp_len + sizeof(*iph);
210 +       total_len = eth_len + ETH_HLEN;
211 +
212 +       skb = find_skb(np, total_len, total_len - len);
213 +       if (!skb)
214 +               return;
215 +
216 +       memcpy(skb->data, msg, len);
217 +       skb->len += len;
218 +
219 +       udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
220 +       udph->source = htons(np->local_port);
221 +       udph->dest = htons(np->remote_port);
222 +       udph->len = htons(udp_len);
223 +       udph->check = 0;
224 +
225 +       iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
226 +
227 +       iph->version  = 4;
228 +       iph->ihl      = 5;
229 +       iph->tos      = 0;
230 +       iph->tot_len  = htons(ip_len);
231 +       iph->id       = 0;
232 +       iph->frag_off = 0;
233 +       iph->ttl      = 64;
234 +       iph->protocol = IPPROTO_UDP;
235 +       iph->check    = 0;
236 +       iph->saddr    = htonl(np->local_ip);
237 +       iph->daddr    = htonl(np->remote_ip);
238 +       iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
239 +
240 +       eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
241 +
242 +       eth->h_proto = htons(ETH_P_IP);
243 +       memcpy(eth->h_source, np->local_mac, 6);
244 +       memcpy(eth->h_dest, np->remote_mac, 6);
245 +
246 +       netpoll_send_skb(np, skb);
247 +}
248 +
249 +static void arp_reply(struct sk_buff *skb)
250 +{
251 +       struct in_device *in_dev = (struct in_device *) skb->dev->ip_ptr;
252 +       struct arphdr *arp;
253 +       unsigned char *arp_ptr, *sha, *tha;
254 +       int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
255 +       u32 sip, tip;
256 +       struct sk_buff *send_skb;
257 +       unsigned long flags;
258 +       struct list_head *p;
259 +       struct netpoll *np = 0;
260 +
261 +       spin_lock_irqsave(&rx_list_lock, flags);
262 +       list_for_each(p, &rx_list) {
263 +               np = list_entry(p, struct netpoll, rx_list);
264 +               if ( np->dev == skb->dev )
265 +                       break;
266 +               np = 0;
267 +       }
268 +       spin_unlock_irqrestore(&rx_list_lock, flags);
269 +
270 +       if (!np) return;
271 +
272 +       /* No arp on this interface */
273 +       if (!in_dev || skb->dev->flags & IFF_NOARP)
274 +               return;
275 +
276 +       if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
277 +                                (2 * skb->dev->addr_len) +
278 +                                (2 * sizeof(u32)))))
279 +               return;
280 +
281 +       skb->h.raw = skb->nh.raw = skb->data;
282 +       arp = skb->nh.arph;
283 +
284 +       if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
285 +            arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
286 +           arp->ar_pro != htons(ETH_P_IP) ||
287 +           arp->ar_op != htons(ARPOP_REQUEST))
288 +               return;
289 +
290 +       arp_ptr= (unsigned char *)(arp+1);
291 +       sha = arp_ptr;
292 +       arp_ptr += skb->dev->addr_len;
293 +       memcpy(&sip, arp_ptr, 4);
294 +       arp_ptr += 4;
295 +       tha = arp_ptr;
296 +       arp_ptr += skb->dev->addr_len;
297 +       memcpy(&tip, arp_ptr, 4);
298 +
299 +       /* Should we ignore arp? */
300 +       if (tip != in_dev->ifa_list->ifa_address ||
301 +           LOOPBACK(tip) || MULTICAST(tip))
302 +               return;
303 +
304 +
305 +       size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
306 +       send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
307 +                           LL_RESERVED_SPACE(np->dev));
308 +
309 +       if (!send_skb)
310 +               return;
311 +
312 +       send_skb->nh.raw = send_skb->data;
313 +       arp = (struct arphdr *) skb_put(send_skb, size);
314 +       send_skb->dev = skb->dev;
315 +       send_skb->protocol = htons(ETH_P_ARP);
316 +
317 +       /* Fill the device header for the ARP frame */
318 +
319 +       if (np->dev->hard_header &&
320 +           np->dev->hard_header(send_skb, skb->dev, ptype,
321 +                                      np->remote_mac, np->local_mac,
322 +                                      send_skb->len) < 0) {
323 +               kfree_skb(send_skb);
324 +               return;
325 +       }
326 +
327 +       /*
328 +        * Fill out the arp protocol part.
329 +        *
330 +        * we only support ethernet device type,
331 +        * which (according to RFC 1390) should always equal 1 (Ethernet).
332 +        */
333 +
334 +       arp->ar_hrd = htons(np->dev->type);
335 +       arp->ar_pro = htons(ETH_P_IP);
336 +       arp->ar_hln = np->dev->addr_len;
337 +       arp->ar_pln = 4;
338 +       arp->ar_op = htons(type);
339 +
340 +       arp_ptr=(unsigned char *)(arp + 1);
341 +       memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len);
342 +       arp_ptr += np->dev->addr_len;
343 +       memcpy(arp_ptr, &tip, 4);
344 +       arp_ptr += 4;
345 +       memcpy(arp_ptr, np->local_mac, np->dev->addr_len);
346 +       arp_ptr += np->dev->addr_len;
347 +       memcpy(arp_ptr, &sip, 4);
348 +
349 +       netpoll_send_skb(np, send_skb);
350 +}
351 +
352 +static int rx_hook(struct sk_buff *skb)
353 +{
354 +       int proto, len, ulen;
355 +       struct iphdr *iph;
356 +       struct udphdr *uh;
357 +       struct netpoll *np;
358 +       struct list_head *p;
359 +       unsigned long flags;
360 +       int rx_hook_called = 0;
361 +
362 +       if (skb->dev->type != ARPHRD_ETHER)
363 +               goto out;
364 +
365 +       /* check if netpoll clients need ARP */
366 +       if (skb->protocol == __constant_htons(ETH_P_ARP) && trapped) {
367 +               arp_reply(skb);
368 +               return 1;
369 +       }
370 +
371 +       proto = ntohs(skb->mac.ethernet->h_proto);
372 +       if (proto != ETH_P_IP)
373 +               goto out;
374 +       if (skb->pkt_type == PACKET_OTHERHOST)
375 +               goto out;
376 +       if (skb_shared(skb))
377 +               goto out;
378 +
379 +       iph = (struct iphdr *)skb->data;
380 +       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
381 +               goto out;
382 +       if (iph->ihl < 5 || iph->version != 4)
383 +               goto out;
384 +       if (!pskb_may_pull(skb, iph->ihl*4))
385 +               goto out;
386 +       if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
387 +               goto out;
388 +
389 +       len = ntohs(iph->tot_len);
390 +       if (skb->len < len || len < iph->ihl*4)
391 +               goto out;
392 +
393 +       if (iph->protocol != IPPROTO_UDP)
394 +               goto out;
395 +
396 +       len -= iph->ihl*4;
397 +       uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
398 +       ulen = ntohs(uh->len);
399 +
400 +       if (ulen != len)
401 +               goto out;
402 +       if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr) < 0)
403 +               goto out;
404 +
405 +       spin_lock_irqsave(&rx_list_lock, flags);
406 +       list_for_each(p, &rx_list) {
407 +               np = list_entry(p, struct netpoll, rx_list);
408 +               if (np->dev && np->dev != skb->dev)
409 +                       continue;
410 +               if (np->local_ip && np->local_ip != ntohl(iph->daddr))
411 +                       continue;
412 +               if (np->remote_ip && np->remote_ip != ntohl(iph->saddr))
413 +                       continue;
414 +               if (np->local_port && np->local_port != ntohs(uh->dest))
415 +                       continue;
416 +
417 +               if (np->rx_hook){
418 +                       np->rx_hook(np, ntohs(uh->source),
419 +                                   (char *)(uh+1), ulen-sizeof(uh)-4);
420 +                       rx_hook_called = 1;
421 +               }
422 +       }
423 +       spin_unlock_irqrestore(&rx_list_lock, flags);
424 +       
425 +       if (rx_hook_called)
426 +               return 1;
427 +out:
428 +       return trapped;
429 +}
430 +
431 +int netpoll_parse_options(struct netpoll *np, char *opt)
432 +{
433 +       char *cur=opt, *delim;
434 +
435 +       if(*cur != '@') {
436 +               if ((delim = strchr(cur, '@')) == NULL)
437 +                       goto parse_failed;
438 +               *delim=0;
439 +               np->local_port=simple_strtol(cur, 0, 10);
440 +               cur=delim;
441 +       }
442 +       cur++;
443 +       printk(KERN_INFO "%s: local port %d\n", np->name, np->local_port);
444 +
445 +       if(*cur != '/') {
446 +               if ((delim = strchr(cur, '/')) == NULL)
447 +                       goto parse_failed;
448 +               *delim=0;
449 +               np->local_ip=ntohl(in_aton(cur));
450 +               cur=delim;
451 +
452 +               printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
453 +                      np->name, HIPQUAD(np->local_ip));
454 +       }
455 +       cur++;
456 +
457 +       if ( *cur != ',') {
458 +               /* parse out dev name */
459 +               if ((delim = strchr(cur, ',')) == NULL)
460 +                       goto parse_failed;
461 +               *delim=0;
462 +               strlcpy(np->dev_name, cur, sizeof(np->dev_name));
463 +               cur=delim;
464 +       }
465 +       cur++;
466 +
467 +       printk(KERN_INFO "%s: interface %s\n", np->name, np->dev_name);
468 +
469 +       if ( *cur != '@' ) {
470 +               /* dst port */
471 +               if ((delim = strchr(cur, '@')) == NULL)
472 +                       goto parse_failed;
473 +               *delim=0;
474 +               np->remote_port=simple_strtol(cur, 0, 10);
475 +               cur=delim;
476 +       }
477 +       cur++;
478 +       printk(KERN_INFO "%s: remote port %d\n", np->name, np->remote_port);
479 +
480 +       /* dst ip */
481 +       if ((delim = strchr(cur, '/')) == NULL)
482 +               goto parse_failed;
483 +       *delim=0;
484 +       np->remote_ip=ntohl(in_aton(cur));
485 +       cur=delim+1;
486 +
487 +       printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n",
488 +                      np->name, HIPQUAD(np->remote_ip));
489 +
490 +       if( *cur != 0 )
491 +       {
492 +               /* MAC address */
493 +               if ((delim = strchr(cur, ':')) == NULL)
494 +                       goto parse_failed;
495 +               *delim=0;
496 +               np->remote_mac[0]=simple_strtol(cur, 0, 16);
497 +               cur=delim+1;
498 +               if ((delim = strchr(cur, ':')) == NULL)
499 +                       goto parse_failed;
500 +               *delim=0;
501 +               np->remote_mac[1]=simple_strtol(cur, 0, 16);
502 +               cur=delim+1;
503 +               if ((delim = strchr(cur, ':')) == NULL)
504 +                       goto parse_failed;
505 +               *delim=0;
506 +               np->remote_mac[2]=simple_strtol(cur, 0, 16);
507 +               cur=delim+1;
508 +               if ((delim = strchr(cur, ':')) == NULL)
509 +                       goto parse_failed;
510 +               *delim=0;
511 +               np->remote_mac[3]=simple_strtol(cur, 0, 16);
512 +               cur=delim+1;
513 +               if ((delim = strchr(cur, ':')) == NULL)
514 +                       goto parse_failed;
515 +               *delim=0;
516 +               np->remote_mac[4]=simple_strtol(cur, 0, 16);
517 +               cur=delim+1;
518 +               np->remote_mac[5]=simple_strtol(cur, 0, 16);
519 +       }
520 +
521 +       printk(KERN_INFO "%s: remote ethernet address "
522 +              "%02x:%02x:%02x:%02x:%02x:%02x\n",
523 +              np->name,
524 +              np->remote_mac[0],
525 +              np->remote_mac[1],
526 +              np->remote_mac[2],
527 +              np->remote_mac[3],
528 +              np->remote_mac[4],
529 +              np->remote_mac[5]);
530 +
531 +       return 0;
532 +
533 + parse_failed:
534 +       printk(KERN_INFO "%s: couldn't parse config at %s!\n",
535 +              np->name, cur);
536 +       return -1;
537 +}
538 +
539 +int netpoll_setup(struct netpoll *np)
540 +{
541 +       struct net_device *ndev = NULL;
542 +       struct in_device *in_dev;
543 +       struct irqaction *a;
544 +
545 +       if (np->dev_name)
546 +               ndev = dev_get_by_name(np->dev_name);
547 +       if (!ndev) {
548 +               printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
549 +                      np->name, np->dev_name);
550 +               return -1;
551 +       }
552 +
553 +       if (!(ndev->flags & IFF_UP)) {
554 +               unsigned short oflags;
555 +               unsigned long jiff;
556 +
557 +               printk(KERN_INFO "%s: device %s not up yet, forcing it\n",
558 +                      np->name, np->dev_name);
559 +
560 +               oflags = ndev->flags;
561 +
562 +               rtnl_shlock();
563 +               if (dev_change_flags(ndev, oflags | IFF_UP) < 0) {
564 +                       printk(KERN_ERR "%s: failed to open %s\n",
565 +                              np->name, np->dev_name);
566 +                       rtnl_shunlock();
567 +                       return -1;
568 +               }
569 +               rtnl_shunlock();
570 +
571 +               jiff = jiffies + 6*HZ;
572 +               while(!netif_carrier_ok(ndev)) {
573 +                       if (!time_before(jiffies, jiff)) {
574 +                               printk(KERN_NOTICE
575 +                                      "%s: timeout waiting for carrier\n",
576 +                                      np->name);
577 +                               break;
578 +                       }
579 +                       cond_resched();
580 +               }
581 +
582 +       }
583 +
584 +       if (!memcmp(np->local_mac, "\0\0\0\0\0\0", 6) && ndev->dev_addr)
585 +               memcpy(np->local_mac, ndev->dev_addr, 6);
586 +
587 +       if (!np->local_ip)
588 +       {
589 +               in_dev = in_dev_get(ndev);
590 +
591 +               if (!in_dev) {
592 +                       printk(KERN_ERR "%s: no IP address for %s, aborting\n",
593 +                              np->name, np->dev_name);
594 +                       return -1;
595 +               }
596 +
597 +               np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
598 +               in_dev_put(in_dev);
599 +               printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
600 +                      np->name, HIPQUAD(np->local_ip));
601 +       }
602 +
603 +       a=find_irq_action(ndev->irq, ndev);
604 +       if (!a) {
605 +               printk(KERN_ERR "%s: couldn't find irq handler for %s, "
606 +                      "aborting\n", np->name, np->dev_name);
607 +               return -1;
608 +       }
609 +
610 +       np->irqfunc = a->handler;
611 +       np->dev = ndev;
612 +
613 +       if(np->rx_hook) {
614 +               unsigned long flags;
615 +
616 +               np->dev->rx_hook = rx_hook;
617 +
618 +               spin_lock_irqsave(&rx_list_lock, flags);
619 +               list_add(&np->rx_list, &rx_list);
620 +               spin_unlock_irqrestore(&rx_list_lock, flags);
621 +       }
622 +
623 +       return 0;
624 +}
625 +
626 +void netpoll_cleanup(struct netpoll *np)
627 +{
628 +       if(np->rx_hook) {
629 +               unsigned long flags;
630 +
631 +               spin_lock_irqsave(&rx_list_lock, flags);
632 +               list_del(&np->rx_list);
633 +               np->dev->rx_hook = 0;
634 +               spin_unlock_irqrestore(&rx_list_lock, flags);
635 +       }
636 +
637 +       np->dev = 0;
638 +}
639 +
640 +int netpoll_trap()
641 +{
642 +       return trapped;
643 +}
644 +
645 +void netpoll_set_trap(int trap)
646 +{
647 +       trapped = trap;
648 +}
649 Index: linux-2.6.0-test6/include/linux/netpoll.h
650 ===================================================================
651 --- linux-2.6.0-test6.orig/include/linux/netpoll.h      2003-10-07 16:08:51.000000000 +0800
652 +++ linux-2.6.0-test6/include/linux/netpoll.h   2003-10-07 16:08:51.000000000 +0800
653 @@ -0,0 +1,37 @@
654 +/*
655 + * Common code for low-level network console, dump, and debugger code
656 + *
657 + * Derived from netconsole, kgdb-over-ethernet, and netdump patches
658 + */
659 +
660 +#ifndef _LINUX_NETPOLL_H
661 +#define _LINUX_NETPOLL_H
662 +
663 +#include <linux/netdevice.h>
664 +#include <linux/irq.h>
665 +#include <linux/list.h>
666 +
667 +struct netpoll;
668 +
669 +struct netpoll {
670 +       struct net_device *dev;
671 +       char dev_name[16], *name;
672 +       irqreturn_t (*irqfunc)(int, void *, struct pt_regs *);
673 +       void (*rx_hook)(struct netpoll *, int, char *, int);
674 +       u32 local_ip, remote_ip;
675 +       u16 local_port, remote_port;
676 +       unsigned char local_mac[6], remote_mac[6];
677 +       struct list_head rx_list;
678 +};
679 +
680 +void netpoll_poll(struct netpoll *np);
681 +void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
682 +void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
683 +int netpoll_parse_options(struct netpoll *np, char *opt);
684 +int netpoll_setup(struct netpoll *np);
685 +int netpoll_trap(void);
686 +void netpoll_set_trap(int trap);
687 +void netpoll_cleanup(struct netpoll *np);
688 +
689 +
690 +#endif
691 Index: linux-2.6.0-test6/net/core/Makefile
692 ===================================================================
693 --- linux-2.6.0-test6.orig/net/core/Makefile    2003-09-28 08:51:03.000000000 +0800
694 +++ linux-2.6.0-test6/net/core/Makefile 2003-10-07 16:08:51.000000000 +0800
695 @@ -13,3 +13,4 @@
696  obj-$(CONFIG_NET_DIVERT) += dv.o
697  obj-$(CONFIG_NET_PKTGEN) += pktgen.o
698  obj-$(CONFIG_NET_RADIO) += wireless.o
699 +obj-$(CONFIG_NETPOLL) += netpoll.o
700 Index: linux-2.6.0-test6/net/Kconfig
701 ===================================================================
702 --- linux-2.6.0-test6.orig/net/Kconfig  2003-09-28 08:50:07.000000000 +0800
703 +++ linux-2.6.0-test6/net/Kconfig       2003-10-09 20:36:23.429162080 +0800
704 @@ -670,4 +670,7 @@
705  
706  source "net/bluetooth/Kconfig"
707  
708 +config NETPOLL
709 +       def_bool KGDB
710 +
711  endmenu
712 Index: linux-2.6.0-test6/include/linux/netdevice.h
713 ===================================================================
714 --- linux-2.6.0-test6.orig/include/linux/netdevice.h    2003-10-07 16:08:42.000000000 +0800
715 +++ linux-2.6.0-test6/include/linux/netdevice.h 2003-10-07 16:08:51.000000000 +0800
716 @@ -452,13 +452,13 @@
717                                                      unsigned char *haddr);
718         int                     (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
719         int                     (*accept_fastpath)(struct net_device *, struct dst_entry*);
720 +#ifdef CONFIG_NETPOLL
721 +       int                     (*rx_hook)(struct sk_buff *skb);
722 +#endif
723  
724         /* bridge stuff */
725         struct net_bridge_port  *br_port;
726  
727 -#ifdef CONFIG_KGDB
728 -       int                     kgdb_is_trapped;
729 -#endif
730  #ifdef CONFIG_NET_POLL_CONTROLLER
731         void                    (*poll_controller)(struct net_device *);
732  #endif
733 @@ -537,10 +537,8 @@
734  extern struct net_device       *dev_get_by_index(int ifindex);
735  extern struct net_device       *__dev_get_by_index(int ifindex);
736  extern int             dev_restart(struct net_device *dev);
737 -#ifdef CONFIG_KGDB
738 -extern int             kgdb_eth_is_trapped(void);
739 -extern int             kgdb_net_interrupt(struct sk_buff *skb);
740 -extern void            kgdb_send_arp_request(void);
741 +#ifdef CONFIG_NETPOLL
742 +extern int             netpoll_trap(void);
743  #endif
744  
745  typedef int gifconf_func_t(struct net_device * dev, char * bufptr, int len);
746 @@ -600,10 +598,9 @@
747  
748  static inline void netif_wake_queue(struct net_device *dev)
749  {
750 -#ifdef CONFIG_KGDB
751 -       if (kgdb_eth_is_trapped()) {
752 +#ifdef CONFIG_NETPOLL
753 +       if (netpoll_trap())
754                 return;
755 -       }
756  #endif
757         if (test_and_clear_bit(__LINK_STATE_XOFF, &dev->state))
758                 __netif_schedule(dev);
759 @@ -611,10 +608,9 @@
760  
761  static inline void netif_stop_queue(struct net_device *dev)
762  {
763 -#ifdef CONFIG_KGDB
764 -       if (kgdb_eth_is_trapped()) {
765 +#ifdef CONFIG_NETPOLL
766 +       if (netpoll_trap())
767                 return;
768 -       }
769  #endif
770         set_bit(__LINK_STATE_XOFF, &dev->state);
771  }
772 Index: linux-2.6.0-test6/net/core/dev.c
773 ===================================================================
774 --- linux-2.6.0-test6.orig/net/core/dev.c       2003-10-07 16:08:42.000000000 +0800
775 +++ linux-2.6.0-test6/net/core/dev.c    2003-10-09 20:36:23.436161016 +0800
776 @@ -1352,16 +1352,8 @@
777         struct softnet_data *queue;
778         unsigned long flags;
779  
780 -#ifdef CONFIG_KGDB
781 -       /* See if kgdb_eth wants this packet */
782 -       if (!kgdb_net_interrupt(skb)) {
783 -               /* No.. if we're 'trapped' then junk it */
784 -               if (kgdb_eth_is_trapped()) {
785 -                       kfree_skb(skb);
786 -                       return NET_RX_DROP;
787 -               }
788 -       } else {
789 -               /* kgdb_eth ate the packet... drop it silently */
790 +#ifdef CONFIG_NETPOLL
791 +       if (skb->dev->rx_hook && skb->dev->rx_hook(skb)) {
792                 kfree_skb(skb);
793                 return NET_RX_DROP;
794         }
795 @@ -1556,6 +1548,13 @@
796         int ret = NET_RX_DROP;
797         unsigned short type = skb->protocol;
798  
799 +#ifdef CONFIG_NETPOLL
800 +       if (skb->dev->rx_hook && skb->dev->rx_hook(skb)) {
801 +               kfree_skb(skb);
802 +               return NET_RX_DROP;
803 +       }
804 +#endif
805 +
806         if (!skb->stamp.tv_sec)
807                 do_gettimeofday(&skb->stamp);
808  
809 Index: linux-2.6.0-test6/include/asm-i386/irq.h
810 ===================================================================
811 --- linux-2.6.0-test6.orig/include/asm-i386/irq.h       2003-09-28 08:50:36.000000000 +0800
812 +++ linux-2.6.0-test6/include/asm-i386/irq.h    2003-10-07 16:08:51.000000000 +0800
813 @@ -24,6 +24,7 @@
814  extern void disable_irq_nosync(unsigned int);
815  extern void enable_irq(unsigned int);
816  extern void release_x86_irqs(struct task_struct *);
817 +struct irqaction *find_irq_action(unsigned int irq, void *dev_id);
818  
819  #ifdef CONFIG_X86_LOCAL_APIC
820  #define ARCH_HAS_NMI_WATCHDOG          /* See include/linux/nmi.h */
821 Index: linux-2.6.0-test6/arch/i386/kernel/irq.c
822 ===================================================================
823 --- linux-2.6.0-test6.orig/arch/i386/kernel/irq.c       2003-10-07 16:08:34.000000000 +0800
824 +++ linux-2.6.0-test6/arch/i386/kernel/irq.c    2003-10-09 20:36:23.433161472 +0800
825 @@ -396,7 +396,6 @@
826         }
827         spin_unlock_irqrestore(&desc->lock, flags);
828  }
829 -
830  /*
831   * do_IRQ handles all normal device IRQ's (the special
832   * SMP cross-CPU interrupts have their own specific
833 @@ -896,6 +895,21 @@
834         return 0;
835  }
836  
837 +struct irqaction *find_irq_action(unsigned int irq, void *dev_id)
838 +{
839 +       struct irqaction *a, *r=0;
840 +
841 +       spin_lock_irq(&irq_desc[irq].lock);
842 +       for(a=irq_desc[irq].action; a; a=a->next) {
843 +               if(a->dev_id == dev_id) {
844 +                       r=a;
845 +                       break;
846 +               }
847 +       }
848 +       spin_unlock_irq(&irq_desc[irq].lock);
849 +       return r;
850 +}
851 +
852  static struct proc_dir_entry * root_irq_dir;
853  static struct proc_dir_entry * irq_dir [NR_IRQS];
854