Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46410c2e authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'pktgen-Behavior-flags-fixes'



Dmitry Safonov says:

====================
pktgen: Behavior flags fixes

v2:
  o fixed a nitpick from David Miller

There are a bunch of fixes/cleanups/Documentations.
Diffstat says for itself, regardless added docs and missed flag
parameters.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 969ade40 52e12d5d
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -12,8 +12,8 @@ suitable sample script and configure that.
On a dual CPU:

ps aux | grep pkt
root       129  0.3  0.0     0    0 ?        SW    2003 523:20 [pktgen/0]
root       130  0.3  0.0     0    0 ?        SW    2003 509:50 [pktgen/1]
root       129  0.3  0.0     0    0 ?        SW    2003 523:20 [kpktgend_0]
root       130  0.3  0.0     0    0 ?        SW    2003 509:50 [kpktgend_1]


For monitoring and control pktgen creates:
@@ -113,9 +113,16 @@ Configuring devices
===================
This is done via the /proc interface, and most easily done via pgset
as defined in the sample scripts.
You need to specify PGDEV environment variable to use functions from sample
scripts, i.e.:
export PGDEV=/proc/net/pktgen/eth4@0
source samples/pktgen/functions.sh

Examples:

 pg_ctrl start           starts injection.
 pg_ctrl stop            aborts injection. Also, ^C aborts generator.

 pgset "clone_skb 1"     sets the number of copies of the same packet
 pgset "clone_skb 0"     use single SKB for all transmits
 pgset "burst 8"         uses xmit_more API to queue 8 copies of the same
@@ -165,8 +172,12 @@ Examples:
                              IPSEC # IPsec encapsulation (needs CONFIG_XFRM)
                              NODE_ALLOC # node specific memory allocation
                              NO_TIMESTAMP # disable timestamping
 pgset 'flag ![name]'    Clear a flag to determine behaviour.
                         Note that you might need to use single quote in
                         interactive mode, so that your shell wouldn't expand
                         the specified flag as a history command.

 pgset spi SPI_VALUE     Set specific SA used to transform packet.
 pgset "spi [SPI_VALUE]" Set specific SA used to transform packet.

 pgset "udp_src_min 9"   set UDP source port min, If < udp_src_max, then
                         cycle through the port range.
@@ -207,8 +218,6 @@ Examples:
 pgset "tos XX"           set former IPv4 TOS field (e.g. "tos 28" for AF11 no ECN, default 00)
 pgset "traffic_class XX" set former IPv6 TRAFFIC CLASS (e.g. "traffic_class B8" for EF no ECN, default 00)

 pgset stop    	          aborts injection. Also, ^C aborts generator.

 pgset "rate 300M"        set rate to 300 Mb/s
 pgset "ratep 1000000"    set rate to 1Mpps

+89 −177
Original line number Diff line number Diff line
@@ -184,25 +184,44 @@

#define func_enter() pr_debug("entering %s\n", __func__);

#define PKT_FLAGS							\
	pf(IPV6)		/* Interface in IPV6 Mode */		\
	pf(IPSRC_RND)		/* IP-Src Random  */			\
	pf(IPDST_RND)		/* IP-Dst Random  */			\
	pf(TXSIZE_RND)		/* Transmit size is random */		\
	pf(UDPSRC_RND)		/* UDP-Src Random */			\
	pf(UDPDST_RND)		/* UDP-Dst Random */			\
	pf(UDPCSUM)		/* Include UDP checksum */		\
	pf(NO_TIMESTAMP)	/* Don't timestamp packets (default TS) */ \
	pf(MPLS_RND)		/* Random MPLS labels */		\
	pf(QUEUE_MAP_RND)	/* queue map Random */			\
	pf(QUEUE_MAP_CPU)	/* queue map mirrors smp_processor_id() */ \
	pf(FLOW_SEQ)		/* Sequential flows */			\
	pf(IPSEC)		/* ipsec on for flows */		\
	pf(MACSRC_RND)		/* MAC-Src Random */			\
	pf(MACDST_RND)		/* MAC-Dst Random */			\
	pf(VID_RND)		/* Random VLAN ID */			\
	pf(SVID_RND)		/* Random SVLAN ID */			\
	pf(NODE)		/* Node memory alloc*/			\

#define pf(flag)		flag##_SHIFT,
enum pkt_flags {
	PKT_FLAGS
};
#undef pf

/* Device flag bits */
#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 */
#define F_MPLS_RND    (1<<8)	/* Random MPLS labels */
#define F_VID_RND     (1<<9)	/* Random VLAN ID */
#define F_SVID_RND    (1<<10)	/* Random SVLAN ID */
#define F_FLOW_SEQ    (1<<11)	/* Sequential flows */
#define F_IPSEC_ON    (1<<12)	/* ipsec on for flows */
#define F_QUEUE_MAP_RND (1<<13)	/* queue map Random */
#define F_QUEUE_MAP_CPU (1<<14)	/* queue map mirrors smp_processor_id() */
#define F_NODE          (1<<15)	/* Node memory alloc*/
#define F_UDPCSUM       (1<<16)	/* Include UDP checksum */
#define F_NO_TIMESTAMP  (1<<17)	/* Don't timestamp packets (default TS) */
#define pf(flag)		static const __u32 F_##flag = (1<<flag##_SHIFT);
PKT_FLAGS
#undef pf

#define pf(flag)		__stringify(flag),
static char *pkt_flag_names[] = {
	PKT_FLAGS
};
#undef pf

#define NR_PKT_FLAGS		ARRAY_SIZE(pkt_flag_names)

/* Thread control flag bits */
#define T_STOP        (1<<0)	/* Stop run */
@@ -534,6 +553,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
{
	const struct pktgen_dev *pkt_dev = seq->private;
	ktime_t stopped;
	unsigned int i;
	u64 idle;

	seq_printf(seq,
@@ -595,7 +615,6 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
		   pkt_dev->src_mac_count, pkt_dev->dst_mac_count);

	if (pkt_dev->nr_labels) {
		unsigned int i;
		seq_puts(seq, "     mpls: ");
		for (i = 0; i < pkt_dev->nr_labels; i++)
			seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]),
@@ -631,68 +650,21 @@ static int pktgen_if_show(struct seq_file *seq, void *v)

	seq_puts(seq, "     Flags: ");

	if (pkt_dev->flags & F_IPV6)
		seq_puts(seq, "IPV6  ");

	if (pkt_dev->flags & F_IPSRC_RND)
		seq_puts(seq, "IPSRC_RND  ");

	if (pkt_dev->flags & F_IPDST_RND)
		seq_puts(seq, "IPDST_RND  ");

	if (pkt_dev->flags & F_TXSIZE_RND)
		seq_puts(seq, "TXSIZE_RND  ");

	if (pkt_dev->flags & F_UDPSRC_RND)
		seq_puts(seq, "UDPSRC_RND  ");

	if (pkt_dev->flags & F_UDPDST_RND)
		seq_puts(seq, "UDPDST_RND  ");

	if (pkt_dev->flags & F_UDPCSUM)
		seq_puts(seq, "UDPCSUM  ");

	if (pkt_dev->flags & F_NO_TIMESTAMP)
		seq_puts(seq, "NO_TIMESTAMP  ");

	if (pkt_dev->flags & F_MPLS_RND)
		seq_puts(seq,  "MPLS_RND  ");

	if (pkt_dev->flags & F_QUEUE_MAP_RND)
		seq_puts(seq,  "QUEUE_MAP_RND  ");

	if (pkt_dev->flags & F_QUEUE_MAP_CPU)
		seq_puts(seq,  "QUEUE_MAP_CPU  ");
	for (i = 0; i < NR_PKT_FLAGS; i++) {
		if (i == F_FLOW_SEQ)
			if (!pkt_dev->cflows)
				continue;

	if (pkt_dev->cflows) {
		if (pkt_dev->flags & F_FLOW_SEQ)
			seq_puts(seq,  "FLOW_SEQ  "); /*in sequence flows*/
		else
		if (pkt_dev->flags & (1 << i))
			seq_printf(seq, "%s  ", pkt_flag_names[i]);
		else if (i == F_FLOW_SEQ)
			seq_puts(seq, "FLOW_RND  ");
	}

#ifdef CONFIG_XFRM
	if (pkt_dev->flags & F_IPSEC_ON) {
		seq_puts(seq,  "IPSEC  ");
		if (pkt_dev->spi)
		if (i == F_IPSEC && pkt_dev->spi)
			seq_printf(seq, "spi:%u", pkt_dev->spi);
	}
#endif

	if (pkt_dev->flags & F_MACSRC_RND)
		seq_puts(seq, "MACSRC_RND  ");

	if (pkt_dev->flags & F_MACDST_RND)
		seq_puts(seq, "MACDST_RND  ");

	if (pkt_dev->flags & F_VID_RND)
		seq_puts(seq, "VID_RND  ");

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

	if (pkt_dev->flags & F_NODE)
		seq_puts(seq, "NODE_ALLOC  ");
	}

	seq_puts(seq, "\n");

@@ -858,6 +830,35 @@ static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
	return i;
}

static __u32 pktgen_read_flag(const char *f, bool *disable)
{
	__u32 i;

	if (f[0] == '!') {
		*disable = true;
		f++;
	}

	for (i = 0; i < NR_PKT_FLAGS; i++) {
		if (!IS_ENABLED(CONFIG_XFRM) && i == IPSEC_SHIFT)
			continue;

		/* allow only disabling ipv6 flag */
		if (!*disable && i == IPV6_SHIFT)
			continue;

		if (strcmp(f, pkt_flag_names[i]) == 0)
			return 1 << i;
	}

	if (strcmp(f, "FLOW_RND") == 0) {
		*disable = !*disable;
		return F_FLOW_SEQ;
	}

	return 0;
}

static ssize_t pktgen_if_write(struct file *file,
			       const char __user * user_buffer, size_t count,
			       loff_t * offset)
@@ -1215,7 +1216,10 @@ static ssize_t pktgen_if_write(struct file *file,
		return count;
	}
	if (!strcmp(name, "flag")) {
		__u32 flag;
		char f[32];
		bool disable = false;

		memset(f, 0, 32);
		len = strn_len(&user_buffer[i], sizeof(f) - 1);
		if (len < 0)
@@ -1224,107 +1228,15 @@ static ssize_t pktgen_if_write(struct file *file,
		if (copy_from_user(f, &user_buffer[i], len))
			return -EFAULT;
		i += len;
		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;

		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;
		flag = pktgen_read_flag(f, &disable);

		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;

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

		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;

		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;
#ifdef CONFIG_XFRM
		else if (strcmp(f, "IPSEC") == 0)
			pkt_dev->flags |= F_IPSEC_ON;
#endif

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

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

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

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

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

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

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

		else {
		if (flag) {
			if (disable)
				pkt_dev->flags &= ~flag;
			else
				pkt_dev->flags |= flag;
		} else {
			sprintf(pg_result,
				"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
				f,
@@ -2541,7 +2453,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
				pkt_dev->flows[flow].cur_daddr =
				    pkt_dev->cur_daddr;
#ifdef CONFIG_XFRM
				if (pkt_dev->flags & F_IPSEC_ON)
				if (pkt_dev->flags & F_IPSEC)
					get_ipsec_sa(pkt_dev, flow);
#endif
				pkt_dev->nflows++;
@@ -2646,7 +2558,7 @@ static void free_SAs(struct pktgen_dev *pkt_dev)
static int process_ipsec(struct pktgen_dev *pkt_dev,
			      struct sk_buff *skb, __be16 protocol)
{
	if (pkt_dev->flags & F_IPSEC_ON) {
	if (pkt_dev->flags & F_IPSEC) {
		struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
		int nhead = 0;
		if (x) {