linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* LKCD Network dump over netpoll patch (2.6.0-test9)
@ 2003-11-10 13:54 Prasanna S Panchamukhi
  0 siblings, 0 replies; 5+ messages in thread
From: Prasanna S Panchamukhi @ 2003-11-10 13:54 UTC (permalink / raw)
  To: lkcd-devel; +Cc: linux-kernel, mpm, suparna

Hi,

This patch includes LKCD networkdump code changes over netpoll API's for 
kernel version 2.6.0-test9. Both the netconsole and network dumping can be 
achieved. Procedure for netdumping is explained below:

1. Apply the netpoll-core.patch and netconsole.patch (http://www.selenic.com/netpoll/)
2. Download the LKCD code from the cvs using
	cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/lkcd login (presee enter key for passwd)
 
	cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/lkcd co 2.6  
	cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/lkcd co lkcdutils 

3. Copy the lkcd files to the kernel source directory.
	#cp -r ../2.6/* ./linux-2.6-test9/
4. Apply the kernel-changes.patch from the 2.6/patches directory.
5. Apply the pollcontroller.patch from the 2.6/patches 
	directory now.
6. Apply the lkcd-netpoll.patch(below)
7. Buid the kernel with LKCD network dumping enabled ;reboot and insert the dump_netdev.o module.

8. You also need to install and setup the lkcdutils.
	#./configure; make ; make install.
	#cd netdump
	#make; make install.
9. Configure the netdump fileds in the /etc/sysconfig/dump file.
	#you need to specify the local port,remote port, local ip, target ip and device name for netdump. 
	eg :	DUMP_ACTIVE=1
		DUMPDEV=eth0
		DUMPDIR=/var/log/dump
		DUMP_SAVE=1
		DUMP_LEVEL=2
		DUMP_FLAGS=0x40000000 
		DUMP_COMPRESS=0
		PANIC_TIMEOUT=5

		TARGET_HOST=9.182.14.40 #h set this to vaild hostname/IP
		TARGET_PORT=6688
		SOURCE_PORT=6688
		ETH_ADDRESS=00:07:95:E6:08:FB

10. Run lkcd config and now you can try test dumps..


diff -urNp linux.orig/drivers/net/3c59x.c linux-2.6.0-test9/drivers/net/3c59x.c
--- linux.orig/drivers/net/3c59x.c	2003-11-11 06:14:48.000000000 +0530
+++ linux-2.6.0-test9/drivers/net/3c59x.c	2003-11-11 06:15:54.386937760 +0530
@@ -900,6 +900,7 @@ static void set_rx_mode(struct net_devic
 static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void vortex_tx_timeout(struct net_device *dev);
 static void acpi_set_WOL(struct net_device *dev);
+static void vorboom_poll(struct net_device *dev);
 static struct ethtool_ops vortex_ethtool_ops;
 \f
 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
@@ -1450,6 +1451,9 @@ static int __devinit vortex_probe1(struc
 	dev->set_multicast_list = set_rx_mode;
 	dev->tx_timeout = vortex_tx_timeout;
 	dev->watchdog_timeo = (watchdog * HZ) / 1000;
+#ifdef HAVE_POLL_CONTROLLER
+	dev->poll_controller = &vorboom_poll;
+#endif
 	if (pdev) {
 		vp->pm_state_valid = 1;
  		pci_save_state(VORTEX_PCI(vp), vp->power_state);
@@ -2440,6 +2444,29 @@ handler_exit:
 	return IRQ_HANDLED;
 }
 
+#ifdef HAVE_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void vorboom_poll (struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+
+	disable_irq(dev->irq);
+	if (vp->full_bus_master_tx)
+		boomerang_interrupt(dev->irq, dev, 0);
+	else
+		vortex_interrupt(dev->irq, dev, 0);
+	enable_irq(dev->irq);
+}
+
+#endif
+
+
 static int vortex_rx(struct net_device *dev)
 {
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
diff -urNp linux.orig/drivers/net/e100/e100_main.c linux-2.6.0-test9/drivers/net/e100/e100_main.c
--- linux.orig/drivers/net/e100/e100_main.c	2003-11-11 06:14:48.000000000 +0530
+++ linux-2.6.0-test9/drivers/net/e100/e100_main.c	2003-11-11 06:15:54.398935936 +0530
@@ -539,6 +539,22 @@ e100_trigger_SWI(struct e100_private *bd
 	readw(&(bdp->scb->scb_status));	/* flushes last write, read-safe */
 }
 
+#ifdef HAVE_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void
+e100_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	e100intr(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 static int __devinit
 e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent)
 {
@@ -557,6 +573,9 @@ e100_found1(struct pci_dev *pcid, const 
 
 	SET_MODULE_OWNER(dev);
 
+#ifdef HAVE_POLL_CONTROLLER
+	dev->poll_controller = &e100_poll;
+#endif
 	if (first_time) {
 		first_time = false;
         	printk(KERN_NOTICE "%s - version %s\n",
diff -urNp linux.orig/drivers/net/e1000/e1000_main.c linux-2.6.0-test9/drivers/net/e1000/e1000_main.c
--- linux.orig/drivers/net/e1000/e1000_main.c	2003-11-11 06:14:48.000000000 +0530
+++ linux-2.6.0-test9/drivers/net/e1000/e1000_main.c	2003-11-11 06:15:54.439929704 +0530
@@ -165,6 +165,7 @@ static void e1000_leave_82542_rst(struct
 static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
                                      struct e1000_rx_desc *rx_desc,
                                      struct sk_buff *skb);
+static void e1000_Poll(struct net_device *dev);
 static void e1000_tx_timeout(struct net_device *dev);
 static void e1000_tx_timeout_task(struct net_device *dev);
 static void e1000_smartspeed(struct e1000_adapter *adapter);
@@ -442,6 +443,9 @@ e1000_probe(struct pci_dev *pdev,
 
 	adapter->bd_number = cards_found;
 
+#ifdef HAVE_POLL_CONTROLLER
+	netdev->poll_controller = &e1000_Poll;
+#endif
 	/* setup the private structure */
 
 	if((err = e1000_sw_init(adapter)))
@@ -2106,6 +2110,15 @@ e1000_intr(int irq, void *data, struct p
 		mod_timer(&adapter->watchdog_timer, jiffies);
 	}
 
+#ifdef HAVE_POLL_CONTROLLER
+static void e1000_Poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	e1000_intr(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 #ifdef CONFIG_E1000_NAPI
 	if(netif_rx_schedule_prep(netdev)) {
 
diff -urNp linux.orig/drivers/net/eepro100.c linux-2.6.0-test9/drivers/net/eepro100.c
--- linux.orig/drivers/net/eepro100.c	2003-11-11 06:14:49.000000000 +0530
+++ linux-2.6.0-test9/drivers/net/eepro100.c	2003-11-11 06:15:54.455927272 +0530
@@ -543,6 +543,7 @@ static void speedo_refill_rx_buffers(str
 static int speedo_rx(struct net_device *dev);
 static void speedo_tx_buffer_gc(struct net_device *dev);
 static irqreturn_t speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static void poll_speedo (struct net_device *dev);
 static int speedo_close(struct net_device *dev);
 static struct net_device_stats *speedo_get_stats(struct net_device *dev);
 static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -885,6 +886,9 @@ static int __devinit speedo_found1(struc
 	dev->get_stats = &speedo_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &speedo_ioctl;
+#ifdef HAVE_POLL_CONTROLLER
+	dev->poll_controller = &poll_speedo;
+#endif
 
 	if (register_netdevice(dev))
 		goto err_free_unlock;
@@ -1675,6 +1679,23 @@ static irqreturn_t speedo_interrupt(int 
 	return IRQ_RETVAL(handled);
 }
 
+#ifdef HAVE_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void poll_speedo (struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	speedo_interrupt (dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+
+#endif
+
 static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
 {
 	struct speedo_private *sp = (struct speedo_private *)dev->priv;
diff -urNp linux.orig/drivers/net/smc-ultra.c linux-2.6.0-test9/drivers/net/smc-ultra.c
--- linux.orig/drivers/net/smc-ultra.c	2003-11-11 06:14:49.000000000 +0530
+++ linux-2.6.0-test9/drivers/net/smc-ultra.c	2003-11-11 06:15:54.466925600 +0530
@@ -122,6 +122,14 @@ MODULE_DEVICE_TABLE(isapnp, ultra_device
 #define ULTRA_IO_EXTENT 32
 #define EN0_ERWCNT		0x08	/* Early receive warning count. */
 \f
+
+static void ultra_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	ei_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+
 /*	Probe for the Ultra.  This looks like a 8013 with the station
 	address PROM at I/O ports <base>+8 to <base>+13, with a checksum
 	following.
@@ -134,6 +142,9 @@ int __init ultra_probe(struct net_device
 
 	SET_MODULE_OWNER(dev);
 
+#ifdef HAVE_POLL_CONTROLLER
+	dev->poll_controller = &ultra_poll;
+#endif
 	if (base_addr > 0x1ff)		/* Check a single specified location. */
 		return ultra_probe1(dev, base_addr);
 	else if (base_addr != 0)	/* Don't probe at all. */
diff -urNp linux.orig/drivers/net/tlan.c linux-2.6.0-test9/drivers/net/tlan.c
--- linux.orig/drivers/net/tlan.c	2003-11-11 06:14:49.000000000 +0530
+++ linux-2.6.0-test9/drivers/net/tlan.c	2003-11-11 06:15:54.472924688 +0530
@@ -346,6 +346,8 @@ static int	TLan_EeSendByte( u16, u8, int
 static void	TLan_EeReceiveByte( u16, u8 *, int );
 static int	TLan_EeReadByte( struct net_device *, u8, u8 * );
 
+static void	TLan_Poll(struct net_device *);
+
 
 static void 
 TLan_StoreSKB( struct tlan_list_tag *tag, struct sk_buff *skb)
@@ -893,6 +895,9 @@ static int TLan_Init( struct net_device 
 	dev->get_stats = &TLan_GetStats;
 	dev->set_multicast_list = &TLan_SetMulticastList;
 	dev->do_ioctl = &TLan_ioctl;
+#ifdef HAVE_POLL_CONTROLLER
+	dev->poll_controller = &TLan_Poll;
+#endif
 	dev->tx_timeout = &TLan_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
@@ -1176,7 +1181,14 @@ static irqreturn_t TLan_HandleInterrupt(
 	return IRQ_HANDLED;
 } /* TLan_HandleInterrupts */
 
-
+#ifdef HAVE_POLL_CONTROLLER
+static void TLan_Poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	TLan_HandleInterrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 
 	/***************************************************************
diff -urNp linux.orig/drivers/net/tulip/tulip_core.c linux-2.6.0-test9/drivers/net/tulip/tulip_core.c
--- linux.orig/drivers/net/tulip/tulip_core.c	2003-11-11 06:14:48.000000000 +0530
+++ linux-2.6.0-test9/drivers/net/tulip/tulip_core.c	2003-11-11 06:15:54.501920280 +0530
@@ -247,6 +247,7 @@ static void tulip_down(struct net_device
 static struct net_device_stats *tulip_get_stats(struct net_device *dev);
 static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
+static void poll_tulip(struct net_device *dev);
 
 
 
@@ -1632,6 +1633,9 @@ static int __devinit tulip_init_one (str
 	dev->get_stats = tulip_get_stats;
 	dev->do_ioctl = private_ioctl;
 	dev->set_multicast_list = set_rx_mode;
+#ifdef HAVE_POLL_CONTROLLER
+	dev->poll_controller = &poll_tulip;
+#endif
 
 	if (register_netdev(dev))
 		goto err_out_free_ring;
@@ -1789,6 +1793,24 @@ static void __devexit tulip_remove_one (
 }
 
 
+#ifdef HAVE_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+static void poll_tulip (struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       tulip_interrupt (dev->irq, dev, NULL);
+       enable_irq(dev->irq);
+}
+
+#endif
+
+
 static struct pci_driver tulip_driver = {
 	.name		= DRV_NAME,
 	.id_table	= tulip_pci_tbl,
diff -urNp linux.orig/include/linux/netdevice.h linux-2.6.0-test9/include/linux/netdevice.h
--- linux.orig/include/linux/netdevice.h	2003-11-11 06:15:18.000000000 +0530
+++ linux-2.6.0-test9/include/linux/netdevice.h	2003-11-11 06:15:54.000000000 +0530
@@ -455,10 +455,10 @@ struct net_device
 #ifdef CONFIG_NETPOLL_RX
 	int			netpoll_rx;
 #endif
+#define HAVE_POLL_CONTROLLER
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	void                    (*poll_controller)(struct net_device *dev);
+       void                    (*poll_controller)(struct net_device *dev);
 #endif
-
 	/* bridge stuff */
 	struct net_bridge_port	*br_port;
 
diff -urNp linux.orig/net/core/dev.c linux-2.6.0-test9/net/core/dev.c
--- linux.orig/net/core/dev.c	2003-11-11 06:15:16.000000000 +0530
+++ linux-2.6.0-test9/net/core/dev.c	2003-11-11 06:17:09.000000000 +0530
@@ -1387,8 +1387,6 @@ int netif_rx(struct sk_buff *skb)
 	}
 #endif
 
-	if (!skb->stamp.tv_sec)
-		do_gettimeofday(&skb->stamp);
 
 	/*
 	 * The code is rearranged so that the path is the most
-- 
Thanks & Regards
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: LKCD Network dump over netpoll patch (2.6.0-test9)
  2003-11-14  4:57   ` Prasanna S Panchamukhi
@ 2003-11-14  5:22     ` Prasanna S Panchamukhi
  0 siblings, 0 replies; 5+ messages in thread
From: Prasanna S Panchamukhi @ 2003-11-14  5:22 UTC (permalink / raw)
  To: lkcd-devel; +Cc: linux-kernel, mpm, suparna, prasanna

Hi,

Below is the lkcd-netdump.patch. This patch includes changes as suggested by 
Matt Mackall to define a new routine netdump_send_packet().


diff -urNp linux.orig/drivers/dump/dump_netdev.c linux+np/drivers/dump/dump_netdev.c
--- linux.orig/drivers/dump/dump_netdev.c	2003-11-13 05:56:01.000000000 +0530
+++ linux+np/drivers/dump/dump_netdev.c	2003-11-14 13:47:39.147245304 +0530
@@ -11,6 +11,8 @@
  * Nov 2002 - Bharata B. Rao <bharata@in.ibm.com>
  * 	Innumerable code cleanups, simplification and some fixes.
  *	Netdump configuration done by ioctl instead of using module parameters.
+ * Oct 2003 - Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ *	Netdump code modified to use Netpoll API's.
  *
  * Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
  * Copyright (C) 2002 International Business Machines Corp. 
@@ -26,23 +28,13 @@
 #include <linux/module.h>
 #include <linux/dump.h>
 #include <linux/dump_netdev.h>
-#include <linux/percpu.h>
 
 #include <asm/unaligned.h>
 
 static int startup_handshake;
 static int page_counter;
-static struct net_device *dump_ndev;
-static struct in_device *dump_in_dev;
-static u16 source_port, target_port;
-static u32 source_ip, target_ip;
-static unsigned char daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
-static spinlock_t dump_skb_lock = SPIN_LOCK_UNLOCKED;
-static int dump_nr_skbs;
-static struct sk_buff *dump_skb;
 static unsigned long flags_global;
 static int netdump_in_progress;
-static char device_name[IFNAMSIZ];
 
 /*
  * security depends on the trusted path between the netconsole
@@ -52,311 +44,27 @@ static char device_name[IFNAMSIZ];
  */
 static u64 dump_magic;
 
-#define MAX_UDP_CHUNK 1460
-#define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
-
 /*
  * We maintain a small pool of fully-sized skbs,
  * to make sure the message gets out even in
  * extreme OOM situations.
  */
-#define DUMP_MAX_SKBS 32
-
-#define MAX_SKB_SIZE \
-		(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
-				sizeof(struct iphdr) + sizeof(struct ethhdr))
-
-static void
-dump_refill_skbs(void)
-{
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dump_skb_lock, flags);
-	while (dump_nr_skbs < DUMP_MAX_SKBS) {
-		skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
-		if (!skb)
-			break;
-		if (dump_skb)
-			skb->next = dump_skb;
-		else
-			skb->next = NULL;
-		dump_skb = skb;
-		dump_nr_skbs++;
-	}
-	spin_unlock_irqrestore(&dump_skb_lock, flags);
-}
-
-static struct
-sk_buff * dump_get_skb(void)
-{
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dump_skb_lock, flags);
-	skb = dump_skb;
-	if (skb) {
-		dump_skb = skb->next;
-		skb->next = NULL;
-		dump_nr_skbs--;
-	}
-	spin_unlock_irqrestore(&dump_skb_lock, flags);
-        
-	return skb;
-}
-
-/*
- * Zap completed output skbs.
- */
-static void
-zap_completion_queue(void)
-{
-	int count;
-	unsigned long flags;
-	struct softnet_data *sd;
-
-        count=0;
-	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;
-			__kfree_skb(skb);
-			count++;
-			if (count > 10000)
-				printk("Error in sk list\n");
-		}
-	}
-}
-
-static void
-dump_send_skb(struct net_device *dev, const char *msg, unsigned int msg_len,
-		reply_t *reply)
-{
-	int once = 1;
-	int total_len, eth_len, ip_len, udp_len, count = 0;
-	struct sk_buff *skb;
-	struct udphdr *udph;
-	struct iphdr *iph;
-	struct ethhdr *eth; 
-
-	udp_len = msg_len + HEADER_LEN + sizeof(*udph);
-	ip_len = eth_len = udp_len + sizeof(*iph);
-	total_len = eth_len + ETH_HLEN;
-
-repeat_loop:
-	zap_completion_queue();
-	if (dump_nr_skbs < DUMP_MAX_SKBS)
-		dump_refill_skbs();
-
-	skb = alloc_skb(total_len, GFP_ATOMIC);
-	if (!skb) {
-		skb = dump_get_skb();
-		if (!skb) {
-			count++;
-			if (once && (count == 1000000)) {
-				printk("possibly FATAL: out of netconsole "
-					"skbs!!! will keep retrying.\n");
-				once = 0;
-			}
-			dev->poll_controller(dev);
-			goto repeat_loop;
-		}
-	}
-
-	atomic_set(&skb->users, 1);
-	skb_reserve(skb, total_len - msg_len - HEADER_LEN);
-	skb->data[0] = NETCONSOLE_VERSION;
-
-	put_unaligned(htonl(reply->nr), (u32 *) (skb->data + 1));
-	put_unaligned(htonl(reply->code), (u32 *) (skb->data + 5));
-	put_unaligned(htonl(reply->info), (u32 *) (skb->data + 9));
-
-	memcpy(skb->data + HEADER_LEN, msg, msg_len);
-	skb->len += msg_len + HEADER_LEN;
-
-	udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
-	udph->source = source_port;
-	udph->dest = target_port;
-	udph->len = htons(udp_len);
-	udph->check = 0;
-
-	iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
-
-	iph->version  = 4;
-	iph->ihl      = 5;
-	iph->tos      = 0;
-	iph->tot_len  = htons(ip_len);
-	iph->id       = 0;
-	iph->frag_off = 0;
-	iph->ttl      = 64;
-	iph->protocol = IPPROTO_UDP;
-	iph->check    = 0;
-	iph->saddr    = source_ip;
-	iph->daddr    = target_ip;
-	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
-	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-
-	eth->h_proto = htons(ETH_P_IP);
-	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-	memcpy(eth->h_dest, daddr, dev->addr_len);
-
-	count=0;
-repeat_poll:
-	spin_lock(&dev->xmit_lock);
-	dev->xmit_lock_owner = smp_processor_id();
-
-	count++;
-
-
-	if (netif_queue_stopped(dev)) {
-		dev->xmit_lock_owner = -1;
-		spin_unlock(&dev->xmit_lock);
-
-		dev->poll_controller(dev);
-		zap_completion_queue();
-
-
-		goto repeat_poll;
-	}
-
-	dev->hard_start_xmit(skb, dev);
-
-	dev->xmit_lock_owner = -1;
-	spin_unlock(&dev->xmit_lock);
-}
-
-static unsigned short
-udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr,
-	       	unsigned long base)
-{
-	return csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base);
-}
-
-static int
-udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
-			     unsigned short ulen, u32 saddr, u32 daddr)
-{
-	if (uh->check == 0) {
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else if (skb->ip_summed == CHECKSUM_HW) {
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
-			return 0;
-		skb->ip_summed = CHECKSUM_NONE;
-	}
-	if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-		skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen,
-				IPPROTO_UDP, 0);
-	/* Probably, we should checksum udp header (it should be in cache
-	 * in any case) and data in tiny packets (< rx copybreak).
-	 */
-	return 0;
-}
-
-static __inline__ int
-__udp_checksum_complete(struct sk_buff *skb)
-{
-	return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len,
-				skb->csum));
-}
-
-static __inline__
-int udp_checksum_complete(struct sk_buff *skb)
-{
-	return skb->ip_summed != CHECKSUM_UNNECESSARY &&
-		__udp_checksum_complete(skb);
-}
 
+static void rx_hook(struct netpoll *np, int port, char *msg, int size);
 int new_req = 0;
 static req_t req;
 
-static int
-dump_rx_hook(struct sk_buff *skb)
+static void rx_hook(struct netpoll *np, int port, char *msg, int size)
 {
-	int proto;
-	struct iphdr *iph;
-	struct udphdr *uh;
-	__u32 len, saddr, daddr, ulen;
-	req_t *__req;
-
+	req_t * __req = (req_t *) msg;
 	/* 
 	 * First check if were are dumping or doing startup handshake, if
 	 * not quickly return.
 	 */
-	if (!netdump_in_progress)
-		return NET_RX_SUCCESS;
-
-	if (skb->dev->type != ARPHRD_ETHER)
-		goto out;
-
-	proto = ntohs(skb->mac.ethernet->h_proto);
-	if (proto != ETH_P_IP)
-		goto out;
-
-	if (skb->pkt_type == PACKET_OTHERHOST)
-		goto out;
-
-	if (skb_shared(skb))
-		goto out;
-
-	 /* IP header correctness testing: */
-	iph = (struct iphdr *)skb->data;
-	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-		goto out;
-
-	if (iph->ihl < 5 || iph->version != 4)
-		goto out;
-
-	if (!pskb_may_pull(skb, iph->ihl*4))
-		goto out;
-
-	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;
-
-	saddr = iph->saddr;
-	daddr = iph->daddr;
-	if (iph->protocol != IPPROTO_UDP)
-		goto out;
-
-	if (source_ip != daddr)
-		goto out;
-
-	if (target_ip != saddr)
-		goto out;
 
-	len -= iph->ihl*4;
-	uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
-	ulen = ntohs(uh->len);
-
-	if (ulen != len || ulen < (sizeof(*uh) + sizeof(*__req)))
-		goto out;
-
-	if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
-		goto out;
-
-	if (udp_checksum_complete(skb))
-		goto out;
-
-	if (source_port != uh->dest)
-		goto out;
-
-	if (target_port != uh->source)
-		goto out;
+	if (!netdump_in_progress)
+		return ;
 
-	__req = (req_t *)(uh + 1);
 	if ((ntohl(__req->command) != COMM_GET_MAGIC) &&
 	    (ntohl(__req->command) != COMM_HELLO) &&
 	    (ntohl(__req->command) != COMM_START_WRITE_NETDUMP_ACK) &&
@@ -371,27 +79,43 @@ dump_rx_hook(struct sk_buff *skb)
 	req.nr = ntohl(__req->nr);
 	new_req = 1;
 out:
-	return NET_RX_DROP;
+	return ;
+}
+static char netdump_membuf[1024 + HEADER_LEN + 1];
+/*
+ * Fill the netdump_membuf with the header information from reply_t structure 
+ * and send it down to netpoll_send_udp() routine.
+ */
+static void 
+netdump_send_packet(struct netpoll *np, reply_t *reply, size_t data_len) {
+	char *b;
+
+	b = &netdump_membuf[1];
+	netdump_membuf[0] = NETCONSOLE_VERSION;
+	put_unaligned(htonl(reply->nr), (u32 *) b);
+	put_unaligned(htonl(reply->code), (u32 *) (b + sizeof(reply->code)));
+	put_unaligned(htonl(reply->info), (u32 *) (b + sizeof(reply->code) + 
+		sizeof(reply->info)));
+	netpoll_send_udp(np, netdump_membuf, data_len + HEADER_LEN);
 }
 
 static void
-dump_send_mem(struct net_device *dev, req_t *req, const char* buff, size_t len)
+dump_send_mem(struct netpoll *np, req_t *req, const char* buff, size_t len)
 {
 	int i;
 
 	int nr_chunks = len/1024;
 	reply_t reply;
-	
-	reply.nr = req->nr;
-	reply.info = 0;
 
+	reply.nr = req->nr;
+	reply.code = REPLY_MEM;
         if ( nr_chunks <= 0)
 		 nr_chunks = 1;
 	for (i = 0; i < nr_chunks; i++) {
 		unsigned int offset = i*1024;
-		reply.code = REPLY_MEM;
 		reply.info = offset;
-                dump_send_skb(dev, buff + offset, 1024, &reply);
+		memcpy((netdump_membuf + HEADER_LEN), (buff + offset), 1024);
+		netdump_send_packet(np, &reply, 1024);
 	}
 }
 
@@ -407,31 +131,33 @@ dump_send_mem(struct net_device *dev, re
 static int
 dump_handshake(struct dump_dev *net_dev)
 {
-	char tmp[200];
 	reply_t reply;
 	int i, j;
+	size_t str_len;
 
 	if (startup_handshake) {
-		sprintf(tmp, "NETDUMP start, waiting for start-ACK.\n");
+		sprintf((netdump_membuf + HEADER_LEN), 
+			"NETDUMP start, waiting for start-ACK.\n");
 		reply.code = REPLY_START_NETDUMP;
 		reply.nr = 0;
 		reply.info = 0;
 	} else {
-		sprintf(tmp, "NETDUMP start, waiting for start-ACK.\n");
+		sprintf((netdump_membuf + HEADER_LEN), 
+			"NETDUMP start, waiting for start-ACK.\n");
 		reply.code = REPLY_START_WRITE_NETDUMP;
 		reply.nr = net_dev->curr_offset;
 		reply.info = net_dev->curr_offset;
 	}
+	str_len = strlen(netdump_membuf + HEADER_LEN);
 	
 	/* send 300 handshake packets before declaring failure */
 	for (i = 0; i < 300; i++) {
-		dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+		netdump_send_packet(&net_dev->np, &reply, str_len);
 
 		/* wait 1 sec */
 		for (j = 0; j < 10000; j++) {
 			udelay(100);
-			dump_ndev->poll_controller(dump_ndev);
-			zap_completion_queue();
+			netpoll_poll(&net_dev->np);
 			if (new_req)
 				break;
 		}
@@ -472,9 +198,9 @@ static ssize_t
 do_netdump(struct dump_dev *net_dev, const char* buff, size_t len)
 {
 	reply_t reply;
-	char tmp[200];
 	ssize_t  ret = 0;
 	int repeatCounter, counter, total_loop;
+	size_t str_len;
 	
 	netdump_in_progress = 1;
 
@@ -497,8 +223,7 @@ do_netdump(struct dump_dev *net_dev, con
 	total_loop = 0;
 	while (1) {
                 if (!new_req) {
-			dump_ndev->poll_controller(dump_ndev);
-			zap_completion_queue();
+			netpoll_poll(&net_dev->np);
 		}
 		if (!new_req) {
 			repeatCounter++;
@@ -530,7 +255,7 @@ do_netdump(struct dump_dev *net_dev, con
 			break;
 
 		case COMM_SEND_MEM:
-			dump_send_mem(dump_ndev, &req, buff, len);
+			dump_send_mem(&net_dev->np, &req, buff, len);
 			break;
 
 		case COMM_EXIT:
@@ -539,46 +264,55 @@ do_netdump(struct dump_dev *net_dev, con
 			goto out;
 
 		case COMM_HELLO:
-			sprintf(tmp, "Hello, this is netdump version "
-					"0.%02d\n", NETCONSOLE_VERSION);
+			sprintf((netdump_membuf + HEADER_LEN), 
+				"Hello, this is netdump version " "0.%02d\n",
+				 NETCONSOLE_VERSION);
+			str_len = strlen(netdump_membuf + HEADER_LEN);
 			reply.code = REPLY_HELLO;
 			reply.nr = req.nr;
                         reply.info = net_dev->curr_offset;
-			dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+			netdump_send_packet(&net_dev->np, &reply, str_len);
 			break;
 
 		case COMM_GET_PAGE_SIZE:
-			sprintf(tmp, "PAGE_SIZE: %ld\n", PAGE_SIZE);
+			sprintf((netdump_membuf + HEADER_LEN), 
+				"PAGE_SIZE: %ld\n", PAGE_SIZE);
+			str_len = strlen(netdump_membuf + HEADER_LEN);
 			reply.code = REPLY_PAGE_SIZE;
 			reply.nr = req.nr;
 			reply.info = PAGE_SIZE;
-			dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+			netdump_send_packet(&net_dev->np, &reply, str_len);
 			break;
 
 		case COMM_GET_NR_PAGES:
 			reply.code = REPLY_NR_PAGES;
 			reply.nr = req.nr;
 			reply.info = num_physpages;
-                        reply.info = page_counter;
-			sprintf(tmp, "Number of pages: %ld\n", num_physpages);
-			dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+			reply.info = page_counter;
+			sprintf((netdump_membuf + HEADER_LEN), 
+				"Number of pages: %ld\n", num_physpages);
+			str_len = strlen(netdump_membuf + HEADER_LEN);
+			netdump_send_packet(&net_dev->np, &reply, str_len);
 			break;
 
 		case COMM_GET_MAGIC:
 			reply.code = REPLY_MAGIC;
 			reply.nr = req.nr;
 			reply.info = NETCONSOLE_VERSION;
-			dump_send_skb(dump_ndev, (char *)&dump_magic,
-					sizeof(dump_magic), &reply);
+			sprintf((netdump_membuf + HEADER_LEN), 
+				(char *)&dump_magic, sizeof(dump_magic));
+			str_len = strlen(netdump_membuf + HEADER_LEN);
+			netdump_send_packet(&net_dev->np, &reply, str_len);
 			break;
 
 		default:
 			reply.code = REPLY_ERROR;
 			reply.nr = req.nr;
 			reply.info = req.command;
-			sprintf(tmp, "Got unknown command code %d!\n",
-					req.command);
-			dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+			sprintf((netdump_membuf + HEADER_LEN), 
+				"Got unknown command code %d!\n", req.command);
+			str_len = strlen(netdump_membuf + HEADER_LEN);
+			netdump_send_packet(&net_dev->np, &reply, str_len);
 			break;
 		}
 	}
@@ -588,47 +322,43 @@ out:
 }
 
 static int
-dump_validate_config(void)
+dump_validate_config(struct netpoll *np)
 {
-	source_ip = dump_in_dev->ifa_list->ifa_local;
-	if (!source_ip) {
+	if (!np->local_ip) {
 		printk("network device %s has no local address, "
-				"aborting.\n", device_name);
+				"aborting.\n", np->name);
 		return -1;
 	}
 
-#define IP(x) ((unsigned char *)&source_ip)[x]
+#define IP(x) ((unsigned char *)&np->local_ip)[x]
 	printk("Source %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
 #undef IP
 
-	if (!source_port) {
+	if (!np->local_port) {
 		printk("source_port parameter not specified, aborting.\n");
 		return -1;
 	}
-	printk(":%i\n", source_port);
-	source_port = htons(source_port);
 
-	if (!target_ip) {
+	if (!np->remote_ip) {
 		printk("target_ip parameter not specified, aborting.\n");
 		return -1;
 	}
 
-#define IP(x) ((unsigned char *)&target_ip)[x]
+	np->remote_ip = ntohl(np->remote_ip);
+#define IP(x) ((unsigned char *)&np->remote_ip)[x]
 	printk("Target %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
 #undef IP
 
-	if (!target_port) {
+	if (!np->remote_port) {
 		printk("target_port parameter not specified, aborting.\n");
 		return -1;
 	}
-	printk(":%i\n", target_port);
-	target_port = htons(target_port);
-
 	printk("Target Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x",
-		daddr[0], daddr[1], daddr[2], daddr[3], daddr[4], daddr[5]);
+		np->remote_mac[0], np->remote_mac[1], np->remote_mac[2], 
+		np->remote_mac[3], np->remote_mac[4], np->remote_mac[5]);
 
-	if ((daddr[0] & daddr[1] & daddr[2] & daddr[3] & daddr[4] & 
-				daddr[5]) == 255)
+	if ((np->remote_mac[0] & np->remote_mac[1] & np->remote_mac[2] & 
+		np->remote_mac[3] & np->remote_mac[4] & np->remote_mac[5]) == 255)
 		printk("(Broadcast)");
 	printk("\n");
 	return 0;
@@ -646,40 +376,15 @@ dump_net_open(struct dump_dev *net_dev, 
 	int retval = 0;
 
 	/* get the interface name */
-	if (copy_from_user(device_name, (void *)arg, IFNAMSIZ))
+	if (copy_from_user(net_dev->np.dev_name, (void *)arg, IFNAMSIZ))
 		return -EFAULT;
+	net_dev->np.rx_hook = rx_hook;	
+	retval = netpoll_setup(&net_dev->np);
 
-	if (!(dump_ndev = dev_get_by_name(device_name))) {
-		printk("network device %s does not exist, aborting.\n",
-				device_name);
-		return -ENODEV;
-	}
-
-	if (!dump_ndev->poll_controller) {
-		printk("network device %s does not implement polling yet, "
-				"aborting.\n", device_name);
-		retval = -1; /* return proper error */
-		goto err1;
-	}
-
-	if (!(dump_in_dev = in_dev_get(dump_ndev))) {
-		printk("network device %s is not an IP protocol device, "
-				"aborting.\n", device_name);
-		retval = -EINVAL;
-		goto err1;
-	}
-
-	if ((retval = dump_validate_config()) < 0)
-		goto err2;
-
+	dump_validate_config(&net_dev->np);
 	net_dev->curr_offset = 0;
 	printk("Network device %s successfully configured for dumping\n",
-			device_name);
-	return retval;
-err2:
-	in_dev_put(dump_in_dev);
-err1:
-	dev_put(dump_ndev);	
+			net_dev->np.dev_name);
 	return retval;
 }
 
@@ -690,10 +395,7 @@ err1:
 static int
 dump_net_release(struct dump_dev *net_dev)
 {
-	if (dump_in_dev)
-		in_dev_put(dump_in_dev);
-	if (dump_ndev)
-		dev_put(dump_ndev);
+	netpoll_cleanup(&net_dev->np);
 	return 0;
 }
 
@@ -705,10 +407,9 @@ static int
 dump_net_silence(struct dump_dev *net_dev)
 {
 	local_irq_save(flags_global);
-	dump_ndev->rx_hook = dump_rx_hook;
         startup_handshake = 1;
 	net_dev->curr_offset = 0;
-	printk("Dumping to network device %s on CPU %d ...\n", device_name,
+	printk("Dumping to network device %s on CPU %d ...\n", net_dev->np.name,
 			smp_processor_id());
 	return 0;
 }
@@ -722,22 +423,19 @@ static int
 dump_net_resume(struct dump_dev *net_dev)
 {
 	int indx;
+	size_t str_len;
 	reply_t reply;
-	char tmp[200];
 
-        if (!dump_ndev)
-		return (0);
-
-	sprintf(tmp, "NETDUMP end.\n");
+	sprintf((netdump_membuf + HEADER_LEN), "NETDUMP end.\n");
+	str_len = strlen(netdump_membuf + HEADER_LEN);
 	for( indx = 0; indx < 6; indx++) {
 		reply.code = REPLY_END_NETDUMP;
 		reply.nr = 0;
 		reply.info = 0;
-		dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+		netdump_send_packet(&net_dev->np, &reply, str_len);
 	}
 	printk("NETDUMP END!\n");
 	local_irq_restore(flags_global);
-	dump_ndev->rx_hook = NULL;
 	startup_handshake = 0;
 	return 0;
 }
@@ -749,11 +447,6 @@ dump_net_resume(struct dump_dev *net_dev
 static  int
 dump_net_seek(struct dump_dev *net_dev, loff_t off)
 {
-	/*
-	 * For now using DUMP_HEADER_OFFSET as hard coded value,
-	 * See dump_block_seekin dump_blockdev.c to know how to
-	 * do this properly.
-	 */
 	net_dev->curr_offset = off;
 	return 0;
 }
@@ -796,16 +489,16 @@ dump_net_ioctl(struct dump_dev *net_dev,
 {
 	switch (cmd) {
 	case DIOSTARGETIP:
-		target_ip = arg;
+		net_dev->np.remote_ip= arg;
 		break;
 	case DIOSTARGETPORT:
-		target_port = (u16)arg;
+		net_dev->np.remote_port = (u16)arg;
 		break;
 	case DIOSSOURCEPORT:
-		source_port = (u16)arg;
+		net_dev->np.local_port = (u16)arg;
 		break;
 	case DIOSETHADDR:
-		return copy_from_user(daddr, (void *)arg, 6);
+		return copy_from_user(net_dev->np.remote_mac, (void *)arg, 6);
 		break;
 	case DIOGTARGETIP:
 	case DIOGTARGETPORT:
@@ -833,13 +526,19 @@ struct dump_dev_ops dump_netdev_ops = {
 static struct dump_dev default_dump_netdev = {
 	.type_name = "networkdev", 
 	.ops = &dump_netdev_ops, 
-	.curr_offset = 0
+	.curr_offset = 0,
+	.np.name = "netdump",
+	.np.dev_name = "eth0",
+	.np.rx_hook = rx_hook,
+	.np.local_port = 6688,
+	.np.remote_port = 6688,
+	.np.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
 };
 
 static int __init
 dump_netdev_init(void)
 {
-        default_dump_netdev.curr_offset = 0;
+	default_dump_netdev.curr_offset = 0;
 
 	if (dump_register_device(&default_dump_netdev) < 0) {
 		printk("network dump device driver registration failed\n");
Binary files linux.orig/drivers/dump/.dump_netdev.c.swp and linux+np/drivers/dump/.dump_netdev.c.swp differ
diff -urNp linux.orig/include/linux/dumpdev.h linux+np/include/linux/dumpdev.h
--- linux.orig/include/linux/dumpdev.h	2003-11-13 05:56:17.000000000 +0530
+++ linux+np/include/linux/dumpdev.h	2003-11-13 05:57:07.000000000 +0530
@@ -21,6 +21,7 @@
 
 #include <linux/kernel.h>
 #include <linux/wait.h>
+#include <linux/netpoll.h>
 #include <linux/bio.h>
 
 /* Determined by the dump target (device) type */
@@ -48,6 +49,7 @@ struct dump_dev {
 	struct dump_dev_ops *ops;
 	struct list_head list;
 	loff_t curr_offset;
+	struct netpoll np;
 };
 
 /*
Binary files linux.orig/index.1 and linux+np/index.1 differ
diff -urNp linux.orig/net/Kconfig linux+np/net/Kconfig
--- linux.orig/net/Kconfig	2003-11-13 05:56:14.000000000 +0530
+++ linux+np/net/Kconfig	2003-11-13 05:57:07.000000000 +0530
@@ -671,7 +671,7 @@ source "net/irda/Kconfig"
 source "net/bluetooth/Kconfig"
 
 config NETPOLL
-	def_bool NETCONSOLE
+	def_bool NETCONSOLE || CRASH_DUMP_NETDEV
 
 config NETPOLL_RX
 	bool "Netpoll support for trapping incoming packets"

-- 
Thanks & Regards
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-5044632

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: LKCD Network dump over netpoll patch (2.6.0-test9)
  2003-11-11  0:52 ` Matt Mackall
@ 2003-11-14  4:57   ` Prasanna S Panchamukhi
  2003-11-14  5:22     ` Prasanna S Panchamukhi
  0 siblings, 1 reply; 5+ messages in thread
From: Prasanna S Panchamukhi @ 2003-11-14  4:57 UTC (permalink / raw)
  To: Matt Mackall; +Cc: linux-kernel, lkcd-devel, suparna, prasanna

Hi,

Below is the patch to netpoll. This patch modifies the netpoll_poll() routine 
to include the zap_completion_queue() routine as suggested by Matt Mackall.

diff -urNp linux.orig/net/core/netpoll.c linux-2.6.0-test9/net/core/netpoll.c
--- linux.orig/net/core/netpoll.c	2003-11-13 05:22:20.000000000 +0530
+++ linux-2.6.0-test9/net/core/netpoll.c	2003-11-13 05:46:46.000000000 +0530
@@ -66,6 +66,7 @@ void netpoll_poll(struct netpoll *np)
 	if(trapped && np->dev->poll &&
 	   test_bit(__LINK_STATE_RX_SCHED, &np->dev->state))
 		np->dev->poll(np->dev, &budget);
+	zap_completion_queue();
 }
 
 static void refill_skbs(void)
@@ -115,8 +116,8 @@ static struct sk_buff * find_skb(struct 
 	unsigned long flags;
 	struct sk_buff *skb = NULL;
 
-repeat:
 	zap_completion_queue();
+repeat:
 	if (nr_skbs < MAX_SKBS)
 		refill_skbs();
 
@@ -165,7 +166,6 @@ repeat:
 		spin_unlock(&np->dev->xmit_lock);
 
 		netpoll_poll(np);
-		zap_completion_queue();
 		goto repeat;
 	}
 
-- 
Thanks & Regards
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-5044632

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: LKCD Network dump over netpoll patch (2.6.0-test9)
  2003-11-10 14:07 Prasanna S Panchamukhi
@ 2003-11-11  0:52 ` Matt Mackall
  2003-11-14  4:57   ` Prasanna S Panchamukhi
  0 siblings, 1 reply; 5+ messages in thread
From: Matt Mackall @ 2003-11-11  0:52 UTC (permalink / raw)
  To: Prasanna S Panchamukhi; +Cc: lkcd-devel, linux-kernel, suparna

On Mon, Nov 10, 2003 at 07:37:42PM +0530, Prasanna S Panchamukhi wrote:
> Hi,
> 

Hi.

> +		put_unaligned(htonl(reply.nr), (u32 *) (tmp_membuf + 1));
> +		put_unaligned(htonl(reply.code), (u32 *) (tmp_membuf + 5));
> +		put_unaligned(htonl(reply.info), (u32 *) (tmp_membuf + 9));
> +
> +		memcpy((tmp_membuf + HEADER_LEN), buff + offset, 1024);
> +		netpoll_send_udp(np, tmp_membuf, (1024 + HEADER_LEN));

There's quite a few instances of this header business, it could really
stand to be in its own netdump_send(nr, code, info, data) function.

> -			dump_ndev->poll_controller(dump_ndev);
> +			netpoll_poll(&net_dev->np);
>  			zap_completion_queue();
...
> +void zap_completion_queue(void);

Instead of this (missing netpoll_, btw), how about we call
zap_completion_queue inside of netpoll_poll?

-- 
Matt Mackall : http://www.selenic.com : Linux development and consulting

^ permalink raw reply	[flat|nested] 5+ messages in thread

* LKCD Network dump over netpoll patch (2.6.0-test9)
@ 2003-11-10 14:07 Prasanna S Panchamukhi
  2003-11-11  0:52 ` Matt Mackall
  0 siblings, 1 reply; 5+ messages in thread
From: Prasanna S Panchamukhi @ 2003-11-10 14:07 UTC (permalink / raw)
  To: lkcd-devel; +Cc: linux-kernel, mpm, suparna

Hi,

Please ignore by previous mail. Below is the actual lkcd-netpoll.patch
This patch includes LKCD networkdump code changes over netpoll API's for 
kernel version 2.6.0-test9. Both the netconsole and network dumping can be 
achieved. Procedure for netdumping is explained below:

1. Apply the netpoll-core.patch and netconsole.patch (http://www.selenic.com/netpoll/)
2. Download the LKCD code from the cvs using
	cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/lkcd login (presee enter key for passwd)
 
	cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/lkcd co 2.6  
	cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/lkcd co lkcdutils 

3. Copy the lkcd files to the kernel source directory.
	#cp -r ../2.6/* ./linux-2.6-test9/
4. Apply the kernel-changes.patch from the 2.6/patches directory.
5. Apply the pollcontroller.patch from the 2.6/patches 
	directory now.
6. Apply the lkcd-netpoll.patch(below)
7. Buid the kernel with LKCD network dumping enabled ;reboot and insert the dump_netdev.o module.

8. You also need to install and setup the lkcdutils.
	#./configure; make ; make install.
	#cd netdump
	#make; make install.
9. Configure the netdump fileds in the /etc/sysconfig/dump file.
	#you need to specify the local port,remote port, local ip, target ip and device name for netdump. 
	eg :	DUMP_ACTIVE=1
		DUMPDEV=eth0
		DUMPDIR=/var/log/dump
		DUMP_SAVE=1
		DUMP_LEVEL=2
		DUMP_FLAGS=0x40000000 
		DUMP_COMPRESS=0
		PANIC_TIMEOUT=5

		TARGET_HOST=9.182.14.40 #h set this to vaild hostname/IP
		TARGET_PORT=6688
		SOURCE_PORT=6688
		ETH_ADDRESS=00:07:95:E6:08:FB

10. Run lkcd config and now you can try test dumps..


diff -urNp linux.orig/drivers/dump/dump_netdev.c linux-2.6.0-test9/drivers/dump/dump_netdev.c
--- linux.orig/drivers/dump/dump_netdev.c	2003-11-11 06:14:57.000000000 +0530
+++ linux-2.6.0-test9/drivers/dump/dump_netdev.c	2003-11-11 09:50:56.952449656 +0530
@@ -11,6 +11,8 @@
  * Nov 2002 - Bharata B. Rao <bharata@in.ibm.com>
  * 	Innumerable code cleanups, simplification and some fixes.
  *	Netdump configuration done by ioctl instead of using module parameters.
+ * Oct 2003 - Prasanna S Panchamukhi <prasanna@in.ibm.com>
+ *	Netdump code modified to use Netpoll API's.
  *
  * Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
  * Copyright (C) 2002 International Business Machines Corp. 
@@ -26,24 +28,14 @@
 #include <linux/module.h>
 #include <linux/dump.h>
 #include <linux/dump_netdev.h>
-#include <linux/percpu.h>
 
 #include <asm/unaligned.h>
 
+
 static int startup_handshake;
 static int page_counter;
-static struct net_device *dump_ndev;
-static struct in_device *dump_in_dev;
-static u16 source_port, target_port;
-static u32 source_ip, target_ip;
-static unsigned char daddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ;
-static spinlock_t dump_skb_lock = SPIN_LOCK_UNLOCKED;
-static int dump_nr_skbs;
-static struct sk_buff *dump_skb;
 static unsigned long flags_global;
 static int netdump_in_progress;
-static char device_name[IFNAMSIZ];
-
 /*
  * security depends on the trusted path between the netconsole
  * server and netconsole client, since none of the packets are
@@ -51,312 +43,27 @@ static char device_name[IFNAMSIZ];
  * against spoofing.
  */
 static u64 dump_magic;
-
-#define MAX_UDP_CHUNK 1460
-#define MAX_PRINT_CHUNK (MAX_UDP_CHUNK-HEADER_LEN)
-
 /*
  * We maintain a small pool of fully-sized skbs,
  * to make sure the message gets out even in
  * extreme OOM situations.
  */
-#define DUMP_MAX_SKBS 32
-
-#define MAX_SKB_SIZE \
-		(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
-				sizeof(struct iphdr) + sizeof(struct ethhdr))
-
-static void
-dump_refill_skbs(void)
-{
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dump_skb_lock, flags);
-	while (dump_nr_skbs < DUMP_MAX_SKBS) {
-		skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
-		if (!skb)
-			break;
-		if (dump_skb)
-			skb->next = dump_skb;
-		else
-			skb->next = NULL;
-		dump_skb = skb;
-		dump_nr_skbs++;
-	}
-	spin_unlock_irqrestore(&dump_skb_lock, flags);
-}
-
-static struct
-sk_buff * dump_get_skb(void)
-{
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dump_skb_lock, flags);
-	skb = dump_skb;
-	if (skb) {
-		dump_skb = skb->next;
-		skb->next = NULL;
-		dump_nr_skbs--;
-	}
-	spin_unlock_irqrestore(&dump_skb_lock, flags);
-        
-	return skb;
-}
-
-/*
- * Zap completed output skbs.
- */
-static void
-zap_completion_queue(void)
-{
-	int count;
-	unsigned long flags;
-	struct softnet_data *sd;
-
-        count=0;
-	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;
-			__kfree_skb(skb);
-			count++;
-			if (count > 10000)
-				printk("Error in sk list\n");
-		}
-	}
-}
-
-static void
-dump_send_skb(struct net_device *dev, const char *msg, unsigned int msg_len,
-		reply_t *reply)
-{
-	int once = 1;
-	int total_len, eth_len, ip_len, udp_len, count = 0;
-	struct sk_buff *skb;
-	struct udphdr *udph;
-	struct iphdr *iph;
-	struct ethhdr *eth; 
-
-	udp_len = msg_len + HEADER_LEN + sizeof(*udph);
-	ip_len = eth_len = udp_len + sizeof(*iph);
-	total_len = eth_len + ETH_HLEN;
-
-repeat_loop:
-	zap_completion_queue();
-	if (dump_nr_skbs < DUMP_MAX_SKBS)
-		dump_refill_skbs();
-
-	skb = alloc_skb(total_len, GFP_ATOMIC);
-	if (!skb) {
-		skb = dump_get_skb();
-		if (!skb) {
-			count++;
-			if (once && (count == 1000000)) {
-				printk("possibly FATAL: out of netconsole "
-					"skbs!!! will keep retrying.\n");
-				once = 0;
-			}
-			dev->poll_controller(dev);
-			goto repeat_loop;
-		}
-	}
-
-	atomic_set(&skb->users, 1);
-	skb_reserve(skb, total_len - msg_len - HEADER_LEN);
-	skb->data[0] = NETCONSOLE_VERSION;
-
-	put_unaligned(htonl(reply->nr), (u32 *) (skb->data + 1));
-	put_unaligned(htonl(reply->code), (u32 *) (skb->data + 5));
-	put_unaligned(htonl(reply->info), (u32 *) (skb->data + 9));
-
-	memcpy(skb->data + HEADER_LEN, msg, msg_len);
-	skb->len += msg_len + HEADER_LEN;
-
-	udph = (struct udphdr *) skb_push(skb, sizeof(*udph));
-	udph->source = source_port;
-	udph->dest = target_port;
-	udph->len = htons(udp_len);
-	udph->check = 0;
-
-	iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
-
-	iph->version  = 4;
-	iph->ihl      = 5;
-	iph->tos      = 0;
-	iph->tot_len  = htons(ip_len);
-	iph->id       = 0;
-	iph->frag_off = 0;
-	iph->ttl      = 64;
-	iph->protocol = IPPROTO_UDP;
-	iph->check    = 0;
-	iph->saddr    = source_ip;
-	iph->daddr    = target_ip;
-	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
-	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-
-	eth->h_proto = htons(ETH_P_IP);
-	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-	memcpy(eth->h_dest, daddr, dev->addr_len);
-
-	count=0;
-repeat_poll:
-	spin_lock(&dev->xmit_lock);
-	dev->xmit_lock_owner = smp_processor_id();
-
-	count++;
-
-
-	if (netif_queue_stopped(dev)) {
-		dev->xmit_lock_owner = -1;
-		spin_unlock(&dev->xmit_lock);
-
-		dev->poll_controller(dev);
-		zap_completion_queue();
-
-
-		goto repeat_poll;
-	}
-
-	dev->hard_start_xmit(skb, dev);
-
-	dev->xmit_lock_owner = -1;
-	spin_unlock(&dev->xmit_lock);
-}
-
-static unsigned short
-udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr,
-	       	unsigned long base)
-{
-	return csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base);
-}
-
-static int
-udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
-			     unsigned short ulen, u32 saddr, u32 daddr)
-{
-	if (uh->check == 0) {
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else if (skb->ip_summed == CHECKSUM_HW) {
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
-			return 0;
-		skb->ip_summed = CHECKSUM_NONE;
-	}
-	if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-		skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen,
-				IPPROTO_UDP, 0);
-	/* Probably, we should checksum udp header (it should be in cache
-	 * in any case) and data in tiny packets (< rx copybreak).
-	 */
-	return 0;
-}
-
-static __inline__ int
-__udp_checksum_complete(struct sk_buff *skb)
-{
-	return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len,
-				skb->csum));
-}
-
-static __inline__
-int udp_checksum_complete(struct sk_buff *skb)
-{
-	return skb->ip_summed != CHECKSUM_UNNECESSARY &&
-		__udp_checksum_complete(skb);
-}
 
+static void rx_hook(struct netpoll *np, int port, char *msg, int size);
 int new_req = 0;
 static req_t req;
 
-static int
-dump_rx_hook(struct sk_buff *skb)
+static void rx_hook(struct netpoll *np, int port, char *msg, int size)
 {
-	int proto;
-	struct iphdr *iph;
-	struct udphdr *uh;
-	__u32 len, saddr, daddr, ulen;
-	req_t *__req;
-
+	req_t * __req = (req_t *) msg;
 	/* 
 	 * First check if were are dumping or doing startup handshake, if
 	 * not quickly return.
 	 */
-	if (!netdump_in_progress)
-		return NET_RX_SUCCESS;
-
-	if (skb->dev->type != ARPHRD_ETHER)
-		goto out;
-
-	proto = ntohs(skb->mac.ethernet->h_proto);
-	if (proto != ETH_P_IP)
-		goto out;
-
-	if (skb->pkt_type == PACKET_OTHERHOST)
-		goto out;
-
-	if (skb_shared(skb))
-		goto out;
-
-	 /* IP header correctness testing: */
-	iph = (struct iphdr *)skb->data;
-	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-		goto out;
-
-	if (iph->ihl < 5 || iph->version != 4)
-		goto out;
-
-	if (!pskb_may_pull(skb, iph->ihl*4))
-		goto out;
-
-	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;
-
-	saddr = iph->saddr;
-	daddr = iph->daddr;
-	if (iph->protocol != IPPROTO_UDP)
-		goto out;
-
-	if (source_ip != daddr)
-		goto out;
-
-	if (target_ip != saddr)
-		goto out;
 
-	len -= iph->ihl*4;
-	uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
-	ulen = ntohs(uh->len);
-
-	if (ulen != len || ulen < (sizeof(*uh) + sizeof(*__req)))
-		goto out;
-
-	if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
-		goto out;
-
-	if (udp_checksum_complete(skb))
-		goto out;
-
-	if (source_port != uh->dest)
-		goto out;
-
-	if (target_port != uh->source)
-		goto out;
+	if (!netdump_in_progress)
+		return ;
 
-	__req = (req_t *)(uh + 1);
 	if ((ntohl(__req->command) != COMM_GET_MAGIC) &&
 	    (ntohl(__req->command) != COMM_HELLO) &&
 	    (ntohl(__req->command) != COMM_START_WRITE_NETDUMP_ACK) &&
@@ -371,17 +78,18 @@ dump_rx_hook(struct sk_buff *skb)
 	req.nr = ntohl(__req->nr);
 	new_req = 1;
 out:
-	return NET_RX_DROP;
+	return ;
 }
 
+
+static	char tmp_membuf[1024 + HEADER_LEN +1];
 static void
-dump_send_mem(struct net_device *dev, req_t *req, const char* buff, size_t len)
+dump_send_mem(struct netpoll *np, req_t *req, const char* buff, size_t len)
 {
 	int i;
 
 	int nr_chunks = len/1024;
 	reply_t reply;
-	
 	reply.nr = req->nr;
 	reply.info = 0;
 
@@ -391,7 +99,15 @@ dump_send_mem(struct net_device *dev, re
 		unsigned int offset = i*1024;
 		reply.code = REPLY_MEM;
 		reply.info = offset;
-                dump_send_skb(dev, buff + offset, 1024, &reply);
+		tmp_membuf[0] = NETCONSOLE_VERSION;
+
+		put_unaligned(htonl(reply.nr), (u32 *) (tmp_membuf + 1));
+		put_unaligned(htonl(reply.code), (u32 *) (tmp_membuf + 5));
+		put_unaligned(htonl(reply.info), (u32 *) (tmp_membuf + 9));
+
+		memcpy((tmp_membuf + HEADER_LEN), buff + offset, 1024);
+		netpoll_send_udp(np, tmp_membuf, (1024 + HEADER_LEN));
+		
 	}
 }
 
@@ -409,28 +125,33 @@ dump_handshake(struct dump_dev *net_dev)
 {
 	char tmp[200];
 	reply_t reply;
-	int i, j;
+	int i, j, slen;
 
 	if (startup_handshake) {
-		sprintf(tmp, "NETDUMP start, waiting for start-ACK.\n");
+		sprintf((tmp + HEADER_LEN), "NETDUMP start, waiting for start-ACK.\n");
 		reply.code = REPLY_START_NETDUMP;
 		reply.nr = 0;
 		reply.info = 0;
 	} else {
-		sprintf(tmp, "NETDUMP start, waiting for start-ACK.\n");
+		sprintf((tmp + HEADER_LEN), "NETDUMP start, waiting for start-ACK.\n");
 		reply.code = REPLY_START_WRITE_NETDUMP;
 		reply.nr = net_dev->curr_offset;
 		reply.info = net_dev->curr_offset;
 	}
+	slen= strlen("NETDUMP start, waiting for start-ACK.\n");
+	tmp[0] = NETCONSOLE_VERSION;
+
+	put_unaligned(htonl(reply.nr), (u32 *) (tmp + 1));
+	put_unaligned(htonl(reply.code), (u32 *) (tmp + 5));
+	put_unaligned(htonl(reply.info), (u32 *) (tmp + 9));
 	
 	/* send 300 handshake packets before declaring failure */
 	for (i = 0; i < 300; i++) {
-		dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
-
+		netpoll_send_udp(&net_dev->np, tmp, (slen + HEADER_LEN));
 		/* wait 1 sec */
 		for (j = 0; j < 10000; j++) {
 			udelay(100);
-			dump_ndev->poll_controller(dump_ndev);
+			netpoll_poll(&net_dev->np);
 			zap_completion_queue();
 			if (new_req)
 				break;
@@ -474,10 +195,9 @@ do_netdump(struct dump_dev *net_dev, con
 	reply_t reply;
 	char tmp[200];
 	ssize_t  ret = 0;
-	int repeatCounter, counter, total_loop;
+	int repeatCounter, counter, total_loop, slen;
 	
 	netdump_in_progress = 1;
-
 	if (dump_handshake(net_dev) < 0) {
 		printk("network dump failed due to handshake failure\n");
 		goto out;
@@ -496,8 +216,9 @@ do_netdump(struct dump_dev *net_dev, con
 	repeatCounter = 0;
 	total_loop = 0;
 	while (1) {
+	
                 if (!new_req) {
-			dump_ndev->poll_controller(dump_ndev);
+			netpoll_poll(&net_dev->np);
 			zap_completion_queue();
 		}
 		if (!new_req) {
@@ -530,7 +251,7 @@ do_netdump(struct dump_dev *net_dev, con
 			break;
 
 		case COMM_SEND_MEM:
-			dump_send_mem(dump_ndev, &req, buff, len);
+			dump_send_mem(&net_dev->np, &req, buff, len);
 			break;
 
 		case COMM_EXIT:
@@ -539,20 +260,34 @@ do_netdump(struct dump_dev *net_dev, con
 			goto out;
 
 		case COMM_HELLO:
-			sprintf(tmp, "Hello, this is netdump version "
+			sprintf((tmp), "Hello, this is netdump version "
+					"0.%02d\n", NETCONSOLE_VERSION);
+			slen= strlen(tmp);
+			sprintf((tmp + HEADER_LEN), "Hello, this is netdump version "
 					"0.%02d\n", NETCONSOLE_VERSION);
 			reply.code = REPLY_HELLO;
 			reply.nr = req.nr;
                         reply.info = net_dev->curr_offset;
-			dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+			tmp[0] = NETCONSOLE_VERSION;
+
+			put_unaligned(htonl(reply.nr), (u32 *) (tmp + 1));
+			put_unaligned(htonl(reply.code), (u32 *) (tmp + 5));
+			put_unaligned(htonl(reply.info), (u32 *) (tmp + 9));
+			netpoll_send_udp(&net_dev->np, tmp, slen + HEADER_LEN);
 			break;
 
 		case COMM_GET_PAGE_SIZE:
-			sprintf(tmp, "PAGE_SIZE: %ld\n", PAGE_SIZE);
+			sprintf((tmp), "PAGE_SIZE: %ld\n", PAGE_SIZE);
+			slen = strlen(tmp);
+			sprintf((tmp + HEADER_LEN), "PAGE_SIZE: %ld\n", PAGE_SIZE);
 			reply.code = REPLY_PAGE_SIZE;
 			reply.nr = req.nr;
 			reply.info = PAGE_SIZE;
-			dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+			tmp[0] = NETCONSOLE_VERSION;
+			put_unaligned(htonl(reply.nr), (u32 *) (tmp + 1));
+			put_unaligned(htonl(reply.code), (u32 *) (tmp + 5));
+			put_unaligned(htonl(reply.info), (u32 *) (tmp + 9));
+			netpoll_send_udp(&net_dev->np, tmp, slen + HEADER_LEN);
 			break;
 
 		case COMM_GET_NR_PAGES:
@@ -560,25 +295,48 @@ do_netdump(struct dump_dev *net_dev, con
 			reply.nr = req.nr;
 			reply.info = num_physpages;
                         reply.info = page_counter;
-			sprintf(tmp, "Number of pages: %ld\n", num_physpages);
-			dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+			sprintf((tmp), "Number of pages: %ld\n", num_physpages);
+			slen = strlen(tmp);
+			sprintf((tmp + HEADER_LEN), "Number of pages: %ld\n", num_physpages);
+			tmp[0] = NETCONSOLE_VERSION;
+
+			put_unaligned(htonl(reply.nr), (u32 *) (tmp + 1));
+			put_unaligned(htonl(reply.code), (u32 *) (tmp + 5));
+			put_unaligned(htonl(reply.info), (u32 *) (tmp + 9));
+			netpoll_send_udp(&net_dev->np, tmp, slen + HEADER_LEN);
 			break;
 
 		case COMM_GET_MAGIC:
 			reply.code = REPLY_MAGIC;
 			reply.nr = req.nr;
 			reply.info = NETCONSOLE_VERSION;
-			dump_send_skb(dump_ndev, (char *)&dump_magic,
-					sizeof(dump_magic), &reply);
+			sprintf((tmp), (char *)&dump_magic, sizeof(dump_magic));
+			slen = strlen(tmp);
+			tmp[0] = NETCONSOLE_VERSION;
+
+			put_unaligned(htonl(reply.nr), (u32 *) (tmp + 1));
+			put_unaligned(htonl(reply.code), (u32 *) (tmp + 5));
+			put_unaligned(htonl(reply.info), (u32 *) (tmp + 9));
+			sprintf((tmp + HEADER_LEN), (char *)&dump_magic, sizeof(dump_magic));
+			
+			netpoll_send_udp(&net_dev->np, tmp, slen + HEADER_LEN);
 			break;
 
 		default:
 			reply.code = REPLY_ERROR;
 			reply.nr = req.nr;
 			reply.info = req.command;
-			sprintf(tmp, "Got unknown command code %d!\n",
+			sprintf((tmp), "Got unknown command code %d!\n",
+					req.command);
+			slen = strlen(tmp);
+			tmp[0] = NETCONSOLE_VERSION;
+
+			put_unaligned(htonl(reply.nr), (u32 *) (tmp + 1));
+			put_unaligned(htonl(reply.code), (u32 *) (tmp + 5));
+			put_unaligned(htonl(reply.info), (u32 *) (tmp + 9));
+			sprintf((tmp + HEADER_LEN), "Got unknown command code %d!\n",
 					req.command);
-			dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+			netpoll_send_udp(&net_dev->np, tmp, slen + HEADER_LEN);
 			break;
 		}
 	}
@@ -588,47 +346,42 @@ out:
 }
 
 static int
-dump_validate_config(void)
+dump_validate_config(struct netpoll *np)
 {
-	source_ip = dump_in_dev->ifa_list->ifa_local;
-	if (!source_ip) {
+	if (!np->local_ip) {
 		printk("network device %s has no local address, "
-				"aborting.\n", device_name);
+				"aborting.\n", np->name);
 		return -1;
 	}
 
-#define IP(x) ((unsigned char *)&source_ip)[x]
+		printk("before printing ip\n");
+#define IP(x) ((unsigned char *)&np->local_ip)[x]
 	printk("Source %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
 #undef IP
+		printk("afterprinting ip\n");
 
-	if (!source_port) {
+	if (!np->local_port) {
 		printk("source_port parameter not specified, aborting.\n");
 		return -1;
 	}
-	printk(":%i\n", source_port);
-	source_port = htons(source_port);
-
-	if (!target_ip) {
+	if (!np->remote_ip) {
 		printk("target_ip parameter not specified, aborting.\n");
 		return -1;
 	}
 
-#define IP(x) ((unsigned char *)&target_ip)[x]
+	np->remote_ip = ntohl(np->remote_ip);
+#define IP(x) ((unsigned char *)&np->remote_ip)[x]
 	printk("Target %d.%d.%d.%d", IP(0), IP(1), IP(2), IP(3));
 #undef IP
-
-	if (!target_port) {
+	if (!np->remote_port) {
 		printk("target_port parameter not specified, aborting.\n");
 		return -1;
 	}
-	printk(":%i\n", target_port);
-	target_port = htons(target_port);
-
 	printk("Target Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x",
-		daddr[0], daddr[1], daddr[2], daddr[3], daddr[4], daddr[5]);
+		np->remote_mac[0], np->remote_mac[1], np->remote_mac[2], np->remote_mac[3], np->remote_mac[4], np->remote_mac[5]);
 
-	if ((daddr[0] & daddr[1] & daddr[2] & daddr[3] & daddr[4] & 
-				daddr[5]) == 255)
+	if ((np->remote_mac[0] & np->remote_mac[1] & np->remote_mac[2] & np->remote_mac[3] & np->remote_mac[4] & 
+				np->remote_mac[5]) == 255)
 		printk("(Broadcast)");
 	printk("\n");
 	return 0;
@@ -645,41 +398,17 @@ dump_net_open(struct dump_dev *net_dev, 
 {
 	int retval = 0;
 
+	
 	/* get the interface name */
-	if (copy_from_user(device_name, (void *)arg, IFNAMSIZ))
+	if (copy_from_user(net_dev->np.dev_name, (void *)arg, IFNAMSIZ))
 		return -EFAULT;
+	net_dev->np.rx_hook = rx_hook;	
+	retval = netpoll_setup(&net_dev->np);
 
-	if (!(dump_ndev = dev_get_by_name(device_name))) {
-		printk("network device %s does not exist, aborting.\n",
-				device_name);
-		return -ENODEV;
-	}
-
-	if (!dump_ndev->poll_controller) {
-		printk("network device %s does not implement polling yet, "
-				"aborting.\n", device_name);
-		retval = -1; /* return proper error */
-		goto err1;
-	}
-
-	if (!(dump_in_dev = in_dev_get(dump_ndev))) {
-		printk("network device %s is not an IP protocol device, "
-				"aborting.\n", device_name);
-		retval = -EINVAL;
-		goto err1;
-	}
-
-	if ((retval = dump_validate_config()) < 0)
-		goto err2;
-
+	dump_validate_config(&net_dev->np);
 	net_dev->curr_offset = 0;
 	printk("Network device %s successfully configured for dumping\n",
-			device_name);
-	return retval;
-err2:
-	in_dev_put(dump_in_dev);
-err1:
-	dev_put(dump_ndev);	
+			net_dev->np.dev_name);
 	return retval;
 }
 
@@ -690,10 +419,8 @@ err1:
 static int
 dump_net_release(struct dump_dev *net_dev)
 {
-	if (dump_in_dev)
-		in_dev_put(dump_in_dev);
-	if (dump_ndev)
-		dev_put(dump_ndev);
+	
+	netpoll_cleanup(&net_dev->np);
 	return 0;
 }
 
@@ -704,11 +431,11 @@ dump_net_release(struct dump_dev *net_de
 static int
 dump_net_silence(struct dump_dev *net_dev)
 {
+
 	local_irq_save(flags_global);
-	dump_ndev->rx_hook = dump_rx_hook;
         startup_handshake = 1;
 	net_dev->curr_offset = 0;
-	printk("Dumping to network device %s on CPU %d ...\n", device_name,
+	printk("Dumping to network device %s on CPU %d ...\n", net_dev->np.name,
 			smp_processor_id());
 	return 0;
 }
@@ -721,23 +448,26 @@ dump_net_silence(struct dump_dev *net_de
 static int
 dump_net_resume(struct dump_dev *net_dev)
 {
-	int indx;
+	int indx, slen;
 	reply_t reply;
 	char tmp[200];
 
-        if (!dump_ndev)
-		return (0);
-
-	sprintf(tmp, "NETDUMP end.\n");
+	sprintf((tmp), "NETDUMP end.\n");
+	slen = strlen(tmp);
+	sprintf((tmp + HEADER_LEN), "NETDUMP end.\n");
 	for( indx = 0; indx < 6; indx++) {
 		reply.code = REPLY_END_NETDUMP;
 		reply.nr = 0;
 		reply.info = 0;
-		dump_send_skb(dump_ndev, tmp, strlen(tmp), &reply);
+		tmp[0] = NETCONSOLE_VERSION;
+
+		put_unaligned(htonl(reply.nr), (u32 *) (tmp + 1));
+		put_unaligned(htonl(reply.code), (u32 *) (tmp + 5));
+		put_unaligned(htonl(reply.info), (u32 *) (tmp + 9));
+		netpoll_send_udp(&net_dev->np, tmp, slen + HEADER_LEN);
 	}
 	printk("NETDUMP END!\n");
 	local_irq_restore(flags_global);
-	dump_ndev->rx_hook = NULL;
 	startup_handshake = 0;
 	return 0;
 }
@@ -749,11 +479,6 @@ dump_net_resume(struct dump_dev *net_dev
 static  int
 dump_net_seek(struct dump_dev *net_dev, loff_t off)
 {
-	/*
-	 * For now using DUMP_HEADER_OFFSET as hard coded value,
-	 * See dump_block_seekin dump_blockdev.c to know how to
-	 * do this properly.
-	 */
 	net_dev->curr_offset = off;
 	return 0;
 }
@@ -796,16 +521,16 @@ dump_net_ioctl(struct dump_dev *net_dev,
 {
 	switch (cmd) {
 	case DIOSTARGETIP:
-		target_ip = arg;
+		net_dev->np.remote_ip= arg;
 		break;
 	case DIOSTARGETPORT:
-		target_port = (u16)arg;
+		net_dev->np.remote_port = (u16)arg;
 		break;
 	case DIOSSOURCEPORT:
-		source_port = (u16)arg;
+		net_dev->np.local_port = (u16)arg;
 		break;
 	case DIOSETHADDR:
-		return copy_from_user(daddr, (void *)arg, 6);
+		return copy_from_user(net_dev->np.remote_mac, (void *)arg, 6);
 		break;
 	case DIOGTARGETIP:
 	case DIOGTARGETPORT:
@@ -833,14 +558,19 @@ struct dump_dev_ops dump_netdev_ops = {
 static struct dump_dev default_dump_netdev = {
 	.type_name = "networkdev", 
 	.ops = &dump_netdev_ops, 
-	.curr_offset = 0
+	.curr_offset = 0,
+	.np.name = "netdump",
+	.np.dev_name = "eth0",
+	.np.rx_hook = rx_hook,
+	.np.local_port = 6688,
+	.np.remote_port = 6688,
+	.np.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
 };
 
 static int __init
 dump_netdev_init(void)
 {
         default_dump_netdev.curr_offset = 0;
-
 	if (dump_register_device(&default_dump_netdev) < 0) {
 		printk("network dump device driver registration failed\n");
 		return -1;
diff -urNp linux.orig/include/linux/dumpdev.h linux-2.6.0-test9/include/linux/dumpdev.h
--- linux.orig/include/linux/dumpdev.h	2003-11-11 06:15:18.000000000 +0530
+++ linux-2.6.0-test9/include/linux/dumpdev.h	2003-11-11 09:50:57.000000000 +0530
@@ -21,6 +21,7 @@
 
 #include <linux/kernel.h>
 #include <linux/wait.h>
+#include <linux/netpoll.h>
 #include <linux/bio.h>
 
 /* Determined by the dump target (device) type */
@@ -48,6 +49,7 @@ struct dump_dev {
 	struct dump_dev_ops *ops;
 	struct list_head list;
 	loff_t curr_offset;
+	struct netpoll np;
 };
 
 /*
diff -urNp linux.orig/include/linux/netpoll.h linux-2.6.0-test9/include/linux/netpoll.h
--- linux.orig/include/linux/netpoll.h	2003-11-11 06:15:18.000000000 +0530
+++ linux-2.6.0-test9/include/linux/netpoll.h	2003-11-11 09:50:57.000000000 +0530
@@ -33,6 +33,7 @@ int netpoll_trap(void);
 void netpoll_set_trap(int trap);
 void netpoll_cleanup(struct netpoll *np);
 int netpoll_rx(struct sk_buff *skb);
+void zap_completion_queue(void);
 
 
 #endif
diff -urNp linux.orig/net/core/netpoll.c linux-2.6.0-test9/net/core/netpoll.c
--- linux.orig/net/core/netpoll.c	2003-11-11 06:15:16.000000000 +0530
+++ linux-2.6.0-test9/net/core/netpoll.c	2003-11-11 09:51:05.000000000 +0530
@@ -86,7 +86,7 @@ static void refill_skbs(void)
 	spin_unlock_irqrestore(&skb_list_lock, flags);
 }
 
-static void zap_completion_queue(void)
+void zap_completion_queue(void)
 {
 	unsigned long flags;
 	struct softnet_data *sd = &get_cpu_var(softnet_data);
@@ -634,3 +634,5 @@ EXPORT_SYMBOL(netpoll_cleanup);
 EXPORT_SYMBOL(netpoll_send_skb);
 EXPORT_SYMBOL(netpoll_send_udp);
 EXPORT_SYMBOL(netpoll_poll);
+EXPORT_SYMBOL(zap_completion_queue);
+
diff -urNp linux.orig/net/Kconfig linux-2.6.0-test9/net/Kconfig
--- linux.orig/net/Kconfig	2003-11-11 06:15:17.000000000 +0530
+++ linux-2.6.0-test9/net/Kconfig	2003-11-11 09:51:05.000000000 +0530
@@ -671,7 +671,7 @@ source "net/irda/Kconfig"
 source "net/bluetooth/Kconfig"
 
 config NETPOLL
-	def_bool NETCONSOLE
+	def_bool NETCONSOLE || CRASH_DUMP_NETDEV
 
 config NETPOLL_RX
 	bool "Netpoll support for trapping incoming packets"
-- 
Thanks & Regards
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-11-14  5:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-10 13:54 LKCD Network dump over netpoll patch (2.6.0-test9) Prasanna S Panchamukhi
2003-11-10 14:07 Prasanna S Panchamukhi
2003-11-11  0:52 ` Matt Mackall
2003-11-14  4:57   ` Prasanna S Panchamukhi
2003-11-14  5:22     ` Prasanna S Panchamukhi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).