lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 14 Jan 2020 11:12:29 +0800
From:   Niu Xilei <niu_xilei@....com>
To:     davem@...emloft.net
Cc:     tglx@...utronix.de, fw@...len.de, peterz@...radead.org,
        steffen.klassert@...unet.com, bigeasy@...utronix.de,
        jonathan.lemon@...il.com, pabeni@...hat.com,
        anshuman.khandual@....com, netdev@...r.kernel.org,
        linux-kernel@...r.kernel.org, Niu Xilei <niu_xilei@....com>
Subject: [v4] pktgen: Allow configuration of IPv6 source address range

Pktgen can use only one IPv6 source address from output device or src6
command setting. In pressure test we need create lots of sessions more
than 65535. So add src6_min and src6_max command to set the range.

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

Changes since v3:
 - function set_src_in6_addr use static instead of static inline
 - precompute min_in6_l,min_in6_h,max_in6_h,max_in6_l in setup time
Changes since v2:
 - reword subject line
Changes since v1:
 - only create IPv6 source address over least significant 64 bit range
---
 net/core/pktgen.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 294bfcf0ce0e..890be1b4877e 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -323,6 +323,10 @@ struct pktgen_dev {
 	struct in6_addr max_in6_daddr;
 	struct in6_addr min_in6_saddr;
 	struct in6_addr max_in6_saddr;
+	u64  max_in6_h;
+	u64  max_in6_l;
+	u64  min_in6_h;
+	u64  min_in6_l;
 
 	/* If we're doing ranges, random or incremental, then this
 	 * defines the min/max for those ranges.
@@ -1355,6 +1359,59 @@ 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);
+
+		memcpy(&pkt_dev->min_in6_h, pkt_dev->min_in6_saddr.s6_addr, 8);
+		memcpy(&pkt_dev->min_in6_l, pkt_dev->min_in6_saddr.s6_addr + 8, 8);
+		pkt_dev->min_in6_h = be64_to_cpu(pkt_dev->min_in6_h);
+		pkt_dev->min_in6_l = be64_to_cpu(pkt_dev->min_in6_l);
+
+		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);
+
+		memcpy(&pkt_dev->max_in6_h, pkt_dev->max_in6_saddr.s6_addr, 8);
+		memcpy(&pkt_dev->max_in6_l, pkt_dev->max_in6_saddr.s6_addr + 8, 8);
+		pkt_dev->max_in6_h = be64_to_cpu(pkt_dev->max_in6_h);
+		pkt_dev->max_in6_l = be64_to_cpu(pkt_dev->max_in6_l);
+
+		if (debug)
+			pr_debug("src6_max set to: %s\n", buf);
+
+		i += len;
+		sprintf(pg_result, "OK: src6_max=%s", buf);
+		return count;
+	}
 	if (!strcmp(name, "src6")) {
 		len = strn_len(&user_buffer[i], sizeof(buf) - 1);
 		if (len < 0)
@@ -2286,6 +2343,45 @@ 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 void set_src_in6_addr(struct pktgen_dev *pkt_dev)
+{
+	u64 min6, max6, rand, i;
+	struct in6_addr addr6;
+	__be64 addr_l, *t;
+
+	min6 = pkt_dev->min_in6_l;
+	max6 = pkt_dev->max_in6_l;
+
+	/* only generate source address in least significant 64 bits range
+	 * most significant 64 bits must be equal
+	 */
+	if (pkt_dev->max_in6_h != pkt_dev->min_in6_h || min6 >= max6)
+		return;
+
+	addr6 = pkt_dev->min_in6_saddr;
+	t = (__be64 *)addr6.s6_addr + 1;
+
+	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 +2550,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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ