pktgen.c (4e58a0275015e5c8988bda9cd0635e2ef405c985) pktgen.c (604dfd6efc9b79bce432f2394791708d8e8f6efc)
1/*
2 * Authors:
3 * Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se>
4 * Uppsala University and
5 * Swedish University of Agricultural Sciences
6 *
7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
8 * Ben Greear <greearb@candelatech.com>

--- 150 unchanged lines hidden (view full) ---

159#include <linux/prefetch.h>
160#include <net/net_namespace.h>
161#include <net/checksum.h>
162#include <net/ipv6.h>
163#include <net/addrconf.h>
164#ifdef CONFIG_XFRM
165#include <net/xfrm.h>
166#endif
1/*
2 * Authors:
3 * Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se>
4 * Uppsala University and
5 * Swedish University of Agricultural Sciences
6 *
7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
8 * Ben Greear <greearb@candelatech.com>

--- 150 unchanged lines hidden (view full) ---

159#include <linux/prefetch.h>
160#include <net/net_namespace.h>
161#include <net/checksum.h>
162#include <net/ipv6.h>
163#include <net/addrconf.h>
164#ifdef CONFIG_XFRM
165#include <net/xfrm.h>
166#endif
167#include <net/netns/generic.h>
168#include <asm/byteorder.h>
169#include <linux/rcupdate.h>
170#include <linux/bitops.h>
171#include <linux/io.h>
172#include <linux/timex.h>
173#include <linux/uaccess.h>
174#include <asm/dma.h>
175#include <asm/div64.h> /* do_div */

--- 32 unchanged lines hidden (view full) ---

208/* If lock -- can be removed after some work */
209#define if_lock(t) spin_lock(&(t->if_lock));
210#define if_unlock(t) spin_unlock(&(t->if_lock));
211
212/* Used to help with determining the pkts on receive */
213#define PKTGEN_MAGIC 0xbe9be955
214#define PG_PROC_DIR "pktgen"
215#define PGCTRL "pgctrl"
167#include <asm/byteorder.h>
168#include <linux/rcupdate.h>
169#include <linux/bitops.h>
170#include <linux/io.h>
171#include <linux/timex.h>
172#include <linux/uaccess.h>
173#include <asm/dma.h>
174#include <asm/div64.h> /* do_div */

--- 32 unchanged lines hidden (view full) ---

207/* If lock -- can be removed after some work */
208#define if_lock(t) spin_lock(&(t->if_lock));
209#define if_unlock(t) spin_unlock(&(t->if_lock));
210
211/* Used to help with determining the pkts on receive */
212#define PKTGEN_MAGIC 0xbe9be955
213#define PG_PROC_DIR "pktgen"
214#define PGCTRL "pgctrl"
215static struct proc_dir_entry *pg_proc_dir;
216
217#define MAX_CFLOWS 65536
218
219#define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
220#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
221
222struct flow_state {
223 __be32 cur_daddr;

--- 168 unchanged lines hidden (view full) ---

392
393struct pktgen_hdr {
394 __be32 pgh_magic;
395 __be32 seq_num;
396 __be32 tv_sec;
397 __be32 tv_usec;
398};
399
216
217#define MAX_CFLOWS 65536
218
219#define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
220#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
221
222struct flow_state {
223 __be32 cur_daddr;

--- 168 unchanged lines hidden (view full) ---

392
393struct pktgen_hdr {
394 __be32 pgh_magic;
395 __be32 seq_num;
396 __be32 tv_sec;
397 __be32 tv_usec;
398};
399
400static bool pktgen_exiting __read_mostly;
400
401
401static int pg_net_id __read_mostly;
402
403struct pktgen_net {
404 struct net *net;
405 struct proc_dir_entry *proc_dir;
406 struct list_head pktgen_threads;
407 bool pktgen_exiting;
408};
409
410struct pktgen_thread {
411 spinlock_t if_lock; /* for list of devices */
412 struct list_head if_list; /* All device here */
413 struct list_head th_list;
414 struct task_struct *tsk;
415 char result[512];
416
417 /* Field for thread to receive "posted" events terminate,
418 stop ifs etc. */
419
420 u32 control;
421 int cpu;
422
423 wait_queue_head_t queue;
424 struct completion start_done;
402struct pktgen_thread {
403 spinlock_t if_lock; /* for list of devices */
404 struct list_head if_list; /* All device here */
405 struct list_head th_list;
406 struct task_struct *tsk;
407 char result[512];
408
409 /* Field for thread to receive "posted" events terminate,
410 stop ifs etc. */
411
412 u32 control;
413 int cpu;
414
415 wait_queue_head_t queue;
416 struct completion start_done;
425 struct pktgen_net *net;
426};
427
428#define REMOVE 1
429#define FIND 0
430
431static const char version[] =
432 "Packet Generator for packet performance testing. "
433 "Version: " VERSION "\n";
434
435static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *i);
436static int pktgen_add_device(struct pktgen_thread *t, const char *ifname);
437static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
438 const char *ifname, bool exact);
439static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
417};
418
419#define REMOVE 1
420#define FIND 0
421
422static const char version[] =
423 "Packet Generator for packet performance testing. "
424 "Version: " VERSION "\n";
425
426static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *i);
427static int pktgen_add_device(struct pktgen_thread *t, const char *ifname);
428static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
429 const char *ifname, bool exact);
430static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
440static void pktgen_run_all_threads(struct pktgen_net *pn);
441static void pktgen_reset_all_threads(struct pktgen_net *pn);
442static void pktgen_stop_all_threads_ifs(struct pktgen_net *pn);
431static void pktgen_run_all_threads(void);
432static void pktgen_reset_all_threads(void);
433static void pktgen_stop_all_threads_ifs(void);
443
444static void pktgen_stop(struct pktgen_thread *t);
445static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
446
447/* Module parameters, defaults. */
448static int pg_count_d __read_mostly = 1000;
449static int pg_delay_d __read_mostly;
450static int pg_clone_skb_d __read_mostly;
451static int debug __read_mostly;
452
453static DEFINE_MUTEX(pktgen_thread_lock);
434
435static void pktgen_stop(struct pktgen_thread *t);
436static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
437
438/* Module parameters, defaults. */
439static int pg_count_d __read_mostly = 1000;
440static int pg_delay_d __read_mostly;
441static int pg_clone_skb_d __read_mostly;
442static int debug __read_mostly;
443
444static DEFINE_MUTEX(pktgen_thread_lock);
445static LIST_HEAD(pktgen_threads);
454
455static struct notifier_block pktgen_notifier_block = {
456 .notifier_call = pktgen_device_event,
457};
458
459/*
460 * /proc handling functions
461 *

--- 5 unchanged lines hidden (view full) ---

467 return 0;
468}
469
470static ssize_t pgctrl_write(struct file *file, const char __user *buf,
471 size_t count, loff_t *ppos)
472{
473 int err = 0;
474 char data[128];
446
447static struct notifier_block pktgen_notifier_block = {
448 .notifier_call = pktgen_device_event,
449};
450
451/*
452 * /proc handling functions
453 *

--- 5 unchanged lines hidden (view full) ---

459 return 0;
460}
461
462static ssize_t pgctrl_write(struct file *file, const char __user *buf,
463 size_t count, loff_t *ppos)
464{
465 int err = 0;
466 char data[128];
475 struct pktgen_net *pn = net_generic(current->nsproxy->net_ns, pg_net_id);
476
477 if (!capable(CAP_NET_ADMIN)) {
478 err = -EPERM;
479 goto out;
480 }
481
482 if (count > sizeof(data))
483 count = sizeof(data);
484
485 if (copy_from_user(data, buf, count)) {
486 err = -EFAULT;
487 goto out;
488 }
489 data[count - 1] = 0; /* Make string */
490
491 if (!strcmp(data, "stop"))
467
468 if (!capable(CAP_NET_ADMIN)) {
469 err = -EPERM;
470 goto out;
471 }
472
473 if (count > sizeof(data))
474 count = sizeof(data);
475
476 if (copy_from_user(data, buf, count)) {
477 err = -EFAULT;
478 goto out;
479 }
480 data[count - 1] = 0; /* Make string */
481
482 if (!strcmp(data, "stop"))
492 pktgen_stop_all_threads_ifs(pn);
483 pktgen_stop_all_threads_ifs();
493
494 else if (!strcmp(data, "start"))
484
485 else if (!strcmp(data, "start"))
495 pktgen_run_all_threads(pn);
486 pktgen_run_all_threads();
496
497 else if (!strcmp(data, "reset"))
487
488 else if (!strcmp(data, "reset"))
498 pktgen_reset_all_threads(pn);
489 pktgen_reset_all_threads();
499
500 else
501 pr_warning("Unknown command: %s\n", data);
502
503 err = count;
504
505out:
506 return err;

--- 1278 unchanged lines hidden (view full) ---

1785 if (len < 0) {
1786 ret = len;
1787 goto out;
1788 }
1789 if (copy_from_user(f, &user_buffer[i], len))
1790 return -EFAULT;
1791 i += len;
1792 mutex_lock(&pktgen_thread_lock);
490
491 else
492 pr_warning("Unknown command: %s\n", data);
493
494 err = count;
495
496out:
497 return err;

--- 1278 unchanged lines hidden (view full) ---

1776 if (len < 0) {
1777 ret = len;
1778 goto out;
1779 }
1780 if (copy_from_user(f, &user_buffer[i], len))
1781 return -EFAULT;
1782 i += len;
1783 mutex_lock(&pktgen_thread_lock);
1793 pktgen_add_device(t, f);
1784 ret = pktgen_add_device(t, f);
1794 mutex_unlock(&pktgen_thread_lock);
1785 mutex_unlock(&pktgen_thread_lock);
1795 ret = count;
1796 sprintf(pg_result, "OK: add_device=%s", f);
1786 if (!ret) {
1787 ret = count;
1788 sprintf(pg_result, "OK: add_device=%s", f);
1789 } else
1790 sprintf(pg_result, "ERROR: can not add device %s", f);
1797 goto out;
1798 }
1799
1800 if (!strcmp(name, "rem_device_all")) {
1801 mutex_lock(&pktgen_thread_lock);
1802 t->control |= T_REMDEVALL;
1803 mutex_unlock(&pktgen_thread_lock);
1804 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */

--- 23 unchanged lines hidden (view full) ---

1828 .open = pktgen_thread_open,
1829 .read = seq_read,
1830 .llseek = seq_lseek,
1831 .write = pktgen_thread_write,
1832 .release = single_release,
1833};
1834
1835/* Think find or remove for NN */
1791 goto out;
1792 }
1793
1794 if (!strcmp(name, "rem_device_all")) {
1795 mutex_lock(&pktgen_thread_lock);
1796 t->control |= T_REMDEVALL;
1797 mutex_unlock(&pktgen_thread_lock);
1798 schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */

--- 23 unchanged lines hidden (view full) ---

1822 .open = pktgen_thread_open,
1823 .read = seq_read,
1824 .llseek = seq_lseek,
1825 .write = pktgen_thread_write,
1826 .release = single_release,
1827};
1828
1829/* Think find or remove for NN */
1836static struct pktgen_dev *__pktgen_NN_threads(const struct pktgen_net *pn,
1837 const char *ifname, int remove)
1830static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove)
1838{
1839 struct pktgen_thread *t;
1840 struct pktgen_dev *pkt_dev = NULL;
1841 bool exact = (remove == FIND);
1842
1831{
1832 struct pktgen_thread *t;
1833 struct pktgen_dev *pkt_dev = NULL;
1834 bool exact = (remove == FIND);
1835
1843 list_for_each_entry(t, &pn->pktgen_threads, th_list) {
1836 list_for_each_entry(t, &pktgen_threads, th_list) {
1844 pkt_dev = pktgen_find_dev(t, ifname, exact);
1845 if (pkt_dev) {
1846 if (remove) {
1847 if_lock(t);
1848 pkt_dev->removal_mark = 1;
1849 t->control |= T_REMDEV;
1850 if_unlock(t);
1851 }
1852 break;
1853 }
1854 }
1855 return pkt_dev;
1856}
1857
1858/*
1859 * mark a device for removal
1860 */
1837 pkt_dev = pktgen_find_dev(t, ifname, exact);
1838 if (pkt_dev) {
1839 if (remove) {
1840 if_lock(t);
1841 pkt_dev->removal_mark = 1;
1842 t->control |= T_REMDEV;
1843 if_unlock(t);
1844 }
1845 break;
1846 }
1847 }
1848 return pkt_dev;
1849}
1850
1851/*
1852 * mark a device for removal
1853 */
1861static void pktgen_mark_device(const struct pktgen_net *pn, const char *ifname)
1854static void pktgen_mark_device(const char *ifname)
1862{
1863 struct pktgen_dev *pkt_dev = NULL;
1864 const int max_tries = 10, msec_per_try = 125;
1865 int i = 0;
1866
1867 mutex_lock(&pktgen_thread_lock);
1868 pr_debug("%s: marking %s for removal\n", __func__, ifname);
1869
1870 while (1) {
1871
1855{
1856 struct pktgen_dev *pkt_dev = NULL;
1857 const int max_tries = 10, msec_per_try = 125;
1858 int i = 0;
1859
1860 mutex_lock(&pktgen_thread_lock);
1861 pr_debug("%s: marking %s for removal\n", __func__, ifname);
1862
1863 while (1) {
1864
1872 pkt_dev = __pktgen_NN_threads(pn, ifname, REMOVE);
1865 pkt_dev = __pktgen_NN_threads(ifname, REMOVE);
1873 if (pkt_dev == NULL)
1874 break; /* success */
1875
1876 mutex_unlock(&pktgen_thread_lock);
1877 pr_debug("%s: waiting for %s to disappear....\n",
1878 __func__, ifname);
1879 schedule_timeout_interruptible(msecs_to_jiffies(msec_per_try));
1880 mutex_lock(&pktgen_thread_lock);

--- 4 unchanged lines hidden (view full) ---

1885 break;
1886 }
1887
1888 }
1889
1890 mutex_unlock(&pktgen_thread_lock);
1891}
1892
1866 if (pkt_dev == NULL)
1867 break; /* success */
1868
1869 mutex_unlock(&pktgen_thread_lock);
1870 pr_debug("%s: waiting for %s to disappear....\n",
1871 __func__, ifname);
1872 schedule_timeout_interruptible(msecs_to_jiffies(msec_per_try));
1873 mutex_lock(&pktgen_thread_lock);

--- 4 unchanged lines hidden (view full) ---

1878 break;
1879 }
1880
1881 }
1882
1883 mutex_unlock(&pktgen_thread_lock);
1884}
1885
1893static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *dev)
1886static void pktgen_change_name(struct net_device *dev)
1894{
1895 struct pktgen_thread *t;
1896
1887{
1888 struct pktgen_thread *t;
1889
1897 list_for_each_entry(t, &pn->pktgen_threads, th_list) {
1890 list_for_each_entry(t, &pktgen_threads, th_list) {
1898 struct pktgen_dev *pkt_dev;
1899
1900 list_for_each_entry(pkt_dev, &t->if_list, list) {
1901 if (pkt_dev->odev != dev)
1902 continue;
1903
1891 struct pktgen_dev *pkt_dev;
1892
1893 list_for_each_entry(pkt_dev, &t->if_list, list) {
1894 if (pkt_dev->odev != dev)
1895 continue;
1896
1904 remove_proc_entry(pkt_dev->entry->name, pn->proc_dir);
1897 remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
1905
1906 pkt_dev->entry = proc_create_data(dev->name, 0600,
1898
1899 pkt_dev->entry = proc_create_data(dev->name, 0600,
1907 pn->proc_dir,
1900 pg_proc_dir,
1908 &pktgen_if_fops,
1909 pkt_dev);
1910 if (!pkt_dev->entry)
1911 pr_err("can't move proc entry for '%s'\n",
1912 dev->name);
1913 break;
1914 }
1915 }
1916}
1917
1918static int pktgen_device_event(struct notifier_block *unused,
1919 unsigned long event, void *ptr)
1920{
1921 struct net_device *dev = ptr;
1901 &pktgen_if_fops,
1902 pkt_dev);
1903 if (!pkt_dev->entry)
1904 pr_err("can't move proc entry for '%s'\n",
1905 dev->name);
1906 break;
1907 }
1908 }
1909}
1910
1911static int pktgen_device_event(struct notifier_block *unused,
1912 unsigned long event, void *ptr)
1913{
1914 struct net_device *dev = ptr;
1922 struct pktgen_net *pn = net_generic(dev_net(dev), pg_net_id);
1923
1915
1924 if (pn->pktgen_exiting)
1916 if (!net_eq(dev_net(dev), &init_net) || pktgen_exiting)
1925 return NOTIFY_DONE;
1926
1927 /* It is OK that we do not hold the group lock right now,
1928 * as we run under the RTNL lock.
1929 */
1930
1931 switch (event) {
1932 case NETDEV_CHANGENAME:
1917 return NOTIFY_DONE;
1918
1919 /* It is OK that we do not hold the group lock right now,
1920 * as we run under the RTNL lock.
1921 */
1922
1923 switch (event) {
1924 case NETDEV_CHANGENAME:
1933 pktgen_change_name(pn, dev);
1925 pktgen_change_name(dev);
1934 break;
1935
1936 case NETDEV_UNREGISTER:
1926 break;
1927
1928 case NETDEV_UNREGISTER:
1937 pktgen_mark_device(pn, dev->name);
1929 pktgen_mark_device(dev->name);
1938 break;
1939 }
1940
1941 return NOTIFY_DONE;
1942}
1943
1930 break;
1931 }
1932
1933 return NOTIFY_DONE;
1934}
1935
1944static struct net_device *pktgen_dev_get_by_name(const struct pktgen_net *pn,
1945 struct pktgen_dev *pkt_dev,
1936static struct net_device *pktgen_dev_get_by_name(struct pktgen_dev *pkt_dev,
1946 const char *ifname)
1947{
1948 char b[IFNAMSIZ+5];
1949 int i;
1950
1951 for (i = 0; ifname[i] != '@'; i++) {
1952 if (i == IFNAMSIZ)
1953 break;
1954
1955 b[i] = ifname[i];
1956 }
1957 b[i] = 0;
1958
1937 const char *ifname)
1938{
1939 char b[IFNAMSIZ+5];
1940 int i;
1941
1942 for (i = 0; ifname[i] != '@'; i++) {
1943 if (i == IFNAMSIZ)
1944 break;
1945
1946 b[i] = ifname[i];
1947 }
1948 b[i] = 0;
1949
1959 return dev_get_by_name(pn->net, b);
1950 return dev_get_by_name(&init_net, b);
1960}
1961
1962
1963/* Associate pktgen_dev with a device. */
1964
1951}
1952
1953
1954/* Associate pktgen_dev with a device. */
1955
1965static int pktgen_setup_dev(const struct pktgen_net *pn,
1966 struct pktgen_dev *pkt_dev, const char *ifname)
1956static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname)
1967{
1968 struct net_device *odev;
1969 int err;
1970
1971 /* Clean old setups */
1972 if (pkt_dev->odev) {
1973 dev_put(pkt_dev->odev);
1974 pkt_dev->odev = NULL;
1975 }
1976
1957{
1958 struct net_device *odev;
1959 int err;
1960
1961 /* Clean old setups */
1962 if (pkt_dev->odev) {
1963 dev_put(pkt_dev->odev);
1964 pkt_dev->odev = NULL;
1965 }
1966
1977 odev = pktgen_dev_get_by_name(pn, pkt_dev, ifname);
1967 odev = pktgen_dev_get_by_name(pkt_dev, ifname);
1978 if (!odev) {
1979 pr_err("no such netdevice: \"%s\"\n", ifname);
1980 return -ENODEV;
1981 }
1982
1983 if (odev->type != ARPHRD_ETHER) {
1984 pr_err("not an ethernet device: \"%s\"\n", ifname);
1985 err = -EINVAL;

--- 225 unchanged lines hidden (view full) ---

2211#ifdef CONFIG_XFRM
2212/* If there was already an IPSEC SA, we keep it as is, else
2213 * we go look for it ...
2214*/
2215#define DUMMY_MARK 0
2216static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
2217{
2218 struct xfrm_state *x = pkt_dev->flows[flow].x;
1968 if (!odev) {
1969 pr_err("no such netdevice: \"%s\"\n", ifname);
1970 return -ENODEV;
1971 }
1972
1973 if (odev->type != ARPHRD_ETHER) {
1974 pr_err("not an ethernet device: \"%s\"\n", ifname);
1975 err = -EINVAL;

--- 225 unchanged lines hidden (view full) ---

2201#ifdef CONFIG_XFRM
2202/* If there was already an IPSEC SA, we keep it as is, else
2203 * we go look for it ...
2204*/
2205#define DUMMY_MARK 0
2206static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
2207{
2208 struct xfrm_state *x = pkt_dev->flows[flow].x;
2219 struct pktgen_net *pn = net_generic(dev_net(pkt_dev->odev), pg_net_id);
2220 if (!x) {
2221 /*slow path: we dont already have xfrm_state*/
2209 if (!x) {
2210 /*slow path: we dont already have xfrm_state*/
2222 x = xfrm_stateonly_find(pn->net, DUMMY_MARK,
2211 x = xfrm_stateonly_find(&init_net, DUMMY_MARK,
2223 (xfrm_address_t *)&pkt_dev->cur_daddr,
2224 (xfrm_address_t *)&pkt_dev->cur_saddr,
2225 AF_INET,
2226 pkt_dev->ipsmode,
2227 pkt_dev->ipsproto, 0);
2228 if (x) {
2229 pkt_dev->flows[flow].x = x;
2230 set_pkt_overhead(pkt_dev);

--- 690 unchanged lines hidden (view full) ---

2921 } else
2922 strcpy(pkt_dev->result, "Error starting");
2923 }
2924 if_unlock(t);
2925 if (started)
2926 t->control &= ~(T_STOP);
2927}
2928
2212 (xfrm_address_t *)&pkt_dev->cur_daddr,
2213 (xfrm_address_t *)&pkt_dev->cur_saddr,
2214 AF_INET,
2215 pkt_dev->ipsmode,
2216 pkt_dev->ipsproto, 0);
2217 if (x) {
2218 pkt_dev->flows[flow].x = x;
2219 set_pkt_overhead(pkt_dev);

--- 690 unchanged lines hidden (view full) ---

2910 } else
2911 strcpy(pkt_dev->result, "Error starting");
2912 }
2913 if_unlock(t);
2914 if (started)
2915 t->control &= ~(T_STOP);
2916}
2917
2929static void pktgen_stop_all_threads_ifs(struct pktgen_net *pn)
2918static void pktgen_stop_all_threads_ifs(void)
2930{
2931 struct pktgen_thread *t;
2932
2933 func_enter();
2934
2935 mutex_lock(&pktgen_thread_lock);
2936
2919{
2920 struct pktgen_thread *t;
2921
2922 func_enter();
2923
2924 mutex_lock(&pktgen_thread_lock);
2925
2937 list_for_each_entry(t, &pn->pktgen_threads, th_list)
2926 list_for_each_entry(t, &pktgen_threads, th_list)
2938 t->control |= T_STOP;
2939
2940 mutex_unlock(&pktgen_thread_lock);
2941}
2942
2943static int thread_is_running(const struct pktgen_thread *t)
2944{
2945 const struct pktgen_dev *pkt_dev;

--- 19 unchanged lines hidden (view full) ---

2965 if_lock(t);
2966 }
2967 if_unlock(t);
2968 return 1;
2969signal:
2970 return 0;
2971}
2972
2927 t->control |= T_STOP;
2928
2929 mutex_unlock(&pktgen_thread_lock);
2930}
2931
2932static int thread_is_running(const struct pktgen_thread *t)
2933{
2934 const struct pktgen_dev *pkt_dev;

--- 19 unchanged lines hidden (view full) ---

2954 if_lock(t);
2955 }
2956 if_unlock(t);
2957 return 1;
2958signal:
2959 return 0;
2960}
2961
2973static int pktgen_wait_all_threads_run(struct pktgen_net *pn)
2962static int pktgen_wait_all_threads_run(void)
2974{
2975 struct pktgen_thread *t;
2976 int sig = 1;
2977
2978 mutex_lock(&pktgen_thread_lock);
2979
2963{
2964 struct pktgen_thread *t;
2965 int sig = 1;
2966
2967 mutex_lock(&pktgen_thread_lock);
2968
2980 list_for_each_entry(t, &pn->pktgen_threads, th_list) {
2969 list_for_each_entry(t, &pktgen_threads, th_list) {
2981 sig = pktgen_wait_thread_run(t);
2982 if (sig == 0)
2983 break;
2984 }
2985
2986 if (sig == 0)
2970 sig = pktgen_wait_thread_run(t);
2971 if (sig == 0)
2972 break;
2973 }
2974
2975 if (sig == 0)
2987 list_for_each_entry(t, &pn->pktgen_threads, th_list)
2976 list_for_each_entry(t, &pktgen_threads, th_list)
2988 t->control |= (T_STOP);
2989
2990 mutex_unlock(&pktgen_thread_lock);
2991 return sig;
2992}
2993
2977 t->control |= (T_STOP);
2978
2979 mutex_unlock(&pktgen_thread_lock);
2980 return sig;
2981}
2982
2994static void pktgen_run_all_threads(struct pktgen_net *pn)
2983static void pktgen_run_all_threads(void)
2995{
2996 struct pktgen_thread *t;
2997
2998 func_enter();
2999
3000 mutex_lock(&pktgen_thread_lock);
3001
2984{
2985 struct pktgen_thread *t;
2986
2987 func_enter();
2988
2989 mutex_lock(&pktgen_thread_lock);
2990
3002 list_for_each_entry(t, &pn->pktgen_threads, th_list)
2991 list_for_each_entry(t, &pktgen_threads, th_list)
3003 t->control |= (T_RUN);
3004
3005 mutex_unlock(&pktgen_thread_lock);
3006
3007 /* Propagate thread->control */
3008 schedule_timeout_interruptible(msecs_to_jiffies(125));
3009
2992 t->control |= (T_RUN);
2993
2994 mutex_unlock(&pktgen_thread_lock);
2995
2996 /* Propagate thread->control */
2997 schedule_timeout_interruptible(msecs_to_jiffies(125));
2998
3010 pktgen_wait_all_threads_run(pn);
2999 pktgen_wait_all_threads_run();
3011}
3012
3000}
3001
3013static void pktgen_reset_all_threads(struct pktgen_net *pn)
3002static void pktgen_reset_all_threads(void)
3014{
3015 struct pktgen_thread *t;
3016
3017 func_enter();
3018
3019 mutex_lock(&pktgen_thread_lock);
3020
3003{
3004 struct pktgen_thread *t;
3005
3006 func_enter();
3007
3008 mutex_lock(&pktgen_thread_lock);
3009
3021 list_for_each_entry(t, &pn->pktgen_threads, th_list)
3010 list_for_each_entry(t, &pktgen_threads, th_list)
3022 t->control |= (T_REMDEVALL);
3023
3024 mutex_unlock(&pktgen_thread_lock);
3025
3026 /* Propagate thread->control */
3027 schedule_timeout_interruptible(msecs_to_jiffies(125));
3028
3011 t->control |= (T_REMDEVALL);
3012
3013 mutex_unlock(&pktgen_thread_lock);
3014
3015 /* Propagate thread->control */
3016 schedule_timeout_interruptible(msecs_to_jiffies(125));
3017
3029 pktgen_wait_all_threads_run(pn);
3018 pktgen_wait_all_threads_run();
3030}
3031
3032static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
3033{
3034 __u64 bps, mbps, pps;
3035 char *p = pkt_dev->result;
3036 ktime_t elapsed = ktime_sub(pkt_dev->stopped_at,
3037 pkt_dev->started_at);

--- 125 unchanged lines hidden (view full) ---

3163 }
3164
3165 if_unlock(t);
3166}
3167
3168static void pktgen_rem_thread(struct pktgen_thread *t)
3169{
3170 /* Remove from the thread list */
3019}
3020
3021static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
3022{
3023 __u64 bps, mbps, pps;
3024 char *p = pkt_dev->result;
3025 ktime_t elapsed = ktime_sub(pkt_dev->stopped_at,
3026 pkt_dev->started_at);

--- 125 unchanged lines hidden (view full) ---

3152 }
3153
3154 if_unlock(t);
3155}
3156
3157static void pktgen_rem_thread(struct pktgen_thread *t)
3158{
3159 /* Remove from the thread list */
3171 remove_proc_entry(t->tsk->comm, t->net->proc_dir);
3160
3161 remove_proc_entry(t->tsk->comm, pg_proc_dir);
3162
3172}
3173
3174static void pktgen_resched(struct pktgen_dev *pkt_dev)
3175{
3176 ktime_t idle_start = ktime_get();
3177 schedule();
3178 pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_get(), idle_start));
3179}

--- 129 unchanged lines hidden (view full) ---

3309 set_current_state(TASK_INTERRUPTIBLE);
3310
3311 set_freezable();
3312
3313 while (!kthread_should_stop()) {
3314 pkt_dev = next_to_run(t);
3315
3316 if (unlikely(!pkt_dev && t->control == 0)) {
3163}
3164
3165static void pktgen_resched(struct pktgen_dev *pkt_dev)
3166{
3167 ktime_t idle_start = ktime_get();
3168 schedule();
3169 pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_get(), idle_start));
3170}

--- 129 unchanged lines hidden (view full) ---

3300 set_current_state(TASK_INTERRUPTIBLE);
3301
3302 set_freezable();
3303
3304 while (!kthread_should_stop()) {
3305 pkt_dev = next_to_run(t);
3306
3307 if (unlikely(!pkt_dev && t->control == 0)) {
3317 if (t->net->pktgen_exiting)
3308 if (pktgen_exiting)
3318 break;
3319 wait_event_interruptible_timeout(t->queue,
3320 t->control != 0,
3321 HZ/10);
3322 try_to_freeze();
3323 continue;
3324 }
3325

--- 105 unchanged lines hidden (view full) ---

3431static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
3432{
3433 struct pktgen_dev *pkt_dev;
3434 int err;
3435 int node = cpu_to_node(t->cpu);
3436
3437 /* We don't allow a device to be on several threads */
3438
3309 break;
3310 wait_event_interruptible_timeout(t->queue,
3311 t->control != 0,
3312 HZ/10);
3313 try_to_freeze();
3314 continue;
3315 }
3316

--- 105 unchanged lines hidden (view full) ---

3422static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
3423{
3424 struct pktgen_dev *pkt_dev;
3425 int err;
3426 int node = cpu_to_node(t->cpu);
3427
3428 /* We don't allow a device to be on several threads */
3429
3439 pkt_dev = __pktgen_NN_threads(t->net, ifname, FIND);
3430 pkt_dev = __pktgen_NN_threads(ifname, FIND);
3440 if (pkt_dev) {
3441 pr_err("ERROR: interface already used\n");
3442 return -EBUSY;
3443 }
3444
3445 pkt_dev = kzalloc_node(sizeof(struct pktgen_dev), GFP_KERNEL, node);
3446 if (!pkt_dev)
3447 return -ENOMEM;

--- 18 unchanged lines hidden (view full) ---

3466 pkt_dev->vlan_p = 0;
3467 pkt_dev->vlan_cfi = 0;
3468 pkt_dev->vlan_id = 0xffff;
3469 pkt_dev->svlan_p = 0;
3470 pkt_dev->svlan_cfi = 0;
3471 pkt_dev->svlan_id = 0xffff;
3472 pkt_dev->node = -1;
3473
3431 if (pkt_dev) {
3432 pr_err("ERROR: interface already used\n");
3433 return -EBUSY;
3434 }
3435
3436 pkt_dev = kzalloc_node(sizeof(struct pktgen_dev), GFP_KERNEL, node);
3437 if (!pkt_dev)
3438 return -ENOMEM;

--- 18 unchanged lines hidden (view full) ---

3457 pkt_dev->vlan_p = 0;
3458 pkt_dev->vlan_cfi = 0;
3459 pkt_dev->vlan_id = 0xffff;
3460 pkt_dev->svlan_p = 0;
3461 pkt_dev->svlan_cfi = 0;
3462 pkt_dev->svlan_id = 0xffff;
3463 pkt_dev->node = -1;
3464
3474 err = pktgen_setup_dev(t->net, pkt_dev, ifname);
3465 err = pktgen_setup_dev(pkt_dev, ifname);
3475 if (err)
3476 goto out1;
3477 if (pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)
3478 pkt_dev->clone_skb = pg_clone_skb_d;
3479
3466 if (err)
3467 goto out1;
3468 if (pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)
3469 pkt_dev->clone_skb = pg_clone_skb_d;
3470
3480 pkt_dev->entry = proc_create_data(ifname, 0600, t->net->proc_dir,
3471 pkt_dev->entry = proc_create_data(ifname, 0600, pg_proc_dir,
3481 &pktgen_if_fops, pkt_dev);
3482 if (!pkt_dev->entry) {
3483 pr_err("cannot create %s/%s procfs entry\n",
3484 PG_PROC_DIR, ifname);
3485 err = -EINVAL;
3486 goto out2;
3487 }
3488#ifdef CONFIG_XFRM

--- 8 unchanged lines hidden (view full) ---

3497#ifdef CONFIG_XFRM
3498 free_SAs(pkt_dev);
3499#endif
3500 vfree(pkt_dev->flows);
3501 kfree(pkt_dev);
3502 return err;
3503}
3504
3472 &pktgen_if_fops, pkt_dev);
3473 if (!pkt_dev->entry) {
3474 pr_err("cannot create %s/%s procfs entry\n",
3475 PG_PROC_DIR, ifname);
3476 err = -EINVAL;
3477 goto out2;
3478 }
3479#ifdef CONFIG_XFRM

--- 8 unchanged lines hidden (view full) ---

3488#ifdef CONFIG_XFRM
3489 free_SAs(pkt_dev);
3490#endif
3491 vfree(pkt_dev->flows);
3492 kfree(pkt_dev);
3493 return err;
3494}
3495
3505static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn)
3496static int __init pktgen_create_thread(int cpu)
3506{
3507 struct pktgen_thread *t;
3508 struct proc_dir_entry *pe;
3509 struct task_struct *p;
3510
3511 t = kzalloc_node(sizeof(struct pktgen_thread), GFP_KERNEL,
3512 cpu_to_node(cpu));
3513 if (!t) {
3514 pr_err("ERROR: out of memory, can't create new thread\n");
3515 return -ENOMEM;
3516 }
3517
3518 spin_lock_init(&t->if_lock);
3519 t->cpu = cpu;
3520
3521 INIT_LIST_HEAD(&t->if_list);
3522
3497{
3498 struct pktgen_thread *t;
3499 struct proc_dir_entry *pe;
3500 struct task_struct *p;
3501
3502 t = kzalloc_node(sizeof(struct pktgen_thread), GFP_KERNEL,
3503 cpu_to_node(cpu));
3504 if (!t) {
3505 pr_err("ERROR: out of memory, can't create new thread\n");
3506 return -ENOMEM;
3507 }
3508
3509 spin_lock_init(&t->if_lock);
3510 t->cpu = cpu;
3511
3512 INIT_LIST_HEAD(&t->if_list);
3513
3523 list_add_tail(&t->th_list, &pn->pktgen_threads);
3514 list_add_tail(&t->th_list, &pktgen_threads);
3524 init_completion(&t->start_done);
3525
3526 p = kthread_create_on_node(pktgen_thread_worker,
3527 t,
3528 cpu_to_node(cpu),
3529 "kpktgend_%d", cpu);
3530 if (IS_ERR(p)) {
3531 pr_err("kernel_thread() failed for cpu %d\n", t->cpu);
3532 list_del(&t->th_list);
3533 kfree(t);
3534 return PTR_ERR(p);
3535 }
3536 kthread_bind(p, cpu);
3537 t->tsk = p;
3538
3515 init_completion(&t->start_done);
3516
3517 p = kthread_create_on_node(pktgen_thread_worker,
3518 t,
3519 cpu_to_node(cpu),
3520 "kpktgend_%d", cpu);
3521 if (IS_ERR(p)) {
3522 pr_err("kernel_thread() failed for cpu %d\n", t->cpu);
3523 list_del(&t->th_list);
3524 kfree(t);
3525 return PTR_ERR(p);
3526 }
3527 kthread_bind(p, cpu);
3528 t->tsk = p;
3529
3539 pe = proc_create_data(t->tsk->comm, 0600, pn->proc_dir,
3530 pe = proc_create_data(t->tsk->comm, 0600, pg_proc_dir,
3540 &pktgen_thread_fops, t);
3541 if (!pe) {
3542 pr_err("cannot create %s/%s procfs entry\n",
3543 PG_PROC_DIR, t->tsk->comm);
3544 kthread_stop(p);
3545 list_del(&t->th_list);
3546 kfree(t);
3547 return -EINVAL;
3548 }
3549
3531 &pktgen_thread_fops, t);
3532 if (!pe) {
3533 pr_err("cannot create %s/%s procfs entry\n",
3534 PG_PROC_DIR, t->tsk->comm);
3535 kthread_stop(p);
3536 list_del(&t->th_list);
3537 kfree(t);
3538 return -EINVAL;
3539 }
3540
3550 t->net = pn;
3551 wake_up_process(p);
3552 wait_for_completion(&t->start_done);
3553
3554 return 0;
3555}
3556
3557/*
3558 * Removes a device from the thread if_list.

--- 9 unchanged lines hidden (view full) ---

3568 if (p == pkt_dev)
3569 list_del(&p->list);
3570 }
3571}
3572
3573static int pktgen_remove_device(struct pktgen_thread *t,
3574 struct pktgen_dev *pkt_dev)
3575{
3541 wake_up_process(p);
3542 wait_for_completion(&t->start_done);
3543
3544 return 0;
3545}
3546
3547/*
3548 * Removes a device from the thread if_list.

--- 9 unchanged lines hidden (view full) ---

3558 if (p == pkt_dev)
3559 list_del(&p->list);
3560 }
3561}
3562
3563static int pktgen_remove_device(struct pktgen_thread *t,
3564 struct pktgen_dev *pkt_dev)
3565{
3576 struct pktgen_net *pn = t->net;
3577
3578 pr_debug("remove_device pkt_dev=%p\n", pkt_dev);
3579
3580 if (pkt_dev->running) {
3581 pr_warning("WARNING: trying to remove a running interface, stopping it now\n");
3582 pktgen_stop_device(pkt_dev);
3583 }
3584

--- 4 unchanged lines hidden (view full) ---

3589 pkt_dev->odev = NULL;
3590 }
3591
3592 /* And update the thread if_list */
3593
3594 _rem_dev_from_if_list(t, pkt_dev);
3595
3596 if (pkt_dev->entry)
3566
3567 pr_debug("remove_device pkt_dev=%p\n", pkt_dev);
3568
3569 if (pkt_dev->running) {
3570 pr_warning("WARNING: trying to remove a running interface, stopping it now\n");
3571 pktgen_stop_device(pkt_dev);
3572 }
3573

--- 4 unchanged lines hidden (view full) ---

3578 pkt_dev->odev = NULL;
3579 }
3580
3581 /* And update the thread if_list */
3582
3583 _rem_dev_from_if_list(t, pkt_dev);
3584
3585 if (pkt_dev->entry)
3597 remove_proc_entry(pkt_dev->entry->name, pn->proc_dir);
3586 remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
3598
3599#ifdef CONFIG_XFRM
3600 free_SAs(pkt_dev);
3601#endif
3602 vfree(pkt_dev->flows);
3603 if (pkt_dev->page)
3604 put_page(pkt_dev->page);
3605 kfree(pkt_dev);
3606 return 0;
3607}
3608
3587
3588#ifdef CONFIG_XFRM
3589 free_SAs(pkt_dev);
3590#endif
3591 vfree(pkt_dev->flows);
3592 if (pkt_dev->page)
3593 put_page(pkt_dev->page);
3594 kfree(pkt_dev);
3595 return 0;
3596}
3597
3609static int __net_init pg_net_init(struct net *net)
3598static int __init pg_init(void)
3610{
3599{
3611 struct pktgen_net *pn = net_generic(net, pg_net_id);
3600 int cpu;
3612 struct proc_dir_entry *pe;
3601 struct proc_dir_entry *pe;
3613 int cpu, ret = 0;
3602 int ret = 0;
3614
3603
3615 pn->net = net;
3616 INIT_LIST_HEAD(&pn->pktgen_threads);
3617 pn->pktgen_exiting = false;
3618 pn->proc_dir = proc_mkdir(PG_PROC_DIR, pn->net->proc_net);
3619 if (!pn->proc_dir) {
3620 pr_warn("cannot create /proc/net/%s\n", PG_PROC_DIR);
3604 pr_info("%s", version);
3605
3606 pg_proc_dir = proc_mkdir(PG_PROC_DIR, init_net.proc_net);
3607 if (!pg_proc_dir)
3621 return -ENODEV;
3608 return -ENODEV;
3622 }
3623 pe = proc_create(PGCTRL, 0600, pn->proc_dir, &pktgen_fops);
3609
3610 pe = proc_create(PGCTRL, 0600, pg_proc_dir, &pktgen_fops);
3624 if (pe == NULL) {
3611 if (pe == NULL) {
3625 pr_err("cannot create %s procfs entry\n", PGCTRL);
3612 pr_err("ERROR: cannot create %s procfs entry\n", PGCTRL);
3626 ret = -EINVAL;
3613 ret = -EINVAL;
3627 goto remove;
3614 goto remove_dir;
3628 }
3629
3615 }
3616
3617 register_netdevice_notifier(&pktgen_notifier_block);
3618
3630 for_each_online_cpu(cpu) {
3631 int err;
3632
3619 for_each_online_cpu(cpu) {
3620 int err;
3621
3633 err = pktgen_create_thread(cpu, pn);
3622 err = pktgen_create_thread(cpu);
3634 if (err)
3623 if (err)
3635 pr_warn("Cannot create thread for cpu %d (%d)\n",
3624 pr_warning("WARNING: Cannot create thread for cpu %d (%d)\n",
3636 cpu, err);
3637 }
3638
3625 cpu, err);
3626 }
3627
3639 if (list_empty(&pn->pktgen_threads)) {
3640 pr_err("Initialization failed for all threads\n");
3628 if (list_empty(&pktgen_threads)) {
3629 pr_err("ERROR: Initialization failed for all threads\n");
3641 ret = -ENODEV;
3630 ret = -ENODEV;
3642 goto remove_entry;
3631 goto unregister;
3643 }
3644
3645 return 0;
3646
3632 }
3633
3634 return 0;
3635
3647remove_entry:
3648 remove_proc_entry(PGCTRL, pn->proc_dir);
3649remove:
3650 proc_net_remove(pn->net, PG_PROC_DIR);
3636 unregister:
3637 unregister_netdevice_notifier(&pktgen_notifier_block);
3638 remove_proc_entry(PGCTRL, pg_proc_dir);
3639 remove_dir:
3640 proc_net_remove(&init_net, PG_PROC_DIR);
3651 return ret;
3652}
3653
3641 return ret;
3642}
3643
3654static void __net_exit pg_net_exit(struct net *net)
3644static void __exit pg_cleanup(void)
3655{
3645{
3656 struct pktgen_net *pn = net_generic(net, pg_net_id);
3657 struct pktgen_thread *t;
3658 struct list_head *q, *n;
3659 LIST_HEAD(list);
3660
3661 /* Stop all interfaces & threads */
3646 struct pktgen_thread *t;
3647 struct list_head *q, *n;
3648 LIST_HEAD(list);
3649
3650 /* Stop all interfaces & threads */
3662 pn->pktgen_exiting = true;
3651 pktgen_exiting = true;
3663
3664 mutex_lock(&pktgen_thread_lock);
3652
3653 mutex_lock(&pktgen_thread_lock);
3665 list_splice_init(&pn->pktgen_threads, &list);
3654 list_splice_init(&pktgen_threads, &list);
3666 mutex_unlock(&pktgen_thread_lock);
3667
3668 list_for_each_safe(q, n, &list) {
3669 t = list_entry(q, struct pktgen_thread, th_list);
3670 list_del(&t->th_list);
3671 kthread_stop(t->tsk);
3672 kfree(t);
3673 }
3674
3655 mutex_unlock(&pktgen_thread_lock);
3656
3657 list_for_each_safe(q, n, &list) {
3658 t = list_entry(q, struct pktgen_thread, th_list);
3659 list_del(&t->th_list);
3660 kthread_stop(t->tsk);
3661 kfree(t);
3662 }
3663
3675 remove_proc_entry(PGCTRL, pn->proc_dir);
3676 proc_net_remove(pn->net, PG_PROC_DIR);
3677}
3664 /* Un-register us from receiving netdevice events */
3665 unregister_netdevice_notifier(&pktgen_notifier_block);
3678
3666
3679static struct pernet_operations pg_net_ops = {
3680 .init = pg_net_init,
3681 .exit = pg_net_exit,
3682 .id = &pg_net_id,
3683 .size = sizeof(struct pktgen_net),
3684};
3685
3686static int __init pg_init(void)
3687{
3688 int ret = 0;
3689
3690 pr_info("%s", version);
3691 ret = register_pernet_subsys(&pg_net_ops);
3692 if (ret)
3693 return ret;
3694 ret = register_netdevice_notifier(&pktgen_notifier_block);
3695 if (ret)
3696 unregister_pernet_subsys(&pg_net_ops);
3697
3698 return ret;
3667 /* Clean up proc file system */
3668 remove_proc_entry(PGCTRL, pg_proc_dir);
3669 proc_net_remove(&init_net, PG_PROC_DIR);
3699}
3700
3670}
3671
3701static void __exit pg_cleanup(void)
3702{
3703 unregister_netdevice_notifier(&pktgen_notifier_block);
3704 unregister_pernet_subsys(&pg_net_ops);
3705}
3706
3707module_init(pg_init);
3708module_exit(pg_cleanup);
3709
3710MODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se>");
3711MODULE_DESCRIPTION("Packet Generator tool");
3712MODULE_LICENSE("GPL");
3713MODULE_VERSION(VERSION);
3714module_param(pg_count_d, int, 0);
3715MODULE_PARM_DESC(pg_count_d, "Default number of packets to inject");
3716module_param(pg_delay_d, int, 0);
3717MODULE_PARM_DESC(pg_delay_d, "Default delay between packets (nanoseconds)");
3718module_param(pg_clone_skb_d, int, 0);
3719MODULE_PARM_DESC(pg_clone_skb_d, "Default number of copies of the same packet");
3720module_param(debug, int, 0);
3721MODULE_PARM_DESC(debug, "Enable debugging of pktgen module");
3672module_init(pg_init);
3673module_exit(pg_cleanup);
3674
3675MODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se>");
3676MODULE_DESCRIPTION("Packet Generator tool");
3677MODULE_LICENSE("GPL");
3678MODULE_VERSION(VERSION);
3679module_param(pg_count_d, int, 0);
3680MODULE_PARM_DESC(pg_count_d, "Default number of packets to inject");
3681module_param(pg_delay_d, int, 0);
3682MODULE_PARM_DESC(pg_delay_d, "Default delay between packets (nanoseconds)");
3683module_param(pg_clone_skb_d, int, 0);
3684MODULE_PARM_DESC(pg_clone_skb_d, "Default number of copies of the same packet");
3685module_param(debug, int, 0);
3686MODULE_PARM_DESC(debug, "Enable debugging of pktgen module");