All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] pktgen: create packet use IPv6 source address between src6_min and src6_max.
@ 2020-01-13 11:21 Niu Xilei
  2020-01-13 12:51 ` Jakub Kicinski
  0 siblings, 1 reply; 2+ messages in thread
From: Niu Xilei @ 2020-01-13 11:21 UTC (permalink / raw)
  To: davem
  Cc: tglx, fw, peterz, steffen.klassert, bigeasy, jonathan.lemon,
	pabeni, anshuman.khandual, netdev, linux-kernel, Niu Xilei

Pktgen can use only one IPv6 source address from output device, or src6 command
setting. In pressure test we need create lots of session more than 65536.If
IPSRC_RND flag is set, generate random source address between src6_min and src6_max.

Signed-off-by: Niu Xilei <niu_xilei@163.com>

Changes since v1:
 - only create IPv6 source address over least significant 64 bit range
---
 net/core/pktgen.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 294bfcf0ce0e..33435ae0ba68 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1355,6 +1355,49 @@ static ssize_t pktgen_if_write(struct file *file,
 		sprintf(pg_result, "OK: dst6_max=%s", buf);
 		return count;
 	}
+	if (!strcmp(name, "src6_min")) {
+		len = strn_len(&user_buffer[i], sizeof(buf) - 1);
+		if (len < 0)
+			return len;
+
+		pkt_dev->flags |= F_IPV6;
+
+		if (copy_from_user(buf, &user_buffer[i], len))
+			return -EFAULT;
+		buf[len] = 0;
+
+		in6_pton(buf, -1, pkt_dev->min_in6_saddr.s6_addr, -1, NULL);
+		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_saddr);
+
+		pkt_dev->cur_in6_saddr = pkt_dev->min_in6_saddr;
+		if (debug)
+			pr_debug("src6_min set to: %s\n", buf);
+
+		i += len;
+		sprintf(pg_result, "OK: src6_min=%s", buf);
+		return count;
+	}
+	if (!strcmp(name, "src6_max")) {
+		len = strn_len(&user_buffer[i], sizeof(buf) - 1);
+		if (len < 0)
+			return len;
+
+		pkt_dev->flags |= F_IPV6;
+
+		if (copy_from_user(buf, &user_buffer[i], len))
+			return -EFAULT;
+		buf[len] = 0;
+
+		in6_pton(buf, -1, pkt_dev->max_in6_saddr.s6_addr, -1, NULL);
+		snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_saddr);
+
+		if (debug)
+			pr_debug("dst6_max set to: %s\n", buf);
+
+		i += len;
+		sprintf(pg_result, "OK: dst6_max=%s", buf);
+		return count;
+	}
 	if (!strcmp(name, "src6")) {
 		len = strn_len(&user_buffer[i], sizeof(buf) - 1);
 		if (len < 0)
@@ -2286,6 +2329,51 @@ static void set_cur_queue_map(struct pktgen_dev *pkt_dev)
 	pkt_dev->cur_queue_map  = pkt_dev->cur_queue_map % pkt_dev->odev->real_num_tx_queues;
 }
 
+/* generate ipv6 source addr */
+static inline void set_src_in6_addr(struct pktgen_dev *pkt_dev)
+{
+	__be64 min6_h, min6_l, max6_h, max6_l, addr_l, *t;
+	u64 min6, max6, rand, i;
+	struct in6_addr addr6;
+
+	memcpy(&min6_h, pkt_dev->min_in6_saddr.s6_addr, 8);
+	memcpy(&min6_l, pkt_dev->min_in6_saddr.s6_addr + 8, 8);
+	memcpy(&max6_h, pkt_dev->max_in6_saddr.s6_addr, 8);
+	memcpy(&max6_l, pkt_dev->max_in6_saddr.s6_addr + 8, 8);
+
+	/* only generate source address in least significant 64 bits range
+	 * most significant 64 bits must be equal
+	 */
+	if (max6_h != min6_h)
+		return;
+
+	addr6 = pkt_dev->min_in6_saddr;
+	t = (__be64 *)addr6.s6_addr + 1;
+	min6 = be64_to_cpu(min6_l);
+	max6 = be64_to_cpu(max6_l);
+
+	if (min6 < max6) {
+		if (pkt_dev->flags & F_IPSRC_RND) {
+			do {
+				prandom_bytes(&rand, sizeof(rand));
+				rand = rand % (max6 - min6) + min6;
+				addr_l = cpu_to_be64(rand);
+				memcpy(t, &addr_l, 8);
+			} while (ipv6_addr_loopback(&addr6) ||
+				 ipv6_addr_v4mapped(&addr6) ||
+				 ipv6_addr_is_multicast(&addr6));
+		} else {
+			addr6 = pkt_dev->cur_in6_saddr;
+			i = be64_to_cpu(*t);
+			if (++i > max6)
+				i = min6;
+			addr_l = cpu_to_be64(i);
+			memcpy(t, &addr_l, 8);
+		}
+	}
+	pkt_dev->cur_in6_saddr = addr6;
+}
+
 /* Increment/randomize headers according to flags and current values
  * for IP src/dest, UDP src/dst port, MAC-Addr src/dst
  */
@@ -2454,6 +2542,8 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
 		}
 	} else {		/* IPV6 * */
 
+		set_src_in6_addr(pkt_dev);
+
 		if (!ipv6_addr_any(&pkt_dev->min_in6_daddr)) {
 			int i;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] pktgen: create packet use IPv6 source address between src6_min and src6_max.
  2020-01-13 11:21 [PATCH v2] pktgen: create packet use IPv6 source address between src6_min and src6_max Niu Xilei
@ 2020-01-13 12:51 ` Jakub Kicinski
  0 siblings, 0 replies; 2+ messages in thread
From: Jakub Kicinski @ 2020-01-13 12:51 UTC (permalink / raw)
  To: Niu Xilei
  Cc: davem, tglx, fw, peterz, steffen.klassert, bigeasy,
	jonathan.lemon, pabeni, anshuman.khandual, netdev, linux-kernel

The subject line could use some rewording, I think.

On Mon, 13 Jan 2020 19:21:02 +0800, Niu Xilei wrote:
> Pktgen can use only one IPv6 source address from output device, or src6 command
> setting. In pressure test we need create lots of session more than 65536.If
> IPSRC_RND flag is set, generate random source address between src6_min and src6_max.
> 
> Signed-off-by: Niu Xilei <niu_xilei@163.com>
> 
> Changes since v1:
>  - only create IPv6 source address over least significant 64 bit range

> +/* generate ipv6 source addr */
> +static inline void set_src_in6_addr(struct pktgen_dev *pkt_dev)

Please just use "static" instead of "static inline". The compiler will
be clever enough to decide the inlining.

> +{
> +	__be64 min6_h, min6_l, max6_h, max6_l, addr_l, *t;
> +	u64 min6, max6, rand, i;
> +	struct in6_addr addr6;
> +
> +	memcpy(&min6_h, pkt_dev->min_in6_saddr.s6_addr, 8);
> +	memcpy(&min6_l, pkt_dev->min_in6_saddr.s6_addr + 8, 8);
> +	memcpy(&max6_h, pkt_dev->max_in6_saddr.s6_addr, 8);
> +	memcpy(&max6_l, pkt_dev->max_in6_saddr.s6_addr + 8, 8);
> +
> +	/* only generate source address in least significant 64 bits range
> +	 * most significant 64 bits must be equal
> +	 */
> +	if (max6_h != min6_h)
> +		return;
> +
> +	addr6 = pkt_dev->min_in6_saddr;
> +	t = (__be64 *)addr6.s6_addr + 1;
> +	min6 = be64_to_cpu(min6_l);
> +	max6 = be64_to_cpu(max6_l);
> +
> +	if (min6 < max6) {

Since this code is executed on every packet, would it be possible to
pre-compute the decision if the IPv6 address is to be generated or not?
We have 4 memcpy()s and 2 byte swaps, and the conditions never change,
so it could be computed at setup time, right?

> +		if (pkt_dev->flags & F_IPSRC_RND) {
> +			do {
> +				prandom_bytes(&rand, sizeof(rand));
> +				rand = rand % (max6 - min6) + min6;
> +				addr_l = cpu_to_be64(rand);
> +				memcpy(t, &addr_l, 8);
> +			} while (ipv6_addr_loopback(&addr6) ||
> +				 ipv6_addr_v4mapped(&addr6) ||
> +				 ipv6_addr_is_multicast(&addr6));
> +		} else {
> +			addr6 = pkt_dev->cur_in6_saddr;
> +			i = be64_to_cpu(*t);
> +			if (++i > max6)
> +				i = min6;
> +			addr_l = cpu_to_be64(i);
> +			memcpy(t, &addr_l, 8);
> +		}
> +	}
> +	pkt_dev->cur_in6_saddr = addr6;
> +}

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-01-13 12:58 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-13 11:21 [PATCH v2] pktgen: create packet use IPv6 source address between src6_min and src6_max Niu Xilei
2020-01-13 12:51 ` Jakub Kicinski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.