OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [core/] [pktgen.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.