pktgen.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:41k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -*-linux-c-*-
  2.  * $Id: pktgen.c,v 1.8 2002/07/15 19:30:17 robert Exp $
  3.  * pktgen.c: Packet Generator for performance evaluation.
  4.  *
  5.  * Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se>
  6.  *                                 Uppsala University, Sweden
  7.  *
  8.  * A tool for loading the network with preconfigurated packets.
  9.  * The tool is implemented as a linux module.  Parameters are output 
  10.  * device, IPG (interpacket gap), number of packets, and whether
  11.  * to use multiple SKBs or just the same one.
  12.  * pktgen uses the installed interface's output routine.
  13.  *
  14.  * Additional hacking by:
  15.  *
  16.  * Jens.Laas@data.slu.se
  17.  * Improved by ANK. 010120.
  18.  * Improved by ANK even more. 010212.
  19.  * MAC address typo fixed. 010417 --ro
  20.  * Integrated.  020301 --DaveM
  21.  * Added multiskb option 020301 --DaveM
  22.  * Scaling of results. 020417--sigurdur@linpro.no
  23.  * Significant re-work of the module:
  24.  *   *  Updated to support generation over multiple interfaces at once
  25.  *       by creating 32 /proc/net/pg* files.  Each file can be manipulated
  26.  *       individually.
  27.  *   *  Converted many counters to __u64 to allow longer runs.
  28.  *   *  Allow configuration of ranges, like min/max IP address, MACs,
  29.  *       and UDP-ports, for both source and destination, and can
  30.  *       set to use a random distribution or sequentially walk the range.
  31.  *   *  Can now change some values after starting.
  32.  *   *  Place 12-byte packet in UDP payload with magic number,
  33.  *       sequence number, and timestamp.  Will write receiver next.
  34.  *   *  The new changes seem to have a performance impact of around 1%,
  35.  *       as far as I can tell.
  36.  *   --Ben Greear <greearb@candelatech.com>
  37.  *
  38.  * Renamed multiskb to clone_skb and cleaned up sending core for two distinct 
  39.  * skb modes. A clone_skb=0 mode for Ben "ranges" work and a clone_skb != 0 
  40.  * as a "fastpath" with a configurable number of clones after alloc's.
  41.  *
  42.  * clone_skb=0 means all packets are allocated this also means ranges time 
  43.  * stamps etc can be used. clone_skb=100 means 1 malloc is followed by 100 
  44.  * clones.
  45.  *
  46.  * Also moved to /proc/net/pktgen/ 
  47.  * --ro 
  48.  *
  49.  * See Documentation/networking/pktgen.txt for how to use this.
  50.  */
  51. #include <linux/module.h>
  52. #include <linux/kernel.h>
  53. #include <linux/sched.h>
  54. #include <linux/types.h>
  55. #include <linux/string.h>
  56. #include <linux/ptrace.h>
  57. #include <linux/errno.h>
  58. #include <linux/ioport.h>
  59. #include <linux/slab.h>
  60. #include <linux/interrupt.h>
  61. #include <linux/pci.h>
  62. #include <linux/delay.h>
  63. #include <linux/init.h>
  64. #include <linux/inet.h>
  65. #include <asm/byteorder.h>
  66. #include <asm/bitops.h>
  67. #include <asm/io.h>
  68. #include <asm/dma.h>
  69. #include <asm/uaccess.h>
  70. #include <linux/in.h>
  71. #include <linux/ip.h>
  72. #include <linux/udp.h>
  73. #include <linux/skbuff.h>
  74. #include <linux/netdevice.h>
  75. #include <linux/inetdevice.h>
  76. #include <linux/rtnetlink.h>
  77. #include <linux/proc_fs.h>
  78. #include <linux/if_arp.h>
  79. #include <net/checksum.h>
  80. #include <asm/timex.h>
  81. #define cycles() ((u32)get_cycles())
  82. #define VERSION "pktgen version 1.2"
  83. static char version[] __initdata = 
  84.   "pktgen.c: v1.2: Packet Generator for packet performance testing.n";
  85. /* Used to help with determining the pkts on receive */
  86. #define PKTGEN_MAGIC 0xbe9be955
  87. /* Keep information per interface */
  88. struct pktgen_info {
  89.         /* Parameters */
  90.         /* If min != max, then we will either do a linear iteration, or
  91.          * we will do a random selection from within the range.
  92.          */
  93.         __u32 flags;     
  94. #define F_IPSRC_RND   (1<<0)  /* IP-Src Random  */
  95. #define F_IPDST_RND   (1<<1)  /* IP-Dst Random  */
  96. #define F_UDPSRC_RND  (1<<2)  /* UDP-Src Random */
  97. #define F_UDPDST_RND  (1<<3)  /* UDP-Dst Random */
  98. #define F_MACSRC_RND  (1<<4)  /* MAC-Src Random */
  99. #define F_MACDST_RND  (1<<5)  /* MAC-Dst Random */
  100. #define F_SET_SRCMAC  (1<<6)  /* Specify-Src-Mac 
  101.  (default is to use Interface's MAC Addr) */
  102. #define F_SET_SRCIP   (1<<7)  /*  Specify-Src-IP
  103.   (default is to use Interface's IP Addr) */ 
  104.         
  105.         int pkt_size;    /* = ETH_ZLEN; */
  106.         int nfrags;
  107.         __u32 ipg;       /* Default Interpacket gap in nsec */
  108.         __u64 count;     /* Default No packets to send */
  109.         __u64 sofar;     /* How many pkts we've sent so far */
  110.         __u64 errors;    /* Errors when trying to transmit, pkts will be re-sent */
  111.         struct timeval started_at;
  112.         struct timeval stopped_at;
  113.         __u64 idle_acc;
  114.         __u32 seq_num;
  115.         
  116.         int clone_skb;   /* Use multiple SKBs during packet gen.  If this number
  117.                           * is greater than 1, then that many coppies of the same
  118.                           * packet will be sent before a new packet is allocated.
  119.                           * For instance, if you want to send 1024 identical packets
  120.                           * before creating a new packet, set clone_skb to 1024.
  121.                           */
  122.         int busy;
  123.         int do_run_run;   /* if this changes to false, the test will stop */
  124.         
  125.         char outdev[32];
  126.         char dst_min[32];
  127.         char dst_max[32];
  128.         char src_min[32];
  129.         char src_max[32];
  130.         /* If we're doing ranges, random or incremental, then this
  131.          * defines the min/max for those ranges.
  132.          */
  133.         __u32 saddr_min; /* inclusive, source IP address */
  134.         __u32 saddr_max; /* exclusive, source IP address */
  135.         __u32 daddr_min; /* inclusive, dest IP address */
  136.         __u32 daddr_max; /* exclusive, dest IP address */
  137.         __u16 udp_src_min; /* inclusive, source UDP port */
  138.         __u16 udp_src_max; /* exclusive, source UDP port */
  139.         __u16 udp_dst_min; /* inclusive, dest UDP port */
  140.         __u16 udp_dst_max; /* exclusive, dest UDP port */
  141.         __u32 src_mac_count; /* How many MACs to iterate through */
  142.         __u32 dst_mac_count; /* How many MACs to iterate through */
  143.         
  144.         unsigned char dst_mac[6];
  145.         unsigned char src_mac[6];
  146.         
  147.         __u32 cur_dst_mac_offset;
  148.         __u32 cur_src_mac_offset;
  149.         __u32 cur_saddr;
  150.         __u32 cur_daddr;
  151.         __u16 cur_udp_dst;
  152.         __u16 cur_udp_src;
  153.         
  154.         __u8 hh[14];
  155.         /* = { 
  156.            0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB, 
  157.            
  158.            We fill in SRC address later
  159.            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  160.            0x08, 0x00
  161.            };
  162.         */
  163.         __u16 pad; /* pad out the hh struct to an even 16 bytes */
  164.         char result[512];
  165.         /* proc file names */
  166.         char fname[80];
  167.         char busy_fname[80];
  168.         
  169.         struct proc_dir_entry *proc_ent;
  170.         struct proc_dir_entry *busy_proc_ent;
  171. };
  172. struct pktgen_hdr {
  173.         __u32 pgh_magic;
  174.         __u32 seq_num;
  175.         struct timeval timestamp;
  176. };
  177. static int cpu_speed;
  178. static int debug;
  179. /* Module parameters, defaults. */
  180. static int count_d = 100000;
  181. static int ipg_d = 0;
  182. static int clone_skb_d = 0;
  183. #define MAX_PKTGEN 8
  184. static struct pktgen_info pginfos[MAX_PKTGEN];
  185. /** Convert to miliseconds */
  186. inline __u64 tv_to_ms(const struct timeval* tv) {
  187.         __u64 ms = tv->tv_usec / 1000;
  188.         ms += (__u64)tv->tv_sec * (__u64)1000;
  189.         return ms;
  190. }
  191. inline __u64 getCurMs(void) {
  192.         struct timeval tv;
  193.         do_gettimeofday(&tv);
  194.         return tv_to_ms(&tv);
  195. }
  196. #define PG_PROC_DIR "pktgen"
  197. static struct proc_dir_entry *proc_dir = 0;
  198. static struct net_device *setup_inject(struct pktgen_info* info)
  199. {
  200. struct net_device *odev;
  201. rtnl_lock();
  202. odev = __dev_get_by_name(info->outdev);
  203. if (!odev) {
  204. sprintf(info->result, "No such netdevice: "%s"", info->outdev);
  205. goto out_unlock;
  206. }
  207. if (odev->type != ARPHRD_ETHER) {
  208. sprintf(info->result, "Not ethernet device: "%s"", info->outdev);
  209. goto out_unlock;
  210. }
  211. if (!netif_running(odev)) {
  212. sprintf(info->result, "Device is down: "%s"", info->outdev);
  213. goto out_unlock;
  214. }
  215.         /* Default to the interface's mac if not explicitly set. */
  216.         if (!(info->flags & F_SET_SRCMAC)) {
  217.                 memcpy(&(info->hh[6]), odev->dev_addr, 6);
  218.         }
  219.         else {
  220.                 memcpy(&(info->hh[6]), info->src_mac, 6);
  221.         }
  222.         /* Set up Dest MAC */
  223.         memcpy(&(info->hh[0]), info->dst_mac, 6);
  224.         
  225. info->saddr_min = 0;
  226. info->saddr_max = 0;
  227.         if (strlen(info->src_min) == 0) {
  228.                 if (odev->ip_ptr) {
  229.                         struct in_device *in_dev = odev->ip_ptr;
  230.                         if (in_dev->ifa_list) {
  231.                                 info->saddr_min = in_dev->ifa_list->ifa_address;
  232.                                 info->saddr_max = info->saddr_min;
  233.                         }
  234.                 }
  235. }
  236.         else {
  237.                 info->saddr_min = in_aton(info->src_min);
  238.                 info->saddr_max = in_aton(info->src_max);
  239.         }
  240.         info->daddr_min = in_aton(info->dst_min);
  241.         info->daddr_max = in_aton(info->dst_max);
  242.         /* Initialize current values. */
  243.         info->cur_dst_mac_offset = 0;
  244.         info->cur_src_mac_offset = 0;
  245.         info->cur_saddr = info->saddr_min;
  246.         info->cur_daddr = info->daddr_min;
  247.         info->cur_udp_dst = info->udp_dst_min;
  248.         info->cur_udp_src = info->udp_src_min;
  249.         
  250. atomic_inc(&odev->refcnt);
  251. rtnl_unlock();
  252. return odev;
  253. out_unlock:
  254. rtnl_unlock();
  255. return NULL;
  256. }
  257. static void nanospin(int ipg, struct pktgen_info* info)
  258. {
  259. u32 idle_start, idle;
  260. idle_start = cycles();
  261. for (;;) {
  262. barrier();
  263. idle = cycles() - idle_start;
  264. if (idle * 1000 >= ipg * cpu_speed)
  265. break;
  266. }
  267. info->idle_acc += idle;
  268. }
  269. static int calc_mhz(void)
  270. {
  271. struct timeval start, stop;
  272. u32 start_s, elapsed;
  273. do_gettimeofday(&start);
  274. start_s = cycles();
  275. do {
  276. barrier();
  277. elapsed = cycles() - start_s;
  278. if (elapsed == 0)
  279. return 0;
  280. } while (elapsed < 1000 * 50000);
  281. do_gettimeofday(&stop);
  282. return elapsed/(stop.tv_usec-start.tv_usec+1000000*(stop.tv_sec-start.tv_sec));
  283. }
  284. static void cycles_calibrate(void)
  285. {
  286. int i;
  287. for (i = 0; i < 3; i++) {
  288. int res = calc_mhz();
  289. if (res > cpu_speed)
  290. cpu_speed = res;
  291. }
  292. }
  293. /* Increment/randomize headers according to flags and current values
  294.  * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
  295.  */
  296. static void mod_cur_headers(struct pktgen_info* info) {        
  297.         __u32 imn;
  298.         __u32 imx;
  299.         
  300. /*  Deal with source MAC */
  301.         if (info->src_mac_count > 1) {
  302.                 __u32 mc;
  303.                 __u32 tmp;
  304.                 if (info->flags & F_MACSRC_RND) {
  305.                         mc = net_random() % (info->src_mac_count);
  306.                 }
  307.                 else {
  308.                         mc = info->cur_src_mac_offset++;
  309.                         if (info->cur_src_mac_offset > info->src_mac_count) {
  310.                                 info->cur_src_mac_offset = 0;
  311.                         }
  312.                 }
  313.                 tmp = info->src_mac[5] + (mc & 0xFF);
  314.                 info->hh[11] = tmp;
  315.                 tmp = (info->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
  316.                 info->hh[10] = tmp;
  317.                 tmp = (info->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
  318.                 info->hh[9] = tmp;
  319.                 tmp = (info->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
  320.                 info->hh[8] = tmp;
  321.                 tmp = (info->src_mac[1] + (tmp >> 8));
  322.                 info->hh[7] = tmp;        
  323.         }
  324.         /*  Deal with Destination MAC */
  325.         if (info->dst_mac_count > 1) {
  326.                 __u32 mc;
  327.                 __u32 tmp;
  328.                 if (info->flags & F_MACDST_RND) {
  329.                         mc = net_random() % (info->dst_mac_count);
  330.                 }
  331.                 else {
  332.                         mc = info->cur_dst_mac_offset++;
  333.                         if (info->cur_dst_mac_offset > info->dst_mac_count) {
  334.                                 info->cur_dst_mac_offset = 0;
  335.                         }
  336.                 }
  337.                 tmp = info->dst_mac[5] + (mc & 0xFF);
  338.                 info->hh[5] = tmp;
  339.                 tmp = (info->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
  340.                 info->hh[4] = tmp;
  341.                 tmp = (info->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
  342.                 info->hh[3] = tmp;
  343.                 tmp = (info->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
  344.                 info->hh[2] = tmp;
  345.                 tmp = (info->dst_mac[1] + (tmp >> 8));
  346.                 info->hh[1] = tmp;        
  347.         }
  348.         if (info->udp_src_min < info->udp_src_max) {
  349.                 if (info->flags & F_UDPSRC_RND) {
  350.                         info->cur_udp_src = ((net_random() % (info->udp_src_max - info->udp_src_min))
  351.                                              + info->udp_src_min);
  352.                 }
  353.                 else {
  354.                      info->cur_udp_src++;
  355.                      if (info->cur_udp_src >= info->udp_src_max) {
  356.                              info->cur_udp_src = info->udp_src_min;
  357.                      }
  358.                 }
  359.         }
  360.         if (info->udp_dst_min < info->udp_dst_max) {
  361.                 if (info->flags & F_UDPDST_RND) {
  362.                         info->cur_udp_dst = ((net_random() % (info->udp_dst_max - info->udp_dst_min))
  363.                                              + info->udp_dst_min);
  364.                 }
  365.                 else {
  366.                      info->cur_udp_dst++;
  367.                      if (info->cur_udp_dst >= info->udp_dst_max) {
  368.                              info->cur_udp_dst = info->udp_dst_min;
  369.                      }
  370.                 }
  371.         }
  372.         if ((imn = ntohl(info->saddr_min)) < (imx = ntohl(info->saddr_max))) {
  373.                 __u32 t;
  374.                 if (info->flags & F_IPSRC_RND) {
  375.                         t = ((net_random() % (imx - imn)) + imn);
  376.                 }
  377.                 else {
  378.                      t = ntohl(info->cur_saddr);
  379.                      t++;
  380.                      if (t >= imx) {
  381.                              t = imn;
  382.                      }
  383.                 }
  384.                 info->cur_saddr = htonl(t);
  385.         }
  386.         if ((imn = ntohl(info->daddr_min)) < (imx = ntohl(info->daddr_max))) {
  387.                 __u32 t;
  388.                 if (info->flags & F_IPDST_RND) {
  389.                         t = ((net_random() % (imx - imn)) + imn);
  390.                 }
  391.                 else {
  392.                      t = ntohl(info->cur_daddr);
  393.                      t++;
  394.                      if (t >= imx) {
  395.                              t = imn;
  396.                      }
  397.                 }
  398.                 info->cur_daddr = htonl(t);
  399.         }
  400. }/* mod_cur_headers */
  401. static struct sk_buff *fill_packet(struct net_device *odev, struct pktgen_info* info)
  402. {
  403. struct sk_buff *skb = NULL;
  404. __u8 *eth;
  405. struct udphdr *udph;
  406. int datalen, iplen;
  407. struct iphdr *iph;
  408.         struct pktgen_hdr *pgh = NULL;
  409.         
  410. skb = alloc_skb(info->pkt_size + 64 + 16, GFP_ATOMIC);
  411. if (!skb) {
  412. sprintf(info->result, "No memory");
  413. return NULL;
  414. }
  415. skb_reserve(skb, 16);
  416. /*  Reserve for ethernet and IP header  */
  417. eth = (__u8 *) skb_push(skb, 14);
  418. iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
  419. udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
  420.         /* Update any of the values, used when we're incrementing various
  421.          * fields.
  422.          */
  423.         mod_cur_headers(info);
  424. memcpy(eth, info->hh, 14);
  425.         
  426. datalen = info->pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
  427. if (datalen < sizeof(struct pktgen_hdr)) {
  428. datalen = sizeof(struct pktgen_hdr);
  429.         }
  430.         
  431. udph->source = htons(info->cur_udp_src);
  432. udph->dest = htons(info->cur_udp_dst);
  433. udph->len = htons(datalen + 8); /* DATA + udphdr */
  434. udph->check = 0;  /* No checksum */
  435. iph->ihl = 5;
  436. iph->version = 4;
  437. iph->ttl = 3;
  438. iph->tos = 0;
  439. iph->protocol = IPPROTO_UDP; /* UDP */
  440. iph->saddr = info->cur_saddr;
  441. iph->daddr = info->cur_daddr;
  442. iph->frag_off = 0;
  443. iplen = 20 + 8 + datalen;
  444. iph->tot_len = htons(iplen);
  445. iph->check = 0;
  446. iph->check = ip_fast_csum((void *) iph, iph->ihl);
  447. skb->protocol = __constant_htons(ETH_P_IP);
  448. skb->mac.raw = ((u8 *)iph) - 14;
  449. skb->dev = odev;
  450. skb->pkt_type = PACKET_HOST;
  451. if (info->nfrags <= 0) {
  452.                 pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
  453. } else {
  454. int frags = info->nfrags;
  455. int i;
  456.                 /* TODO: Verify this is OK...it sure is ugly. --Ben */
  457.                 pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8);
  458.                 
  459. if (frags > MAX_SKB_FRAGS)
  460. frags = MAX_SKB_FRAGS;
  461. if (datalen > frags*PAGE_SIZE) {
  462. skb_put(skb, datalen-frags*PAGE_SIZE);
  463. datalen = frags*PAGE_SIZE;
  464. }
  465. i = 0;
  466. while (datalen > 0) {
  467. struct page *page = alloc_pages(GFP_KERNEL, 0);
  468. skb_shinfo(skb)->frags[i].page = page;
  469. skb_shinfo(skb)->frags[i].page_offset = 0;
  470. skb_shinfo(skb)->frags[i].size =
  471. (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
  472. datalen -= skb_shinfo(skb)->frags[i].size;
  473. skb->len += skb_shinfo(skb)->frags[i].size;
  474. skb->data_len += skb_shinfo(skb)->frags[i].size;
  475. i++;
  476. skb_shinfo(skb)->nr_frags = i;
  477. }
  478. while (i < frags) {
  479. int rem;
  480. if (i == 0)
  481. break;
  482. rem = skb_shinfo(skb)->frags[i - 1].size / 2;
  483. if (rem == 0)
  484. break;
  485. skb_shinfo(skb)->frags[i - 1].size -= rem;
  486. skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1];
  487. get_page(skb_shinfo(skb)->frags[i].page);
  488. skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page;
  489. skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size;
  490. skb_shinfo(skb)->frags[i].size = rem;
  491. i++;
  492. skb_shinfo(skb)->nr_frags = i;
  493. }
  494. }
  495.         /* Stamp the time, and sequence number, convert them to network byte order */
  496.         if (pgh) {
  497.                 pgh->pgh_magic = htonl(PKTGEN_MAGIC);
  498.                 do_gettimeofday(&(pgh->timestamp));
  499.                 pgh->timestamp.tv_usec = htonl(pgh->timestamp.tv_usec);
  500.                 pgh->timestamp.tv_sec = htonl(pgh->timestamp.tv_sec);
  501.                 pgh->seq_num = htonl(info->seq_num);
  502.         }
  503.         
  504. return skb;
  505. }
  506. static void inject(struct pktgen_info* info)
  507. {
  508. struct net_device *odev = NULL;
  509. struct sk_buff *skb = NULL;
  510. __u64 total = 0;
  511.         __u64 idle = 0;
  512. __u64 lcount = 0;
  513.         int nr_frags = 0;
  514. int last_ok = 1;           /* Was last skb sent? 
  515.                             * Or a failed transmit of some sort?  This will keep
  516.                                     * sequence numbers in order, for example.
  517.                                     */
  518.         __u64 fp = 0;
  519.         __u32 fp_tmp = 0;
  520. odev = setup_inject(info);
  521. if (!odev)
  522. return;
  523.         info->do_run_run = 1; /* Cranke yeself! */
  524. info->idle_acc = 0;
  525. info->sofar = 0;
  526. lcount = info->count;
  527.         /* Build our initial pkt and place it as a re-try pkt. */
  528. skb = fill_packet(odev, info);
  529. if (skb == NULL) goto out_reldev;
  530. do_gettimeofday(&(info->started_at));
  531. while(info->do_run_run) {
  532.                 /* Set a time-stamp, so build a new pkt each time */
  533.                 if (last_ok) {
  534.                         if (++fp_tmp >= info->clone_skb ) {
  535.                                 kfree_skb(skb);
  536.                                 skb = fill_packet(odev, info);
  537.                                 if (skb == NULL) {
  538.                                         break;
  539.                                 }
  540.                                 fp++;
  541.                                 fp_tmp = 0; /* reset counter */
  542.                         }
  543.                         atomic_inc(&skb->users);
  544.                 }
  545.                 nr_frags = skb_shinfo(skb)->nr_frags;
  546.                    
  547. spin_lock_bh(&odev->xmit_lock);
  548. if (!netif_queue_stopped(odev)) {
  549. if (odev->hard_start_xmit(skb, odev)) {
  550. if (net_ratelimit()) {
  551.                                    printk(KERN_INFO "Hard xmit errorn");
  552.                                 }
  553.                                 info->errors++;
  554. last_ok = 0;
  555. }
  556.                         else {
  557.            last_ok = 1;
  558.                            info->sofar++;
  559.                            info->seq_num++;
  560.                         }
  561. }
  562. else {
  563.                         /* Re-try it next time */
  564. last_ok = 0;
  565.                 }
  566.                 
  567. spin_unlock_bh(&odev->xmit_lock);
  568. if (info->ipg) {
  569.                         /* Try not to busy-spin if we have larger sleep times.
  570.                          * TODO:  Investigate better ways to do this.
  571.                          */
  572.                         if (info->ipg < 10000) { /* 10 usecs or less */
  573.                                 nanospin(info->ipg, info);
  574.                         }
  575.                         else if (info->ipg < 10000000) { /* 10ms or less */
  576.                                 udelay(info->ipg / 1000);
  577.                         }
  578.                         else {
  579.                                 mdelay(info->ipg / 1000000);
  580.                         }
  581.                 }
  582.                 
  583. if (signal_pending(current)) {
  584.                         break;
  585.                 }
  586.                 /* If lcount is zero, then run forever */
  587. if ((lcount != 0) && (--lcount == 0)) {
  588. if (atomic_read(&skb->users) != 1) {
  589. u32 idle_start, idle;
  590. idle_start = cycles();
  591. while (atomic_read(&skb->users) != 1) {
  592. if (signal_pending(current)) {
  593.                                                 break;
  594.                                         }
  595. schedule();
  596. }
  597. idle = cycles() - idle_start;
  598. info->idle_acc += idle;
  599. }
  600. break;
  601. }
  602. if (netif_queue_stopped(odev) || current->need_resched) {
  603. u32 idle_start, idle;
  604. idle_start = cycles();
  605. do {
  606. if (signal_pending(current)) {
  607.                                         info->do_run_run = 0;
  608.                                         break;
  609.                                 }
  610. if (!netif_running(odev)) {
  611.                                         info->do_run_run = 0;
  612. break;
  613.                                 }
  614. if (current->need_resched)
  615. schedule();
  616. else
  617. do_softirq();
  618. } while (netif_queue_stopped(odev));
  619. idle = cycles() - idle_start;
  620. info->idle_acc += idle;
  621. }
  622. }/* while we should be running */
  623. do_gettimeofday(&(info->stopped_at));
  624. total = (info->stopped_at.tv_sec - info->started_at.tv_sec) * 1000000 +
  625. info->stopped_at.tv_usec - info->started_at.tv_usec;
  626. idle = (__u32)(info->idle_acc)/(__u32)(cpu_speed);
  627.         {
  628. char *p = info->result;
  629.                 __u64 pps = (__u32)(info->sofar * 1000) / ((__u32)(total) / 1000);
  630.                 __u64 bps = pps * 8 * (info->pkt_size + 4); /* take 32bit ethernet CRC into account */
  631. p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags) %llupps %lluMb/sec (%llubps)  errors: %llu",
  632.      (unsigned long long) total,
  633.      (unsigned long long) (total - idle),
  634.      (unsigned long long) idle,
  635.      (unsigned long long) info->sofar,
  636.                              skb->len + 4, /* Add 4 to account for the ethernet checksum */
  637.                              nr_frags,
  638.      (unsigned long long) pps,
  639.      (unsigned long long) (bps / (u64) 1024 / (u64) 1024),
  640.      (unsigned long long) bps,
  641.      (unsigned long long) info->errors
  642.      );
  643. }
  644.         
  645. out_reldev:
  646.         if (odev) {
  647.                 dev_put(odev);
  648.                 odev = NULL;
  649.         }
  650.         /* TODO:  Is this worth printing out (other than for debug?) */
  651.         printk("fp = %llun", (unsigned long long) fp);
  652. return;
  653. }
  654. /* proc/net/pktgen/pg */
  655. static int proc_busy_read(char *buf , char **start, off_t offset,
  656.      int len, int *eof, void *data)
  657. {
  658. char *p;
  659.         int idx = (int)(long)(data);
  660.         struct pktgen_info* info = NULL;
  661.         
  662.         if ((idx < 0) || (idx >= MAX_PKTGEN)) {
  663.                 printk("ERROR: idx: %i is out of range in proc_writen", idx);
  664.                 return -EINVAL;
  665.         }
  666.         info = &(pginfos[idx]);
  667.   
  668. p = buf;
  669. p += sprintf(p, "%dn", info->busy);
  670. *eof = 1;
  671.   
  672. return p-buf;
  673. }
  674. static int proc_read(char *buf , char **start, off_t offset,
  675. int len, int *eof, void *data)
  676. {
  677. char *p;
  678. int i;
  679.         int idx = (int)(long)(data);
  680.         struct pktgen_info* info = NULL;
  681.         __u64 sa;
  682.         __u64 stopped;
  683.         __u64 now = getCurMs();
  684.         
  685.         if ((idx < 0) || (idx >= MAX_PKTGEN)) {
  686.                 printk("ERROR: idx: %i is out of range in proc_writen", idx);
  687.                 return -EINVAL;
  688.         }
  689.         info = &(pginfos[idx]);
  690.   
  691. p = buf;
  692.         p += sprintf(p, "%sn", VERSION); /* Help with parsing compatibility */
  693. p += sprintf(p, "Params: count %llu  pkt_size: %u  frags: %d  ipg: %u  clone_skb: %d odev "%s"n",
  694.      (unsigned long long) info->count,
  695.      info->pkt_size, info->nfrags, info->ipg,
  696.                      info->clone_skb, info->outdev);
  697.         p += sprintf(p, "     dst_min: %s  dst_max: %s  src_min: %s  src_max: %sn",
  698.                      info->dst_min, info->dst_max, info->src_min, info->src_max);
  699.         p += sprintf(p, "     src_mac: ");
  700. for (i = 0; i < 6; i++) {
  701. p += sprintf(p, "%02X%s", info->src_mac[i], i == 5 ? "  " : ":");
  702.         }
  703.         p += sprintf(p, "dst_mac: ");
  704. for (i = 0; i < 6; i++) {
  705. p += sprintf(p, "%02X%s", info->dst_mac[i], i == 5 ? "n" : ":");
  706.         }
  707.         p += sprintf(p, "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %dn",
  708.                      info->udp_src_min, info->udp_src_max, info->udp_dst_min,
  709.                      info->udp_dst_max);
  710.         p += sprintf(p, "     src_mac_count: %d  dst_mac_count: %dn     Flags: ",
  711.                      info->src_mac_count, info->dst_mac_count);
  712.         if (info->flags &  F_IPSRC_RND) {
  713.                 p += sprintf(p, "IPSRC_RND  ");
  714.         }
  715.         if (info->flags & F_IPDST_RND) {
  716.                 p += sprintf(p, "IPDST_RND  ");
  717.         }
  718.         if (info->flags & F_UDPSRC_RND) {
  719.                 p += sprintf(p, "UDPSRC_RND  ");
  720.         }
  721.         if (info->flags & F_UDPDST_RND) {
  722.                 p += sprintf(p, "UDPDST_RND  ");
  723.         }
  724.         if (info->flags & F_MACSRC_RND) {
  725.                 p += sprintf(p, "MACSRC_RND  ");
  726.         }
  727.         if (info->flags & F_MACDST_RND) {
  728.                 p += sprintf(p, "MACDST_RND  ");
  729.         }
  730.         p += sprintf(p, "n");
  731.         
  732.         sa = tv_to_ms(&(info->started_at));
  733.         stopped = tv_to_ms(&(info->stopped_at));
  734.         if (info->do_run_run) {
  735.                 stopped = now; /* not really stopped, more like last-running-at */
  736.         }
  737.         p += sprintf(p, "Current:n     pkts-sofar: %llu  errors: %llun     started: %llums  stopped: %llums  now: %llums  idle: %llunsn",
  738.                      (unsigned long long) info->sofar,
  739.      (unsigned long long) info->errors,
  740.      (unsigned long long) sa,
  741.      (unsigned long long) stopped,
  742.      (unsigned long long) now,
  743.      (unsigned long long) info->idle_acc);
  744.         p += sprintf(p, "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %dn",
  745.                      info->seq_num, info->cur_dst_mac_offset, info->cur_src_mac_offset);
  746.         p += sprintf(p, "     cur_saddr: 0x%x  cur_daddr: 0x%x  cur_udp_dst: %d  cur_udp_src: %dn",
  747.                      info->cur_saddr, info->cur_daddr, info->cur_udp_dst, info->cur_udp_src);
  748.         
  749. if (info->result[0])
  750. p += sprintf(p, "Result: %sn", info->result);
  751. else
  752. p += sprintf(p, "Result: Idlen");
  753. *eof = 1;
  754. return p - buf;
  755. }
  756. static int count_trail_chars(const char *user_buffer, unsigned int maxlen)
  757. {
  758. int i;
  759. for (i = 0; i < maxlen; i++) {
  760. char c;
  761. if (get_user(c, &user_buffer[i]))
  762. return -EFAULT;
  763. switch (c) {
  764. case '"':
  765. case 'n':
  766. case 'r':
  767. case 't':
  768. case ' ':
  769. case '=':
  770. break;
  771. default:
  772. goto done;
  773. };
  774. }
  775. done:
  776. return i;
  777. }
  778. static unsigned long num_arg(const char *user_buffer, unsigned long maxlen,
  779.      unsigned long *num)
  780. {
  781. int i = 0;
  782. *num = 0;
  783.   
  784. for(; i < maxlen; i++) {
  785. char c;
  786. if (get_user(c, &user_buffer[i]))
  787. return -EFAULT;
  788. if ((c >= '0') && (c <= '9')) {
  789. *num *= 10;
  790. *num += c -'0';
  791. } else
  792. break;
  793. }
  794. return i;
  795. }
  796. static int strn_len(const char *user_buffer, unsigned int maxlen)
  797. {
  798. int i = 0;
  799. for(; i < maxlen; i++) {
  800. char c;
  801. if (get_user(c, &user_buffer[i]))
  802. return -EFAULT;
  803. switch (c) {
  804. case '"':
  805. case 'n':
  806. case 'r':
  807. case 't':
  808. case ' ':
  809. goto done_str;
  810. default:
  811. break;
  812. };
  813. }
  814. done_str:
  815. return i;
  816. }
  817. static int proc_write(struct file *file, const char *user_buffer,
  818.  unsigned long count, void *data)
  819. {
  820. int i = 0, max, len;
  821. char name[16], valstr[32];
  822. unsigned long value = 0;
  823.         int idx = (int)(long)(data);
  824.         struct pktgen_info* info = NULL;
  825.         char* result = NULL;
  826. int tmp;
  827.         
  828.         if ((idx < 0) || (idx >= MAX_PKTGEN)) {
  829.                 printk("ERROR: idx: %i is out of range in proc_writen", idx);
  830.                 return -EINVAL;
  831.         }
  832.         info = &(pginfos[idx]);
  833.         result = &(info->result[0]);
  834.         
  835. if (count < 1) {
  836. sprintf(result, "Wrong command format");
  837. return -EINVAL;
  838. }
  839.   
  840. max = count - i;
  841. tmp = count_trail_chars(&user_buffer[i], max);
  842. if (tmp < 0)
  843. return tmp;
  844. i += tmp;
  845.   
  846. /* Read variable name */
  847. len = strn_len(&user_buffer[i], sizeof(name) - 1);
  848. if (len < 0)
  849. return len;
  850. memset(name, 0, sizeof(name));
  851. copy_from_user(name, &user_buffer[i], len);
  852. i += len;
  853.   
  854. max = count -i;
  855. len = count_trail_chars(&user_buffer[i], max);
  856. if (len < 0)
  857. return len;
  858. i += len;
  859. if (debug)
  860. printk("pg: %s,%lun", name, count);
  861. if (!strcmp(name, "stop")) {
  862. if (info->do_run_run) {
  863. strcpy(result, "Stopping");
  864.                 }
  865.                 else {
  866.                         strcpy(result, "Already stopped...n");
  867.                 }
  868.                 info->do_run_run = 0;
  869. return count;
  870. }
  871. if (!strcmp(name, "pkt_size")) {
  872. len = num_arg(&user_buffer[i], 10, &value);
  873. if (len < 0)
  874. return len;
  875. i += len;
  876. if (value < 14+20+8)
  877. value = 14+20+8;
  878. info->pkt_size = value;
  879. sprintf(result, "OK: pkt_size=%u", info->pkt_size);
  880. return count;
  881. }
  882. if (!strcmp(name, "frags")) {
  883. len = num_arg(&user_buffer[i], 10, &value);
  884. if (len < 0)
  885. return len;
  886. i += len;
  887. info->nfrags = value;
  888. sprintf(result, "OK: frags=%u", info->nfrags);
  889. return count;
  890. }
  891. if (!strcmp(name, "ipg")) {
  892. len = num_arg(&user_buffer[i], 10, &value);
  893. if (len < 0)
  894. return len;
  895. i += len;
  896. info->ipg = value;
  897. sprintf(result, "OK: ipg=%u", info->ipg);
  898. return count;
  899. }
  900.   if (!strcmp(name, "udp_src_min")) {
  901. len = num_arg(&user_buffer[i], 10, &value);
  902. if (len < 0)
  903. return len;
  904. i += len;
  905.   info->udp_src_min = value;
  906. sprintf(result, "OK: udp_src_min=%u", info->udp_src_min);
  907. return count;
  908. }
  909.   if (!strcmp(name, "udp_dst_min")) {
  910. len = num_arg(&user_buffer[i], 10, &value);
  911. if (len < 0)
  912. return len;
  913. i += len;
  914.   info->udp_dst_min = value;
  915. sprintf(result, "OK: udp_dst_min=%u", info->udp_dst_min);
  916. return count;
  917. }
  918.   if (!strcmp(name, "udp_src_max")) {
  919. len = num_arg(&user_buffer[i], 10, &value);
  920. if (len < 0)
  921. return len;
  922. i += len;
  923.   info->udp_src_max = value;
  924. sprintf(result, "OK: udp_src_max=%u", info->udp_src_max);
  925. return count;
  926. }
  927.   if (!strcmp(name, "udp_dst_max")) {
  928. len = num_arg(&user_buffer[i], 10, &value);
  929. if (len < 0)
  930. return len;
  931. i += len;
  932.   info->udp_dst_max = value;
  933. sprintf(result, "OK: udp_dst_max=%u", info->udp_dst_max);
  934. return count;
  935. }
  936. if (!strcmp(name, "clone_skb")) {
  937. len = num_arg(&user_buffer[i], 10, &value);
  938. if (len < 0)
  939. return len;
  940. i += len;
  941.                 info->clone_skb = value;
  942. sprintf(result, "OK: clone_skb=%d", info->clone_skb);
  943. return count;
  944. }
  945. if (!strcmp(name, "count")) {
  946. len = num_arg(&user_buffer[i], 10, &value);
  947. if (len < 0)
  948. return len;
  949. i += len;
  950. info->count = value;
  951. sprintf(result, "OK: count=%llu", (unsigned long long) info->count);
  952. return count;
  953. }
  954. if (!strcmp(name, "src_mac_count")) {
  955. len = num_arg(&user_buffer[i], 10, &value);
  956. if (len < 0)
  957. return len;
  958. i += len;
  959. info->src_mac_count = value;
  960. sprintf(result, "OK: src_mac_count=%d", info->src_mac_count);
  961. return count;
  962. }
  963. if (!strcmp(name, "dst_mac_count")) {
  964. len = num_arg(&user_buffer[i], 10, &value);
  965. if (len < 0)
  966. return len;
  967. i += len;
  968. info->dst_mac_count = value;
  969. sprintf(result, "OK: dst_mac_count=%d", info->dst_mac_count);
  970. return count;
  971. }
  972. if (!strcmp(name, "odev")) {
  973. len = strn_len(&user_buffer[i], sizeof(info->outdev) - 1);
  974. if (len < 0)
  975. return len;
  976. memset(info->outdev, 0, sizeof(info->outdev));
  977. copy_from_user(info->outdev, &user_buffer[i], len);
  978. i += len;
  979. sprintf(result, "OK: odev=%s", info->outdev);
  980. return count;
  981. }
  982. if (!strcmp(name, "flag")) {
  983.                 char f[32];
  984.                 memset(f, 0, 32);
  985. len = strn_len(&user_buffer[i], sizeof(f) - 1);
  986. if (len < 0)
  987. return len;
  988. copy_from_user(f, &user_buffer[i], len);
  989. i += len;
  990.                 if (strcmp(f, "IPSRC_RND") == 0) {
  991.                         info->flags |= F_IPSRC_RND;
  992.                 }
  993.                 else if (strcmp(f, "!IPSRC_RND") == 0) {
  994.                         info->flags &= ~F_IPSRC_RND;
  995.                 }
  996.                 else if (strcmp(f, "IPDST_RND") == 0) {
  997.                         info->flags |= F_IPDST_RND;
  998.                 }
  999.                 else if (strcmp(f, "!IPDST_RND") == 0) {
  1000.                         info->flags &= ~F_IPDST_RND;
  1001.                 }
  1002.                 else if (strcmp(f, "UDPSRC_RND") == 0) {
  1003.                         info->flags |= F_UDPSRC_RND;
  1004.                 }
  1005.                 else if (strcmp(f, "!UDPSRC_RND") == 0) {
  1006.                         info->flags &= ~F_UDPSRC_RND;
  1007.                 }
  1008.                 else if (strcmp(f, "UDPDST_RND") == 0) {
  1009.                         info->flags |= F_UDPDST_RND;
  1010.                 }
  1011.                 else if (strcmp(f, "!UDPDST_RND") == 0) {
  1012.                         info->flags &= ~F_UDPDST_RND;
  1013.                 }
  1014.                 else if (strcmp(f, "MACSRC_RND") == 0) {
  1015.                         info->flags |= F_MACSRC_RND;
  1016.                 }
  1017.                 else if (strcmp(f, "!MACSRC_RND") == 0) {
  1018.                         info->flags &= ~F_MACSRC_RND;
  1019.                 }
  1020.                 else if (strcmp(f, "MACDST_RND") == 0) {
  1021.                         info->flags |= F_MACDST_RND;
  1022.                 }
  1023.                 else if (strcmp(f, "!MACDST_RND") == 0) {
  1024.                         info->flags &= ~F_MACDST_RND;
  1025.                 }
  1026.                 else {
  1027.                         sprintf(result, "Flag -:%s:- unknownnAvailable flags, (prepend ! to un-set flag):n%s",
  1028.                                 f,
  1029.                                 "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RNDn");
  1030.                         return count;
  1031.                 }
  1032. sprintf(result, "OK: flags=0x%x", info->flags);
  1033. return count;
  1034. }
  1035. if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
  1036. len = strn_len(&user_buffer[i], sizeof(info->dst_min) - 1);
  1037. if (len < 0)
  1038. return len;
  1039. memset(info->dst_min, 0, sizeof(info->dst_min));
  1040. copy_from_user(info->dst_min, &user_buffer[i], len);
  1041. if(debug)
  1042. printk("pg: dst_min set to: %sn", info->dst_min);
  1043. i += len;
  1044. sprintf(result, "OK: dst_min=%s", info->dst_min);
  1045. return count;
  1046. }
  1047. if (!strcmp(name, "dst_max")) {
  1048. len = strn_len(&user_buffer[i], sizeof(info->dst_max) - 1);
  1049. if (len < 0)
  1050. return len;
  1051. memset(info->dst_max, 0, sizeof(info->dst_max));
  1052. copy_from_user(info->dst_max, &user_buffer[i], len);
  1053. if(debug)
  1054. printk("pg: dst_max set to: %sn", info->dst_max);
  1055. i += len;
  1056. sprintf(result, "OK: dst_max=%s", info->dst_max);
  1057. return count;
  1058. }
  1059. if (!strcmp(name, "src_min")) {
  1060. len = strn_len(&user_buffer[i], sizeof(info->src_min) - 1);
  1061. if (len < 0)
  1062. return len;
  1063. memset(info->src_min, 0, sizeof(info->src_min));
  1064. copy_from_user(info->src_min, &user_buffer[i], len);
  1065. if(debug)
  1066. printk("pg: src_min set to: %sn", info->src_min);
  1067. i += len;
  1068. sprintf(result, "OK: src_min=%s", info->src_min);
  1069. return count;
  1070. }
  1071. if (!strcmp(name, "src_max")) {
  1072. len = strn_len(&user_buffer[i], sizeof(info->src_max) - 1);
  1073. if (len < 0)
  1074. return len;
  1075. memset(info->src_max, 0, sizeof(info->src_max));
  1076. copy_from_user(info->src_max, &user_buffer[i], len);
  1077. if(debug)
  1078. printk("pg: src_max set to: %sn", info->src_max);
  1079. i += len;
  1080. sprintf(result, "OK: src_max=%s", info->src_max);
  1081. return count;
  1082. }
  1083. if (!strcmp(name, "dstmac")) {
  1084. char *v = valstr;
  1085. unsigned char *m = info->dst_mac;
  1086. len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
  1087. if (len < 0)
  1088. return len;
  1089. memset(valstr, 0, sizeof(valstr));
  1090. copy_from_user(valstr, &user_buffer[i], len);
  1091. i += len;
  1092. for(*m = 0;*v && m < info->dst_mac + 6; v++) {
  1093. if (*v >= '0' && *v <= '9') {
  1094. *m *= 16;
  1095. *m += *v - '0';
  1096. }
  1097. if (*v >= 'A' && *v <= 'F') {
  1098. *m *= 16;
  1099. *m += *v - 'A' + 10;
  1100. }
  1101. if (*v >= 'a' && *v <= 'f') {
  1102. *m *= 16;
  1103. *m += *v - 'a' + 10;
  1104. }
  1105. if (*v == ':') {
  1106. m++;
  1107. *m = 0;
  1108. }
  1109. }   
  1110. sprintf(result, "OK: dstmac");
  1111. return count;
  1112. }
  1113. if (!strcmp(name, "srcmac")) {
  1114. char *v = valstr;
  1115. unsigned char *m = info->src_mac;
  1116. len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
  1117. if (len < 0)
  1118. return len;
  1119. memset(valstr, 0, sizeof(valstr));
  1120. copy_from_user(valstr, &user_buffer[i], len);
  1121. i += len;
  1122. for(*m = 0;*v && m < info->src_mac + 6; v++) {
  1123. if (*v >= '0' && *v <= '9') {
  1124. *m *= 16;
  1125. *m += *v - '0';
  1126. }
  1127. if (*v >= 'A' && *v <= 'F') {
  1128. *m *= 16;
  1129. *m += *v - 'A' + 10;
  1130. }
  1131. if (*v >= 'a' && *v <= 'f') {
  1132. *m *= 16;
  1133. *m += *v - 'a' + 10;
  1134. }
  1135. if (*v == ':') {
  1136. m++;
  1137. *m = 0;
  1138. }
  1139. }   
  1140. sprintf(result, "OK: srcmac");
  1141. return count;
  1142. }
  1143. if (!strcmp(name, "inject") || !strcmp(name, "start")) {
  1144. MOD_INC_USE_COUNT;
  1145.                 if (info->busy) {
  1146.                         strcpy(info->result, "Already running...n");
  1147.                 }
  1148.                 else {
  1149.                         info->busy = 1;
  1150.                         strcpy(info->result, "Starting");
  1151.                         inject(info);
  1152.                         info->busy = 0;
  1153.                 }
  1154. MOD_DEC_USE_COUNT;
  1155. return count;
  1156. }
  1157. sprintf(info->result, "No such parameter "%s"", name);
  1158. return -EINVAL;
  1159. }
  1160. int create_proc_dir(void)
  1161. {
  1162.         int     len;
  1163.         /*  does proc_dir already exists */
  1164.         len = strlen(PG_PROC_DIR);
  1165.         for (proc_dir = proc_net->subdir; proc_dir;
  1166.              proc_dir=proc_dir->next) {
  1167.                 if ((proc_dir->namelen == len) &&
  1168.                     (! memcmp(proc_dir->name, PG_PROC_DIR, len)))
  1169.                         break;
  1170.         }
  1171.         if (!proc_dir)
  1172.                 proc_dir = create_proc_entry(PG_PROC_DIR, S_IFDIR, proc_net);
  1173.         if (!proc_dir) return -ENODEV;
  1174.         return 1;
  1175. }
  1176. int remove_proc_dir(void)
  1177. {
  1178.         remove_proc_entry(PG_PROC_DIR, proc_net);
  1179.         return 1;
  1180. }
  1181. static int __init init(void)
  1182. {
  1183.         int i;
  1184. printk(version);
  1185. cycles_calibrate();
  1186. if (cpu_speed == 0) {
  1187. printk("pktgen: Error: your machine does not have working cycle counter.n");
  1188. return -EINVAL;
  1189. }
  1190. create_proc_dir();
  1191.         for (i = 0; i<MAX_PKTGEN; i++) {
  1192.                 memset(&(pginfos[i]), 0, sizeof(pginfos[i]));
  1193.                 pginfos[i].pkt_size = ETH_ZLEN;
  1194.                 pginfos[i].nfrags = 0;
  1195.                 pginfos[i].clone_skb = clone_skb_d;
  1196.                 pginfos[i].ipg = ipg_d;
  1197.                 pginfos[i].count = count_d;
  1198.                 pginfos[i].sofar = 0;
  1199.                 pginfos[i].hh[12] = 0x08; /* fill in protocol.  Rest is filled in later. */
  1200.                 pginfos[i].hh[13] = 0x00;
  1201.                 pginfos[i].udp_src_min = 9; /* sink NULL */
  1202.                 pginfos[i].udp_src_max = 9;
  1203.                 pginfos[i].udp_dst_min = 9;
  1204.                 pginfos[i].udp_dst_max = 9;
  1205.                 
  1206.                 sprintf(pginfos[i].fname, "net/%s/pg%i", PG_PROC_DIR, i);
  1207.                 pginfos[i].proc_ent = create_proc_entry(pginfos[i].fname, 0600, 0);
  1208.                 if (!pginfos[i].proc_ent) {
  1209.                         printk("pktgen: Error: cannot create net/%s/pg procfs entry.n", PG_PROC_DIR);
  1210.                         goto cleanup_mem;
  1211.                 }
  1212.                 pginfos[i].proc_ent->read_proc = proc_read;
  1213.                 pginfos[i].proc_ent->write_proc = proc_write;
  1214.                 pginfos[i].proc_ent->data = (void*)(long)(i);
  1215.                 sprintf(pginfos[i].busy_fname, "net/%s/pg_busy%i",  PG_PROC_DIR, i);
  1216.                 pginfos[i].busy_proc_ent = create_proc_entry(pginfos[i].busy_fname, 0, 0);
  1217.                 if (!pginfos[i].busy_proc_ent) {
  1218.                         printk("pktgen: Error: cannot create net/%s/pg_busy procfs entry.n", PG_PROC_DIR);
  1219.                         goto cleanup_mem;
  1220.                 }
  1221.                 pginfos[i].busy_proc_ent->read_proc = proc_busy_read;
  1222.                 pginfos[i].busy_proc_ent->data = (void*)(long)(i);
  1223.         }
  1224.         return 0;
  1225.         
  1226. cleanup_mem:
  1227.         for (i = 0; i<MAX_PKTGEN; i++) {
  1228.                 if (strlen(pginfos[i].fname)) {
  1229.                         remove_proc_entry(pginfos[i].fname, NULL);
  1230.                 }
  1231.                 if (strlen(pginfos[i].busy_fname)) {
  1232.                         remove_proc_entry(pginfos[i].busy_fname, NULL);
  1233.                 }
  1234.         }
  1235. return -ENOMEM;
  1236. }
  1237. static void __exit cleanup(void)
  1238. {
  1239.         int i;
  1240.         for (i = 0; i<MAX_PKTGEN; i++) {
  1241.                 if (strlen(pginfos[i].fname)) {
  1242.                         remove_proc_entry(pginfos[i].fname, NULL);
  1243.                 }
  1244.                 if (strlen(pginfos[i].busy_fname)) {
  1245.                         remove_proc_entry(pginfos[i].busy_fname, NULL);
  1246.                 }
  1247.         }
  1248. remove_proc_dir();
  1249. }
  1250. module_init(init);
  1251. module_exit(cleanup);
  1252. MODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se");
  1253. MODULE_DESCRIPTION("Packet Generator tool");
  1254. MODULE_LICENSE("GPL");
  1255. MODULE_PARM(count_d, "i");
  1256. MODULE_PARM(ipg_d, "i");
  1257. MODULE_PARM(cpu_speed, "i");
  1258. MODULE_PARM(clone_skb_d, "i");