1 Index: linux-2.6.0-test6/drivers/dump/dump_netdev.c
2 ===================================================================
3 --- linux-2.6.0-test6.orig/drivers/dump/dump_netdev.c 2003-10-07 16:08:57.000000000 +0800
4 +++ linux-2.6.0-test6/drivers/dump/dump_netdev.c 2003-10-09 17:36:18.000000000 +0800
7 * Copyright (C) 2001 Ingo Molnar <mingo@redhat.com>
8 * Copyright (C) 2002 International Business Machines Corp.
9 + * Rewrited with netpoll by wangdi <wangdi@clusterfs.com>
11 * This code is released under version 2 of the GNU GPL.
14 #include <linux/module.h>
15 #include <linux/dump.h>
16 #include <linux/dump_netdev.h>
17 +#include <linux/netpoll.h>
19 #include <asm/unaligned.h>
21 static int startup_handshake;
22 static int page_counter;
23 -static struct net_device *dump_ndev;
24 static struct in_device *dump_in_dev;
25 -static u16 source_port, target_port;
26 -static u32 source_ip, target_ip;
27 -static unsigned char daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
28 -static spinlock_t dump_skb_lock = SPIN_LOCK_UNLOCKED;
29 -static int dump_nr_skbs;
30 -static struct sk_buff *dump_skb;
31 static unsigned long flags_global;
32 static int netdump_in_progress;
33 static char device_name[IFNAMSIZ];
38 - * security depends on the trusted path between the netconsole
39 - * server and netconsole client, since none of the packets are
40 - * encrypted. The random magic number protects the protocol
43 static u64 dump_magic;
45 #define MAX_UDP_CHUNK 1460
47 #define MAX_SKB_SIZE \
48 (MAX_UDP_CHUNK + sizeof(struct udphdr) + \
49 sizeof(struct iphdr) + sizeof(struct ethhdr))
50 +static char send_buffer[MAX_UDP_CHUNK];
53 -dump_refill_skbs(void)
55 - struct sk_buff *skb;
56 - unsigned long flags;
58 - spin_lock_irqsave(&dump_skb_lock, flags);
59 - while (dump_nr_skbs < DUMP_MAX_SKBS) {
60 - skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
64 - skb->next = dump_skb;
70 - spin_unlock_irqrestore(&dump_skb_lock, flags);
74 -sk_buff * dump_get_skb(void)
76 - struct sk_buff *skb;
77 - unsigned long flags;
79 - spin_lock_irqsave(&dump_skb_lock, flags);
82 - dump_skb = skb->next;
86 - spin_unlock_irqrestore(&dump_skb_lock, flags);
92 - * Zap completed output skbs.
95 -zap_completion_queue(void)
98 - unsigned long flags;
99 - int cpu = smp_processor_id();
100 - struct softnet_data *softnet_data;
103 - softnet_data = &__get_cpu_var(softnet_data);
105 - if (softnet_data[cpu].completion_queue) {
106 - struct sk_buff *clist;
108 - local_irq_save(flags);
109 - clist = softnet_data[cpu].completion_queue;
110 - softnet_data[cpu].completion_queue = NULL;
111 - local_irq_restore(flags);
113 - while (clist != NULL) {
114 - struct sk_buff *skb = clist;
115 - clist = clist->next;
119 - printk("Error in sk list\n");
125 -dump_send_skb(struct net_device *dev, const char *msg, unsigned int msg_len,
129 - int total_len, eth_len, ip_len, udp_len, count = 0;
130 - struct sk_buff *skb;
131 - struct udphdr *udph;
133 - struct ethhdr *eth;
135 - udp_len = msg_len + HEADER_LEN + sizeof(*udph);
136 - ip_len = eth_len = udp_len + sizeof(*iph);
137 - total_len = eth_len + ETH_HLEN;
140 - zap_completion_queue();
141 - if (dump_nr_skbs < DUMP_MAX_SKBS)
142 - dump_refill_skbs();
144 - skb = alloc_skb(total_len, GFP_ATOMIC);
146 - skb = dump_get_skb();
149 - if (once && (count == 1000000)) {
150 - printk("possibly FATAL: out of netconsole "
151 - "skbs!!! will keep retrying.\n");
154 - dev->poll_controller(dev);
159 - atomic_set(&skb->users, 1);
160 - skb_reserve(skb, total_len - msg_len - HEADER_LEN);
161 - skb->data[0] = NETCONSOLE_VERSION;
163 - put_unaligned(htonl(reply->nr), (u32 *) (skb->data + 1));
164 - put_unaligned(htonl(reply->code), (u32 *) (skb->data + 5));
165 - put_unaligned(htonl(reply->info), (u32 *) (skb->data + 9));
167 - memcpy(skb->data + HEADER_LEN, msg, msg_len);
168 - skb->len += msg_len + HEADER_LEN;
170 - udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
171 - udph->source = source_port;
172 - udph->dest = target_port;
173 - udph->len = htons(udp_len);
176 - iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
181 - iph->tot_len = htons(ip_len);
185 - iph->protocol = IPPROTO_UDP;
187 - iph->saddr = source_ip;
188 - iph->daddr = target_ip;
189 - iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
191 - eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
193 - eth->h_proto = htons(ETH_P_IP);
194 - memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
195 - memcpy(eth->h_dest, daddr, dev->addr_len);
196 +extern void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty);
197 +static void dump_rx_hook(struct netpoll *np, int port, char *msg, int len);
201 - spin_lock(&dev->xmit_lock);
202 - dev->xmit_lock_owner = smp_processor_id();
207 - if (netif_queue_stopped(dev)) {
208 - dev->xmit_lock_owner = -1;
209 - spin_unlock(&dev->xmit_lock);
211 - dev->poll_controller(dev);
212 - zap_completion_queue();
218 - dev->hard_start_xmit(skb, dev);
220 - dev->xmit_lock_owner = -1;
221 - spin_unlock(&dev->xmit_lock);
224 -static unsigned short
225 -udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr,
226 - unsigned long base)
228 - return csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base);
232 -udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
233 - unsigned short ulen, u32 saddr, u32 daddr)
235 - if (uh->check == 0) {
236 - skb->ip_summed = CHECKSUM_UNNECESSARY;
237 - } else if (skb->ip_summed == CHECKSUM_HW) {
238 - skb->ip_summed = CHECKSUM_UNNECESSARY;
239 - if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
241 - skb->ip_summed = CHECKSUM_NONE;
243 - if (skb->ip_summed != CHECKSUM_UNNECESSARY)
244 - skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen,
246 - /* Probably, we should checksum udp header (it should be in cache
247 - * in any case) and data in tiny packets (< rx copybreak).
252 -static __inline__ int
253 -__udp_checksum_complete(struct sk_buff *skb)
255 - return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len,
260 -int udp_checksum_complete(struct sk_buff *skb)
262 - return skb->ip_summed != CHECKSUM_UNNECESSARY &&
263 - __udp_checksum_complete(skb);
268 +static struct netpoll np = {
269 + .name = "netdumpoe",
270 + .dev_name = "eth0",
271 + .rx_hook = dump_rx_hook,
274 + .remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
278 -dump_rx_hook(struct sk_buff *skb)
279 +static void dump_rx_hook(struct netpoll *np, int port, char *msg, int len)
284 - __u32 len, saddr, daddr, ulen;
288 - * First check if were are dumping or doing startup handshake, if
289 - * not quickly return.
292 if (!netdump_in_progress)
293 - return NET_RX_SUCCESS;
295 + __req = (req_t *)msg;
297 - if (skb->dev->type != ARPHRD_ETHER)
300 - proto = ntohs(skb->mac.ethernet->h_proto);
301 - if (proto != ETH_P_IP)
304 - if (skb->pkt_type == PACKET_OTHERHOST)
307 - if (skb_shared(skb))
310 - /* IP header correctness testing: */
311 - iph = (struct iphdr *)skb->data;
312 - if (!pskb_may_pull(skb, sizeof(struct iphdr)))
315 - if (iph->ihl < 5 || iph->version != 4)
318 - if (!pskb_may_pull(skb, iph->ihl*4))
321 - if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
324 - len = ntohs(iph->tot_len);
325 - if (skb->len < len || len < iph->ihl*4)
328 - saddr = iph->saddr;
329 - daddr = iph->daddr;
330 - if (iph->protocol != IPPROTO_UDP)
333 - if (source_ip != daddr)
336 - if (target_ip != saddr)
340 - uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
341 - ulen = ntohs(uh->len);
343 - if (ulen != len || ulen < (sizeof(*uh) + sizeof(*__req)))
346 - if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
349 - if (udp_checksum_complete(skb))
352 - if (source_port != uh->dest)
355 - if (target_port != uh->source)
358 - __req = (req_t *)(uh + 1);
359 if ((ntohl(__req->command) != COMM_GET_MAGIC) &&
360 (ntohl(__req->command) != COMM_HELLO) &&
361 (ntohl(__req->command) != COMM_START_WRITE_NETDUMP_ACK) &&
363 req.nr = ntohl(__req->nr);
366 - return NET_RX_DROP;
371 -dump_send_mem(struct net_device *dev, req_t *req, const char* buff, size_t len)
372 +dump_send_skb(const char *msg, unsigned int msg_len, reply_t *reply)
374 + /*copy the msg to send buffer*/
375 + send_buffer[0] = NETCONSOLE_VERSION;
377 + put_unaligned(htonl(reply->nr), (u32 *) (send_buffer + 1));
378 + put_unaligned(htonl(reply->code), (u32 *) (send_buffer + 5));
379 + put_unaligned(htonl(reply->info), (u32 *) (send_buffer + 9));
380 + memcpy(send_buffer + 1 + sizeof(reply_t), msg, msg_len);
384 + netpoll_send_udp(&np, send_buffer, (msg_len + 1 + sizeof(reply_t)));
388 +dump_send_mem( req_t *req, const char* buff, size_t len)
393 unsigned int offset = i*1024;
394 reply.code = REPLY_MEM;
396 - dump_send_skb(dev, buff + offset, 1024, &reply);
397 + dump_send_skb(buff + offset, 1024, &reply);
400 static void dump_do_sysrq(int key)
404 get_current_regs(®s);
405 - handle_sysrq(key, ®s, NULL, NULL);
406 + handle_sysrq(key, ®s, NULL);
409 +static void netdump_netpoll_poll(struct netpoll *np)
411 + /*FIXME netpoll_set_trap(0) may have impacts to other parts */
412 + netpoll_set_trap(1);
414 + netpoll_set_trap(0);
417 * This function waits for the client to acknowledge the receipt
418 * of the netdump startup reply, with the possibility of packets
419 @@ -433,24 +175,27 @@
421 /* send 300 handshake packets before declaring failure */
422 for (i = 0; i < 300; i++) {
423 - dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
425 + dump_send_skb(tmp, strlen(tmp), &reply);
434 for (j = 0; j < 10000; j++) {
436 - dump_ndev->poll_controller(dump_ndev);
437 - zap_completion_queue();
438 + netdump_netpoll_poll(&np);
444 * if there is no new request, try sending the handshaking
451 * check if the new request is of the expected type,
452 * if so, return, else try sending the handshaking
453 @@ -504,10 +249,12 @@
458 - dump_ndev->poll_controller(dump_ndev);
459 - zap_completion_queue();
461 + netdump_netpoll_poll(&np);
469 @@ -532,13 +279,15 @@
476 switch (req.command) {
481 - dump_send_mem(dump_ndev, &req, buff, len);
482 + dump_send_mem(&req, buff, len);
486 @@ -549,10 +298,11 @@
488 sprintf(tmp, "Hello, this is netdump version "
489 "0.%02d\n", NETCONSOLE_VERSION);
491 reply.code = REPLY_HELLO;
493 reply.info = net_dev->curr_offset;
494 - dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
495 + dump_send_skb(tmp, strlen(tmp), &reply);
498 case COMM_GET_PAGE_SIZE:
500 reply.code = REPLY_PAGE_SIZE;
502 reply.info = PAGE_SIZE;
503 - dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
504 + dump_send_skb(tmp, strlen(tmp), &reply);
507 case COMM_GET_NR_PAGES:
508 @@ -569,15 +319,14 @@
509 reply.info = num_physpages;
510 reply.info = page_counter;
511 sprintf(tmp, "Number of pages: %ld\n", num_physpages);
512 - dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
513 + dump_send_skb(tmp, strlen(tmp), &reply);
517 reply.code = REPLY_MAGIC;
519 reply.info = NETCONSOLE_VERSION;
520 - dump_send_skb(dump_ndev, (char *)&dump_magic,
521 - sizeof(dump_magic), &reply);
522 + dump_send_skb((char *)&dump_magic, sizeof(dump_magic), &reply);
525 dump_do_sysrq(req.from);
528 reply.info = req.from;
529 sprintf(tmp, "SYSRQ command %d \n", req.from);
530 - dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
531 + dump_send_skb(tmp, strlen(tmp), &reply);
534 reply.code = REPLY_ERROR;
536 reply.info = req.command;
537 sprintf(tmp, "Got unknown command code %d!\n",
539 - dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
540 + dump_send_skb(tmp, strlen(tmp), &reply);
544 @@ -605,45 +354,45 @@
546 dump_validate_config(void)
548 - source_ip = dump_in_dev->ifa_list->ifa_local;
551 + np.local_ip = dump_in_dev->ifa_list->ifa_local;
552 + if (!np.local_ip) {
553 printk("network device %s has no local address, "
554 "aborting.\n", device_name);
558 -#define IP(x) ((unsigned char *)&source_ip)[x]
560 +#define IP(x) ((unsigned char *)&np.local_ip)[x]
561 printk("Source %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
564 - if (!source_port) {
565 + if (!np.local_port) {
566 printk("source_port parameter not specified, aborting.\n");
569 - printk(":%i\n", source_port);
570 - source_port = htons(source_port);
571 + printk(":%i\n", np.local_port);
574 + if (!np.remote_ip) {
575 printk("target_ip parameter not specified, aborting.\n");
579 -#define IP(x) ((unsigned char *)&target_ip)[x]
580 +#define IP(x) ((unsigned char *)&np.remote_ip)[x]
581 printk("Target %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
584 - if (!target_port) {
585 + if (!np.remote_port) {
586 printk("target_port parameter not specified, aborting.\n");
589 - printk(":%i\n", target_port);
590 - target_port = htons(target_port);
591 + printk(":%i\n", np.remote_port);
593 printk("Target Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x",
594 - daddr[0], daddr[1], daddr[2], daddr[3], daddr[4], daddr[5]);
595 + np.remote_mac[0], np.remote_mac[1], np.remote_mac[2],
596 + np.remote_mac[3], np.remote_mac[4], np.remote_mac[5]);
598 - if ((daddr[0] & daddr[1] & daddr[2] & daddr[3] & daddr[4] &
600 + if ((np.remote_mac[0] & np.remote_mac[1] & np.remote_mac[2] &
601 + np.remote_mac[3] & np.remote_mac[4] & np.remote_mac[5]) == 255)
602 printk("(Broadcast)");
605 @@ -659,31 +408,24 @@
606 dump_net_open(struct dump_dev *net_dev, unsigned long arg)
611 /* get the interface name */
612 if (copy_from_user(device_name, (void *)arg, IFNAMSIZ))
615 - if (!(dump_ndev = dev_get_by_name(device_name))) {
616 + if (!(np.dev = dev_get_by_name(device_name))) {
617 printk("network device %s does not exist, aborting.\n",
622 - if (!dump_ndev->poll_controller) {
623 - printk("network device %s does not implement polling yet, "
624 - "aborting.\n", device_name);
625 - retval = -1; /* return proper error */
629 - if (!(dump_in_dev = in_dev_get(dump_ndev))) {
631 + if (!(dump_in_dev = in_dev_get(np.dev))) {
632 printk("network device %s is not an IP protocol device, "
633 "aborting.\n", device_name);
639 if ((retval = dump_validate_config()) < 0)
644 in_dev_put(dump_in_dev);
646 - dev_put(dump_ndev);
654 in_dev_put(dump_in_dev);
656 - dev_put(dump_ndev);
663 dump_net_silence(struct dump_dev *net_dev)
665 local_irq_save(flags_global);
666 - dump_ndev->rx_hook = dump_rx_hook;
667 startup_handshake = 1;
668 net_dev->curr_offset = 0;
669 printk("Dumping to network device %s on CPU %d ...\n", device_name,
678 sprintf(tmp, "NETDUMP end.\n");
679 @@ -748,11 +489,10 @@
680 reply.code = REPLY_END_NETDUMP;
683 - dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
684 + dump_send_skb(tmp, strlen(tmp), &reply);
686 printk("NETDUMP END!\n");
687 local_irq_restore(flags_global);
688 - dump_ndev->rx_hook = NULL;
689 startup_handshake = 0;
692 @@ -809,18 +549,19 @@
694 dump_net_ioctl(struct dump_dev *net_dev, unsigned int cmd, unsigned long arg)
700 + np.remote_ip = arg;
703 - target_port = (u16)arg;
704 + np.remote_port = (u16)arg;
707 - source_port = (u16)arg;
708 + np.local_port = (u16)arg;
711 - return copy_from_user(daddr, (void *)arg, 6);
712 + return copy_from_user(np.remote_mac, (void *)arg, 6);
724 @@ -851,17 +593,28 @@
728 +static int option_setup(char *opt)
730 + return netpoll_parse_options(&np, opt);
733 +__setup("netdumpoe=", option_setup);
737 dump_netdev_init(void)
739 default_dump_netdev.curr_offset = 0;
741 + if(!np.remote_ip || netpoll_setup(&np))
744 if (dump_register_device(&default_dump_netdev) < 0) {
745 printk("network dump device driver registration failed\n");
748 printk("network device driver for LKCD registered\n");
751 get_random_bytes(&dump_magic, sizeof(dump_magic));
755 dump_netdev_cleanup(void)
757 dump_unregister_device(&default_dump_netdev);
758 + netpoll_cleanup(&np);
761 MODULE_AUTHOR("LKCD Development Team <lkcd-devel@lists.sourceforge.net>");