linux-bk/net/core/pktgen.c
<<
>>
Prefs
   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>
   9 * Jens Låås <jens.laas@data.slu.se>
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License
  13 * as published by the Free Software Foundation; either version
  14 * 2 of the License, or (at your option) any later version.
  15 *
  16 *
  17 * A tool for loading the network with preconfigurated packets.
  18 * The tool is implemented as a linux module.  Parameters are output 
  19 * device, delay (to hard_xmit), number of packets, and whether
  20 * to use multiple SKBs or just the same one.
  21 * pktgen uses the installed interface's output routine.
  22 *
  23 * Additional hacking by:
  24 *
  25 * Jens.Laas@data.slu.se
  26 * Improved by ANK. 010120.
  27 * Improved by ANK even more. 010212.
  28 * MAC address typo fixed. 010417 --ro
  29 * Integrated.  020301 --DaveM
  30 * Added multiskb option 020301 --DaveM
  31 * Scaling of results. 020417--sigurdur@linpro.no
  32 * Significant re-work of the module:
  33 *   *  Convert to threaded model to more efficiently be able to transmit
  34 *       and receive on multiple interfaces at once.
  35 *   *  Converted many counters to __u64 to allow longer runs.
  36 *   *  Allow configuration of ranges, like min/max IP address, MACs,
  37 *       and UDP-ports, for both source and destination, and can
  38 *       set to use a random distribution or sequentially walk the range.
  39 *   *  Can now change most values after starting.
  40 *   *  Place 12-byte packet in UDP payload with magic number,
  41 *       sequence number, and timestamp.
  42 *   *  Add receiver code that detects dropped pkts, re-ordered pkts, and
  43 *       latencies (with micro-second) precision.
  44 *   *  Add IOCTL interface to easily get counters & configuration.
  45 *   --Ben Greear <greearb@candelatech.com>
  46 *
  47 * Renamed multiskb to clone_skb and cleaned up sending core for two distinct 
  48 * skb modes. A clone_skb=0 mode for Ben "ranges" work and a clone_skb != 0 
  49 * as a "fastpath" with a configurable number of clones after alloc's.
  50 * clone_skb=0 means all packets are allocated this also means ranges time 
  51 * stamps etc can be used. clone_skb=100 means 1 malloc is followed by 100 
  52 * clones.
  53 *
  54 * Also moved to /proc/net/pktgen/ 
  55 * --ro
  56 *
  57 * Sept 10:  Fixed threading/locking.  Lots of bone-headed and more clever
  58 *    mistakes.  Also merged in DaveM's patch in the -pre6 patch.
  59 * --Ben Greear <greearb@candelatech.com>
  60 *
  61 * Integrated to 2.5.x 021029 --Lucio Maciel (luciomaciel@zipmail.com.br)
  62 *
  63 * 
  64 * 021124 Finished major redesign and rewrite for new functionality.
  65 * See Documentation/networking/pktgen.txt for how to use this.
  66 *
  67 * The new operation:
  68 * For each CPU one thread/process is created at start. This process checks 
  69 * for running devices in the if_list and sends packets until count is 0 it 
  70 * also the thread checks the thread->control which is used for inter-process 
  71 * communication. controlling process "posts" operations to the threads this 
  72 * way. The if_lock should be possible to remove when add/rem_device is merged
  73 * into this too.
  74 *
  75 * By design there should only be *one* "controlling" process. In practice 
  76 * multiple write accesses gives unpredictable result. Understood by "write" 
  77 * to /proc gives result code thats should be read be the "writer".
  78 * For pratical use this should be no problem.
  79 *
  80 * Note when adding devices to a specific CPU there good idea to also assign 
  81 * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU. 
  82 * --ro
  83 *
  84 * Fix refcount off by one if first packet fails, potential null deref, 
  85 * memleak 030710- KJP
  86 *
  87 * First "ranges" functionality for ipv6 030726 --ro
  88 *
  89 * Included flow support. 030802 ANK.
  90 *
  91 * Fixed unaligned access on IA-64 Grant Grundler <grundler@parisc-linux.org>
  92 * 
  93 * Remove if fix from added Harald Welte <laforge@netfilter.org> 040419
  94 * ia64 compilation fix from  Aron Griffis <aron@hp.com> 040604
  95 *
  96 * New xmit() return, do_div and misc clean up by Stephen Hemminger 
  97 * <shemminger@osdl.org> 040923
  98 *
  99 * Rany Dunlap fixed u64 printk compiler waring 
 100 *
 101 * Remove FCS from BW calculation.  Lennert Buytenhek <buytenh@wantstofly.org>
 102 * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213
 103 *
 104 * Corrections from Nikolai Malykh (nmalykh@bilim.com) 
 105 * Removed unused flags F_SET_SRCMAC & F_SET_SRCIP 041230
 106 *
 107 * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com> 
 108 * 050103
 109 */
 110#include <linux/sys.h>
 111#include <linux/types.h>
 112#include <linux/module.h>
 113#include <linux/moduleparam.h>
 114#include <linux/kernel.h>
 115#include <linux/smp_lock.h>
 116#include <linux/sched.h>
 117#include <linux/slab.h>
 118#include <linux/vmalloc.h>
 119#include <linux/sched.h>
 120#include <linux/unistd.h>
 121#include <linux/string.h>
 122#include <linux/ptrace.h>
 123#include <linux/errno.h>
 124#include <linux/ioport.h>
 125#include <linux/interrupt.h>
 126#include <linux/delay.h>
 127#include <linux/timer.h>
 128#include <linux/init.h>
 129#include <linux/skbuff.h>
 130#include <linux/netdevice.h>
 131#include <linux/inet.h>
 132#include <linux/inetdevice.h>
 133#include <linux/rtnetlink.h>
 134#include <linux/if_arp.h>
 135#include <linux/in.h>
 136#include <linux/ip.h>
 137#include <linux/ipv6.h>
 138#include <linux/udp.h>
 139#include <linux/proc_fs.h>
 140#include <linux/wait.h>
 141#include <net/checksum.h>
 142#include <net/ipv6.h>
 143#include <net/addrconf.h>
 144#include <asm/byteorder.h>
 145#include <linux/rcupdate.h>
 146#include <asm/bitops.h>
 147#include <asm/io.h>
 148#include <asm/dma.h>
 149#include <asm/uaccess.h>
 150#include <asm/div64.h> /* do_div */
 151#include <asm/timex.h>
 152
 153
 154#define VERSION  "pktgen v2.58: Packet Generator for packet performance testing.\n"
 155
 156/* #define PG_DEBUG(a) a */
 157#define PG_DEBUG(a) 
 158
 159/* The buckets are exponential in 'width' */
 160#define LAT_BUCKETS_MAX 32
 161#define IP_NAME_SZ 32
 162
 163/* Device flag bits */
 164#define F_IPSRC_RND   (1<<0)  /* IP-Src Random  */
 165#define F_IPDST_RND   (1<<1)  /* IP-Dst Random  */
 166#define F_UDPSRC_RND  (1<<2)  /* UDP-Src Random */
 167#define F_UDPDST_RND  (1<<3)  /* UDP-Dst Random */
 168#define F_MACSRC_RND  (1<<4)  /* MAC-Src Random */
 169#define F_MACDST_RND  (1<<5)  /* MAC-Dst Random */
 170#define F_TXSIZE_RND  (1<<6)  /* Transmit size is random */
 171#define F_IPV6        (1<<7)  /* Interface in IPV6 Mode */
 172
 173/* Thread control flag bits */
 174#define T_TERMINATE   (1<<0)  
 175#define T_STOP        (1<<1)  /* Stop run */
 176#define T_RUN         (1<<2)  /* Start run */
 177#define T_REMDEV      (1<<3)  /* Remove all devs */
 178
 179/* Locks */
 180#define   thread_lock()        spin_lock(&_thread_lock)
 181#define   thread_unlock()      spin_unlock(&_thread_lock)
 182
 183/* If lock -- can be removed after some work */
 184#define   if_lock(t)           spin_lock(&(t->if_lock));
 185#define   if_unlock(t)           spin_unlock(&(t->if_lock));
 186
 187/* Used to help with determining the pkts on receive */
 188#define PKTGEN_MAGIC 0xbe9be955
 189#define PG_PROC_DIR "pktgen"
 190
 191#define MAX_CFLOWS  65536
 192
 193struct flow_state
 194{
 195        __u32           cur_daddr;
 196        int             count;
 197};
 198
 199struct pktgen_dev {
 200
 201        /*
 202         * Try to keep frequent/infrequent used vars. separated.
 203         */
 204
 205        char ifname[32];
 206        struct proc_dir_entry *proc_ent;
 207        char result[512];
 208        /* proc file names */
 209        char fname[80];
 210
 211        struct pktgen_thread* pg_thread; /* the owner */
 212        struct pktgen_dev *next; /* Used for chaining in the thread's run-queue */
 213
 214        int running;  /* if this changes to false, the test will stop */
 215        
 216        /* If min != max, then we will either do a linear iteration, or
 217         * we will do a random selection from within the range.
 218         */
 219        __u32 flags;     
 220
 221        int min_pkt_size;    /* = ETH_ZLEN; */
 222        int max_pkt_size;    /* = ETH_ZLEN; */
 223        int nfrags;
 224        __u32 delay_us;    /* Default delay */
 225        __u32 delay_ns;
 226        __u64 count;  /* Default No packets to send */
 227        __u64 sofar;  /* How many pkts we've sent so far */
 228        __u64 tx_bytes; /* How many bytes we've transmitted */
 229        __u64 errors;    /* Errors when trying to transmit, pkts will be re-sent */
 230
 231        /* runtime counters relating to clone_skb */
 232        __u64 next_tx_us;          /* timestamp of when to tx next */
 233        __u32 next_tx_ns;
 234        
 235        __u64 allocated_skbs;
 236        __u32 clone_count;
 237        int last_ok;           /* Was last skb sent? 
 238                                * Or a failed transmit of some sort?  This will keep
 239                                * sequence numbers in order, for example.
 240                                */
 241        __u64 started_at; /* micro-seconds */
 242        __u64 stopped_at; /* micro-seconds */
 243        __u64 idle_acc; /* micro-seconds */
 244        __u32 seq_num;
 245        
 246        int clone_skb; /* Use multiple SKBs during packet gen.  If this number
 247                          * is greater than 1, then that many coppies of the same
 248                          * packet will be sent before a new packet is allocated.
 249                          * For instance, if you want to send 1024 identical packets
 250                          * before creating a new packet, set clone_skb to 1024.
 251                          */
 252        
 253        char dst_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
 254        char dst_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
 255        char src_min[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
 256        char src_max[IP_NAME_SZ]; /* IP, ie 1.2.3.4 */
 257
 258        struct in6_addr  in6_saddr;
 259        struct in6_addr  in6_daddr;
 260        struct in6_addr  cur_in6_daddr;
 261        struct in6_addr  cur_in6_saddr;
 262        /* For ranges */
 263        struct in6_addr  min_in6_daddr;
 264        struct in6_addr  max_in6_daddr;
 265        struct in6_addr  min_in6_saddr;
 266        struct in6_addr  max_in6_saddr;
 267
 268        /* If we're doing ranges, random or incremental, then this
 269         * defines the min/max for those ranges.
 270         */
 271        __u32 saddr_min; /* inclusive, source IP address */
 272        __u32 saddr_max; /* exclusive, source IP address */
 273        __u32 daddr_min; /* inclusive, dest IP address */
 274        __u32 daddr_max; /* exclusive, dest IP address */
 275
 276        __u16 udp_src_min; /* inclusive, source UDP port */
 277        __u16 udp_src_max; /* exclusive, source UDP port */
 278        __u16 udp_dst_min; /* inclusive, dest UDP port */
 279        __u16 udp_dst_max; /* exclusive, dest UDP port */
 280
 281        __u32 src_mac_count; /* How many MACs to iterate through */
 282        __u32 dst_mac_count; /* How many MACs to iterate through */
 283        
 284        unsigned char dst_mac[6];
 285        unsigned char src_mac[6];
 286        
 287        __u32 cur_dst_mac_offset;
 288        __u32 cur_src_mac_offset;
 289        __u32 cur_saddr;
 290        __u32 cur_daddr;
 291        __u16 cur_udp_dst;
 292        __u16 cur_udp_src;
 293        __u32 cur_pkt_size;
 294        
 295        __u8 hh[14];
 296        /* = { 
 297           0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB, 
 298           
 299           We fill in SRC address later
 300           0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 301           0x08, 0x00
 302           };
 303        */
 304        __u16 pad; /* pad out the hh struct to an even 16 bytes */
 305
 306        struct sk_buff* skb; /* skb we are to transmit next, mainly used for when we
 307                              * are transmitting the same one multiple times
 308                              */
 309        struct net_device* odev; /* The out-going device.  Note that the device should
 310                                  * have it's pg_info pointer pointing back to this
 311                                  * device.  This will be set when the user specifies
 312                                  * the out-going device name (not when the inject is
 313                                  * started as it used to do.)
 314                                  */
 315        struct flow_state *flows;
 316        unsigned cflows;         /* Concurrent flows (config) */
 317        unsigned lflow;          /* Flow length  (config) */
 318        unsigned nflows;         /* accumulated flows (stats) */
 319};
 320
 321struct pktgen_hdr {
 322        __u32 pgh_magic;
 323        __u32 seq_num;
 324        __u32 tv_sec;
 325        __u32 tv_usec;
 326};
 327
 328struct pktgen_thread {
 329        spinlock_t if_lock;
 330        struct pktgen_dev *if_list;           /* All device here */
 331        struct pktgen_thread* next;
 332        char name[32];
 333        char fname[128]; /* name of proc file */
 334        struct proc_dir_entry *proc_ent;
 335        char result[512];
 336        u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
 337        
 338        /* Field for thread to receive "posted" events terminate, stop ifs etc.*/
 339
 340        u32 control;
 341        int pid;
 342        int cpu;
 343
 344        wait_queue_head_t queue;
 345};
 346
 347#define REMOVE 1
 348#define FIND   0
 349
 350/*  This code works around the fact that do_div cannot handle two 64-bit
 351    numbers, and regular 64-bit division doesn't work on x86 kernels.
 352    --Ben
 353*/
 354
 355#define PG_DIV 0
 356
 357/* This was emailed to LMKL by: Chris Caputo <ccaputo@alt.net>
 358 * Function copied/adapted/optimized from:
 359 *
 360 *  nemesis.sourceforge.net/browse/lib/static/intmath/ix86/intmath.c.html
 361 *
 362 * Copyright 1994, University of Cambridge Computer Laboratory
 363 * All Rights Reserved.
 364 *
 365 */
 366inline static s64 divremdi3(s64 x, s64 y, int type) 
 367{
 368        u64 a = (x < 0) ? -x : x;
 369        u64 b = (y < 0) ? -y : y;
 370        u64 res = 0, d = 1;
 371
 372        if (b > 0) {
 373                while (b < a) {
 374                        b <<= 1;
 375                        d <<= 1;
 376                }
 377        }
 378        
 379        do {
 380                if ( a >= b ) {
 381                        a -= b;
 382                        res += d;
 383                }
 384                b >>= 1;
 385                d >>= 1;
 386        }
 387        while (d);
 388
 389        if (PG_DIV == type) {
 390                return (((x ^ y) & (1ll<<63)) == 0) ? res : -(s64)res;
 391        }
 392        else {
 393                return ((x & (1ll<<63)) == 0) ? a : -(s64)a;
 394        }
 395}
 396
 397/* End of hacks to deal with 64-bit math on x86 */
 398
 399/** Convert to miliseconds */
 400static inline __u64 tv_to_ms(const struct timeval* tv) 
 401{
 402        __u64 ms = tv->tv_usec / 1000;
 403        ms += (__u64)tv->tv_sec * (__u64)1000;
 404        return ms;
 405}
 406
 407
 408/** Convert to micro-seconds */
 409static inline __u64 tv_to_us(const struct timeval* tv) 
 410{
 411        __u64 us = tv->tv_usec;
 412        us += (__u64)tv->tv_sec * (__u64)1000000;
 413        return us;
 414}
 415
 416static inline __u64 pg_div(__u64 n, __u32 base) {
 417        __u64 tmp = n;
 418        do_div(tmp, base);
 419        /* printk("pktgen: pg_div, n: %llu  base: %d  rv: %llu\n",
 420                  n, base, tmp); */
 421        return tmp;
 422}
 423
 424static inline __u64 pg_div64(__u64 n, __u64 base) 
 425{
 426        __u64 tmp = n;
 427/*
 428 * How do we know if the architectrure we are running on
 429 * supports division with 64 bit base?
 430 * 
 431 */
 432#if defined(__sparc_v9__) || defined(__powerpc64__) || defined(__alpha__) || defined(__x86_64__) || defined(__ia64__) 
 433
 434                do_div(tmp, base);
 435#else
 436                tmp = divremdi3(n, base, PG_DIV);
 437#endif
 438        return tmp;
 439}
 440
 441static inline u32 pktgen_random(void)
 442{
 443#if 0
 444        __u32 n;
 445        get_random_bytes(&n, 4);
 446        return n;
 447#else
 448        return net_random();
 449#endif
 450}
 451
 452static inline __u64 getCurMs(void) 
 453{
 454        struct timeval tv;
 455        do_gettimeofday(&tv);
 456        return tv_to_ms(&tv);
 457}
 458
 459static inline __u64 getCurUs(void) 
 460{
 461        struct timeval tv;
 462        do_gettimeofday(&tv);
 463        return tv_to_us(&tv);
 464}
 465
 466static inline __u64 tv_diff(const struct timeval* a, const struct timeval* b) 
 467{
 468        return tv_to_us(a) - tv_to_us(b);
 469}
 470
 471
 472/* old include end */
 473
 474static char version[] __initdata = VERSION;
 475
 476static ssize_t proc_pgctrl_read(struct file* file, char __user * buf, size_t count, loff_t *ppos);
 477static ssize_t proc_pgctrl_write(struct file* file, const char __user * buf, size_t count, loff_t *ppos);
 478static int proc_if_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
 479
 480static int proc_thread_read(char *buf , char **start, off_t offset, int len, int *eof, void *data);
 481static int proc_if_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
 482static int proc_thread_write(struct file *file, const char __user *user_buffer, unsigned long count, void *data);
 483static int create_proc_dir(void);
 484static int remove_proc_dir(void);
 485
 486static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i);
 487static int pktgen_add_device(struct pktgen_thread* t, const char* ifname);
 488static struct pktgen_thread* pktgen_find_thread(const char* name);
 489static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread* t, const char* ifname);
 490static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
 491static void pktgen_run_all_threads(void);
 492static void pktgen_stop_all_threads_ifs(void);
 493static int pktgen_stop_device(struct pktgen_dev *pkt_dev);
 494static void pktgen_stop(struct pktgen_thread* t);
 495static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
 496static struct pktgen_dev *pktgen_NN_threads(const char* dev_name, int remove);
 497static unsigned int scan_ip6(const char *s,char ip[16]);
 498static unsigned int fmt_ip6(char *s,const char ip[16]);
 499
 500/* Module parameters, defaults. */
 501static int pg_count_d = 1000; /* 1000 pkts by default */
 502static int pg_delay_d = 0;
 503static int pg_clone_skb_d = 0;
 504static int debug = 0;
 505
 506static spinlock_t _thread_lock = SPIN_LOCK_UNLOCKED;
 507static struct pktgen_thread *pktgen_threads = NULL;
 508
 509static char module_fname[128];
 510static struct proc_dir_entry *module_proc_ent = NULL;
 511
 512static struct notifier_block pktgen_notifier_block = {
 513        .notifier_call = pktgen_device_event,
 514};
 515
 516static struct file_operations pktgen_fops = {
 517        .read     = proc_pgctrl_read,
 518        .write    = proc_pgctrl_write,
 519        /*  .ioctl    = pktgen_ioctl, later maybe */
 520};
 521
 522/*
 523 * /proc handling functions 
 524 *
 525 */
 526
 527static struct proc_dir_entry *pg_proc_dir = NULL;
 528static int proc_pgctrl_read_eof=0;
 529
 530static ssize_t proc_pgctrl_read(struct file* file, char __user * buf,
 531                                 size_t count, loff_t *ppos)
 532{ 
 533        char data[200];
 534        int len = 0;
 535
 536        if(proc_pgctrl_read_eof) {
 537                proc_pgctrl_read_eof=0;
 538                len = 0;
 539                goto out;
 540        }
 541
 542        sprintf(data, "%s", VERSION); 
 543
 544        len = strlen(data);
 545
 546        if(len > count) {
 547                len =-EFAULT;
 548                goto out;
 549        }       
 550
 551        if (copy_to_user(buf, data, len)) {
 552                len =-EFAULT;
 553                goto out;
 554        }  
 555
 556        *ppos += len;
 557        proc_pgctrl_read_eof=1; /* EOF next call */
 558
 559 out:
 560        return len;
 561}
 562
 563static ssize_t proc_pgctrl_write(struct file* file,const char __user * buf,
 564                                 size_t count, loff_t *ppos)
 565{
 566        char *data = NULL;
 567        int err = 0;
 568
 569        if (!capable(CAP_NET_ADMIN)){
 570                err = -EPERM;
 571                goto out;
 572        }
 573
 574        data = (void*)vmalloc ((unsigned int)count);
 575
 576        if(!data) {
 577                err = -ENOMEM;
 578                goto out;
 579        }
 580        if (copy_from_user(data, buf, count)) {
 581                err =-EFAULT;
 582                goto out_free;
 583        }  
 584        data[count-1] = 0; /* Make string */
 585
 586        if (!strcmp(data, "stop")) 
 587                pktgen_stop_all_threads_ifs();
 588
 589        else if (!strcmp(data, "start")) 
 590                pktgen_run_all_threads();
 591
 592        else 
 593                printk("pktgen: Unknown command: %s\n", data);
 594
 595        err = count;
 596
 597 out_free:
 598        vfree (data);
 599 out:
 600        return err;
 601}
 602
 603static int proc_if_read(char *buf , char **start, off_t offset,
 604                           int len, int *eof, void *data)
 605{
 606        char *p;
 607        int i;
 608        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
 609        __u64 sa;
 610        __u64 stopped;
 611        __u64 now = getCurUs();
 612        
 613        p = buf;
 614        p += sprintf(p, "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
 615                     (unsigned long long) pkt_dev->count,
 616                     pkt_dev->min_pkt_size, pkt_dev->max_pkt_size);
 617
 618        p += sprintf(p, "     frags: %d  delay: %u  clone_skb: %d  ifname: %s\n",
 619                     pkt_dev->nfrags, 1000*pkt_dev->delay_us+pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->ifname);
 620
 621        p += sprintf(p, "     flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow);
 622
 623
 624        if(pkt_dev->flags & F_IPV6) {
 625                char b1[128], b2[128], b3[128];
 626                fmt_ip6(b1,  pkt_dev->in6_saddr.s6_addr);
 627                fmt_ip6(b2,  pkt_dev->min_in6_saddr.s6_addr);
 628                fmt_ip6(b3,  pkt_dev->max_in6_saddr.s6_addr);
 629                p += sprintf(p, "     saddr: %s  min_saddr: %s  max_saddr: %s\n", b1, b2, b3);
 630
 631                fmt_ip6(b1,  pkt_dev->in6_daddr.s6_addr);
 632                fmt_ip6(b2,  pkt_dev->min_in6_daddr.s6_addr);
 633                fmt_ip6(b3,  pkt_dev->max_in6_daddr.s6_addr);
 634                p += sprintf(p, "     daddr: %s  min_daddr: %s  max_daddr: %s\n", b1, b2, b3);
 635
 636        } 
 637        else 
 638                p += sprintf(p, "     dst_min: %s  dst_max: %s\n     src_min: %s  src_max: %s\n",
 639                     pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max);
 640
 641        p += sprintf(p, "     src_mac: ");
 642
 643        if ((pkt_dev->src_mac[0] == 0) && 
 644            (pkt_dev->src_mac[1] == 0) && 
 645            (pkt_dev->src_mac[2] == 0) && 
 646            (pkt_dev->src_mac[3] == 0) && 
 647            (pkt_dev->src_mac[4] == 0) && 
 648            (pkt_dev->src_mac[5] == 0)) 
 649
 650                for (i = 0; i < 6; i++) 
 651                        p += sprintf(p, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? "  " : ":");
 652
 653        else 
 654                for (i = 0; i < 6; i++) 
 655                        p += sprintf(p, "%02X%s", pkt_dev->src_mac[i], i == 5 ? "  " : ":");
 656
 657        p += sprintf(p, "dst_mac: ");
 658        for (i = 0; i < 6; i++) 
 659                p += sprintf(p, "%02X%s", pkt_dev->dst_mac[i], i == 5 ? "\n" : ":");
 660
 661        p += sprintf(p, "     udp_src_min: %d  udp_src_max: %d  udp_dst_min: %d  udp_dst_max: %d\n",
 662                     pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min,
 663                     pkt_dev->udp_dst_max);
 664
 665        p += sprintf(p, "     src_mac_count: %d  dst_mac_count: %d \n     Flags: ",
 666                     pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
 667
 668
 669        if (pkt_dev->flags &  F_IPV6) 
 670                p += sprintf(p, "IPV6  ");
 671
 672        if (pkt_dev->flags &  F_IPSRC_RND) 
 673                p += sprintf(p, "IPSRC_RND  ");
 674
 675        if (pkt_dev->flags & F_IPDST_RND) 
 676                p += sprintf(p, "IPDST_RND  ");
 677        
 678        if (pkt_dev->flags & F_TXSIZE_RND) 
 679                p += sprintf(p, "TXSIZE_RND  ");
 680        
 681        if (pkt_dev->flags & F_UDPSRC_RND) 
 682                p += sprintf(p, "UDPSRC_RND  ");
 683        
 684        if (pkt_dev->flags & F_UDPDST_RND) 
 685                p += sprintf(p, "UDPDST_RND  ");
 686        
 687        if (pkt_dev->flags & F_MACSRC_RND) 
 688                p += sprintf(p, "MACSRC_RND  ");
 689        
 690        if (pkt_dev->flags & F_MACDST_RND) 
 691                p += sprintf(p, "MACDST_RND  ");
 692
 693        
 694        p += sprintf(p, "\n");
 695        
 696        sa = pkt_dev->started_at;
 697        stopped = pkt_dev->stopped_at;
 698        if (pkt_dev->running) 
 699                stopped = now; /* not really stopped, more like last-running-at */
 700        
 701        p += sprintf(p, "Current:\n     pkts-sofar: %llu  errors: %llu\n     started: %lluus  stopped: %lluus idle: %lluus\n",
 702                     (unsigned long long) pkt_dev->sofar,
 703                     (unsigned long long) pkt_dev->errors,
 704                     (unsigned long long) sa,
 705                     (unsigned long long) stopped, 
 706                     (unsigned long long) pkt_dev->idle_acc);
 707
 708        p += sprintf(p, "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
 709                     pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset, pkt_dev->cur_src_mac_offset);
 710
 711        if(pkt_dev->flags & F_IPV6) {
 712                char b1[128], b2[128];
 713                fmt_ip6(b1,  pkt_dev->cur_in6_daddr.s6_addr);
 714                fmt_ip6(b2,  pkt_dev->cur_in6_saddr.s6_addr);
 715                p += sprintf(p, "     cur_saddr: %s  cur_daddr: %s\n", b2, b1);
 716        } 
 717        else 
 718                p += sprintf(p, "     cur_saddr: 0x%x  cur_daddr: 0x%x\n",
 719                     pkt_dev->cur_saddr, pkt_dev->cur_daddr);
 720
 721
 722        p += sprintf(p, "     cur_udp_dst: %d  cur_udp_src: %d\n",
 723                     pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
 724
 725        p += sprintf(p, "     flows: %u\n", pkt_dev->nflows);
 726
 727        if (pkt_dev->result[0])
 728                p += sprintf(p, "Result: %s\n", pkt_dev->result);
 729        else
 730                p += sprintf(p, "Result: Idle\n");
 731        *eof = 1;
 732
 733        return p - buf;
 734}
 735
 736
 737static int count_trail_chars(const char __user *user_buffer, unsigned int maxlen)
 738{
 739        int i;
 740
 741        for (i = 0; i < maxlen; i++) {
 742                char c;
 743                if (get_user(c, &user_buffer[i]))
 744                        return -EFAULT;
 745                switch (c) {
 746                case '\"':
 747                case '\n':
 748                case '\r':
 749                case '\t':
 750                case ' ':
 751                case '=':
 752                        break;
 753                default:
 754                        goto done;
 755                };
 756        }
 757done:
 758        return i;
 759}
 760
 761static unsigned long num_arg(const char __user *user_buffer, unsigned long maxlen, 
 762                             unsigned long *num)
 763{
 764        int i = 0;
 765        *num = 0;
 766  
 767        for(; i < maxlen; i++) {
 768                char c;
 769                if (get_user(c, &user_buffer[i]))
 770                        return -EFAULT;
 771                if ((c >= '0') && (c <= '9')) {
 772                        *num *= 10;
 773                        *num += c -'0';
 774                } else
 775                        break;
 776        }
 777        return i;
 778}
 779
 780static int strn_len(const char __user *user_buffer, unsigned int maxlen)
 781{
 782        int i = 0;
 783
 784        for(; i < maxlen; i++) {
 785                char c;
 786                if (get_user(c, &user_buffer[i]))
 787                        return -EFAULT;
 788                switch (c) {
 789                case '\"':
 790                case '\n':
 791                case '\r':
 792                case '\t':
 793                case ' ':
 794                        goto done_str;
 795                        break;
 796                default:
 797                        break;
 798                };
 799        }
 800done_str:
 801
 802        return i;
 803}
 804
 805static int proc_if_write(struct file *file, const char __user *user_buffer,
 806                            unsigned long count, void *data)
 807{
 808        int i = 0, max, len;
 809        char name[16], valstr[32];
 810        unsigned long value = 0;
 811        struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
 812        char* pg_result = NULL;
 813        int tmp = 0;
 814        char buf[128];
 815        
 816        pg_result = &(pkt_dev->result[0]);
 817        
 818        if (count < 1) {
 819                printk("pktgen: wrong command format\n");
 820                return -EINVAL;
 821        }
 822  
 823        max = count - i;
 824        tmp = count_trail_chars(&user_buffer[i], max);
 825        if (tmp < 0) { 
 826                printk("pktgen: illegal format\n");
 827                return tmp; 
 828        }
 829        i += tmp;
 830        
 831        /* Read variable name */
 832
 833        len = strn_len(&user_buffer[i], sizeof(name) - 1);
 834        if (len < 0) { return len; }
 835        memset(name, 0, sizeof(name));
 836        if (copy_from_user(name, &user_buffer[i], len) )
 837                return -EFAULT;
 838        i += len;
 839  
 840        max = count -i;
 841        len = count_trail_chars(&user_buffer[i], max);
 842        if (len < 0) 
 843                return len;
 844        
 845        i += len;
 846
 847        if (debug) {
 848                char tb[count + 1];
 849                if (copy_from_user(tb, user_buffer, count))
 850                        return -EFAULT;
 851                tb[count] = 0;
 852                printk("pktgen: %s,%lu  buffer -:%s:-\n", name, count, tb);
 853        }
 854
 855        if (!strcmp(name, "min_pkt_size")) {
 856                len = num_arg(&user_buffer[i], 10, &value);
 857                if (len < 0) { return len; }
 858                i += len;
 859                if (value < 14+20+8)
 860                        value = 14+20+8;
 861                if (value != pkt_dev->min_pkt_size) {
 862                        pkt_dev->min_pkt_size = value;
 863                        pkt_dev->cur_pkt_size = value;
 864                }
 865                sprintf(pg_result, "OK: min_pkt_size=%u", pkt_dev->min_pkt_size);
 866                return count;
 867        }
 868
 869        if (!strcmp(name, "max_pkt_size")) {
 870                len = num_arg(&user_buffer[i], 10, &value);
 871                if (len < 0) { return len; }
 872                i += len;
 873                if (value < 14+20+8)
 874                        value = 14+20+8;
 875                if (value != pkt_dev->max_pkt_size) {
 876                        pkt_dev->max_pkt_size = value;
 877                        pkt_dev->cur_pkt_size = value;
 878                }
 879                sprintf(pg_result, "OK: max_pkt_size=%u", pkt_dev->max_pkt_size);
 880                return count;
 881        }
 882
 883        /* Shortcut for min = max */
 884
 885        if (!strcmp(name, "pkt_size")) {
 886                len = num_arg(&user_buffer[i], 10, &value);
 887                if (len < 0) { return len; }
 888                i += len;
 889                if (value < 14+20+8)
 890                        value = 14+20+8;
 891                if (value != pkt_dev->min_pkt_size) {
 892                        pkt_dev->min_pkt_size = value;
 893                        pkt_dev->max_pkt_size = value;
 894                        pkt_dev->cur_pkt_size = value;
 895                }
 896                sprintf(pg_result, "OK: pkt_size=%u", pkt_dev->min_pkt_size);
 897                return count;
 898        }
 899
 900        if (!strcmp(name, "debug")) {
 901                len = num_arg(&user_buffer[i], 10, &value);
 902                if (len < 0) { return len; }
 903                i += len;
 904                debug = value;
 905                sprintf(pg_result, "OK: debug=%u", debug);
 906                return count;
 907        }
 908
 909        if (!strcmp(name, "frags")) {
 910                len = num_arg(&user_buffer[i], 10, &value);
 911                if (len < 0) { return len; }
 912                i += len;
 913                pkt_dev->nfrags = value;
 914                sprintf(pg_result, "OK: frags=%u", pkt_dev->nfrags);
 915                return count;
 916        }
 917        if (!strcmp(name, "delay")) {
 918                len = num_arg(&user_buffer[i], 10, &value);
 919                if (len < 0) { return len; }
 920                i += len;
 921                if (value == 0x7FFFFFFF) {
 922                        pkt_dev->delay_us = 0x7FFFFFFF;
 923                        pkt_dev->delay_ns = 0;
 924                } else {
 925                        pkt_dev->delay_us = value / 1000;
 926                        pkt_dev->delay_ns = value % 1000;
 927                }
 928                sprintf(pg_result, "OK: delay=%u", 1000*pkt_dev->delay_us+pkt_dev->delay_ns);
 929                return count;
 930        }
 931        if (!strcmp(name, "udp_src_min")) {
 932                len = num_arg(&user_buffer[i], 10, &value);
 933                if (len < 0) { return len; }
 934                i += len;
 935                if (value != pkt_dev->udp_src_min) {
 936                        pkt_dev->udp_src_min = value;
 937                        pkt_dev->cur_udp_src = value;
 938                }       
 939                sprintf(pg_result, "OK: udp_src_min=%u", pkt_dev->udp_src_min);
 940                return count;
 941        }
 942        if (!strcmp(name, "udp_dst_min")) {
 943                len = num_arg(&user_buffer[i], 10, &value);
 944                if (len < 0) { return len; }
 945                i += len;
 946                if (value != pkt_dev->udp_dst_min) {
 947                        pkt_dev->udp_dst_min = value;
 948                        pkt_dev->cur_udp_dst = value;
 949                }
 950                sprintf(pg_result, "OK: udp_dst_min=%u", pkt_dev->udp_dst_min);
 951                return count;
 952        }
 953        if (!strcmp(name, "udp_src_max")) {
 954                len = num_arg(&user_buffer[i], 10, &value);
 955                if (len < 0) { return len; }
 956                i += len;
 957                if (value != pkt_dev->udp_src_max) {
 958                        pkt_dev->udp_src_max = value;
 959                        pkt_dev->cur_udp_src = value;
 960                }
 961                sprintf(pg_result, "OK: udp_src_max=%u", pkt_dev->udp_src_max);
 962                return count;
 963        }
 964        if (!strcmp(name, "udp_dst_max")) {
 965                len = num_arg(&user_buffer[i], 10, &value);
 966                if (len < 0) { return len; }
 967                i += len;
 968                if (value != pkt_dev->udp_dst_max) {
 969                        pkt_dev->udp_dst_max = value;
 970                        pkt_dev->cur_udp_dst = value;
 971                }
 972                sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max);
 973                return count;
 974        }
 975        if (!strcmp(name, "clone_skb")) {
 976                len = num_arg(&user_buffer[i], 10, &value);
 977                if (len < 0) { return len; }
 978                i += len;
 979                pkt_dev->clone_skb = value;
 980        
 981                sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb);
 982                return count;
 983        }
 984        if (!strcmp(name, "count")) {
 985                len = num_arg(&user_buffer[i], 10, &value);
 986                if (len < 0) { return len; }
 987                i += len;
 988                pkt_dev->count = value;
 989                sprintf(pg_result, "OK: count=%llu",
 990                        (unsigned long long) pkt_dev->count);
 991                return count;
 992        }
 993        if (!strcmp(name, "src_mac_count")) {
 994                len = num_arg(&user_buffer[i], 10, &value);
 995                if (len < 0) { return len; }
 996                i += len;
 997                if (pkt_dev->src_mac_count != value) {
 998                        pkt_dev->src_mac_count = value;
 999                        pkt_dev->cur_src_mac_offset = 0;
1000                }
1001                sprintf(pg_result, "OK: src_mac_count=%d", pkt_dev->src_mac_count);
1002                return count;
1003        }
1004        if (!strcmp(name, "dst_mac_count")) {
1005                len = num_arg(&user_buffer[i], 10, &value);
1006                if (len < 0) { return len; }
1007                i += len;
1008                if (pkt_dev->dst_mac_count != value) {
1009                        pkt_dev->dst_mac_count = value;
1010                        pkt_dev->cur_dst_mac_offset = 0;
1011                }
1012                sprintf(pg_result, "OK: dst_mac_count=%d", pkt_dev->dst_mac_count);
1013                return count;
1014        }
1015        if (!strcmp(name, "flag")) {
1016                char f[32];
1017                memset(f, 0, 32);
1018                len = strn_len(&user_buffer[i], sizeof(f) - 1);
1019                if (len < 0) { return len; }
1020                if (copy_from_user(f, &user_buffer[i], len))
1021                        return -EFAULT;
1022                i += len;
1023                if (strcmp(f, "IPSRC_RND") == 0) 
1024                        pkt_dev->flags |= F_IPSRC_RND;
1025                
1026                else if (strcmp(f, "!IPSRC_RND") == 0) 
1027                        pkt_dev->flags &= ~F_IPSRC_RND;
1028                
1029                else if (strcmp(f, "TXSIZE_RND") == 0) 
1030                        pkt_dev->flags |= F_TXSIZE_RND;
1031                
1032                else if (strcmp(f, "!TXSIZE_RND") == 0) 
1033                        pkt_dev->flags &= ~F_TXSIZE_RND;
1034                
1035                else if (strcmp(f, "IPDST_RND") == 0) 
1036                        pkt_dev->flags |= F_IPDST_RND;
1037                
1038                else if (strcmp(f, "!IPDST_RND") == 0) 
1039                        pkt_dev->flags &= ~F_IPDST_RND;
1040                
1041                else if (strcmp(f, "UDPSRC_RND") == 0) 
1042                        pkt_dev->flags |= F_UDPSRC_RND;
1043                
1044                else if (strcmp(f, "!UDPSRC_RND") == 0) 
1045                        pkt_dev->flags &= ~F_UDPSRC_RND;
1046                
1047                else if (strcmp(f, "UDPDST_RND") == 0) 
1048                        pkt_dev->flags |= F_UDPDST_RND;
1049                
1050                else if (strcmp(f, "!UDPDST_RND") == 0) 
1051                        pkt_dev->flags &= ~F_UDPDST_RND;
1052                
1053                else if (strcmp(f, "MACSRC_RND") == 0) 
1054                        pkt_dev->flags |= F_MACSRC_RND;
1055                
1056                else if (strcmp(f, "!MACSRC_RND") == 0) 
1057                        pkt_dev->flags &= ~F_MACSRC_RND;
1058                
1059                else if (strcmp(f, "MACDST_RND") == 0) 
1060                        pkt_dev->flags |= F_MACDST_RND;
1061                
1062                else if (strcmp(f, "!MACDST_RND") == 0) 
1063                        pkt_dev->flags &= ~F_MACDST_RND;
1064                
1065                else {
1066                        sprintf(pg_result, "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
1067                                f,
1068                                "IPSRC_RND, IPDST_RND, TXSIZE_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND\n");
1069                        return count;
1070                }
1071                sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
1072                return count;
1073        }
1074        if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
1075                len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1);
1076                if (len < 0) { return len; }
1077
1078                if (copy_from_user(buf, &user_buffer[i], len))
1079                        return -EFAULT;
1080                buf[len] = 0;
1081                if (strcmp(buf, pkt_dev->dst_min) != 0) {
1082                        memset(pkt_dev->dst_min, 0, sizeof(pkt_dev->dst_min));
1083                        strncpy(pkt_dev->dst_min, buf, len);
1084                        pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
1085                        pkt_dev->cur_daddr = pkt_dev->daddr_min;
1086                }
1087                if(debug)
1088                        printk("pktgen: dst_min set to: %s\n", pkt_dev->dst_min);
1089                i += len;
1090                sprintf(pg_result, "OK: dst_min=%s", pkt_dev->dst_min);
1091                return count;
1092        }
1093        if (!strcmp(name, "dst_max")) {
1094                len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1);
1095                if (len < 0) { return len; }
1096
1097                if (copy_from_user(buf, &user_buffer[i], len))
1098                        return -EFAULT;
1099
1100                buf[len] = 0;
1101                if (strcmp(buf, pkt_dev->dst_max) != 0) {
1102                        memset(pkt_dev->dst_max, 0, sizeof(pkt_dev->dst_max));
1103                        strncpy(pkt_dev->dst_max, buf, len);
1104                        pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
1105                        pkt_dev->cur_daddr = pkt_dev->daddr_max;
1106                }
1107                if(debug)
1108                        printk("pktgen: dst_max set to: %s\n", pkt_dev->dst_max);
1109                i += len;
1110                sprintf(pg_result, "OK: dst_max=%s", pkt_dev->dst_max);
1111                return count;
1112        }
1113        if (!strcmp(name, "dst6")) {
1114                len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1115                if (len < 0) return len; 
1116
1117                pkt_dev->flags |= F_IPV6;
1118
1119                if (copy_from_user(buf, &user_buffer[i], len))
1120                        return -EFAULT;
1121                buf[len] = 0;
1122
1123                scan_ip6(buf, pkt_dev->in6_daddr.s6_addr);
1124                fmt_ip6(buf,  pkt_dev->in6_daddr.s6_addr);
1125
1126                ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr);
1127
1128                if(debug) 
1129                        printk("pktgen: dst6 set to: %s\n", buf);
1130
1131                i += len;
1132                sprintf(pg_result, "OK: dst6=%s", buf);
1133                return count;
1134        }
1135        if (!strcmp(name, "dst6_min")) {
1136                len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1137                if (len < 0) return len; 
1138
1139                pkt_dev->flags |= F_IPV6;
1140
1141                if (copy_from_user(buf, &user_buffer[i], len))
1142                        return -EFAULT;
1143                buf[len] = 0;
1144
1145                scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr);
1146                fmt_ip6(buf,  pkt_dev->min_in6_daddr.s6_addr);
1147
1148                ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->min_in6_daddr);
1149                if(debug) 
1150                        printk("pktgen: dst6_min set to: %s\n", buf);
1151
1152                i += len;
1153                sprintf(pg_result, "OK: dst6_min=%s", buf);
1154                return count;
1155        }
1156        if (!strcmp(name, "dst6_max")) {
1157                len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1158                if (len < 0) return len; 
1159
1160                pkt_dev->flags |= F_IPV6;
1161
1162                if (copy_from_user(buf, &user_buffer[i], len))
1163                        return -EFAULT;
1164                buf[len] = 0;
1165
1166                scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
1167                fmt_ip6(buf,  pkt_dev->max_in6_daddr.s6_addr);
1168
1169                if(debug) 
1170                        printk("pktgen: dst6_max set to: %s\n", buf);
1171
1172                i += len;
1173                sprintf(pg_result, "OK: dst6_max=%s", buf);
1174                return count;
1175        }
1176        if (!strcmp(name, "src6")) {
1177                len = strn_len(&user_buffer[i], sizeof(buf) - 1);
1178                if (len < 0) return len; 
1179
1180                pkt_dev->flags |= F_IPV6;
1181
1182                if (copy_from_user(buf, &user_buffer[i], len))
1183                        return -EFAULT;
1184                buf[len] = 0;
1185
1186                scan_ip6(buf, pkt_dev->in6_saddr.s6_addr);
1187                fmt_ip6(buf,  pkt_dev->in6_saddr.s6_addr);
1188
1189                ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr);
1190
1191                if(debug) 
1192                        printk("pktgen: src6 set to: %s\n", buf);
1193                
1194                i += len;
1195                sprintf(pg_result, "OK: src6=%s", buf);
1196                return count;
1197        }
1198        if (!strcmp(name, "src_min")) {
1199                len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1);
1200                if (len < 0) { return len; }
1201                if (copy_from_user(buf, &user_buffer[i], len))
1202                        return -EFAULT;
1203                buf[len] = 0;
1204                if (strcmp(buf, pkt_dev->src_min) != 0) {
1205                        memset(pkt_dev->src_min, 0, sizeof(pkt_dev->src_min));
1206                        strncpy(pkt_dev->src_min, buf, len);
1207                        pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
1208                        pkt_dev->cur_saddr = pkt_dev->saddr_min;
1209                }
1210                if(debug)
1211                        printk("pktgen: src_min set to: %s\n", pkt_dev->src_min);
1212                i += len;
1213                sprintf(pg_result, "OK: src_min=%s", pkt_dev->src_min);
1214                return count;
1215        }
1216        if (!strcmp(name, "src_max")) {
1217                len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1);
1218                if (len < 0) { return len; }
1219                if (copy_from_user(buf, &user_buffer[i], len))
1220                        return -EFAULT;
1221                buf[len] = 0;
1222                if (strcmp(buf, pkt_dev->src_max) != 0) {
1223                        memset(pkt_dev->src_max, 0, sizeof(pkt_dev->src_max));
1224                        strncpy(pkt_dev->src_max, buf, len);
1225                        pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
1226                        pkt_dev->cur_saddr = pkt_dev->saddr_max;
1227                }
1228                if(debug)
1229                        printk("pktgen: src_max set to: %s\n", pkt_dev->src_max);
1230                i += len;
1231                sprintf(pg_result, "OK: src_max=%s", pkt_dev->src_max);
1232                return count;
1233        }
1234        if (!strcmp(name, "dst_mac")) {
1235                char *v = valstr;
1236                unsigned char old_dmac[6];
1237                unsigned char *m = pkt_dev->dst_mac;
1238                memcpy(old_dmac, pkt_dev->dst_mac, 6);
1239                
1240                len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1241                if (len < 0) { return len; }
1242                memset(valstr, 0, sizeof(valstr));
1243                if( copy_from_user(valstr, &user_buffer[i], len))
1244                        return -EFAULT;
1245                i += len;
1246
1247                for(*m = 0;*v && m < pkt_dev->dst_mac + 6; v++) {
1248                        if (*v >= '0' && *v <= '9') {
1249                                *m *= 16;
1250                                *m += *v - '0';
1251                        }
1252                        if (*v >= 'A' && *v <= 'F') {
1253                                *m *= 16;
1254                                *m += *v - 'A' + 10;
1255                        }
1256                        if (*v >= 'a' && *v <= 'f') {
1257                                *m *= 16;
1258                                *m += *v - 'a' + 10;
1259                        }
1260                        if (*v == ':') {
1261                                m++;
1262                                *m = 0;
1263                        }
1264                }
1265
1266                /* Set up Dest MAC */
1267                if (memcmp(old_dmac, pkt_dev->dst_mac, 6) != 0) 
1268                        memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6);
1269                
1270                sprintf(pg_result, "OK: dstmac");
1271                return count;
1272        }
1273        if (!strcmp(name, "src_mac")) {
1274                char *v = valstr;
1275                unsigned char *m = pkt_dev->src_mac;
1276
1277                len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1278                if (len < 0) { return len; }
1279                memset(valstr, 0, sizeof(valstr));
1280                if( copy_from_user(valstr, &user_buffer[i], len)) 
1281                        return -EFAULT;
1282                i += len;
1283
1284                for(*m = 0;*v && m < pkt_dev->src_mac + 6; v++) {
1285                        if (*v >= '0' && *v <= '9') {
1286                                *m *= 16;
1287                                *m += *v - '0';
1288                        }
1289                        if (*v >= 'A' && *v <= 'F') {
1290                                *m *= 16;
1291                                *m += *v - 'A' + 10;
1292                        }
1293                        if (*v >= 'a' && *v <= 'f') {
1294                                *m *= 16;
1295                                *m += *v - 'a' + 10;
1296                        }
1297                        if (*v == ':') {
1298                                m++;
1299                                *m = 0;
1300                        }
1301                }         
1302
1303                sprintf(pg_result, "OK: srcmac");
1304                return count;
1305        }
1306
1307        if (!strcmp(name, "clear_counters")) {
1308                pktgen_clear_counters(pkt_dev);
1309                sprintf(pg_result, "OK: Clearing counters.\n");
1310                return count;
1311        }
1312
1313        if (!strcmp(name, "flows")) {
1314                len = num_arg(&user_buffer[i], 10, &value);
1315                if (len < 0) { return len; }
1316                i += len;
1317                if (value > MAX_CFLOWS)
1318                        value = MAX_CFLOWS;
1319
1320                pkt_dev->cflows = value;
1321                sprintf(pg_result, "OK: flows=%u", pkt_dev->cflows);
1322                return count;
1323        }
1324
1325        if (!strcmp(name, "flowlen")) {
1326                len = num_arg(&user_buffer[i], 10, &value);
1327                if (len < 0) { return len; }
1328                i += len;
1329                pkt_dev->lflow = value;
1330                sprintf(pg_result, "OK: flowlen=%u", pkt_dev->lflow);
1331                return count;
1332        }
1333        
1334        sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
1335        return -EINVAL;
1336}
1337
1338static int proc_thread_read(char *buf , char **start, off_t offset,
1339                               int len, int *eof, void *data)
1340{
1341        char *p;
1342        struct pktgen_thread *t = (struct pktgen_thread*)(data);
1343        struct pktgen_dev *pkt_dev = NULL;
1344
1345
1346        if (!t) {
1347                printk("pktgen: ERROR: could not find thread in proc_thread_read\n");
1348                return -EINVAL;
1349        }
1350
1351        p = buf;
1352        p += sprintf(p, "Name: %s  max_before_softirq: %d\n",
1353                     t->name, t->max_before_softirq);
1354
1355        p += sprintf(p, "Running: ");
1356        
1357        if_lock(t);
1358        for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
1359                if(pkt_dev->running)
1360                        p += sprintf(p, "%s ", pkt_dev->ifname);
1361        
1362        p += sprintf(p, "\nStopped: ");
1363
1364        for(pkt_dev = t->if_list;pkt_dev; pkt_dev = pkt_dev->next) 
1365                if(!pkt_dev->running)
1366                        p += sprintf(p, "%s ", pkt_dev->ifname);
1367
1368        if (t->result[0])
1369                p += sprintf(p, "\nResult: %s\n", t->result);
1370        else
1371                p += sprintf(p, "\nResult: NA\n");
1372
1373        *eof = 1;
1374
1375        if_unlock(t);
1376
1377        return p - buf;
1378}
1379
1380static int proc_thread_write(struct file *file, const char __user *user_buffer,
1381                                unsigned long count, void *data)
1382{
1383        int i = 0, max, len, ret;
1384        char name[40];
1385        struct pktgen_thread *t;
1386        char *pg_result;
1387        unsigned long value = 0;
1388        
1389        if (count < 1) {
1390                //      sprintf(pg_result, "Wrong command format");
1391                return -EINVAL;
1392        }
1393  
1394        max = count - i;
1395        len = count_trail_chars(&user_buffer[i], max);
1396        if (len < 0) 
1397                return len; 
1398     
1399        i += len;
1400  
1401        /* Read variable name */
1402
1403        len = strn_len(&user_buffer[i], sizeof(name) - 1);
1404        if (len < 0)  
1405                return len; 
1406        
1407        memset(name, 0, sizeof(name));
1408        if (copy_from_user(name, &user_buffer[i], len))
1409                return -EFAULT;
1410        i += len;
1411  
1412        max = count -i;
1413        len = count_trail_chars(&user_buffer[i], max);
1414        if (len < 0)  
1415                return len; 
1416        
1417        i += len;
1418
1419        if (debug) 
1420                printk("pktgen: t=%s, count=%lu\n", name, count);
1421        
1422        thread_lock();
1423
1424        t = (struct pktgen_thread*)(data);
1425        if(!t) {
1426                printk("pktgen: ERROR: No thread\n");
1427                ret = -EINVAL;
1428                goto out;
1429        }
1430
1431        pg_result = &(t->result[0]);
1432
1433        if (!strcmp(name, "add_device")) {
1434                char f[32];
1435                memset(f, 0, 32);
1436                len = strn_len(&user_buffer[i], sizeof(f) - 1);
1437                if (len < 0) { 
1438                        ret = len; 
1439                        goto out;
1440                }
1441                if( copy_from_user(f, &user_buffer[i], len) )
1442                        return -EFAULT;
1443                i += len;
1444                pktgen_add_device(t, f);
1445                ret = count;
1446                sprintf(pg_result, "OK: add_device=%s", f);
1447                goto out;
1448        }
1449
1450        if (!strcmp(name, "rem_device_all")) {
1451                t->control |= T_REMDEV;
1452                current->state = TASK_INTERRUPTIBLE;
1453                schedule_timeout(HZ/8);  /* Propagate thread->control  */
1454                ret = count;
1455                sprintf(pg_result, "OK: rem_device_all");
1456                goto out;
1457        }
1458
1459
1460        if (!strcmp(name, "max_before_softirq")) {
1461                len = num_arg(&user_buffer[i], 10, &value);
1462                t->max_before_softirq = value;
1463                ret = count;
1464                sprintf(pg_result, "OK: max_before_softirq=%lu", value);
1465                goto out;
1466        }
1467
1468        ret = -EINVAL;
1469 out:
1470        thread_unlock();
1471
1472        return ret;
1473}
1474
1475static int create_proc_dir(void)
1476{
1477        int     len;
1478        /*  does proc_dir already exists */
1479        len = strlen(PG_PROC_DIR);
1480
1481        for (pg_proc_dir = proc_net->subdir; pg_proc_dir; pg_proc_dir=pg_proc_dir->next) {
1482                if ((pg_proc_dir->namelen == len) &&
1483                    (! memcmp(pg_proc_dir->name, PG_PROC_DIR, len))) 
1484                        break;
1485        }
1486        
1487        if (!pg_proc_dir) 
1488                pg_proc_dir = create_proc_entry(PG_PROC_DIR, S_IFDIR, proc_net);
1489        
1490        if (!pg_proc_dir) 
1491                return -ENODEV;
1492        
1493        return 0;
1494}
1495
1496static int remove_proc_dir(void)
1497{
1498        remove_proc_entry(PG_PROC_DIR, proc_net);
1499        return 0;
1500}
1501
1502/* Think find or remove for NN */
1503static struct pktgen_dev *__pktgen_NN_threads(const char* ifname, int remove) 
1504{
1505        struct pktgen_thread *t;
1506        struct pktgen_dev *pkt_dev = NULL;
1507
1508        t = pktgen_threads;
1509                
1510        while (t) {
1511                pkt_dev = pktgen_find_dev(t, ifname);
1512                if (pkt_dev) {
1513                                if(remove) { 
1514                                        if_lock(t);
1515                                        pktgen_remove_device(t, pkt_dev);
1516                                        if_unlock(t);
1517                                }
1518                        break;
1519                }
1520                t = t->next;
1521        }
1522        return pkt_dev;
1523}
1524
1525static struct pktgen_dev *pktgen_NN_threads(const char* ifname, int remove) 
1526{
1527        struct pktgen_dev *pkt_dev = NULL;
1528        thread_lock();
1529        pkt_dev = __pktgen_NN_threads(ifname, remove);
1530        thread_unlock();
1531        return pkt_dev;
1532}
1533
1534static int pktgen_device_event(struct notifier_block *unused, unsigned long event, void *ptr) 
1535{
1536        struct net_device *dev = (struct net_device *)(ptr);
1537
1538        /* It is OK that we do not hold the group lock right now,
1539         * as we run under the RTNL lock.
1540         */
1541
1542        switch (event) {
1543        case NETDEV_CHANGEADDR:
1544        case NETDEV_GOING_DOWN:
1545        case NETDEV_DOWN:
1546        case NETDEV_UP:
1547                /* Ignore for now */
1548                break;
1549                
1550        case NETDEV_UNREGISTER:
1551                pktgen_NN_threads(dev->name, REMOVE);
1552                break;
1553        };
1554
1555        return NOTIFY_DONE;
1556}
1557
1558/* Associate pktgen_dev with a device. */
1559
1560static struct net_device* pktgen_setup_dev(struct pktgen_dev *pkt_dev) {
1561        struct net_device *odev;
1562
1563        /* Clean old setups */
1564
1565        if (pkt_dev->odev) {
1566                dev_put(pkt_dev->odev);
1567                pkt_dev->odev = NULL;
1568        }
1569
1570        odev = dev_get_by_name(pkt_dev->ifname);
1571
1572        if (!odev) {
1573                printk("pktgen: no such netdevice: \"%s\"\n", pkt_dev->ifname);
1574                goto out;
1575        }
1576        if (odev->type != ARPHRD_ETHER) {
1577                printk("pktgen: not an ethernet device: \"%s\"\n", pkt_dev->ifname);
1578                goto out_put;
1579        }
1580        if (!netif_running(odev)) {
1581                printk("pktgen: device is down: \"%s\"\n", pkt_dev->ifname);
1582                goto out_put;
1583        }
1584        pkt_dev->odev = odev;
1585        
1586        return pkt_dev->odev;
1587
1588out_put:
1589        dev_put(odev);
1590out:
1591        return NULL;
1592
1593}
1594
1595/* Read pkt_dev from the interface and set up internal pktgen_dev
1596 * structure to have the right information to create/send packets
1597 */
1598static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
1599{
1600        /* Try once more, just in case it works now. */
1601        if (!pkt_dev->odev) 
1602                pktgen_setup_dev(pkt_dev);
1603        
1604        if (!pkt_dev->odev) {
1605                printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n");
1606                sprintf(pkt_dev->result, "ERROR: pkt_dev->odev == NULL in setup_inject.\n");
1607                return;
1608        }
1609        
1610        /* Default to the interface's mac if not explicitly set. */
1611
1612        if ((pkt_dev->src_mac[0] == 0) && 
1613            (pkt_dev->src_mac[1] == 0) && 
1614            (pkt_dev->src_mac[2] == 0) && 
1615            (pkt_dev->src_mac[3] == 0) && 
1616            (pkt_dev->src_mac[4] == 0) && 
1617            (pkt_dev->src_mac[5] == 0)) {
1618
1619               memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, 6);
1620       }
1621        /* Set up Dest MAC */
1622        memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6);
1623
1624        /* Set up pkt size */
1625        pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;
1626        
1627        if(pkt_dev->flags & F_IPV6) {
1628                /*
1629                 * Skip this automatic address setting until locks or functions 
1630                 * gets exported
1631                 */
1632
1633#ifdef NOTNOW
1634                int i, set = 0, err=1;
1635                struct inet6_dev *idev;
1636
1637                for(i=0; i< IN6_ADDR_HSIZE; i++)
1638                        if(pkt_dev->cur_in6_saddr.s6_addr[i]) {
1639                                set = 1;
1640                                break;
1641                        }
1642
1643                if(!set) {
1644                        
1645                        /*
1646                         * Use linklevel address if unconfigured.
1647                         *
1648                         * use ipv6_get_lladdr if/when it's get exported
1649                         */
1650
1651
1652                        read_lock(&addrconf_lock);
1653                        if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) {
1654                                struct inet6_ifaddr *ifp;
1655
1656                                read_lock_bh(&idev->lock);
1657                                for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) {
1658                                        if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) {
1659                                                ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &ifp->addr);
1660                                                err = 0;
1661                                                break;
1662                                        }
1663                                }
1664                                read_unlock_bh(&idev->lock);
1665                        }
1666                        read_unlock(&addrconf_lock);
1667                        if(err) printk("pktgen: ERROR: IPv6 link address not availble.\n");
1668                }
1669#endif
1670        } 
1671        else {
1672                pkt_dev->saddr_min = 0;
1673                pkt_dev->saddr_max = 0;
1674                if (strlen(pkt_dev->src_min) == 0) {
1675                        
1676                        struct in_device *in_dev; 
1677
1678                        rcu_read_lock();
1679                        in_dev = __in_dev_get(pkt_dev->odev);
1680                        if (in_dev) {
1681                                if (in_dev->ifa_list) {
1682                                        pkt_dev->saddr_min = in_dev->ifa_list->ifa_address;
1683                                        pkt_dev->saddr_max = pkt_dev->saddr_min;
1684                                }
1685                                in_dev_put(in_dev);     
1686                        }
1687                        rcu_read_unlock();
1688                }
1689                else {
1690                        pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
1691                        pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
1692                }
1693
1694                pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
1695                pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
1696        }
1697        /* Initialize current values. */
1698        pkt_dev->cur_dst_mac_offset = 0;
1699        pkt_dev->cur_src_mac_offset = 0;
1700        pkt_dev->cur_saddr = pkt_dev->saddr_min;
1701        pkt_dev->cur_daddr = pkt_dev->daddr_min;
1702        pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
1703        pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
1704        pkt_dev->nflows = 0;
1705}
1706
1707static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
1708{
1709        __u64 start;
1710        __u64 now;
1711
1712        start = now = getCurUs();
1713        printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now));
1714        while (now < spin_until_us) {
1715                /* TODO: optimise sleeping behavior */
1716                if (spin_until_us - now > (1000000/HZ)+1) {
1717                        current->state = TASK_INTERRUPTIBLE;
1718                        schedule_timeout(1);
1719                } else if (spin_until_us - now > 100) {
1720                        do_softirq();
1721                        if (!pkt_dev->running)
1722                                return;
1723                        if (need_resched())
1724                                schedule();
1725                }
1726
1727                now = getCurUs();
1728        }
1729
1730        pkt_dev->idle_acc += now - start;
1731}
1732
1733
1734/* Increment/randomize headers according to flags and current values
1735 * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
1736 */
1737static void mod_cur_headers(struct pktgen_dev *pkt_dev) {        
1738        __u32 imn;
1739        __u32 imx;
1740        int  flow = 0;
1741
1742        if(pkt_dev->cflows)  {
1743                flow = pktgen_random() % pkt_dev->cflows;
1744                
1745                if (pkt_dev->flows[flow].count > pkt_dev->lflow)
1746                        pkt_dev->flows[flow].count = 0;
1747        }                                               
1748
1749
1750        /*  Deal with source MAC */
1751        if (pkt_dev->src_mac_count > 1) {
1752                __u32 mc;
1753                __u32 tmp;
1754
1755                if (pkt_dev->flags & F_MACSRC_RND) 
1756                        mc = pktgen_random() % (pkt_dev->src_mac_count);
1757                else {
1758                        mc = pkt_dev->cur_src_mac_offset++;
1759                        if (pkt_dev->cur_src_mac_offset > pkt_dev->src_mac_count) 
1760                                pkt_dev->cur_src_mac_offset = 0;
1761                }
1762
1763                tmp = pkt_dev->src_mac[5] + (mc & 0xFF);
1764                pkt_dev->hh[11] = tmp;
1765                tmp = (pkt_dev->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
1766                pkt_dev->hh[10] = tmp;
1767                tmp = (pkt_dev->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
1768                pkt_dev->hh[9] = tmp;
1769                tmp = (pkt_dev->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
1770                pkt_dev->hh[8] = tmp;
1771                tmp = (pkt_dev->src_mac[1] + (tmp >> 8));
1772                pkt_dev->hh[7] = tmp;        
1773        }
1774
1775        /*  Deal with Destination MAC */
1776        if (pkt_dev->dst_mac_count > 1) {
1777                __u32 mc;
1778                __u32 tmp;
1779
1780                if (pkt_dev->flags & F_MACDST_RND) 
1781                        mc = pktgen_random() % (pkt_dev->dst_mac_count);
1782
1783                else {
1784                        mc = pkt_dev->cur_dst_mac_offset++;
1785                        if (pkt_dev->cur_dst_mac_offset > pkt_dev->dst_mac_count) {
1786                                pkt_dev->cur_dst_mac_offset = 0;
1787                        }
1788                }
1789
1790                tmp = pkt_dev->dst_mac[5] + (mc & 0xFF);
1791                pkt_dev->hh[5] = tmp;
1792                tmp = (pkt_dev->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
1793                pkt_dev->hh[4] = tmp;
1794                tmp = (pkt_dev->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
1795                pkt_dev->hh[3] = tmp;
1796                tmp = (pkt_dev->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
1797                pkt_dev->hh[2] = tmp;
1798                tmp = (pkt_dev->dst_mac[1] + (tmp >> 8));
1799                pkt_dev->hh[1] = tmp;        
1800        }
1801
1802        if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
1803                if (pkt_dev->flags & F_UDPSRC_RND) 
1804                        pkt_dev->cur_udp_src = ((pktgen_random() % (pkt_dev->udp_src_max - pkt_dev->udp_src_min)) + pkt_dev->udp_src_min);
1805
1806                else {
1807                        pkt_dev->cur_udp_src++;
1808                        if (pkt_dev->cur_udp_src >= pkt_dev->udp_src_max)
1809                                pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
1810                }
1811        }
1812
1813        if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {
1814                if (pkt_dev->flags & F_UDPDST_RND) {
1815                        pkt_dev->cur_udp_dst = ((pktgen_random() % (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)) + pkt_dev->udp_dst_min);
1816                }
1817                else {
1818                        pkt_dev->cur_udp_dst++;
1819                        if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max) 
1820                                pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
1821                }
1822        }
1823
1824        if (!(pkt_dev->flags & F_IPV6)) {
1825
1826                if ((imn = ntohl(pkt_dev->saddr_min)) < (imx = ntohl(pkt_dev->saddr_max))) {
1827                        __u32 t;
1828                        if (pkt_dev->flags & F_IPSRC_RND) 
1829                                t = ((pktgen_random() % (imx - imn)) + imn);
1830                        else {
1831                                t = ntohl(pkt_dev->cur_saddr);
1832                                t++;
1833                                if (t > imx) {
1834                                        t = imn;
1835                                }
1836                        }
1837                        pkt_dev->cur_saddr = htonl(t);
1838                }
1839                
1840                if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) {
1841                        pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
1842                } else {
1843
1844                        if ((imn = ntohl(pkt_dev->daddr_min)) < (imx = ntohl(pkt_dev->daddr_max))) {
1845                                __u32 t;
1846                                if (pkt_dev->flags & F_IPDST_RND) {
1847
1848                                        t = ((pktgen_random() % (imx - imn)) + imn);
1849                                        t = htonl(t);
1850
1851                                        while( LOOPBACK(t) || MULTICAST(t) || BADCLASS(t) || ZERONET(t) ||  LOCAL_MCAST(t) ) {
1852                                                t = ((pktgen_random() % (imx - imn)) + imn);
1853                                                t = htonl(t);
1854                                        }
1855                                        pkt_dev->cur_daddr = t;
1856                                }
1857                                
1858                                else {
1859                                        t = ntohl(pkt_dev->cur_daddr);
1860                                        t++;
1861                                        if (t > imx) {
1862                                                t = imn;
1863                                        }
1864                                        pkt_dev->cur_daddr = htonl(t);
1865                                }
1866                        }
1867                        if(pkt_dev->cflows) {   
1868                                pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr;
1869                                pkt_dev->nflows++;
1870                        }
1871                }
1872        }
1873        else /* IPV6 * */
1874        {
1875                if(pkt_dev->min_in6_daddr.s6_addr32[0] == 0 &&
1876                   pkt_dev->min_in6_daddr.s6_addr32[1] == 0 &&
1877                   pkt_dev->min_in6_daddr.s6_addr32[2] == 0 &&
1878                   pkt_dev->min_in6_daddr.s6_addr32[3] == 0);
1879                else {
1880                        int i;
1881
1882                        /* Only random destinations yet */
1883
1884                        for(i=0; i < 4; i++) {
1885                                pkt_dev->cur_in6_daddr.s6_addr32[i] =
1886                                        ((pktgen_random() |
1887                                          pkt_dev->min_in6_daddr.s6_addr32[i]) &
1888                                         pkt_dev->max_in6_daddr.s6_addr32[i]);
1889                        }
1890                }
1891        }
1892
1893        if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {
1894                __u32 t;
1895                if (pkt_dev->flags & F_TXSIZE_RND) {
1896                        t = ((pktgen_random() % (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size))
1897                             + pkt_dev->min_pkt_size);
1898                }
1899                else {
1900                        t = pkt_dev->cur_pkt_size + 1;
1901                        if (t > pkt_dev->max_pkt_size) 
1902                                t = pkt_dev->min_pkt_size;
1903                }
1904                pkt_dev->cur_pkt_size = t;
1905        }
1906
1907        pkt_dev->flows[flow].count++;
1908}
1909
1910
1911static struct sk_buff *fill_packet_ipv4(struct net_device *odev, 
1912                                   struct pktgen_dev *pkt_dev)
1913{
1914        struct sk_buff *skb = NULL;
1915        __u8 *eth;
1916        struct udphdr *udph;
1917        int datalen, iplen;
1918        struct iphdr *iph;
1919        struct pktgen_hdr *pgh = NULL;
1920        
1921        skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
1922        if (!skb) {
1923                sprintf(pkt_dev->result, "No memory");
1924                return NULL;
1925        }
1926
1927        skb_reserve(skb, 16);
1928
1929        /*  Reserve for ethernet and IP header  */
1930        eth = (__u8 *) skb_push(skb, 14);
1931        iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
1932        udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
1933
1934        /* Update any of the values, used when we're incrementing various
1935         * fields.
1936         */
1937        mod_cur_headers(pkt_dev);
1938
1939        memcpy(eth, pkt_dev->hh, 12);
1940        *(u16*)&eth[12] = __constant_htons(ETH_P_IP);
1941
1942        datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8; /* Eth + IPh + UDPh */
1943        if (datalen < sizeof(struct pktgen_hdr)) 
1944                datalen = sizeof(struct pktgen_hdr);
1945        
1946        udph->source = htons(pkt_dev->cur_udp_src);
1947        udph->dest = htons(pkt_dev->cur_udp_dst);
1948        udph->len = htons(datalen + 8); /* DATA + udphdr */
1949        udph->check = 0;  /* No checksum */
1950
1951        iph->ihl = 5;
1952        iph->version = 4;
1953        iph->ttl = 32;
1954        iph->tos = 0;
1955        iph->protocol = IPPROTO_UDP; /* UDP */
1956        iph->saddr = pkt_dev->cur_saddr;
1957        iph->daddr = pkt_dev->cur_daddr;
1958        iph->frag_off = 0;
1959        iplen = 20 + 8 + datalen;
1960        iph->tot_len = htons(iplen);
1961        iph->check = 0;
1962        iph->check = ip_fast_csum((void *) iph, iph->ihl);
1963        skb->protocol = __constant_htons(ETH_P_IP);
1964        skb->mac.raw = ((u8 *)iph) - 14;
1965        skb->dev = odev;
1966        skb->pkt_type = PACKET_HOST;
1967
1968        if (pkt_dev->nfrags <= 0) 
1969                pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
1970        else {
1971                int frags = pkt_dev->nfrags;
1972                int i;
1973
1974                pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8);
1975                
1976                if (frags > MAX_SKB_FRAGS)
1977                        frags = MAX_SKB_FRAGS;
1978                if (datalen > frags*PAGE_SIZE) {
1979                        skb_put(skb, datalen-frags*PAGE_SIZE);
1980                        datalen = frags*PAGE_SIZE;
1981                }
1982
1983                i = 0;
1984                while (datalen > 0) {
1985                        struct page *page = alloc_pages(GFP_KERNEL, 0);
1986                        skb_shinfo(skb)->frags[i].page = page;
1987                        skb_shinfo(skb)->frags[i].page_offset = 0;
1988                        skb_shinfo(skb)->frags[i].size =
1989                                (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
1990                        datalen -= skb_shinfo(skb)->frags[i].size;
1991                        skb->len += skb_shinfo(skb)->frags[i].size;
1992                        skb->data_len += skb_shinfo(skb)->frags[i].size;
1993                        i++;
1994                        skb_shinfo(skb)->nr_frags = i;
1995                }
1996
1997                while (i < frags) {
1998                        int rem;
1999
2000                        if (i == 0)
2001                                break;
2002
2003                        rem = skb_shinfo(skb)->frags[i - 1].size / 2;
2004                        if (rem == 0)
2005                                break;
2006
2007                        skb_shinfo(skb)->frags[i - 1].size -= rem;
2008
2009                        skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1];
2010                        get_page(skb_shinfo(skb)->frags[i].page);
2011                        skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page;
2012                        skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size;
2013                        skb_shinfo(skb)->frags[i].size = rem;
2014                        i++;
2015                        skb_shinfo(skb)->nr_frags = i;
2016                }
2017        }
2018
2019        /* Stamp the time, and sequence number, convert them to network byte order */
2020
2021        if (pgh) {
2022              struct timeval timestamp;
2023              
2024              pgh->pgh_magic = htonl(PKTGEN_MAGIC);
2025              pgh->seq_num   = htonl(pkt_dev->seq_num);
2026              
2027              do_gettimeofday(&timestamp);
2028              pgh->tv_sec    = htonl(timestamp.tv_sec);
2029              pgh->tv_usec   = htonl(timestamp.tv_usec);
2030        }
2031        pkt_dev->seq_num++;
2032        
2033        return skb;
2034}
2035
2036/*
2037 * scan_ip6, fmt_ip taken from dietlibc-0.21 
2038 * Author Felix von Leitner <felix-dietlibc@fefe.de>
2039 *
2040 * Slightly modified for kernel. 
2041 * Should be candidate for net/ipv4/utils.c
2042 * --ro
2043 */
2044
2045static unsigned int scan_ip6(const char *s,char ip[16])
2046{
2047        unsigned int i;
2048        unsigned int len=0;
2049        unsigned long u;
2050        char suffix[16];
2051        unsigned int prefixlen=0;
2052        unsigned int suffixlen=0;
2053        __u32 tmp;
2054
2055        for (i=0; i<16; i++) ip[i]=0;
2056
2057        for (;;) {
2058                if (*s == ':') {
2059                        len++;
2060                        if (s[1] == ':') {        /* Found "::", skip to part 2 */
2061                                s+=2;
2062                                len++;
2063                                break;
2064                        }
2065                        s++;
2066                }
2067                {
2068                        char *tmp;
2069                        u=simple_strtoul(s,&tmp,16);
2070                        i=tmp-s;
2071                }
2072
2073                if (!i) return 0;
2074                if (prefixlen==12 && s[i]=='.') {
2075
2076                        /* the last 4 bytes may be written as IPv4 address */
2077
2078                        tmp = in_aton(s);
2079                        memcpy((struct in_addr*)(ip+12), &tmp, sizeof(tmp));
2080                        return i+len;
2081                }
2082                ip[prefixlen++] = (u >> 8);
2083                ip[prefixlen++] = (u & 255);
2084                s += i; len += i;
2085                if (prefixlen==16)
2086                        return len;
2087        }
2088
2089/* part 2, after "::" */
2090        for (;;) {
2091                if (*s == ':') {
2092                        if (suffixlen==0)
2093                                break;
2094                        s++;
2095                        len++;
2096                } else if (suffixlen!=0)
2097                        break;
2098                {
2099                        char *tmp;
2100                        u=simple_strtol(s,&tmp,16);
2101                        i=tmp-s;
2102                }
2103                if (!i) {
2104                        if (*s) len--;
2105                        break;
2106                }
2107                if (suffixlen+prefixlen<=12 && s[i]=='.') {
2108                        tmp = in_aton(s);
2109                        memcpy((struct in_addr*)(suffix+suffixlen), &tmp, sizeof(tmp));
2110                        suffixlen+=4;
2111                        len+=strlen(s);
2112                        break;
2113                }
2114                suffix[suffixlen++] = (u >> 8);
2115                suffix[suffixlen++] = (u & 255);
2116                s += i; len += i;
2117                if (prefixlen+suffixlen==16)
2118                        break;
2119        }
2120        for (i=0; i<suffixlen; i++)
2121                ip[16-suffixlen+i] = suffix[i];
2122        return len;
2123}
2124
2125static char tohex(char hexdigit) {
2126        return hexdigit>9?hexdigit+'a'-10:hexdigit+'0';
2127}
2128
2129static int fmt_xlong(char* s,unsigned int i) {
2130        char* bak=s;
2131        *s=tohex((i>>12)&0xf); if (s!=bak || *s!='0') ++s;
2132        *s=tohex((i>>8)&0xf); if (s!=bak || *s!='0') ++s;
2133        *s=tohex((i>>4)&0xf); if (s!=bak || *s!='0') ++s;
2134        *s=tohex(i&0xf);
2135        return s-bak+1;
2136}
2137
2138static unsigned int fmt_ip6(char *s,const char ip[16]) {
2139        unsigned int len;
2140        unsigned int i;
2141        unsigned int temp;
2142        unsigned int compressing;
2143        int j;
2144
2145        len = 0; compressing = 0;
2146        for (j=0; j<16; j+=2) {
2147
2148#ifdef V4MAPPEDPREFIX
2149                if (j==12 && !memcmp(ip,V4mappedprefix,12)) {
2150                        inet_ntoa_r(*(struct in_addr*)(ip+12),s);
2151                        temp=strlen(s);
2152                        return len+temp;
2153                }
2154#endif
2155                temp = ((unsigned long) (unsigned char) ip[j] << 8) +
2156                        (unsigned long) (unsigned char) ip[j+1];
2157                if (temp == 0) {
2158                        if (!compressing) {
2159                                compressing=1;
2160                                if (j==0) {
2161                                        *s++=':'; ++len;
2162                                }
2163                        }
2164                } else {
2165                        if (compressing) {
2166                                compressing=0;
2167                                *s++=':'; ++len;
2168                        }
2169                        i = fmt_xlong(s,temp); len += i; s += i;
2170                        if (j<14) {
2171                                *s++ = ':';
2172                                ++len;
2173                        }
2174                }
2175        }
2176        if (compressing) {
2177                *s++=':'; ++len;
2178        }
2179        *s=0;
2180        return len;
2181}
2182
2183static struct sk_buff *fill_packet_ipv6(struct net_device *odev, 
2184                                   struct pktgen_dev *pkt_dev)
2185{
2186        struct sk_buff *skb = NULL;
2187        __u8 *eth;
2188        struct udphdr *udph;
2189        int datalen;
2190        struct ipv6hdr *iph;
2191        struct pktgen_hdr *pgh = NULL;
2192        
2193        skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
2194        if (!skb) {
2195                sprintf(pkt_dev->result, "No memory");
2196                return NULL;
2197        }
2198
2199        skb_reserve(skb, 16);
2200
2201        /*  Reserve for ethernet and IP header  */
2202        eth = (__u8 *) skb_push(skb, 14);
2203        iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
2204        udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
2205
2206
2207        /* Update any of the values, used when we're incrementing various
2208         * fields.
2209         */
2210        mod_cur_headers(pkt_dev);
2211
2212        
2213        memcpy(eth, pkt_dev->hh, 12);
2214        *(u16*)&eth[12] = __constant_htons(ETH_P_IPV6);
2215        
2216        
2217        datalen = pkt_dev->cur_pkt_size-14- 
2218                sizeof(struct ipv6hdr)-sizeof(struct udphdr); /* Eth + IPh + UDPh */
2219
2220        if (datalen < sizeof(struct pktgen_hdr)) { 
2221                datalen = sizeof(struct pktgen_hdr);
2222                if (net_ratelimit())
2223                        printk(KERN_INFO "pktgen: increased datalen to %d\n", datalen);
2224        }
2225
2226        udph->source = htons(pkt_dev->cur_udp_src);
2227        udph->dest = htons(pkt_dev->cur_udp_dst);
2228        udph->len = htons(datalen + sizeof(struct udphdr)); 
2229        udph->check = 0;  /* No checksum */
2230
2231         *(u32*)iph = __constant_htonl(0x60000000); /* Version + flow */
2232
2233        iph->hop_limit = 32;
2234
2235        iph->payload_len = htons(sizeof(struct udphdr) + datalen);
2236        iph->nexthdr = IPPROTO_UDP;
2237
2238        ipv6_addr_copy(&iph->daddr, &pkt_dev->cur_in6_daddr);
2239        ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
2240
2241        skb->mac.raw = ((u8 *)iph) - 14;
2242        skb->protocol = __constant_htons(ETH_P_IPV6);
2243        skb->dev = odev;
2244        skb->pkt_type = PACKET_HOST;
2245
2246        if (pkt_dev->nfrags <= 0) 
2247                pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
2248        else {
2249                int frags = pkt_dev->nfrags;
2250                int i;
2251
2252                pgh = (struct pktgen_hdr*)(((char*)(udph)) + 8);
2253                
2254                if (frags > MAX_SKB_FRAGS)
2255                        frags = MAX_SKB_FRAGS;
2256                if (datalen > frags*PAGE_SIZE) {
2257                        skb_put(skb, datalen-frags*PAGE_SIZE);
2258                        datalen = frags*PAGE_SIZE;
2259                }
2260
2261                i = 0;
2262                while (datalen > 0) {
2263                        struct page *page = alloc_pages(GFP_KERNEL, 0);
2264                        skb_shinfo(skb)->frags[i].page = page;
2265                        skb_shinfo(skb)->frags[i].page_offset = 0;
2266                        skb_shinfo(skb)->frags[i].size =
2267                                (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
2268                        datalen -= skb_shinfo(skb)->frags[i].size;
2269                        skb->len += skb_shinfo(skb)->frags[i].size;
2270                        skb->data_len += skb_shinfo(skb)->frags[i].size;
2271                        i++;
2272                        skb_shinfo(skb)->nr_frags = i;
2273                }
2274
2275                while (i < frags) {
2276                        int rem;
2277
2278                        if (i == 0)
2279                                break;
2280
2281                        rem = skb_shinfo(skb)->frags[i - 1].size / 2;
2282                        if (rem == 0)
2283                                break;
2284
2285                        skb_shinfo(skb)->frags[i - 1].size -= rem;
2286
2287                        skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i - 1];
2288                        get_page(skb_shinfo(skb)->frags[i].page);
2289                        skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i - 1].page;
2290                        skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i - 1].size;
2291                        skb_shinfo(skb)->frags[i].size = rem;
2292                        i++;
2293                        skb_shinfo(skb)->nr_frags = i;
2294                }
2295        }
2296
2297        /* Stamp the time, and sequence number, convert them to network byte order */
2298        /* should we update cloned packets too ? */
2299        if (pgh) {
2300              struct timeval timestamp;
2301              
2302              pgh->pgh_magic = htonl(PKTGEN_MAGIC);
2303              pgh->seq_num   = htonl(pkt_dev->seq_num);
2304              
2305              do_gettimeofday(&timestamp);
2306              pgh->tv_sec    = htonl(timestamp.tv_sec);
2307              pgh->tv_usec   = htonl(timestamp.tv_usec);
2308        }
2309        pkt_dev->seq_num++;
2310        
2311        return skb;
2312}
2313
2314static inline struct sk_buff *fill_packet(struct net_device *odev, 
2315                                   struct pktgen_dev *pkt_dev)
2316{
2317        if(pkt_dev->flags & F_IPV6) 
2318                return fill_packet_ipv6(odev, pkt_dev);
2319        else
2320                return fill_packet_ipv4(odev, pkt_dev);
2321}
2322
2323static void pktgen_clear_counters(struct pktgen_dev *pkt_dev) 
2324{
2325        pkt_dev->seq_num = 1;
2326        pkt_dev->idle_acc = 0;
2327        pkt_dev->sofar = 0;
2328        pkt_dev->tx_bytes = 0;
2329        pkt_dev->errors = 0;
2330}
2331
2332/* Set up structure for sending pkts, clear counters */
2333
2334static void pktgen_run(struct pktgen_thread *t)
2335{
2336        struct pktgen_dev *pkt_dev = NULL;
2337        int started = 0;
2338
2339        PG_DEBUG(printk("pktgen: entering pktgen_run. %p\n", t));
2340
2341        if_lock(t);
2342        for (pkt_dev = t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
2343
2344                /*
2345                 * setup odev and create initial packet.
2346                 */
2347                pktgen_setup_inject(pkt_dev);
2348
2349                if(pkt_dev->odev) { 
2350                        pktgen_clear_counters(pkt_dev);
2351                        pkt_dev->running = 1; /* Cranke yeself! */
2352                        pkt_dev->skb = NULL;
2353                        pkt_dev->started_at = getCurUs();
2354                        pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */
2355                        pkt_dev->next_tx_ns = 0;
2356                        
2357                        strcpy(pkt_dev->result, "Starting");
2358                        started++;
2359                }
2360                else 
2361                        strcpy(pkt_dev->result, "Error starting");
2362        }
2363        if_unlock(t);
2364        if(started) t->control &= ~(T_STOP);
2365}
2366
2367static void pktgen_stop_all_threads_ifs(void)
2368{
2369        struct pktgen_thread *t = pktgen_threads;
2370
2371        PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads.\n"));
2372
2373        thread_lock();
2374        while(t) {
2375                pktgen_stop(t);
2376                t = t->next;
2377        }
2378       thread_unlock();
2379}
2380
2381static int thread_is_running(struct pktgen_thread *t )
2382{
2383        struct pktgen_dev *next;
2384        int res = 0;
2385
2386        for(next=t->if_list; next; next=next->next) { 
2387                if(next->running) {
2388                        res = 1;
2389                        break;
2390                }
2391        }
2392        return res;
2393}
2394
2395static int pktgen_wait_thread_run(struct pktgen_thread *t )
2396{
2397        if_lock(t);
2398
2399        while(thread_is_running(t)) {
2400
2401                if_unlock(t);
2402
2403                msleep_interruptible(100); 
2404
2405                if (signal_pending(current)) 
2406                        goto signal;
2407                if_lock(t);
2408        }
2409        if_unlock(t);
2410        return 1;
2411 signal:
2412        return 0;
2413}
2414
2415static int pktgen_wait_all_threads_run(void)
2416{
2417        struct pktgen_thread *t = pktgen_threads;
2418        int sig = 1;
2419        
2420        while (t) {
2421                sig = pktgen_wait_thread_run(t);
2422                if( sig == 0 ) break;
2423                thread_lock();
2424                t=t->next;
2425                thread_unlock();
2426        }
2427        if(sig == 0) {
2428                thread_lock();
2429                while (t) {
2430                        t->control |= (T_STOP);
2431                        t=t->next;
2432                }
2433                thread_unlock();
2434        }
2435        return sig;
2436}
2437
2438static void pktgen_run_all_threads(void)
2439{
2440        struct pktgen_thread *t = pktgen_threads;
2441
2442        PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n"));
2443
2444        thread_lock();
2445
2446        while(t) {
2447                t->control |= (T_RUN);
2448                t = t->next;
2449        }
2450        thread_unlock();
2451
2452        current->state = TASK_INTERRUPTIBLE;
2453        schedule_timeout(HZ/8);  /* Propagate thread->control  */
2454                        
2455        pktgen_wait_all_threads_run();
2456}
2457
2458
2459static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
2460{
2461       __u64 total_us, bps, mbps, pps, idle;
2462       char *p = pkt_dev->result;
2463
2464       total_us = pkt_dev->stopped_at - pkt_dev->started_at;
2465
2466       idle = pkt_dev->idle_acc;
2467
2468       p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n",
2469                    (unsigned long long) total_us, 
2470                    (unsigned long long)(total_us - idle), 
2471                    (unsigned long long) idle,
2472                    (unsigned long long) pkt_dev->sofar, 
2473                    pkt_dev->cur_pkt_size, nr_frags);
2474
2475       pps = pkt_dev->sofar * USEC_PER_SEC;
2476
2477       while ((total_us >> 32) != 0) {
2478               pps >>= 1;
2479               total_us >>= 1;
2480       }
2481
2482       do_div(pps, total_us);
2483       
2484       bps = pps * 8 * pkt_dev->cur_pkt_size;
2485
2486       mbps = bps;
2487       do_div(mbps, 1000000);
2488       p += sprintf(p, "  %llupps %lluMb/sec (%llubps) errors: %llu",
2489                    (unsigned long long) pps, 
2490                    (unsigned long long) mbps, 
2491                    (unsigned long long) bps, 
2492                    (unsigned long long) pkt_dev->errors);
2493}
2494 
2495
2496/* Set stopped-at timer, remove from running list, do counters & statistics */
2497
2498static int pktgen_stop_device(struct pktgen_dev *pkt_dev) 
2499{
2500        
2501        if (!pkt_dev->running) {
2502                printk("pktgen: interface: %s is already stopped\n", pkt_dev->ifname);
2503                return -EINVAL;
2504        }
2505
2506        pkt_dev->stopped_at = getCurUs();
2507        pkt_dev->running = 0;
2508
2509        show_results(pkt_dev, skb_shinfo(pkt_dev->skb)->nr_frags);
2510
2511        if (pkt_dev->skb) 
2512                kfree_skb(pkt_dev->skb);
2513
2514        pkt_dev->skb = NULL;
2515        
2516        return 0;
2517}
2518
2519static struct pktgen_dev *next_to_run(struct pktgen_thread *t )
2520{
2521        struct pktgen_dev *next, *best = NULL;
2522        
2523        if_lock(t);
2524
2525        for(next=t->if_list; next ; next=next->next) {
2526                if(!next->running) continue;
2527                if(best == NULL) best=next;
2528                else if ( next->next_tx_us < best->next_tx_us) 
2529                        best =  next;
2530        }
2531        if_unlock(t);
2532        return best;
2533}
2534
2535static void pktgen_stop(struct pktgen_thread *t) {
2536        struct pktgen_dev *next = NULL;
2537
2538        PG_DEBUG(printk("pktgen: entering pktgen_stop.\n"));
2539
2540        if_lock(t);
2541
2542        for(next=t->if_list; next; next=next->next)
2543                pktgen_stop_device(next);
2544
2545        if_unlock(t);
2546}
2547
2548static void pktgen_rem_all_ifs(struct pktgen_thread *t) 
2549{
2550        struct pktgen_dev *cur, *next = NULL;
2551        
2552        /* Remove all devices, free mem */
2553 
2554        if_lock(t);
2555
2556        for(cur=t->if_list; cur; cur=next) { 
2557                next = cur->next;
2558                pktgen_remove_device(t, cur);
2559        }
2560
2561        if_unlock(t);
2562}
2563
2564static void pktgen_rem_thread(struct pktgen_thread *t) 
2565{
2566        /* Remove from the thread list */
2567
2568        struct pktgen_thread *tmp = pktgen_threads;
2569
2570        if (strlen(t->fname))
2571                remove_proc_entry(t->fname, NULL);
2572
2573       thread_lock();
2574
2575        if (tmp == t)
2576                pktgen_threads = tmp->next;
2577        else {
2578                while (tmp) {
2579                        if (tmp->next == t) {
2580                                tmp->next = t->next;
2581                                t->next = NULL;
2582                                break;
2583                        }
2584                        tmp = tmp->next;
2585                }
2586        }
2587        thread_unlock();
2588}
2589
2590__inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
2591{
2592        struct net_device *odev = NULL;
2593        __u64 idle_start = 0;
2594        int ret;
2595
2596        odev = pkt_dev->odev;
2597        
2598        if (pkt_dev->delay_us || pkt_dev->delay_ns) {
2599                u64 now;
2600
2601                now = getCurUs();
2602                if (now < pkt_dev->next_tx_us)
2603                        spin(pkt_dev, pkt_dev->next_tx_us);
2604
2605                /* This is max DELAY, this has special meaning of
2606                 * "never transmit"
2607                 */
2608                if (pkt_dev->delay_us == 0x7FFFFFFF) {
2609                        pkt_dev->next_tx_us = getCurUs() + pkt_dev->delay_us;
2610                        pkt_dev->next_tx_ns = pkt_dev->delay_ns;
2611                        goto out;
2612                }
2613        }
2614        
2615        if (netif_queue_stopped(odev) || need_resched()) {
2616                idle_start = getCurUs();
2617                
2618                if (!netif_running(odev)) {
2619                        pktgen_stop_device(pkt_dev);
2620                        goto out;
2621                }
2622                if (need_resched()) 
2623                        schedule();
2624                
2625                pkt_dev->idle_acc += getCurUs() - idle_start;
2626                
2627                if (netif_queue_stopped(odev)) {
2628                        pkt_dev->next_tx_us = getCurUs(); /* TODO */
2629                        pkt_dev->next_tx_ns = 0;
2630                        goto out; /* Try the next interface */
2631                }
2632        }
2633        
2634        if (pkt_dev->last_ok || !pkt_dev->skb) {
2635                if ((++pkt_dev->clone_count >= pkt_dev->clone_skb ) || (!pkt_dev->skb)) {
2636                        /* build a new pkt */
2637                        if (pkt_dev->skb) 
2638                                kfree_skb(pkt_dev->skb);
2639                        
2640                        pkt_dev->skb = fill_packet(odev, pkt_dev);
2641                        if (pkt_dev->skb == NULL) {
2642                                printk("pktgen: ERROR: couldn't allocate skb in fill_packet.\n");
2643                                schedule();
2644                                pkt_dev->clone_count--; /* back out increment, OOM */
2645                                goto out;
2646                        }
2647                        pkt_dev->allocated_skbs++;
2648                        pkt_dev->clone_count = 0; /* reset counter */
2649                }
2650        }
2651        
2652        spin_lock_bh(&odev->xmit_lock);
2653        if (!netif_queue_stopped(odev)) {
2654                u64 now;
2655
2656                atomic_inc(&(pkt_dev->skb->users));
2657retry_now:
2658                ret = odev->hard_start_xmit(pkt_dev->skb, odev);
2659                if (likely(ret == NETDEV_TX_OK)) {
2660                        pkt_dev->last_ok = 1;    
2661                        pkt_dev->sofar++;
2662                        pkt_dev->seq_num++;
2663                        pkt_dev->tx_bytes += pkt_dev->cur_pkt_size;
2664                        
2665                } else if (ret == NETDEV_TX_LOCKED 
2666                           && (odev->features & NETIF_F_LLTX)) {
2667                        cpu_relax();
2668                        goto retry_now;
2669                } else {  /* Retry it next time */
2670                        
2671                        atomic_dec(&(pkt_dev->skb->users));
2672                        
2673                        if (debug && net_ratelimit())
2674                                printk(KERN_INFO "pktgen: Hard xmit error\n");
2675                        
2676                        pkt_dev->errors++;
2677                        pkt_dev->last_ok = 0;
2678                        pkt_dev->next_tx_us = getCurUs(); /* TODO */
2679                        pkt_dev->next_tx_ns = 0;
2680                }
2681
2682                pkt_dev->next_tx_us += pkt_dev->delay_us;
2683                pkt_dev->next_tx_ns += pkt_dev->delay_ns;
2684                if (pkt_dev->next_tx_ns > 1000) {
2685                        pkt_dev->next_tx_us++;
2686                        pkt_dev->next_tx_ns -= 1000;
2687                }
2688
2689                now = getCurUs();
2690                if (now > pkt_dev->next_tx_us) {
2691                        /* TODO: this code is slightly wonky.  */
2692                        pkt_dev->errors++;
2693                        pkt_dev->next_tx_us = now - pkt_dev->delay_us;
2694                        pkt_dev->next_tx_ns = 0;
2695                }
2696        } 
2697
2698        else {  /* Retry it next time */
2699                pkt_dev->last_ok = 0;
2700                pkt_dev->next_tx_us = getCurUs(); /* TODO */
2701                pkt_dev->next_tx_ns = 0;
2702        }
2703
2704        spin_unlock_bh(&odev->xmit_lock);
2705        
2706        /* If pkt_dev->count is zero, then run forever */
2707        if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
2708                if (atomic_read(&(pkt_dev->skb->users)) != 1) {
2709                        idle_start = getCurUs();
2710                        while (atomic_read(&(pkt_dev->skb->users)) != 1) {
2711                                if (signal_pending(current)) {
2712                                        break;
2713                                }
2714                                schedule();
2715                        }
2716                        pkt_dev->idle_acc += getCurUs() - idle_start;
2717                }
2718                
2719                /* Done with this */
2720                pktgen_stop_device(pkt_dev);
2721        } 
2722 out:;
2723 }
2724
2725/* 
2726 * Main loop of the thread goes here
2727 */
2728
2729static void pktgen_thread_worker(struct pktgen_thread *t) 
2730{
2731        DEFINE_WAIT(wait);
2732        struct pktgen_dev *pkt_dev = NULL;
2733        int cpu = t->cpu;
2734        sigset_t tmpsig;
2735        u32 max_before_softirq;
2736        u32 tx_since_softirq = 0;
2737
2738        daemonize("pktgen/%d", cpu);
2739
2740        /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */
2741
2742        spin_lock_irq(&current->sighand->siglock);
2743        tmpsig = current->blocked;
2744        siginitsetinv(&current->blocked, 
2745                      sigmask(SIGKILL) | 
2746                      sigmask(SIGSTOP)| 
2747                      sigmask(SIGTERM));
2748
2749        recalc_sigpending();
2750        spin_unlock_irq(&current->sighand->siglock);
2751
2752        /* Migrate to the right CPU */
2753        set_cpus_allowed(current, cpumask_of_cpu(cpu));
2754        if (smp_processor_id() != cpu)
2755                BUG();
2756
2757        init_waitqueue_head(&t->queue);
2758
2759        t->control &= ~(T_TERMINATE);
2760        t->control &= ~(T_RUN);
2761        t->control &= ~(T_STOP);
2762        t->control &= ~(T_REMDEV);
2763
2764        t->pid = current->pid;        
2765
2766        PG_DEBUG(printk("pktgen: starting pktgen/%d:  pid=%d\n", cpu, current->pid));
2767
2768        max_before_softirq = t->max_before_softirq;
2769        
2770        __set_current_state(TASK_INTERRUPTIBLE);
2771        mb();
2772
2773        while (1) {
2774                
2775                __set_current_state(TASK_RUNNING);
2776
2777                /*
2778                 * Get next dev to xmit -- if any.
2779                 */
2780
2781                pkt_dev = next_to_run(t);
2782                
2783                if (pkt_dev) {
2784
2785                        pktgen_xmit(pkt_dev);
2786
2787                        /*
2788                         * We like to stay RUNNING but must also give
2789                         * others fair share.
2790                         */
2791
2792                        tx_since_softirq += pkt_dev->last_ok;
2793
2794                        if (tx_since_softirq > max_before_softirq) {
2795                                if (local_softirq_pending())
2796                                        do_softirq();
2797                                tx_since_softirq = 0;
2798                        }
2799                } else {
2800                        prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE);
2801                        schedule_timeout(HZ/10);
2802                        finish_wait(&(t->queue), &wait);
2803                }
2804
2805                /* 
2806                 * Back from sleep, either due to the timeout or signal.
2807                 * We check if we have any "posted" work for us.
2808                 */
2809
2810                if (t->control & T_TERMINATE || signal_pending(current)) 
2811                        /* we received a request to terminate ourself */
2812                        break;
2813                
2814
2815                if(t->control & T_STOP) {
2816                        pktgen_stop(t);
2817                        t->control &= ~(T_STOP);
2818                }
2819
2820                if(t->control & T_RUN) {
2821                        pktgen_run(t);
2822                        t->control &= ~(T_RUN);
2823                }
2824
2825                if(t->control & T_REMDEV) {
2826                        pktgen_rem_all_ifs(t);
2827                        t->control &= ~(T_REMDEV);
2828                }
2829
2830                if (need_resched()) 
2831                        schedule();
2832        } 
2833
2834        PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name));
2835        pktgen_stop(t);
2836
2837        PG_DEBUG(printk("pktgen: %s removing all device\n", t->name));
2838        pktgen_rem_all_ifs(t);
2839
2840        PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
2841        pktgen_rem_thread(t);
2842}
2843
2844static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, const char* ifname) 
2845{
2846        struct pktgen_dev *pkt_dev = NULL;
2847        if_lock(t);
2848
2849        for(pkt_dev=t->if_list; pkt_dev; pkt_dev = pkt_dev->next ) {
2850                if (strcmp(pkt_dev->ifname, ifname) == 0) {
2851                        break;
2852                }
2853        }
2854
2855        if_unlock(t);
2856        PG_DEBUG(printk("pktgen: find_dev(%s) returning %p\n", ifname,pkt_dev));
2857        return pkt_dev;
2858}
2859
2860/* 
2861 * Adds a dev at front of if_list. 
2862 */
2863
2864static int add_dev_to_thread(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 
2865{
2866        int rv = 0;
2867        
2868        if_lock(t);
2869
2870        if (pkt_dev->pg_thread) {
2871                printk("pktgen: ERROR:  already assigned to a thread.\n");
2872                rv = -EBUSY;
2873                goto out;
2874        }
2875        pkt_dev->next =t->if_list; t->if_list=pkt_dev;
2876        pkt_dev->pg_thread = t;
2877        pkt_dev->running = 0;
2878
2879 out:
2880        if_unlock(t);        
2881        return rv;
2882}
2883
2884/* Called under thread lock */
2885
2886static int pktgen_add_device(struct pktgen_thread *t, const char* ifname) 
2887{
2888        struct pktgen_dev *pkt_dev;
2889        
2890        /* We don't allow a device to be on several threads */
2891
2892        if( (pkt_dev = __pktgen_NN_threads(ifname, FIND)) == NULL) {
2893                                                   
2894                pkt_dev = kmalloc(sizeof(struct pktgen_dev), GFP_KERNEL);
2895                if (!pkt_dev) 
2896                        return -ENOMEM;
2897
2898                memset(pkt_dev, 0, sizeof(struct pktgen_dev));
2899
2900                pkt_dev->flows = vmalloc(MAX_CFLOWS*sizeof(struct flow_state));
2901                if (pkt_dev->flows == NULL) {
2902                        kfree(pkt_dev);
2903                        return -ENOMEM;
2904                }
2905                memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state));
2906
2907                pkt_dev->min_pkt_size = ETH_ZLEN;
2908                pkt_dev->max_pkt_size = ETH_ZLEN;
2909                pkt_dev->nfrags = 0;
2910                pkt_dev->clone_skb = pg_clone_skb_d;
2911                pkt_dev->delay_us = pg_delay_d / 1000;
2912                pkt_dev->delay_ns = pg_delay_d % 1000;
2913                pkt_dev->count = pg_count_d;
2914                pkt_dev->sofar = 0;
2915                pkt_dev->udp_src_min = 9; /* sink port */
2916                pkt_dev->udp_src_max = 9;
2917                pkt_dev->udp_dst_min = 9;
2918                pkt_dev->udp_dst_max = 9;
2919
2920                strncpy(pkt_dev->ifname, ifname, 31);
2921                sprintf(pkt_dev->fname, "net/%s/%s", PG_PROC_DIR, ifname);
2922
2923                if (! pktgen_setup_dev(pkt_dev)) {
2924                        printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
2925                        if (pkt_dev->flows)
2926                                vfree(pkt_dev->flows);
2927                        kfree(pkt_dev);
2928                        return -ENODEV;
2929                }
2930
2931                pkt_dev->proc_ent = create_proc_entry(pkt_dev->fname, 0600, NULL);
2932                if (!pkt_dev->proc_ent) {
2933                        printk("pktgen: cannot create %s procfs entry.\n", pkt_dev->fname);
2934                        if (pkt_dev->flows)
2935                                vfree(pkt_dev->flows);
2936                        kfree(pkt_dev);
2937                        return -EINVAL;
2938                }
2939                pkt_dev->proc_ent->read_proc = proc_if_read;
2940                pkt_dev->proc_ent->write_proc = proc_if_write;
2941                pkt_dev->proc_ent->data = (void*)(pkt_dev);
2942                pkt_dev->proc_ent->owner = THIS_MODULE;
2943
2944                return add_dev_to_thread(t, pkt_dev);
2945        }
2946        else {
2947                printk("pktgen: ERROR: interface already used.\n");
2948                return -EBUSY;
2949        }
2950}
2951
2952static struct pktgen_thread *pktgen_find_thread(const char* name) 
2953{
2954        struct pktgen_thread *t = NULL;
2955
2956       thread_lock();
2957
2958        t = pktgen_threads;
2959        while (t) {
2960                if (strcmp(t->name, name) == 0) 
2961                        break;
2962
2963                t = t->next;
2964        }
2965        thread_unlock();
2966        return t;
2967}
2968
2969static int pktgen_create_thread(const char* name, int cpu) 
2970{
2971        struct pktgen_thread *t = NULL;
2972
2973        if (strlen(name) > 31) {
2974                printk("pktgen: ERROR:  Thread name cannot be more than 31 characters.\n");
2975                return -EINVAL;
2976        }
2977        
2978        if (pktgen_find_thread(name)) {
2979                printk("pktgen: ERROR: thread: %s already exists\n", name);
2980                return -EINVAL;
2981        }
2982
2983        t = (struct pktgen_thread*)(kmalloc(sizeof(struct pktgen_thread), GFP_KERNEL));
2984        if (!t) {
2985                printk("pktgen: ERROR: out of memory, can't create new thread.\n");
2986                return -ENOMEM;
2987        }
2988
2989        memset(t, 0, sizeof(struct pktgen_thread));
2990        strcpy(t->name, name);
2991        spin_lock_init(&t->if_lock);
2992        t->cpu = cpu;
2993        
2994        sprintf(t->fname, "net/%s/%s", PG_PROC_DIR, t->name);
2995        t->proc_ent = create_proc_entry(t->fname, 0600, NULL);
2996        if (!t->proc_ent) {
2997                printk("pktgen: cannot create %s procfs entry.\n", t->fname);
2998                kfree(t);
2999                return -EINVAL;
3000        }
3001        t->proc_ent->read_proc = proc_thread_read;
3002        t->proc_ent->write_proc = proc_thread_write;
3003        t->proc_ent->data = (void*)(t);
3004        t->proc_ent->owner = THIS_MODULE;
3005
3006        t->next = pktgen_threads;
3007        pktgen_threads = t;
3008
3009        if (kernel_thread((void *) pktgen_thread_worker, (void *) t, 
3010                          CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0)
3011                printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
3012
3013        return 0;
3014}
3015
3016/* 
3017 * Removes a device from the thread if_list. 
3018 */
3019static void _rem_dev_from_if_list(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 
3020{
3021        struct pktgen_dev *i, *prev = NULL;
3022
3023        i = t->if_list;
3024
3025        while(i) {
3026                if(i == pkt_dev) {
3027                        if(prev) prev->next = i->next;
3028                        else t->if_list = NULL;
3029                        break;
3030                }
3031                prev = i;
3032                i=i->next;
3033        }
3034}
3035
3036static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *pkt_dev) 
3037{
3038
3039        PG_DEBUG(printk("pktgen: remove_device pkt_dev=%p\n", pkt_dev));
3040
3041        if (pkt_dev->running) { 
3042                printk("pktgen:WARNING: trying to remove a running interface, stopping it now.\n");
3043                pktgen_stop_device(pkt_dev);
3044        }
3045        
3046        /* Dis-associate from the interface */
3047
3048        if (pkt_dev->odev) {
3049                dev_put(pkt_dev->odev);
3050                pkt_dev->odev = NULL;
3051        }
3052        
3053        /* And update the thread if_list */
3054
3055        _rem_dev_from_if_list(t, pkt_dev);
3056
3057        /* Clean up proc file system */
3058
3059        if (strlen(pkt_dev->fname)) 
3060                remove_proc_entry(pkt_dev->fname, NULL);
3061
3062        if (pkt_dev->flows)
3063                vfree(pkt_dev->flows);
3064        kfree(pkt_dev);
3065        return 0;
3066}
3067
3068static int __init pg_init(void) 
3069{
3070        int cpu;
3071        printk(version);
3072
3073        module_fname[0] = 0;
3074
3075        create_proc_dir();
3076
3077        sprintf(module_fname, "net/%s/pgctrl", PG_PROC_DIR);
3078        module_proc_ent = create_proc_entry(module_fname, 0600, NULL);
3079        if (!module_proc_ent) {
3080                printk("pktgen: ERROR: cannot create %s procfs entry.\n", module_fname);
3081                return -EINVAL;
3082        }
3083
3084        module_proc_ent->proc_fops =  &pktgen_fops;
3085        module_proc_ent->data = NULL;
3086
3087        /* Register us to receive netdevice events */
3088        register_netdevice_notifier(&pktgen_notifier_block);
3089        
3090        for (cpu = 0; cpu < NR_CPUS ; cpu++) {
3091                char buf[30];
3092
3093                if (!cpu_online(cpu))
3094                        continue;
3095
3096                sprintf(buf, "kpktgend_%i", cpu);
3097                pktgen_create_thread(buf, cpu);
3098        }
3099        return 0;        
3100}
3101
3102static void __exit pg_cleanup(void)
3103{
3104        wait_queue_head_t queue;
3105        init_waitqueue_head(&queue);
3106
3107        /* Stop all interfaces & threads */        
3108
3109        while (pktgen_threads) {
3110                struct pktgen_thread *t = pktgen_threads;
3111                pktgen_threads->control |= (T_TERMINATE);
3112
3113                wait_event_interruptible_timeout(queue, (t != pktgen_threads), HZ);
3114        }
3115
3116        /* Un-register us from receiving netdevice events */
3117        unregister_netdevice_notifier(&pktgen_notifier_block);
3118
3119        /* Clean up proc file system */
3120
3121        remove_proc_entry(module_fname, NULL);
3122        
3123        remove_proc_dir();
3124}
3125
3126
3127module_init(pg_init);
3128module_exit(pg_cleanup);
3129
3130MODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se");
3131MODULE_DESCRIPTION("Packet Generator tool");
3132MODULE_LICENSE("GPL");
3133module_param(pg_count_d, int, 0);
3134module_param(pg_delay_d, int, 0);
3135module_param(pg_clone_skb_d, int, 0);
3136module_param(debug, int, 0);
3137
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.