pktgen.c 91.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8
/*
 * Authors:
 * Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se>
 *                             Uppsala University and
 *                             Swedish University of Agricultural Sciences
 *
 * Alexey Kuznetsov  <kuznet@ms2.inr.ac.ru>
 * Ben Greear <greearb@candelatech.com>
9
 * Jens Låås <jens.laas@data.slu.se>
L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 *
 * A tool for loading the network with preconfigurated packets.
18
 * The tool is implemented as a linux module.  Parameters are output
L
Linus Torvalds 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 * device, delay (to hard_xmit), 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:
 *   *  Convert to threaded model to more efficiently be able to transmit
 *       and receive on multiple interfaces at once.
 *   *  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 most values after starting.
 *   *  Place 12-byte packet in UDP payload with magic number,
 *       sequence number, and timestamp.
 *   *  Add receiver code that detects dropped pkts, re-ordered pkts, and
 *       latencies (with micro-second) precision.
 *   *  Add IOCTL interface to easily get counters & configuration.
 *   --Ben Greear <greearb@candelatech.com>
 *
47 48
 * 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
L
Linus Torvalds 已提交
49
 * as a "fastpath" with a configurable number of clones after alloc's.
50 51
 * 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
L
Linus Torvalds 已提交
52 53
 * clones.
 *
54
 * Also moved to /proc/net/pktgen/
L
Linus Torvalds 已提交
55 56 57 58 59 60 61 62
 * --ro
 *
 * Sept 10:  Fixed threading/locking.  Lots of bone-headed and more clever
 *    mistakes.  Also merged in DaveM's patch in the -pre6 patch.
 * --Ben Greear <greearb@candelatech.com>
 *
 * Integrated to 2.5.x 021029 --Lucio Maciel (luciomaciel@zipmail.com.br)
 *
63
 *
L
Linus Torvalds 已提交
64 65 66 67
 * 021124 Finished major redesign and rewrite for new functionality.
 * See Documentation/networking/pktgen.txt for how to use this.
 *
 * The new operation:
68 69 70 71
 * For each CPU one thread/process is created at start. This process checks
 * for running devices in the if_list and sends packets until count is 0 it
 * also the thread checks the thread->control which is used for inter-process
 * communication. controlling process "posts" operations to the threads this
L
Linus Torvalds 已提交
72 73 74
 * way. The if_lock should be possible to remove when add/rem_device is merged
 * into this too.
 *
75 76
 * By design there should only be *one* "controlling" process. In practice
 * multiple write accesses gives unpredictable result. Understood by "write"
L
Linus Torvalds 已提交
77
 * to /proc gives result code thats should be read be the "writer".
78
 * For practical use this should be no problem.
L
Linus Torvalds 已提交
79
 *
80 81
 * Note when adding devices to a specific CPU there good idea to also assign
 * /proc/irq/XX/smp_affinity so TX-interrupts gets bound to the same CPU.
L
Linus Torvalds 已提交
82 83
 * --ro
 *
84
 * Fix refcount off by one if first packet fails, potential null deref,
L
Linus Torvalds 已提交
85 86 87 88 89 90 91
 * memleak 030710- KJP
 *
 * First "ranges" functionality for ipv6 030726 --ro
 *
 * Included flow support. 030802 ANK.
 *
 * Fixed unaligned access on IA-64 Grant Grundler <grundler@parisc-linux.org>
92
 *
L
Linus Torvalds 已提交
93 94 95
 * Remove if fix from added Harald Welte <laforge@netfilter.org> 040419
 * ia64 compilation fix from  Aron Griffis <aron@hp.com> 040604
 *
96
 * New xmit() return, do_div and misc clean up by Stephen Hemminger
L
Linus Torvalds 已提交
97 98
 * <shemminger@osdl.org> 040923
 *
99
 * Randy Dunlap fixed u64 printk compiler waring
L
Linus Torvalds 已提交
100 101 102 103
 *
 * Remove FCS from BW calculation.  Lennert Buytenhek <buytenh@wantstofly.org>
 * New time handling. Lennert Buytenhek <buytenh@wantstofly.org> 041213
 *
104
 * Corrections from Nikolai Malykh (nmalykh@bilim.com)
L
Linus Torvalds 已提交
105 106
 * Removed unused flags F_SET_SRCMAC & F_SET_SRCIP 041230
 *
107
 * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
L
Linus Torvalds 已提交
108
 * 050103
109 110 111
 *
 * MPLS support by Steven Whitehouse <steve@chygwyn.com>
 *
F
Francesco Fondelli 已提交
112 113
 * 802.1Q/Q-in-Q support by Francesco Fondelli (FF) <francesco.fondelli@gmail.com>
 *
A
Adit Ranadive 已提交
114 115 116
 * Fixed src_mac command to set source mac of packet to value specified in
 * command by Adit Ranadive <adit.262@gmail.com>
 *
L
Linus Torvalds 已提交
117
 */
J
Joe Perches 已提交
118 119 120

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

L
Linus Torvalds 已提交
121 122 123 124 125
#include <linux/sys.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
126
#include <linux/mutex.h>
L
Linus Torvalds 已提交
127 128 129 130 131 132 133 134 135
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
136
#include <linux/capability.h>
S
Stephen Hemminger 已提交
137
#include <linux/hrtimer.h>
A
Andrew Morton 已提交
138
#include <linux/freezer.h>
L
Linus Torvalds 已提交
139 140
#include <linux/delay.h>
#include <linux/timer.h>
141
#include <linux/list.h>
L
Linus Torvalds 已提交
142 143 144 145 146 147 148
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/inet.h>
#include <linux/inetdevice.h>
#include <linux/rtnetlink.h>
#include <linux/if_arp.h>
F
Francesco Fondelli 已提交
149
#include <linux/if_vlan.h>
L
Linus Torvalds 已提交
150 151 152 153 154
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <linux/proc_fs.h>
155
#include <linux/seq_file.h>
L
Linus Torvalds 已提交
156
#include <linux/wait.h>
157
#include <linux/etherdevice.h>
158
#include <linux/kthread.h>
159
#include <linux/prefetch.h>
160
#include <net/net_namespace.h>
L
Linus Torvalds 已提交
161 162
#include <net/checksum.h>
#include <net/ipv6.h>
163
#include <net/udp.h>
164
#include <net/ip6_checksum.h>
L
Linus Torvalds 已提交
165
#include <net/addrconf.h>
J
Jamal Hadi Salim 已提交
166 167 168
#ifdef CONFIG_XFRM
#include <net/xfrm.h>
#endif
C
Cong Wang 已提交
169
#include <net/netns/generic.h>
L
Linus Torvalds 已提交
170 171
#include <asm/byteorder.h>
#include <linux/rcupdate.h>
J
Jiri Slaby 已提交
172
#include <linux/bitops.h>
173 174 175
#include <linux/io.h>
#include <linux/timex.h>
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
176
#include <asm/dma.h>
L
Luiz Capitulino 已提交
177
#include <asm/div64.h>		/* do_div */
L
Linus Torvalds 已提交
178

179
#define VERSION	"2.74"
L
Linus Torvalds 已提交
180
#define IP_NAME_SZ 32
181
#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
182
#define MPLS_STACK_BOTTOM htonl(0x00000100)
L
Linus Torvalds 已提交
183

J
Joe Perches 已提交
184 185
#define func_enter() pr_debug("entering %s\n", __func__);

L
Linus Torvalds 已提交
186
/* Device flag bits */
L
Luiz Capitulino 已提交
187 188 189 190 191 192 193 194
#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_TXSIZE_RND  (1<<6)	/* Transmit size is random */
#define F_IPV6        (1<<7)	/* Interface in IPV6 Mode */
195
#define F_MPLS_RND    (1<<8)	/* Random MPLS labels */
F
Francesco Fondelli 已提交
196 197
#define F_VID_RND     (1<<9)	/* Random VLAN ID */
#define F_SVID_RND    (1<<10)	/* Random SVLAN ID */
198
#define F_FLOW_SEQ    (1<<11)	/* Sequential flows */
J
Jamal Hadi Salim 已提交
199
#define F_IPSEC_ON    (1<<12)	/* ipsec on for flows */
R
Robert Olsson 已提交
200
#define F_QUEUE_MAP_RND (1<<13)	/* queue map Random */
R
Robert Olsson 已提交
201
#define F_QUEUE_MAP_CPU (1<<14)	/* queue map mirrors smp_processor_id() */
R
Robert Olsson 已提交
202
#define F_NODE          (1<<15)	/* Node memory alloc*/
203
#define F_UDPCSUM       (1<<16)	/* Include UDP checksum */
L
Linus Torvalds 已提交
204 205

/* Thread control flag bits */
206 207 208 209
#define T_STOP        (1<<0)	/* Stop run */
#define T_RUN         (1<<1)	/* Start run */
#define T_REMDEVALL   (1<<2)	/* Remove all devs */
#define T_REMDEV      (1<<3)	/* Remove one dev */
L
Linus Torvalds 已提交
210 211 212 213 214 215 216

/* If lock -- can be removed after some work */
#define   if_lock(t)           spin_lock(&(t->if_lock));
#define   if_unlock(t)           spin_unlock(&(t->if_lock));

/* Used to help with determining the pkts on receive */
#define PKTGEN_MAGIC 0xbe9be955
217 218
#define PG_PROC_DIR "pktgen"
#define PGCTRL	    "pgctrl"
L
Linus Torvalds 已提交
219 220 221

#define MAX_CFLOWS  65536

F
Francesco Fondelli 已提交
222 223 224
#define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)

L
Luiz Capitulino 已提交
225
struct flow_state {
A
Al Viro 已提交
226
	__be32 cur_daddr;
L
Luiz Capitulino 已提交
227
	int count;
J
Jamal Hadi Salim 已提交
228 229 230
#ifdef CONFIG_XFRM
	struct xfrm_state *x;
#endif
231
	__u32 flags;
L
Linus Torvalds 已提交
232 233
};

234 235 236
/* flow flag bits */
#define F_INIT   (1<<0)		/* flow has been initialized */

L
Linus Torvalds 已提交
237 238 239 240
struct pktgen_dev {
	/*
	 * Try to keep frequent/infrequent used vars. separated.
	 */
241 242
	struct proc_dir_entry *entry;	/* proc file */
	struct pktgen_thread *pg_thread;/* the owner */
243
	struct list_head list;		/* chaining in the thread's run-queue */
L
Linus Torvalds 已提交
244

245
	int running;		/* if false, the test will stop */
L
Linus Torvalds 已提交
246

L
Luiz Capitulino 已提交
247 248 249 250
	/* If min != max, then we will either do a linear iteration, or
	 * we will do a random selection from within the range.
	 */
	__u32 flags;
251 252
	int removal_mark;	/* non-zero => the device is marked for
				 * removal by worker thread */
L
Linus Torvalds 已提交
253

254 255
	int min_pkt_size;
	int max_pkt_size;
256
	int pkt_overhead;	/* overhead for MPLS, VLANs, IPSEC etc */
L
Luiz Capitulino 已提交
257
	int nfrags;
E
Eric Dumazet 已提交
258
	struct page *page;
259 260
	u64 delay;		/* nano-seconds */

L
Luiz Capitulino 已提交
261 262 263
	__u64 count;		/* Default No packets to send */
	__u64 sofar;		/* How many pkts we've sent so far */
	__u64 tx_bytes;		/* How many bytes we've transmitted */
264
	__u64 errors;		/* Errors when trying to transmit, */
L
Luiz Capitulino 已提交
265 266 267 268 269 270

	/* runtime counters relating to clone_skb */

	__u64 allocated_skbs;
	__u32 clone_count;
	int last_ok;		/* Was last skb sent?
271 272
				 * Or a failed transmit of some sort?
				 * This will keep sequence numbers in order
L
Luiz Capitulino 已提交
273
				 */
274 275 276 277 278
	ktime_t next_tx;
	ktime_t started_at;
	ktime_t stopped_at;
	u64	idle_acc;	/* nano-seconds */

L
Luiz Capitulino 已提交
279 280
	__u32 seq_num;

281 282 283 284 285 286 287 288
	int clone_skb;		/*
				 * Use multiple SKBs during packet gen.
				 * If this number is greater than 1, then
				 * that many copies of the same packet will be
				 * sent before a new packet is allocated.
				 * If you want to send 1024 identical packets
				 * before creating a new packet,
				 * set clone_skb to 1024.
L
Luiz Capitulino 已提交
289 290 291 292 293 294 295 296 297 298 299
				 */

	char dst_min[IP_NAME_SZ];	/* IP, ie 1.2.3.4 */
	char dst_max[IP_NAME_SZ];	/* IP, ie 1.2.3.4 */
	char src_min[IP_NAME_SZ];	/* IP, ie 1.2.3.4 */
	char src_max[IP_NAME_SZ];	/* IP, ie 1.2.3.4 */

	struct in6_addr in6_saddr;
	struct in6_addr in6_daddr;
	struct in6_addr cur_in6_daddr;
	struct in6_addr cur_in6_saddr;
L
Linus Torvalds 已提交
300
	/* For ranges */
L
Luiz Capitulino 已提交
301 302 303 304 305 306 307 308
	struct in6_addr min_in6_daddr;
	struct in6_addr max_in6_daddr;
	struct in6_addr min_in6_saddr;
	struct in6_addr max_in6_saddr;

	/* If we're doing ranges, random or incremental, then this
	 * defines the min/max for those ranges.
	 */
A
Al Viro 已提交
309 310 311 312
	__be32 saddr_min;	/* inclusive, source IP address */
	__be32 saddr_max;	/* exclusive, source IP address */
	__be32 daddr_min;	/* inclusive, dest IP address */
	__be32 daddr_max;	/* exclusive, dest IP address */
L
Luiz Capitulino 已提交
313 314 315 316 317 318

	__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 */

F
Francesco Fondelli 已提交
319
	/* DSCP + ECN */
320 321 322 323
	__u8 tos;            /* six MSB of (former) IPv4 TOS
				are for dscp codepoint */
	__u8 traffic_class;  /* ditto for the (former) Traffic Class in IPv6
				(see RFC 3260, sec. 4) */
F
Francesco Fondelli 已提交
324

325
	/* MPLS */
326
	unsigned int nr_labels;	/* Depth of stack, 0 = no MPLS */
327 328
	__be32 labels[MAX_MPLS_LABELS];

F
Francesco Fondelli 已提交
329 330 331 332 333 334 335 336 337
	/* VLAN/SVLAN (802.1Q/Q-in-Q) */
	__u8  vlan_p;
	__u8  vlan_cfi;
	__u16 vlan_id;  /* 0xffff means no vlan tag */

	__u8  svlan_p;
	__u8  svlan_cfi;
	__u16 svlan_id; /* 0xffff means no svlan tag */

L
Luiz Capitulino 已提交
338 339 340 341 342 343 344 345
	__u32 src_mac_count;	/* How many MACs to iterate through */
	__u32 dst_mac_count;	/* How many MACs to iterate through */

	unsigned char dst_mac[ETH_ALEN];
	unsigned char src_mac[ETH_ALEN];

	__u32 cur_dst_mac_offset;
	__u32 cur_src_mac_offset;
A
Al Viro 已提交
346 347
	__be32 cur_saddr;
	__be32 cur_daddr;
E
Eric Dumazet 已提交
348
	__u16 ip_id;
L
Luiz Capitulino 已提交
349 350
	__u16 cur_udp_dst;
	__u16 cur_udp_src;
R
Robert Olsson 已提交
351
	__u16 cur_queue_map;
L
Luiz Capitulino 已提交
352
	__u32 cur_pkt_size;
353
	__u32 last_pkt_size;
L
Luiz Capitulino 已提交
354 355 356 357 358 359 360 361 362 363 364 365

	__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 */

366
	struct sk_buff *skb;	/* skb we are to transmit next, used for when we
L
Luiz Capitulino 已提交
367 368
				 * are transmitting the same one multiple times
				 */
369 370 371 372 373 374 375 376
	struct net_device *odev; /* The out-going device.
				  * Note that the device should have it's
				  * pg_info pointer pointing back to this
				  * device.
				  * Set when the user specifies the out-going
				  * device name (not when the inject is
				  * started as it used to do.)
				  */
E
Eric Dumazet 已提交
377
	char odevname[32];
L
Linus Torvalds 已提交
378
	struct flow_state *flows;
379 380 381 382
	unsigned int cflows;	/* Concurrent flows (config) */
	unsigned int lflow;		/* Flow length  (config) */
	unsigned int nflows;	/* accumulated flows (stats) */
	unsigned int curfl;		/* current sequenced flow (state)*/
R
Robert Olsson 已提交
383 384 385

	u16 queue_map_min;
	u16 queue_map_max;
J
John Fastabend 已提交
386
	__u32 skb_priority;	/* skb priority field */
R
Robert Olsson 已提交
387
	int node;               /* Memory node */
R
Robert Olsson 已提交
388

J
Jamal Hadi Salim 已提交
389 390 391
#ifdef CONFIG_XFRM
	__u8	ipsmode;		/* IPSEC mode (config) */
	__u8	ipsproto;		/* IPSEC type (config) */
392
	__u32	spi;
J
Jamal Hadi Salim 已提交
393
#endif
394
	char result[512];
L
Linus Torvalds 已提交
395 396 397
};

struct pktgen_hdr {
A
Al Viro 已提交
398 399 400 401
	__be32 pgh_magic;
	__be32 seq_num;
	__be32 tv_sec;
	__be32 tv_usec;
L
Linus Torvalds 已提交
402 403
};

C
Cong Wang 已提交
404 405 406 407 408 409 410 411 412

static int pg_net_id __read_mostly;

struct pktgen_net {
	struct net		*net;
	struct proc_dir_entry	*proc_dir;
	struct list_head	pktgen_threads;
	bool			pktgen_exiting;
};
E
Eric Dumazet 已提交
413

L
Linus Torvalds 已提交
414
struct pktgen_thread {
415
	spinlock_t if_lock;		/* for list of devices */
416
	struct list_head if_list;	/* All device here */
417
	struct list_head th_list;
418
	struct task_struct *tsk;
L
Luiz Capitulino 已提交
419 420
	char result[512];

421 422
	/* Field for thread to receive "posted" events terminate,
	   stop ifs etc. */
L
Luiz Capitulino 已提交
423 424

	u32 control;
L
Linus Torvalds 已提交
425 426
	int cpu;

L
Luiz Capitulino 已提交
427
	wait_queue_head_t queue;
428
	struct completion start_done;
C
Cong Wang 已提交
429
	struct pktgen_net *net;
L
Linus Torvalds 已提交
430 431 432 433 434
};

#define REMOVE 1
#define FIND   0

S
Stephen Hemminger 已提交
435
static const char version[] =
J
Joe Perches 已提交
436 437
	"Packet Generator for packet performance testing. "
	"Version: " VERSION "\n";
L
Linus Torvalds 已提交
438

L
Luiz Capitulino 已提交
439 440 441
static int pktgen_remove_device(struct pktgen_thread *t, struct pktgen_dev *i);
static int pktgen_add_device(struct pktgen_thread *t, const char *ifname);
static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
E
Eric Dumazet 已提交
442
					  const char *ifname, bool exact);
L
Linus Torvalds 已提交
443
static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
C
Cong Wang 已提交
444 445 446
static void pktgen_run_all_threads(struct pktgen_net *pn);
static void pktgen_reset_all_threads(struct pktgen_net *pn);
static void pktgen_stop_all_threads_ifs(struct pktgen_net *pn);
S
Stephen Hemminger 已提交
447

L
Luiz Capitulino 已提交
448
static void pktgen_stop(struct pktgen_thread *t);
L
Linus Torvalds 已提交
449
static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
450

L
Linus Torvalds 已提交
451
/* Module parameters, defaults. */
452 453 454 455
static int pg_count_d __read_mostly = 1000;
static int pg_delay_d __read_mostly;
static int pg_clone_skb_d  __read_mostly;
static int debug  __read_mostly;
L
Linus Torvalds 已提交
456

457
static DEFINE_MUTEX(pktgen_thread_lock);
L
Linus Torvalds 已提交
458 459 460 461 462 463

static struct notifier_block pktgen_notifier_block = {
	.notifier_call = pktgen_device_event,
};

/*
464
 * /proc handling functions
L
Linus Torvalds 已提交
465 466 467
 *
 */

468
static int pgctrl_show(struct seq_file *seq, void *v)
L
Luiz Capitulino 已提交
469
{
S
Stephen Hemminger 已提交
470
	seq_puts(seq, version);
471
	return 0;
L
Linus Torvalds 已提交
472 473
}

474 475
static ssize_t pgctrl_write(struct file *file, const char __user *buf,
			    size_t count, loff_t *ppos)
L
Linus Torvalds 已提交
476 477
{
	int err = 0;
478
	char data[128];
C
Cong Wang 已提交
479
	struct pktgen_net *pn = net_generic(current->nsproxy->net_ns, pg_net_id);
L
Linus Torvalds 已提交
480

L
Luiz Capitulino 已提交
481 482
	if (!capable(CAP_NET_ADMIN)) {
		err = -EPERM;
L
Linus Torvalds 已提交
483
		goto out;
L
Luiz Capitulino 已提交
484
	}
L
Linus Torvalds 已提交
485

486 487
	if (count > sizeof(data))
		count = sizeof(data);
L
Linus Torvalds 已提交
488 489

	if (copy_from_user(data, buf, count)) {
490
		err = -EFAULT;
491
		goto out;
L
Luiz Capitulino 已提交
492 493
	}
	data[count - 1] = 0;	/* Make string */
L
Linus Torvalds 已提交
494

L
Luiz Capitulino 已提交
495
	if (!strcmp(data, "stop"))
C
Cong Wang 已提交
496
		pktgen_stop_all_threads_ifs(pn);
L
Linus Torvalds 已提交
497

L
Luiz Capitulino 已提交
498
	else if (!strcmp(data, "start"))
C
Cong Wang 已提交
499
		pktgen_run_all_threads(pn);
L
Linus Torvalds 已提交
500

501
	else if (!strcmp(data, "reset"))
C
Cong Wang 已提交
502
		pktgen_reset_all_threads(pn);
503

L
Luiz Capitulino 已提交
504
	else
J
Joe Perches 已提交
505
		pr_warning("Unknown command: %s\n", data);
L
Linus Torvalds 已提交
506 507 508

	err = count;

L
Luiz Capitulino 已提交
509 510
out:
	return err;
L
Linus Torvalds 已提交
511 512
}

513 514
static int pgctrl_open(struct inode *inode, struct file *file)
{
A
Al Viro 已提交
515
	return single_open(file, pgctrl_show, PDE_DATA(inode));
516 517
}

518
static const struct file_operations pktgen_fops = {
L
Luiz Capitulino 已提交
519 520 521 522 523 524
	.owner   = THIS_MODULE,
	.open    = pgctrl_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.write   = pgctrl_write,
	.release = single_release,
525 526 527
};

static int pktgen_if_show(struct seq_file *seq, void *v)
L
Linus Torvalds 已提交
528
{
S
Stephen Hemminger 已提交
529
	const struct pktgen_dev *pkt_dev = seq->private;
530 531
	ktime_t stopped;
	u64 idle;
L
Luiz Capitulino 已提交
532 533 534 535 536 537 538

	seq_printf(seq,
		   "Params: count %llu  min_pkt_size: %u  max_pkt_size: %u\n",
		   (unsigned long long)pkt_dev->count, pkt_dev->min_pkt_size,
		   pkt_dev->max_pkt_size);

	seq_printf(seq,
539 540
		   "     frags: %d  delay: %llu  clone_skb: %d  ifname: %s\n",
		   pkt_dev->nfrags, (unsigned long long) pkt_dev->delay,
E
Eric Dumazet 已提交
541
		   pkt_dev->clone_skb, pkt_dev->odevname);
L
Luiz Capitulino 已提交
542 543 544 545

	seq_printf(seq, "     flows: %u flowlen: %u\n", pkt_dev->cflows,
		   pkt_dev->lflow);

R
Robert Olsson 已提交
546 547 548 549 550
	seq_printf(seq,
		   "     queue_map_min: %u  queue_map_max: %u\n",
		   pkt_dev->queue_map_min,
		   pkt_dev->queue_map_max);

J
John Fastabend 已提交
551 552 553 554
	if (pkt_dev->skb_priority)
		seq_printf(seq, "     skb_priority: %u\n",
			   pkt_dev->skb_priority);

L
Luiz Capitulino 已提交
555 556
	if (pkt_dev->flags & F_IPV6) {
		seq_printf(seq,
557 558 559 560 561 562
			   "     saddr: %pI6c  min_saddr: %pI6c  max_saddr: %pI6c\n"
			   "     daddr: %pI6c  min_daddr: %pI6c  max_daddr: %pI6c\n",
			   &pkt_dev->in6_saddr,
			   &pkt_dev->min_in6_saddr, &pkt_dev->max_in6_saddr,
			   &pkt_dev->in6_daddr,
			   &pkt_dev->min_in6_daddr, &pkt_dev->max_in6_daddr);
563 564 565 566
	} else {
		seq_printf(seq,
			   "     dst_min: %s  dst_max: %s\n",
			   pkt_dev->dst_min, pkt_dev->dst_max);
L
Luiz Capitulino 已提交
567
		seq_printf(seq,
568 569 570
			   "        src_min: %s  src_max: %s\n",
			   pkt_dev->src_min, pkt_dev->src_max);
	}
L
Linus Torvalds 已提交
571

L
Luiz Capitulino 已提交
572
	seq_puts(seq, "     src_mac: ");
L
Linus Torvalds 已提交
573

J
Johannes Berg 已提交
574 575 576
	seq_printf(seq, "%pM ",
		   is_zero_ether_addr(pkt_dev->src_mac) ?
			     pkt_dev->odev->dev_addr : pkt_dev->src_mac);
L
Luiz Capitulino 已提交
577 578

	seq_printf(seq, "dst_mac: ");
J
Johannes Berg 已提交
579
	seq_printf(seq, "%pM\n", pkt_dev->dst_mac);
L
Luiz Capitulino 已提交
580 581

	seq_printf(seq,
582 583
		   "     udp_src_min: %d  udp_src_max: %d"
		   "  udp_dst_min: %d  udp_dst_max: %d\n",
L
Luiz Capitulino 已提交
584 585 586 587
		   pkt_dev->udp_src_min, pkt_dev->udp_src_max,
		   pkt_dev->udp_dst_min, pkt_dev->udp_dst_max);

	seq_printf(seq,
588
		   "     src_mac_count: %d  dst_mac_count: %d\n",
L
Luiz Capitulino 已提交
589
		   pkt_dev->src_mac_count, pkt_dev->dst_mac_count);
L
Linus Torvalds 已提交
590

591
	if (pkt_dev->nr_labels) {
592
		unsigned int i;
593
		seq_printf(seq, "     mpls: ");
594
		for (i = 0; i < pkt_dev->nr_labels; i++)
595 596 597 598
			seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]),
				   i == pkt_dev->nr_labels-1 ? "\n" : ", ");
	}

599
	if (pkt_dev->vlan_id != 0xffff)
F
Francesco Fondelli 已提交
600
		seq_printf(seq, "     vlan_id: %u  vlan_p: %u  vlan_cfi: %u\n",
601 602
			   pkt_dev->vlan_id, pkt_dev->vlan_p,
			   pkt_dev->vlan_cfi);
F
Francesco Fondelli 已提交
603

604
	if (pkt_dev->svlan_id != 0xffff)
F
Francesco Fondelli 已提交
605
		seq_printf(seq, "     svlan_id: %u  vlan_p: %u  vlan_cfi: %u\n",
606 607
			   pkt_dev->svlan_id, pkt_dev->svlan_p,
			   pkt_dev->svlan_cfi);
F
Francesco Fondelli 已提交
608

609
	if (pkt_dev->tos)
F
Francesco Fondelli 已提交
610 611
		seq_printf(seq, "     tos: 0x%02x\n", pkt_dev->tos);

612
	if (pkt_dev->traffic_class)
F
Francesco Fondelli 已提交
613 614
		seq_printf(seq, "     traffic_class: 0x%02x\n", pkt_dev->traffic_class);

R
Robert Olsson 已提交
615 616 617
	if (pkt_dev->node >= 0)
		seq_printf(seq, "     node: %d\n", pkt_dev->node);

618 619
	seq_printf(seq, "     Flags: ");

L
Luiz Capitulino 已提交
620 621
	if (pkt_dev->flags & F_IPV6)
		seq_printf(seq, "IPV6  ");
L
Linus Torvalds 已提交
622

L
Luiz Capitulino 已提交
623 624
	if (pkt_dev->flags & F_IPSRC_RND)
		seq_printf(seq, "IPSRC_RND  ");
L
Linus Torvalds 已提交
625

L
Luiz Capitulino 已提交
626 627
	if (pkt_dev->flags & F_IPDST_RND)
		seq_printf(seq, "IPDST_RND  ");
L
Linus Torvalds 已提交
628

L
Luiz Capitulino 已提交
629 630
	if (pkt_dev->flags & F_TXSIZE_RND)
		seq_printf(seq, "TXSIZE_RND  ");
L
Linus Torvalds 已提交
631

L
Luiz Capitulino 已提交
632 633
	if (pkt_dev->flags & F_UDPSRC_RND)
		seq_printf(seq, "UDPSRC_RND  ");
L
Linus Torvalds 已提交
634

L
Luiz Capitulino 已提交
635 636
	if (pkt_dev->flags & F_UDPDST_RND)
		seq_printf(seq, "UDPDST_RND  ");
L
Linus Torvalds 已提交
637

638 639 640
	if (pkt_dev->flags & F_UDPCSUM)
		seq_printf(seq, "UDPCSUM  ");

641 642 643
	if (pkt_dev->flags & F_MPLS_RND)
		seq_printf(seq,  "MPLS_RND  ");

R
Robert Olsson 已提交
644 645 646
	if (pkt_dev->flags & F_QUEUE_MAP_RND)
		seq_printf(seq,  "QUEUE_MAP_RND  ");

R
Robert Olsson 已提交
647 648 649
	if (pkt_dev->flags & F_QUEUE_MAP_CPU)
		seq_printf(seq,  "QUEUE_MAP_CPU  ");

650 651 652 653 654 655 656
	if (pkt_dev->cflows) {
		if (pkt_dev->flags & F_FLOW_SEQ)
			seq_printf(seq,  "FLOW_SEQ  "); /*in sequence flows*/
		else
			seq_printf(seq,  "FLOW_RND  ");
	}

J
Jamal Hadi Salim 已提交
657 658 659 660 661
#ifdef CONFIG_XFRM
	if (pkt_dev->flags & F_IPSEC_ON)
		seq_printf(seq,  "IPSEC  ");
#endif

L
Luiz Capitulino 已提交
662 663
	if (pkt_dev->flags & F_MACSRC_RND)
		seq_printf(seq, "MACSRC_RND  ");
L
Linus Torvalds 已提交
664

L
Luiz Capitulino 已提交
665 666
	if (pkt_dev->flags & F_MACDST_RND)
		seq_printf(seq, "MACDST_RND  ");
L
Linus Torvalds 已提交
667

F
Francesco Fondelli 已提交
668 669 670 671 672 673
	if (pkt_dev->flags & F_VID_RND)
		seq_printf(seq, "VID_RND  ");

	if (pkt_dev->flags & F_SVID_RND)
		seq_printf(seq, "SVID_RND  ");

R
Robert Olsson 已提交
674 675 676
	if (pkt_dev->flags & F_NODE)
		seq_printf(seq, "NODE_ALLOC  ");

L
Luiz Capitulino 已提交
677 678
	seq_puts(seq, "\n");

679
	/* not really stopped, more like last-running-at */
D
Daniel Borkmann 已提交
680
	stopped = pkt_dev->running ? ktime_get() : pkt_dev->stopped_at;
681 682
	idle = pkt_dev->idle_acc;
	do_div(idle, NSEC_PER_USEC);
L
Linus Torvalds 已提交
683

L
Luiz Capitulino 已提交
684
	seq_printf(seq,
685
		   "Current:\n     pkts-sofar: %llu  errors: %llu\n",
L
Luiz Capitulino 已提交
686
		   (unsigned long long)pkt_dev->sofar,
687 688 689 690 691 692 693
		   (unsigned long long)pkt_dev->errors);

	seq_printf(seq,
		   "     started: %lluus  stopped: %lluus idle: %lluus\n",
		   (unsigned long long) ktime_to_us(pkt_dev->started_at),
		   (unsigned long long) ktime_to_us(stopped),
		   (unsigned long long) idle);
L
Linus Torvalds 已提交
694

L
Luiz Capitulino 已提交
695 696
	seq_printf(seq,
		   "     seq_num: %d  cur_dst_mac_offset: %d  cur_src_mac_offset: %d\n",
697 698
		   pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset,
		   pkt_dev->cur_src_mac_offset);
L
Linus Torvalds 已提交
699

L
Luiz Capitulino 已提交
700
	if (pkt_dev->flags & F_IPV6) {
701 702 703
		seq_printf(seq, "     cur_saddr: %pI6c  cur_daddr: %pI6c\n",
				&pkt_dev->cur_in6_saddr,
				&pkt_dev->cur_in6_daddr);
L
Luiz Capitulino 已提交
704
	} else
705 706
		seq_printf(seq, "     cur_saddr: %pI4  cur_daddr: %pI4\n",
			   &pkt_dev->cur_saddr, &pkt_dev->cur_daddr);
L
Linus Torvalds 已提交
707

L
Luiz Capitulino 已提交
708
	seq_printf(seq, "     cur_udp_dst: %d  cur_udp_src: %d\n",
709
		   pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src);
L
Linus Torvalds 已提交
710

R
Robert Olsson 已提交
711 712
	seq_printf(seq, "     cur_queue_map: %u\n", pkt_dev->cur_queue_map);

L
Luiz Capitulino 已提交
713
	seq_printf(seq, "     flows: %u\n", pkt_dev->nflows);
L
Linus Torvalds 已提交
714 715

	if (pkt_dev->result[0])
L
Luiz Capitulino 已提交
716
		seq_printf(seq, "Result: %s\n", pkt_dev->result);
L
Linus Torvalds 已提交
717
	else
L
Luiz Capitulino 已提交
718
		seq_printf(seq, "Result: Idle\n");
L
Linus Torvalds 已提交
719

720
	return 0;
L
Linus Torvalds 已提交
721 722
}

723

724 725
static int hex32_arg(const char __user *user_buffer, unsigned long maxlen,
		     __u32 *num)
726 727 728 729
{
	int i = 0;
	*num = 0;

730
	for (; i < maxlen; i++) {
731
		int value;
732 733 734 735
		char c;
		*num <<= 4;
		if (get_user(c, &user_buffer[i]))
			return -EFAULT;
736 737 738
		value = hex_to_bin(c);
		if (value >= 0)
			*num |= value;
739 740 741 742 743 744
		else
			break;
	}
	return i;
}

L
Luiz Capitulino 已提交
745 746
static int count_trail_chars(const char __user * user_buffer,
			     unsigned int maxlen)
L
Linus Torvalds 已提交
747 748 749 750
{
	int i;

	for (i = 0; i < maxlen; i++) {
L
Luiz Capitulino 已提交
751 752 753 754
		char c;
		if (get_user(c, &user_buffer[i]))
			return -EFAULT;
		switch (c) {
L
Linus Torvalds 已提交
755 756 757 758 759 760 761 762 763
		case '\"':
		case '\n':
		case '\r':
		case '\t':
		case ' ':
		case '=':
			break;
		default:
			goto done;
764
		}
L
Linus Torvalds 已提交
765 766 767 768 769
	}
done:
	return i;
}

770 771
static long num_arg(const char __user *user_buffer, unsigned long maxlen,
				unsigned long *num)
L
Linus Torvalds 已提交
772
{
773
	int i;
L
Linus Torvalds 已提交
774
	*num = 0;
L
Luiz Capitulino 已提交
775

776
	for (i = 0; i < maxlen; i++) {
L
Luiz Capitulino 已提交
777 778 779 780
		char c;
		if (get_user(c, &user_buffer[i]))
			return -EFAULT;
		if ((c >= '0') && (c <= '9')) {
L
Linus Torvalds 已提交
781
			*num *= 10;
L
Luiz Capitulino 已提交
782
			*num += c - '0';
L
Linus Torvalds 已提交
783 784 785 786 787 788
		} else
			break;
	}
	return i;
}

L
Luiz Capitulino 已提交
789
static int strn_len(const char __user * user_buffer, unsigned int maxlen)
L
Linus Torvalds 已提交
790
{
791
	int i;
L
Linus Torvalds 已提交
792

793
	for (i = 0; i < maxlen; i++) {
L
Luiz Capitulino 已提交
794 795 796 797
		char c;
		if (get_user(c, &user_buffer[i]))
			return -EFAULT;
		switch (c) {
L
Linus Torvalds 已提交
798 799 800 801 802 803 804 805 806
		case '\"':
		case '\n':
		case '\r':
		case '\t':
		case ' ':
			goto done_str;
			break;
		default:
			break;
807
		}
L
Linus Torvalds 已提交
808 809 810 811 812
	}
done_str:
	return i;
}

813 814
static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
{
815
	unsigned int n = 0;
816 817 818 819 820 821 822
	char c;
	ssize_t i = 0;
	int len;

	pkt_dev->nr_labels = 0;
	do {
		__u32 tmp;
F
Francesco Fondelli 已提交
823
		len = hex32_arg(&buffer[i], 8, &tmp);
824 825 826 827 828 829 830 831 832 833 834 835
		if (len <= 0)
			return len;
		pkt_dev->labels[n] = htonl(tmp);
		if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM)
			pkt_dev->flags |= F_MPLS_RND;
		i += len;
		if (get_user(c, &buffer[i]))
			return -EFAULT;
		i++;
		n++;
		if (n >= MAX_MPLS_LABELS)
			return -E2BIG;
836
	} while (c == ',');
837 838 839 840 841

	pkt_dev->nr_labels = n;
	return i;
}

L
Luiz Capitulino 已提交
842 843 844
static ssize_t pktgen_if_write(struct file *file,
			       const char __user * user_buffer, size_t count,
			       loff_t * offset)
L
Linus Torvalds 已提交
845
{
846
	struct seq_file *seq = file->private_data;
L
Luiz Capitulino 已提交
847
	struct pktgen_dev *pkt_dev = seq->private;
848
	int i, max, len;
L
Linus Torvalds 已提交
849 850
	char name[16], valstr[32];
	unsigned long value = 0;
L
Luiz Capitulino 已提交
851 852
	char *pg_result = NULL;
	int tmp = 0;
L
Linus Torvalds 已提交
853
	char buf[128];
L
Luiz Capitulino 已提交
854 855 856

	pg_result = &(pkt_dev->result[0]);

L
Linus Torvalds 已提交
857
	if (count < 1) {
J
Joe Perches 已提交
858
		pr_warning("wrong command format\n");
L
Linus Torvalds 已提交
859 860
		return -EINVAL;
	}
L
Luiz Capitulino 已提交
861

862 863
	max = count;
	tmp = count_trail_chars(user_buffer, max);
L
Luiz Capitulino 已提交
864
	if (tmp < 0) {
J
Joe Perches 已提交
865
		pr_warning("illegal format\n");
L
Luiz Capitulino 已提交
866
		return tmp;
L
Linus Torvalds 已提交
867
	}
868
	i = tmp;
L
Luiz Capitulino 已提交
869

L
Linus Torvalds 已提交
870 871 872
	/* Read variable name */

	len = strn_len(&user_buffer[i], sizeof(name) - 1);
873
	if (len < 0)
L
Luiz Capitulino 已提交
874
		return len;
875

L
Linus Torvalds 已提交
876
	memset(name, 0, sizeof(name));
L
Luiz Capitulino 已提交
877
	if (copy_from_user(name, &user_buffer[i], len))
L
Linus Torvalds 已提交
878 879
		return -EFAULT;
	i += len;
L
Luiz Capitulino 已提交
880 881

	max = count - i;
L
Linus Torvalds 已提交
882
	len = count_trail_chars(&user_buffer[i], max);
L
Luiz Capitulino 已提交
883 884 885
	if (len < 0)
		return len;

L
Linus Torvalds 已提交
886 887 888
	i += len;

	if (debug) {
889
		size_t copy = min_t(size_t, count, 1023);
890 891
		char tb[copy + 1];
		if (copy_from_user(tb, user_buffer, copy))
L
Linus Torvalds 已提交
892
			return -EFAULT;
893
		tb[copy] = 0;
J
Joe Perches 已提交
894 895
		pr_debug("%s,%lu  buffer -:%s:-\n",
			 name, (unsigned long)count, tb);
L
Luiz Capitulino 已提交
896
	}
L
Linus Torvalds 已提交
897 898 899

	if (!strcmp(name, "min_pkt_size")) {
		len = num_arg(&user_buffer[i], 10, &value);
900
		if (len < 0)
L
Luiz Capitulino 已提交
901
			return len;
902

L
Linus Torvalds 已提交
903
		i += len;
L
Luiz Capitulino 已提交
904 905 906 907 908 909 910 911
		if (value < 14 + 20 + 8)
			value = 14 + 20 + 8;
		if (value != pkt_dev->min_pkt_size) {
			pkt_dev->min_pkt_size = value;
			pkt_dev->cur_pkt_size = value;
		}
		sprintf(pg_result, "OK: min_pkt_size=%u",
			pkt_dev->min_pkt_size);
L
Linus Torvalds 已提交
912 913 914
		return count;
	}

L
Luiz Capitulino 已提交
915
	if (!strcmp(name, "max_pkt_size")) {
L
Linus Torvalds 已提交
916
		len = num_arg(&user_buffer[i], 10, &value);
917
		if (len < 0)
L
Luiz Capitulino 已提交
918
			return len;
919

L
Linus Torvalds 已提交
920
		i += len;
L
Luiz Capitulino 已提交
921 922 923 924 925 926 927 928
		if (value < 14 + 20 + 8)
			value = 14 + 20 + 8;
		if (value != pkt_dev->max_pkt_size) {
			pkt_dev->max_pkt_size = value;
			pkt_dev->cur_pkt_size = value;
		}
		sprintf(pg_result, "OK: max_pkt_size=%u",
			pkt_dev->max_pkt_size);
L
Linus Torvalds 已提交
929 930 931
		return count;
	}

L
Luiz Capitulino 已提交
932
	/* Shortcut for min = max */
L
Linus Torvalds 已提交
933 934 935

	if (!strcmp(name, "pkt_size")) {
		len = num_arg(&user_buffer[i], 10, &value);
936
		if (len < 0)
L
Luiz Capitulino 已提交
937
			return len;
938

L
Linus Torvalds 已提交
939
		i += len;
L
Luiz Capitulino 已提交
940 941 942 943 944 945 946
		if (value < 14 + 20 + 8)
			value = 14 + 20 + 8;
		if (value != pkt_dev->min_pkt_size) {
			pkt_dev->min_pkt_size = value;
			pkt_dev->max_pkt_size = value;
			pkt_dev->cur_pkt_size = value;
		}
L
Linus Torvalds 已提交
947 948 949 950
		sprintf(pg_result, "OK: pkt_size=%u", pkt_dev->min_pkt_size);
		return count;
	}

L
Luiz Capitulino 已提交
951
	if (!strcmp(name, "debug")) {
L
Linus Torvalds 已提交
952
		len = num_arg(&user_buffer[i], 10, &value);
953
		if (len < 0)
L
Luiz Capitulino 已提交
954
			return len;
955

L
Linus Torvalds 已提交
956
		i += len;
L
Luiz Capitulino 已提交
957
		debug = value;
L
Linus Torvalds 已提交
958 959 960 961
		sprintf(pg_result, "OK: debug=%u", debug);
		return count;
	}

L
Luiz Capitulino 已提交
962
	if (!strcmp(name, "frags")) {
L
Linus Torvalds 已提交
963
		len = num_arg(&user_buffer[i], 10, &value);
964
		if (len < 0)
L
Luiz Capitulino 已提交
965
			return len;
966

L
Linus Torvalds 已提交
967 968 969 970 971 972 973
		i += len;
		pkt_dev->nfrags = value;
		sprintf(pg_result, "OK: frags=%u", pkt_dev->nfrags);
		return count;
	}
	if (!strcmp(name, "delay")) {
		len = num_arg(&user_buffer[i], 10, &value);
974
		if (len < 0)
L
Luiz Capitulino 已提交
975
			return len;
976

L
Linus Torvalds 已提交
977
		i += len;
978 979 980
		if (value == 0x7FFFFFFF)
			pkt_dev->delay = ULLONG_MAX;
		else
E
Eric Dumazet 已提交
981
			pkt_dev->delay = (u64)value;
982 983 984

		sprintf(pg_result, "OK: delay=%llu",
			(unsigned long long) pkt_dev->delay);
L
Linus Torvalds 已提交
985 986
		return count;
	}
987 988 989 990 991 992 993 994 995 996
	if (!strcmp(name, "rate")) {
		len = num_arg(&user_buffer[i], 10, &value);
		if (len < 0)
			return len;

		i += len;
		if (!value)
			return len;
		pkt_dev->delay = pkt_dev->min_pkt_size*8*NSEC_PER_USEC/value;
		if (debug)
J
Joe Perches 已提交
997
			pr_info("Delay set at: %llu ns\n", pkt_dev->delay);
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011

		sprintf(pg_result, "OK: rate=%lu", value);
		return count;
	}
	if (!strcmp(name, "ratep")) {
		len = num_arg(&user_buffer[i], 10, &value);
		if (len < 0)
			return len;

		i += len;
		if (!value)
			return len;
		pkt_dev->delay = NSEC_PER_SEC/value;
		if (debug)
J
Joe Perches 已提交
1012
			pr_info("Delay set at: %llu ns\n", pkt_dev->delay);
1013 1014 1015 1016

		sprintf(pg_result, "OK: rate=%lu", value);
		return count;
	}
L
Luiz Capitulino 已提交
1017
	if (!strcmp(name, "udp_src_min")) {
L
Linus Torvalds 已提交
1018
		len = num_arg(&user_buffer[i], 10, &value);
1019
		if (len < 0)
L
Luiz Capitulino 已提交
1020
			return len;
1021

L
Linus Torvalds 已提交
1022
		i += len;
L
Luiz Capitulino 已提交
1023 1024 1025 1026
		if (value != pkt_dev->udp_src_min) {
			pkt_dev->udp_src_min = value;
			pkt_dev->cur_udp_src = value;
		}
L
Linus Torvalds 已提交
1027 1028 1029
		sprintf(pg_result, "OK: udp_src_min=%u", pkt_dev->udp_src_min);
		return count;
	}
L
Luiz Capitulino 已提交
1030
	if (!strcmp(name, "udp_dst_min")) {
L
Linus Torvalds 已提交
1031
		len = num_arg(&user_buffer[i], 10, &value);
1032
		if (len < 0)
L
Luiz Capitulino 已提交
1033
			return len;
1034

L
Linus Torvalds 已提交
1035
		i += len;
L
Luiz Capitulino 已提交
1036 1037 1038 1039
		if (value != pkt_dev->udp_dst_min) {
			pkt_dev->udp_dst_min = value;
			pkt_dev->cur_udp_dst = value;
		}
L
Linus Torvalds 已提交
1040 1041 1042
		sprintf(pg_result, "OK: udp_dst_min=%u", pkt_dev->udp_dst_min);
		return count;
	}
L
Luiz Capitulino 已提交
1043
	if (!strcmp(name, "udp_src_max")) {
L
Linus Torvalds 已提交
1044
		len = num_arg(&user_buffer[i], 10, &value);
1045
		if (len < 0)
L
Luiz Capitulino 已提交
1046
			return len;
1047

L
Linus Torvalds 已提交
1048
		i += len;
L
Luiz Capitulino 已提交
1049 1050 1051 1052
		if (value != pkt_dev->udp_src_max) {
			pkt_dev->udp_src_max = value;
			pkt_dev->cur_udp_src = value;
		}
L
Linus Torvalds 已提交
1053 1054 1055
		sprintf(pg_result, "OK: udp_src_max=%u", pkt_dev->udp_src_max);
		return count;
	}
L
Luiz Capitulino 已提交
1056
	if (!strcmp(name, "udp_dst_max")) {
L
Linus Torvalds 已提交
1057
		len = num_arg(&user_buffer[i], 10, &value);
1058
		if (len < 0)
L
Luiz Capitulino 已提交
1059
			return len;
1060

L
Linus Torvalds 已提交
1061
		i += len;
L
Luiz Capitulino 已提交
1062 1063 1064 1065
		if (value != pkt_dev->udp_dst_max) {
			pkt_dev->udp_dst_max = value;
			pkt_dev->cur_udp_dst = value;
		}
L
Linus Torvalds 已提交
1066 1067 1068 1069 1070
		sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max);
		return count;
	}
	if (!strcmp(name, "clone_skb")) {
		len = num_arg(&user_buffer[i], 10, &value);
1071
		if (len < 0)
L
Luiz Capitulino 已提交
1072
			return len;
1073 1074 1075
		if ((value > 0) &&
		    (!(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)))
			return -ENOTSUPP;
L
Linus Torvalds 已提交
1076
		i += len;
L
Luiz Capitulino 已提交
1077 1078
		pkt_dev->clone_skb = value;

L
Linus Torvalds 已提交
1079 1080 1081 1082 1083
		sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb);
		return count;
	}
	if (!strcmp(name, "count")) {
		len = num_arg(&user_buffer[i], 10, &value);
1084
		if (len < 0)
L
Luiz Capitulino 已提交
1085
			return len;
1086

L
Linus Torvalds 已提交
1087 1088 1089
		i += len;
		pkt_dev->count = value;
		sprintf(pg_result, "OK: count=%llu",
L
Luiz Capitulino 已提交
1090
			(unsigned long long)pkt_dev->count);
L
Linus Torvalds 已提交
1091 1092 1093 1094
		return count;
	}
	if (!strcmp(name, "src_mac_count")) {
		len = num_arg(&user_buffer[i], 10, &value);
1095
		if (len < 0)
L
Luiz Capitulino 已提交
1096
			return len;
1097

L
Linus Torvalds 已提交
1098 1099
		i += len;
		if (pkt_dev->src_mac_count != value) {
L
Luiz Capitulino 已提交
1100 1101 1102 1103 1104
			pkt_dev->src_mac_count = value;
			pkt_dev->cur_src_mac_offset = 0;
		}
		sprintf(pg_result, "OK: src_mac_count=%d",
			pkt_dev->src_mac_count);
L
Linus Torvalds 已提交
1105 1106 1107 1108
		return count;
	}
	if (!strcmp(name, "dst_mac_count")) {
		len = num_arg(&user_buffer[i], 10, &value);
1109
		if (len < 0)
L
Luiz Capitulino 已提交
1110
			return len;
1111

L
Linus Torvalds 已提交
1112 1113
		i += len;
		if (pkt_dev->dst_mac_count != value) {
L
Luiz Capitulino 已提交
1114 1115 1116 1117 1118
			pkt_dev->dst_mac_count = value;
			pkt_dev->cur_dst_mac_offset = 0;
		}
		sprintf(pg_result, "OK: dst_mac_count=%d",
			pkt_dev->dst_mac_count);
L
Linus Torvalds 已提交
1119 1120
		return count;
	}
R
Robert Olsson 已提交
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
	if (!strcmp(name, "node")) {
		len = num_arg(&user_buffer[i], 10, &value);
		if (len < 0)
			return len;

		i += len;

		if (node_possible(value)) {
			pkt_dev->node = value;
			sprintf(pg_result, "OK: node=%d", pkt_dev->node);
E
Eric Dumazet 已提交
1131 1132 1133 1134
			if (pkt_dev->page) {
				put_page(pkt_dev->page);
				pkt_dev->page = NULL;
			}
R
Robert Olsson 已提交
1135 1136 1137 1138 1139
		}
		else
			sprintf(pg_result, "ERROR: node not possible");
		return count;
	}
L
Linus Torvalds 已提交
1140
	if (!strcmp(name, "flag")) {
L
Luiz Capitulino 已提交
1141 1142
		char f[32];
		memset(f, 0, 32);
L
Linus Torvalds 已提交
1143
		len = strn_len(&user_buffer[i], sizeof(f) - 1);
1144
		if (len < 0)
L
Luiz Capitulino 已提交
1145
			return len;
1146

L
Linus Torvalds 已提交
1147 1148 1149
		if (copy_from_user(f, &user_buffer[i], len))
			return -EFAULT;
		i += len;
L
Luiz Capitulino 已提交
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191
		if (strcmp(f, "IPSRC_RND") == 0)
			pkt_dev->flags |= F_IPSRC_RND;

		else if (strcmp(f, "!IPSRC_RND") == 0)
			pkt_dev->flags &= ~F_IPSRC_RND;

		else if (strcmp(f, "TXSIZE_RND") == 0)
			pkt_dev->flags |= F_TXSIZE_RND;

		else if (strcmp(f, "!TXSIZE_RND") == 0)
			pkt_dev->flags &= ~F_TXSIZE_RND;

		else if (strcmp(f, "IPDST_RND") == 0)
			pkt_dev->flags |= F_IPDST_RND;

		else if (strcmp(f, "!IPDST_RND") == 0)
			pkt_dev->flags &= ~F_IPDST_RND;

		else if (strcmp(f, "UDPSRC_RND") == 0)
			pkt_dev->flags |= F_UDPSRC_RND;

		else if (strcmp(f, "!UDPSRC_RND") == 0)
			pkt_dev->flags &= ~F_UDPSRC_RND;

		else if (strcmp(f, "UDPDST_RND") == 0)
			pkt_dev->flags |= F_UDPDST_RND;

		else if (strcmp(f, "!UDPDST_RND") == 0)
			pkt_dev->flags &= ~F_UDPDST_RND;

		else if (strcmp(f, "MACSRC_RND") == 0)
			pkt_dev->flags |= F_MACSRC_RND;

		else if (strcmp(f, "!MACSRC_RND") == 0)
			pkt_dev->flags &= ~F_MACSRC_RND;

		else if (strcmp(f, "MACDST_RND") == 0)
			pkt_dev->flags |= F_MACDST_RND;

		else if (strcmp(f, "!MACDST_RND") == 0)
			pkt_dev->flags &= ~F_MACDST_RND;

1192 1193 1194 1195 1196 1197
		else if (strcmp(f, "MPLS_RND") == 0)
			pkt_dev->flags |= F_MPLS_RND;

		else if (strcmp(f, "!MPLS_RND") == 0)
			pkt_dev->flags &= ~F_MPLS_RND;

F
Francesco Fondelli 已提交
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209
		else if (strcmp(f, "VID_RND") == 0)
			pkt_dev->flags |= F_VID_RND;

		else if (strcmp(f, "!VID_RND") == 0)
			pkt_dev->flags &= ~F_VID_RND;

		else if (strcmp(f, "SVID_RND") == 0)
			pkt_dev->flags |= F_SVID_RND;

		else if (strcmp(f, "!SVID_RND") == 0)
			pkt_dev->flags &= ~F_SVID_RND;

1210 1211 1212
		else if (strcmp(f, "FLOW_SEQ") == 0)
			pkt_dev->flags |= F_FLOW_SEQ;

R
Robert Olsson 已提交
1213 1214 1215 1216 1217
		else if (strcmp(f, "QUEUE_MAP_RND") == 0)
			pkt_dev->flags |= F_QUEUE_MAP_RND;

		else if (strcmp(f, "!QUEUE_MAP_RND") == 0)
			pkt_dev->flags &= ~F_QUEUE_MAP_RND;
R
Robert Olsson 已提交
1218 1219 1220 1221 1222 1223

		else if (strcmp(f, "QUEUE_MAP_CPU") == 0)
			pkt_dev->flags |= F_QUEUE_MAP_CPU;

		else if (strcmp(f, "!QUEUE_MAP_CPU") == 0)
			pkt_dev->flags &= ~F_QUEUE_MAP_CPU;
J
Jamal Hadi Salim 已提交
1224 1225 1226 1227 1228
#ifdef CONFIG_XFRM
		else if (strcmp(f, "IPSEC") == 0)
			pkt_dev->flags |= F_IPSEC_ON;
#endif

F
Francesco Fondelli 已提交
1229 1230 1231
		else if (strcmp(f, "!IPV6") == 0)
			pkt_dev->flags &= ~F_IPV6;

R
Robert Olsson 已提交
1232 1233 1234 1235 1236 1237
		else if (strcmp(f, "NODE_ALLOC") == 0)
			pkt_dev->flags |= F_NODE;

		else if (strcmp(f, "!NODE_ALLOC") == 0)
			pkt_dev->flags &= ~F_NODE;

1238 1239 1240 1241 1242 1243
		else if (strcmp(f, "UDPCSUM") == 0)
			pkt_dev->flags |= F_UDPCSUM;

		else if (strcmp(f, "!UDPCSUM") == 0)
			pkt_dev->flags &= ~F_UDPCSUM;

L
Luiz Capitulino 已提交
1244 1245 1246 1247
		else {
			sprintf(pg_result,
				"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
				f,
F
Francesco Fondelli 已提交
1248
				"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, "
R
Robert Olsson 已提交
1249
				"MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC, NODE_ALLOC\n");
L
Luiz Capitulino 已提交
1250 1251
			return count;
		}
L
Linus Torvalds 已提交
1252 1253 1254 1255 1256
		sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
		return count;
	}
	if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
		len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1);
1257
		if (len < 0)
L
Luiz Capitulino 已提交
1258
			return len;
L
Linus Torvalds 已提交
1259

L
Luiz Capitulino 已提交
1260
		if (copy_from_user(buf, &user_buffer[i], len))
L
Linus Torvalds 已提交
1261
			return -EFAULT;
L
Luiz Capitulino 已提交
1262 1263 1264 1265 1266 1267 1268 1269
		buf[len] = 0;
		if (strcmp(buf, pkt_dev->dst_min) != 0) {
			memset(pkt_dev->dst_min, 0, sizeof(pkt_dev->dst_min));
			strncpy(pkt_dev->dst_min, buf, len);
			pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
			pkt_dev->cur_daddr = pkt_dev->daddr_min;
		}
		if (debug)
J
Joe Perches 已提交
1270
			pr_debug("dst_min set to: %s\n", pkt_dev->dst_min);
L
Luiz Capitulino 已提交
1271
		i += len;
L
Linus Torvalds 已提交
1272 1273 1274 1275 1276
		sprintf(pg_result, "OK: dst_min=%s", pkt_dev->dst_min);
		return count;
	}
	if (!strcmp(name, "dst_max")) {
		len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1);
1277
		if (len < 0)
L
Luiz Capitulino 已提交
1278
			return len;
1279

L
Linus Torvalds 已提交
1280

L
Luiz Capitulino 已提交
1281
		if (copy_from_user(buf, &user_buffer[i], len))
L
Linus Torvalds 已提交
1282 1283
			return -EFAULT;

L
Luiz Capitulino 已提交
1284 1285 1286 1287 1288 1289 1290 1291
		buf[len] = 0;
		if (strcmp(buf, pkt_dev->dst_max) != 0) {
			memset(pkt_dev->dst_max, 0, sizeof(pkt_dev->dst_max));
			strncpy(pkt_dev->dst_max, buf, len);
			pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
			pkt_dev->cur_daddr = pkt_dev->daddr_max;
		}
		if (debug)
J
Joe Perches 已提交
1292
			pr_debug("dst_max set to: %s\n", pkt_dev->dst_max);
L
Linus Torvalds 已提交
1293 1294 1295 1296 1297 1298
		i += len;
		sprintf(pg_result, "OK: dst_max=%s", pkt_dev->dst_max);
		return count;
	}
	if (!strcmp(name, "dst6")) {
		len = strn_len(&user_buffer[i], sizeof(buf) - 1);
L
Luiz Capitulino 已提交
1299 1300
		if (len < 0)
			return len;
L
Linus Torvalds 已提交
1301 1302 1303

		pkt_dev->flags |= F_IPV6;

L
Luiz Capitulino 已提交
1304
		if (copy_from_user(buf, &user_buffer[i], len))
L
Linus Torvalds 已提交
1305
			return -EFAULT;
L
Luiz Capitulino 已提交
1306
		buf[len] = 0;
L
Linus Torvalds 已提交
1307

1308
		in6_pton(buf, -1, pkt_dev->in6_daddr.s6_addr, -1, NULL);
1309
		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr);
L
Linus Torvalds 已提交
1310

A
Alexey Dobriyan 已提交
1311
		pkt_dev->cur_in6_daddr = pkt_dev->in6_daddr;
L
Linus Torvalds 已提交
1312

L
Luiz Capitulino 已提交
1313
		if (debug)
J
Joe Perches 已提交
1314
			pr_debug("dst6 set to: %s\n", buf);
L
Linus Torvalds 已提交
1315

L
Luiz Capitulino 已提交
1316
		i += len;
L
Linus Torvalds 已提交
1317 1318 1319 1320 1321
		sprintf(pg_result, "OK: dst6=%s", buf);
		return count;
	}
	if (!strcmp(name, "dst6_min")) {
		len = strn_len(&user_buffer[i], sizeof(buf) - 1);
L
Luiz Capitulino 已提交
1322 1323
		if (len < 0)
			return len;
L
Linus Torvalds 已提交
1324 1325 1326

		pkt_dev->flags |= F_IPV6;

L
Luiz Capitulino 已提交
1327
		if (copy_from_user(buf, &user_buffer[i], len))
L
Linus Torvalds 已提交
1328
			return -EFAULT;
L
Luiz Capitulino 已提交
1329
		buf[len] = 0;
L
Linus Torvalds 已提交
1330

1331
		in6_pton(buf, -1, pkt_dev->min_in6_daddr.s6_addr, -1, NULL);
1332
		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr);
L
Linus Torvalds 已提交
1333

A
Alexey Dobriyan 已提交
1334
		pkt_dev->cur_in6_daddr = pkt_dev->min_in6_daddr;
L
Luiz Capitulino 已提交
1335
		if (debug)
J
Joe Perches 已提交
1336
			pr_debug("dst6_min set to: %s\n", buf);
L
Linus Torvalds 已提交
1337

L
Luiz Capitulino 已提交
1338
		i += len;
L
Linus Torvalds 已提交
1339 1340 1341 1342 1343
		sprintf(pg_result, "OK: dst6_min=%s", buf);
		return count;
	}
	if (!strcmp(name, "dst6_max")) {
		len = strn_len(&user_buffer[i], sizeof(buf) - 1);
L
Luiz Capitulino 已提交
1344 1345
		if (len < 0)
			return len;
L
Linus Torvalds 已提交
1346 1347 1348

		pkt_dev->flags |= F_IPV6;

L
Luiz Capitulino 已提交
1349
		if (copy_from_user(buf, &user_buffer[i], len))
L
Linus Torvalds 已提交
1350
			return -EFAULT;
L
Luiz Capitulino 已提交
1351
		buf[len] = 0;
L
Linus Torvalds 已提交
1352

1353
		in6_pton(buf, -1, pkt_dev->max_in6_daddr.s6_addr, -1, NULL);
1354
		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr);
L
Linus Torvalds 已提交
1355

L
Luiz Capitulino 已提交
1356
		if (debug)
J
Joe Perches 已提交
1357
			pr_debug("dst6_max set to: %s\n", buf);
L
Linus Torvalds 已提交
1358

L
Luiz Capitulino 已提交
1359
		i += len;
L
Linus Torvalds 已提交
1360 1361 1362 1363 1364
		sprintf(pg_result, "OK: dst6_max=%s", buf);
		return count;
	}
	if (!strcmp(name, "src6")) {
		len = strn_len(&user_buffer[i], sizeof(buf) - 1);
L
Luiz Capitulino 已提交
1365 1366
		if (len < 0)
			return len;
L
Linus Torvalds 已提交
1367 1368 1369

		pkt_dev->flags |= F_IPV6;

L
Luiz Capitulino 已提交
1370
		if (copy_from_user(buf, &user_buffer[i], len))
L
Linus Torvalds 已提交
1371
			return -EFAULT;
L
Luiz Capitulino 已提交
1372
		buf[len] = 0;
L
Linus Torvalds 已提交
1373

1374
		in6_pton(buf, -1, pkt_dev->in6_saddr.s6_addr, -1, NULL);
1375
		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr);
L
Linus Torvalds 已提交
1376

A
Alexey Dobriyan 已提交
1377
		pkt_dev->cur_in6_saddr = pkt_dev->in6_saddr;
L
Linus Torvalds 已提交
1378

L
Luiz Capitulino 已提交
1379
		if (debug)
J
Joe Perches 已提交
1380
			pr_debug("src6 set to: %s\n", buf);
L
Luiz Capitulino 已提交
1381 1382

		i += len;
L
Linus Torvalds 已提交
1383 1384 1385 1386 1387
		sprintf(pg_result, "OK: src6=%s", buf);
		return count;
	}
	if (!strcmp(name, "src_min")) {
		len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1);
1388
		if (len < 0)
L
Luiz Capitulino 已提交
1389
			return len;
1390

L
Luiz Capitulino 已提交
1391
		if (copy_from_user(buf, &user_buffer[i], len))
L
Linus Torvalds 已提交
1392
			return -EFAULT;
L
Luiz Capitulino 已提交
1393 1394 1395 1396 1397 1398 1399 1400
		buf[len] = 0;
		if (strcmp(buf, pkt_dev->src_min) != 0) {
			memset(pkt_dev->src_min, 0, sizeof(pkt_dev->src_min));
			strncpy(pkt_dev->src_min, buf, len);
			pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
			pkt_dev->cur_saddr = pkt_dev->saddr_min;
		}
		if (debug)
J
Joe Perches 已提交
1401
			pr_debug("src_min set to: %s\n", pkt_dev->src_min);
L
Linus Torvalds 已提交
1402 1403 1404 1405 1406 1407
		i += len;
		sprintf(pg_result, "OK: src_min=%s", pkt_dev->src_min);
		return count;
	}
	if (!strcmp(name, "src_max")) {
		len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1);
1408
		if (len < 0)
L
Luiz Capitulino 已提交
1409
			return len;
1410

L
Luiz Capitulino 已提交
1411
		if (copy_from_user(buf, &user_buffer[i], len))
L
Linus Torvalds 已提交
1412
			return -EFAULT;
L
Luiz Capitulino 已提交
1413 1414 1415 1416 1417 1418 1419 1420
		buf[len] = 0;
		if (strcmp(buf, pkt_dev->src_max) != 0) {
			memset(pkt_dev->src_max, 0, sizeof(pkt_dev->src_max));
			strncpy(pkt_dev->src_max, buf, len);
			pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
			pkt_dev->cur_saddr = pkt_dev->saddr_max;
		}
		if (debug)
J
Joe Perches 已提交
1421
			pr_debug("src_max set to: %s\n", pkt_dev->src_max);
L
Linus Torvalds 已提交
1422 1423 1424 1425 1426 1427
		i += len;
		sprintf(pg_result, "OK: src_max=%s", pkt_dev->src_max);
		return count;
	}
	if (!strcmp(name, "dst_mac")) {
		len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1428
		if (len < 0)
L
Luiz Capitulino 已提交
1429
			return len;
1430

L
Linus Torvalds 已提交
1431
		memset(valstr, 0, sizeof(valstr));
L
Luiz Capitulino 已提交
1432
		if (copy_from_user(valstr, &user_buffer[i], len))
L
Linus Torvalds 已提交
1433 1434
			return -EFAULT;

1435 1436
		if (!mac_pton(valstr, pkt_dev->dst_mac))
			return -EINVAL;
L
Linus Torvalds 已提交
1437
		/* Set up Dest MAC */
1438
		memcpy(&pkt_dev->hh[0], pkt_dev->dst_mac, ETH_ALEN);
L
Luiz Capitulino 已提交
1439

1440
		sprintf(pg_result, "OK: dstmac %pM", pkt_dev->dst_mac);
L
Linus Torvalds 已提交
1441 1442 1443 1444
		return count;
	}
	if (!strcmp(name, "src_mac")) {
		len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
1445
		if (len < 0)
L
Luiz Capitulino 已提交
1446
			return len;
1447

L
Linus Torvalds 已提交
1448
		memset(valstr, 0, sizeof(valstr));
L
Luiz Capitulino 已提交
1449
		if (copy_from_user(valstr, &user_buffer[i], len))
L
Linus Torvalds 已提交
1450 1451
			return -EFAULT;

1452 1453
		if (!mac_pton(valstr, pkt_dev->src_mac))
			return -EINVAL;
A
Adit Ranadive 已提交
1454
		/* Set up Src MAC */
1455
		memcpy(&pkt_dev->hh[6], pkt_dev->src_mac, ETH_ALEN);
A
Adit Ranadive 已提交
1456

1457
		sprintf(pg_result, "OK: srcmac %pM", pkt_dev->src_mac);
L
Linus Torvalds 已提交
1458 1459 1460
		return count;
	}

L
Luiz Capitulino 已提交
1461 1462 1463 1464 1465
	if (!strcmp(name, "clear_counters")) {
		pktgen_clear_counters(pkt_dev);
		sprintf(pg_result, "OK: Clearing counters.\n");
		return count;
	}
L
Linus Torvalds 已提交
1466 1467 1468

	if (!strcmp(name, "flows")) {
		len = num_arg(&user_buffer[i], 10, &value);
1469
		if (len < 0)
L
Luiz Capitulino 已提交
1470
			return len;
1471

L
Linus Torvalds 已提交
1472 1473 1474 1475 1476 1477 1478 1479 1480
		i += len;
		if (value > MAX_CFLOWS)
			value = MAX_CFLOWS;

		pkt_dev->cflows = value;
		sprintf(pg_result, "OK: flows=%u", pkt_dev->cflows);
		return count;
	}

1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
	if (!strcmp(name, "spi")) {
		len = num_arg(&user_buffer[i], 10, &value);
		if (len < 0)
			return len;

		i += len;
		pkt_dev->spi = value;
		sprintf(pg_result, "OK: spi=%u", pkt_dev->spi);
		return count;
	}

L
Linus Torvalds 已提交
1492 1493
	if (!strcmp(name, "flowlen")) {
		len = num_arg(&user_buffer[i], 10, &value);
1494
		if (len < 0)
L
Luiz Capitulino 已提交
1495
			return len;
1496

L
Linus Torvalds 已提交
1497 1498 1499 1500 1501
		i += len;
		pkt_dev->lflow = value;
		sprintf(pg_result, "OK: flowlen=%u", pkt_dev->lflow);
		return count;
	}
L
Luiz Capitulino 已提交
1502

R
Robert Olsson 已提交
1503 1504
	if (!strcmp(name, "queue_map_min")) {
		len = num_arg(&user_buffer[i], 5, &value);
1505
		if (len < 0)
R
Robert Olsson 已提交
1506
			return len;
1507

R
Robert Olsson 已提交
1508 1509 1510 1511 1512 1513 1514 1515
		i += len;
		pkt_dev->queue_map_min = value;
		sprintf(pg_result, "OK: queue_map_min=%u", pkt_dev->queue_map_min);
		return count;
	}

	if (!strcmp(name, "queue_map_max")) {
		len = num_arg(&user_buffer[i], 5, &value);
1516
		if (len < 0)
R
Robert Olsson 已提交
1517
			return len;
1518

R
Robert Olsson 已提交
1519 1520 1521 1522 1523 1524
		i += len;
		pkt_dev->queue_map_max = value;
		sprintf(pg_result, "OK: queue_map_max=%u", pkt_dev->queue_map_max);
		return count;
	}

1525
	if (!strcmp(name, "mpls")) {
1526
		unsigned int n, cnt;
S
Stephen Hemminger 已提交
1527

1528
		len = get_labels(&user_buffer[i], pkt_dev);
S
Stephen Hemminger 已提交
1529 1530
		if (len < 0)
			return len;
1531
		i += len;
S
Stephen Hemminger 已提交
1532
		cnt = sprintf(pg_result, "OK: mpls=");
1533
		for (n = 0; n < pkt_dev->nr_labels; n++)
S
Stephen Hemminger 已提交
1534 1535 1536
			cnt += sprintf(pg_result + cnt,
				       "%08x%s", ntohl(pkt_dev->labels[n]),
				       n == pkt_dev->nr_labels-1 ? "" : ",");
F
Francesco Fondelli 已提交
1537 1538 1539 1540 1541 1542

		if (pkt_dev->nr_labels && pkt_dev->vlan_id != 0xffff) {
			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
			pkt_dev->svlan_id = 0xffff;

			if (debug)
J
Joe Perches 已提交
1543
				pr_debug("VLAN/SVLAN auto turned off\n");
F
Francesco Fondelli 已提交
1544 1545 1546 1547 1548 1549
		}
		return count;
	}

	if (!strcmp(name, "vlan_id")) {
		len = num_arg(&user_buffer[i], 4, &value);
1550
		if (len < 0)
F
Francesco Fondelli 已提交
1551
			return len;
1552

F
Francesco Fondelli 已提交
1553 1554 1555 1556 1557
		i += len;
		if (value <= 4095) {
			pkt_dev->vlan_id = value;  /* turn on VLAN */

			if (debug)
J
Joe Perches 已提交
1558
				pr_debug("VLAN turned on\n");
F
Francesco Fondelli 已提交
1559 1560

			if (debug && pkt_dev->nr_labels)
J
Joe Perches 已提交
1561
				pr_debug("MPLS auto turned off\n");
F
Francesco Fondelli 已提交
1562 1563 1564 1565 1566 1567 1568 1569

			pkt_dev->nr_labels = 0;    /* turn off MPLS */
			sprintf(pg_result, "OK: vlan_id=%u", pkt_dev->vlan_id);
		} else {
			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
			pkt_dev->svlan_id = 0xffff;

			if (debug)
J
Joe Perches 已提交
1570
				pr_debug("VLAN/SVLAN turned off\n");
F
Francesco Fondelli 已提交
1571 1572 1573 1574 1575 1576
		}
		return count;
	}

	if (!strcmp(name, "vlan_p")) {
		len = num_arg(&user_buffer[i], 1, &value);
1577
		if (len < 0)
F
Francesco Fondelli 已提交
1578
			return len;
1579

F
Francesco Fondelli 已提交
1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
		i += len;
		if ((value <= 7) && (pkt_dev->vlan_id != 0xffff)) {
			pkt_dev->vlan_p = value;
			sprintf(pg_result, "OK: vlan_p=%u", pkt_dev->vlan_p);
		} else {
			sprintf(pg_result, "ERROR: vlan_p must be 0-7");
		}
		return count;
	}

	if (!strcmp(name, "vlan_cfi")) {
		len = num_arg(&user_buffer[i], 1, &value);
1592
		if (len < 0)
F
Francesco Fondelli 已提交
1593
			return len;
1594

F
Francesco Fondelli 已提交
1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
		i += len;
		if ((value <= 1) && (pkt_dev->vlan_id != 0xffff)) {
			pkt_dev->vlan_cfi = value;
			sprintf(pg_result, "OK: vlan_cfi=%u", pkt_dev->vlan_cfi);
		} else {
			sprintf(pg_result, "ERROR: vlan_cfi must be 0-1");
		}
		return count;
	}

	if (!strcmp(name, "svlan_id")) {
		len = num_arg(&user_buffer[i], 4, &value);
1607
		if (len < 0)
F
Francesco Fondelli 已提交
1608
			return len;
1609

F
Francesco Fondelli 已提交
1610 1611 1612 1613 1614
		i += len;
		if ((value <= 4095) && ((pkt_dev->vlan_id != 0xffff))) {
			pkt_dev->svlan_id = value;  /* turn on SVLAN */

			if (debug)
J
Joe Perches 已提交
1615
				pr_debug("SVLAN turned on\n");
F
Francesco Fondelli 已提交
1616 1617

			if (debug && pkt_dev->nr_labels)
J
Joe Perches 已提交
1618
				pr_debug("MPLS auto turned off\n");
F
Francesco Fondelli 已提交
1619 1620 1621 1622 1623 1624 1625 1626

			pkt_dev->nr_labels = 0;    /* turn off MPLS */
			sprintf(pg_result, "OK: svlan_id=%u", pkt_dev->svlan_id);
		} else {
			pkt_dev->vlan_id = 0xffff; /* turn off VLAN/SVLAN */
			pkt_dev->svlan_id = 0xffff;

			if (debug)
J
Joe Perches 已提交
1627
				pr_debug("VLAN/SVLAN turned off\n");
F
Francesco Fondelli 已提交
1628 1629 1630 1631 1632 1633
		}
		return count;
	}

	if (!strcmp(name, "svlan_p")) {
		len = num_arg(&user_buffer[i], 1, &value);
1634
		if (len < 0)
F
Francesco Fondelli 已提交
1635
			return len;
1636

F
Francesco Fondelli 已提交
1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
		i += len;
		if ((value <= 7) && (pkt_dev->svlan_id != 0xffff)) {
			pkt_dev->svlan_p = value;
			sprintf(pg_result, "OK: svlan_p=%u", pkt_dev->svlan_p);
		} else {
			sprintf(pg_result, "ERROR: svlan_p must be 0-7");
		}
		return count;
	}

	if (!strcmp(name, "svlan_cfi")) {
		len = num_arg(&user_buffer[i], 1, &value);
1649
		if (len < 0)
F
Francesco Fondelli 已提交
1650
			return len;
1651

F
Francesco Fondelli 已提交
1652 1653 1654 1655 1656 1657 1658
		i += len;
		if ((value <= 1) && (pkt_dev->svlan_id != 0xffff)) {
			pkt_dev->svlan_cfi = value;
			sprintf(pg_result, "OK: svlan_cfi=%u", pkt_dev->svlan_cfi);
		} else {
			sprintf(pg_result, "ERROR: svlan_cfi must be 0-1");
		}
1659 1660 1661
		return count;
	}

F
Francesco Fondelli 已提交
1662 1663 1664
	if (!strcmp(name, "tos")) {
		__u32 tmp_value = 0;
		len = hex32_arg(&user_buffer[i], 2, &tmp_value);
1665
		if (len < 0)
F
Francesco Fondelli 已提交
1666
			return len;
1667

F
Francesco Fondelli 已提交
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
		i += len;
		if (len == 2) {
			pkt_dev->tos = tmp_value;
			sprintf(pg_result, "OK: tos=0x%02x", pkt_dev->tos);
		} else {
			sprintf(pg_result, "ERROR: tos must be 00-ff");
		}
		return count;
	}

	if (!strcmp(name, "traffic_class")) {
		__u32 tmp_value = 0;
		len = hex32_arg(&user_buffer[i], 2, &tmp_value);
1681
		if (len < 0)
F
Francesco Fondelli 已提交
1682
			return len;
1683

F
Francesco Fondelli 已提交
1684 1685 1686 1687 1688 1689 1690 1691 1692 1693
		i += len;
		if (len == 2) {
			pkt_dev->traffic_class = tmp_value;
			sprintf(pg_result, "OK: traffic_class=0x%02x", pkt_dev->traffic_class);
		} else {
			sprintf(pg_result, "ERROR: traffic_class must be 00-ff");
		}
		return count;
	}

J
John Fastabend 已提交
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
	if (!strcmp(name, "skb_priority")) {
		len = num_arg(&user_buffer[i], 9, &value);
		if (len < 0)
			return len;

		i += len;
		pkt_dev->skb_priority = value;
		sprintf(pg_result, "OK: skb_priority=%i",
			pkt_dev->skb_priority);
		return count;
	}

L
Linus Torvalds 已提交
1706 1707 1708 1709
	sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
	return -EINVAL;
}

1710
static int pktgen_if_open(struct inode *inode, struct file *file)
L
Linus Torvalds 已提交
1711
{
A
Al Viro 已提交
1712
	return single_open(file, pktgen_if_show, PDE_DATA(inode));
1713
}
L
Linus Torvalds 已提交
1714

1715
static const struct file_operations pktgen_if_fops = {
L
Luiz Capitulino 已提交
1716 1717 1718 1719 1720 1721
	.owner   = THIS_MODULE,
	.open    = pktgen_if_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.write   = pktgen_if_write,
	.release = single_release,
1722
};
L
Linus Torvalds 已提交
1723

1724 1725
static int pktgen_thread_show(struct seq_file *seq, void *v)
{
L
Luiz Capitulino 已提交
1726
	struct pktgen_thread *t = seq->private;
S
Stephen Hemminger 已提交
1727
	const struct pktgen_dev *pkt_dev;
1728 1729

	BUG_ON(!t);
L
Linus Torvalds 已提交
1730

L
Luiz Capitulino 已提交
1731
	seq_printf(seq, "Running: ");
L
Linus Torvalds 已提交
1732

L
Luiz Capitulino 已提交
1733
	if_lock(t);
1734
	list_for_each_entry(pkt_dev, &t->if_list, list)
L
Luiz Capitulino 已提交
1735
		if (pkt_dev->running)
E
Eric Dumazet 已提交
1736
			seq_printf(seq, "%s ", pkt_dev->odevname);
L
Linus Torvalds 已提交
1737

L
Luiz Capitulino 已提交
1738 1739
	seq_printf(seq, "\nStopped: ");

1740
	list_for_each_entry(pkt_dev, &t->if_list, list)
L
Luiz Capitulino 已提交
1741
		if (!pkt_dev->running)
E
Eric Dumazet 已提交
1742
			seq_printf(seq, "%s ", pkt_dev->odevname);
L
Linus Torvalds 已提交
1743 1744

	if (t->result[0])
1745
		seq_printf(seq, "\nResult: %s\n", t->result);
L
Linus Torvalds 已提交
1746
	else
1747
		seq_printf(seq, "\nResult: NA\n");
L
Linus Torvalds 已提交
1748

L
Luiz Capitulino 已提交
1749
	if_unlock(t);
L
Linus Torvalds 已提交
1750

1751
	return 0;
L
Linus Torvalds 已提交
1752 1753
}

1754
static ssize_t pktgen_thread_write(struct file *file,
L
Luiz Capitulino 已提交
1755 1756
				   const char __user * user_buffer,
				   size_t count, loff_t * offset)
L
Linus Torvalds 已提交
1757
{
1758
	struct seq_file *seq = file->private_data;
L
Luiz Capitulino 已提交
1759
	struct pktgen_thread *t = seq->private;
1760
	int i, max, len, ret;
L
Linus Torvalds 已提交
1761
	char name[40];
L
Luiz Capitulino 已提交
1762
	char *pg_result;
1763

L
Linus Torvalds 已提交
1764
	if (count < 1) {
L
Luiz Capitulino 已提交
1765
		//      sprintf(pg_result, "Wrong command format");
L
Linus Torvalds 已提交
1766 1767
		return -EINVAL;
	}
1768

1769 1770
	max = count;
	len = count_trail_chars(user_buffer, max);
L
Luiz Capitulino 已提交
1771
	if (len < 0)
1772 1773
		return len;

1774
	i = len;
1775

L
Linus Torvalds 已提交
1776 1777 1778
	/* Read variable name */

	len = strn_len(&user_buffer[i], sizeof(name) - 1);
L
Luiz Capitulino 已提交
1779
	if (len < 0)
1780
		return len;
L
Luiz Capitulino 已提交
1781

L
Linus Torvalds 已提交
1782 1783 1784 1785
	memset(name, 0, sizeof(name));
	if (copy_from_user(name, &user_buffer[i], len))
		return -EFAULT;
	i += len;
1786

L
Luiz Capitulino 已提交
1787
	max = count - i;
L
Linus Torvalds 已提交
1788
	len = count_trail_chars(&user_buffer[i], max);
L
Luiz Capitulino 已提交
1789
	if (len < 0)
1790 1791
		return len;

L
Linus Torvalds 已提交
1792 1793
	i += len;

1794
	if (debug)
J
Joe Perches 已提交
1795
		pr_debug("t=%s, count=%lu\n", name, (unsigned long)count);
L
Linus Torvalds 已提交
1796

L
Luiz Capitulino 已提交
1797
	if (!t) {
J
Joe Perches 已提交
1798
		pr_err("ERROR: No thread\n");
L
Linus Torvalds 已提交
1799 1800 1801 1802 1803 1804
		ret = -EINVAL;
		goto out;
	}

	pg_result = &(t->result[0]);

L
Luiz Capitulino 已提交
1805 1806 1807
	if (!strcmp(name, "add_device")) {
		char f[32];
		memset(f, 0, 32);
L
Linus Torvalds 已提交
1808
		len = strn_len(&user_buffer[i], sizeof(f) - 1);
L
Luiz Capitulino 已提交
1809 1810
		if (len < 0) {
			ret = len;
L
Linus Torvalds 已提交
1811 1812
			goto out;
		}
L
Luiz Capitulino 已提交
1813
		if (copy_from_user(f, &user_buffer[i], len))
L
Linus Torvalds 已提交
1814 1815
			return -EFAULT;
		i += len;
1816
		mutex_lock(&pktgen_thread_lock);
1817
		ret = pktgen_add_device(t, f);
1818
		mutex_unlock(&pktgen_thread_lock);
1819 1820 1821 1822 1823
		if (!ret) {
			ret = count;
			sprintf(pg_result, "OK: add_device=%s", f);
		} else
			sprintf(pg_result, "ERROR: can not add device %s", f);
L
Linus Torvalds 已提交
1824 1825 1826
		goto out;
	}

L
Luiz Capitulino 已提交
1827
	if (!strcmp(name, "rem_device_all")) {
1828
		mutex_lock(&pktgen_thread_lock);
1829
		t->control |= T_REMDEVALL;
1830
		mutex_unlock(&pktgen_thread_lock);
L
Luiz Capitulino 已提交
1831
		schedule_timeout_interruptible(msecs_to_jiffies(125));	/* Propagate thread->control  */
L
Linus Torvalds 已提交
1832
		ret = count;
L
Luiz Capitulino 已提交
1833
		sprintf(pg_result, "OK: rem_device_all");
L
Linus Torvalds 已提交
1834 1835 1836
		goto out;
	}

L
Luiz Capitulino 已提交
1837
	if (!strcmp(name, "max_before_softirq")) {
1838
		sprintf(pg_result, "OK: Note! max_before_softirq is obsoleted -- Do not use");
L
Luiz Capitulino 已提交
1839
		ret = count;
L
Linus Torvalds 已提交
1840 1841 1842 1843
		goto out;
	}

	ret = -EINVAL;
L
Luiz Capitulino 已提交
1844
out:
L
Linus Torvalds 已提交
1845 1846 1847
	return ret;
}

1848
static int pktgen_thread_open(struct inode *inode, struct file *file)
L
Linus Torvalds 已提交
1849
{
A
Al Viro 已提交
1850
	return single_open(file, pktgen_thread_show, PDE_DATA(inode));
L
Linus Torvalds 已提交
1851 1852
}

1853
static const struct file_operations pktgen_thread_fops = {
L
Luiz Capitulino 已提交
1854 1855 1856 1857 1858 1859
	.owner   = THIS_MODULE,
	.open    = pktgen_thread_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.write   = pktgen_thread_write,
	.release = single_release,
1860
};
L
Linus Torvalds 已提交
1861 1862

/* Think find or remove for NN */
C
Cong Wang 已提交
1863 1864
static struct pktgen_dev *__pktgen_NN_threads(const struct pktgen_net *pn,
					      const char *ifname, int remove)
L
Linus Torvalds 已提交
1865 1866 1867
{
	struct pktgen_thread *t;
	struct pktgen_dev *pkt_dev = NULL;
E
Eric Dumazet 已提交
1868
	bool exact = (remove == FIND);
L
Linus Torvalds 已提交
1869

C
Cong Wang 已提交
1870
	list_for_each_entry(t, &pn->pktgen_threads, th_list) {
E
Eric Dumazet 已提交
1871
		pkt_dev = pktgen_find_dev(t, ifname, exact);
L
Linus Torvalds 已提交
1872
		if (pkt_dev) {
L
Luiz Capitulino 已提交
1873 1874 1875 1876 1877 1878
			if (remove) {
				if_lock(t);
				pkt_dev->removal_mark = 1;
				t->control |= T_REMDEV;
				if_unlock(t);
			}
L
Linus Torvalds 已提交
1879 1880 1881
			break;
		}
	}
L
Luiz Capitulino 已提交
1882
	return pkt_dev;
L
Linus Torvalds 已提交
1883 1884
}

1885 1886 1887
/*
 * mark a device for removal
 */
C
Cong Wang 已提交
1888
static void pktgen_mark_device(const struct pktgen_net *pn, const char *ifname)
L
Linus Torvalds 已提交
1889 1890
{
	struct pktgen_dev *pkt_dev = NULL;
1891 1892 1893
	const int max_tries = 10, msec_per_try = 125;
	int i = 0;

1894
	mutex_lock(&pktgen_thread_lock);
J
Joe Perches 已提交
1895
	pr_debug("%s: marking %s for removal\n", __func__, ifname);
1896

L
Luiz Capitulino 已提交
1897
	while (1) {
1898

C
Cong Wang 已提交
1899
		pkt_dev = __pktgen_NN_threads(pn, ifname, REMOVE);
L
Luiz Capitulino 已提交
1900 1901
		if (pkt_dev == NULL)
			break;	/* success */
1902

1903
		mutex_unlock(&pktgen_thread_lock);
J
Joe Perches 已提交
1904 1905
		pr_debug("%s: waiting for %s to disappear....\n",
			 __func__, ifname);
1906
		schedule_timeout_interruptible(msecs_to_jiffies(msec_per_try));
1907
		mutex_lock(&pktgen_thread_lock);
1908 1909

		if (++i >= max_tries) {
J
Joe Perches 已提交
1910 1911
			pr_err("%s: timed out after waiting %d msec for device %s to be removed\n",
			       __func__, msec_per_try * i, ifname);
1912 1913 1914 1915 1916
			break;
		}

	}

1917
	mutex_unlock(&pktgen_thread_lock);
1918
}
1919

C
Cong Wang 已提交
1920
static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *dev)
1921 1922 1923
{
	struct pktgen_thread *t;

C
Cong Wang 已提交
1924
	list_for_each_entry(t, &pn->pktgen_threads, th_list) {
1925 1926 1927 1928 1929 1930
		struct pktgen_dev *pkt_dev;

		list_for_each_entry(pkt_dev, &t->if_list, list) {
			if (pkt_dev->odev != dev)
				continue;

1931
			proc_remove(pkt_dev->entry);
1932

A
Alexey Dobriyan 已提交
1933
			pkt_dev->entry = proc_create_data(dev->name, 0600,
C
Cong Wang 已提交
1934
							  pn->proc_dir,
A
Alexey Dobriyan 已提交
1935 1936
							  &pktgen_if_fops,
							  pkt_dev);
1937
			if (!pkt_dev->entry)
J
Joe Perches 已提交
1938 1939
				pr_err("can't move proc entry for '%s'\n",
				       dev->name);
1940 1941 1942
			break;
		}
	}
L
Linus Torvalds 已提交
1943 1944
}

L
Luiz Capitulino 已提交
1945 1946
static int pktgen_device_event(struct notifier_block *unused,
			       unsigned long event, void *ptr)
L
Linus Torvalds 已提交
1947
{
1948
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
C
Cong Wang 已提交
1949
	struct pktgen_net *pn = net_generic(dev_net(dev), pg_net_id);
L
Linus Torvalds 已提交
1950

C
Cong Wang 已提交
1951
	if (pn->pktgen_exiting)
1952 1953
		return NOTIFY_DONE;

L
Linus Torvalds 已提交
1954 1955 1956 1957 1958
	/* It is OK that we do not hold the group lock right now,
	 * as we run under the RTNL lock.
	 */

	switch (event) {
1959
	case NETDEV_CHANGENAME:
C
Cong Wang 已提交
1960
		pktgen_change_name(pn, dev);
L
Linus Torvalds 已提交
1961
		break;
L
Luiz Capitulino 已提交
1962

L
Linus Torvalds 已提交
1963
	case NETDEV_UNREGISTER:
C
Cong Wang 已提交
1964
		pktgen_mark_device(pn, dev->name);
L
Linus Torvalds 已提交
1965
		break;
1966
	}
L
Linus Torvalds 已提交
1967 1968 1969 1970

	return NOTIFY_DONE;
}

C
Cong Wang 已提交
1971 1972
static struct net_device *pktgen_dev_get_by_name(const struct pktgen_net *pn,
						 struct pktgen_dev *pkt_dev,
1973
						 const char *ifname)
R
Robert Olsson 已提交
1974 1975
{
	char b[IFNAMSIZ+5];
1976
	int i;
R
Robert Olsson 已提交
1977

1978 1979
	for (i = 0; ifname[i] != '@'; i++) {
		if (i == IFNAMSIZ)
R
Robert Olsson 已提交
1980 1981 1982 1983 1984 1985
			break;

		b[i] = ifname[i];
	}
	b[i] = 0;

C
Cong Wang 已提交
1986
	return dev_get_by_name(pn->net, b);
R
Robert Olsson 已提交
1987 1988 1989
}


L
Linus Torvalds 已提交
1990 1991
/* Associate pktgen_dev with a device. */

C
Cong Wang 已提交
1992 1993
static int pktgen_setup_dev(const struct pktgen_net *pn,
			    struct pktgen_dev *pkt_dev, const char *ifname)
L
Luiz Capitulino 已提交
1994
{
L
Linus Torvalds 已提交
1995
	struct net_device *odev;
1996
	int err;
L
Linus Torvalds 已提交
1997 1998 1999 2000

	/* Clean old setups */
	if (pkt_dev->odev) {
		dev_put(pkt_dev->odev);
L
Luiz Capitulino 已提交
2001 2002
		pkt_dev->odev = NULL;
	}
L
Linus Torvalds 已提交
2003

C
Cong Wang 已提交
2004
	odev = pktgen_dev_get_by_name(pn, pkt_dev, ifname);
L
Linus Torvalds 已提交
2005
	if (!odev) {
J
Joe Perches 已提交
2006
		pr_err("no such netdevice: \"%s\"\n", ifname);
2007
		return -ENODEV;
L
Linus Torvalds 已提交
2008
	}
2009

L
Linus Torvalds 已提交
2010
	if (odev->type != ARPHRD_ETHER) {
J
Joe Perches 已提交
2011
		pr_err("not an ethernet device: \"%s\"\n", ifname);
2012 2013
		err = -EINVAL;
	} else if (!netif_running(odev)) {
J
Joe Perches 已提交
2014
		pr_err("device is down: \"%s\"\n", ifname);
2015 2016 2017 2018
		err = -ENETDOWN;
	} else {
		pkt_dev->odev = odev;
		return 0;
L
Linus Torvalds 已提交
2019 2020 2021
	}

	dev_put(odev);
2022
	return err;
L
Linus Torvalds 已提交
2023 2024 2025 2026 2027 2028 2029
}

/* Read pkt_dev from the interface and set up internal pktgen_dev
 * structure to have the right information to create/send packets
 */
static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
{
2030 2031
	int ntxq;

L
Luiz Capitulino 已提交
2032
	if (!pkt_dev->odev) {
J
Joe Perches 已提交
2033
		pr_err("ERROR: pkt_dev->odev == NULL in setup_inject\n");
L
Luiz Capitulino 已提交
2034 2035 2036 2037 2038
		sprintf(pkt_dev->result,
			"ERROR: pkt_dev->odev == NULL in setup_inject.\n");
		return;
	}

2039 2040
	/* make sure that we don't pick a non-existing transmit queue */
	ntxq = pkt_dev->odev->real_num_tx_queues;
R
Robert Olsson 已提交
2041

2042
	if (ntxq <= pkt_dev->queue_map_min) {
J
Joe Perches 已提交
2043 2044 2045
		pr_warning("WARNING: Requested queue_map_min (zero-based) (%d) exceeds valid range [0 - %d] for (%d) queues on %s, resetting\n",
			   pkt_dev->queue_map_min, (ntxq ?: 1) - 1, ntxq,
			   pkt_dev->odevname);
2046
		pkt_dev->queue_map_min = (ntxq ?: 1) - 1;
2047
	}
2048
	if (pkt_dev->queue_map_max >= ntxq) {
J
Joe Perches 已提交
2049 2050 2051
		pr_warning("WARNING: Requested queue_map_max (zero-based) (%d) exceeds valid range [0 - %d] for (%d) queues on %s, resetting\n",
			   pkt_dev->queue_map_max, (ntxq ?: 1) - 1, ntxq,
			   pkt_dev->odevname);
2052
		pkt_dev->queue_map_max = (ntxq ?: 1) - 1;
2053 2054
	}

L
Luiz Capitulino 已提交
2055
	/* Default to the interface's mac if not explicitly set. */
L
Linus Torvalds 已提交
2056

2057
	if (is_zero_ether_addr(pkt_dev->src_mac))
L
Luiz Capitulino 已提交
2058
		memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN);
L
Linus Torvalds 已提交
2059

L
Luiz Capitulino 已提交
2060
	/* Set up Dest MAC */
2061
	memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
L
Linus Torvalds 已提交
2062

L
Luiz Capitulino 已提交
2063
	if (pkt_dev->flags & F_IPV6) {
2064 2065 2066
		int i, set = 0, err = 1;
		struct inet6_dev *idev;

2067 2068 2069 2070 2071 2072 2073
		if (pkt_dev->min_pkt_size == 0) {
			pkt_dev->min_pkt_size = 14 + sizeof(struct ipv6hdr)
						+ sizeof(struct udphdr)
						+ sizeof(struct pktgen_hdr)
						+ pkt_dev->pkt_overhead;
		}

L
Luiz Capitulino 已提交
2074 2075
		for (i = 0; i < IN6_ADDR_HSIZE; i++)
			if (pkt_dev->cur_in6_saddr.s6_addr[i]) {
L
Linus Torvalds 已提交
2076 2077 2078 2079
				set = 1;
				break;
			}

L
Luiz Capitulino 已提交
2080 2081
		if (!set) {

L
Linus Torvalds 已提交
2082 2083 2084 2085 2086 2087
			/*
			 * Use linklevel address if unconfigured.
			 *
			 * use ipv6_get_lladdr if/when it's get exported
			 */

2088
			rcu_read_lock();
2089 2090
			idev = __in6_dev_get(pkt_dev->odev);
			if (idev) {
L
Linus Torvalds 已提交
2091 2092 2093
				struct inet6_ifaddr *ifp;

				read_lock_bh(&idev->lock);
2094 2095
				list_for_each_entry(ifp, &idev->addr_list, if_list) {
					if ((ifp->scope & IFA_LINK) &&
2096
					    !(ifp->flags & IFA_F_TENTATIVE)) {
A
Alexey Dobriyan 已提交
2097
						pkt_dev->cur_in6_saddr = ifp->addr;
L
Linus Torvalds 已提交
2098 2099 2100 2101 2102 2103
						err = 0;
						break;
					}
				}
				read_unlock_bh(&idev->lock);
			}
2104
			rcu_read_unlock();
L
Luiz Capitulino 已提交
2105
			if (err)
J
Joe Perches 已提交
2106
				pr_err("ERROR: IPv6 link address not available\n");
L
Linus Torvalds 已提交
2107
		}
L
Luiz Capitulino 已提交
2108
	} else {
2109 2110 2111 2112 2113 2114 2115
		if (pkt_dev->min_pkt_size == 0) {
			pkt_dev->min_pkt_size = 14 + sizeof(struct iphdr)
						+ sizeof(struct udphdr)
						+ sizeof(struct pktgen_hdr)
						+ pkt_dev->pkt_overhead;
		}

L
Linus Torvalds 已提交
2116 2117 2118
		pkt_dev->saddr_min = 0;
		pkt_dev->saddr_max = 0;
		if (strlen(pkt_dev->src_min) == 0) {
L
Luiz Capitulino 已提交
2119 2120

			struct in_device *in_dev;
L
Linus Torvalds 已提交
2121 2122

			rcu_read_lock();
2123
			in_dev = __in_dev_get_rcu(pkt_dev->odev);
L
Linus Torvalds 已提交
2124 2125
			if (in_dev) {
				if (in_dev->ifa_list) {
L
Luiz Capitulino 已提交
2126 2127
					pkt_dev->saddr_min =
					    in_dev->ifa_list->ifa_address;
L
Linus Torvalds 已提交
2128 2129 2130 2131
					pkt_dev->saddr_max = pkt_dev->saddr_min;
				}
			}
			rcu_read_unlock();
L
Luiz Capitulino 已提交
2132
		} else {
L
Linus Torvalds 已提交
2133 2134 2135 2136 2137 2138 2139
			pkt_dev->saddr_min = in_aton(pkt_dev->src_min);
			pkt_dev->saddr_max = in_aton(pkt_dev->src_max);
		}

		pkt_dev->daddr_min = in_aton(pkt_dev->dst_min);
		pkt_dev->daddr_max = in_aton(pkt_dev->dst_max);
	}
L
Luiz Capitulino 已提交
2140
	/* Initialize current values. */
2141 2142 2143 2144
	pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;
	if (pkt_dev->min_pkt_size > pkt_dev->max_pkt_size)
		pkt_dev->max_pkt_size = pkt_dev->min_pkt_size;

L
Luiz Capitulino 已提交
2145 2146 2147 2148 2149 2150
	pkt_dev->cur_dst_mac_offset = 0;
	pkt_dev->cur_src_mac_offset = 0;
	pkt_dev->cur_saddr = pkt_dev->saddr_min;
	pkt_dev->cur_daddr = pkt_dev->daddr_min;
	pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
	pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
L
Linus Torvalds 已提交
2151 2152 2153
	pkt_dev->nflows = 0;
}

2154 2155 2156

static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
{
2157
	ktime_t start_time, end_time;
E
Eric Dumazet 已提交
2158
	s64 remaining;
S
Stephen Hemminger 已提交
2159 2160 2161 2162 2163
	struct hrtimer_sleeper t;

	hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
	hrtimer_set_expires(&t.timer, spin_until);

2164
	remaining = ktime_to_ns(hrtimer_expires_remaining(&t.timer));
E
Eric Dumazet 已提交
2165 2166
	if (remaining <= 0) {
		pkt_dev->next_tx = ktime_add_ns(spin_until, pkt_dev->delay);
S
Stephen Hemminger 已提交
2167
		return;
E
Eric Dumazet 已提交
2168
	}
S
Stephen Hemminger 已提交
2169

D
Daniel Borkmann 已提交
2170
	start_time = ktime_get();
E
Eric Dumazet 已提交
2171 2172 2173
	if (remaining < 100000) {
		/* for small delays (<100us), just loop until limit is reached */
		do {
D
Daniel Borkmann 已提交
2174 2175
			end_time = ktime_get();
		} while (ktime_compare(end_time, spin_until) < 0);
E
Eric Dumazet 已提交
2176
	} else {
S
Stephen Hemminger 已提交
2177 2178 2179 2180 2181 2182 2183 2184 2185
		/* see do_nanosleep */
		hrtimer_init_sleeper(&t, current);
		do {
			set_current_state(TASK_INTERRUPTIBLE);
			hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS);
			if (!hrtimer_active(&t.timer))
				t.task = NULL;

			if (likely(t.task))
L
Linus Torvalds 已提交
2186 2187
				schedule();

S
Stephen Hemminger 已提交
2188 2189 2190
			hrtimer_cancel(&t.timer);
		} while (t.task && pkt_dev->running && !signal_pending(current));
		__set_current_state(TASK_RUNNING);
D
Daniel Borkmann 已提交
2191
		end_time = ktime_get();
L
Linus Torvalds 已提交
2192
	}
2193 2194

	pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
2195
	pkt_dev->next_tx = ktime_add_ns(spin_until, pkt_dev->delay);
L
Linus Torvalds 已提交
2196 2197
}

2198 2199
static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
{
J
Jamal Hadi Salim 已提交
2200
	pkt_dev->pkt_overhead = 0;
2201 2202 2203 2204 2205
	pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32);
	pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev);
	pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev);
}

S
Stephen Hemminger 已提交
2206
static inline int f_seen(const struct pktgen_dev *pkt_dev, int flow)
2207
{
S
Stephen Hemminger 已提交
2208
	return !!(pkt_dev->flows[flow].flags & F_INIT);
2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
}

static inline int f_pick(struct pktgen_dev *pkt_dev)
{
	int flow = pkt_dev->curfl;

	if (pkt_dev->flags & F_FLOW_SEQ) {
		if (pkt_dev->flows[flow].count >= pkt_dev->lflow) {
			/* reset time */
			pkt_dev->flows[flow].count = 0;
R
Robert Olsson 已提交
2219
			pkt_dev->flows[flow].flags = 0;
2220 2221 2222 2223 2224
			pkt_dev->curfl += 1;
			if (pkt_dev->curfl >= pkt_dev->cflows)
				pkt_dev->curfl = 0; /*reset */
		}
	} else {
2225
		flow = prandom_u32() % pkt_dev->cflows;
R
Robert Olsson 已提交
2226
		pkt_dev->curfl = flow;
2227

R
Robert Olsson 已提交
2228
		if (pkt_dev->flows[flow].count > pkt_dev->lflow) {
2229
			pkt_dev->flows[flow].count = 0;
R
Robert Olsson 已提交
2230 2231
			pkt_dev->flows[flow].flags = 0;
		}
2232 2233 2234 2235 2236
	}

	return pkt_dev->curfl;
}

J
Jamal Hadi Salim 已提交
2237 2238 2239 2240 2241

#ifdef CONFIG_XFRM
/* If there was already an IPSEC SA, we keep it as is, else
 * we go look for it ...
*/
2242
#define DUMMY_MARK 0
2243
static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
J
Jamal Hadi Salim 已提交
2244 2245
{
	struct xfrm_state *x = pkt_dev->flows[flow].x;
C
Cong Wang 已提交
2246
	struct pktgen_net *pn = net_generic(dev_net(pkt_dev->odev), pg_net_id);
J
Jamal Hadi Salim 已提交
2247 2248
	if (!x) {
		/*slow path: we dont already have xfrm_state*/
C
Cong Wang 已提交
2249
		x = xfrm_stateonly_find(pn->net, DUMMY_MARK,
2250
					(xfrm_address_t *)&pkt_dev->cur_daddr,
J
Jamal Hadi Salim 已提交
2251 2252 2253 2254 2255 2256 2257
					(xfrm_address_t *)&pkt_dev->cur_saddr,
					AF_INET,
					pkt_dev->ipsmode,
					pkt_dev->ipsproto, 0);
		if (x) {
			pkt_dev->flows[flow].x = x;
			set_pkt_overhead(pkt_dev);
2258
			pkt_dev->pkt_overhead += x->props.header_len;
J
Jamal Hadi Salim 已提交
2259 2260 2261 2262 2263
		}

	}
}
#endif
2264 2265
static void set_cur_queue_map(struct pktgen_dev *pkt_dev)
{
R
Robert Olsson 已提交
2266 2267 2268 2269

	if (pkt_dev->flags & F_QUEUE_MAP_CPU)
		pkt_dev->cur_queue_map = smp_processor_id();

E
Eric Dumazet 已提交
2270
	else if (pkt_dev->queue_map_min <= pkt_dev->queue_map_max) {
2271 2272
		__u16 t;
		if (pkt_dev->flags & F_QUEUE_MAP_RND) {
2273
			t = prandom_u32() %
2274 2275 2276 2277 2278 2279 2280 2281 2282 2283
				(pkt_dev->queue_map_max -
				 pkt_dev->queue_map_min + 1)
				+ pkt_dev->queue_map_min;
		} else {
			t = pkt_dev->cur_queue_map + 1;
			if (t > pkt_dev->queue_map_max)
				t = pkt_dev->queue_map_min;
		}
		pkt_dev->cur_queue_map = t;
	}
R
Robert Olsson 已提交
2284
	pkt_dev->cur_queue_map  = pkt_dev->cur_queue_map % pkt_dev->odev->real_num_tx_queues;
2285 2286
}

L
Linus Torvalds 已提交
2287 2288 2289
/* Increment/randomize headers according to flags and current values
 * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
 */
L
Luiz Capitulino 已提交
2290 2291 2292 2293 2294
static void mod_cur_headers(struct pktgen_dev *pkt_dev)
{
	__u32 imn;
	__u32 imx;
	int flow = 0;
L
Linus Torvalds 已提交
2295

2296 2297
	if (pkt_dev->cflows)
		flow = f_pick(pkt_dev);
L
Linus Torvalds 已提交
2298 2299

	/*  Deal with source MAC */
L
Luiz Capitulino 已提交
2300 2301 2302 2303 2304
	if (pkt_dev->src_mac_count > 1) {
		__u32 mc;
		__u32 tmp;

		if (pkt_dev->flags & F_MACSRC_RND)
2305
			mc = prandom_u32() % pkt_dev->src_mac_count;
L
Luiz Capitulino 已提交
2306 2307
		else {
			mc = pkt_dev->cur_src_mac_offset++;
R
Robert Olsson 已提交
2308
			if (pkt_dev->cur_src_mac_offset >=
L
Luiz Capitulino 已提交
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330
			    pkt_dev->src_mac_count)
				pkt_dev->cur_src_mac_offset = 0;
		}

		tmp = pkt_dev->src_mac[5] + (mc & 0xFF);
		pkt_dev->hh[11] = tmp;
		tmp = (pkt_dev->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
		pkt_dev->hh[10] = tmp;
		tmp = (pkt_dev->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
		pkt_dev->hh[9] = tmp;
		tmp = (pkt_dev->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
		pkt_dev->hh[8] = tmp;
		tmp = (pkt_dev->src_mac[1] + (tmp >> 8));
		pkt_dev->hh[7] = tmp;
	}

	/*  Deal with Destination MAC */
	if (pkt_dev->dst_mac_count > 1) {
		__u32 mc;
		__u32 tmp;

		if (pkt_dev->flags & F_MACDST_RND)
2331
			mc = prandom_u32() % pkt_dev->dst_mac_count;
L
Luiz Capitulino 已提交
2332 2333 2334

		else {
			mc = pkt_dev->cur_dst_mac_offset++;
R
Robert Olsson 已提交
2335
			if (pkt_dev->cur_dst_mac_offset >=
L
Luiz Capitulino 已提交
2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352
			    pkt_dev->dst_mac_count) {
				pkt_dev->cur_dst_mac_offset = 0;
			}
		}

		tmp = pkt_dev->dst_mac[5] + (mc & 0xFF);
		pkt_dev->hh[5] = tmp;
		tmp = (pkt_dev->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8));
		pkt_dev->hh[4] = tmp;
		tmp = (pkt_dev->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8));
		pkt_dev->hh[3] = tmp;
		tmp = (pkt_dev->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8));
		pkt_dev->hh[2] = tmp;
		tmp = (pkt_dev->dst_mac[1] + (tmp >> 8));
		pkt_dev->hh[1] = tmp;
	}

2353
	if (pkt_dev->flags & F_MPLS_RND) {
2354
		unsigned int i;
2355
		for (i = 0; i < pkt_dev->nr_labels; i++)
2356 2357
			if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM)
				pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
2358
					     ((__force __be32)prandom_u32() &
2359 2360 2361
						      htonl(0x000fffff));
	}

F
Francesco Fondelli 已提交
2362
	if ((pkt_dev->flags & F_VID_RND) && (pkt_dev->vlan_id != 0xffff)) {
2363
		pkt_dev->vlan_id = prandom_u32() & (4096 - 1);
F
Francesco Fondelli 已提交
2364 2365 2366
	}

	if ((pkt_dev->flags & F_SVID_RND) && (pkt_dev->svlan_id != 0xffff)) {
2367
		pkt_dev->svlan_id = prandom_u32() & (4096 - 1);
F
Francesco Fondelli 已提交
2368 2369
	}

L
Luiz Capitulino 已提交
2370 2371
	if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
		if (pkt_dev->flags & F_UDPSRC_RND)
2372
			pkt_dev->cur_udp_src = prandom_u32() %
S
Stephen Hemminger 已提交
2373 2374
				(pkt_dev->udp_src_max - pkt_dev->udp_src_min)
				+ pkt_dev->udp_src_min;
L
Luiz Capitulino 已提交
2375 2376

		else {
L
Linus Torvalds 已提交
2377 2378 2379
			pkt_dev->cur_udp_src++;
			if (pkt_dev->cur_udp_src >= pkt_dev->udp_src_max)
				pkt_dev->cur_udp_src = pkt_dev->udp_src_min;
L
Luiz Capitulino 已提交
2380 2381 2382 2383 2384
		}
	}

	if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) {
		if (pkt_dev->flags & F_UDPDST_RND) {
2385
			pkt_dev->cur_udp_dst = prandom_u32() %
S
Stephen Hemminger 已提交
2386 2387
				(pkt_dev->udp_dst_max - pkt_dev->udp_dst_min)
				+ pkt_dev->udp_dst_min;
L
Luiz Capitulino 已提交
2388
		} else {
L
Linus Torvalds 已提交
2389
			pkt_dev->cur_udp_dst++;
L
Luiz Capitulino 已提交
2390
			if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max)
L
Linus Torvalds 已提交
2391
				pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min;
L
Luiz Capitulino 已提交
2392 2393
		}
	}
L
Linus Torvalds 已提交
2394 2395 2396

	if (!(pkt_dev->flags & F_IPV6)) {

2397 2398 2399
		imn = ntohl(pkt_dev->saddr_min);
		imx = ntohl(pkt_dev->saddr_max);
		if (imn < imx) {
L
Linus Torvalds 已提交
2400
			__u32 t;
L
Luiz Capitulino 已提交
2401
			if (pkt_dev->flags & F_IPSRC_RND)
2402
				t = prandom_u32() % (imx - imn) + imn;
L
Linus Torvalds 已提交
2403 2404 2405
			else {
				t = ntohl(pkt_dev->cur_saddr);
				t++;
2406
				if (t > imx)
L
Linus Torvalds 已提交
2407
					t = imn;
2408

L
Linus Torvalds 已提交
2409 2410 2411
			}
			pkt_dev->cur_saddr = htonl(t);
		}
L
Luiz Capitulino 已提交
2412

2413
		if (pkt_dev->cflows && f_seen(pkt_dev, flow)) {
L
Linus Torvalds 已提交
2414 2415
			pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
		} else {
A
Al Viro 已提交
2416 2417 2418
			imn = ntohl(pkt_dev->daddr_min);
			imx = ntohl(pkt_dev->daddr_max);
			if (imn < imx) {
L
Linus Torvalds 已提交
2419
				__u32 t;
A
Al Viro 已提交
2420
				__be32 s;
L
Linus Torvalds 已提交
2421 2422
				if (pkt_dev->flags & F_IPDST_RND) {

2423
					do {
2424 2425
						t = prandom_u32() %
							(imx - imn) + imn;
A
Al Viro 已提交
2426
						s = htonl(t);
2427 2428 2429 2430 2431
					} while (ipv4_is_loopback(s) ||
						ipv4_is_multicast(s) ||
						ipv4_is_lbcast(s) ||
						ipv4_is_zeronet(s) ||
						ipv4_is_local_multicast(s));
A
Al Viro 已提交
2432 2433
					pkt_dev->cur_daddr = s;
				} else {
L
Linus Torvalds 已提交
2434 2435 2436 2437 2438 2439 2440 2441
					t = ntohl(pkt_dev->cur_daddr);
					t++;
					if (t > imx) {
						t = imn;
					}
					pkt_dev->cur_daddr = htonl(t);
				}
			}
L
Luiz Capitulino 已提交
2442
			if (pkt_dev->cflows) {
2443
				pkt_dev->flows[flow].flags |= F_INIT;
L
Luiz Capitulino 已提交
2444 2445
				pkt_dev->flows[flow].cur_daddr =
				    pkt_dev->cur_daddr;
J
Jamal Hadi Salim 已提交
2446 2447 2448 2449
#ifdef CONFIG_XFRM
				if (pkt_dev->flags & F_IPSEC_ON)
					get_ipsec_sa(pkt_dev, flow);
#endif
L
Linus Torvalds 已提交
2450 2451 2452
				pkt_dev->nflows++;
			}
		}
L
Luiz Capitulino 已提交
2453 2454
	} else {		/* IPV6 * */

J
Joe Perches 已提交
2455
		if (!ipv6_addr_any(&pkt_dev->min_in6_daddr)) {
L
Linus Torvalds 已提交
2456 2457 2458 2459
			int i;

			/* Only random destinations yet */

L
Luiz Capitulino 已提交
2460
			for (i = 0; i < 4; i++) {
L
Linus Torvalds 已提交
2461
				pkt_dev->cur_in6_daddr.s6_addr32[i] =
2462
				    (((__force __be32)prandom_u32() |
L
Luiz Capitulino 已提交
2463 2464
				      pkt_dev->min_in6_daddr.s6_addr32[i]) &
				     pkt_dev->max_in6_daddr.s6_addr32[i]);
L
Linus Torvalds 已提交
2465
			}
L
Luiz Capitulino 已提交
2466
		}
L
Linus Torvalds 已提交
2467 2468
	}

L
Luiz Capitulino 已提交
2469 2470 2471
	if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) {
		__u32 t;
		if (pkt_dev->flags & F_TXSIZE_RND) {
2472
			t = prandom_u32() %
S
Stephen Hemminger 已提交
2473 2474
				(pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)
				+ pkt_dev->min_pkt_size;
L
Luiz Capitulino 已提交
2475
		} else {
L
Linus Torvalds 已提交
2476
			t = pkt_dev->cur_pkt_size + 1;
L
Luiz Capitulino 已提交
2477
			if (t > pkt_dev->max_pkt_size)
L
Linus Torvalds 已提交
2478
				t = pkt_dev->min_pkt_size;
L
Luiz Capitulino 已提交
2479 2480 2481
		}
		pkt_dev->cur_pkt_size = t;
	}
L
Linus Torvalds 已提交
2482

2483
	set_cur_queue_map(pkt_dev);
R
Robert Olsson 已提交
2484

L
Linus Torvalds 已提交
2485 2486 2487
	pkt_dev->flows[flow].count++;
}

J
Jamal Hadi Salim 已提交
2488 2489 2490 2491 2492 2493

#ifdef CONFIG_XFRM
static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
{
	struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
	int err = 0;
2494
	struct net *net = dev_net(pkt_dev->odev);
J
Jamal Hadi Salim 已提交
2495 2496 2497 2498 2499 2500 2501 2502

	if (!x)
		return 0;
	/* XXX: we dont support tunnel mode for now until
	 * we resolve the dst issue */
	if (x->props.mode != XFRM_MODE_TRANSPORT)
		return 0;

2503
	err = x->outer_mode->output(x, skb);
2504 2505
	if (err) {
		XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
J
Jamal Hadi Salim 已提交
2506
		goto error;
2507
	}
J
Jamal Hadi Salim 已提交
2508
	err = x->type->output(x, skb);
2509 2510
	if (err) {
		XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEPROTOERROR);
J
Jamal Hadi Salim 已提交
2511
		goto error;
2512
	}
2513
	spin_lock_bh(&x->lock);
2514
	x->curlft.bytes += skb->len;
J
Jamal Hadi Salim 已提交
2515
	x->curlft.packets++;
2516
	spin_unlock_bh(&x->lock);
J
Jamal Hadi Salim 已提交
2517 2518 2519 2520
error:
	return err;
}

S
Stephen Hemminger 已提交
2521
static void free_SAs(struct pktgen_dev *pkt_dev)
J
Jamal Hadi Salim 已提交
2522 2523 2524
{
	if (pkt_dev->cflows) {
		/* let go of the SAs if we have them */
2525 2526
		int i;
		for (i = 0; i < pkt_dev->cflows; i++) {
J
Jamal Hadi Salim 已提交
2527 2528 2529 2530 2531 2532 2533 2534 2535
			struct xfrm_state *x = pkt_dev->flows[i].x;
			if (x) {
				xfrm_state_put(x);
				pkt_dev->flows[i].x = NULL;
			}
		}
	}
}

S
Stephen Hemminger 已提交
2536
static int process_ipsec(struct pktgen_dev *pkt_dev,
J
Jamal Hadi Salim 已提交
2537 2538 2539 2540 2541 2542 2543 2544
			      struct sk_buff *skb, __be16 protocol)
{
	if (pkt_dev->flags & F_IPSEC_ON) {
		struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
		int nhead = 0;
		if (x) {
			int ret;
			__u8 *eth;
2545 2546
			struct iphdr *iph;

J
Jamal Hadi Salim 已提交
2547
			nhead = x->props.header_len - skb_headroom(skb);
2548
			if (nhead > 0) {
J
Jamal Hadi Salim 已提交
2549 2550
				ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
				if (ret < 0) {
J
Joe Perches 已提交
2551 2552
					pr_err("Error expanding ipsec packet %d\n",
					       ret);
2553
					goto err;
J
Jamal Hadi Salim 已提交
2554 2555 2556 2557 2558 2559 2560
				}
			}

			/* ipsec is not expecting ll header */
			skb_pull(skb, ETH_HLEN);
			ret = pktgen_output_ipsec(skb, pkt_dev);
			if (ret) {
J
Joe Perches 已提交
2561
				pr_err("Error creating ipsec packet %d\n", ret);
2562
				goto err;
J
Jamal Hadi Salim 已提交
2563 2564 2565 2566
			}
			/* restore ll */
			eth = (__u8 *) skb_push(skb, ETH_HLEN);
			memcpy(eth, pkt_dev->hh, 12);
2567
			*(u16 *) &eth[12] = protocol;
2568 2569 2570 2571 2572

			/* Update IPv4 header len as well as checksum value */
			iph = ip_hdr(skb);
			iph->tot_len = htons(skb->len - ETH_HLEN);
			ip_send_check(iph);
J
Jamal Hadi Salim 已提交
2573 2574 2575
		}
	}
	return 1;
2576 2577 2578
err:
	kfree_skb(skb);
	return 0;
J
Jamal Hadi Salim 已提交
2579 2580 2581
}
#endif

2582 2583
static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
{
2584
	unsigned int i;
2585
	for (i = 0; i < pkt_dev->nr_labels; i++)
2586
		*mpls++ = pkt_dev->labels[i] & ~MPLS_STACK_BOTTOM;
2587

2588 2589 2590 2591
	mpls--;
	*mpls |= MPLS_STACK_BOTTOM;
}

A
Al Viro 已提交
2592 2593 2594 2595 2596 2597
static inline __be16 build_tci(unsigned int id, unsigned int cfi,
			       unsigned int prio)
{
	return htons(id | (cfi << 12) | (prio << 13));
}

E
Eric Dumazet 已提交
2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,
				int datalen)
{
	struct timeval timestamp;
	struct pktgen_hdr *pgh;

	pgh = (struct pktgen_hdr *)skb_put(skb, sizeof(*pgh));
	datalen -= sizeof(*pgh);

	if (pkt_dev->nfrags <= 0) {
2608
		memset(skb_put(skb, datalen), 0, datalen);
E
Eric Dumazet 已提交
2609 2610 2611
	} else {
		int frags = pkt_dev->nfrags;
		int i, len;
2612
		int frag_len;
E
Eric Dumazet 已提交
2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623


		if (frags > MAX_SKB_FRAGS)
			frags = MAX_SKB_FRAGS;
		len = datalen - frags * PAGE_SIZE;
		if (len > 0) {
			memset(skb_put(skb, len), 0, len);
			datalen = frags * PAGE_SIZE;
		}

		i = 0;
2624 2625
		frag_len = (datalen/frags) < PAGE_SIZE ?
			   (datalen/frags) : PAGE_SIZE;
E
Eric Dumazet 已提交
2626 2627 2628 2629 2630 2631 2632 2633 2634 2635
		while (datalen > 0) {
			if (unlikely(!pkt_dev->page)) {
				int node = numa_node_id();

				if (pkt_dev->node >= 0 && (pkt_dev->flags & F_NODE))
					node = pkt_dev->node;
				pkt_dev->page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
				if (!pkt_dev->page)
					break;
			}
2636
			get_page(pkt_dev->page);
2637
			skb_frag_set_page(skb, i, pkt_dev->page);
E
Eric Dumazet 已提交
2638
			skb_shinfo(skb)->frags[i].page_offset = 0;
2639 2640
			/*last fragment, fill rest of data*/
			if (i == (frags - 1))
E
Eric Dumazet 已提交
2641 2642
				skb_frag_size_set(&skb_shinfo(skb)->frags[i],
				    (datalen < PAGE_SIZE ? datalen : PAGE_SIZE));
2643
			else
E
Eric Dumazet 已提交
2644 2645 2646 2647
				skb_frag_size_set(&skb_shinfo(skb)->frags[i], frag_len);
			datalen -= skb_frag_size(&skb_shinfo(skb)->frags[i]);
			skb->len += skb_frag_size(&skb_shinfo(skb)->frags[i]);
			skb->data_len += skb_frag_size(&skb_shinfo(skb)->frags[i]);
E
Eric Dumazet 已提交
2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663
			i++;
			skb_shinfo(skb)->nr_frags = i;
		}
	}

	/* Stamp the time, and sequence number,
	 * convert them to network byte order
	 */
	pgh->pgh_magic = htonl(PKTGEN_MAGIC);
	pgh->seq_num = htonl(pkt_dev->seq_num);

	do_gettimeofday(&timestamp);
	pgh->tv_sec = htonl(timestamp.tv_sec);
	pgh->tv_usec = htonl(timestamp.tv_usec);
}

2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686
static struct sk_buff *pktgen_alloc_skb(struct net_device *dev,
					struct pktgen_dev *pkt_dev,
					unsigned int extralen)
{
	struct sk_buff *skb = NULL;
	unsigned int size = pkt_dev->cur_pkt_size + 64 + extralen +
			    pkt_dev->pkt_overhead;

	if (pkt_dev->flags & F_NODE) {
		int node = pkt_dev->node >= 0 ? pkt_dev->node : numa_node_id();

		skb = __alloc_skb(NET_SKB_PAD + size, GFP_NOWAIT, 0, node);
		if (likely(skb)) {
			skb_reserve(skb, NET_SKB_PAD);
			skb->dev = dev;
		}
	} else {
		 skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT);
	}

	return skb;
}

L
Luiz Capitulino 已提交
2687 2688
static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
					struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
2689 2690 2691 2692 2693 2694
{
	struct sk_buff *skb = NULL;
	__u8 *eth;
	struct udphdr *udph;
	int datalen, iplen;
	struct iphdr *iph;
2695
	__be16 protocol = htons(ETH_P_IP);
2696
	__be32 *mpls;
F
Francesco Fondelli 已提交
2697 2698 2699 2700
	__be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
	__be16 *vlan_encapsulated_proto = NULL;  /* packet type ID field (or len) for VLAN tag */
	__be16 *svlan_tci = NULL;                /* Encapsulates priority and SVLAN ID */
	__be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
2701
	u16 queue_map;
2702 2703

	if (pkt_dev->nr_labels)
2704
		protocol = htons(ETH_P_MPLS_UC);
L
Luiz Capitulino 已提交
2705

F
Francesco Fondelli 已提交
2706
	if (pkt_dev->vlan_id != 0xffff)
2707
		protocol = htons(ETH_P_8021Q);
F
Francesco Fondelli 已提交
2708

2709 2710 2711 2712
	/* Update any of the values, used when we're incrementing various
	 * fields.
	 */
	mod_cur_headers(pkt_dev);
2713
	queue_map = pkt_dev->cur_queue_map;
2714

2715
	datalen = (odev->hard_header_len + 16) & ~0xf;
R
Robert Olsson 已提交
2716

2717
	skb = pktgen_alloc_skb(odev, pkt_dev, datalen);
L
Linus Torvalds 已提交
2718 2719 2720 2721 2722
	if (!skb) {
		sprintf(pkt_dev->result, "No memory");
		return NULL;
	}

2723
	prefetchw(skb->data);
2724
	skb_reserve(skb, datalen);
L
Linus Torvalds 已提交
2725 2726 2727

	/*  Reserve for ethernet and IP header  */
	eth = (__u8 *) skb_push(skb, 14);
2728 2729 2730
	mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
	if (pkt_dev->nr_labels)
		mpls_push(mpls, pkt_dev);
F
Francesco Fondelli 已提交
2731 2732

	if (pkt_dev->vlan_id != 0xffff) {
2733
		if (pkt_dev->svlan_id != 0xffff) {
F
Francesco Fondelli 已提交
2734
			svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
A
Al Viro 已提交
2735 2736 2737
			*svlan_tci = build_tci(pkt_dev->svlan_id,
					       pkt_dev->svlan_cfi,
					       pkt_dev->svlan_p);
F
Francesco Fondelli 已提交
2738
			svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
2739
			*svlan_encapsulated_proto = htons(ETH_P_8021Q);
F
Francesco Fondelli 已提交
2740 2741
		}
		vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
A
Al Viro 已提交
2742 2743 2744
		*vlan_tci = build_tci(pkt_dev->vlan_id,
				      pkt_dev->vlan_cfi,
				      pkt_dev->vlan_p);
F
Francesco Fondelli 已提交
2745
		vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
2746
		*vlan_encapsulated_proto = htons(ETH_P_IP);
F
Francesco Fondelli 已提交
2747 2748
	}

2749 2750 2751 2752 2753 2754
	skb_set_mac_header(skb, 0);
	skb_set_network_header(skb, skb->len);
	iph = (struct iphdr *) skb_put(skb, sizeof(struct iphdr));

	skb_set_transport_header(skb, skb->len);
	udph = (struct udphdr *) skb_put(skb, sizeof(struct udphdr));
2755
	skb_set_queue_mapping(skb, queue_map);
J
John Fastabend 已提交
2756 2757
	skb->priority = pkt_dev->skb_priority;

L
Linus Torvalds 已提交
2758
	memcpy(eth, pkt_dev->hh, 12);
A
Al Viro 已提交
2759
	*(__be16 *) & eth[12] = protocol;
L
Linus Torvalds 已提交
2760

2761 2762
	/* Eth + IPh + UDPh + mpls */
	datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
2763
		  pkt_dev->pkt_overhead;
2764
	if (datalen < 0 || datalen < sizeof(struct pktgen_hdr))
L
Linus Torvalds 已提交
2765
		datalen = sizeof(struct pktgen_hdr);
L
Luiz Capitulino 已提交
2766

L
Linus Torvalds 已提交
2767 2768
	udph->source = htons(pkt_dev->cur_udp_src);
	udph->dest = htons(pkt_dev->cur_udp_dst);
L
Luiz Capitulino 已提交
2769
	udph->len = htons(datalen + 8);	/* DATA + udphdr */
2770
	udph->check = 0;
L
Linus Torvalds 已提交
2771 2772 2773 2774

	iph->ihl = 5;
	iph->version = 4;
	iph->ttl = 32;
F
Francesco Fondelli 已提交
2775
	iph->tos = pkt_dev->tos;
L
Luiz Capitulino 已提交
2776
	iph->protocol = IPPROTO_UDP;	/* UDP */
L
Linus Torvalds 已提交
2777 2778
	iph->saddr = pkt_dev->cur_saddr;
	iph->daddr = pkt_dev->cur_daddr;
E
Eric Dumazet 已提交
2779 2780
	iph->id = htons(pkt_dev->ip_id);
	pkt_dev->ip_id++;
L
Linus Torvalds 已提交
2781 2782 2783
	iph->frag_off = 0;
	iplen = 20 + 8 + datalen;
	iph->tot_len = htons(iplen);
2784
	ip_send_check(iph);
2785
	skb->protocol = protocol;
L
Linus Torvalds 已提交
2786 2787
	skb->dev = odev;
	skb->pkt_type = PACKET_HOST;
2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805

	if (!(pkt_dev->flags & F_UDPCSUM)) {
		skb->ip_summed = CHECKSUM_NONE;
	} else if (odev->features & NETIF_F_V4_CSUM) {
		skb->ip_summed = CHECKSUM_PARTIAL;
		skb->csum = 0;
		udp4_hwcsum(skb, udph->source, udph->dest);
	} else {
		__wsum csum = udp_csum(skb);

		/* add protocol-dependent pseudo-header */
		udph->check = csum_tcpudp_magic(udph->source, udph->dest,
						datalen + 8, IPPROTO_UDP, csum);

		if (udph->check == 0)
			udph->check = CSUM_MANGLED_0;
	}

E
Eric Dumazet 已提交
2806
	pktgen_finalize_skb(pkt_dev, skb, datalen);
L
Linus Torvalds 已提交
2807

J
Jamal Hadi Salim 已提交
2808 2809 2810 2811 2812
#ifdef CONFIG_XFRM
	if (!process_ipsec(pkt_dev, skb, protocol))
		return NULL;
#endif

L
Linus Torvalds 已提交
2813 2814 2815
	return skb;
}

L
Luiz Capitulino 已提交
2816 2817
static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
					struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
2818 2819 2820 2821
{
	struct sk_buff *skb = NULL;
	__u8 *eth;
	struct udphdr *udph;
2822
	int datalen, udplen;
L
Linus Torvalds 已提交
2823
	struct ipv6hdr *iph;
2824
	__be16 protocol = htons(ETH_P_IPV6);
2825
	__be32 *mpls;
F
Francesco Fondelli 已提交
2826 2827 2828 2829
	__be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
	__be16 *vlan_encapsulated_proto = NULL;  /* packet type ID field (or len) for VLAN tag */
	__be16 *svlan_tci = NULL;                /* Encapsulates priority and SVLAN ID */
	__be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
2830
	u16 queue_map;
2831 2832

	if (pkt_dev->nr_labels)
2833
		protocol = htons(ETH_P_MPLS_UC);
2834

F
Francesco Fondelli 已提交
2835
	if (pkt_dev->vlan_id != 0xffff)
2836
		protocol = htons(ETH_P_8021Q);
F
Francesco Fondelli 已提交
2837

2838 2839 2840 2841
	/* Update any of the values, used when we're incrementing various
	 * fields.
	 */
	mod_cur_headers(pkt_dev);
2842
	queue_map = pkt_dev->cur_queue_map;
2843

2844
	skb = pktgen_alloc_skb(odev, pkt_dev, 16);
L
Linus Torvalds 已提交
2845 2846 2847 2848 2849
	if (!skb) {
		sprintf(pkt_dev->result, "No memory");
		return NULL;
	}

2850
	prefetchw(skb->data);
L
Linus Torvalds 已提交
2851 2852 2853 2854
	skb_reserve(skb, 16);

	/*  Reserve for ethernet and IP header  */
	eth = (__u8 *) skb_push(skb, 14);
2855 2856 2857
	mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
	if (pkt_dev->nr_labels)
		mpls_push(mpls, pkt_dev);
F
Francesco Fondelli 已提交
2858 2859

	if (pkt_dev->vlan_id != 0xffff) {
2860
		if (pkt_dev->svlan_id != 0xffff) {
F
Francesco Fondelli 已提交
2861
			svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
A
Al Viro 已提交
2862 2863 2864
			*svlan_tci = build_tci(pkt_dev->svlan_id,
					       pkt_dev->svlan_cfi,
					       pkt_dev->svlan_p);
F
Francesco Fondelli 已提交
2865
			svlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
2866
			*svlan_encapsulated_proto = htons(ETH_P_8021Q);
F
Francesco Fondelli 已提交
2867 2868
		}
		vlan_tci = (__be16 *)skb_put(skb, sizeof(__be16));
A
Al Viro 已提交
2869 2870 2871
		*vlan_tci = build_tci(pkt_dev->vlan_id,
				      pkt_dev->vlan_cfi,
				      pkt_dev->vlan_p);
F
Francesco Fondelli 已提交
2872
		vlan_encapsulated_proto = (__be16 *)skb_put(skb, sizeof(__be16));
2873
		*vlan_encapsulated_proto = htons(ETH_P_IPV6);
F
Francesco Fondelli 已提交
2874 2875
	}

2876 2877 2878 2879 2880 2881
	skb_set_mac_header(skb, 0);
	skb_set_network_header(skb, skb->len);
	iph = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr));

	skb_set_transport_header(skb, skb->len);
	udph = (struct udphdr *) skb_put(skb, sizeof(struct udphdr));
2882
	skb_set_queue_mapping(skb, queue_map);
J
John Fastabend 已提交
2883
	skb->priority = pkt_dev->skb_priority;
L
Linus Torvalds 已提交
2884 2885

	memcpy(eth, pkt_dev->hh, 12);
2886
	*(__be16 *) &eth[12] = protocol;
2887

2888 2889 2890
	/* Eth + IPh + UDPh + mpls */
	datalen = pkt_dev->cur_pkt_size - 14 -
		  sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
2891
		  pkt_dev->pkt_overhead;
L
Linus Torvalds 已提交
2892

2893
	if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) {
L
Linus Torvalds 已提交
2894
		datalen = sizeof(struct pktgen_hdr);
2895
		net_info_ratelimited("increased datalen to %d\n", datalen);
L
Linus Torvalds 已提交
2896 2897
	}

2898
	udplen = datalen + sizeof(struct udphdr);
L
Linus Torvalds 已提交
2899 2900
	udph->source = htons(pkt_dev->cur_udp_src);
	udph->dest = htons(pkt_dev->cur_udp_dst);
2901 2902
	udph->len = htons(udplen);
	udph->check = 0;
L
Linus Torvalds 已提交
2903

2904
	*(__be32 *) iph = htonl(0x60000000);	/* Version + flow */
L
Linus Torvalds 已提交
2905

F
Francesco Fondelli 已提交
2906 2907
	if (pkt_dev->traffic_class) {
		/* Version + traffic class + flow (0) */
A
Al Viro 已提交
2908
		*(__be32 *)iph |= htonl(0x60000000 | (pkt_dev->traffic_class << 20));
F
Francesco Fondelli 已提交
2909 2910
	}

L
Linus Torvalds 已提交
2911 2912
	iph->hop_limit = 32;

2913
	iph->payload_len = htons(udplen);
L
Linus Torvalds 已提交
2914 2915
	iph->nexthdr = IPPROTO_UDP;

A
Alexey Dobriyan 已提交
2916 2917
	iph->daddr = pkt_dev->cur_in6_daddr;
	iph->saddr = pkt_dev->cur_in6_saddr;
L
Linus Torvalds 已提交
2918

2919
	skb->protocol = protocol;
L
Linus Torvalds 已提交
2920 2921 2922
	skb->dev = odev;
	skb->pkt_type = PACKET_HOST;

2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939
	if (!(pkt_dev->flags & F_UDPCSUM)) {
		skb->ip_summed = CHECKSUM_NONE;
	} else if (odev->features & NETIF_F_V6_CSUM) {
		skb->ip_summed = CHECKSUM_PARTIAL;
		skb->csum_start = skb_transport_header(skb) - skb->head;
		skb->csum_offset = offsetof(struct udphdr, check);
		udph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, 0);
	} else {
		__wsum csum = udp_csum(skb);

		/* add protocol-dependent pseudo-header */
		udph->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, csum);

		if (udph->check == 0)
			udph->check = CSUM_MANGLED_0;
	}

E
Eric Dumazet 已提交
2940
	pktgen_finalize_skb(pkt_dev, skb, datalen);
L
Luiz Capitulino 已提交
2941

L
Linus Torvalds 已提交
2942 2943 2944
	return skb;
}

S
Stephen Hemminger 已提交
2945 2946
static struct sk_buff *fill_packet(struct net_device *odev,
				   struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
2947
{
L
Luiz Capitulino 已提交
2948
	if (pkt_dev->flags & F_IPV6)
L
Linus Torvalds 已提交
2949 2950 2951 2952 2953
		return fill_packet_ipv6(odev, pkt_dev);
	else
		return fill_packet_ipv4(odev, pkt_dev);
}

L
Luiz Capitulino 已提交
2954
static void pktgen_clear_counters(struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
2955
{
L
Luiz Capitulino 已提交
2956 2957
	pkt_dev->seq_num = 1;
	pkt_dev->idle_acc = 0;
L
Linus Torvalds 已提交
2958
	pkt_dev->sofar = 0;
L
Luiz Capitulino 已提交
2959 2960
	pkt_dev->tx_bytes = 0;
	pkt_dev->errors = 0;
L
Linus Torvalds 已提交
2961 2962 2963 2964 2965 2966
}

/* Set up structure for sending pkts, clear counters */

static void pktgen_run(struct pktgen_thread *t)
{
2967
	struct pktgen_dev *pkt_dev;
L
Linus Torvalds 已提交
2968 2969
	int started = 0;

J
Joe Perches 已提交
2970
	func_enter();
L
Linus Torvalds 已提交
2971 2972

	if_lock(t);
2973
	list_for_each_entry(pkt_dev, &t->if_list, list) {
L
Linus Torvalds 已提交
2974 2975 2976 2977 2978 2979

		/*
		 * setup odev and create initial packet.
		 */
		pktgen_setup_inject(pkt_dev);

L
Luiz Capitulino 已提交
2980
		if (pkt_dev->odev) {
L
Linus Torvalds 已提交
2981
			pktgen_clear_counters(pkt_dev);
L
Luiz Capitulino 已提交
2982
			pkt_dev->running = 1;	/* Cranke yeself! */
L
Linus Torvalds 已提交
2983
			pkt_dev->skb = NULL;
D
Daniel Borkmann 已提交
2984
			pkt_dev->started_at = pkt_dev->next_tx = ktime_get();
2985

2986
			set_pkt_overhead(pkt_dev);
L
Luiz Capitulino 已提交
2987

L
Linus Torvalds 已提交
2988 2989
			strcpy(pkt_dev->result, "Starting");
			started++;
L
Luiz Capitulino 已提交
2990
		} else
L
Linus Torvalds 已提交
2991 2992 2993
			strcpy(pkt_dev->result, "Error starting");
	}
	if_unlock(t);
L
Luiz Capitulino 已提交
2994 2995
	if (started)
		t->control &= ~(T_STOP);
L
Linus Torvalds 已提交
2996 2997
}

C
Cong Wang 已提交
2998
static void pktgen_stop_all_threads_ifs(struct pktgen_net *pn)
L
Linus Torvalds 已提交
2999
{
3000
	struct pktgen_thread *t;
L
Linus Torvalds 已提交
3001

J
Joe Perches 已提交
3002
	func_enter();
L
Linus Torvalds 已提交
3003

3004
	mutex_lock(&pktgen_thread_lock);
3005

C
Cong Wang 已提交
3006
	list_for_each_entry(t, &pn->pktgen_threads, th_list)
3007
		t->control |= T_STOP;
3008

3009
	mutex_unlock(&pktgen_thread_lock);
L
Linus Torvalds 已提交
3010 3011
}

S
Stephen Hemminger 已提交
3012
static int thread_is_running(const struct pktgen_thread *t)
L
Linus Torvalds 已提交
3013
{
S
Stephen Hemminger 已提交
3014
	const struct pktgen_dev *pkt_dev;
L
Linus Torvalds 已提交
3015

3016
	list_for_each_entry(pkt_dev, &t->if_list, list)
S
Stephen Hemminger 已提交
3017 3018 3019
		if (pkt_dev->running)
			return 1;
	return 0;
L
Linus Torvalds 已提交
3020 3021
}

L
Luiz Capitulino 已提交
3022
static int pktgen_wait_thread_run(struct pktgen_thread *t)
L
Linus Torvalds 已提交
3023
{
L
Luiz Capitulino 已提交
3024
	if_lock(t);
L
Linus Torvalds 已提交
3025

L
Luiz Capitulino 已提交
3026
	while (thread_is_running(t)) {
L
Linus Torvalds 已提交
3027

L
Luiz Capitulino 已提交
3028
		if_unlock(t);
L
Linus Torvalds 已提交
3029

L
Luiz Capitulino 已提交
3030
		msleep_interruptible(100);
L
Linus Torvalds 已提交
3031

L
Luiz Capitulino 已提交
3032 3033 3034 3035 3036 3037 3038 3039
		if (signal_pending(current))
			goto signal;
		if_lock(t);
	}
	if_unlock(t);
	return 1;
signal:
	return 0;
L
Linus Torvalds 已提交
3040 3041
}

C
Cong Wang 已提交
3042
static int pktgen_wait_all_threads_run(struct pktgen_net *pn)
L
Linus Torvalds 已提交
3043
{
3044
	struct pktgen_thread *t;
L
Linus Torvalds 已提交
3045
	int sig = 1;
L
Luiz Capitulino 已提交
3046

3047
	mutex_lock(&pktgen_thread_lock);
3048

C
Cong Wang 已提交
3049
	list_for_each_entry(t, &pn->pktgen_threads, th_list) {
L
Linus Torvalds 已提交
3050
		sig = pktgen_wait_thread_run(t);
L
Luiz Capitulino 已提交
3051 3052
		if (sig == 0)
			break;
L
Linus Torvalds 已提交
3053
	}
3054 3055

	if (sig == 0)
C
Cong Wang 已提交
3056
		list_for_each_entry(t, &pn->pktgen_threads, th_list)
L
Linus Torvalds 已提交
3057
			t->control |= (T_STOP);
3058

3059
	mutex_unlock(&pktgen_thread_lock);
L
Linus Torvalds 已提交
3060 3061 3062
	return sig;
}

C
Cong Wang 已提交
3063
static void pktgen_run_all_threads(struct pktgen_net *pn)
L
Linus Torvalds 已提交
3064
{
3065
	struct pktgen_thread *t;
L
Linus Torvalds 已提交
3066

J
Joe Perches 已提交
3067
	func_enter();
L
Linus Torvalds 已提交
3068

3069
	mutex_lock(&pktgen_thread_lock);
L
Linus Torvalds 已提交
3070

C
Cong Wang 已提交
3071
	list_for_each_entry(t, &pn->pktgen_threads, th_list)
L
Linus Torvalds 已提交
3072
		t->control |= (T_RUN);
3073

3074
	mutex_unlock(&pktgen_thread_lock);
L
Linus Torvalds 已提交
3075

3076 3077
	/* Propagate thread->control  */
	schedule_timeout_interruptible(msecs_to_jiffies(125));
L
Luiz Capitulino 已提交
3078

C
Cong Wang 已提交
3079
	pktgen_wait_all_threads_run(pn);
L
Linus Torvalds 已提交
3080 3081
}

C
Cong Wang 已提交
3082
static void pktgen_reset_all_threads(struct pktgen_net *pn)
3083 3084 3085
{
	struct pktgen_thread *t;

J
Joe Perches 已提交
3086
	func_enter();
3087 3088 3089

	mutex_lock(&pktgen_thread_lock);

C
Cong Wang 已提交
3090
	list_for_each_entry(t, &pn->pktgen_threads, th_list)
3091 3092 3093 3094
		t->control |= (T_REMDEVALL);

	mutex_unlock(&pktgen_thread_lock);

3095 3096
	/* Propagate thread->control  */
	schedule_timeout_interruptible(msecs_to_jiffies(125));
3097

C
Cong Wang 已提交
3098
	pktgen_wait_all_threads_run(pn);
3099 3100
}

L
Linus Torvalds 已提交
3101 3102
static void show_results(struct pktgen_dev *pkt_dev, int nr_frags)
{
3103
	__u64 bps, mbps, pps;
L
Luiz Capitulino 已提交
3104
	char *p = pkt_dev->result;
3105 3106 3107 3108
	ktime_t elapsed = ktime_sub(pkt_dev->stopped_at,
				    pkt_dev->started_at);
	ktime_t idle = ns_to_ktime(pkt_dev->idle_acc);

3109
	p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n",
3110 3111 3112
		     (unsigned long long)ktime_to_us(elapsed),
		     (unsigned long long)ktime_to_us(ktime_sub(elapsed, idle)),
		     (unsigned long long)ktime_to_us(idle),
L
Luiz Capitulino 已提交
3113 3114 3115
		     (unsigned long long)pkt_dev->sofar,
		     pkt_dev->cur_pkt_size, nr_frags);

3116 3117
	pps = div64_u64(pkt_dev->sofar * NSEC_PER_SEC,
			ktime_to_ns(elapsed));
L
Luiz Capitulino 已提交
3118 3119 3120 3121 3122 3123 3124 3125 3126 3127

	bps = pps * 8 * pkt_dev->cur_pkt_size;

	mbps = bps;
	do_div(mbps, 1000000);
	p += sprintf(p, "  %llupps %lluMb/sec (%llubps) errors: %llu",
		     (unsigned long long)pps,
		     (unsigned long long)mbps,
		     (unsigned long long)bps,
		     (unsigned long long)pkt_dev->errors);
L
Linus Torvalds 已提交
3128 3129 3130
}

/* Set stopped-at timer, remove from running list, do counters & statistics */
L
Luiz Capitulino 已提交
3131
static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
3132
{
L
Luiz Capitulino 已提交
3133
	int nr_frags = pkt_dev->skb ? skb_shinfo(pkt_dev->skb)->nr_frags : -1;
3134

L
Luiz Capitulino 已提交
3135
	if (!pkt_dev->running) {
J
Joe Perches 已提交
3136 3137
		pr_warning("interface: %s is already stopped\n",
			   pkt_dev->odevname);
L
Luiz Capitulino 已提交
3138 3139
		return -EINVAL;
	}
L
Linus Torvalds 已提交
3140

S
Stephen Hemminger 已提交
3141 3142
	kfree_skb(pkt_dev->skb);
	pkt_dev->skb = NULL;
D
Daniel Borkmann 已提交
3143
	pkt_dev->stopped_at = ktime_get();
L
Luiz Capitulino 已提交
3144
	pkt_dev->running = 0;
L
Linus Torvalds 已提交
3145

3146
	show_results(pkt_dev, nr_frags);
L
Linus Torvalds 已提交
3147

L
Luiz Capitulino 已提交
3148
	return 0;
L
Linus Torvalds 已提交
3149 3150
}

L
Luiz Capitulino 已提交
3151
static struct pktgen_dev *next_to_run(struct pktgen_thread *t)
L
Linus Torvalds 已提交
3152
{
3153
	struct pktgen_dev *pkt_dev, *best = NULL;
L
Luiz Capitulino 已提交
3154

L
Linus Torvalds 已提交
3155 3156
	if_lock(t);

3157 3158
	list_for_each_entry(pkt_dev, &t->if_list, list) {
		if (!pkt_dev->running)
L
Luiz Capitulino 已提交
3159 3160
			continue;
		if (best == NULL)
3161
			best = pkt_dev;
D
Daniel Borkmann 已提交
3162
		else if (ktime_compare(pkt_dev->next_tx, best->next_tx) < 0)
3163
			best = pkt_dev;
L
Linus Torvalds 已提交
3164 3165
	}
	if_unlock(t);
L
Luiz Capitulino 已提交
3166
	return best;
L
Linus Torvalds 已提交
3167 3168
}

L
Luiz Capitulino 已提交
3169 3170
static void pktgen_stop(struct pktgen_thread *t)
{
3171
	struct pktgen_dev *pkt_dev;
L
Linus Torvalds 已提交
3172

J
Joe Perches 已提交
3173
	func_enter();
L
Linus Torvalds 已提交
3174

L
Luiz Capitulino 已提交
3175
	if_lock(t);
L
Linus Torvalds 已提交
3176

3177 3178
	list_for_each_entry(pkt_dev, &t->if_list, list) {
		pktgen_stop_device(pkt_dev);
3179
	}
L
Linus Torvalds 已提交
3180

L
Luiz Capitulino 已提交
3181
	if_unlock(t);
L
Linus Torvalds 已提交
3182 3183
}

3184 3185 3186 3187 3188 3189
/*
 * one of our devices needs to be removed - find it
 * and remove it
 */
static void pktgen_rem_one_if(struct pktgen_thread *t)
{
3190 3191
	struct list_head *q, *n;
	struct pktgen_dev *cur;
3192

J
Joe Perches 已提交
3193
	func_enter();
3194 3195 3196

	if_lock(t);

3197 3198
	list_for_each_safe(q, n, &t->if_list) {
		cur = list_entry(q, struct pktgen_dev, list);
3199

L
Luiz Capitulino 已提交
3200 3201
		if (!cur->removal_mark)
			continue;
3202

3203
		kfree_skb(cur->skb);
3204 3205 3206 3207 3208 3209 3210 3211 3212 3213
		cur->skb = NULL;

		pktgen_remove_device(t, cur);

		break;
	}

	if_unlock(t);
}

L
Luiz Capitulino 已提交
3214
static void pktgen_rem_all_ifs(struct pktgen_thread *t)
L
Linus Torvalds 已提交
3215
{
3216 3217
	struct list_head *q, *n;
	struct pktgen_dev *cur;
L
Luiz Capitulino 已提交
3218

J
Joe Perches 已提交
3219 3220
	func_enter();

L
Luiz Capitulino 已提交
3221
	/* Remove all devices, free mem */
3222

L
Luiz Capitulino 已提交
3223
	if_lock(t);
L
Linus Torvalds 已提交
3224

3225 3226
	list_for_each_safe(q, n, &t->if_list) {
		cur = list_entry(q, struct pktgen_dev, list);
3227

3228
		kfree_skb(cur->skb);
3229 3230
		cur->skb = NULL;

L
Linus Torvalds 已提交
3231 3232 3233
		pktgen_remove_device(t, cur);
	}

L
Luiz Capitulino 已提交
3234
	if_unlock(t);
L
Linus Torvalds 已提交
3235 3236
}

L
Luiz Capitulino 已提交
3237
static void pktgen_rem_thread(struct pktgen_thread *t)
L
Linus Torvalds 已提交
3238
{
L
Luiz Capitulino 已提交
3239
	/* Remove from the thread list */
C
Cong Wang 已提交
3240
	remove_proc_entry(t->tsk->comm, t->net->proc_dir);
L
Linus Torvalds 已提交
3241 3242
}

3243
static void pktgen_resched(struct pktgen_dev *pkt_dev)
3244
{
D
Daniel Borkmann 已提交
3245
	ktime_t idle_start = ktime_get();
3246
	schedule();
D
Daniel Borkmann 已提交
3247
	pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_get(), idle_start));
3248
}
3249

3250 3251
static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
{
D
Daniel Borkmann 已提交
3252
	ktime_t idle_start = ktime_get();
3253

3254 3255 3256 3257 3258 3259 3260 3261 3262
	while (atomic_read(&(pkt_dev->skb->users)) != 1) {
		if (signal_pending(current))
			break;

		if (need_resched())
			pktgen_resched(pkt_dev);
		else
			cpu_relax();
	}
D
Daniel Borkmann 已提交
3263
	pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_get(), idle_start));
3264 3265
}

S
Stephen Hemminger 已提交
3266
static void pktgen_xmit(struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
3267
{
3268
	struct net_device *odev = pkt_dev->odev;
3269
	netdev_tx_t (*xmit)(struct sk_buff *, struct net_device *)
3270
		= odev->netdev_ops->ndo_start_xmit;
3271 3272
	struct netdev_queue *txq;
	u16 queue_map;
L
Linus Torvalds 已提交
3273 3274
	int ret;

3275 3276 3277 3278
	/* If device is offline, then don't send */
	if (unlikely(!netif_running(odev) || !netif_carrier_ok(odev))) {
		pktgen_stop_device(pkt_dev);
		return;
3279 3280
	}

3281 3282 3283 3284
	/* This is max DELAY, this has special meaning of
	 * "never transmit"
	 */
	if (unlikely(pkt_dev->delay == ULLONG_MAX)) {
D
Daniel Borkmann 已提交
3285
		pkt_dev->next_tx = ktime_add_ns(ktime_get(), ULONG_MAX);
3286
		return;
L
Linus Torvalds 已提交
3287
	}
L
Luiz Capitulino 已提交
3288

3289
	/* If no skb or clone count exhausted then get new one */
3290 3291 3292 3293 3294 3295 3296
	if (!pkt_dev->skb || (pkt_dev->last_ok &&
			      ++pkt_dev->clone_count >= pkt_dev->clone_skb)) {
		/* build a new pkt */
		kfree_skb(pkt_dev->skb);

		pkt_dev->skb = fill_packet(odev, pkt_dev);
		if (pkt_dev->skb == NULL) {
J
Joe Perches 已提交
3297
			pr_err("ERROR: couldn't allocate skb in fill_packet\n");
3298 3299 3300
			schedule();
			pkt_dev->clone_count--;	/* back out increment, OOM */
			return;
L
Linus Torvalds 已提交
3301
		}
3302
		pkt_dev->last_pkt_size = pkt_dev->skb->len;
3303 3304
		pkt_dev->allocated_skbs++;
		pkt_dev->clone_count = 0;	/* reset counter */
L
Linus Torvalds 已提交
3305
	}
3306

3307 3308 3309
	if (pkt_dev->delay && pkt_dev->last_ok)
		spin(pkt_dev, pkt_dev->next_tx);

3310 3311 3312 3313
	queue_map = skb_get_queue_mapping(pkt_dev->skb);
	txq = netdev_get_tx_queue(odev, queue_map);

	__netif_tx_lock_bh(txq);
3314

3315
	if (unlikely(netif_xmit_frozen_or_stopped(txq))) {
3316
		ret = NETDEV_TX_BUSY;
3317 3318 3319 3320 3321
		pkt_dev->last_ok = 0;
		goto unlock;
	}
	atomic_inc(&(pkt_dev->skb->users));
	ret = (*xmit)(pkt_dev->skb, odev);
3322 3323 3324 3325 3326 3327 3328

	switch (ret) {
	case NETDEV_TX_OK:
		txq_trans_update(txq);
		pkt_dev->last_ok = 1;
		pkt_dev->sofar++;
		pkt_dev->seq_num++;
3329
		pkt_dev->tx_bytes += pkt_dev->last_pkt_size;
3330
		break;
3331 3332 3333 3334 3335 3336
	case NET_XMIT_DROP:
	case NET_XMIT_CN:
	case NET_XMIT_POLICED:
		/* skb has been consumed */
		pkt_dev->errors++;
		break;
3337
	default: /* Drivers are not supposed to return other values! */
3338 3339
		net_info_ratelimited("%s xmit error: %d\n",
				     pkt_dev->odevname, ret);
3340 3341 3342 3343 3344 3345 3346
		pkt_dev->errors++;
		/* fallthru */
	case NETDEV_TX_LOCKED:
	case NETDEV_TX_BUSY:
		/* Retry it next time */
		atomic_dec(&(pkt_dev->skb->users));
		pkt_dev->last_ok = 0;
L
Luiz Capitulino 已提交
3347
	}
3348
unlock:
3349
	__netif_tx_unlock_bh(txq);
L
Luiz Capitulino 已提交
3350

L
Linus Torvalds 已提交
3351 3352
	/* If pkt_dev->count is zero, then run forever */
	if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
3353
		pktgen_wait_for_skb(pkt_dev);
L
Luiz Capitulino 已提交
3354

L
Linus Torvalds 已提交
3355 3356
		/* Done with this */
		pktgen_stop_device(pkt_dev);
L
Luiz Capitulino 已提交
3357 3358
	}
}
L
Linus Torvalds 已提交
3359

3360
/*
L
Linus Torvalds 已提交
3361 3362 3363
 * Main loop of the thread goes here
 */

3364
static int pktgen_thread_worker(void *arg)
L
Linus Torvalds 已提交
3365 3366
{
	DEFINE_WAIT(wait);
3367
	struct pktgen_thread *t = arg;
L
Luiz Capitulino 已提交
3368
	struct pktgen_dev *pkt_dev = NULL;
L
Linus Torvalds 已提交
3369 3370
	int cpu = t->cpu;

3371
	BUG_ON(smp_processor_id() != cpu);
L
Linus Torvalds 已提交
3372 3373

	init_waitqueue_head(&t->queue);
3374
	complete(&t->start_done);
L
Linus Torvalds 已提交
3375

J
Joe Perches 已提交
3376
	pr_debug("starting pktgen/%d:  pid=%d\n", cpu, task_pid_nr(current));
L
Linus Torvalds 已提交
3377

3378
	set_current_state(TASK_INTERRUPTIBLE);
L
Luiz Capitulino 已提交
3379

3380 3381
	set_freezable();

3382 3383
	while (!kthread_should_stop()) {
		pkt_dev = next_to_run(t);
L
Linus Torvalds 已提交
3384

3385
		if (unlikely(!pkt_dev && t->control == 0)) {
C
Cong Wang 已提交
3386
			if (t->net->pktgen_exiting)
E
Eric Dumazet 已提交
3387
				break;
3388 3389 3390
			wait_event_interruptible_timeout(t->queue,
							 t->control != 0,
							 HZ/10);
R
Rafael J. Wysocki 已提交
3391
			try_to_freeze();
3392
			continue;
3393
		}
L
Linus Torvalds 已提交
3394

3395
		__set_current_state(TASK_RUNNING);
L
Luiz Capitulino 已提交
3396

3397
		if (likely(pkt_dev)) {
L
Linus Torvalds 已提交
3398 3399
			pktgen_xmit(pkt_dev);

3400 3401 3402 3403 3404 3405
			if (need_resched())
				pktgen_resched(pkt_dev);
			else
				cpu_relax();
		}

L
Luiz Capitulino 已提交
3406
		if (t->control & T_STOP) {
L
Linus Torvalds 已提交
3407 3408 3409 3410
			pktgen_stop(t);
			t->control &= ~(T_STOP);
		}

L
Luiz Capitulino 已提交
3411
		if (t->control & T_RUN) {
L
Linus Torvalds 已提交
3412 3413 3414 3415
			pktgen_run(t);
			t->control &= ~(T_RUN);
		}

L
Luiz Capitulino 已提交
3416
		if (t->control & T_REMDEVALL) {
L
Linus Torvalds 已提交
3417
			pktgen_rem_all_ifs(t);
3418 3419 3420
			t->control &= ~(T_REMDEVALL);
		}

L
Luiz Capitulino 已提交
3421
		if (t->control & T_REMDEV) {
3422
			pktgen_rem_one_if(t);
L
Linus Torvalds 已提交
3423 3424 3425
			t->control &= ~(T_REMDEV);
		}

A
Andrew Morton 已提交
3426 3427
		try_to_freeze();

3428
		set_current_state(TASK_INTERRUPTIBLE);
L
Luiz Capitulino 已提交
3429
	}
L
Linus Torvalds 已提交
3430

J
Joe Perches 已提交
3431
	pr_debug("%s stopping all device\n", t->tsk->comm);
L
Luiz Capitulino 已提交
3432
	pktgen_stop(t);
L
Linus Torvalds 已提交
3433

J
Joe Perches 已提交
3434
	pr_debug("%s removing all device\n", t->tsk->comm);
L
Luiz Capitulino 已提交
3435
	pktgen_rem_all_ifs(t);
L
Linus Torvalds 已提交
3436

J
Joe Perches 已提交
3437
	pr_debug("%s removing thread\n", t->tsk->comm);
L
Luiz Capitulino 已提交
3438
	pktgen_rem_thread(t);
3439

E
Eric Dumazet 已提交
3440 3441 3442 3443 3444 3445 3446
	/* Wait for kthread_stop */
	while (!kthread_should_stop()) {
		set_current_state(TASK_INTERRUPTIBLE);
		schedule();
	}
	__set_current_state(TASK_RUNNING);

3447
	return 0;
L
Linus Torvalds 已提交
3448 3449
}

L
Luiz Capitulino 已提交
3450
static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
E
Eric Dumazet 已提交
3451
					  const char *ifname, bool exact)
L
Linus Torvalds 已提交
3452
{
3453
	struct pktgen_dev *p, *pkt_dev = NULL;
E
Eric Dumazet 已提交
3454
	size_t len = strlen(ifname);
L
Luiz Capitulino 已提交
3455

E
Eric Dumazet 已提交
3456
	if_lock(t);
3457
	list_for_each_entry(p, &t->if_list, list)
E
Eric Dumazet 已提交
3458 3459 3460 3461 3462
		if (strncmp(p->odevname, ifname, len) == 0) {
			if (p->odevname[len]) {
				if (exact || p->odevname[len] != '@')
					continue;
			}
3463
			pkt_dev = p;
L
Luiz Capitulino 已提交
3464 3465 3466 3467
			break;
		}

	if_unlock(t);
J
Joe Perches 已提交
3468
	pr_debug("find_dev(%s) returning %p\n", ifname, pkt_dev);
L
Luiz Capitulino 已提交
3469
	return pkt_dev;
L
Linus Torvalds 已提交
3470 3471
}

3472 3473
/*
 * Adds a dev at front of if_list.
L
Linus Torvalds 已提交
3474 3475
 */

L
Luiz Capitulino 已提交
3476 3477
static int add_dev_to_thread(struct pktgen_thread *t,
			     struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
3478 3479
{
	int rv = 0;
L
Luiz Capitulino 已提交
3480 3481 3482 3483

	if_lock(t);

	if (pkt_dev->pg_thread) {
J
Joe Perches 已提交
3484
		pr_err("ERROR: already assigned to a thread\n");
L
Luiz Capitulino 已提交
3485 3486 3487
		rv = -EBUSY;
		goto out;
	}
3488 3489

	list_add(&pkt_dev->list, &t->if_list);
L
Luiz Capitulino 已提交
3490
	pkt_dev->pg_thread = t;
L
Linus Torvalds 已提交
3491 3492
	pkt_dev->running = 0;

L
Luiz Capitulino 已提交
3493 3494 3495
out:
	if_unlock(t);
	return rv;
L
Linus Torvalds 已提交
3496 3497 3498 3499
}

/* Called under thread lock */

L
Luiz Capitulino 已提交
3500
static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
L
Linus Torvalds 已提交
3501
{
L
Luiz Capitulino 已提交
3502
	struct pktgen_dev *pkt_dev;
3503
	int err;
E
Eric Dumazet 已提交
3504
	int node = cpu_to_node(t->cpu);
L
Luiz Capitulino 已提交
3505

L
Linus Torvalds 已提交
3506 3507
	/* We don't allow a device to be on several threads */

C
Cong Wang 已提交
3508
	pkt_dev = __pktgen_NN_threads(t->net, ifname, FIND);
3509
	if (pkt_dev) {
J
Joe Perches 已提交
3510
		pr_err("ERROR: interface already used\n");
L
Luiz Capitulino 已提交
3511 3512
		return -EBUSY;
	}
3513

E
Eric Dumazet 已提交
3514
	pkt_dev = kzalloc_node(sizeof(struct pktgen_dev), GFP_KERNEL, node);
3515 3516 3517
	if (!pkt_dev)
		return -ENOMEM;

E
Eric Dumazet 已提交
3518
	strcpy(pkt_dev->odevname, ifname);
3519
	pkt_dev->flows = vzalloc_node(MAX_CFLOWS * sizeof(struct flow_state),
E
Eric Dumazet 已提交
3520
				      node);
3521 3522 3523 3524 3525
	if (pkt_dev->flows == NULL) {
		kfree(pkt_dev);
		return -ENOMEM;
	}

3526
	pkt_dev->removal_mark = 0;
3527
	pkt_dev->nfrags = 0;
3528
	pkt_dev->delay = pg_delay_d;
3529 3530
	pkt_dev->count = pg_count_d;
	pkt_dev->sofar = 0;
L
Luiz Capitulino 已提交
3531
	pkt_dev->udp_src_min = 9;	/* sink port */
3532 3533 3534
	pkt_dev->udp_src_max = 9;
	pkt_dev->udp_dst_min = 9;
	pkt_dev->udp_dst_max = 9;
F
Francesco Fondelli 已提交
3535 3536 3537 3538 3539 3540
	pkt_dev->vlan_p = 0;
	pkt_dev->vlan_cfi = 0;
	pkt_dev->vlan_id = 0xffff;
	pkt_dev->svlan_p = 0;
	pkt_dev->svlan_cfi = 0;
	pkt_dev->svlan_id = 0xffff;
R
Robert Olsson 已提交
3541
	pkt_dev->node = -1;
F
Francesco Fondelli 已提交
3542

C
Cong Wang 已提交
3543
	err = pktgen_setup_dev(t->net, pkt_dev, ifname);
3544 3545
	if (err)
		goto out1;
3546 3547
	if (pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)
		pkt_dev->clone_skb = pg_clone_skb_d;
3548

C
Cong Wang 已提交
3549
	pkt_dev->entry = proc_create_data(ifname, 0600, t->net->proc_dir,
3550
					  &pktgen_if_fops, pkt_dev);
3551
	if (!pkt_dev->entry) {
J
Joe Perches 已提交
3552
		pr_err("cannot create %s/%s procfs entry\n",
3553
		       PG_PROC_DIR, ifname);
3554 3555
		err = -EINVAL;
		goto out2;
3556
	}
J
Jamal Hadi Salim 已提交
3557 3558 3559 3560
#ifdef CONFIG_XFRM
	pkt_dev->ipsmode = XFRM_MODE_TRANSPORT;
	pkt_dev->ipsproto = IPPROTO_ESP;
#endif
3561 3562

	return add_dev_to_thread(t, pkt_dev);
3563 3564 3565
out2:
	dev_put(pkt_dev->odev);
out1:
J
Jamal Hadi Salim 已提交
3566 3567 3568
#ifdef CONFIG_XFRM
	free_SAs(pkt_dev);
#endif
F
Figo.zhang 已提交
3569
	vfree(pkt_dev->flows);
3570 3571
	kfree(pkt_dev);
	return err;
L
Linus Torvalds 已提交
3572 3573
}

C
Cong Wang 已提交
3574
static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn)
L
Linus Torvalds 已提交
3575
{
3576
	struct pktgen_thread *t;
3577
	struct proc_dir_entry *pe;
3578
	struct task_struct *p;
L
Luiz Capitulino 已提交
3579

E
Eric Dumazet 已提交
3580 3581
	t = kzalloc_node(sizeof(struct pktgen_thread), GFP_KERNEL,
			 cpu_to_node(cpu));
L
Luiz Capitulino 已提交
3582
	if (!t) {
J
Joe Perches 已提交
3583
		pr_err("ERROR: out of memory, can't create new thread\n");
L
Luiz Capitulino 已提交
3584 3585 3586 3587
		return -ENOMEM;
	}

	spin_lock_init(&t->if_lock);
L
Linus Torvalds 已提交
3588
	t->cpu = cpu;
L
Luiz Capitulino 已提交
3589

3590 3591
	INIT_LIST_HEAD(&t->if_list);

C
Cong Wang 已提交
3592
	list_add_tail(&t->th_list, &pn->pktgen_threads);
3593
	init_completion(&t->start_done);
3594

3595 3596 3597 3598
	p = kthread_create_on_node(pktgen_thread_worker,
				   t,
				   cpu_to_node(cpu),
				   "kpktgend_%d", cpu);
3599
	if (IS_ERR(p)) {
J
Joe Perches 已提交
3600
		pr_err("kernel_thread() failed for cpu %d\n", t->cpu);
3601 3602 3603 3604 3605 3606 3607
		list_del(&t->th_list);
		kfree(t);
		return PTR_ERR(p);
	}
	kthread_bind(p, cpu);
	t->tsk = p;

C
Cong Wang 已提交
3608
	pe = proc_create_data(t->tsk->comm, 0600, pn->proc_dir,
3609
			      &pktgen_thread_fops, t);
L
Luiz Capitulino 已提交
3610
	if (!pe) {
J
Joe Perches 已提交
3611
		pr_err("cannot create %s/%s procfs entry\n",
3612 3613 3614
		       PG_PROC_DIR, t->tsk->comm);
		kthread_stop(p);
		list_del(&t->th_list);
L
Luiz Capitulino 已提交
3615 3616 3617
		kfree(t);
		return -EINVAL;
	}
3618

C
Cong Wang 已提交
3619
	t->net = pn;
3620
	wake_up_process(p);
3621
	wait_for_completion(&t->start_done);
L
Linus Torvalds 已提交
3622 3623 3624 3625

	return 0;
}

3626 3627
/*
 * Removes a device from the thread if_list.
L
Linus Torvalds 已提交
3628
 */
L
Luiz Capitulino 已提交
3629 3630
static void _rem_dev_from_if_list(struct pktgen_thread *t,
				  struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
3631
{
3632 3633
	struct list_head *q, *n;
	struct pktgen_dev *p;
L
Linus Torvalds 已提交
3634

3635 3636 3637 3638
	list_for_each_safe(q, n, &t->if_list) {
		p = list_entry(q, struct pktgen_dev, list);
		if (p == pkt_dev)
			list_del(&p->list);
L
Linus Torvalds 已提交
3639 3640 3641
	}
}

L
Luiz Capitulino 已提交
3642 3643
static int pktgen_remove_device(struct pktgen_thread *t,
				struct pktgen_dev *pkt_dev)
L
Linus Torvalds 已提交
3644
{
J
Joe Perches 已提交
3645
	pr_debug("remove_device pkt_dev=%p\n", pkt_dev);
L
Linus Torvalds 已提交
3646

L
Luiz Capitulino 已提交
3647
	if (pkt_dev->running) {
J
Joe Perches 已提交
3648
		pr_warning("WARNING: trying to remove a running interface, stopping it now\n");
L
Luiz Capitulino 已提交
3649 3650 3651 3652
		pktgen_stop_device(pkt_dev);
	}

	/* Dis-associate from the interface */
L
Linus Torvalds 已提交
3653 3654 3655

	if (pkt_dev->odev) {
		dev_put(pkt_dev->odev);
L
Luiz Capitulino 已提交
3656 3657 3658
		pkt_dev->odev = NULL;
	}

L
Linus Torvalds 已提交
3659 3660 3661 3662
	/* And update the thread if_list */

	_rem_dev_from_if_list(t, pkt_dev);

3663
	if (pkt_dev->entry)
3664
		proc_remove(pkt_dev->entry);
L
Linus Torvalds 已提交
3665

J
Jamal Hadi Salim 已提交
3666 3667 3668
#ifdef CONFIG_XFRM
	free_SAs(pkt_dev);
#endif
F
Figo.zhang 已提交
3669
	vfree(pkt_dev->flows);
E
Eric Dumazet 已提交
3670 3671
	if (pkt_dev->page)
		put_page(pkt_dev->page);
L
Linus Torvalds 已提交
3672
	kfree(pkt_dev);
L
Luiz Capitulino 已提交
3673
	return 0;
L
Linus Torvalds 已提交
3674 3675
}

C
Cong Wang 已提交
3676
static int __net_init pg_net_init(struct net *net)
L
Linus Torvalds 已提交
3677
{
C
Cong Wang 已提交
3678
	struct pktgen_net *pn = net_generic(net, pg_net_id);
3679
	struct proc_dir_entry *pe;
C
Cong Wang 已提交
3680 3681 3682 3683 3684 3685 3686 3687
	int cpu, ret = 0;

	pn->net = net;
	INIT_LIST_HEAD(&pn->pktgen_threads);
	pn->pktgen_exiting = false;
	pn->proc_dir = proc_mkdir(PG_PROC_DIR, pn->net->proc_net);
	if (!pn->proc_dir) {
		pr_warn("cannot create /proc/net/%s\n", PG_PROC_DIR);
3688
		return -ENODEV;
C
Cong Wang 已提交
3689 3690
	}
	pe = proc_create(PGCTRL, 0600, pn->proc_dir, &pktgen_fops);
L
Luiz Capitulino 已提交
3691
	if (pe == NULL) {
C
Cong Wang 已提交
3692
		pr_err("cannot create %s procfs entry\n", PGCTRL);
W
WANG Cong 已提交
3693
		ret = -EINVAL;
C
Cong Wang 已提交
3694
		goto remove;
L
Luiz Capitulino 已提交
3695
	}
L
Linus Torvalds 已提交
3696

J
John Hawkes 已提交
3697
	for_each_online_cpu(cpu) {
3698
		int err;
L
Linus Torvalds 已提交
3699

C
Cong Wang 已提交
3700
		err = pktgen_create_thread(cpu, pn);
3701
		if (err)
C
Cong Wang 已提交
3702
			pr_warn("Cannot create thread for cpu %d (%d)\n",
J
Joe Perches 已提交
3703
				   cpu, err);
L
Luiz Capitulino 已提交
3704
	}
3705

C
Cong Wang 已提交
3706 3707
	if (list_empty(&pn->pktgen_threads)) {
		pr_err("Initialization failed for all threads\n");
W
WANG Cong 已提交
3708
		ret = -ENODEV;
C
Cong Wang 已提交
3709
		goto remove_entry;
3710 3711
	}

L
Luiz Capitulino 已提交
3712
	return 0;
W
WANG Cong 已提交
3713

C
Cong Wang 已提交
3714 3715 3716
remove_entry:
	remove_proc_entry(PGCTRL, pn->proc_dir);
remove:
3717
	remove_proc_entry(PG_PROC_DIR, pn->net->proc_net);
W
WANG Cong 已提交
3718
	return ret;
L
Linus Torvalds 已提交
3719 3720
}

C
Cong Wang 已提交
3721
static void __net_exit pg_net_exit(struct net *net)
L
Linus Torvalds 已提交
3722
{
C
Cong Wang 已提交
3723
	struct pktgen_net *pn = net_generic(net, pg_net_id);
3724 3725
	struct pktgen_thread *t;
	struct list_head *q, *n;
3726
	LIST_HEAD(list);
L
Linus Torvalds 已提交
3727

L
Luiz Capitulino 已提交
3728
	/* Stop all interfaces & threads */
C
Cong Wang 已提交
3729
	pn->pktgen_exiting = true;
L
Linus Torvalds 已提交
3730

3731
	mutex_lock(&pktgen_thread_lock);
C
Cong Wang 已提交
3732
	list_splice_init(&pn->pktgen_threads, &list);
3733 3734 3735
	mutex_unlock(&pktgen_thread_lock);

	list_for_each_safe(q, n, &list) {
3736
		t = list_entry(q, struct pktgen_thread, th_list);
3737
		list_del(&t->th_list);
3738 3739
		kthread_stop(t->tsk);
		kfree(t);
L
Luiz Capitulino 已提交
3740
	}
L
Linus Torvalds 已提交
3741

C
Cong Wang 已提交
3742
	remove_proc_entry(PGCTRL, pn->proc_dir);
3743
	remove_proc_entry(PG_PROC_DIR, pn->net->proc_net);
C
Cong Wang 已提交
3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755
}

static struct pernet_operations pg_net_ops = {
	.init = pg_net_init,
	.exit = pg_net_exit,
	.id   = &pg_net_id,
	.size = sizeof(struct pktgen_net),
};

static int __init pg_init(void)
{
	int ret = 0;
L
Linus Torvalds 已提交
3756

C
Cong Wang 已提交
3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771
	pr_info("%s", version);
	ret = register_pernet_subsys(&pg_net_ops);
	if (ret)
		return ret;
	ret = register_netdevice_notifier(&pktgen_notifier_block);
	if (ret)
		unregister_pernet_subsys(&pg_net_ops);

	return ret;
}

static void __exit pg_cleanup(void)
{
	unregister_netdevice_notifier(&pktgen_notifier_block);
	unregister_pernet_subsys(&pg_net_ops);
L
Linus Torvalds 已提交
3772 3773 3774 3775 3776
}

module_init(pg_init);
module_exit(pg_cleanup);

S
Stephen Hemminger 已提交
3777
MODULE_AUTHOR("Robert Olsson <robert.olsson@its.uu.se>");
L
Linus Torvalds 已提交
3778 3779
MODULE_DESCRIPTION("Packet Generator tool");
MODULE_LICENSE("GPL");
S
Stephen Hemminger 已提交
3780
MODULE_VERSION(VERSION);
L
Linus Torvalds 已提交
3781
module_param(pg_count_d, int, 0);
S
Stephen Hemminger 已提交
3782
MODULE_PARM_DESC(pg_count_d, "Default number of packets to inject");
L
Linus Torvalds 已提交
3783
module_param(pg_delay_d, int, 0);
S
Stephen Hemminger 已提交
3784
MODULE_PARM_DESC(pg_delay_d, "Default delay between packets (nanoseconds)");
L
Linus Torvalds 已提交
3785
module_param(pg_clone_skb_d, int, 0);
S
Stephen Hemminger 已提交
3786
MODULE_PARM_DESC(pg_clone_skb_d, "Default number of copies of the same packet");
L
Linus Torvalds 已提交
3787
module_param(debug, int, 0);
S
Stephen Hemminger 已提交
3788
MODULE_PARM_DESC(debug, "Enable debugging of pktgen module");