[PKTGEN]: proc interface revision
authorStephen Hemminger <shemminger@osdl.org>
Fri, 14 Oct 2005 22:42:33 +0000 (15:42 -0700)
committerArnaldo Carvalho de Melo <acme@mandriva.com>
Wed, 26 Oct 2005 02:12:18 +0000 (00:12 -0200)
The code to handle the /proc interface can be cleaned up in several places:
* use seq_file for read
* don't need to remember all the filenames separately
* use for_online_cpu's
* don't vmalloc a buffer for small command from user.

Committer note:
This patch clashed with John Hawkes's "[NET]: Wider use of for_each_*cpu()",
so I fixed it up manually.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Robert Olsson <robert.olsson@its.uu.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
net/core/pktgen.c

index ad053c8cb7fcf74f21a28abc8e8068d7849d8cfb..7fc3e9e28c34c3353b3e48082916d4cb737ad5e8 100644 (file)
 #include <linux/ipv6.h>
 #include <linux/udp.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/wait.h>
 #include <net/checksum.h>
 #include <net/ipv6.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) 
 
 /* Used to help with determining the pkts on receive */
 #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
 
@@ -202,11 +205,8 @@ struct pktgen_dev {
         * Try to keep frequent/infrequent used vars. separated.
         */
 
-        char ifname[32];
-        struct proc_dir_entry *proc_ent;
+        char ifname[IFNAMSIZ];
         char result[512];
-        /* proc file names */
-        char fname[80];
 
         struct pktgen_thread* pg_thread; /* the owner */
         struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */
@@ -330,8 +330,6 @@ struct pktgen_thread {
         struct pktgen_dev *if_list;           /* All device here */
         struct pktgen_thread* next;
         char name[32];
-        char fname[128]; /* name of proc file */
-        struct proc_dir_entry *proc_ent;
         char result[512];
         u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
         
@@ -473,16 +471,6 @@ static inline __u64 tv_diff(const struct timeval* a, const struct timeval* b)
 
 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_add_device(struct pktgen_thread* t, const char* ifname);
 static struct pktgen_thread* pktgen_find_thread(const char* name);
@@ -506,80 +494,38 @@ static int debug = 0;
 static DECLARE_MUTEX(pktgen_sem);
 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 = {
        .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 
  *
  */
 
-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;
+       char data[128];
 
         if (!capable(CAP_NET_ADMIN)){
                 err = -EPERM;
                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)) {
                err = -EFAULT;
-               goto out_free;
+               goto out;
        }  
        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;
 
- out_free:
-       vfree (data);
  out:
         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;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
+        struct pktgen_dev *pkt_dev = seq->private;
         __u64 sa;
         __u64 stopped;
         __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) {
@@ -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(b2,  pkt_dev->min_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(b2,  pkt_dev->min_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 
-               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) && 
            (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)) 
 
                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 
                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++) 
-               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) 
-                p += sprintf(p, "IPV6  ");
+                seq_printf(seq,  "IPV6  ");
 
         if (pkt_dev->flags &  F_IPSRC_RND) 
-                p += sprintf(p, "IPSRC_RND  ");
+                seq_printf(seq,  "IPSRC_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) 
-                p += sprintf(p, "TXSIZE_RND  ");
+                seq_printf(seq,  "TXSIZE_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) 
-                p += sprintf(p, "UDPDST_RND  ");
+                seq_printf(seq,  "UDPDST_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) 
-                p += sprintf(p, "MACDST_RND  ");
+                seq_printf(seq,  "MACDST_RND  ");
 
         
-        p += sprintf(p, "\n");
+        seq_puts(seq,  "\n");
         
         sa = pkt_dev->started_at;
         stopped = pkt_dev->stopped_at;
         if (pkt_dev->running) 
                 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) {
                char b1[128], b2[128];
                fmt_ip6(b1,  pkt_dev->cur_in6_daddr.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 
-               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])
-               p += sprintf(p, "Result: %s\n", pkt_dev->result);
+               seq_printf(seq,  "Result: %s\n", pkt_dev->result);
        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;
 }
 
-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;
        char name[16], valstr[32];
        unsigned long value = 0;
-        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
         char* pg_result = NULL;
         int tmp = 0;
        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))
                        return -EFAULT;
                 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")) {
@@ -1335,92 +1292,98 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
        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);
 
-        p += sprintf(p, "Running: ");
+        seq_printf(seq, "Running: ");
         
         if_lock(t);
         for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
                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) 
                if(!pkt_dev->running)
-                       p += sprintf(p, "%s ", pkt_dev->ifname);
+                       seq_printf(seq, "%s ", pkt_dev->ifname);
 
        if (t->result[0])
-               p += sprintf(p, "\nResult: %s\n", t->result);
+               seq_printf(seq, "\nResult: %s\n", t->result);
        else
-               p += sprintf(p, "\nResult: NA\n");
-
-       *eof = 1;
+               seq_printf(seq, "\nResult: NA\n");
 
         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;
        char name[40];
-        struct pktgen_thread *t;
         char *pg_result;
         unsigned long value = 0;
-        
+
        if (count < 1) {
                //      sprintf(pg_result, "Wrong command format");
                return -EINVAL;
        }
-  
+
        max = count - i;
         len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0) 
-               return len; 
-     
+        if (len < 0)
+               return len;
+
        i += len;
-  
+
        /* Read variable name */
 
        len = strn_len(&user_buffer[i], sizeof(name) - 1);
-        if (len < 0)  
-               return len; 
+        if (len < 0)
+               return len;
        
        memset(name, 0, sizeof(name));
        if (copy_from_user(name, &user_buffer[i], len))
                return -EFAULT;
        i += len;
-  
+
        max = count -i;
        len = count_trail_chars(&user_buffer[i], max);
-        if (len < 0)  
-               return len; 
-       
+        if (len < 0)
+               return 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) {
                printk("pktgen: ERROR: No thread\n");
                ret = -EINVAL;
@@ -1474,21 +1437,19 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
        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 */
 static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 
@@ -2552,8 +2513,7 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
 
        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();
 
@@ -2825,7 +2785,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, const char* i
         if_lock(t);
 
         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;
                 }
         }
@@ -2864,65 +2824,63 @@ 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) 
 {
         struct pktgen_dev *pkt_dev;
+       struct proc_dir_entry *pe;
        
        /* We don't allow a device to be on several threads */
 
-       if( (pkt_dev = __pktgen_NN_threads(ifname, FIND)) == NULL) {
-                                                  
-               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->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;
-
-                return add_dev_to_thread(t, pkt_dev);
-        }
-        else {
+       pkt_dev = __pktgen_NN_threads(ifname, FIND);
+       if (pkt_dev) {
                 printk("pktgen: ERROR: interface already used.\n");
                 return -EBUSY;
         }
+
+       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, 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);
 }
 
 static struct pktgen_thread *pktgen_find_thread(const char* name) 
@@ -2945,6 +2903,7 @@ static struct pktgen_thread *pktgen_find_thread(const char* name)
 static int pktgen_create_thread(const char* name, int cpu) 
 {
         struct pktgen_thread *t = NULL;
+       struct proc_dir_entry *pe;
 
         if (strlen(name) > 31) {
                 printk("pktgen: ERROR:  Thread name cannot be more than 31 characters.\n");
@@ -2966,17 +2925,16 @@ static int pktgen_create_thread(const char* name, int cpu)
         spin_lock_init(&t->if_lock);
        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);
                 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;
         pktgen_threads = t;
@@ -3031,8 +2989,7 @@ static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_
 
         /* 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)
                vfree(pkt_dev->flows);
@@ -3043,21 +3000,24 @@ static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_
 static int __init pg_init(void) 
 {
        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;
         }
 
-        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_netdevice_notifier(&pktgen_notifier_block);
@@ -3089,10 +3049,8 @@ static void __exit pg_cleanup(void)
        unregister_netdevice_notifier(&pktgen_notifier_block);
 
         /* 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);
 }