1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* pg3.c: Packet Generator for packet performance testing.
2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Copyright 2001 by Robert Olsson <robert.olsson@its.uu.se>
4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *                                 Uppsala University, Sweden
5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * This program is free software; you can redistribute it and/or modify
7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * it under the terms of the GNU General Public License as published by
8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * the Free Software Foundation; either version 2 of the License, or
9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * (at your option) any later version.
10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
16313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiA tool for loading a network with a preconfigurated packets. The tool is
18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiimplemented as a linux module. Parameters as output device IPG interpacket
19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittipacket, number of packets can be configured. pg uses already intalled
20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittidevice driver output routine.
21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiAdditional hacking by:
24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiJens.Laas@data.slu.se
26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiImproved by ANK. 010120.
27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiImproved by ANK even more. 010212.
28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiMAC address typo fixed. 010417 --ro
29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiTODO:
32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti* could release kernel lock yet.
33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiHOWTO:
36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti1. Compile module pg3.o and install it in the place where modprobe may find it.
38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti2. Cut script "ipg" (see below).
39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti3. Edit script to set preferred device and destination IP address.
40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti4. . ipg
41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti5. After this two commands are defined:
42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti   A. "pg" to start generator and to get results.
43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti   B. "pgset" to change generator parameters. F.e.
44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti      pgset "pkt_size 9014"   sets packet size to 9014
45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti      pgset "frags 5"         packet will consist of 5 fragments
46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti      pgset "count 200000"    sets number of packets to send
47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti      pgset "ipg 5000"        sets artificial gap inserted between packets
48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      to 5000 nanoseconds
49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti      pgset "dst 10.0.0.1"    sets IP destination address
50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      (BEWARE! This generator is very aggressive!)
51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti      pgset "dstmac 00:00:00:00:00:00"    sets MAC destination address
52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti      pgset stop    	      aborts injection
53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti  Also, ^C aborts generator.
55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti---- cut here
57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#! /bin/sh
59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittimodprobe pg3.o
61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittifunction pgset() {
63313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    local result
64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    echo $1 > /proc/net/pg
66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    result=`cat /proc/net/pg | fgrep "Result: OK:"`
68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    if [ "$result" = "" ]; then
69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	 cat /proc/net/pg | fgrep Result:
70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    fi
71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittifunction pg() {
74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    echo inject > /proc/net/pg
75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    cat /proc/net/pg
76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittipgset "odev eth0"
79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittipgset "dst 0.0.0.0"
80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti---- cut here
82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti*/
83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/module.h>
85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/kernel.h>
86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/sched.h>
87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/types.h>
88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/string.h>
89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/ptrace.h>
90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/errno.h>
91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/ioport.h>
92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/malloc.h>
93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/interrupt.h>
94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/pci.h>
95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/delay.h>
96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/init.h>
97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/inet.h>
98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <asm/byteorder.h>
99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <asm/bitops.h>
100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <asm/io.h>
101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <asm/dma.h>
102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/in.h>
104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/ip.h>
105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/udp.h>
106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/skbuff.h>
107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/netdevice.h>
108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/inetdevice.h>
109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/rtnetlink.h>
110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/proc_fs.h>
111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/if_arp.h>
112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <net/checksum.h>
113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic char version[] __initdata =
115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti  "pg3.c: v1.0 010812: Packet Generator for packet performance testing.\n";
116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Parameters */
120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar pg_outdev[32], pg_dst[32];
122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pkt_size=ETH_ZLEN;
123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint nfrags=0;
124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti__u32 pg_count = 100000;  /* Default No packets to send */
125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti__u32 pg_ipg = 0;  /* Default Interpacket gap in nsec */
126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Globar vars */
128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint debug;
130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint forced_stop;
131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pg_cpu_speed;
132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pg_busy;
133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic __u8 hh[14] = {
135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    /* We fill in SRC address later */
138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti    0x08, 0x00
140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti};
141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiunsigned char *pg_dstmac = hh;
143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar pg_result[512];
144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct net_device *pg_setup_inject(u32 *saddrp)
147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int p1, p2;
149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct net_device *odev;
150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	u32 saddr;
151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	rtnl_lock();
153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	odev = __dev_get_by_name(pg_outdev);
154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!odev) {
155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "No such netdevice: \"%s\"", pg_outdev);
156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		goto out_unlock;
157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (odev->type != ARPHRD_ETHER) {
160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "Not ethernet device: \"%s\"", pg_outdev);
161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		goto out_unlock;
162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!netif_running(odev)) {
165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "Device is down: \"%s\"", pg_outdev);
166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		goto out_unlock;
167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for(p1=6,p2=0; p1 < odev->addr_len+6;p1++)
170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		hh[p1]=odev->dev_addr[p2++];
171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	saddr = 0;
173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (odev->ip_ptr) {
174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		struct in_device *in_dev = odev->ip_ptr;
175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (in_dev->ifa_list)
177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			saddr = in_dev->ifa_list->ifa_address;
178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	atomic_inc(&odev->refcnt);
180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	rtnl_unlock();
181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	*saddrp = saddr;
183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return odev;
184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout_unlock:
186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	rtnl_unlock();
187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return NULL;
188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiu32 idle_acc_lo, idle_acc_hi;
192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid nanospin(int pg_ipg)
194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	u32 idle_start, idle;
196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	idle_start = get_cycles();
198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (;;) {
200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		barrier();
201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		idle = get_cycles() - idle_start;
202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (idle*1000 >= pg_ipg*pg_cpu_speed)
203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	idle_acc_lo += idle;
206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (idle_acc_lo < idle)
207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		idle_acc_hi++;
208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint calc_mhz(void)
211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct timeval start, stop;
213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	u32 start_s, elapsed;
214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	do_gettimeofday(&start);
216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	start_s = get_cycles();
217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	do {
218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		barrier();
219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		elapsed = get_cycles() - start_s;
220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (elapsed == 0)
221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return 0;
222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} while (elapsed < 1000*50000);
223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	do_gettimeofday(&stop);
224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return elapsed/(stop.tv_usec-start.tv_usec+1000000*(stop.tv_sec-start.tv_sec));
225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void cycles_calibrate(void)
228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for (i=0; i<3; i++) {
232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int res = calc_mhz();
233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (res > pg_cpu_speed)
234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pg_cpu_speed = res;
235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct sk_buff *
239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittifill_packet(struct net_device *odev, __u32 saddr)
240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct sk_buff *skb;
242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	__u8 *eth;
243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct udphdr *udph;
244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int datalen, iplen;
245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct iphdr *iph;
246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	skb = alloc_skb(pkt_size+64+16, GFP_ATOMIC);
248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!skb) {
249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "No memory");
250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return NULL;
251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	skb_reserve(skb, 16);
254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/*  Reserve for ethernet and IP header  */
256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	eth = (__u8 *) skb_push(skb, 14);
257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph = (struct iphdr*)skb_put(skb, sizeof( struct iphdr));
258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	udph = (struct udphdr*)skb_put(skb, sizeof( struct udphdr));
259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/*  Copy the ethernet header  */
261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(eth, hh, 14);
262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	datalen = pkt_size-14-20-8; /* Eth + IPh + UDPh */
264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (datalen < 0)
265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		datalen = 0;
266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	udph->source= htons(9);
268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	udph->dest= htons(9);
269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	udph->len= htons(datalen+8); /* DATA + udphdr */
270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	udph->check=0;  /* No checksum */
271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->ihl=5;
273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->version=4;
274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->ttl=3;
275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->tos=0;
276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->protocol = IPPROTO_UDP; /* UDP */
277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->saddr =  saddr;
278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->daddr =  in_aton(pg_dst);
279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->frag_off = 0;
280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iplen = 20 + 8 + datalen;
281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->tot_len = htons(iplen);
282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->check = 0;
283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	iph->check = ip_fast_csum((void *)iph, iph->ihl);
284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	skb->protocol = __constant_htons(ETH_P_IP);
285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	skb->mac.raw = ((u8*)iph) - 14;
286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	skb->dev = odev;
287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	skb->pkt_type = PACKET_HOST;
288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (nfrags<=0) {
290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		skb_put(skb, datalen);
291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	} else {
292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int frags = nfrags;
293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int i;
294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (frags > MAX_SKB_FRAGS)
296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			frags = MAX_SKB_FRAGS;
297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (datalen > frags*PAGE_SIZE) {
298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_put(skb, datalen-frags*PAGE_SIZE);
299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			datalen = frags*PAGE_SIZE;
300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i = 0;
303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		while (datalen > 0) {
304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			struct page *page = alloc_pages(GFP_KERNEL, 0);
305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->frags[i].page = page;
306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->frags[i].page_offset = 0;
307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->frags[i].size = (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			datalen -= skb_shinfo(skb)->frags[i].size;
309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb->len += skb_shinfo(skb)->frags[i].size;
310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb->data_len += skb_shinfo(skb)->frags[i].size;
311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			i++;
312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->nr_frags = i;
313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		while (i < frags) {
316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			int rem;
317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (i == 0)
319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				break;
320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			rem = skb_shinfo(skb)->frags[i-1].size/2;
322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (rem == 0)
323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				break;
324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->frags[i-1].size -= rem;
326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->frags[i] = skb_shinfo(skb)->frags[i-1];
328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			get_page(skb_shinfo(skb)->frags[i].page);
329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->frags[i].page = skb_shinfo(skb)->frags[i-1].page;
330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->frags[i].page_offset += skb_shinfo(skb)->frags[i-1].size;
331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->frags[i].size = rem;
332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			i++;
333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			skb_shinfo(skb)->nr_frags = i;
334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return skb;
338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void pg_inject(void)
342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	u32 saddr;
344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct net_device *odev;
345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct sk_buff *skb;
346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct timeval start, stop;
347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	u32 total, idle;
348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int pc, lcount;
349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	odev = pg_setup_inject(&saddr);
351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!odev)
352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	skb = fill_packet(odev, saddr);
355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (skb == NULL)
356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		goto out_reldev;
357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	forced_stop = 0;
359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	idle_acc_hi = 0;
360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	idle_acc_lo = 0;
361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	pc = 0;
362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	lcount = pg_count;
363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	do_gettimeofday(&start);
364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for(;;) {
366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		spin_lock_bh(&odev->xmit_lock);
367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		atomic_inc(&skb->users);
368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!netif_queue_stopped(odev)) {
369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (odev->hard_start_xmit(skb, odev)) {
370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				kfree_skb(skb);
371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (net_ratelimit())
372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					printk(KERN_INFO "Hard xmit error\n");
373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pc++;
375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		} else {
376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			kfree_skb(skb);
377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		spin_unlock_bh(&odev->xmit_lock);
379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (pg_ipg)
381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			nanospin(pg_ipg);
382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (forced_stop)
383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			goto out_intr;
384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (signal_pending(current))
385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			goto out_intr;
386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (--lcount == 0) {
388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (atomic_read(&skb->users) != 1) {
389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				u32 idle_start, idle;
390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				idle_start = get_cycles();
392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				while (atomic_read(&skb->users) != 1) {
393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					if (signal_pending(current))
394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						goto out_intr;
395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					schedule();
396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				idle = get_cycles() - idle_start;
398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				idle_acc_lo += idle;
399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (idle_acc_lo < idle)
400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					idle_acc_hi++;
401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (netif_queue_stopped(odev) || current->need_resched) {
406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			u32 idle_start, idle;
407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			idle_start = get_cycles();
409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			do {
410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (signal_pending(current))
411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					goto out_intr;
412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (!netif_running(odev))
413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					goto out_intr;
414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (current->need_resched)
415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					schedule();
416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				else
417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					do_softirq();
418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			} while (netif_queue_stopped(odev));
419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			idle = get_cycles() - idle_start;
420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			idle_acc_lo += idle;
421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (idle_acc_lo < idle)
422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				idle_acc_hi++;
423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	do_gettimeofday(&stop);
427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	total = (stop.tv_sec - start.tv_sec)*1000000 +
429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		stop.tv_usec - start.tv_usec;
430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	idle = (((idle_acc_hi<<20)/pg_cpu_speed)<<12)+idle_acc_lo/pg_cpu_speed;
432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (1) {
434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		char *p = pg_result;
435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p += sprintf(p, "OK: %u(c%u+d%u) usec, %u (%dbyte,%dfrags) %upps %uMB/sec",
437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     total, total-idle, idle,
438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     pc, skb->len, skb_shinfo(skb)->nr_frags,
439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     ((pc*1000)/(total/1000)),
440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     (((pc*1000)/(total/1000))*pkt_size)/1024/1024
441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     );
442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout_relskb:
445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	kfree_skb(skb);
446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout_reldev:
447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	dev_put(odev);
448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return;
449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiout_intr:
451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sprintf(pg_result, "Interrupted");
452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	goto out_relskb;
453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* proc/net/pg */
456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct proc_dir_entry *pg_proc_ent = 0;
458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct proc_dir_entry *pg_busy_proc_ent = 0;
459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint proc_pg_busy_read(char *buf , char **start, off_t offset,
461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      int len, int *eof, void *data)
462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char *p;
464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p = buf;
466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p += sprintf(p, "%d\n", pg_busy);
467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	*eof = 1;
468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return p-buf;
470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint proc_pg_read(char *buf , char **start, off_t offset,
473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		 int len, int *eof, void *data)
474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char *p;
476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p = buf;
479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	p += sprintf(p, "Params: count=%u pkt_size=%u frags %d ipg %u odev \"%s\" dst %s dstmac ",
480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		     pg_count, pkt_size, nfrags, pg_ipg,
481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		     pg_outdev, pg_dst);
482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for(i=0;i<6;i++)
483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p += sprintf(p, "%02X%s", pg_dstmac[i], i == 5 ? "\n" : ":");
484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(pg_result[0])
486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p += sprintf(p, "Result: %s\n", pg_result);
487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	else
488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p += sprintf(p, "Result: Idle\n");
489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	*eof = 1;
490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return p-buf;
491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint count_trail_chars(const char *buffer, unsigned int maxlen)
494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for(i=0; i<maxlen;i++) {
498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		switch(buffer[i]) {
499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '\"':
500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '\n':
501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '\r':
502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '\t':
503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case ' ':
504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '=':
505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		default:
507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			goto done;
508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittidone:
511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return i;
512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiunsigned long num_arg(const char *buffer, unsigned long maxlen,
515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		      unsigned long *num)
516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i=0;
518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	*num = 0;
519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for(; i<maxlen;i++) {
521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if( (buffer[i] >= '0') && (buffer[i] <= '9')) {
522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			*num *= 10;
523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			*num += buffer[i] -'0';
524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		else
526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return i;
529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint strn_len(const char *buffer, unsigned int maxlen)
532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i=0;
534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	for(; i<maxlen;i++)
536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		switch(buffer[i]) {
537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '\"':
538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '\n':
539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '\r':
540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case '\t':
541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		case ' ':
542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			goto done_str;
543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		default:
544313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
545313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittidone_str:
546313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return i;
547313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
548313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
549313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint proc_pg_write(struct file *file, const char *buffer,
550313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		     unsigned long count, void *data)
551313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
552313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i=0, max, len;
553313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	char name[16], valstr[32];
554313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	unsigned long value = 0;
555313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
556313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (count < 1) {
557313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "Wrong command format");
558313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -EINVAL;
559313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
560313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
561313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	max = count -i;
562313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	i += count_trail_chars(&buffer[i], max);
563313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
564313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Read variable name */
565313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
566313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	len = strn_len(&buffer[i], sizeof(name)-1);
567313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(name, 0, sizeof(name));
568313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	strncpy(name, &buffer[i], len);
569313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	i += len;
570313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
571313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	max = count -i;
572313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	len = count_trail_chars(&buffer[i], max);
573313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	i += len;
574313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
575313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (debug)
576313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printk("pg: %s,%lu\n", name, count);
577313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
578313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* Only stop is allowed when we are running */
579313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
580313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!strcmp(name, "stop")) {
581313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		forced_stop=1;
582313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (pg_busy)
583313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			strcpy(pg_result, "Stopping");
584313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
585313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
586313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
587313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (pg_busy) {
588313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		strcpy(pg_result, "Busy");
589313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -EINVAL;
590313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
591313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
592313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!strcmp(name, "pkt_size")) {
593313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		len = num_arg(&buffer[i], 10, &value);
594313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i += len;
595313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (value < 14+20+8)
596313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			value = 14+20+8;
597313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pkt_size = value;
598313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "OK: pkt_size=%u", pkt_size);
599313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
600313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
601313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!strcmp(name, "frags")) {
602313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		len = num_arg(&buffer[i], 10, &value);
603313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i += len;
604313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		nfrags = value;
605313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "OK: frags=%u", nfrags);
606313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
607313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
608313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!strcmp(name, "ipg")) {
609313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		len = num_arg(&buffer[i], 10, &value);
610313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i += len;
611313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_ipg = value;
612313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "OK: ipg=%u", pg_ipg);
613313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
614313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
615313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!strcmp(name, "count")) {
616313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		len = num_arg(&buffer[i], 10, &value);
617313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i += len;
618313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_count = value;
619313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "OK: count=%u", pg_count);
620313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
621313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
622313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!strcmp(name, "odev")) {
623313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		len = strn_len(&buffer[i], sizeof(pg_outdev)-1);
624313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memset(pg_outdev, 0, sizeof(pg_outdev));
625313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		strncpy(pg_outdev, &buffer[i], len);
626313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i += len;
627313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "OK: odev=%s", pg_outdev);
628313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
629313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
630313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!strcmp(name, "dst")) {
631313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		len = strn_len(&buffer[i], sizeof(pg_dst)-1);
632313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memset(pg_dst, 0, sizeof(pg_dst));
633313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		strncpy(pg_dst, &buffer[i], len);
634313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if(debug)
635313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			printk("pg: dst set to: %s\n", pg_dst);
636313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i += len;
637313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "OK: dst=%s", pg_dst);
638313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
639313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
640313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!strcmp(name, "dstmac")) {
641313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		char *v = valstr;
642313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		unsigned char *m = pg_dstmac;
643313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
644313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		len = strn_len(&buffer[i], sizeof(valstr)-1);
645313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		memset(valstr, 0, sizeof(valstr));
646313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		strncpy(valstr, &buffer[i], len);
647313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i += len;
648313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
649313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for(*m = 0;*v && m < pg_dstmac+6;v++) {
650313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if(*v >= '0' && *v <= '9') {
651313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*m *= 16;
652313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*m += *v - '0';
653313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
654313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if(*v >= 'A' && *v <= 'F') {
655313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*m *= 16;
656313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*m += *v - 'A' + 10;
657313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
658313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if(*v >= 'a' && *v <= 'f') {
659313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*m *= 16;
660313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*m += *v - 'a' + 10;
661313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
662313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if(*v == ':') {
663313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				m++;
664313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				*m = 0;
665313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
666313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
667313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		sprintf(pg_result, "OK: dstmac");
668313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
669313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
670313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
671313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!strcmp(name, "inject") || !strcmp(name, "start") ) {
672313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		MOD_INC_USE_COUNT;
673313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_busy = 1;
674313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		strcpy(pg_result, "Starting");
675313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_inject();
676313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_busy = 0;
677313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		MOD_DEC_USE_COUNT;
678313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return count;
679313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
680313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
681313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	sprintf(pg_result, "No such parameter \"%s\"", name);
682313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return -EINVAL;
683313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
684313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
685313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int pg_init(void)
686313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
687313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	printk(version);
688313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	cycles_calibrate();
689313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (pg_cpu_speed == 0) {
690313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		printk("pg3: Error: your machine does not have working cycle counter.\n");
691313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -EINVAL;
692313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
693313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if(!pg_proc_ent) {
694313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_proc_ent = create_proc_entry("net/pg", 0600, 0);
695313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (pg_proc_ent) {
696313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pg_proc_ent->read_proc = proc_pg_read;
697313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pg_proc_ent->write_proc = proc_pg_write;
698313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pg_proc_ent->data = 0;
699313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
700313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_busy_proc_ent = create_proc_entry("net/pg_busy", 0, 0);
701313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (pg_busy_proc_ent) {
702313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pg_busy_proc_ent->read_proc = proc_pg_busy_read;
703313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			pg_busy_proc_ent->data = 0;
704313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
705313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
706313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
707313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
708313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
709313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid pg_cleanup(void)
710313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
711313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (pg_proc_ent) {
712313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		remove_proc_entry("net/pg", NULL);
713313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_proc_ent = 0;
714313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		remove_proc_entry("net/pg_busy", NULL);
715313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		pg_busy_proc_ent = 0;
716313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
717313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
718313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
719313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittimodule_init(pg_init);
720313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittimodule_exit(pg_cleanup);
721313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
722313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
723313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if LINUX_VERSION_CODE > 0x20118
724313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiMODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se");
725313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiMODULE_DESCRIPTION("Packet Generator tool");
726313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiMODULE_PARM(pg_count, "i");
727313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiMODULE_PARM(pg_ipg, "i");
728313379eb6b9da55f7371adef39a92153a0707d4aLorenzo ColittiMODULE_PARM(pg_cpu_speed, "i");
729313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
730313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
731313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
732313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Local variables:
733313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c pg3.c"
734313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * End:
735313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
736