Преглед изворни кода

Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6.15

Linus Torvalds пре 19 година
родитељ
комит
236fa08168

+ 2 - 1
include/linux/skbuff.h

@@ -171,7 +171,6 @@ enum {
  *	struct sk_buff - socket buffer
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
  *	@next: Next buffer in list
  *	@prev: Previous buffer in list
  *	@prev: Previous buffer in list
- *	@list: List we are on
  *	@sk: Socket we are owned by
  *	@sk: Socket we are owned by
  *	@tstamp: Time we arrived
  *	@tstamp: Time we arrived
  *	@dev: Device we arrived on/are leaving by
  *	@dev: Device we arrived on/are leaving by
@@ -190,6 +189,7 @@ enum {
  *	@cloned: Head may be cloned (check refcnt to be sure)
  *	@cloned: Head may be cloned (check refcnt to be sure)
  *	@nohdr: Payload reference only, must not modify header
  *	@nohdr: Payload reference only, must not modify header
  *	@pkt_type: Packet class
  *	@pkt_type: Packet class
+ *	@fclone: skbuff clone status
  *	@ip_summed: Driver fed us an IP checksum
  *	@ip_summed: Driver fed us an IP checksum
  *	@priority: Packet queueing priority
  *	@priority: Packet queueing priority
  *	@users: User count - see {datagram,tcp}.c
  *	@users: User count - see {datagram,tcp}.c
@@ -202,6 +202,7 @@ enum {
  *	@destructor: Destruct function
  *	@destructor: Destruct function
  *	@nfmark: Can be used for communication between hooks
  *	@nfmark: Can be used for communication between hooks
  *	@nfct: Associated connection, if any
  *	@nfct: Associated connection, if any
+ *	@ipvs_property: skbuff is owned by ipvs
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nfctinfo: Relationship of this skb to the connection
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *	@tc_index: Traffic control index
  *	@tc_index: Traffic control index

+ 0 - 1
include/net/dst.h

@@ -94,7 +94,6 @@ struct dst_ops
 	struct dst_entry *	(*negative_advice)(struct dst_entry *);
 	struct dst_entry *	(*negative_advice)(struct dst_entry *);
 	void			(*link_failure)(struct sk_buff *);
 	void			(*link_failure)(struct sk_buff *);
 	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
 	void			(*update_pmtu)(struct dst_entry *dst, u32 mtu);
-	int			(*get_mss)(struct dst_entry *dst, u32 mtu);
 	int			entry_size;
 	int			entry_size;
 
 
 	atomic_t		entries;
 	atomic_t		entries;

+ 1 - 4
net/core/neighbour.c

@@ -1625,12 +1625,9 @@ static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
 
 
 		memset(&ndst, 0, sizeof(ndst));
 		memset(&ndst, 0, sizeof(ndst));
 
 
-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		for_each_cpu(cpu) {
 			struct neigh_statistics	*st;
 			struct neigh_statistics	*st;
 
 
-			if (!cpu_possible(cpu))
-				continue;
-
 			st = per_cpu_ptr(tbl->stats, cpu);
 			st = per_cpu_ptr(tbl->stats, cpu);
 			ndst.ndts_allocs		+= st->allocs;
 			ndst.ndts_allocs		+= st->allocs;
 			ndst.ndts_destroys		+= st->destroys;
 			ndst.ndts_destroys		+= st->destroys;

+ 229 - 277
net/core/pktgen.c

@@ -75,7 +75,7 @@
  * By design there should only be *one* "controlling" process. In practice 
  * By design there should only be *one* "controlling" process. In practice 
  * multiple write accesses gives unpredictable result. Understood by "write" 
  * multiple write accesses gives unpredictable result. Understood by "write" 
  * to /proc gives result code thats should be read be the "writer".
  * to /proc gives result code thats should be read be the "writer".
- * For pratical use this should be no problem.
+ * For practical use this should be no problem.
  *
  *
  * Note when adding devices to a specific CPU there good idea to also assign 
  * Note when adding devices to a specific CPU there good idea to also assign 
  * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU. 
  * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU. 
@@ -96,7 +96,7 @@
  * New xmit() return, do_div and misc clean up by Stephen Hemminger 
  * New xmit() return, do_div and misc clean up by Stephen Hemminger 
  * <shemminger@osdl.org> 040923
  * <shemminger@osdl.org> 040923
  *
  *
- * Rany Dunlap fixed u64 printk compiler waring 
+ * Randy Dunlap fixed u64 printk compiler waring 
  *
  *
  * Remove FCS from BW calculation.  Lennert Buytenhek <buytenh@wantstofly.org>
  * Remove FCS from BW calculation.  Lennert Buytenhek <buytenh@wantstofly.org>
  * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213
  * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213
@@ -137,6 +137,7 @@
 #include <linux/ipv6.h>
 #include <linux/ipv6.h>
 #include <linux/udp.h>
 #include <linux/udp.h>
 #include <linux/proc_fs.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/wait.h>
 #include <linux/wait.h>
 #include <net/checksum.h>
 #include <net/checksum.h>
 #include <net/ipv6.h>
 #include <net/ipv6.h>
@@ -151,7 +152,7 @@
 #include <asm/timex.h>
 #include <asm/timex.h>
 
 
 
 
-#define VERSION  "pktgen v2.62: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.63: Packet Generator for packet performance testing.\n"
 
 
 /* #define PG_DEBUG(a) a */
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a) 
 #define PG_DEBUG(a) 
@@ -177,8 +178,8 @@
 #define T_REMDEV      (1<<3)  /* Remove all devs */
 #define T_REMDEV      (1<<3)  /* Remove all devs */
 
 
 /* Locks */
 /* Locks */
-#define   thread_lock()        spin_lock(&_thread_lock)
-#define   thread_unlock()      spin_unlock(&_thread_lock)
+#define   thread_lock()        down(&pktgen_sem)
+#define   thread_unlock()      up(&pktgen_sem)
 
 
 /* If lock -- can be removed after some work */
 /* If lock -- can be removed after some work */
 #define   if_lock(t)           spin_lock(&(t->if_lock));
 #define   if_lock(t)           spin_lock(&(t->if_lock));
@@ -186,7 +187,9 @@
 
 
 /* Used to help with determining the pkts on receive */
 /* Used to help with determining the pkts on receive */
 #define PKTGEN_MAGIC 0xbe9be955
 #define PKTGEN_MAGIC 0xbe9be955
-#define PG_PROC_DIR "net/pktgen"
+#define PG_PROC_DIR "pktgen"
+#define PGCTRL	    "pgctrl"
+static struct proc_dir_entry *pg_proc_dir = NULL;
 
 
 #define MAX_CFLOWS  65536
 #define MAX_CFLOWS  65536
 
 
@@ -202,11 +205,8 @@ struct pktgen_dev {
 	 * Try to keep frequent/infrequent used vars. separated.
 	 * Try to keep frequent/infrequent used vars. separated.
 	 */
 	 */
 
 
-        char ifname[32];
-        struct proc_dir_entry *proc_ent;
+        char ifname[IFNAMSIZ];
         char result[512];
         char result[512];
-        /* proc file names */
-        char fname[80];
 
 
         struct pktgen_thread* pg_thread; /* the owner */
         struct pktgen_thread* pg_thread; /* the owner */
         struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */
         struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */
@@ -244,7 +244,7 @@ struct pktgen_dev {
         __u32 seq_num;
         __u32 seq_num;
         
         
         int clone_skb; /* Use multiple SKBs during packet gen.  If this number
         int clone_skb; /* Use multiple SKBs during packet gen.  If this number
-                          * is greater than 1, then that many coppies of the same
+                          * is greater than 1, then that many copies of the same
                           * packet will be sent before a new packet is allocated.
                           * packet will be sent before a new packet is allocated.
                           * For instance, if you want to send 1024 identical packets
                           * For instance, if you want to send 1024 identical packets
                           * before creating a new packet, set clone_skb to 1024.
                           * before creating a new packet, set clone_skb to 1024.
@@ -330,8 +330,6 @@ struct pktgen_thread {
         struct pktgen_dev *if_list;           /* All device here */
         struct pktgen_dev *if_list;           /* All device here */
         struct pktgen_thread* next;
         struct pktgen_thread* next;
         char name[32];
         char name[32];
-        char fname[128]; /* name of proc file */
-        struct proc_dir_entry *proc_ent;
         char result[512];
         char result[512];
         u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
         u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
         
         
@@ -396,7 +394,7 @@ static inline s64 divremdi3(s64 x, s64 y, int type)
 
 
 /* End of hacks to deal with 64-bit math on x86 */
 /* End of hacks to deal with 64-bit math on x86 */
 
 
-/** Convert to miliseconds */
+/** Convert to milliseconds */
 static inline __u64 tv_to_ms(const struct timeval* tv) 
 static inline __u64 tv_to_ms(const struct timeval* tv) 
 {
 {
         __u64 ms = tv->tv_usec / 1000;
         __u64 ms = tv->tv_usec / 1000;
@@ -425,7 +423,7 @@ static inline __u64 pg_div64(__u64 n, __u64 base)
 {
 {
         __u64 tmp = n;
         __u64 tmp = n;
 /*
 /*
- * How do we know if the architectrure we are running on
+ * How do we know if the architecture we are running on
  * supports division with 64 bit base?
  * supports division with 64 bit base?
  * 
  * 
  */
  */
@@ -473,16 +471,6 @@ static inline __u64 tv_diff(const struct timeval* a, const struct timeval* b)
 
 
 static char version[] __initdata = VERSION;
 static char version[] __initdata = VERSION;
 
 
-static ssize_t proc_pgctrl_read(struct file* file, char __user * buf, size_t count, loff_t *ppos);
-static ssize_t proc_pgctrl_write(struct file* file, const char __user * buf, size_t count, loff_t *ppos);
-static int proc_if_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
-
-static int proc_thread_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
-static int proc_if_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
-static int proc_thread_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
-static int create_proc_dir(void);
-static int remove_proc_dir(void);
-
 static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i);
 static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i);
 static int pktgen_add_device(struct pktgen_thread* t, const char* ifname);
 static int pktgen_add_device(struct pktgen_thread* t, const char* ifname);
 static struct pktgen_thread* pktgen_find_thread(const char* name);
 static struct pktgen_thread* pktgen_find_thread(const char* name);
@@ -503,83 +491,41 @@ static int pg_delay_d = 0;
 static int pg_clone_skb_d = 0;
 static int pg_clone_skb_d = 0;
 static int debug = 0;
 static int debug = 0;
 
 
-static DEFINE_SPINLOCK(_thread_lock);
+static DECLARE_MUTEX(pktgen_sem);
 static struct pktgen_thread *pktgen_threads = NULL;
 static struct pktgen_thread *pktgen_threads = NULL;
 
 
-static char module_fname[128];
-static struct proc_dir_entry *module_proc_ent = NULL;
-
 static struct notifier_block pktgen_notifier_block = {
 static struct notifier_block pktgen_notifier_block = {
 	.notifier_call = pktgen_device_event,
 	.notifier_call = pktgen_device_event,
 };
 };
 
 
-static struct file_operations pktgen_fops = {
-        .read     = proc_pgctrl_read,
-        .write    = proc_pgctrl_write,
-	/*  .ioctl    = pktgen_ioctl, later maybe */
-};
-
 /*
 /*
  * /proc handling functions 
  * /proc handling functions 
  *
  *
  */
  */
 
 
-static struct proc_dir_entry *pg_proc_dir = NULL;
-static int proc_pgctrl_read_eof=0;
-
-static ssize_t proc_pgctrl_read(struct file* file, char __user * buf,
-                                 size_t count, loff_t *ppos)
+static int pgctrl_show(struct seq_file *seq, void *v)
 { 
 { 
-	char data[200];
-	int len = 0;
-
-	if(proc_pgctrl_read_eof) {
-		proc_pgctrl_read_eof=0;
-		len = 0;
-		goto out;
-	}
-
-	sprintf(data, "%s", VERSION); 
-
-	len = strlen(data);
-
-	if(len > count) {
-		len =-EFAULT;
-		goto out;
-	}  	
-
-	if (copy_to_user(buf, data, len)) {
-		len =-EFAULT;
-		goto out;
-	}  
-
-	*ppos += len;
-	proc_pgctrl_read_eof=1; /* EOF next call */
-
- out:
-	return len;
+	seq_puts(seq, VERSION);
+	return 0;
 }
 }
 
 
-static ssize_t proc_pgctrl_write(struct file* file,const char __user * buf,
-				 size_t count, loff_t *ppos)
+static ssize_t pgctrl_write(struct file* file,const char __user * buf,
+			    size_t count, loff_t *ppos)
 {
 {
-	char *data = NULL;
 	int err = 0;
 	int err = 0;
+	char data[128];
 
 
         if (!capable(CAP_NET_ADMIN)){
         if (!capable(CAP_NET_ADMIN)){
                 err = -EPERM;
                 err = -EPERM;
 		goto out;
 		goto out;
         }
         }
 
 
-	data = (void*)vmalloc ((unsigned int)count);
+	if (count > sizeof(data))
+		count = sizeof(data);
 
 
-	if(!data) {
-		err = -ENOMEM;
-		goto out;
-	}
 	if (copy_from_user(data, buf, count)) {
 	if (copy_from_user(data, buf, count)) {
-		err =-EFAULT;
-		goto out_free;
+		err = -EFAULT;
+		goto out;
 	}  
 	}  
 	data[count-1] = 0; /* Make string */
 	data[count-1] = 0; /* Make string */
 
 
@@ -594,31 +540,40 @@ static ssize_t proc_pgctrl_write(struct file* file,const char __user * buf,
 
 
 	err = count;
 	err = count;
 
 
- out_free:
-	vfree (data);
  out:
  out:
         return err;
         return err;
 }
 }
 
 
-static int proc_if_read(char *buf , char **start, off_t offset,
-                           int len, int *eof, void *data)
+static int pgctrl_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pgctrl_show, PDE(inode)->data);
+}
+
+static struct file_operations pktgen_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pgctrl_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pgctrl_write,
+	.release  = single_release,
+};
+
+static int pktgen_if_show(struct seq_file *seq, void *v)
 {
 {
-	char *p;
 	int i;
 	int i;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
+        struct pktgen_dev *pkt_dev = seq->private;
         __u64 sa;
         __u64 sa;
         __u64 stopped;
         __u64 stopped;
         __u64 now = getCurUs();
         __u64 now = getCurUs();
         
         
-	p = buf;
-	p += sprintf(p, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
-		     (unsigned long long) pkt_dev->count,
-		     pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
+	seq_printf(seq, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
+		   (unsigned long long) pkt_dev->count,
+		   pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
 
 
-	p += sprintf(p, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
-                     pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
+	seq_printf(seq, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
+		   pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
 
 
-	p += sprintf(p, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
+	seq_printf(seq, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
 
 
 
 
 	if(pkt_dev->flags & F_IPV6) {
 	if(pkt_dev->flags & F_IPV6) {
@@ -626,19 +581,19 @@ static int proc_if_read(char *buf , char **start, off_t offset,
 		fmt_ip6(b1,  pkt_dev->in6_saddr.s6_addr);
 		fmt_ip6(b1,  pkt_dev->in6_saddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->min_in6_saddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->min_in6_saddr.s6_addr);
 		fmt_ip6(b3,  pkt_dev->max_in6_saddr.s6_addr);
 		fmt_ip6(b3,  pkt_dev->max_in6_saddr.s6_addr);
-		p += sprintf(p, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
+		seq_printf(seq, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
 
 
 		fmt_ip6(b1,  pkt_dev->in6_daddr.s6_addr);
 		fmt_ip6(b1,  pkt_dev->in6_daddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->min_in6_daddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->min_in6_daddr.s6_addr);
 		fmt_ip6(b3,  pkt_dev->max_in6_daddr.s6_addr);
 		fmt_ip6(b3,  pkt_dev->max_in6_daddr.s6_addr);
-		p += sprintf(p, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
+		seq_printf(seq, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
 
 
 	} 
 	} 
 	else 
 	else 
-		p += sprintf(p, "     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
-                     pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
+		seq_printf(seq,"     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
+			   pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
 
 
-        p += sprintf(p, "     src_mac: ");
+	seq_puts(seq, "     src_mac: ");
 
 
 	if ((pkt_dev->src_mac[0] == 0) && 
 	if ((pkt_dev->src_mac[0] == 0) && 
 	    (pkt_dev->src_mac[1] == 0) && 
 	    (pkt_dev->src_mac[1] == 0) && 
@@ -648,89 +603,89 @@ static int proc_if_read(char *buf , char **start, off_t offset,
 	    (pkt_dev->src_mac[5] == 0)) 
 	    (pkt_dev->src_mac[5] == 0)) 
 
 
 		for (i = 0; i < 6; i++) 
 		for (i = 0; i < 6; i++) 
-			p += sprintf(p, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
+			seq_printf(seq,  "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
 
 
 	else 
 	else 
 		for (i = 0; i < 6; i++) 
 		for (i = 0; i < 6; i++) 
-			p += sprintf(p, "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
+			seq_printf(seq,  "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
 
 
-        p += sprintf(p, "dst_mac: ");
+        seq_printf(seq,  "dst_mac: ");
 	for (i = 0; i < 6; i++) 
 	for (i = 0; i < 6; i++) 
-		p += sprintf(p, "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
+		seq_printf(seq,  "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
 
 
-        p += sprintf(p, "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
-                     pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
-                     pkt_dev->udp_dst_max);
+        seq_printf(seq,  "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
+		   pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
+		   pkt_dev->udp_dst_max);
 
 
-        p += sprintf(p, "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
-                     pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
+        seq_printf(seq,  "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
+		   pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
 
 
 
 
         if (pkt_dev->flags &  F_IPV6) 
         if (pkt_dev->flags &  F_IPV6) 
-                p += sprintf(p, "IPV6  ");
+                seq_printf(seq,  "IPV6  ");
 
 
         if (pkt_dev->flags &  F_IPSRC_RND) 
         if (pkt_dev->flags &  F_IPSRC_RND) 
-                p += sprintf(p, "IPSRC_RND  ");
+                seq_printf(seq,  "IPSRC_RND  ");
 
 
         if (pkt_dev->flags & F_IPDST_RND) 
         if (pkt_dev->flags & F_IPDST_RND) 
-                p += sprintf(p, "IPDST_RND  ");
+                seq_printf(seq,  "IPDST_RND  ");
         
         
         if (pkt_dev->flags & F_TXSIZE_RND) 
         if (pkt_dev->flags & F_TXSIZE_RND) 
-                p += sprintf(p, "TXSIZE_RND  ");
+                seq_printf(seq,  "TXSIZE_RND  ");
         
         
         if (pkt_dev->flags & F_UDPSRC_RND) 
         if (pkt_dev->flags & F_UDPSRC_RND) 
-                p += sprintf(p, "UDPSRC_RND  ");
+                seq_printf(seq,  "UDPSRC_RND  ");
         
         
         if (pkt_dev->flags & F_UDPDST_RND) 
         if (pkt_dev->flags & F_UDPDST_RND) 
-                p += sprintf(p, "UDPDST_RND  ");
+                seq_printf(seq,  "UDPDST_RND  ");
         
         
         if (pkt_dev->flags & F_MACSRC_RND) 
         if (pkt_dev->flags & F_MACSRC_RND) 
-                p += sprintf(p, "MACSRC_RND  ");
+                seq_printf(seq,  "MACSRC_RND  ");
         
         
         if (pkt_dev->flags & F_MACDST_RND) 
         if (pkt_dev->flags & F_MACDST_RND) 
-                p += sprintf(p, "MACDST_RND  ");
+                seq_printf(seq,  "MACDST_RND  ");
 
 
         
         
-        p += sprintf(p, "\n");
+        seq_puts(seq,  "\n");
         
         
         sa = pkt_dev->started_at;
         sa = pkt_dev->started_at;
         stopped = pkt_dev->stopped_at;
         stopped = pkt_dev->stopped_at;
         if (pkt_dev->running) 
         if (pkt_dev->running) 
                 stopped = now; /* not really stopped, more like last-running-at */
                 stopped = now; /* not really stopped, more like last-running-at */
         
         
-        p += sprintf(p, "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
-		     (unsigned long long) pkt_dev->sofar,
-		     (unsigned long long) pkt_dev->errors,
-		     (unsigned long long) sa,
-		     (unsigned long long) stopped, 
-		     (unsigned long long) pkt_dev->idle_acc);
+        seq_printf(seq,  "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
+		   (unsigned long long) pkt_dev->sofar,
+		   (unsigned long long) pkt_dev->errors,
+		   (unsigned long long) sa,
+		   (unsigned long long) stopped,
+		   (unsigned long long) pkt_dev->idle_acc);
 
 
-        p += sprintf(p, "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
-                     pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset, pkt_dev->cur_src_mac_offset);
+        seq_printf(seq,  "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
+		   pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset,
+		   pkt_dev->cur_src_mac_offset);
 
 
 	if(pkt_dev->flags & F_IPV6) {
 	if(pkt_dev->flags & F_IPV6) {
 		char b1[128], b2[128];
 		char b1[128], b2[128];
 		fmt_ip6(b1,  pkt_dev->cur_in6_daddr.s6_addr);
 		fmt_ip6(b1,  pkt_dev->cur_in6_daddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->cur_in6_saddr.s6_addr);
 		fmt_ip6(b2,  pkt_dev->cur_in6_saddr.s6_addr);
-		p += sprintf(p, "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
+		seq_printf(seq,  "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
 	} 
 	} 
 	else 
 	else 
-		p += sprintf(p, "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
-                     pkt_dev->cur_saddr, pkt_dev->cur_daddr);
+		seq_printf(seq,  "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
+			   pkt_dev->cur_saddr, pkt_dev->cur_daddr);
 
 
 
 
-	p += sprintf(p, "     cur_udp_dst: %d  cur_udp_src: %d\n",
-                     pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
+	seq_printf(seq,  "     cur_udp_dst: %d  cur_udp_src: %d\n",
+		   pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
 
 
-	p += sprintf(p, "     flows: %u\n", pkt_dev->nflows);
+	seq_printf(seq,  "     flows: %u\n", pkt_dev->nflows);
 
 
 	if (pkt_dev->result[0])
 	if (pkt_dev->result[0])
-		p += sprintf(p, "Result: %s\n", pkt_dev->result);
+		seq_printf(seq,  "Result: %s\n", pkt_dev->result);
 	else
 	else
-		p += sprintf(p, "Result: Idle\n");
-	*eof = 1;
+		seq_printf(seq,  "Result: Idle\n");
 
 
-	return p - buf;
+	return 0;
 }
 }
 
 
 
 
@@ -802,13 +757,14 @@ done_str:
 	return i;
 	return i;
 }
 }
 
 
-static int proc_if_write(struct file *file, const char __user *user_buffer,
-                            unsigned long count, void *data)
+static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer,
+			       size_t count, loff_t *offset)
 {
 {
+	struct seq_file *seq = (struct seq_file *) file->private_data;
+        struct pktgen_dev *pkt_dev = seq->private;
 	int i = 0, max, len;
 	int i = 0, max, len;
 	char name[16], valstr[32];
 	char name[16], valstr[32];
 	unsigned long value = 0;
 	unsigned long value = 0;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
         char* pg_result = NULL;
         char* pg_result = NULL;
         int tmp = 0;
         int tmp = 0;
 	char buf[128];
 	char buf[128];
@@ -849,7 +805,8 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
                 if (copy_from_user(tb, user_buffer, count))
                 if (copy_from_user(tb, user_buffer, count))
 			return -EFAULT;
 			return -EFAULT;
                 tb[count] = 0;
                 tb[count] = 0;
-		printk("pktgen: %s,%lu  buffer -:%s:-\n", name, count, tb);
+		printk("pktgen: %s,%lu  buffer -:%s:-\n", name,
+		       (unsigned long) count, tb);
         }
         }
 
 
 	if (!strcmp(name, "min_pkt_size")) {
 	if (!strcmp(name, "min_pkt_size")) {
@@ -1335,92 +1292,98 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
-static int proc_thread_read(char *buf , char **start, off_t offset,
-                               int len, int *eof, void *data)
+static int pktgen_if_open(struct inode *inode, struct file *file)
 {
 {
-	char *p;
-        struct pktgen_thread *t = (struct pktgen_thread*)(data);
-        struct pktgen_dev *pkt_dev = NULL;
+	return single_open(file, pktgen_if_show, PDE(inode)->data);
+}
 
 
+static struct file_operations pktgen_if_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pktgen_if_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pktgen_if_write,
+	.release  = single_release,
+};
 
 
-        if (!t) {
-                printk("pktgen: ERROR: could not find thread in proc_thread_read\n");
-                return -EINVAL;
-        }
+static int pktgen_thread_show(struct seq_file *seq, void *v)
+{
+        struct pktgen_thread *t = seq->private;
+        struct pktgen_dev *pkt_dev = NULL;
+
+	BUG_ON(!t);
 
 
-	p = buf;
-	p += sprintf(p, "Name: %s  max_before_softirq: %d\n",
+	seq_printf(seq, "Name: %s  max_before_softirq: %d\n",
                      t->name, t->max_before_softirq);
                      t->name, t->max_before_softirq);
 
 
-        p += sprintf(p, "Running: ");
+        seq_printf(seq, "Running: ");
         
         
         if_lock(t);
         if_lock(t);
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
 		if(pkt_dev->running)
 		if(pkt_dev->running)
-			p += sprintf(p, "%s ", pkt_dev->ifname);
+			seq_printf(seq, "%s ", pkt_dev->ifname);
         
         
-        p += sprintf(p, "\nStopped: ");
+        seq_printf(seq, "\nStopped: ");
 
 
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
 		if(!pkt_dev->running)
 		if(!pkt_dev->running)
-			p += sprintf(p, "%s ", pkt_dev->ifname);
+			seq_printf(seq, "%s ", pkt_dev->ifname);
 
 
 	if (t->result[0])
 	if (t->result[0])
-		p += sprintf(p, "\nResult: %s\n", t->result);
+		seq_printf(seq, "\nResult: %s\n", t->result);
 	else
 	else
-		p += sprintf(p, "\nResult: NA\n");
-
-	*eof = 1;
+		seq_printf(seq, "\nResult: NA\n");
 
 
         if_unlock(t);
         if_unlock(t);
 
 
-	return p - buf;
+	return 0;
 }
 }
 
 
-static int proc_thread_write(struct file *file, const char __user *user_buffer,
-                                unsigned long count, void *data)
+static ssize_t pktgen_thread_write(struct file *file,
+				   const char __user *user_buffer,
+				   size_t count, loff_t *offset)
 {
 {
+	struct seq_file *seq = (struct seq_file *) file->private_data;
+        struct pktgen_thread *t = seq->private;
 	int i = 0, max, len, ret;
 	int i = 0, max, len, ret;
 	char name[40];
 	char name[40];
-        struct pktgen_thread *t;
         char *pg_result;
         char *pg_result;
         unsigned long value = 0;
         unsigned long value = 0;
-        
+
 	if (count < 1) {
 	if (count < 1) {
 		//	sprintf(pg_result, "Wrong command format");
 		//	sprintf(pg_result, "Wrong command format");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-  
+
 	max = count - i;
 	max = count - i;
         len = count_trail_chars(&user_buffer[i], max);
         len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0) 
-		return len; 
-     
+        if (len < 0)
+		return len;
+
 	i += len;
 	i += len;
-  
+
 	/* Read variable name */
 	/* Read variable name */
 
 
 	len = strn_len(&user_buffer[i], sizeof(name) - 1);
 	len = strn_len(&user_buffer[i], sizeof(name) - 1);
-        if (len < 0)  
-		return len; 
+        if (len < 0)
+		return len;
 	
 	
 	memset(name, 0, sizeof(name));
 	memset(name, 0, sizeof(name));
 	if (copy_from_user(name, &user_buffer[i], len))
 	if (copy_from_user(name, &user_buffer[i], len))
 		return -EFAULT;
 		return -EFAULT;
 	i += len;
 	i += len;
-  
+
 	max = count -i;
 	max = count -i;
 	len = count_trail_chars(&user_buffer[i], max);
 	len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0)  
-		return len; 
-	
+        if (len < 0)
+		return len;
+
 	i += len;
 	i += len;
 
 
-	if (debug) 
-		printk("pktgen: t=%s, count=%lu\n", name, count);
-        
+	if (debug)
+		printk("pktgen: t=%s, count=%lu\n", name,
+		       (unsigned long) count);
 
 
-        t = (struct pktgen_thread*)(data);
 	if(!t) {
 	if(!t) {
 		printk("pktgen: ERROR: No thread\n");
 		printk("pktgen: ERROR: No thread\n");
 		ret = -EINVAL;
 		ret = -EINVAL;
@@ -1474,21 +1437,19 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
 	return ret;
 	return ret;
 }
 }
 
 
-static int create_proc_dir(void)
+static int pktgen_thread_open(struct inode *inode, struct file *file)
 {
 {
-	pg_proc_dir = proc_mkdir(PG_PROC_DIR, NULL);
-        
-        if (!pg_proc_dir) 
-                return -ENODEV;
-        
-        return 0;
+	return single_open(file, pktgen_thread_show, PDE(inode)->data);
 }
 }
 
 
-static int remove_proc_dir(void)
-{
-        remove_proc_entry(PG_PROC_DIR, NULL);
-        return 0;
-}
+static struct file_operations pktgen_thread_fops = {
+	.owner	  = THIS_MODULE,
+	.open	  = pktgen_thread_open,
+        .read     = seq_read,
+	.llseek	  = seq_lseek,
+        .write    = pktgen_thread_write,
+	.release  = single_release,
+};
 
 
 /* Think find or remove for NN */
 /* Think find or remove for NN */
 static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 
 static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 
@@ -1702,7 +1663,7 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
 	start = now = getCurUs();
 	start = now = getCurUs();
 	printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
 	printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
 	while (now < spin_until_us) {
 	while (now < spin_until_us) {
-		/* TODO: optimise sleeping behavior */
+		/* TODO: optimize sleeping behavior */
 		if (spin_until_us - now > jiffies_to_usecs(1)+1)
 		if (spin_until_us - now > jiffies_to_usecs(1)+1)
 			schedule_timeout_interruptible(1);
 			schedule_timeout_interruptible(1);
 		else if (spin_until_us - now > 100) {
 		else if (spin_until_us - now > 100) {
@@ -2361,7 +2322,7 @@ static void pktgen_stop_all_threads_ifs(void)
 		pktgen_stop(t);
 		pktgen_stop(t);
 		t = t->next;
 		t = t->next;
 	}
 	}
-       thread_unlock();
+	thread_unlock();
 }
 }
 
 
 static int thread_is_running(struct pktgen_thread *t )
 static int thread_is_running(struct pktgen_thread *t )
@@ -2552,10 +2513,9 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
 
 
 	struct pktgen_thread *tmp = pktgen_threads;
 	struct pktgen_thread *tmp = pktgen_threads;
 
 
-        if (strlen(t->fname))
-                remove_proc_entry(t->fname, NULL);
+	remove_proc_entry(t->name, pg_proc_dir);
 
 
-       thread_lock();
+	thread_lock();
 
 
 	if (tmp == t)
 	if (tmp == t)
 		pktgen_threads = tmp->next;
 		pktgen_threads = tmp->next;
@@ -2825,7 +2785,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, const char* i
         if_lock(t);
         if_lock(t);
 
 
         for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
         for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
-                if (strcmp(pkt_dev->ifname, ifname) == 0) {
+                if (strncmp(pkt_dev->ifname, ifname, IFNAMSIZ) == 0) {
                         break;
                         break;
                 }
                 }
         }
         }
@@ -2864,74 +2824,70 @@ static int add_dev_to_thread(struct pktgen_thread *t, struct pktgen_dev *pkt_dev
 static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) 
 static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) 
 {
 {
         struct pktgen_dev *pkt_dev;
         struct pktgen_dev *pkt_dev;
+	struct proc_dir_entry *pe;
 	
 	
 	/* We don't allow a device to be on several threads */
 	/* We don't allow a device to be on several threads */
 
 
-	if( (pkt_dev = __pktgen_NN_threads(ifname, FIND)) == NULL) {
-						   
-		pkt_dev = kmalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
-                if (!pkt_dev) 
-                        return -ENOMEM;
+	pkt_dev = __pktgen_NN_threads(ifname, FIND);
+	if (pkt_dev) {
+                printk("pktgen: ERROR: interface already used.\n");
+                return -EBUSY;
+        }
 
 
-                memset(pkt_dev, 0, sizeof(struct pktgen_dev));
+	pkt_dev = kzalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
+	if (!pkt_dev)
+		return -ENOMEM;
 
 
-		pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
-		if (pkt_dev->flows == NULL) {
-			kfree(pkt_dev);
-			return -ENOMEM;
-		}
-		memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
-
-		pkt_dev->min_pkt_size = ETH_ZLEN;
-                pkt_dev->max_pkt_size = ETH_ZLEN;
-                pkt_dev->nfrags = 0;
-                pkt_dev->clone_skb = pg_clone_skb_d;
-                pkt_dev->delay_us = pg_delay_d / 1000;
-                pkt_dev->delay_ns = pg_delay_d % 1000;
-                pkt_dev->count = pg_count_d;
-                pkt_dev->sofar = 0;
-                pkt_dev->udp_src_min = 9; /* sink port */
-                pkt_dev->udp_src_max = 9;
-                pkt_dev->udp_dst_min = 9;
-                pkt_dev->udp_dst_max = 9;
-
-                strncpy(pkt_dev->ifname, ifname, 31);
-                sprintf(pkt_dev->fname, "%s/%s", PG_PROC_DIR, ifname);
-
-                if (! pktgen_setup_dev(pkt_dev)) {
-                        printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
-			if (pkt_dev->flows)
-				vfree(pkt_dev->flows);
-                        kfree(pkt_dev);
-                        return -ENODEV;
-                }
+	pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
+	if (pkt_dev->flows == NULL) {
+		kfree(pkt_dev);
+		return -ENOMEM;
+	}
+	memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
 
 
-                pkt_dev->proc_ent = create_proc_entry(pkt_dev->fname, 0600, NULL);
-                if (!pkt_dev->proc_ent) {
-                        printk("pktgen: cannot create %s procfs entry.\n", pkt_dev->fname);
-			if (pkt_dev->flows)
-				vfree(pkt_dev->flows);
-                        kfree(pkt_dev);
-                        return -EINVAL;
-                }
-                pkt_dev->proc_ent->read_proc = proc_if_read;
-                pkt_dev->proc_ent->write_proc = proc_if_write;
-                pkt_dev->proc_ent->data = (void*)(pkt_dev);
-		pkt_dev->proc_ent->owner = THIS_MODULE;
+	pkt_dev->min_pkt_size = ETH_ZLEN;
+	pkt_dev->max_pkt_size = ETH_ZLEN;
+	pkt_dev->nfrags = 0;
+	pkt_dev->clone_skb = pg_clone_skb_d;
+	pkt_dev->delay_us = pg_delay_d / 1000;
+	pkt_dev->delay_ns = pg_delay_d % 1000;
+	pkt_dev->count = pg_count_d;
+	pkt_dev->sofar = 0;
+	pkt_dev->udp_src_min = 9; /* sink port */
+	pkt_dev->udp_src_max = 9;
+	pkt_dev->udp_dst_min = 9;
+	pkt_dev->udp_dst_max = 9;
+
+	strncpy(pkt_dev->ifname, ifname, IFNAMSIZ);
+
+	if (! pktgen_setup_dev(pkt_dev)) {
+		printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
+		if (pkt_dev->flows)
+			vfree(pkt_dev->flows);
+		kfree(pkt_dev);
+		return -ENODEV;
+	}
+
+	pe = create_proc_entry(ifname, 0600, pg_proc_dir);
+	if (!pe) {
+		printk("pktgen: cannot create %s/%s procfs entry.\n",
+		       PG_PROC_DIR, ifname);
+		if (pkt_dev->flows)
+			vfree(pkt_dev->flows);
+		kfree(pkt_dev);
+		return -EINVAL;
+	}
+	pe->proc_fops = &pktgen_if_fops;
+	pe->data = pkt_dev;
 
 
-                return add_dev_to_thread(t, pkt_dev);
-        }
-        else {
-                printk("pktgen: ERROR: interface already used.\n");
-                return -EBUSY;
-        }
+	return add_dev_to_thread(t, pkt_dev);
 }
 }
 
 
 static struct pktgen_thread *pktgen_find_thread(const char* name) 
 static struct pktgen_thread *pktgen_find_thread(const char* name) 
 {
 {
         struct pktgen_thread *t = NULL;
         struct pktgen_thread *t = NULL;
 
 
-       thread_lock();
+	thread_lock();
 
 
         t = pktgen_threads;
         t = pktgen_threads;
         while (t) {
         while (t) {
@@ -2947,6 +2903,7 @@ static struct pktgen_thread *pktgen_find_thread(const char* name)
 static int pktgen_create_thread(const char* name, int cpu) 
 static int pktgen_create_thread(const char* name, int cpu) 
 {
 {
         struct pktgen_thread *t = NULL;
         struct pktgen_thread *t = NULL;
+	struct proc_dir_entry *pe;
 
 
         if (strlen(name) > 31) {
         if (strlen(name) > 31) {
                 printk("pktgen: ERROR:  Thread name cannot be more than 31 characters.\n");
                 printk("pktgen: ERROR:  Thread name cannot be more than 31 characters.\n");
@@ -2958,28 +2915,26 @@ static int pktgen_create_thread(const char* name, int cpu)
                 return -EINVAL;
                 return -EINVAL;
         }
         }
 
 
-        t = (struct pktgen_thread*)(kmalloc(sizeof(struct pktgen_thread), GFP_KERNEL));
+        t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
         if (!t) {
         if (!t) {
                 printk("pktgen: ERROR: out of memory, can't create new thread.\n");
                 printk("pktgen: ERROR: out of memory, can't create new thread.\n");
                 return -ENOMEM;
                 return -ENOMEM;
         }
         }
 
 
-        memset(t, 0, sizeof(struct pktgen_thread));
         strcpy(t->name, name);
         strcpy(t->name, name);
         spin_lock_init(&t->if_lock);
         spin_lock_init(&t->if_lock);
 	t->cpu = cpu;
 	t->cpu = cpu;
         
         
-        sprintf(t->fname, "%s/%s", PG_PROC_DIR, t->name);
-        t->proc_ent = create_proc_entry(t->fname, 0600, NULL);
-        if (!t->proc_ent) {
-                printk("pktgen: cannot create %s procfs entry.\n", t->fname);
+        pe = create_proc_entry(t->name, 0600, pg_proc_dir);
+        if (!pe) {
+                printk("pktgen: cannot create %s/%s procfs entry.\n",
+		       PG_PROC_DIR, t->name);
                 kfree(t);
                 kfree(t);
                 return -EINVAL;
                 return -EINVAL;
         }
         }
-        t->proc_ent->read_proc = proc_thread_read;
-        t->proc_ent->write_proc = proc_thread_write;
-        t->proc_ent->data = (void*)(t);
-        t->proc_ent->owner = THIS_MODULE;
+
+	pe->proc_fops = &pktgen_thread_fops;
+	pe->data = t;
 
 
         t->next = pktgen_threads;
         t->next = pktgen_threads;
         pktgen_threads = t;
         pktgen_threads = t;
@@ -3034,8 +2989,7 @@ static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_
 
 
         /* Clean up proc file system */
         /* Clean up proc file system */
 
 
-        if (strlen(pkt_dev->fname)) 
-                remove_proc_entry(pkt_dev->fname, NULL);
+	remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
 
 
 	if (pkt_dev->flows)
 	if (pkt_dev->flows)
 		vfree(pkt_dev->flows);
 		vfree(pkt_dev->flows);
@@ -3046,31 +3000,31 @@ static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_
 static int __init pg_init(void) 
 static int __init pg_init(void) 
 {
 {
 	int cpu;
 	int cpu;
-	printk(version);
+	struct proc_dir_entry *pe;
 
 
-        module_fname[0] = 0;
+	printk(version);
 
 
-	create_proc_dir();
+	pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
+	if (!pg_proc_dir)
+		return -ENODEV;
+	pg_proc_dir->owner = THIS_MODULE;
 
 
-        sprintf(module_fname, "%s/pgctrl", PG_PROC_DIR);
-        module_proc_ent = create_proc_entry(module_fname, 0600, NULL);
-        if (!module_proc_ent) {
-                printk("pktgen: ERROR: cannot create %s procfs entry.\n", module_fname);
+	pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir);
+        if (pe == NULL) {
+		printk("pktgen: ERROR: cannot create %s procfs entry.\n", PGCTRL);
+		proc_net_remove(PG_PROC_DIR);
                 return -EINVAL;
                 return -EINVAL;
         }
         }
 
 
-        module_proc_ent->proc_fops =  &pktgen_fops;
-        module_proc_ent->data = NULL;
+        pe->proc_fops = &pktgen_fops;
+        pe->data      = NULL;
 
 
 	/* Register us to receive netdevice events */
 	/* Register us to receive netdevice events */
 	register_netdevice_notifier(&pktgen_notifier_block);
 	register_netdevice_notifier(&pktgen_notifier_block);
         
         
-	for (cpu = 0; cpu < NR_CPUS ; cpu++) {
+	for_each_online_cpu(cpu) {
 		char buf[30];
 		char buf[30];
 
 
-		if (!cpu_online(cpu))
-			continue;
-
                 sprintf(buf, "kpktgend_%i", cpu);
                 sprintf(buf, "kpktgend_%i", cpu);
                 pktgen_create_thread(buf, cpu);
                 pktgen_create_thread(buf, cpu);
         }
         }
@@ -3095,10 +3049,8 @@ static void __exit pg_cleanup(void)
 	unregister_netdevice_notifier(&pktgen_notifier_block);
 	unregister_netdevice_notifier(&pktgen_notifier_block);
 
 
         /* Clean up proc file system */
         /* Clean up proc file system */
-
-        remove_proc_entry(module_fname, NULL);
-        
-	remove_proc_dir();
+	remove_proc_entry(PGCTRL, pg_proc_dir);
+	proc_net_remove(PG_PROC_DIR);
 }
 }
 
 
 
 

+ 2 - 0
net/core/skbuff.c

@@ -122,6 +122,8 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
  *	__alloc_skb	-	allocate a network buffer
  *	__alloc_skb	-	allocate a network buffer
  *	@size: size to allocate
  *	@size: size to allocate
  *	@gfp_mask: allocation mask
  *	@gfp_mask: allocation mask
+ *	@fclone: allocate from fclone cache instead of head cache
+ *		and allocate a cloned (child) skb
  *
  *
  *	Allocate a new &sk_buff. The returned buffer has no headroom and a
  *	Allocate a new &sk_buff. The returned buffer has no headroom and a
  *	tail room of size bytes. The object has a reference count of one.
  *	tail room of size bytes. The object has a reference count of one.

+ 0 - 13
net/decnet/af_decnet.c

@@ -719,22 +719,9 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	if (saddr->sdn_flags & ~SDF_WILD)
 	if (saddr->sdn_flags & ~SDF_WILD)
 		return -EINVAL;
 		return -EINVAL;
 
 
-#if 1
 	if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
 	if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
 	    (saddr->sdn_flags & SDF_WILD)))
 	    (saddr->sdn_flags & SDF_WILD)))
 		return -EACCES;
 		return -EACCES;
-#else
-	/*
-	 * Maybe put the default actions in the default security ops for
-	 * dn_prot_sock ? Would be nice if the capable call would go there
-	 * too.
-	 */
-	if (security_dn_prot_sock(saddr) &&
-	    !capable(CAP_NET_BIND_SERVICE) || 
-	    saddr->sdn_objnum || (saddr->sdn_flags & SDF_WILD))
-		return -EACCES;
-#endif
-
 
 
 	if (!(saddr->sdn_flags & SDF_WILD)) {
 	if (!(saddr->sdn_flags & SDF_WILD)) {
 		if (dn_ntohs(saddr->sdn_nodeaddrl)) {
 		if (dn_ntohs(saddr->sdn_nodeaddrl)) {

+ 2 - 1
net/ipv4/devinet.c

@@ -715,6 +715,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
 			break;
 			break;
 		ret = 0;
 		ret = 0;
 		if (ifa->ifa_mask != sin->sin_addr.s_addr) {
 		if (ifa->ifa_mask != sin->sin_addr.s_addr) {
+			u32 old_mask = ifa->ifa_mask;
 			inet_del_ifa(in_dev, ifap, 0);
 			inet_del_ifa(in_dev, ifap, 0);
 			ifa->ifa_mask = sin->sin_addr.s_addr;
 			ifa->ifa_mask = sin->sin_addr.s_addr;
 			ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
 			ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
@@ -728,7 +729,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
 			if ((dev->flags & IFF_BROADCAST) &&
 			if ((dev->flags & IFF_BROADCAST) &&
 			    (ifa->ifa_prefixlen < 31) &&
 			    (ifa->ifa_prefixlen < 31) &&
 			    (ifa->ifa_broadcast ==
 			    (ifa->ifa_broadcast ==
-			     (ifa->ifa_local|~ifa->ifa_mask))) {
+			     (ifa->ifa_local|~old_mask))) {
 				ifa->ifa_broadcast = (ifa->ifa_local |
 				ifa->ifa_broadcast = (ifa->ifa_local |
 						      ~sin->sin_addr.s_addr);
 						      ~sin->sin_addr.s_addr);
 			}
 			}

+ 1 - 1
net/ipv4/fib_trie.c

@@ -2404,7 +2404,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
 		prefix = htonl(l->key);
 		prefix = htonl(l->key);
 
 
 		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
 		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
-			const struct fib_info *fi = rcu_dereference(fa->fa_info);
+			const struct fib_info *fi = fa->fa_info;
 			unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
 			unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
 
 
 			if (fa->fa_type == RTN_BROADCAST
 			if (fa->fa_type == RTN_BROADCAST

+ 1 - 4
net/ipv4/icmp.c

@@ -1108,12 +1108,9 @@ void __init icmp_init(struct net_proto_family *ops)
 	struct inet_sock *inet;
 	struct inet_sock *inet;
 	int i;
 	int i;
 
 
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		int err;
 		int err;
 
 
-		if (!cpu_possible(i))
-			continue;
-
 		err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
 		err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
 				       &per_cpu(__icmp_socket, i));
 				       &per_cpu(__icmp_socket, i));
 
 

+ 1 - 4
net/ipv4/ip_output.c

@@ -1023,10 +1023,7 @@ ssize_t	ip_append_page(struct sock *sk, struct page *page,
 			int alloclen;
 			int alloclen;
 
 
 			skb_prev = skb;
 			skb_prev = skb;
-			if (skb_prev)
-				fraggap = skb_prev->len - maxfraglen;
-			else
-				fraggap = 0;
+			fraggap = skb_prev->len - maxfraglen;
 
 
 			alloclen = fragheaderlen + hh_len + fraggap + 15;
 			alloclen = fragheaderlen + hh_len + fraggap + 15;
 			skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
 			skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);

+ 95 - 37
net/ipv4/netfilter/ip_conntrack_core.c

@@ -50,7 +50,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
 
-#define IP_CONNTRACK_VERSION	"2.3"
+#define IP_CONNTRACK_VERSION	"2.4"
 
 
 #if 0
 #if 0
 #define DEBUGP printk
 #define DEBUGP printk
@@ -148,16 +148,20 @@ DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
 static int ip_conntrack_hash_rnd_initted;
 static int ip_conntrack_hash_rnd_initted;
 static unsigned int ip_conntrack_hash_rnd;
 static unsigned int ip_conntrack_hash_rnd;
 
 
-static u_int32_t
-hash_conntrack(const struct ip_conntrack_tuple *tuple)
+static u_int32_t __hash_conntrack(const struct ip_conntrack_tuple *tuple,
+			    unsigned int size, unsigned int rnd)
 {
 {
-#if 0
-	dump_tuple(tuple);
-#endif
 	return (jhash_3words(tuple->src.ip,
 	return (jhash_3words(tuple->src.ip,
 	                     (tuple->dst.ip ^ tuple->dst.protonum),
 	                     (tuple->dst.ip ^ tuple->dst.protonum),
 	                     (tuple->src.u.all | (tuple->dst.u.all << 16)),
 	                     (tuple->src.u.all | (tuple->dst.u.all << 16)),
-	                     ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
+	                     rnd) % size);
+}
+
+static u_int32_t
+hash_conntrack(const struct ip_conntrack_tuple *tuple)
+{
+	return __hash_conntrack(tuple, ip_conntrack_htable_size,
+				ip_conntrack_hash_rnd);
 }
 }
 
 
 int
 int
@@ -1341,14 +1345,13 @@ static int kill_all(struct ip_conntrack *i, void *data)
 	return 1;
 	return 1;
 }
 }
 
 
-static void free_conntrack_hash(void)
+static void free_conntrack_hash(struct list_head *hash, int vmalloced,int size)
 {
 {
-	if (ip_conntrack_vmalloc)
-		vfree(ip_conntrack_hash);
+	if (vmalloced)
+		vfree(hash);
 	else
 	else
-		free_pages((unsigned long)ip_conntrack_hash, 
-			   get_order(sizeof(struct list_head)
-				     * ip_conntrack_htable_size));
+		free_pages((unsigned long)hash, 
+			   get_order(sizeof(struct list_head) * size));
 }
 }
 
 
 void ip_conntrack_flush()
 void ip_conntrack_flush()
@@ -1378,12 +1381,83 @@ void ip_conntrack_cleanup(void)
 	ip_conntrack_flush();
 	ip_conntrack_flush();
 	kmem_cache_destroy(ip_conntrack_cachep);
 	kmem_cache_destroy(ip_conntrack_cachep);
 	kmem_cache_destroy(ip_conntrack_expect_cachep);
 	kmem_cache_destroy(ip_conntrack_expect_cachep);
-	free_conntrack_hash();
+	free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
+			    ip_conntrack_htable_size);
 	nf_unregister_sockopt(&so_getorigdst);
 	nf_unregister_sockopt(&so_getorigdst);
 }
 }
 
 
-static int hashsize;
-module_param(hashsize, int, 0400);
+static struct list_head *alloc_hashtable(int size, int *vmalloced)
+{
+	struct list_head *hash;
+	unsigned int i;
+
+	*vmalloced = 0; 
+	hash = (void*)__get_free_pages(GFP_KERNEL, 
+				       get_order(sizeof(struct list_head)
+						 * size));
+	if (!hash) { 
+		*vmalloced = 1;
+		printk(KERN_WARNING"ip_conntrack: falling back to vmalloc.\n");
+		hash = vmalloc(sizeof(struct list_head) * size);
+	}
+
+	if (hash)
+		for (i = 0; i < size; i++)
+			INIT_LIST_HEAD(&hash[i]);
+
+	return hash;
+}
+
+int set_hashsize(const char *val, struct kernel_param *kp)
+{
+	int i, bucket, hashsize, vmalloced;
+	int old_vmalloced, old_size;
+	int rnd;
+	struct list_head *hash, *old_hash;
+	struct ip_conntrack_tuple_hash *h;
+
+	/* On boot, we can set this without any fancy locking. */
+	if (!ip_conntrack_htable_size)
+		return param_set_int(val, kp);
+
+	hashsize = simple_strtol(val, NULL, 0);
+	if (!hashsize)
+		return -EINVAL;
+
+	hash = alloc_hashtable(hashsize, &vmalloced);
+	if (!hash)
+		return -ENOMEM;
+
+	/* We have to rehash for the new table anyway, so we also can 
+	 * use a new random seed */
+	get_random_bytes(&rnd, 4);
+
+	write_lock_bh(&ip_conntrack_lock);
+	for (i = 0; i < ip_conntrack_htable_size; i++) {
+		while (!list_empty(&ip_conntrack_hash[i])) {
+			h = list_entry(ip_conntrack_hash[i].next,
+				       struct ip_conntrack_tuple_hash, list);
+			list_del(&h->list);
+			bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
+			list_add_tail(&h->list, &hash[bucket]);
+		}
+	}
+	old_size = ip_conntrack_htable_size;
+	old_vmalloced = ip_conntrack_vmalloc;
+	old_hash = ip_conntrack_hash;
+
+	ip_conntrack_htable_size = hashsize;
+	ip_conntrack_vmalloc = vmalloced;
+	ip_conntrack_hash = hash;
+	ip_conntrack_hash_rnd = rnd;
+	write_unlock_bh(&ip_conntrack_lock);
+
+	free_conntrack_hash(old_hash, old_vmalloced, old_size);
+	return 0;
+}
+
+module_param_call(hashsize, set_hashsize, param_get_uint,
+		  &ip_conntrack_htable_size, 0600);
 
 
 int __init ip_conntrack_init(void)
 int __init ip_conntrack_init(void)
 {
 {
@@ -1392,9 +1466,7 @@ int __init ip_conntrack_init(void)
 
 
 	/* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
 	/* Idea from tcp.c: use 1/16384 of memory.  On i386: 32MB
 	 * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
 	 * machine has 256 buckets.  >= 1GB machines have 8192 buckets. */
- 	if (hashsize) {
- 		ip_conntrack_htable_size = hashsize;
- 	} else {
+ 	if (!ip_conntrack_htable_size) {
 		ip_conntrack_htable_size
 		ip_conntrack_htable_size
 			= (((num_physpages << PAGE_SHIFT) / 16384)
 			= (((num_physpages << PAGE_SHIFT) / 16384)
 			   / sizeof(struct list_head));
 			   / sizeof(struct list_head));
@@ -1416,20 +1488,8 @@ int __init ip_conntrack_init(void)
 		return ret;
 		return ret;
 	}
 	}
 
 
-	/* AK: the hash table is twice as big than needed because it
-	   uses list_head.  it would be much nicer to caches to use a
-	   single pointer list head here. */
-	ip_conntrack_vmalloc = 0; 
-	ip_conntrack_hash 
-		=(void*)__get_free_pages(GFP_KERNEL, 
-					 get_order(sizeof(struct list_head)
-						   *ip_conntrack_htable_size));
-	if (!ip_conntrack_hash) { 
-		ip_conntrack_vmalloc = 1;
-		printk(KERN_WARNING "ip_conntrack: falling back to vmalloc.\n");
-		ip_conntrack_hash = vmalloc(sizeof(struct list_head)
-					    * ip_conntrack_htable_size);
-	}
+	ip_conntrack_hash = alloc_hashtable(ip_conntrack_htable_size,
+					    &ip_conntrack_vmalloc);
 	if (!ip_conntrack_hash) {
 	if (!ip_conntrack_hash) {
 		printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
 		printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
 		goto err_unreg_sockopt;
 		goto err_unreg_sockopt;
@@ -1461,9 +1521,6 @@ int __init ip_conntrack_init(void)
 	ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
 	ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
 	write_unlock_bh(&ip_conntrack_lock);
 	write_unlock_bh(&ip_conntrack_lock);
 
 
-	for (i = 0; i < ip_conntrack_htable_size; i++)
-		INIT_LIST_HEAD(&ip_conntrack_hash[i]);
-
 	/* For use by ipt_REJECT */
 	/* For use by ipt_REJECT */
 	ip_ct_attach = ip_conntrack_attach;
 	ip_ct_attach = ip_conntrack_attach;
 
 
@@ -1478,7 +1535,8 @@ int __init ip_conntrack_init(void)
 err_free_conntrack_slab:
 err_free_conntrack_slab:
 	kmem_cache_destroy(ip_conntrack_cachep);
 	kmem_cache_destroy(ip_conntrack_cachep);
 err_free_hash:
 err_free_hash:
-	free_conntrack_hash();
+	free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
+			    ip_conntrack_htable_size);
 err_unreg_sockopt:
 err_unreg_sockopt:
 	nf_unregister_sockopt(&so_getorigdst);
 	nf_unregister_sockopt(&so_getorigdst);
 
 

+ 1 - 3
net/ipv4/proc.c

@@ -90,9 +90,7 @@ fold_field(void *mib[], int offt)
 	unsigned long res = 0;
 	unsigned long res = 0;
 	int i;
 	int i;
 
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
 		res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt);
 		res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
 		res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt);
 	}
 	}

+ 2 - 7
net/ipv6/icmp.c

@@ -700,10 +700,7 @@ int __init icmpv6_init(struct net_proto_family *ops)
 	struct sock *sk;
 	struct sock *sk;
 	int err, i, j;
 	int err, i, j;
 
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
-
+	for_each_cpu(i) {
 		err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
 		err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
 				       &per_cpu(__icmpv6_socket, i));
 				       &per_cpu(__icmpv6_socket, i));
 		if (err < 0) {
 		if (err < 0) {
@@ -749,9 +746,7 @@ void icmpv6_cleanup(void)
 {
 {
 	int i;
 	int i;
 
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		sock_release(per_cpu(__icmpv6_socket, i));
 		sock_release(per_cpu(__icmpv6_socket, i));
 	}
 	}
 	inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
 	inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);

+ 1 - 3
net/ipv6/proc.c

@@ -140,9 +140,7 @@ fold_field(void *mib[], int offt)
         unsigned long res = 0;
         unsigned long res = 0;
         int i;
         int i;
  
  
-        for (i = 0; i < NR_CPUS; i++) {
-                if (!cpu_possible(i))
-                        continue;
+        for_each_cpu(i) {
                 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
                 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
                 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
                 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
         }
         }

+ 0 - 3
net/netlink/af_netlink.c

@@ -740,11 +740,8 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
 
 
 int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol)
 int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol)
 {
 {
-	struct netlink_sock *nlk;
 	int len = skb->len;
 	int len = skb->len;
 
 
-	nlk = nlk_sk(sk);
-
 	skb_queue_tail(&sk->sk_receive_queue, skb);
 	skb_queue_tail(&sk->sk_receive_queue, skb);
 	sk->sk_data_ready(sk, len);
 	sk->sk_data_ready(sk, len);
 	sock_put(sk);
 	sock_put(sk);

+ 1 - 1
net/rose/rose_route.c

@@ -727,7 +727,7 @@ int rose_rt_ioctl(unsigned int cmd, void __user *arg)
 		}
 		}
 		if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
 		if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
 			return -EINVAL;
 			return -EINVAL;
-		if (rose_route.ndigis > 8) /* No more than 8 digipeats */
+		if (rose_route.ndigis > AX25_MAX_DIGIS)
 			return -EINVAL;
 			return -EINVAL;
 		err = rose_add_node(&rose_route, dev);
 		err = rose_add_node(&rose_route, dev);
 		dev_put(dev);
 		dev_put(dev);

+ 1 - 3
net/sctp/proc.c

@@ -69,9 +69,7 @@ fold_field(void *mib[], int nr)
 	unsigned long res = 0;
 	unsigned long res = 0;
 	int i;
 	int i;
 
 
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_possible(i))
-			continue;
+	for_each_cpu(i) {
 		res +=
 		res +=
 		    *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
 		    *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
 					 sizeof (unsigned long) * nr));
 					 sizeof (unsigned long) * nr));

+ 0 - 43
net/xfrm/xfrm_policy.c

@@ -1192,46 +1192,6 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
 
 
 EXPORT_SYMBOL(xfrm_bundle_ok);
 EXPORT_SYMBOL(xfrm_bundle_ok);
 
 
-/* Well... that's _TASK_. We need to scan through transformation
- * list and figure out what mss tcp should generate in order to
- * final datagram fit to mtu. Mama mia... :-)
- *
- * Apparently, some easy way exists, but we used to choose the most
- * bizarre ones. :-) So, raising Kalashnikov... tra-ta-ta.
- *
- * Consider this function as something like dark humour. :-)
- */
-static int xfrm_get_mss(struct dst_entry *dst, u32 mtu)
-{
-	int res = mtu - dst->header_len;
-
-	for (;;) {
-		struct dst_entry *d = dst;
-		int m = res;
-
-		do {
-			struct xfrm_state *x = d->xfrm;
-			if (x) {
-				spin_lock_bh(&x->lock);
-				if (x->km.state == XFRM_STATE_VALID &&
-				    x->type && x->type->get_max_size)
-					m = x->type->get_max_size(d->xfrm, m);
-				else
-					m += x->props.header_len;
-				spin_unlock_bh(&x->lock);
-			}
-		} while ((d = d->child) != NULL);
-
-		if (m <= mtu)
-			break;
-		res -= (m - mtu);
-		if (res < 88)
-			return mtu;
-	}
-
-	return res + dst->header_len;
-}
-
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
 {
 	int err = 0;
 	int err = 0;
@@ -1252,8 +1212,6 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 			dst_ops->negative_advice = xfrm_negative_advice;
 			dst_ops->negative_advice = xfrm_negative_advice;
 		if (likely(dst_ops->link_failure == NULL))
 		if (likely(dst_ops->link_failure == NULL))
 			dst_ops->link_failure = xfrm_link_failure;
 			dst_ops->link_failure = xfrm_link_failure;
-		if (likely(dst_ops->get_mss == NULL))
-			dst_ops->get_mss = xfrm_get_mss;
 		if (likely(afinfo->garbage_collect == NULL))
 		if (likely(afinfo->garbage_collect == NULL))
 			afinfo->garbage_collect = __xfrm_garbage_collect;
 			afinfo->garbage_collect = __xfrm_garbage_collect;
 		xfrm_policy_afinfo[afinfo->family] = afinfo;
 		xfrm_policy_afinfo[afinfo->family] = afinfo;
@@ -1281,7 +1239,6 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
 			dst_ops->check = NULL;
 			dst_ops->check = NULL;
 			dst_ops->negative_advice = NULL;
 			dst_ops->negative_advice = NULL;
 			dst_ops->link_failure = NULL;
 			dst_ops->link_failure = NULL;
-			dst_ops->get_mss = NULL;
 			afinfo->garbage_collect = NULL;
 			afinfo->garbage_collect = NULL;
 		}
 		}
 	}
 	}

+ 6 - 0
net/xfrm/xfrm_state.c

@@ -1026,6 +1026,12 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
 }
 }
 EXPORT_SYMBOL(xfrm_state_delete_tunnel);
 EXPORT_SYMBOL(xfrm_state_delete_tunnel);
 
 
+/*
+ * This function is NOT optimal.  For example, with ESP it will give an
+ * MTU that's usually two bytes short of being optimal.  However, it will
+ * usually give an answer that's a multiple of 4 provided the input is
+ * also a multiple of 4.
+ */
 int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 {
 {
 	int res = mtu;
 	int res = mtu;