aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-03-04 19:11:51 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:23:31 -0400
commit39df232f1a9ba48d41c68ee7d4046756e709cf91 (patch)
tree8778c69e9b70f55d9c3161674887f3de217a0d6a
parentd5f1ce9a5e80fb315c86b036a89b1237fdf11938 (diff)
[PKTGEN]: fix device name handling
Since devices can change name and other wierdness, don't hold onto a copy of device name, instead use pointer to output device. Fix a couple of leaks in error handling path as well. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Robert Olsson <robert.olsson@its.uu.se> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/pktgen.c137
1 files changed, 70 insertions, 67 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index edf46fbb27d1..895739fdfac3 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -211,15 +211,11 @@ struct flow_state {
211}; 211};
212 212
213struct pktgen_dev { 213struct pktgen_dev {
214
215 /* 214 /*
216 * Try to keep frequent/infrequent used vars. separated. 215 * Try to keep frequent/infrequent used vars. separated.
217 */ 216 */
218 217 struct proc_dir_entry *entry; /* proc file */
219 char ifname[IFNAMSIZ]; 218 struct pktgen_thread *pg_thread;/* the owner */
220 char result[512];
221
222 struct pktgen_thread *pg_thread; /* the owner */
223 struct list_head list; /* Used for chaining in the thread's run-queue */ 219 struct list_head list; /* Used for chaining in the thread's run-queue */
224 220
225 int running; /* if this changes to false, the test will stop */ 221 int running; /* if this changes to false, the test will stop */
@@ -346,6 +342,8 @@ struct pktgen_dev {
346 unsigned cflows; /* Concurrent flows (config) */ 342 unsigned cflows; /* Concurrent flows (config) */
347 unsigned lflow; /* Flow length (config) */ 343 unsigned lflow; /* Flow length (config) */
348 unsigned nflows; /* accumulated flows (stats) */ 344 unsigned nflows; /* accumulated flows (stats) */
345
346 char result[512];
349}; 347};
350 348
351struct pktgen_hdr { 349struct pktgen_hdr {
@@ -498,7 +496,7 @@ static void pktgen_stop_all_threads_ifs(void);
498static int pktgen_stop_device(struct pktgen_dev *pkt_dev); 496static int pktgen_stop_device(struct pktgen_dev *pkt_dev);
499static void pktgen_stop(struct pktgen_thread *t); 497static void pktgen_stop(struct pktgen_thread *t);
500static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); 498static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
501static int pktgen_mark_device(const char *ifname); 499
502static unsigned int scan_ip6(const char *s, char ip[16]); 500static unsigned int scan_ip6(const char *s, char ip[16]);
503static unsigned int fmt_ip6(char *s, const char ip[16]); 501static unsigned int fmt_ip6(char *s, const char ip[16]);
504 502
@@ -592,7 +590,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
592 " frags: %d delay: %u clone_skb: %d ifname: %s\n", 590 " frags: %d delay: %u clone_skb: %d ifname: %s\n",
593 pkt_dev->nfrags, 591 pkt_dev->nfrags,
594 1000 * pkt_dev->delay_us + pkt_dev->delay_ns, 592 1000 * pkt_dev->delay_us + pkt_dev->delay_ns,
595 pkt_dev->clone_skb, pkt_dev->ifname); 593 pkt_dev->clone_skb, pkt_dev->odev->name);
596 594
597 seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows, 595 seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows,
598 pkt_dev->lflow); 596 pkt_dev->lflow);
@@ -1683,13 +1681,13 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
1683 if_lock(t); 1681 if_lock(t);
1684 list_for_each_entry(pkt_dev, &t->if_list, list) 1682 list_for_each_entry(pkt_dev, &t->if_list, list)
1685 if (pkt_dev->running) 1683 if (pkt_dev->running)
1686 seq_printf(seq, "%s ", pkt_dev->ifname); 1684 seq_printf(seq, "%s ", pkt_dev->odev->name);
1687 1685
1688 seq_printf(seq, "\nStopped: "); 1686 seq_printf(seq, "\nStopped: ");
1689 1687
1690 list_for_each_entry(pkt_dev, &t->if_list, list) 1688 list_for_each_entry(pkt_dev, &t->if_list, list)
1691 if (!pkt_dev->running) 1689 if (!pkt_dev->running)
1692 seq_printf(seq, "%s ", pkt_dev->ifname); 1690 seq_printf(seq, "%s ", pkt_dev->odev->name);
1693 1691
1694 if (t->result[0]) 1692 if (t->result[0])
1695 seq_printf(seq, "\nResult: %s\n", t->result); 1693 seq_printf(seq, "\nResult: %s\n", t->result);
@@ -1835,12 +1833,11 @@ static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove)
1835/* 1833/*
1836 * mark a device for removal 1834 * mark a device for removal
1837 */ 1835 */
1838static int pktgen_mark_device(const char *ifname) 1836static void pktgen_mark_device(const char *ifname)
1839{ 1837{
1840 struct pktgen_dev *pkt_dev = NULL; 1838 struct pktgen_dev *pkt_dev = NULL;
1841 const int max_tries = 10, msec_per_try = 125; 1839 const int max_tries = 10, msec_per_try = 125;
1842 int i = 0; 1840 int i = 0;
1843 int ret = 0;
1844 1841
1845 mutex_lock(&pktgen_thread_lock); 1842 mutex_lock(&pktgen_thread_lock);
1846 pr_debug("pktgen: pktgen_mark_device marking %s for removal\n", ifname); 1843 pr_debug("pktgen: pktgen_mark_device marking %s for removal\n", ifname);
@@ -1861,32 +1858,49 @@ static int pktgen_mark_device(const char *ifname)
1861 printk("pktgen_mark_device: timed out after waiting " 1858 printk("pktgen_mark_device: timed out after waiting "
1862 "%d msec for device %s to be removed\n", 1859 "%d msec for device %s to be removed\n",
1863 msec_per_try * i, ifname); 1860 msec_per_try * i, ifname);
1864 ret = 1;
1865 break; 1861 break;
1866 } 1862 }
1867 1863
1868 } 1864 }
1869 1865
1870 mutex_unlock(&pktgen_thread_lock); 1866 mutex_unlock(&pktgen_thread_lock);
1867}
1871 1868
1872 return ret; 1869static void pktgen_change_name(struct net_device *dev)
1870{
1871 struct pktgen_thread *t;
1872
1873 list_for_each_entry(t, &pktgen_threads, th_list) {
1874 struct pktgen_dev *pkt_dev;
1875
1876 list_for_each_entry(pkt_dev, &t->if_list, list) {
1877 if (pkt_dev->odev != dev)
1878 continue;
1879
1880 remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
1881
1882 pkt_dev->entry = create_proc_entry(dev->name, 0600,
1883 pg_proc_dir);
1884 if (!pkt_dev->entry)
1885 printk(KERN_ERR "pktgen: can't move proc "
1886 " entry for '%s'\n", dev->name);
1887 break;
1888 }
1889 }
1873} 1890}
1874 1891
1875static int pktgen_device_event(struct notifier_block *unused, 1892static int pktgen_device_event(struct notifier_block *unused,
1876 unsigned long event, void *ptr) 1893 unsigned long event, void *ptr)
1877{ 1894{
1878 struct net_device *dev = (struct net_device *)(ptr); 1895 struct net_device *dev = ptr;
1879 1896
1880 /* It is OK that we do not hold the group lock right now, 1897 /* It is OK that we do not hold the group lock right now,
1881 * as we run under the RTNL lock. 1898 * as we run under the RTNL lock.
1882 */ 1899 */
1883 1900
1884 switch (event) { 1901 switch (event) {
1885 case NETDEV_CHANGEADDR: 1902 case NETDEV_CHANGENAME:
1886 case NETDEV_GOING_DOWN: 1903 pktgen_change_name(dev);
1887 case NETDEV_DOWN:
1888 case NETDEV_UP:
1889 /* Ignore for now */
1890 break; 1904 break;
1891 1905
1892 case NETDEV_UNREGISTER: 1906 case NETDEV_UNREGISTER:
@@ -1899,41 +1913,36 @@ static int pktgen_device_event(struct notifier_block *unused,
1899 1913
1900/* Associate pktgen_dev with a device. */ 1914/* Associate pktgen_dev with a device. */
1901 1915
1902static struct net_device *pktgen_setup_dev(struct pktgen_dev *pkt_dev) 1916static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname)
1903{ 1917{
1904 struct net_device *odev; 1918 struct net_device *odev;
1919 int err;
1905 1920
1906 /* Clean old setups */ 1921 /* Clean old setups */
1907
1908 if (pkt_dev->odev) { 1922 if (pkt_dev->odev) {
1909 dev_put(pkt_dev->odev); 1923 dev_put(pkt_dev->odev);
1910 pkt_dev->odev = NULL; 1924 pkt_dev->odev = NULL;
1911 } 1925 }
1912 1926
1913 odev = dev_get_by_name(pkt_dev->ifname); 1927 odev = dev_get_by_name(ifname);
1914
1915 if (!odev) { 1928 if (!odev) {
1916 printk("pktgen: no such netdevice: \"%s\"\n", pkt_dev->ifname); 1929 printk("pktgen: no such netdevice: \"%s\"\n", ifname);
1917 goto out; 1930 return -ENODEV;
1918 } 1931 }
1932
1919 if (odev->type != ARPHRD_ETHER) { 1933 if (odev->type != ARPHRD_ETHER) {
1920 printk("pktgen: not an ethernet device: \"%s\"\n", 1934 printk("pktgen: not an ethernet device: \"%s\"\n", ifname);
1921 pkt_dev->ifname); 1935 err = -EINVAL;
1922 goto out_put; 1936 } else if (!netif_running(odev)) {
1923 } 1937 printk("pktgen: device is down: \"%s\"\n", ifname);
1924 if (!netif_running(odev)) { 1938 err = -ENETDOWN;
1925 printk("pktgen: device is down: \"%s\"\n", pkt_dev->ifname); 1939 } else {
1926 goto out_put; 1940 pkt_dev->odev = odev;
1941 return 0;
1927 } 1942 }
1928 pkt_dev->odev = odev;
1929 1943
1930 return pkt_dev->odev;
1931
1932out_put:
1933 dev_put(odev); 1944 dev_put(odev);
1934out: 1945 return err;
1935 return NULL;
1936
1937} 1946}
1938 1947
1939/* Read pkt_dev from the interface and set up internal pktgen_dev 1948/* Read pkt_dev from the interface and set up internal pktgen_dev
@@ -1941,10 +1950,6 @@ out:
1941 */ 1950 */
1942static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) 1951static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
1943{ 1952{
1944 /* Try once more, just in case it works now. */
1945 if (!pkt_dev->odev)
1946 pktgen_setup_dev(pkt_dev);
1947
1948 if (!pkt_dev->odev) { 1953 if (!pkt_dev->odev) {
1949 printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n"); 1954 printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n");
1950 sprintf(pkt_dev->result, 1955 sprintf(pkt_dev->result,
@@ -2988,7 +2993,7 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
2988 2993
2989 if (!pkt_dev->running) { 2994 if (!pkt_dev->running) {
2990 printk("pktgen: interface: %s is already stopped\n", 2995 printk("pktgen: interface: %s is already stopped\n",
2991 pkt_dev->ifname); 2996 pkt_dev->odev->name);
2992 return -EINVAL; 2997 return -EINVAL;
2993 } 2998 }
2994 2999
@@ -3340,7 +3345,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
3340 if_lock(t); 3345 if_lock(t);
3341 3346
3342 list_for_each_entry(p, &t->if_list, list) 3347 list_for_each_entry(p, &t->if_list, list)
3343 if (strncmp(p->ifname, ifname, IFNAMSIZ) == 0) { 3348 if (strncmp(p->odev->name, ifname, IFNAMSIZ) == 0) {
3344 pkt_dev = p; 3349 pkt_dev = p;
3345 break; 3350 break;
3346 } 3351 }
@@ -3381,7 +3386,7 @@ out:
3381static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) 3386static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
3382{ 3387{
3383 struct pktgen_dev *pkt_dev; 3388 struct pktgen_dev *pkt_dev;
3384 struct proc_dir_entry *pe; 3389 int err;
3385 3390
3386 /* We don't allow a device to be on several threads */ 3391 /* We don't allow a device to be on several threads */
3387 3392
@@ -3423,29 +3428,28 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
3423 pkt_dev->svlan_cfi = 0; 3428 pkt_dev->svlan_cfi = 0;
3424 pkt_dev->svlan_id = 0xffff; 3429 pkt_dev->svlan_id = 0xffff;
3425 3430
3426 strncpy(pkt_dev->ifname, ifname, IFNAMSIZ); 3431 err = pktgen_setup_dev(pkt_dev, ifname);
3427 3432 if (err)
3428 if (!pktgen_setup_dev(pkt_dev)) { 3433 goto out1;
3429 printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
3430 if (pkt_dev->flows)
3431 vfree(pkt_dev->flows);
3432 kfree(pkt_dev);
3433 return -ENODEV;
3434 }
3435 3434
3436 pe = create_proc_entry(ifname, 0600, pg_proc_dir); 3435 pkt_dev->entry = create_proc_entry(ifname, 0600, pg_proc_dir);
3437 if (!pe) { 3436 if (!pkt_dev->entry) {
3438 printk("pktgen: cannot create %s/%s procfs entry.\n", 3437 printk("pktgen: cannot create %s/%s procfs entry.\n",
3439 PG_PROC_DIR, ifname); 3438 PG_PROC_DIR, ifname);
3440 if (pkt_dev->flows) 3439 err = -EINVAL;
3441 vfree(pkt_dev->flows); 3440 goto out2;
3442 kfree(pkt_dev);
3443 return -EINVAL;
3444 } 3441 }
3445 pe->proc_fops = &pktgen_if_fops; 3442 pkt_dev->entry->proc_fops = &pktgen_if_fops;
3446 pe->data = pkt_dev; 3443 pkt_dev->entry->data = pkt_dev;
3447 3444
3448 return add_dev_to_thread(t, pkt_dev); 3445 return add_dev_to_thread(t, pkt_dev);
3446out2:
3447 dev_put(pkt_dev->odev);
3448out1:
3449 if (pkt_dev->flows)
3450 vfree(pkt_dev->flows);
3451 kfree(pkt_dev);
3452 return err;
3449} 3453}
3450 3454
3451static int __init pktgen_create_thread(int cpu) 3455static int __init pktgen_create_thread(int cpu)
@@ -3533,9 +3537,8 @@ static int pktgen_remove_device(struct pktgen_thread *t,
3533 3537
3534 _rem_dev_from_if_list(t, pkt_dev); 3538 _rem_dev_from_if_list(t, pkt_dev);
3535 3539
3536 /* Clean up proc file system */ 3540 if (pkt_dev->entry)
3537 3541 remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
3538 remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
3539 3542
3540 if (pkt_dev->flows) 3543 if (pkt_dev->flows)
3541 vfree(pkt_dev->flows); 3544 vfree(pkt_dev->flows);