Netdev List
 help / color / mirror / Atom feed
* Re: PATCH 2.6.17-rc5 tulip free_irq() called too late
From: Grant Grundler @ 2006-06-08 17:01 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Grant Grundler, Andrew Morton, netdev, Val Henson
In-Reply-To: <44883778.8000209@pobox.com>

On Thu, Jun 08, 2006 at 10:43:04AM -0400, Jeff Garzik wrote:
...
> Perhaps cp_close() in 8139cp.c could be an example of a good ordering? 
> It stops the chip, syncs irqs, frees irq, then frees [thus unmapping] 
> the rings.

Here is a new patch that moves free_irq() into tulip_down().
The resulting code is structured the same as cp_close().

While I believe the code is correct, I'm not real happy
that tulip_up() and tulip_down() don't both deal with IRQs.
(ie not symetrical). Oh well, I can submit another patch
for that if Val doesn't want to wrangle that herself.

This is compile tested only.
I'll drop it on ia64/parisc servers later and retest.

thanks,
grant


Index: drivers/net/tulip/tulip_core.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/net/tulip/tulip_core.c,v
retrieving revision 1.35
diff -u -p -r1.35 tulip_core.c
--- drivers/net/tulip/tulip_core.c	23 Apr 2006 15:18:28 -0000	1.35
+++ drivers/net/tulip/tulip_core.c	8 Jun 2006 16:25:43 -0000
@@ -18,11 +18,11 @@
 
 #define DRV_NAME	"tulip"
 #ifdef CONFIG_TULIP_NAPI
-#define DRV_VERSION    "1.1.13-NAPI" /* Keep at least for test */
+#define DRV_VERSION    "1.1.14-NAPI" /* Keep at least for test */
 #else
-#define DRV_VERSION	"1.1.13"
+#define DRV_VERSION	"1.1.14"
 #endif
-#define DRV_RELDATE	"December 15, 2004"
+#define DRV_RELDATE	"May 6, 2006"
 
 
 #include <linux/module.h>
@@ -743,6 +745,11 @@ static void tulip_down (struct net_devic
 	/* Stop the Tx and Rx processes. */
 	tulip_stop_rxtx(tp);
 
+	spin_unlock_irqrestore (&tp->lock, flags);
+
+	synchronize_irq(dev->irq);
+	free_irq (dev->irq, dev);
+
 	/* prepare receive buffers */
 	tulip_refill_rx(dev);
 
@@ -752,7 +759,6 @@ static void tulip_down (struct net_devic
 	if (ioread32 (ioaddr + CSR6) != 0xffffffff)
 		tp->stats.rx_missed_errors += ioread32 (ioaddr + CSR8) & 0xffff;
 
-	spin_unlock_irqrestore (&tp->lock, flags);
 
 	init_timer(&tp->timer);
 	tp->timer.data = (unsigned long)dev;
@@ -774,14 +780,13 @@ static int tulip_close (struct net_devic
 	int i;
 
 	netif_stop_queue (dev);
 
 	tulip_down (dev);
 
 	if (tulip_debug > 1)
 		printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
 			dev->name, ioread32 (ioaddr + CSR5));
 
-	free_irq (dev->irq, dev);
 
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
@@ -1750,7 +1757,6 @@ static int tulip_suspend (struct pci_dev
 		tulip_down(dev);
 
 	netif_device_detach(dev);
-	free_irq(dev->irq, dev);
 
 	pci_save_state(pdev);
 	pci_disable_device(pdev);

^ permalink raw reply

* Netchannels: netchannel vs. socket. 2:0.
From: Evgeniy Polyakov @ 2006-06-08 17:15 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev

After some enhancements made for netchannel subsystem I'm pleased to
announce, that netchannel subsystem outperforms existing layered design
both in CPU usage and network speed.

Well, after such pretentious introduction I want to cool things down.
CPU usage is about 1-2% less for netchannels and network performance is
about 1-2 MB higher and sometimes exceeds 84 MB/sec which, I think, 
is maximum for given network setup (e1000 receive, r8169 send, 1500 MTU).

It is stable and 100% reproductible result.

Performance graph and patch are attached.

Interesting note, that netchannel copy_to_user() setup slightly 
outperforms memcpy() setup.

I have some doubts that stock socket TCP code was used in Van Jacobson 
netchannel implementation, especially in the final benchmarks, because
of his words about userspace TCP processing, which sometimes pushes to read 
RFC 793 and do some coding...


Previous patches, userspace utility, design and implementatin details
can be found at project's homepage [1].

1. Netchannel homepage.
http://tservice.net.ru/~s0mbre/old/?section=projects&item=netchannel

Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>

diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index f48bef1..7a4a758 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -315,3 +315,5 @@ ENTRY(sys_call_table)
 	.long sys_splice
 	.long sys_sync_file_range
 	.long sys_tee			/* 315 */
+	.long sys_vmsplice
+	.long sys_netchannel_control
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 5a92fed..fdfb997 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -696,4 +696,5 @@ ia32_sys_call_table:
 	.quad sys_sync_file_range
 	.quad sys_tee
 	.quad compat_sys_vmsplice
+	.quad sys_netchannel_control
 ia32_syscall_end:		
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index eb4b152..777cd85 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -322,8 +322,9 @@
 #define __NR_sync_file_range	314
 #define __NR_tee		315
 #define __NR_vmsplice		316
+#define __NR_netchannel_control	317
 
-#define NR_syscalls 317
+#define NR_syscalls 318
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index feb77cb..08c230e 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -617,8 +617,10 @@ __SYSCALL(__NR_tee, sys_tee)
 __SYSCALL(__NR_sync_file_range, sys_sync_file_range)
 #define __NR_vmsplice		278
 __SYSCALL(__NR_vmsplice, sys_vmsplice)
+#define __NR_netchannel_control	279
+__SYSCALL(__NR_vmsplice, sys_netchannel_control)
 
-#define __NR_syscall_max __NR_vmsplice
+#define __NR_syscall_max __NR_netchannel_control
 
 #ifndef __NO_STUBS
 
diff --git a/include/linux/netchannel.h b/include/linux/netchannel.h
new file mode 100644
index 0000000..ed426e6
--- /dev/null
+++ b/include/linux/netchannel.h
@@ -0,0 +1,118 @@
+/*
+ * 	netchannel.h
+ * 
+ * 2006 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __NETCHANNEL_H
+#define __NETCHANNEL_H
+
+#include <linux/types.h>
+
+enum netchannel_commands {
+	NETCHANNEL_CREATE = 0,
+	NETCHANNEL_REMOVE,
+	NETCHANNEL_BIND,
+	NETCHANNEL_READ,
+	NETCHANNEL_DUMP,
+};
+
+enum netchannel_type {
+	NETCHANNEL_COPY_USER = 0,
+	NETCHANNEL_MMAP,
+	NETCHANEL_VM_HACK,
+};
+
+struct unetchannel
+{
+	__u32			src, dst;		/* source/destination hashes */
+	__u16			sport, dport;		/* source/destination ports */
+	__u8			proto;			/* IP protocol number */
+	__u8			type;			/* Netchannel type */
+	__u8			memory_limit_order;	/* Memor limit order */
+	__u8			init_stat_work;		/* Start statistic dumping */
+};
+
+struct unetchannel_control
+{
+	struct unetchannel	unc;
+	__u32			cmd;
+	__u32			len;
+	__u32			flags;
+	__u32			timeout;
+	unsigned int		fd;
+};
+
+#ifdef __KERNEL__
+
+struct netchannel_stat
+{
+	u64			enter;
+	u64			ready;
+	u64			recv;
+	u64			empty;
+	u64			null;
+	u64			backlog;
+	u64			backlog_err;
+	u64			eat;
+};
+
+struct netchannel
+{
+	struct hlist_node	node;
+	atomic_t		refcnt;
+	struct rcu_head		rcu_head;
+	struct unetchannel	unc;
+	unsigned long		hit;
+
+	struct page *		(*nc_alloc_page)(unsigned int size);
+	void			(*nc_free_page)(struct page *page);
+	int			(*nc_read_data)(struct netchannel *, unsigned int *timeout, unsigned int *len, void *arg);
+
+	struct sk_buff_head 	recv_queue;
+	wait_queue_head_t	wait;
+
+	unsigned int		qlen;
+
+	void			*priv;
+
+	struct inode 		*inode;
+
+	struct work_struct	work;
+
+	struct netchannel_stat	stat;
+};
+
+struct netchannel_cache_head
+{
+	struct hlist_head	head;
+	struct mutex		mutex;
+};
+
+#define NETCHANNEL_MAX_ORDER	31
+#define NETCHANNEL_MIN_ORDER	PAGE_SHIFT
+
+struct netchannel_mmap
+{
+	struct page		**page;
+	unsigned int		pnum;
+	unsigned int		poff;
+};
+
+#endif /* __KERNEL__ */
+#endif /* __NETCHANNEL_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a461b51..9924911 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -684,6 +684,15 @@ extern void		dev_queue_xmit_nit(struct s
 
 extern void		dev_init(void);
 
+#ifdef CONFIG_NETCHANNEL
+extern int netchannel_recv(struct sk_buff *skb);
+#else
+static int netchannel_recv(struct sk_buff *skb) 
+{ 
+	return -1;
+}
+#endif
+
 extern int		netdev_nit;
 extern int		netdev_budget;
 
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f8f2347..69f0c32 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -265,7 +265,8 @@ struct sk_buff {
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-				ipvs_property:1;
+				ipvs_property:1,
+				netchannel:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
@@ -314,6 +315,18 @@ static inline struct sk_buff *alloc_skb(
 	return __alloc_skb(size, priority, 0);
 }
 
+#ifdef CONFIG_NETCHANNEL
+struct unetchannel;
+extern struct sk_buff *netchannel_alloc(struct unetchannel *unc, unsigned int header_size, 
+		unsigned int total_size, gfp_t gfp_mask);
+#else
+static struct sk_buff *netchannel_alloc(void *unc, unsigned int header_size, 
+		unsigned int total_size, gfp_t gfp_mask)
+{
+	return NULL;
+}
+#endif
+
 static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
 					       gfp_t priority)
 {
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 9ab2ddd..036a221 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -298,6 +298,7 @@ extern int csum_partial_copy_fromiovecen
 
 extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
 extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
+extern int memcpy_toiovec_copy(struct iovec *v, unsigned char *kdata, int len);
 extern int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen);
 extern int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3996960..8c22875 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -582,4 +582,6 @@ asmlinkage long sys_tee(int fdin, int fd
 asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
 					unsigned int flags);
 
+asmlinkage long sys_netchannel_control(void __user *arg);
+
 #endif
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 5433195..1747fc3 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -132,3 +132,5 @@ cond_syscall(sys_mincore);
 cond_syscall(sys_madvise);
 cond_syscall(sys_mremap);
 cond_syscall(sys_remap_file_pages);
+
+cond_syscall(sys_netchannel_control);
diff --git a/net/Kconfig b/net/Kconfig
index 4193cdc..465e37b 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -66,6 +66,14 @@ source "net/ipv6/Kconfig"
 
 endif # if INET
 
+config NETCHANNEL
+	bool "Network channels"
+	---help---
+	  Network channels are peer-to-peer abstraction, which allows to create
+	  high performance communications. 
+	  Main advantages are unified address cache, protocol processing moved
+	  to userspace, receiving zero-copy support and other interesting features.
+
 menuconfig NETFILTER
 	bool "Network packet filtering (replaces ipchains)"
 	---help---
diff --git a/net/core/Makefile b/net/core/Makefile
index 79fe12c..7119812 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_NET_DIVERT) += dv.o
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
 obj-$(CONFIG_WIRELESS_EXT) += wireless.o
 obj-$(CONFIG_NETPOLL) += netpoll.o
+obj-$(CONFIG_NETCHANNEL) += netchannel.o
diff --git a/net/core/datagram.c b/net/core/datagram.c
index aecddcc..3db8873 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -235,6 +235,8 @@ void skb_kill_datagram(struct sock *sk, 
 
 EXPORT_SYMBOL(skb_kill_datagram);
 
+typedef int (* copy_iovec_t)(struct iovec *iov, unsigned char *kdata, int len);
+
 /**
  *	skb_copy_datagram_iovec - Copy a datagram to an iovec.
  *	@skb: buffer to copy
@@ -249,12 +251,13 @@ int skb_copy_datagram_iovec(const struct
 {
 	int start = skb_headlen(skb);
 	int i, copy = start - offset;
+	copy_iovec_t func = (skb->netchannel)?&memcpy_toiovec_copy:&memcpy_toiovec;
 
 	/* Copy header. */
 	if (copy > 0) {
 		if (copy > len)
 			copy = len;
-		if (memcpy_toiovec(to, skb->data + offset, copy))
+		if (func(to, skb->data + offset, copy))
 			goto fault;
 		if ((len -= copy) == 0)
 			return 0;
@@ -277,7 +280,7 @@ int skb_copy_datagram_iovec(const struct
 			if (copy > len)
 				copy = len;
 			vaddr = kmap(page);
-			err = memcpy_toiovec(to, vaddr + frag->page_offset +
+			err = func(to, vaddr + frag->page_offset +
 					     offset - start, copy);
 			kunmap(page);
 			if (err)
diff --git a/net/core/dev.c b/net/core/dev.c
index 9ab3cfa..2721111 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1712,6 +1712,10 @@ int netif_receive_skb(struct sk_buff *sk
 		}
 	}
 
+	ret = netchannel_recv(skb);
+	if (!ret)
+		goto out;
+
 #ifdef CONFIG_NET_CLS_ACT
 	if (pt_prev) {
 		ret = deliver_skb(skb, pt_prev, orig_dev);
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 65e4b56..8d19ed7 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -98,6 +98,23 @@ int memcpy_toiovec(struct iovec *iov, un
 	return 0;
 }
 
+int memcpy_toiovec_copy(struct iovec *iov, unsigned char *kdata, int len)
+{
+	while (len > 0) {
+		if (iov->iov_len) {
+			int copy = min_t(unsigned int, iov->iov_len, len);
+			memcpy(iov->iov_base, kdata, copy);
+			kdata += copy;
+			len -= copy;
+			iov->iov_len -= copy;
+			iov->iov_base += copy;
+		}
+		iov++;
+	}
+
+	return 0;
+}
+
 /*
  *	Copy iovec to kernel. Returns -EFAULT on error.
  *
@@ -237,3 +254,4 @@ EXPORT_SYMBOL(csum_partial_copy_fromiove
 EXPORT_SYMBOL(memcpy_fromiovec);
 EXPORT_SYMBOL(memcpy_fromiovecend);
 EXPORT_SYMBOL(memcpy_toiovec);
+EXPORT_SYMBOL(memcpy_toiovec_copy);
diff --git a/net/core/netchannel.c b/net/core/netchannel.c
new file mode 100644
index 0000000..d053d3d
--- /dev/null
+++ b/net/core/netchannel.c
@@ -0,0 +1,1201 @@
+/*
+ * 	netchannel.c
+ * 
+ * 2006 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/unistd.h>
+#include <linux/linkage.h>
+#include <linux/notifier.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#include <linux/workqueue.h>
+#include <linux/netchannel.h>
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include <linux/udp.h>
+
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <net/addrconf.h>
+
+#include <asm/uaccess.h>
+
+static unsigned int netchannel_hash_order = 8;
+static struct netchannel_cache_head ***netchannel_hash_table;
+static kmem_cache_t *netchannel_cache;
+
+static int netchannel_inetaddr_notifier_call(struct notifier_block *, unsigned long, void *);
+static struct notifier_block netchannel_inetaddr_notifier = {
+	.notifier_call = &netchannel_inetaddr_notifier_call
+};
+
+#ifdef CONFIG_IPV6
+static int netchannel_inet6addr_notifier_call(struct notifier_block *, unsigned long, void *);
+static struct notifier_block netchannel_inet6addr_notifier = {
+	.notifier_call = &netchannel_inet6addr_notifier_call
+};
+#endif
+
+static inline unsigned int netchannel_hash(struct unetchannel *unc)
+{
+	unsigned int h = (unc->dst ^ unc->dport) ^ (unc->src ^ unc->sport);
+	h ^= h >> 16;
+	h ^= h >> 8;
+	h ^= unc->proto;
+	return h & ((1 << 2*netchannel_hash_order) - 1);
+}
+
+static inline void netchannel_convert_hash(unsigned int hash, unsigned int *col, unsigned int *row)
+{
+	*row = hash & ((1 << netchannel_hash_order) - 1);
+	*col = (hash >> netchannel_hash_order) & ((1 << netchannel_hash_order) - 1);
+}
+
+static struct netchannel_cache_head *netchannel_bucket(struct unetchannel *unc)
+{
+	unsigned int hash = netchannel_hash(unc);
+	unsigned int col, row;
+
+	netchannel_convert_hash(hash, &col, &row);
+	return netchannel_hash_table[col][row];
+}
+
+static inline int netchannel_hash_equal_full(struct unetchannel *unc1, struct unetchannel *unc2)
+{
+	return (unc1->dport == unc2->dport) && (unc1->dst == unc2->dst) &&
+				(unc1->sport == unc2->sport) && (unc1->src == unc2->src) && 
+				(unc1->proto == unc2->proto);
+}
+
+static inline int netchannel_hash_equal_dest(struct unetchannel *unc1, struct unetchannel *unc2)
+{
+	return ((unc1->dport == unc2->dport) && (unc1->dst == unc2->dst) && (unc1->proto == unc2->proto));
+}
+
+static struct netchannel *netchannel_check_dest(struct unetchannel *unc, struct netchannel_cache_head *bucket)
+{
+	struct netchannel *nc;
+	struct hlist_node *node;
+	int found = 0;
+	
+	hlist_for_each_entry_rcu(nc, node, &bucket->head, node) {
+		if (netchannel_hash_equal_dest(&nc->unc, unc)) {
+			found = 1;
+			break;
+		}
+	}
+
+	return (found)?nc:NULL;
+}
+
+static struct netchannel *netchannel_check_full(struct unetchannel *unc, struct netchannel_cache_head *bucket)
+{
+	struct netchannel *nc;
+	struct hlist_node *node;
+	int found = 0;
+
+	hlist_for_each_entry_rcu(nc, node, &bucket->head, node) {
+		if (netchannel_hash_equal_full(&nc->unc, unc)) {
+			found = 1;
+			break;
+		}
+	}
+
+	return (found)?nc:NULL;
+}
+
+static void netchannel_mmap_cleanup(struct netchannel *nc)
+{
+	unsigned int i;
+	struct netchannel_mmap *m = nc->priv;
+
+	for (i=0; i<m->pnum; ++i)
+		__free_page(m->page[i]);
+
+	kfree(m);
+}
+
+static void netchannel_cleanup(struct netchannel *nc)
+{
+	switch (nc->unc.type) {
+		case NETCHANNEL_COPY_USER:
+			break;
+		case NETCHANNEL_MMAP:
+			netchannel_mmap_cleanup(nc);
+			break;
+		default:
+			break;
+	}
+}
+
+static void netchannel_free_rcu(struct rcu_head *rcu)
+{
+	struct netchannel *nc = container_of(rcu, struct netchannel, rcu_head);
+
+	netchannel_cleanup(nc);
+	kmem_cache_free(netchannel_cache, nc);
+}
+
+static inline void netchannel_get(struct netchannel *nc)
+{
+	atomic_inc(&nc->refcnt);
+}
+
+static inline void netchannel_put(struct netchannel *nc)
+{
+	if (atomic_dec_and_test(&nc->refcnt))
+		call_rcu(&nc->rcu_head, &netchannel_free_rcu);
+}
+
+static inline void netchannel_dump_info_unc(struct unetchannel *unc, char *prefix, unsigned long hit, int err)
+{
+	u32 src, dst;
+	u16 sport, dport;
+	
+	dst = unc->dst;
+	src = unc->src;
+	dport = ntohs(unc->dport);
+	sport = ntohs(unc->sport);
+
+	printk(KERN_NOTICE "netchannel: %s %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u, "
+			"proto: %u, type: %u, order: %u, hit: %lu, err: %d.\n",
+			prefix, NIPQUAD(src), sport, NIPQUAD(dst), dport, 
+			unc->proto, unc->type, unc->memory_limit_order, hit, err);
+}
+
+static int netchannel_convert_skb_ipv6(struct sk_buff *skb, struct unetchannel *unc)
+{
+	/*
+	 * Hash IP addresses into src/dst. Setup TCP/UDP ports.
+	 * Not supported yet.
+	 */
+	return -1;
+}
+
+static int netchannel_convert_skb_ipv4(struct sk_buff *skb, struct unetchannel *unc)
+{
+	struct iphdr *iph;
+	u32 len;
+
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		goto inhdr_error;
+
+	iph = skb->nh.iph;
+
+	if (iph->ihl < 5 || iph->version != 4)
+		goto inhdr_error;
+
+	if (!pskb_may_pull(skb, iph->ihl*4))
+		goto inhdr_error;
+
+	iph = skb->nh.iph;
+
+	if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
+		goto inhdr_error;
+
+	len = ntohs(iph->tot_len);
+	if (skb->len < len || len < (iph->ihl*4))
+		goto inhdr_error;
+
+	if (pskb_trim_rcsum(skb, len))
+		goto inhdr_error;
+
+	unc->dst = iph->daddr;
+	unc->src = iph->saddr;
+	unc->proto = iph->protocol;
+
+	len = skb->len;
+
+	skb->h.raw = skb->nh.raw + iph->ihl*4;
+
+	switch (unc->proto) {
+		case IPPROTO_TCP:
+		case IPPROTO_UDP:
+			unc->sport = ((u16 *)skb->h.raw)[0];
+			unc->dport = ((u16 *)skb->h.raw)[1];
+			break;
+		default:
+			goto inhdr_error;
+	}
+
+	return 0;
+
+inhdr_error:
+	return -1;
+}
+
+static int netchannel_convert_skb(struct sk_buff *skb, struct unetchannel *unc)
+{
+	if (skb->pkt_type == PACKET_OTHERHOST)
+		return -1;
+
+	switch (ntohs(skb->protocol)) {
+		case ETH_P_IP:
+			return netchannel_convert_skb_ipv4(skb, unc);
+		case ETH_P_IPV6:
+			return netchannel_convert_skb_ipv6(skb, unc);
+		default:
+			return -1;
+	}
+}
+
+/*
+ * By design netchannels allow to "allocate" data
+ * not only from SLAB cache, but get it from mapped area
+ * or from VFS cache (requires process' context or preallocation).
+ */
+struct sk_buff *netchannel_alloc(struct unetchannel *unc, unsigned int header_size, 
+		unsigned int total_size, gfp_t gfp_mask)
+{
+	struct netchannel *nc;
+	struct netchannel_cache_head *bucket;
+	int err;
+	struct sk_buff *skb = NULL;
+	unsigned int size, pnum, i;
+
+	skb = alloc_skb(header_size, gfp_mask);
+	if (!skb)
+		return NULL;
+
+	rcu_read_lock();
+	bucket = netchannel_bucket(unc);
+	nc = netchannel_check_full(unc, bucket);
+	if (!nc) {
+		err = -ENODEV;
+		goto err_out_free_skb;
+	}
+
+	if (!nc->nc_alloc_page || !nc->nc_free_page) {
+		err = -EINVAL;
+		goto err_out_free_skb;
+	}
+
+	netchannel_get(nc);
+
+	size = total_size - header_size;
+	pnum = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	for (i=0; i<pnum; ++i) {
+		unsigned int cs = min_t(unsigned int, PAGE_SIZE, size);
+		struct page *page;
+
+		page = nc->nc_alloc_page(cs);
+		if (!page)
+			break;
+		
+		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 0, cs);
+		
+		skb->len	+= cs;
+		skb->data_len	+= cs;
+		skb->truesize	+= cs;
+
+		size -= cs;
+	}
+
+	if (i < pnum) {
+		pnum = i;
+		err = -ENOMEM;
+		goto err_out_free_frags;
+	}
+
+	rcu_read_unlock();
+
+	return skb;
+
+err_out_free_frags:
+	for (i=0; i<pnum; ++i) {
+		unsigned int cs = skb_shinfo(skb)->frags[i].size;
+		struct page *page = skb_shinfo(skb)->frags[i].page;
+		
+		nc->nc_free_page(page);
+
+		skb->len	-= cs;
+		skb->data_len	-= cs;
+		skb->truesize	-= cs;
+	}
+
+err_out_free_skb:
+	kfree_skb(skb);
+	return NULL;
+}
+
+int netchannel_recv(struct sk_buff *skb)
+{
+	struct netchannel *nc;
+	struct unetchannel unc;
+	struct netchannel_cache_head *bucket;
+	int err;
+
+	if (!netchannel_hash_table)
+		return -ENODEV;
+
+	rcu_read_lock();
+
+	err = netchannel_convert_skb(skb, &unc);
+	if (err)
+		goto unlock;
+
+	bucket = netchannel_bucket(&unc);
+	nc = netchannel_check_full(&unc, bucket);
+	if (!nc) {
+		err = -ENODEV;
+		goto unlock;
+	}
+
+	nc->hit++;
+#if 0
+	if (nc->qlen + skb->len > (1 << nc->unc.memory_limit_order)) {
+		kfree_skb(skb);
+		err = 0;
+		goto unlock;
+	}
+#endif
+	nc->qlen += skb->len;
+	skb_queue_tail(&nc->recv_queue, skb);
+	wake_up(&nc->wait);
+
+unlock:
+	rcu_read_unlock();
+	
+	return err;
+}
+
+static int netchannel_wait_for_packet(struct netchannel *nc, long *timeo_p)
+{
+	int error = 0;
+	DEFINE_WAIT(wait);
+
+	prepare_to_wait_exclusive(&nc->wait, &wait, TASK_INTERRUPTIBLE);
+
+	if (skb_queue_empty(&nc->recv_queue)) {
+		if (signal_pending(current))
+			goto interrupted;
+
+		*timeo_p = schedule_timeout(*timeo_p);
+	}
+out:
+	finish_wait(&nc->wait, &wait);
+	return error;
+interrupted:
+	error = (*timeo_p == MAX_SCHEDULE_TIMEOUT) ? -ERESTARTSYS : -EINTR;
+	goto out;
+}
+
+static struct sk_buff *netchannel_get_skb(struct netchannel *nc, unsigned int *timeout, int *error)
+{
+	struct sk_buff *skb = NULL;
+	long tm = *timeout;
+
+	*error = 0;
+
+	while (1) {
+		skb = skb_dequeue(&nc->recv_queue);
+		if (skb) {
+			nc->qlen -= skb->len;
+			break;
+		}
+
+		if (*timeout) {
+			*error = netchannel_wait_for_packet(nc, &tm);
+			if (*error) {
+				*timeout = tm;
+				skb = skb_dequeue(&nc->recv_queue);
+				break;
+			}
+			tm = *timeout;
+		} else {
+			*error = -EAGAIN;
+			break;
+		}
+	}
+
+	return skb;
+}
+
+static int netchannel_copy_to_user_tcp(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+	struct tcphdr *th;
+	int err = -ENODEV;
+	struct socket *sock;
+	struct sock *sk;
+	struct sk_buff *skb;
+	struct iovec iov;
+	struct msghdr msg;
+	unsigned flags = MSG_DONTWAIT;
+	unsigned int size = *len, read = 0, osize = *len;
+	unsigned int slen, process;
+	unsigned int tm = *timeout;
+
+	if (!nc->inode)
+		goto err_out;
+	sock = SOCKET_I(nc->inode);
+	if (!sock || !sock->sk)
+		goto err_out;
+
+	sk = sock->sk;
+
+	while (size) {
+		msg.msg_control=NULL;
+		msg.msg_controllen=0;
+		msg.msg_iovlen=1;
+		msg.msg_iov=&iov;
+		msg.msg_name=NULL;
+		msg.msg_namelen=0;
+		msg.msg_flags = flags;
+		iov.iov_len=size;
+		iov.iov_base=arg;
+
+		nc->stat.enter++;
+
+		err = sock_recvmsg(sock, &msg, iov.iov_len, flags);
+
+		if (err > 0) {
+			size -= err;
+			read += err;
+
+			if (!size) {
+				err = 0;
+				nc->stat.ready++;
+				break;
+			}
+		} else if (err && err != -EAGAIN)
+			break;
+
+		err = 0;
+		process = 0;
+		slen = 0;
+
+		nc->stat.recv++;
+
+		while (slen < 2*osize) {
+#if 1
+			if (skb_queue_empty(&nc->recv_queue) && slen > osize) {
+				nc->stat.empty++;
+				break;
+			}
+#endif
+			skb = netchannel_get_skb(nc, &tm, &err);
+			if (!skb) {
+				nc->stat.null++;
+				break;
+			}
+			skb->netchannel = nc->unc.type & 1;
+
+			__skb_pull(skb, skb->nh.iph->ihl*4);
+
+			skb->h.raw = skb->data;
+
+			th = skb->h.th;
+			TCP_SKB_CB(skb)->seq = ntohl(th->seq);
+			TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
+						    skb->len - th->doff * 4);
+			TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
+			TCP_SKB_CB(skb)->when	 = 0;
+			TCP_SKB_CB(skb)->flags	 = skb->nh.iph->tos;
+			TCP_SKB_CB(skb)->sacked	 = 0;
+
+			nc->stat.backlog++;
+						
+			if (sk->sk_backlog_rcv) {
+				err = sk->sk_backlog_rcv(sk, skb);
+				if (err) {
+					nc->stat.backlog_err++;
+					break;
+				}
+			}
+
+			slen += skb->len;
+
+			nc->stat.eat++;
+		}
+
+		if (err)
+			break;
+	}
+
+	*timeout = tm;
+	*len = read;
+
+	return err;
+
+err_out:
+	return err;
+}
+
+static int netchannel_copy_to_user(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+	unsigned int copied;
+	struct sk_buff *skb;
+	struct iovec to;
+	int err;
+
+	skb = netchannel_get_skb(nc, timeout, &err);
+	if (!skb)
+		return err;
+
+	to.iov_base = arg;
+	to.iov_len = *len;
+
+	copied = skb->len;
+	if (copied > *len)
+		copied = *len;
+
+	if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+		err = skb_copy_datagram_iovec(skb, 0, &to, copied);
+	} else {
+		err = skb_copy_and_csum_datagram_iovec(skb,0, &to);
+	}
+
+	*len = (err == 0)?copied:0;
+
+	kfree_skb(skb);
+
+	return err;
+}
+
+int netchannel_skb_copy_datagram(const struct sk_buff *skb, int offset,
+			    void *to, int len)
+{
+	int start = skb_headlen(skb);
+	int i, copy = start - offset;
+
+	/* Copy header. */
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		memcpy(to, skb->data + offset, copy);
+
+		if ((len -= copy) == 0)
+			return 0;
+		offset += copy;
+		to += copy;
+	}
+
+	/* Copy paged appendix. Hmm... why does this look so complicated? */
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			u8  *vaddr;
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			struct page *page = frag->page;
+
+			if (copy > len)
+				copy = len;
+			vaddr = kmap(page);
+			memcpy(to, vaddr + frag->page_offset +
+					     offset - start, copy);
+			kunmap(page);
+			if (!(len -= copy))
+				return 0;
+			offset += copy;
+			to += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				if (netchannel_skb_copy_datagram(list,
+							    offset - start,
+							    to, copy))
+					goto fault;
+				if ((len -= copy) == 0)
+					return 0;
+				offset += copy;
+				to += copy;
+			}
+			start = end;
+		}
+	}
+	if (!len)
+		return 0;
+
+fault:
+	return -EFAULT;
+}
+
+static int netchannel_copy_to_mem(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+	struct netchannel_mmap *m = nc->priv;
+	unsigned int copied, skb_offset = 0;
+	struct sk_buff *skb;
+	int err;
+
+	skb = netchannel_get_skb(nc, timeout, &err);
+	if (!skb)
+		return err;
+
+	copied = skb->len;
+
+	while (copied) {
+		int pnum = ((m->poff % PAGE_SIZE) % m->pnum);
+		struct page *page = m->page[pnum];
+		void *page_map, *ptr;
+		unsigned int sz, left;
+
+		left = PAGE_SIZE - (m->poff % (PAGE_SIZE - 1));
+		sz = min_t(unsigned int, left, copied);
+
+		if (!sz) {
+			err = -ENOSPC;
+			goto err_out;
+		}
+
+		page_map = kmap_atomic(page, KM_USER0);
+		if (!page_map) {
+			err = -ENOMEM;
+			goto err_out;
+		}
+		ptr = page_map + (m->poff % (PAGE_SIZE - 1));
+
+		err = netchannel_skb_copy_datagram(skb, skb_offset, ptr, sz);
+		if (err) {
+			kunmap_atomic(page_map, KM_USER0);
+			goto err_out;
+		}
+		kunmap_atomic(page_map, KM_USER0);
+
+		copied -= sz;
+		m->poff += sz;
+		skb_offset += sz;
+#if 1
+		if (m->poff >= PAGE_SIZE * m->pnum) {
+			//netchannel_dump_info_unc(&nc->unc, "rewind", nc->hit, 0);
+			m->poff = 0;
+		}
+#endif
+	}
+	*len = skb->len;
+
+	err = 0;
+
+err_out:
+	kfree_skb(skb);
+
+	return err;
+}
+
+static int netchannel_mmap_setup(struct netchannel *nc)
+{
+	struct netchannel_mmap *m;
+	unsigned int i, pnum;
+
+	pnum = nc->unc.memory_limit_order - NETCHANNEL_MIN_ORDER;
+
+	m = kzalloc(sizeof(struct netchannel_mmap) + sizeof(struct page *) * pnum, GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	m->page = (struct page **)(m + 1);
+	m->pnum = pnum;
+
+	for (i=0; i<pnum; ++i) {
+		m->page[i] = alloc_page(GFP_KERNEL);
+		if (!m->page[i])
+			break;
+	}
+
+	if (i < pnum) {
+		pnum = i;
+		goto err_out_free;
+	}
+
+	nc->priv = m;
+
+	switch (nc->unc.proto) {
+		case IPPROTO_TCP:
+			nc->nc_read_data = &netchannel_copy_to_user_tcp;
+			break;
+		case IPPROTO_UDP:
+		default:
+			nc->nc_read_data = &netchannel_copy_to_mem;
+			break;
+	}
+
+	return 0;
+
+err_out_free:
+	for (i=0; i<pnum; ++i)
+		__free_page(m->page[i]);
+
+	kfree(m);
+
+	return -ENOMEM;
+	
+}
+
+static int netchannel_copy_user_setup(struct netchannel *nc)
+{
+	int ret = 0;
+	
+	switch (nc->unc.proto) {
+		case IPPROTO_UDP:
+			nc->nc_read_data = &netchannel_copy_to_user;
+			break;
+		case IPPROTO_TCP:
+			nc->nc_read_data = &netchannel_copy_to_user_tcp;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+
+	return ret;
+}
+
+static int netchannel_setup(struct netchannel *nc)
+{
+	int ret = 0;
+
+	if (nc->unc.memory_limit_order > NETCHANNEL_MAX_ORDER)
+		nc->unc.memory_limit_order = NETCHANNEL_MAX_ORDER;
+
+	if (nc->unc.memory_limit_order < NETCHANNEL_MIN_ORDER)
+		nc->unc.memory_limit_order = NETCHANNEL_MIN_ORDER;
+	
+	switch (nc->unc.type) {
+		case NETCHANNEL_COPY_USER:
+			ret = netchannel_copy_user_setup(nc);
+			break;
+		case NETCHANNEL_MMAP:
+			ret = netchannel_mmap_setup(nc);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+
+	return ret;
+}
+
+static int netchannel_bind(struct unetchannel_control *ctl)
+{
+	struct netchannel *nc;
+	int err = -EINVAL, fput_needed;
+	struct netchannel_cache_head *bucket;
+	struct file *file;
+	struct inode *inode;
+
+	file = fget_light(ctl->fd, &fput_needed);
+	if (!file)
+		goto err_out_exit;
+
+	inode = igrab(file->f_dentry->d_inode);
+	if (!inode)
+		goto err_out_fput;
+
+	bucket = netchannel_bucket(&ctl->unc);
+	
+	mutex_lock(&bucket->mutex);
+	
+	nc = netchannel_check_full(&ctl->unc, bucket);
+	if (!nc) {
+		err = -ENODEV;
+		goto err_out_unlock;
+	}
+
+	nc->inode = inode;
+
+	fput_light(file, fput_needed);
+	mutex_unlock(&bucket->mutex);
+
+	return 0;
+
+err_out_unlock:
+	mutex_unlock(&bucket->mutex);
+err_out_fput:
+	fput_light(file, fput_needed);
+err_out_exit:
+	return err;
+}
+
+static void netchannel_dump_stat(struct netchannel *nc)
+{
+	printk("netchannel: enter: %llu, ready: %llu, recv: %llu, empty: %llu, null: %llu, backlog: %llu, backlog_err: %llu, eat: %llu.\n",
+			nc->stat.enter, nc->stat.ready, nc->stat.recv, nc->stat.empty, nc->stat.null, nc->stat.backlog,
+			nc->stat.backlog_err, nc->stat.eat);
+}
+
+static void netchannel_work(void *data)
+{
+	struct netchannel *nc = data;
+	
+	netchannel_dump_info_unc(&nc->unc, "work", nc->hit, 0);
+
+	if (nc->inode) {
+		struct socket *sock;
+		struct sock *sk;
+
+		sock = SOCKET_I(nc->inode);
+		if (!sock || !sock->sk)
+			goto out;
+
+		sk = sock->sk;
+		printk("netchannel: sk: %p, skb_qlen: %u, nc_qlen: %u.\n", 
+				sk, skb_queue_len(&nc->recv_queue), nc->qlen);
+	}
+	netchannel_dump_stat(nc);
+out:
+	schedule_delayed_work(&nc->work, msecs_to_jiffies(1000*nc->unc.init_stat_work));
+}
+
+static int netchannel_create(struct unetchannel *unc)
+{
+	struct netchannel *nc;
+	int err = -ENOMEM;
+	struct netchannel_cache_head *bucket;
+	
+	nc = kmem_cache_alloc(netchannel_cache, GFP_KERNEL);
+	if (!nc)
+		return -ENOMEM;
+
+	memset(nc, 0, sizeof(struct netchannel));
+	
+	nc->hit = 0;
+	skb_queue_head_init(&nc->recv_queue);
+	init_waitqueue_head(&nc->wait);
+	atomic_set(&nc->refcnt, 1);
+	memcpy(&nc->unc, unc, sizeof(struct unetchannel));
+
+	err = netchannel_setup(nc);
+	if (err)
+		goto err_out_free;
+	
+	bucket = netchannel_bucket(unc);
+	
+	mutex_lock(&bucket->mutex);
+	
+	if (netchannel_check_full(unc, bucket)) {
+		err = -EEXIST;
+		goto err_out_unlock;
+	}
+
+	hlist_add_head_rcu(&nc->node, &bucket->head);
+	err = 0;
+
+	mutex_unlock(&bucket->mutex);
+	
+	netchannel_dump_info_unc(unc, "create", 0, err);
+
+	INIT_WORK(&nc->work, netchannel_work, nc);
+	if (nc->unc.init_stat_work)
+		schedule_delayed_work(&nc->work, msecs_to_jiffies(1000*nc->unc.init_stat_work));
+
+	return err;
+
+err_out_unlock:
+	mutex_unlock(&bucket->mutex);
+
+	netchannel_cleanup(nc);
+
+err_out_free:
+	kmem_cache_free(netchannel_cache, nc);
+
+	return err;
+}
+
+static int netchannel_remove(struct unetchannel *unc)
+{
+	struct netchannel *nc;
+	int err = -ENODEV;
+	struct netchannel_cache_head *bucket;
+	unsigned long hit = 0;
+	
+	if (!netchannel_hash_table)
+		return -ENODEV;
+	
+	bucket = netchannel_bucket(unc);
+
+	mutex_lock(&bucket->mutex);
+
+	nc = netchannel_check_full(unc, bucket);
+	if (!nc)
+		nc = netchannel_check_dest(unc, bucket);
+
+	if (!nc)
+		goto out_unlock;
+	
+	hlist_del_rcu(&nc->node);
+	hit = nc->hit;
+
+	if (nc->unc.init_stat_work) {
+		cancel_rearming_delayed_work(&nc->work);
+		flush_scheduled_work();
+	}
+	
+	if (nc->inode) {
+		iput(nc->inode);
+		nc->inode = NULL;
+	}
+	
+	netchannel_put(nc);
+	err = 0;
+
+out_unlock:
+	mutex_unlock(&bucket->mutex);
+	netchannel_dump_info_unc(unc, "remove", hit, err);
+	return err;
+}
+
+static int netchannel_recv_data(struct unetchannel_control *ctl, void __user *data)
+{
+	int ret = -ENODEV;
+	struct netchannel_cache_head *bucket;
+	struct netchannel *nc;
+	
+	bucket = netchannel_bucket(&ctl->unc);
+
+	mutex_lock(&bucket->mutex);
+
+	nc = netchannel_check_full(&ctl->unc, bucket);
+	if (!nc)
+		nc = netchannel_check_dest(&ctl->unc, bucket);
+
+	if (!nc)
+		goto err_out_unlock;
+
+	netchannel_get(nc);
+	mutex_unlock(&bucket->mutex);
+
+	ret = nc->nc_read_data(nc, &ctl->timeout, &ctl->len, data);
+	
+	netchannel_put(nc);
+	return ret;
+
+err_out_unlock:
+	mutex_unlock(&bucket->mutex);
+	return ret;
+}
+
+static int netchannel_dump_info(struct unetchannel *unc)
+{
+	struct netchannel_cache_head *bucket;
+	struct netchannel *nc;
+	char *ncs = "none";
+	unsigned long hit = 0;
+	int err;
+	
+	bucket = netchannel_bucket(unc);
+
+	mutex_lock(&bucket->mutex);
+	nc = netchannel_check_full(unc, bucket);
+	if (!nc) {
+		nc = netchannel_check_dest(unc, bucket);
+		if (nc)
+			ncs = "dest";
+	} else 
+		ncs = "full";
+	if (nc)
+		hit = nc->hit;
+	mutex_unlock(&bucket->mutex);
+	err = (nc)?0:-ENODEV;
+
+	netchannel_dump_info_unc(unc, ncs, hit, err);
+
+	return err;
+}
+
+asmlinkage long sys_netchannel_control(void __user *arg)
+{
+	struct unetchannel_control ctl;
+	int ret;
+
+	if (!netchannel_hash_table)
+		return -ENODEV;
+
+	if (copy_from_user(&ctl, arg, sizeof(struct unetchannel_control)))
+		return -ERESTARTSYS;
+
+	switch (ctl.cmd) {
+		case NETCHANNEL_CREATE:
+			ret = netchannel_create(&ctl.unc);
+			break;
+		case NETCHANNEL_BIND:
+			ret = netchannel_bind(&ctl);
+			break;
+		case NETCHANNEL_REMOVE:
+			ret = netchannel_remove(&ctl.unc);
+			break;
+		case NETCHANNEL_READ:
+			ret = netchannel_recv_data(&ctl, arg + sizeof(struct unetchannel_control));
+			break;
+		case NETCHANNEL_DUMP:
+			ret = netchannel_dump_info(&ctl.unc);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+	
+	if (copy_to_user(arg, &ctl, sizeof(struct unetchannel_control)))
+		return -ERESTARTSYS;
+
+	return ret;
+}
+
+static inline void netchannel_dump_addr(struct in_ifaddr *ifa, char *str)
+{
+	printk("netchannel: %s %u.%u.%u.%u/%u.%u.%u.%u\n", str, NIPQUAD(ifa->ifa_local), NIPQUAD(ifa->ifa_mask));
+}
+
+static int netchannel_inetaddr_notifier_call(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct in_ifaddr *ifa = ptr;
+
+	switch (event) {
+		case NETDEV_UP:
+			netchannel_dump_addr(ifa, "add");
+			break;
+		case NETDEV_DOWN:
+			netchannel_dump_addr(ifa, "del");
+			break;
+		default:
+			netchannel_dump_addr(ifa, "unk");
+			break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+#ifdef CONFIG_IPV6
+static int netchannel_inet6addr_notifier_call(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct inet6_ifaddr *ifa = ptr;
+
+	printk("netchannel: inet6 event=%lx, ifa=%p.\n", event, ifa);
+	return NOTIFY_DONE;
+}
+#endif
+
+static int __init netchannel_init(void)
+{
+	unsigned int i, j, size;
+	int err = -ENOMEM;
+
+	size = (1 << netchannel_hash_order);
+
+	netchannel_hash_table = kzalloc(size * sizeof(void *), GFP_KERNEL);
+	if (!netchannel_hash_table)
+		goto err_out_exit;
+
+	for (i=0; i<size; ++i) {
+		struct netchannel_cache_head **col;
+
+		col = kzalloc(size * sizeof(void *), GFP_KERNEL);
+		if (!col)
+			break;
+		
+		for (j=0; j<size; ++j) {
+			struct netchannel_cache_head *head;
+
+			head = kzalloc(sizeof(struct netchannel_cache_head), GFP_KERNEL);
+			if (!head)
+				break;
+
+			INIT_HLIST_HEAD(&head->head);
+			mutex_init(&head->mutex);
+
+			col[j] = head;
+		}
+		
+		if (j<size && j>0) {
+			while (j >= 0)
+				kfree(col[j--]);
+			kfree(col);
+			break;
+		}
+
+		netchannel_hash_table[i] = col;
+	}
+
+	if (i<size) {
+		size = i;
+		goto err_out_free;
+	}
+
+	netchannel_cache = kmem_cache_create("netchannel", sizeof(struct netchannel), 0, 0,
+			NULL, NULL);
+	if (!netchannel_cache)
+		goto err_out_free;
+
+	register_inetaddr_notifier(&netchannel_inetaddr_notifier);
+#ifdef CONFIG_IPV6
+	register_inet6addr_notifier(&netchannel_inet6addr_notifier);
+#endif
+
+	printk("netchannel: Created %u order two-dimensional hash table.\n", 
+			netchannel_hash_order);
+
+	return 0;
+
+err_out_free:
+	for (i=0; i<size; ++i) {
+		for (j=0; j<(1 << netchannel_hash_order); ++j)
+			kfree(netchannel_hash_table[i][j]);
+		kfree(netchannel_hash_table[i]);
+	}
+	kfree(netchannel_hash_table);
+err_out_exit:
+	
+	printk("netchannel: Failed to create %u order two-dimensional hash table.\n", 
+			netchannel_hash_order);
+	return err;
+}
+
+static void __exit netchannel_exit(void)
+{
+	unsigned int i, j;
+
+	unregister_inetaddr_notifier(&netchannel_inetaddr_notifier);
+#ifdef CONFIG_IPV6
+	unregister_inet6addr_notifier(&netchannel_inet6addr_notifier);
+#endif
+	kmem_cache_destroy(netchannel_cache);
+
+	for (i=0; i<(1 << netchannel_hash_order); ++i) {
+		for (j=0; j<(1 << netchannel_hash_order); ++j)
+			kfree(netchannel_hash_table[i][j]);
+		kfree(netchannel_hash_table[i]);
+	}
+	kfree(netchannel_hash_table);
+}
+
+late_initcall(netchannel_init);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index fb3770f..f979fd6 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -437,6 +437,7 @@ struct sk_buff *skb_clone(struct sk_buff
 	C(pkt_type);
 	C(ip_summed);
 	C(priority);
+	C(netchannel);
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	C(ipvs_property);
 #endif
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 672950e..eb2dc12 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -727,7 +727,10 @@ int tcp_v4_conn_request(struct sock *sk,
 #endif
 
 	/* Never answer to SYNs send to broadcast or multicast */
-	if (((struct rtable *)skb->dst)->rt_flags &
+	if (!skb->dst) {
+		if (MULTICAST(daddr))
+			goto drop;
+	} else if (((struct rtable *)skb->dst)->rt_flags &
 	    (RTCF_BROADCAST | RTCF_MULTICAST))
 		goto drop;
 
@@ -924,15 +927,21 @@ static struct sock *tcp_v4_hnd_req(struc
 	struct iphdr *iph = skb->nh.iph;
 	struct sock *nsk;
 	struct request_sock **prev;
+	int iif;
 	/* Find possible connection requests. */
 	struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
 						       iph->saddr, iph->daddr);
 	if (req)
 		return tcp_check_req(sk, skb, req, prev);
 
+	if (!skb->dst)
+		iif = 0;
+	else
+		iif = inet_iif(skb);
+
 	nsk = __inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
 					th->source, skb->nh.iph->daddr,
-					ntohs(th->dest), inet_iif(skb));
+					ntohs(th->dest), iif);
 
 	if (nsk) {
 		if (nsk->sk_state != TCP_TIME_WAIT) {

-- 
	Evgeniy Polyakov

^ permalink raw reply related

* Re: [PATCH 1/2] e1000: fix netpoll with NAPI
From: Mitch Williams @ 2006-06-08 17:19 UTC (permalink / raw)
  To: Jeff Moyer
  Cc: Kok, Auke-jan H, Matt Mackall, Garzik, Jeff, Neil Horman, netdev,
	Brandeburg, Jesse, Kok, Auke
In-Reply-To: <x49d5dkvm8p.fsf@segfault.boston.redhat.com>

On Wed, 2006-06-07 at 11:44 -0700, Jeff Moyer wrote:

> That patch locks around the tx clean routine.  As such, it doesn't
> prevent
> the problem.

The call to netif_rx_schedule_prep provides locking because it sets the
__LINK_STATE_RX_SCHED bit atomically.  The spinlock around
e1000_clean_tx_irq is to protect it from other calls to the transmit
routine, not NAPI.

-Mitch

> > +     disable_irq(adapter->pdev->irq);
> > +     if
> (likely(netif_rx_schedule_prep(&adapter->polling_netdev[0]))) {
> > +             if (spin_trylock(&adapter->tx_queue_lock)) {
> > +                     e1000_clean_tx_irq(adapter,
> &adapter->tx_ring[0]);
> > +                     spin_unlock(&adapter->tx_queue_lock);
> > +             }
> > +             adapter->clean_rx(adapter, adapter->rx_ring,
> > +                             &budget, netdev->weight);
> > +             clear_bit(__LINK_STATE_RX_SCHED,
> > +                             &adapter->polling_netdev[0].state);
> 
> -Jeff
> 
> 

^ permalink raw reply

* Re: [PATCH 1/2] e1000: fix netpoll with NAPI
From: Jeff Moyer @ 2006-06-08 17:29 UTC (permalink / raw)
  To: Mitch Williams
  Cc: Kok, Auke-jan H, Matt Mackall, Garzik, Jeff, Neil Horman, netdev,
	Brandeburg, Jesse, Kok, Auke
In-Reply-To: <1149787174.2928.3.camel@strongmad>

==> Regarding Re: [PATCH 1/2] e1000: fix netpoll with NAPI; Mitch Williams <mitch.a.williams@intel.com> adds:

mitch.a.williams> On Wed, 2006-06-07 at 11:44 -0700, Jeff Moyer wrote:
>> That patch locks around the tx clean routine.  As such, it doesn't
>> prevent the problem.

mitch.a.williams> The call to netif_rx_schedule_prep provides locking
mitch.a.williams> because it sets the __LINK_STATE_RX_SCHED bit atomically.
mitch.a.williams> The spinlock around e1000_clean_tx_irq is to protect it
mitch.a.williams> from other calls to the transmit routine, not NAPI.

Yes, but what prevents recursion in the poll routine?  Consider that the
poll routine could end up triggerring a printk (think iptables, here).  In
that case, you end up calling into netpoll, and if the tx ring is full, we
call the poll_controller routine.  We've now recursed.

The poll lock was originally introduced to prevent recursion, not
concurrent access.

-Jeff

^ permalink raw reply

* Re: [PATCH 1/2] e1000: fix netpoll with NAPI
From: Mitch Williams @ 2006-06-08 17:23 UTC (permalink / raw)
  To: John W. Linville
  Cc: Kok, Auke-jan H, Matt Mackall, Garzik, Jeff, Neil Horman,
	Jeff Moyer, netdev, Brandeburg, Jesse, Kok, Auke
In-Reply-To: <20060607185440.GC26702@tuxdriver.com>

On Wed, 2006-06-07 at 11:54 -0700, John W. Linville wrote:

> Pedantic objection, but I think this would read easier w/o the extra
> newline before disable_irq.

Heh.  I prefer to have a newline between declarations and code.  The
real problem is the position of the #ifdef -- that's what makes it
difficult to read.  The other solution would be
{
        struct e1000_adapter *adapter = netdev_priv(netdev);
#ifdef CONFIG_E1000_NAPI
	int budget = 0;
#endif

	disable_irq(adapter->pdev->irq);

#ifdef CONFIG_E1000_NAPI
	< all that stuff >
#else
	<rest of the stuff >
#endif
}

Which I think is worse to read.
-Mitch

^ permalink raw reply

* Fw: [Bugme-new] [Bug 6666] New: invalid tcp socket connection to windows stacks
From: Andrew Morton @ 2006-06-08 17:36 UTC (permalink / raw)
  To: netdev; +Cc: technik, bugme-daemon@kernel-bugs.osdl.org



Begin forwarded message:

Date: Thu, 8 Jun 2006 05:23:04 -0700
From: bugme-daemon@bugzilla.kernel.org
To: bugme-new@lists.osdl.org
Subject: [Bugme-new] [Bug 6666] New: invalid tcp socket connection to windows stacks


http://bugzilla.kernel.org/show_bug.cgi?id=6666

           Summary: invalid tcp socket connection to windows stacks
    Kernel Version: 2.6.17.rc3-rc6
            Status: NEW
          Severity: normal
             Owner: shemminger@osdl.org
         Submitter: technik@power-netz.de


Most recent kernel where this bug did not occur:

2.6.16 stable

Distribution:
none. static kernel compiled directly out of the box.

Hardware Environment:
dual Xeon 2.66 512kB 1024MB networks e1000 e1000 e100
dual Xeon 3.20 2048kB 2048MB networks e1000 sky2

Software Environment:
problem occurs in kernel version 2.6.17rc3, 2.6.17rc6
problem does NOT occur in kernel version 2.6.16

Problem Description:

The kernel sends an ack to the windows stack after sync has been
replied, but theres no answere to this ack(1) and the kernel sends
a FIN packet after connection timeout. Now the windowsstack sends 
an ack(2) and a FIN and the connections ends.

It takes a while for the linux kernel to send the fin, we have shorten 
this in our tcpdump a bit.

connections to other windowssystems i.e. throu a dsl router or other linux 
based computers are working as expected. 

It is a very! special bug which you are maybe not able to reproduce. 

that's why i added the ip adress to test with. As far as i know, the ip
belongs to an exchange server in a home network somewhere in switzerland.

You can use it freely as it acts as a public mailserver for the domain.

Problem occurs independently of "Rx Polling"/"NAPI" and "Packet Split" 
settings.

Steps to reproduce:

You need TCPDUMP and NETCAT ( nc ).

1) tcpdump -w /tmp/log -s 2000 host  212.90.215.40  &
2) nc 212.90.215.40 25

If it's buggy you get :

11:24:15.021572 d59.x-mailer.de.59959 >
cust.static.212-90-215-40.cybernet.ch.smtp: S 2028538653:2028538653(0) win 5840
<mss 1460,sackOK,timestamp 243108498 0,nop,wscale 7> (DF)
11:24:15.076329 cust.static.212-90-215-40.cybernet.ch.smtp >
d59.x-mailer.de.59959: S 2328498080:2328498080(0) ack 2028538654 win 16384 <mss
1400,nop,wscale 0,nop,nop,timestamp 0
0,nop,nop,sackOK>
11:24:15.076352 d59.x-mailer.de.59959 >
cust.static.212-90-215-40.cybernet.ch.smtp: . ack 1 win 46 <nop,nop,timestamp
243108503 0> (DF)
11:24:21.926186 d59.x-mailer.de.59959 >
cust.static.212-90-215-40.cybernet.ch.smtp: F 1:1(0) ack 1 win 46
<nop,nop,timestamp 243109188 0> (DF)
11:24:21.972106 cust.static.212-90-215-40.cybernet.ch.smtp >
d59.x-mailer.de.59959: . ack 2 win 65535 <nop,nop,timestamp 19121191 243109188> (DF)
11:24:21.973980 cust.static.212-90-215-40.cybernet.ch.smtp >
d59.x-mailer.de.59959: F 116:116(0) ack 2 win 65535 <nop,nop,timestamp 19121191
243109188> (DF)
11:24:21.973999 d59.x-mailer.de.59959 >
cust.static.212-90-215-40.cybernet.ch.smtp: R 2028538655:2028538655(0) win 0 (DF)   

### you should get kind of this:

13:56:37.203297 d59.x-mailer.de.43286 >
cust.static.212-90-215-40.cybernet.ch.smtp: S 1489507409:1489507409(0) win 5840
<mss 1460,sackOK,timestamp 16627469 0,nop,wscale 2> (DF)
13:56:37.250827 cust.static.212-90-215-40.cybernet.ch.smtp >
d59.x-mailer.de.43286: S 783498912:783498912(0) ack 1489507410 win 16384 <mss
1400,nop,wscale 0,nop,nop,timestamp 0 0,nop,nop,sackOK>
13:56:37.250888 d59.x-mailer.de.43286 >
cust.static.212-90-215-40.cybernet.ch.smtp: . ack 1 win 1460 <nop,nop,timestamp
16627473 0> (DF)
13:56:37.292170 cust.static.212-90-215-40.cybernet.ch.smtp >
d59.x-mailer.de.43286: P 1:116(115) ack 1 win 65535 <nop,nop,timestamp 20940584
16627469> (DF)
13:56:37.292207 d59.x-mailer.de.43286 >
cust.static.212-90-215-40.cybernet.ch.smtp: . ack 116 win 1460
<nop,nop,timestamp 16627478 20940584> (DF)
13:56:39.373383 d59.x-mailer.de.43286 >
cust.static.212-90-215-40.cybernet.ch.smtp: F 1:1(0) ack 116 win 1460
<nop,nop,timestamp 16627686 20940584> (DF)
13:56:39.413075 cust.static.212-90-215-40.cybernet.ch.smtp >
d59.x-mailer.de.43286: . ack 2 win 65535 <nop,nop,timestamp 20940605 16627686> (DF)
13:56:39.414449 cust.static.212-90-215-40.cybernet.ch.smtp >
d59.x-mailer.de.43286: F 116:116(0) ack 2 win 65535 <nop,nop,timestamp 20940605
16627686> (DF)
13:56:39.414464 d59.x-mailer.de.43286 >
cust.static.212-90-215-40.cybernet.ch.smtp: . ack 117 win 1460
<nop,nop,timestamp 16627690 20940605> (DF)

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.

^ permalink raw reply

* Re: Netchannels: netchannel vs. socket. 2:0.
From: Evgeniy Polyakov @ 2006-06-08 17:40 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev
In-Reply-To: <20060608171555.GA10273@2ka.mipt.ru>

[-- Attachment #1: Type: text/plain, Size: 722 bytes --]

On Thu, Jun 08, 2006 at 09:15:55PM +0400, Evgeniy Polyakov (johnpol@2ka.mipt.ru) wrote:
> After some enhancements made for netchannel subsystem I'm pleased to
> announce, that netchannel subsystem outperforms existing layered design
> both in CPU usage and network speed.
> 
> Well, after such pretentious introduction I want to cool things down.
> CPU usage is about 1-2% less for netchannels and network performance is
> about 1-2 MB higher and sometimes exceeds 84 MB/sec which, I think, 
> is maximum for given network setup (e1000 receive, r8169 send, 1500 MTU).
> 
> It is stable and 100% reproductible result.
> 
> Performance graph and patch are attached.

Hmm, graph has been attached now.

-- 
	Evgeniy Polyakov

[-- Attachment #2: netchannel_speed.png --]
[-- Type: image/png, Size: 6029 bytes --]

^ permalink raw reply

* [DOC] update bonding documentation with sysfs
From: Auke Kok @ 2006-06-08 18:15 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: NetDev, Mitch Williams, Auke Kok, Kok, Auke

[-- Attachment #1: Type: text/plain, Size: 717 bytes --]


Jeff,

Attached patch is pushed on top of #upstream on our git server also containing 
the resent patches earlier today.

Please pull:
   git pull git://lost.foo-projects.org/~ahkok/git/netdev-2.6 upstream

Cheers,

Auke


---
[DOC] Update bonding documentation with sysfs info

Bonding documentation needed an update to include sysfs specific
information. This patch adds information on how to change bonding
parameters at runtime using the sysfs interface.

Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>

---
  bonding.txt |  323 ++++++++++++++++++++++++++++++++++++++++++------------------
  1 file changed, 229 insertions(+), 94 deletions(-)


---

[-- Attachment #2: bonding_doc.patch --]
[-- Type: text/x-patch, Size: 26248 bytes --]

[DOC] Update bonding documentation with sysfs info

Bonding documentation needed an update to include sysfs specific
information. This patch adds information on how to change bonding
parameters at runtime using the sysfs interface.

Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>

---
 bonding.txt |  323 ++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 229 insertions(+), 94 deletions(-)

---
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 8d8b4e5..afac780 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -1,7 +1,7 @@
 
 		Linux Ethernet Bonding Driver HOWTO
 
-		Latest update: 21 June 2005
+		Latest update: 24 April 2006
 
 Initial release : Thomas Davis <tadavis at lbl.gov>
 Corrections, HA extensions : 2000/10/03-15 :
@@ -12,6 +12,8 @@ Corrections, HA extensions : 2000/10/03-
   - Jay Vosburgh <fubar at us dot ibm dot com>
 
 Reorganized and updated Feb 2005 by Jay Vosburgh
+Added Sysfs information: 2006/04/24
+  - Mitch Williams <mitch.a.williams at intel.com>
 
 Introduction
 ============
@@ -38,61 +40,62 @@ Table of Contents
 2. Bonding Driver Options
 
 3. Configuring Bonding Devices
-3.1	Configuration with sysconfig support
-3.1.1		Using DHCP with sysconfig
-3.1.2		Configuring Multiple Bonds with sysconfig
-3.2	Configuration with initscripts support
-3.2.1		Using DHCP with initscripts
-3.2.2		Configuring Multiple Bonds with initscripts
-3.3	Configuring Bonding Manually
+3.1	Configuration with Sysconfig Support
+3.1.1		Using DHCP with Sysconfig
+3.1.2		Configuring Multiple Bonds with Sysconfig
+3.2	Configuration with Initscripts Support
+3.2.1		Using DHCP with Initscripts
+3.2.2		Configuring Multiple Bonds with Initscripts
+3.3	Configuring Bonding Manually with Ifenslave
 3.3.1		Configuring Multiple Bonds Manually
+3.4	Configuring Bonding Manually via Sysfs
 
-5. Querying Bonding Configuration
-5.1	Bonding Configuration
-5.2	Network Configuration
+4. Querying Bonding Configuration
+4.1	Bonding Configuration
+4.2	Network Configuration
 
-6. Switch Configuration
+5. Switch Configuration
 
-7. 802.1q VLAN Support
+6. 802.1q VLAN Support
 
-8. Link Monitoring
-8.1	ARP Monitor Operation
-8.2	Configuring Multiple ARP Targets
-8.3	MII Monitor Operation
+7. Link Monitoring
+7.1	ARP Monitor Operation
+7.2	Configuring Multiple ARP Targets
+7.3	MII Monitor Operation
 
-9. Potential Trouble Sources
-9.1	Adventures in Routing
-9.2	Ethernet Device Renaming
-9.3	Painfully Slow Or No Failed Link Detection By Miimon
+8. Potential Trouble Sources
+8.1	Adventures in Routing
+8.2	Ethernet Device Renaming
+8.3	Painfully Slow Or No Failed Link Detection By Miimon
 
-10. SNMP agents
+9. SNMP agents
 
-11. Promiscuous mode
+10. Promiscuous mode
 
-12. Configuring Bonding for High Availability
-12.1	High Availability in a Single Switch Topology
-12.2	High Availability in a Multiple Switch Topology
-12.2.1		HA Bonding Mode Selection for Multiple Switch Topology
-12.2.2		HA Link Monitoring for Multiple Switch Topology
+11. Configuring Bonding for High Availability
+11.1	High Availability in a Single Switch Topology
+11.2	High Availability in a Multiple Switch Topology
+11.2.1		HA Bonding Mode Selection for Multiple Switch Topology
+11.2.2		HA Link Monitoring for Multiple Switch Topology
 
-13. Configuring Bonding for Maximum Throughput
-13.1	Maximum Throughput in a Single Switch Topology
-13.1.1		MT Bonding Mode Selection for Single Switch Topology
-13.1.2		MT Link Monitoring for Single Switch Topology
-13.2	Maximum Throughput in a Multiple Switch Topology
-13.2.1		MT Bonding Mode Selection for Multiple Switch Topology
-13.2.2		MT Link Monitoring for Multiple Switch Topology
+12. Configuring Bonding for Maximum Throughput
+12.1	Maximum Throughput in a Single Switch Topology
+12.1.1		MT Bonding Mode Selection for Single Switch Topology
+12.1.2		MT Link Monitoring for Single Switch Topology
+12.2	Maximum Throughput in a Multiple Switch Topology
+12.2.1		MT Bonding Mode Selection for Multiple Switch Topology
+12.2.2		MT Link Monitoring for Multiple Switch Topology
 
-14. Switch Behavior Issues
-14.1	Link Establishment and Failover Delays
-14.2	Duplicated Incoming Packets
+13. Switch Behavior Issues
+13.1	Link Establishment and Failover Delays
+13.2	Duplicated Incoming Packets
 
-15. Hardware Specific Considerations
-15.1	IBM BladeCenter
+14. Hardware Specific Considerations
+14.1	IBM BladeCenter
 
-16. Frequently Asked Questions
+15. Frequently Asked Questions
 
-17. Resources and Links
+16. Resources and Links
 
 
 1. Bonding Driver Installation
@@ -156,6 +159,9 @@ you're trying to build it for.  Some dis
 onwards) do not have /usr/include/linux symbolically linked to the
 default kernel source include directory.
 
+SECOND IMPORTANT NOTE:
+	If you plan to configure bonding using sysfs, you do not need
+to use ifenslave.
 
 2. Bonding Driver Options
 =========================
@@ -270,7 +276,7 @@ mode
 		In bonding version 2.6.2 or later, when a failover
 		occurs in active-backup mode, bonding will issue one
 		or more gratuitous ARPs on the newly active slave.
-		One gratutious ARP is issued for the bonding master
+		One gratuitous ARP is issued for the bonding master
 		interface and each VLAN interfaces configured above
 		it, provided that the interface has at least one IP
 		address configured.  Gratuitous ARPs issued for VLAN
@@ -377,7 +383,7 @@ mode
 		When a link is reconnected or a new slave joins the
 		bond the receive traffic is redistributed among all
 		active slaves in the bond by initiating ARP Replies
-		with the selected mac address to each of the
+		with the selected MAC address to each of the
 		clients. The updelay parameter (detailed below) must
 		be set to a value equal or greater than the switch's
 		forwarding delay so that the ARP Replies sent to the
@@ -498,11 +504,12 @@ not exist, and the layer2 policy is the 
 3. Configuring Bonding Devices
 ==============================
 
-	There are, essentially, two methods for configuring bonding:
-with support from the distro's network initialization scripts, and
-without.  Distros generally use one of two packages for the network
-initialization scripts: initscripts or sysconfig.  Recent versions of
-these packages have support for bonding, while older versions do not.
+	You can configure bonding using either your distro's network
+initialization scripts, or manually using either ifenslave or the
+sysfs interface.  Distros generally use one of two packages for the
+network initialization scripts: initscripts or sysconfig.  Recent
+versions of these packages have support for bonding, while older
+versions do not.
 
 	We will first describe the options for configuring bonding for
 distros using versions of initscripts and sysconfig with full or
@@ -530,7 +537,7 @@ issue the command:
 	If this returns any matches, then your initscripts or
 sysconfig has support for bonding.
 
-3.1 Configuration with sysconfig support
+3.1 Configuration with Sysconfig Support
 ----------------------------------------
 
 	This section applies to distros using a version of sysconfig
@@ -538,7 +545,7 @@ with bonding support, for example, SuSE 
 
 	SuSE SLES 9's networking configuration system does support
 bonding, however, at this writing, the YaST system configuration
-frontend does not provide any means to work with bonding devices.
+front end does not provide any means to work with bonding devices.
 Bonding devices can be managed by hand, however, as follows.
 
 	First, if they have not already been configured, configure the
@@ -660,7 +667,7 @@ format can be found in an example ifcfg 
 	Note that the template does not document the various BONDING_
 settings described above, but does describe many of the other options.
 
-3.1.1 Using DHCP with sysconfig
+3.1.1 Using DHCP with Sysconfig
 -------------------------------
 
 	Under sysconfig, configuring a device with BOOTPROTO='dhcp'
@@ -670,7 +677,7 @@ attempt to obtain the device address fro
 the slave devices.  Without active slaves, the DHCP requests are not
 sent to the network.
 
-3.1.2 Configuring Multiple Bonds with sysconfig
+3.1.2 Configuring Multiple Bonds with Sysconfig
 -----------------------------------------------
 
 	The sysconfig network initialization system is capable of
@@ -685,7 +692,7 @@ ifcfg-bondX files.
 options in the ifcfg-bondX file, it is not necessary to add them to
 the system /etc/modules.conf or /etc/modprobe.conf configuration file.
 
-3.2 Configuration with initscripts support
+3.2 Configuration with Initscripts Support
 ------------------------------------------
 
 	This section applies to distros using a version of initscripts
@@ -756,7 +763,7 @@ options for your configuration.
 will restart the networking subsystem and your bond link should be now
 up and running.
 
-3.2.1 Using DHCP with initscripts
+3.2.1 Using DHCP with Initscripts
 ---------------------------------
 
 	Recent versions of initscripts (the version supplied with
@@ -768,7 +775,7 @@ above, except replace the line "BOOTPROT
 and add a line consisting of "TYPE=Bonding".  Note that the TYPE value
 is case sensitive.
 
-3.2.2 Configuring Multiple Bonds with initscripts
+3.2.2 Configuring Multiple Bonds with Initscripts
 -------------------------------------------------
 
 	At this writing, the initscripts package does not directly
@@ -784,8 +791,8 @@ Fedora Core kernels, and has been seen o
 exhibiting this problem, it will be impossible to configure multiple
 bonds with differing parameters.
 
-3.3 Configuring Bonding Manually
---------------------------------
+3.3 Configuring Bonding Manually with Ifenslave
+-----------------------------------------------
 
 	This section applies to distros whose network initialization
 scripts (the sysconfig or initscripts package) do not have specific
@@ -888,12 +895,140 @@ install bond1 /sbin/modprobe --ignore-in
 
 	This may be repeated any number of times, specifying a new and
 unique name in place of bond1 for each subsequent instance.
+
+3.4 Configuring Bonding Manually via Sysfs
+------------------------------------------
+
+	Starting with version 3.0, Channel Bonding may be configured
+via the sysfs interface.  This interface allows dynamic configuration
+of all bonds in the system without unloading the module.  It also
+allows for adding and removing bonds at runtime.  Ifenslave is no
+longer required, though it is still supported.
+
+	Use of the sysfs interface allows you to use multiple bonds
+with different configurations without having to reload the module.
+It also allows you to use multiple, differently configured bonds when
+bonding is compiled into the kernel.
+
+	You must have the sysfs filesystem mounted to configure
+bonding this way.  The examples in this document assume that you
+are using the standard mount point for sysfs, e.g. /sys.  If your
+sysfs filesystem is mounted elsewhere, you will need to adjust the
+example paths accordingly.
+
+Creating and Destroying Bonds
+-----------------------------
+To add a new bond foo:
+# echo +foo > /sys/class/net/bonding_masters
+
+To remove an existing bond bar:
+# echo -bar > /sys/class/net/bonding_masters
+
+To show all existing bonds:
+# cat /sys/class/net/bonding_masters
+
+NOTE: due to 4K size limitation of sysfs files, this list may be
+truncated if you have more than a few hundred bonds.  This is unlikely
+to occur under normal operating conditions.
+
+Adding and Removing Slaves
+--------------------------
+	Interfaces may be enslaved to a bond using the file
+/sys/class/net/<bond>/bonding/slaves.  The semantics for this file
+are the same as for the bonding_masters file.
+
+To enslave interface eth0 to bond bond0:
+# ifconfig bond0 up
+# echo +eth0 > /sys/class/net/bond0/bonding/slaves
+
+To free slave eth0 from bond bond0:
+# echo -eth0 > /sys/class/net/bond0/bonding/slaves
+
+	NOTE: The bond must be up before slaves can be added.  All
+slaves are freed when the interface is brought down.
+
+	When an interface is enslaved to a bond, symlinks between the
+two are created in the sysfs filesystem.  In this case, you would get
+/sys/class/net/bond0/slave_eth0 pointing to /sys/class/net/eth0, and
+/sys/class/net/eth0/master pointing to /sys/class/net/bond0.
+
+	This means that you can tell quickly whether or not an
+interface is enslaved by looking for the master symlink.  Thus:
+# echo -eth0 > /sys/class/net/eth0/master/bonding/slaves
+will free eth0 from whatever bond it is enslaved to, regardless of
+the name of the bond interface.
+
+Changing a Bond's Configuration
+-------------------------------
+	Each bond may be configured individually by manipulating the
+files located in /sys/class/net/<bond name>/bonding
+
+	The names of these files correspond directly with the command-
+line parameters described elsewhere in in this file, and, with the
+exception of arp_ip_target, they accept the same values.  To see the
+current setting, simply cat the appropriate file.
+
+	A few examples will be given here; for specific usage
+guidelines for each parameter, see the appropriate section in this
+document.
+
+To configure bond0 for balance-alb mode:
+# ifconfig bond0 down
+# echo 6 > /sys/class/net/bond0/bonding/mode
+ - or -
+# echo balance-alb > /sys/class/net/bond0/bonding/mode
+	NOTE: The bond interface must be down before the mode can be
+changed.
+
+To enable MII monitoring on bond0 with a 1 second interval:
+# echo 1000 > /sys/class/net/bond0/bonding/miimon
+	NOTE: If ARP monitoring is enabled, it will disabled when MII
+monitoring is enabled, and vice-versa.
+
+To add ARP targets:
+# echo +192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
+# echo +192.168.0.101 > /sys/class/net/bond0/bonding/arp_ip_target
+	NOTE:  up to 10 target addresses may be specified.
+
+To remove an ARP target:
+# echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
+
+Example Configuration
+---------------------
+	We begin with the same example that is shown in section 3.3,
+executed with sysfs, and without using ifenslave.
+
+	To make a simple bond of two e100 devices (presumed to be eth0
+and eth1), and have it persist across reboots, edit the appropriate
+file (/etc/init.d/boot.local or /etc/rc.d/rc.local), and add the
+following:
+
+modprobe bonding
+modprobe e100
+echo balance-alb > /sys/class/net/bond0/bonding/mode
+ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
+echo 100 > /sys/class/net/bond0/bonding/miimon
+echo +eth0 > /sys/class/net/bond0/bonding/slaves
+echo +eth1 > /sys/class/net/bond0/bonding/slaves
+
+	To add a second bond, with two e1000 interfaces in
+active-backup mode, using ARP monitoring, add the following lines to
+your init script:
+
+modprobe e1000
+echo +bond1 > /sys/class/net/bonding_masters
+echo active-backup > /sys/class/net/bond1/bonding/mode
+ifconfig bond1 192.168.2.1 netmask 255.255.255.0 up
+echo +192.168.2.100 /sys/class/net/bond1/bonding/arp_ip_target
+echo 2000 > /sys/class/net/bond1/bonding/arp_interval
+echo +eth2 > /sys/class/net/bond1/bonding/slaves
+echo +eth3 > /sys/class/net/bond1/bonding/slaves
 
 
-5. Querying Bonding Configuration 
+4. Querying Bonding Configuration 
 =================================
 
-5.1 Bonding Configuration
+4.1 Bonding Configuration
 -------------------------
 
 	Each bonding device has a read-only file residing in the
@@ -923,7 +1058,7 @@ generally as follows:
 	The precise format and contents will change depending upon the
 bonding configuration, state, and version of the bonding driver.
 
-5.2 Network configuration
+4.2 Network configuration
 -------------------------
 
 	The network configuration can be inspected using the ifconfig
@@ -958,7 +1093,7 @@ eth1      Link encap:Ethernet  HWaddr 00
           collisions:0 txqueuelen:100
           Interrupt:9 Base address:0x1400
 
-6. Switch Configuration
+5. Switch Configuration
 =======================
 
 	For this section, "switch" refers to whatever system the
@@ -991,7 +1126,7 @@ transmit policy for an EtherChannel grou
 with another EtherChannel group.
 
 
-7. 802.1q VLAN Support
+6. 802.1q VLAN Support
 ======================
 
 	It is possible to configure VLAN devices over a bond interface
@@ -1042,7 +1177,7 @@ underlying device -- i.e. the bonding in
 mode, which might not be what you want.
 
 
-8. Link Monitoring
+7. Link Monitoring
 ==================
 
 	The bonding driver at present supports two schemes for
@@ -1053,7 +1188,7 @@ monitor.
 bonding driver itself, it is not possible to enable both ARP and MII
 monitoring simultaneously.
 
-8.1 ARP Monitor Operation
+7.1 ARP Monitor Operation
 -------------------------
 
 	The ARP monitor operates as its name suggests: it sends ARP
@@ -1071,7 +1206,7 @@ those slaves will stay down.  If network
 shows the ARP requests and replies on the network, then it may be that
 your device driver is not updating last_rx and trans_start.
 
-8.2 Configuring Multiple ARP Targets
+7.2 Configuring Multiple ARP Targets
 ------------------------------------
 
 	While ARP monitoring can be done with just one target, it can
@@ -1094,7 +1229,7 @@ alias bond0 bonding
 options bond0 arp_interval=60 arp_ip_target=192.168.0.100
 
 
-8.3 MII Monitor Operation
+7.3 MII Monitor Operation
 -------------------------
 
 	The MII monitor monitors only the carrier state of the local
@@ -1120,14 +1255,14 @@ does not support or had some error in pr
 and ethtool requests), then the MII monitor will assume the link is
 up.
 
-9. Potential Sources of Trouble
+8. Potential Sources of Trouble
 ===============================
 
-9.1 Adventures in Routing
+8.1 Adventures in Routing
 -------------------------
 
 	When bonding is configured, it is important that the slave
-devices not have routes that supercede routes of the master (or,
+devices not have routes that supersede routes of the master (or,
 generally, not have routes at all).  For example, suppose the bonding
 device bond0 has two slaves, eth0 and eth1, and the routing table is
 as follows:
@@ -1154,11 +1289,11 @@ by the state of the routing table.
 
 	The solution here is simply to insure that slaves do not have
 routes of their own, and if for some reason they must, those routes do
-not supercede routes of their master.  This should generally be the
+not supersede routes of their master.  This should generally be the
 case, but unusual configurations or errant manual or automatic static
 route additions may cause trouble.
 
-9.2 Ethernet Device Renaming
+8.2 Ethernet Device Renaming
 ----------------------------
 
 	On systems with network configuration scripts that do not
@@ -1207,7 +1342,7 @@ modprobe with --ignore-install to cause 
 place.  Full documentation on this can be found in the modprobe.conf
 and modprobe manual pages.
 
-9.3. Painfully Slow Or No Failed Link Detection By Miimon
+8.3. Painfully Slow Or No Failed Link Detection By Miimon
 ---------------------------------------------------------
 
 	By default, bonding enables the use_carrier option, which
@@ -1235,7 +1370,7 @@ carrier state.  It has no way to determi
 beyond other ports of a switch, or if a switch is refusing to pass
 traffic while still maintaining carrier on.
 
-10. SNMP agents
+9. SNMP agents
 ===============
 
 	If running SNMP agents, the bonding driver should be loaded
@@ -1281,7 +1416,7 @@ ifDescr, the association between the IP 
 and SNMP functions such as Interface_Scan_Next will report that
 association.
 
-11. Promiscuous mode
+10. Promiscuous mode
 ====================
 
 	When running network monitoring tools, e.g., tcpdump, it is
@@ -1308,7 +1443,7 @@ sending to peers that are unassigned or 
 the active slave changes (e.g., due to a link failure), the
 promiscuous setting will be propagated to the new active slave.
 
-12. Configuring Bonding for High Availability
+11. Configuring Bonding for High Availability
 =============================================
 
 	High Availability refers to configurations that provide
@@ -1318,7 +1453,7 @@ goal is to provide the maximum availabil
 (i.e., the network always works), even though other configurations
 could provide higher throughput.
 
-12.1 High Availability in a Single Switch Topology
+11.1 High Availability in a Single Switch Topology
 --------------------------------------------------
 
 	If two hosts (or a host and a single switch) are directly
@@ -1332,7 +1467,7 @@ the load will be rebalanced across the r
 	See Section 13, "Configuring Bonding for Maximum Throughput"
 for information on configuring bonding with one peer device.
 
-12.2 High Availability in a Multiple Switch Topology
+11.2 High Availability in a Multiple Switch Topology
 ----------------------------------------------------
 
 	With multiple switches, the configuration of bonding and the
@@ -1359,7 +1494,7 @@ switches (ISL, or inter switch link), an
 the outside world ("port3" on each switch).  There is no technical
 reason that this could not be extended to a third switch.
 
-12.2.1 HA Bonding Mode Selection for Multiple Switch Topology
+11.2.1 HA Bonding Mode Selection for Multiple Switch Topology
 -------------------------------------------------------------
 
 	In a topology such as the example above, the active-backup and
@@ -1381,7 +1516,7 @@ broadcast: This mode is really a special
 	necessary for some specific one-way traffic to reach both
 	independent networks, then the broadcast mode may be suitable.
 
-12.2.2 HA Link Monitoring Selection for Multiple Switch Topology
+11.2.2 HA Link Monitoring Selection for Multiple Switch Topology
 ----------------------------------------------------------------
 
 	The choice of link monitoring ultimately depends upon your
@@ -1402,10 +1537,10 @@ regardless of which switch is active, th
 target to query.
 
 
-13. Configuring Bonding for Maximum Throughput
+12. Configuring Bonding for Maximum Throughput
 ==============================================
 
-13.1 Maximizing Throughput in a Single Switch Topology
+12.1 Maximizing Throughput in a Single Switch Topology
 ------------------------------------------------------
 
 	In a single switch configuration, the best method to maximize
@@ -1476,7 +1611,7 @@ destination to make load balancing decis
 mode is described below.
 
 
-13.1.1 MT Bonding Mode Selection for Single Switch Topology
+12.1.1 MT Bonding Mode Selection for Single Switch Topology
 -----------------------------------------------------------
 
 	This configuration is the easiest to set up and to understand,
@@ -1607,7 +1742,7 @@ balance-alb: This mode is everything tha
 	device driver must support changing the hardware address while
 	the device is open.
 
-13.1.2 MT Link Monitoring for Single Switch Topology
+12.1.2 MT Link Monitoring for Single Switch Topology
 ----------------------------------------------------
 
 	The choice of link monitoring may largely depend upon which
@@ -1616,7 +1751,7 @@ support the use of the ARP monitor, and 
 the MII monitor (which does not provide as high a level of end to end
 assurance as the ARP monitor).
 
-13.2 Maximum Throughput in a Multiple Switch Topology
+12.2 Maximum Throughput in a Multiple Switch Topology
 -----------------------------------------------------
 
 	Multiple switches may be utilized to optimize for throughput
@@ -1651,7 +1786,7 @@ a single 72 port switch.
 can be equipped with an additional network device connected to an
 external network; this host then additionally acts as a gateway.
 
-13.2.1 MT Bonding Mode Selection for Multiple Switch Topology
+12.2.1 MT Bonding Mode Selection for Multiple Switch Topology
 -------------------------------------------------------------
 
 	In actual practice, the bonding mode typically employed in
@@ -1664,7 +1799,7 @@ packets has arrived).  When employed in 
 mode allows individual connections between two hosts to effectively
 utilize greater than one interface's bandwidth.
 
-13.2.2 MT Link Monitoring for Multiple Switch Topology
+12.2.2 MT Link Monitoring for Multiple Switch Topology
 ------------------------------------------------------
 
 	Again, in actual practice, the MII monitor is most often used
@@ -1674,10 +1809,10 @@ advantages over the MII monitor are miti
 needed as the number of systems involved grows (remember that each
 host in the network is configured with bonding).
 
-14. Switch Behavior Issues
+13. Switch Behavior Issues
 ==========================
 
-14.1 Link Establishment and Failover Delays
+13.1 Link Establishment and Failover Delays
 -------------------------------------------
 
 	Some switches exhibit undesirable behavior with regard to the
@@ -1712,7 +1847,7 @@ switches take a long time to go into bac
 to not activate a backup interface immediately after a link goes down.
 Failover may be delayed via the downdelay bonding module option.
 
-14.2 Duplicated Incoming Packets
+13.2 Duplicated Incoming Packets
 --------------------------------
 
 	It is not uncommon to observe a short burst of duplicated
@@ -1751,14 +1886,14 @@ behavior, it can be induced by clearing 
 most Cisco switches, the privileged command "clear mac address-table
 dynamic" will accomplish this).
 
-15. Hardware Specific Considerations
+14. Hardware Specific Considerations
 ====================================
 
 	This section contains additional information for configuring
 bonding on specific hardware platforms, or for interfacing bonding
 with particular switches or other devices.
 
-15.1 IBM BladeCenter
+14.1 IBM BladeCenter
 --------------------
 
 	This applies to the JS20 and similar systems.
@@ -1861,7 +1996,7 @@ (either the internal Ethernet Switch Mod
 avoid fail-over delay issues when using bonding.
 
 	
-16. Frequently Asked Questions
+15. Frequently Asked Questions
 ==============================
 
 1.  Is it SMP safe?
@@ -1925,7 +2060,7 @@ not have special switch requirements, bu
 support specific features (described in the appropriate section under
 module parameters, above).
 
-	In 802.3ad mode, it works with with systems that support IEEE
+	In 802.3ad mode, it works with systems that support IEEE
 802.3ad Dynamic Link Aggregation.  Most managed and many unmanaged
 switches currently available support 802.3ad.
 

^ permalink raw reply related

* Re: [patch 06/17] neighbour.c, pneigh_get_next() skips published entry
From: Jari Takkala @ 2006-06-08 18:21 UTC (permalink / raw)
  To: David Miller, akpm; +Cc: netdev


On Mon, 5 Jun 2006, David Miller wrote:

> This patch doesn't make any sense, I've been over it a few times.
> 
> The seqfile layer should take care of that user buffering issue
transparently as
> long as we implement the interface callbacks properly.
>
> Even if something needs to be fixed in the pneigh dumper, special
casing *pos==1
> doesn't look right.  Also, if pneigh has this problem, how come the
neigh seqfile
> iterators don't have the same problem or do they?

>From my analysis, the problem is that pneigh_get_next() ends up
assigning pn to one entry ahead of what it should be pointing too. This
only occurs when the user's read buffer fills up, where pneigh_get_idx()
is called, which calls pneigh_get_next() until *pos is not true.

I have not checked neigh seqfile iterators, the problem may exist in
there as well. My patch solves this issue for us, however a more elegant
solution would be most welcome.  Could the root of the problem be that
*pos is off by one when pneigh_get_idx() is called?

Jari


^ permalink raw reply

* Re: [PATCH 1/2] e1000: fix netpoll with NAPI
From: John W. Linville @ 2006-06-08 18:39 UTC (permalink / raw)
  To: Mitch Williams
  Cc: Kok, Auke-jan H, Matt Mackall, Garzik, Jeff, Neil Horman,
	Jeff Moyer, netdev, Brandeburg, Jesse, Kok, Auke
In-Reply-To: <1149787436.2928.9.camel@strongmad>

On Thu, Jun 08, 2006 at 10:23:56AM -0700, Mitch Williams wrote:
> On Wed, 2006-06-07 at 11:54 -0700, John W. Linville wrote:
> 
> > Pedantic objection, but I think this would read easier w/o the extra
> > newline before disable_irq.
> 
> Heh.  I prefer to have a newline between declarations and code.  The

Normally I would agree.  But in this case, I find the distraction of
the random newline after the #else to be more compelling.

> real problem is the position of the #ifdef -- that's what makes it
> difficult to read.  The other solution would be
> {
>         struct e1000_adapter *adapter = netdev_priv(netdev);
> #ifdef CONFIG_E1000_NAPI
> 	int budget = 0;
> #endif
> 
> 	disable_irq(adapter->pdev->irq);
> 
> #ifdef CONFIG_E1000_NAPI
> 	< all that stuff >
> #else
> 	<rest of the stuff >
> #endif
> }
> 
> Which I think is worse to read.

I presume it is the double #ifdef that you find objectionable?
I don't really like it, but at least that idiom is quite common.

Given that the disable_irq appears in both code paths (almost by
necessity), there is a certain appeal to having it outside of the
#ifdef block.  That seems more maintainable.

To me, the idiomatic #ifdef placement seems more readable, if for no
other reason than familiarity.  I suppose we can agree to disagree.

John
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply

* Re: [PATCH 2.6.17-rc6-mm1 ] net: RFC 3828-compliant UDP-Lite support
From: David Miller @ 2006-06-08 18:51 UTC (permalink / raw)
  To: gerrit; +Cc: yoshfuji, kuznet, pekkas, jmorris, kaber, linux-kernel, netdev
In-Reply-To: <200606081222.54856.gerrit@erg.abdn.ac.uk>

From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Date: Thu, 8 Jun 2006 12:22:54 +0100

> I am sorry, I don't at the moment have the time to port to v6 with the
> same degree of rigour. 

You give the impression that you would just disappear from the face of
the planet should your work actually be integrated into the kernel
tree.

So I can only assume that you are posting this for people to play
around with, and not for serious consideration of inclusion into the
kernel tree.

We're trying to avoid this serious problem we have where a group or
individual submits on a piece of code, works just hard enough to get
it integrated into the tree, then disappears and does not stick around
to support the inevitable ensuing bugs and problem reports.  Such
behavior is totally irresponsible, yet it happens quite a bit.

So if you can't be bothered to cook up IPV6 support, chances are you
won't stick around to support your code if it went into the tree
either.

^ permalink raw reply

* Re: [PATCH 2.6.17-rc6-mm1 ] net: RFC 3828-compliant UDP-Lite support
From: David Miller @ 2006-06-08 18:53 UTC (permalink / raw)
  To: gerrit; +Cc: alan, kuznet, pekkas, jmorris, yoshfuji, kaber, linux-kernel,
	netdev
In-Reply-To: <200606081703.55361.gerrit@erg.abdn.ac.uk>

From: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Date: Thu, 8 Jun 2006 17:03:54 +0100

> Understood. Please, anyone, disregard or un-apply the previous
> UDP-Lite patch.  A revised patch will be prepared and posted as soon
> as testing permits.

Nobody is going to integrate your patch anywhere, don't worry.
You make it clear that once you toss this piece of code over
the wall, you'll disappear.

^ permalink raw reply

* Firewall question
From: Alex Davis @ 2006-06-08 18:57 UTC (permalink / raw)
  To: netfilter, netdev

The scenario:
I have a DSL modem in pass through (bridge) mode. The linux firewall/router 
has a single ethernet card.  It is running pppoe. This gives two interfaces: 
eth0 and ppp0. The firewall is running iptables. There are several machines 
behind the firewall.

Problem:
I've been told that if someone whose public IP address is on the same
network subnet as mine were to get my mac address, (s)he could bypass
the firewall and talk directly to the machines behind it.

Is this true?

Thanks.


I code, therefore I am

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

^ permalink raw reply

* Re: [Bugme-new] [Bug 6666] New: invalid tcp socket connection to windows stacks
From: David Miller @ 2006-06-08 18:57 UTC (permalink / raw)
  To: akpm; +Cc: netdev, technik, bugme-daemon
In-Reply-To: <20060608103627.23cfc83a.akpm@osdl.org>


FIN only gets output when the connection is actually closed
for sending, and that is controlled by the application not
by the kernel.

^ permalink raw reply

* Re: Firewall question
From: Lennart Sorensen @ 2006-06-08 19:26 UTC (permalink / raw)
  To: Alex Davis; +Cc: netfilter, netdev
In-Reply-To: <20060608185712.79340.qmail@web50207.mail.yahoo.com>

On Thu, Jun 08, 2006 at 11:57:12AM -0700, Alex Davis wrote:
> The scenario:
> I have a DSL modem in pass through (bridge) mode. The linux firewall/router 
> has a single ethernet card.  It is running pppoe. This gives two interfaces: 
> eth0 and ppp0. The firewall is running iptables. There are several machines 
> behind the firewall.
> 
> Problem:
> I've been told that if someone whose public IP address is on the same
> network subnet as mine were to get my mac address, (s)he could bypass
> the firewall and talk directly to the machines behind it.
> 
> Is this true?

Well the DSL modem only transfers whatever data the ISP end sends to it,
which in your case is just PPP packets (LCC or LCP I think).  No one out
on the internet would be able to send ethernet data over the DSL link,
so the only way to send data to another machine on your network (that
the DSL modem is connected to physically) is if you have other machines
on your local network which are also running PPPoE and listening for
that traffic.

So the worst thing I can see happening is that someone on your local
network could potentially take over your PPPoE session, but that's about
it.  I just can't see anything else that could happen.  I used to run
exactly the setup you describe before I had to drop the DSL connection
(I moved).

Len Sorensen

^ permalink raw reply

* Using netconsole for debugging suspend/resume
From: Jeremy Fitzhardinge @ 2006-06-08 17:50 UTC (permalink / raw)
  To: Matt Mackall, Linux Kernel Mailing List, netdev

I've been trying to get suspend/resume working well on my new laptop.  
In general, netconsole has been pretty useful for extracting oopses and 
other messages, but it is of more limited help in debugging the actual 
suspend/resume cycle.  The problem looks like the e1000 driver won't 
suspend while netconsole is using it, so I have to rmmod/modprobe 
netconsole around the actual suspend/resume.

This is a big problem during resume because the screen is also blank, so 
I get no useful clue as to what went wrong when things go wrong.  I'm 
wondering if there's some way to keep netconsole alive to the last 
possible moment during suspend, and re-woken as soon as possible during 
resume.  It would be nice to have a clean solution, but I'm willing to 
use a bletcherous hack if that's what it takes.

Any ideas?

Thanks,
    J


^ permalink raw reply

* Re: [PATCH 9/10] Add Vitesse 8244 PHY for MPC8641 HPCN platform.
From: Jeff Garzik @ 2006-06-08 19:34 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org, netdev
In-Reply-To: <1149720298.23938.207.camel@cashmere.sps.mot.com>

Jon Loeliger wrote:
> Signed-off-by: Kriston Carson <KristonCarson@freescale.com>
> Signed-off-by: Xianghua Xiao <x.xiao@freescale.com>
> Signed-off-by: Jon Loeliger <jdl@freescale.com>

ACK, but patch does not apply to netdev-2.6.git#upstream.

	Jeff




^ permalink raw reply

* Re: [PATCH 1/5] skge: use workq for PHY handling
From: Jeff Garzik @ 2006-06-08 19:45 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20060606171341.432229000@zqx3.pdx.osdl.net>

applied 1-5 to #upstream



^ permalink raw reply

* Re: [PATCH 2.6.17-rc6-mm1 ] net: RFC 3828-compliant UDP-Lite support
From: James Morris @ 2006-06-08 19:46 UTC (permalink / raw)
  To: David Miller
  Cc: gerrit, alan, kuznet, pekkas, yoshfuji, kaber, linux-kernel,
	netdev
In-Reply-To: <20060608.115331.71094388.davem@davemloft.net>

On Thu, 8 Jun 2006, David Miller wrote:

> > Understood. Please, anyone, disregard or un-apply the previous
> > UDP-Lite patch.  A revised patch will be prepared and posted as soon
> > as testing permits.
> 
> Nobody is going to integrate your patch anywhere, don't worry.
> You make it clear that once you toss this piece of code over
> the wall, you'll disappear.

Having dealt with more than enough code thrown over the wall in recent 
times, I agree.

But, if someone well known & trusted wants to claim responsibility for the 
code once it's upstream, that might be a way forward (I think the Apache 
project has or had a policy like this).



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply

* Re: Please pull 'upstream-fixes' branch of wireless-2.6
From: Jeff Garzik @ 2006-06-08 19:46 UTC (permalink / raw)
  To: jeff, netdev
In-Reply-To: <20060605215353.GA7381@tuxdriver.com>

John W. Linville wrote:
> This pull is intended for 2.6.17 if at all possible.
> 
> Thanks,
> 
> John
> 
> ---
> 
> The following changes since commit 672c6108a51bf559d19595d9f8193dfd81f0f752:
>   Linus Torvalds:
>         Merge master.kernel.org:/.../jejb/scsi-rc-fixes-2.6
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream-fixes

pulled



^ permalink raw reply

* Re: Please pull 'upstream' branch of wireless-2.6
From: Jeff Garzik @ 2006-06-08 19:48 UTC (permalink / raw)
  To: John W. Linville, netdev
In-Reply-To: <20060605215513.GB7381@tuxdriver.com>

John W. Linville wrote:
> This pull is intended for 2.6.18.
> 
> Thanks,
> 
> John
> 
> ---
> 
> The following changes since commit f6882a0688ea83db5fc2f3491ac9fcdce0834cc7:
>   John W. Linville:
>         Merge branch 'upstream-fixes' into upstream
> 
> are found in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git upstream

applied


^ permalink raw reply

* Re: [PATCH 2.6.17-rc6-mm1 ] net: RFC 3828-compliant UDP-Lite support
From: Gerrit Renker @ 2006-06-08 20:09 UTC (permalink / raw)
  To: James Morris
  Cc: David Miller, alan, kuznet, pekkas, yoshfuji, kaber, linux-kernel,
	netdev
In-Reply-To: <Pine.LNX.4.64.0606081542390.3555@d.namei>

Quoting James Morris:
|  On Thu, 8 Jun 2006, David Miller wrote:
|  
|  > > Understood. Please, anyone, disregard or un-apply the previous
|  > > UDP-Lite patch.  A revised patch will be prepared and posted as soon
|  > > as testing permits.
|  > 
|  > Nobody is going to integrate your patch anywhere, don't worry.
|  > You make it clear that once you toss this piece of code over
|  > the wall, you'll disappear.
|  
|  Having dealt with more than enough code thrown over the wall in recent 
|  times, I agree.

I understand the points of both of you well enough. But how come this is interpreted 
as saying I'd "toss this piece of code over the wall"? I can understand getting tired 
of cowboy coding jobs, but there is a misunderstanding here.

Of course do and will I maintain that code and every issue related it. I have been
maintaining, improving, testing this code for 9 months. The protocol spec (RFC 3828)
was developed at University of Aberdeen, and there is continuing research into 
UDP-Lite here, i.e. it is not a `dead' project. That is why I held back regarding the 
IPv6 port: I can ensure that this (IPv4) code is up to standard and to date, but am 
lacking the required additional time to implement the same for IPv6. 
I am trying to contact people to help with the port, but for the moment I will take 
responsibility only for the IPv4 version.

And if there is someone `well-known and respected' who is interested in taking this code 
over, I would only be happy for him/her to do this. But I won't simply `disappear' :-)







^ permalink raw reply

* Re: [PATCH 9/10] Add Vitesse 8244 PHY for MPC8641 HPCN platform.
From: Jon Loeliger @ 2006-06-08 20:13 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linuxppc-dev@ozlabs.org, netdev
In-Reply-To: <44887BD3.7000009@garzik.org>

On Thu, 2006-06-08 at 14:34, Jeff Garzik wrote:
> Jon Loeliger wrote:
> > Signed-off-by: Kriston Carson <KristonCarson@freescale.com>
> > Signed-off-by: Xianghua Xiao <x.xiao@freescale.com>
> > Signed-off-by: Jon Loeliger <jdl@freescale.com>
> 
> ACK, but patch does not apply to netdev-2.6.git#upstream.
> 
> 	Jeff

Thanks, Jeff.

Are you willing to take the netdev parts as-is, then?
Or would you like me to reformat the netdev parts to
apply against the netdev-2.6.git#upstream branch?
The patch is currently for the Paul Mackerras powerpc.git
tree as it stands now.  Should we apply it through that
path now as you have ACK'ed it?

Thanks,
jdl



^ permalink raw reply

* Re: Using netconsole for debugging suspend/resume
From: Auke Kok @ 2006-06-08 20:35 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: Matt Mackall, Linux Kernel Mailing List, netdev
In-Reply-To: <44886381.9050506@goop.org>

Jeremy Fitzhardinge wrote:
> I've been trying to get suspend/resume working well on my new laptop.  
> In general, netconsole has been pretty useful for extracting oopses and 
> other messages, but it is of more limited help in debugging the actual 
> suspend/resume cycle.  The problem looks like the e1000 driver won't 
> suspend while netconsole is using it, so I have to rmmod/modprobe 
> netconsole around the actual suspend/resume.
> 
> This is a big problem during resume because the screen is also blank, so 
> I get no useful clue as to what went wrong when things go wrong.  I'm 
> wondering if there's some way to keep netconsole alive to the last 
> possible moment during suspend, and re-woken as soon as possible during 
> resume.  It would be nice to have a clean solution, but I'm willing to 
> use a bletcherous hack if that's what it takes.
> 
> Any ideas?

Have you tried using different cards/drivers? This might or might not be 
either a netconsole problem (generic) or driver related (which could impact 
other drivers too).

 From the top of my head I don't see any reason why the e1000 shouldn't handle 
the suspend event - but mind you that a fix for e1000/WoL impacting shutdown 
handlers was only recently added. Which kernels does this impact?

Auke

^ permalink raw reply

* Re: [PATCH 9/10] Add Vitesse 8244 PHY for MPC8641 HPCN platform.
From: Jeff Garzik @ 2006-06-08 20:36 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org, netdev
In-Reply-To: <1149797603.23938.251.camel@cashmere.sps.mot.com>

Jon Loeliger wrote:
> On Thu, 2006-06-08 at 14:34, Jeff Garzik wrote:
>> Jon Loeliger wrote:
>>> Signed-off-by: Kriston Carson <KristonCarson@freescale.com>
>>> Signed-off-by: Xianghua Xiao <x.xiao@freescale.com>
>>> Signed-off-by: Jon Loeliger <jdl@freescale.com>
>> ACK, but patch does not apply to netdev-2.6.git#upstream.
>>
>> 	Jeff
> 
> Thanks, Jeff.
> 
> Are you willing to take the netdev parts as-is, then?
> Or would you like me to reformat the netdev parts to
> apply against the netdev-2.6.git#upstream branch?
> The patch is currently for the Paul Mackerras powerpc.git
> tree as it stands now.  Should we apply it through that
> path now as you have ACK'ed it?

Is it dependent on other stuff in Paul's tree?

Normally this should come through netdev-2.6.git#upstream...

	Jeff




^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox