⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pktgen.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*-linux-c-*- * $Id: pktgen.c,v 1.8 2002/07/15 19:30:17 robert Exp $ * pktgen.c: Packet Generator for performance evaluation. * * Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se> *				 Uppsala University, Sweden * * A tool for loading the network with preconfigurated packets. * The tool is implemented as a linux module.  Parameters are output  * device, IPG (interpacket gap), number of packets, and whether * to use multiple SKBs or just the same one. * pktgen uses the installed interface's output routine. * * Additional hacking by: * * Jens.Laas@data.slu.se * Improved by ANK. 010120. * Improved by ANK even more. 010212. * MAC address typo fixed. 010417 --ro * Integrated.  020301 --DaveM * Added multiskb option 020301 --DaveM * Scaling of results. 020417--sigurdur@linpro.no * Significant re-work of the module: *   *  Updated to support generation over multiple interfaces at once *       by creating 32 /proc/net/pg* files.  Each file can be manipulated *       individually. *   *  Converted many counters to __u64 to allow longer runs. *   *  Allow configuration of ranges, like min/max IP address, MACs, *       and UDP-ports, for both source and destination, and can *       set to use a random distribution or sequentially walk the range. *   *  Can now change some values after starting. *   *  Place 12-byte packet in UDP payload with magic number, *       sequence number, and timestamp.  Will write receiver next. *   *  The new changes seem to have a performance impact of around 1%, *       as far as I can tell. *   --Ben Greear <greearb@candelatech.com> * Integrated to 2.5.x 021029 --Lucio Maciel (luciomaciel@zipmail.com.br) * * Renamed multiskb to clone_skb and cleaned up sending core for two distinct  * skb modes. A clone_skb=0 mode for Ben "ranges" work and a clone_skb != 0  * as a "fastpath" with a configurable number of clones after alloc's. * * clone_skb=0 means all packets are allocated this also means ranges time  * stamps etc can be used. clone_skb=100 means 1 malloc is followed by 100  * clones. * * Also moved to /proc/net/pktgen/  * --ro  * * Fix refcount off by one if first packet fails, potential null deref,  * memleak 030710- KJP * * Fixed unaligned access on IA-64 Grant Grundler <grundler@parisc-linux.org> * * New xmit() return, do_div and misc clean up by Stephen Hemminger  * <shemminger@osdl.org> 040923 * * See Documentation/networking/pktgen.txt for how to use this. */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/string.h>#include <linux/ptrace.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/inet.h>#include <linux/rcupdate.h>#include <asm/byteorder.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/uaccess.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/udp.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <linux/rtnetlink.h>#include <linux/proc_fs.h>#include <linux/if_arp.h>#include <net/checksum.h>#include <asm/timex.h>#define cycles()	((u32)get_cycles())#define VERSION "pktgen version 1.32"static char version[] __initdata =   "pktgen.c: v1.4: Packet Generator for packet performance testing.\n";/* Used to help with determining the pkts on receive */#define PKTGEN_MAGIC 0xbe9be955/* Keep information per interface */struct pktgen_info {	/* Parameters */	/* If min != max, then we will either do a linear iteration, or	 * we will do a random selection from within the range.	 */	__u32 flags;     #define F_IPSRC_RND   (1<<0)  /* IP-Src Random  */#define F_IPDST_RND   (1<<1)  /* IP-Dst Random  */#define F_UDPSRC_RND  (1<<2)  /* UDP-Src Random */#define F_UDPDST_RND  (1<<3)  /* UDP-Dst Random */#define F_MACSRC_RND  (1<<4)  /* MAC-Src Random */#define F_MACDST_RND  (1<<5)  /* MAC-Dst Random */#define F_SET_SRCMAC  (1<<6)  /* Specify-Src-Mac 				 (default is to use Interface's MAC Addr) */#define F_SET_SRCIP   (1<<7)  /*  Specify-Src-IP				  (default is to use Interface's IP Addr) */ 		int pkt_size;    /* = ETH_ZLEN; */	int nfrags;	__u32 ipg;       /* Default Interpacket gap in nsec */	__u64 count;     /* Default No packets to send */	__u64 sofar;     /* How many pkts we've sent so far */	__u64 errors;    /* Errors when trying to transmit, pkts will be re-sent */	struct timeval started_at;	struct timeval stopped_at;	__u64 idle_acc;	__u32 seq_num;		int clone_skb;   /* Use multiple SKBs during packet gen.  If this number			  * is greater than 1, then that many coppies of the same			  * packet will be sent before a new packet is allocated.			  * For instance, if you want to send 1024 identical packets			  * before creating a new packet, set clone_skb to 1024.			  */	int busy;	int do_run_run;   /* if this changes to false, the test will stop */		char outdev[32];	char dst_min[32];	char dst_max[32];	char src_min[32];	char src_max[32];	/* If we're doing ranges, random or incremental, then this	 * defines the min/max for those ranges.	 */	__u32 saddr_min; /* inclusive, source IP address */	__u32 saddr_max; /* exclusive, source IP address */	__u32 daddr_min; /* inclusive, dest IP address */	__u32 daddr_max; /* exclusive, dest IP address */	__u16 udp_src_min; /* inclusive, source UDP port */	__u16 udp_src_max; /* exclusive, source UDP port */	__u16 udp_dst_min; /* inclusive, dest UDP port */	__u16 udp_dst_max; /* exclusive, dest UDP port */	__u32 src_mac_count; /* How many MACs to iterate through */	__u32 dst_mac_count; /* How many MACs to iterate through */		unsigned char dst_mac[6];	unsigned char src_mac[6];		__u32 cur_dst_mac_offset;	__u32 cur_src_mac_offset;	__u32 cur_saddr;	__u32 cur_daddr;	__u16 cur_udp_dst;	__u16 cur_udp_src;		__u8 hh[14];	/* = { 	   0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB, 	   	   We fill in SRC address later	   0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	   0x08, 0x00	   };	*/	__u16 pad; /* pad out the hh struct to an even 16 bytes */	char result[512];	/* proc file names */	char fname[80];	char busy_fname[80];		struct proc_dir_entry *proc_ent;	struct proc_dir_entry *busy_proc_ent;};struct pktgen_hdr {	__u32 pgh_magic;	__u32 seq_num;	__u32 tv_sec;	__u32 tv_usec;};static int cpu_speed;static int debug;/* Module parameters, defaults. */static int count_d = 100000;static int ipg_d;static int clone_skb_d;#define MAX_PKTGEN 8static struct pktgen_info pginfos[MAX_PKTGEN];/** Convert to miliseconds */static inline __u64 tv_to_ms(const struct timeval* tv) {	__u64 ms = tv->tv_usec / 1000;	ms += (__u64)tv->tv_sec * (__u64)1000;	return ms;}static inline __u64 getCurMs(void) {	struct timeval tv;	do_gettimeofday(&tv);	return tv_to_ms(&tv);}#define PG_PROC_DIR "pktgen"static struct proc_dir_entry *proc_dir;static struct net_device *setup_inject(struct pktgen_info* info){	struct net_device *odev;	odev = dev_get_by_name(info->outdev);	if (!odev) {		sprintf(info->result, "No such netdevice: \"%s\"", info->outdev);		goto out;	}	if (odev->type != ARPHRD_ETHER) {		sprintf(info->result, "Not ethernet device: \"%s\"", info->outdev);		goto out_put;	}	if (!netif_running(odev)) {		sprintf(info->result, "Device is down: \"%s\"", info->outdev);		goto out_put;	}	/* Default to the interface's mac if not explicitly set. */	if (!(info->flags & F_SET_SRCMAC)) {		memcpy(&(info->hh[6]), odev->dev_addr, 6);	}	else {		memcpy(&(info->hh[6]), info->src_mac, 6);	}	/* Set up Dest MAC */	memcpy(&(info->hh[0]), info->dst_mac, 6);		info->saddr_min = 0;	info->saddr_max = 0;	if (strlen(info->src_min) == 0) {		struct in_device *in_dev;		rcu_read_lock();		in_dev = __in_dev_get(odev);		if (in_dev) {			if (in_dev->ifa_list) {				info->saddr_min = in_dev->ifa_list->ifa_address;				info->saddr_max = info->saddr_min;			}		}		rcu_read_unlock();	}	else {		info->saddr_min = in_aton(info->src_min);		info->saddr_max = in_aton(info->src_max);	}	info->daddr_min = in_aton(info->dst_min);	info->daddr_max = in_aton(info->dst_max);	/* Initialize current values. */	info->cur_dst_mac_offset = 0;	info->cur_src_mac_offset = 0;	info->cur_saddr = info->saddr_min;	info->cur_daddr = info->daddr_min;	info->cur_udp_dst = info->udp_dst_min;	info->cur_udp_src = info->udp_src_min;		return odev;out_put:	dev_put(odev);out:	return NULL;}static void nanospin(int ipg, struct pktgen_info* info){	u32 idle_start, idle;	idle_start = cycles();	for (;;) {		barrier();		idle = cycles() - idle_start;		if (idle * 1000 >= ipg * cpu_speed)			break;	}	info->idle_acc += idle;}static int calc_mhz(void){	struct timeval start, stop;	u32 start_s, elapsed;	do_gettimeofday(&start);	start_s = cycles();	do {		barrier();		elapsed = cycles() - start_s;		if (elapsed == 0)			return 0;	} while (elapsed < 1000 * 50000);	do_gettimeofday(&stop);	return elapsed/(stop.tv_usec-start.tv_usec+1000000*(stop.tv_sec-start.tv_sec));}static void cycles_calibrate(void){	int i;	for (i = 0; i < 3; i++) {		int res = calc_mhz();		if (res > cpu_speed)			cpu_speed = res;	}}/* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */static void mod_cur_headers(struct pktgen_info* info) {		__u32 imn;	__u32 imx;		/*  Deal with source MAC */	if (info->src_mac_count > 1) {		__u32 mc;		__u32 tmp;		if (info->flags & F_MACSRC_RND) {			mc = net_random() % (info->src_mac_count);		}		else {			mc = info->cur_src_mac_offset++;			if (info->cur_src_mac_offset > info->src_mac_count) {				info->cur_src_mac_offset = 0;			}		}		tmp = info->src_mac[5] + (mc & 0xFF);		info->hh[11] = tmp;		tmp = (info->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));		info->hh[10] = tmp;		tmp = (info->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));		info->hh[9] = tmp;		tmp = (info->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));		info->hh[8] = tmp;		tmp = (info->src_mac[1] + (tmp >> 8));		info->hh[7] = tmp;		}	/*  Deal with Destination MAC */	if (info->dst_mac_count > 1) {		__u32 mc;		__u32 tmp;		if (info->flags & F_MACDST_RND) {			mc = net_random() % (info->dst_mac_count);		}		else {			mc = info->cur_dst_mac_offset++;			if (info->cur_dst_mac_offset > info->dst_mac_count) {				info->cur_dst_mac_offset = 0;			}		}		tmp = info->dst_mac[5] + (mc & 0xFF);		info->hh[5] = tmp;		tmp = (info->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));		info->hh[4] = tmp;		tmp = (info->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));		info->hh[3] = tmp;		tmp = (info->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));		info->hh[2] = tmp;		tmp = (info->dst_mac[1] + (tmp >> 8));		info->hh[1] = tmp;		}	if (info->udp_src_min < info->udp_src_max) {		if (info->flags & F_UDPSRC_RND) {			info->cur_udp_src = ((net_random() % (info->udp_src_max - info->udp_src_min))					     + info->udp_src_min);		}		else {		     info->cur_udp_src++;		     if (info->cur_udp_src >= info->udp_src_max) {			     info->cur_udp_src = info->udp_src_min;		     }		}	}	if (info->udp_dst_min < info->udp_dst_max) {		if (info->flags & F_UDPDST_RND) {			info->cur_udp_dst = ((net_random() % (info->udp_dst_max - info->udp_dst_min))					     + info->udp_dst_min);		}		else {		     info->cur_udp_dst++;		     if (info->cur_udp_dst >= info->udp_dst_max) {			     info->cur_udp_dst = info->udp_dst_min;		     }		}	}	if ((imn = ntohl(info->saddr_min)) < (imx = ntohl(info->saddr_max))) {		__u32 t;		if (info->flags & F_IPSRC_RND) {			t = ((net_random() % (imx - imn)) + imn);		}		else {		     t = ntohl(info->cur_saddr);		     t++;		     if (t >= imx) {			     t = imn;		     }		}		info->cur_saddr = htonl(t);	}	if ((imn = ntohl(info->daddr_min)) < (imx = ntohl(info->daddr_max))) {		__u32 t;		if (info->flags & F_IPDST_RND) {			t = ((net_random() % (imx - imn)) + imn);		}		else {		     t = ntohl(info->cur_daddr);		     t++;		     if (t >= imx) {			     t = imn;		     }		}		info->cur_daddr = htonl(t);	}}/* mod_cur_headers */static struct sk_buff *fill_packet(struct net_device *odev, struct pktgen_info* info){	struct sk_buff *skb = NULL;	__u8 *eth;	struct udphdr *udph;	int datalen, iplen;	struct iphdr *iph;	struct pktgen_hdr *pgh = NULL;		skb = alloc_skb(info->pkt_size + 64 + 16, GFP_ATOMIC);	if (!skb) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -