DPDK patches and discussions
 help / color / mirror / Atom feed
From: Robin Jarry <rjarry@redhat.com>
To: dev@dpdk.org, Thomas Monjalon <thomas@monjalon.net>
Subject: [PATCH dpdk v2 06/16] net: add ipv6 address utilities
Date: Tue,  1 Oct 2024 10:17:18 +0200	[thread overview]
Message-ID: <20241001081728.301272-7-rjarry@redhat.com> (raw)
In-Reply-To: <20241001081728.301272-1-rjarry@redhat.com>

Add utility functions that use the previously introduced IPv6 address
structure. Add basic unit tests to ensure everything works as expected.

These functions will be used in the next commits to replace private
and/or duplicated functions.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---

Notes:
    v2:
    
    - added RTE_IPV6_ADDR() helper macro
    - added app/test/test_net_ipv6.c in MAINTAINERS

 MAINTAINERS              |   1 +
 app/test/meson.build     |   1 +
 app/test/test_net_ipv6.c | 129 +++++++++++++++++++++++++++++++++++++++
 lib/net/rte_ip6.h        | 117 +++++++++++++++++++++++++++++++++++
 4 files changed, 248 insertions(+)
 create mode 100644 app/test/test_net_ipv6.c

diff --git a/MAINTAINERS b/MAINTAINERS
index af2620bf0a4d..c1c16a443c33 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1520,6 +1520,7 @@ F: lib/net/
 F: app/test/test_cksum.c
 F: app/test/test_cksum_perf.c
 F: app/test/test_net_ether.c
+F: app/test/test_net_ip6.c
 
 Packet CRC
 M: Jasvinder Singh <jasvinder.singh@intel.com>
diff --git a/app/test/meson.build b/app/test/meson.build
index e29258e6ec05..f5276e28c3b9 100644
--- a/app/test/meson.build
+++ b/app/test/meson.build
@@ -130,6 +130,7 @@ source_file_deps = {
     'test_metrics.c': ['metrics'],
     'test_mp_secondary.c': ['hash'],
     'test_net_ether.c': ['net'],
+    'test_net_ipv6.c': ['net'],
     'test_pcapng.c': ['ethdev', 'net', 'pcapng', 'bus_vdev'],
     'test_pdcp.c': ['eventdev', 'pdcp', 'net', 'timer', 'security'],
     'test_pdump.c': ['pdump'] + sample_packet_forward_deps,
diff --git a/app/test/test_net_ipv6.c b/app/test/test_net_ipv6.c
new file mode 100644
index 000000000000..c2b42d67285e
--- /dev/null
+++ b/app/test/test_net_ipv6.c
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2024 Robin Jarry
+ */
+
+#include <rte_ip6.h>
+
+#include "test.h"
+
+static const struct rte_ipv6_addr bcast_addr = {
+	"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+};
+static const struct rte_ipv6_addr zero_addr = { 0 };
+
+static int
+test_ipv6_addr_mask(void)
+{
+	const struct rte_ipv6_addr masked_3 = {
+		"\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+	};
+	const struct rte_ipv6_addr masked_42 = {
+		"\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+	};
+	const struct rte_ipv6_addr masked_85 = {
+		"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00"
+	};
+	const struct rte_ipv6_addr masked_127 = {
+		"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe"
+	};
+	struct rte_ipv6_addr ip;
+
+	ip = bcast_addr;
+	rte_ipv6_addr_mask(&ip, 0);
+	TEST_ASSERT(rte_ipv6_addr_eq(&ip, &zero_addr), "");
+	TEST_ASSERT_EQUAL(rte_ipv6_mask_depth(&zero_addr), 0, "");
+
+	ip = bcast_addr;
+	rte_ipv6_addr_mask(&ip, 3);
+	TEST_ASSERT(rte_ipv6_addr_eq(&ip, &masked_3), "");
+	TEST_ASSERT_EQUAL(rte_ipv6_mask_depth(&masked_3), 3, "");
+
+	ip = bcast_addr;
+	rte_ipv6_addr_mask(&ip, 42);
+	TEST_ASSERT(rte_ipv6_addr_eq(&ip, &masked_42), "");
+	TEST_ASSERT_EQUAL(rte_ipv6_mask_depth(&masked_42), 42, "");
+
+	ip = bcast_addr;
+	rte_ipv6_addr_mask(&ip, 85);
+	TEST_ASSERT(rte_ipv6_addr_eq(&ip, &masked_85), "");
+	TEST_ASSERT_EQUAL(rte_ipv6_mask_depth(&masked_85), 85, "");
+
+	ip = bcast_addr;
+	rte_ipv6_addr_mask(&ip, 127);
+	TEST_ASSERT(rte_ipv6_addr_eq(&ip, &masked_127), "");
+	TEST_ASSERT_EQUAL(rte_ipv6_mask_depth(&masked_127), 127, "");
+
+	ip = bcast_addr;
+	rte_ipv6_addr_mask(&ip, 128);
+	TEST_ASSERT(rte_ipv6_addr_eq(&ip, &bcast_addr), "");
+	TEST_ASSERT_EQUAL(rte_ipv6_mask_depth(&bcast_addr), 128, "");
+
+	const struct rte_ipv6_addr holed_mask = {
+		"\xff\xff\xff\xff\xff\xff\xef\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+	};
+	TEST_ASSERT_EQUAL(rte_ipv6_mask_depth(&holed_mask), 51, "");
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_ipv6_addr_eq_prefix(void)
+{
+	struct rte_ipv6_addr ip1 = {
+		"\x2a\x01\xcb\x00\x02\x54\x33\x00\x1b\x9f\x80\x71\x67\xcd\xbf\x20"
+	};
+	struct rte_ipv6_addr ip2 = {
+		"\x2a\x01\xcb\x00\x02\x54\x33\x00\x62\x39\xe1\xf4\x7a\x0b\x23\x71"
+	};
+	struct rte_ipv6_addr ip3 = {
+		"\xfd\x10\x00\x39\x02\x08\x00\x01\x00\x00\x00\x00\x00\x00\x10\x08"
+	};
+
+	TEST_ASSERT(rte_ipv6_addr_eq_prefix(&ip1, &ip2, 1), "");
+	TEST_ASSERT(rte_ipv6_addr_eq_prefix(&ip1, &ip2, 37), "");
+	TEST_ASSERT(rte_ipv6_addr_eq_prefix(&ip1, &ip2, 64), "");
+	TEST_ASSERT(!rte_ipv6_addr_eq_prefix(&ip1, &ip2, 112), "");
+	TEST_ASSERT(rte_ipv6_addr_eq_prefix(&ip1, &ip3, 0), "");
+	TEST_ASSERT(!rte_ipv6_addr_eq_prefix(&ip1, &ip3, 13), "");
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_ipv6_addr_kind(void)
+{
+	TEST_ASSERT(rte_ipv6_addr_is_unspec(&zero_addr), "");
+
+	struct rte_ipv6_addr ucast = {
+		"\x2a\x01\xcb\x00\x02\x54\x33\x00\x62\x39\xe1\xf4\x7a\x0b\x23\x71"
+	};
+	TEST_ASSERT(!rte_ipv6_addr_is_unspec(&ucast), "");
+
+	struct rte_ipv6_addr mcast = {
+		"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
+	};
+	TEST_ASSERT(!rte_ipv6_addr_is_unspec(&mcast), "");
+
+	struct rte_ipv6_addr lo = {
+		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
+	};
+	TEST_ASSERT(!rte_ipv6_addr_is_unspec(&lo), "");
+
+	struct rte_ipv6_addr local = {
+		"\xfe\x80\x00\x00\x00\x00\x00\x00\x5a\x84\xc5\x2c\x6a\xef\x46\x39"
+	};
+	TEST_ASSERT(!rte_ipv6_addr_is_unspec(&local), "");
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_net_ipv6(void)
+{
+	TEST_ASSERT_SUCCESS(test_ipv6_addr_mask(), "");
+	TEST_ASSERT_SUCCESS(test_ipv6_addr_eq_prefix(), "");
+	TEST_ASSERT_SUCCESS(test_ipv6_addr_kind(), "");
+	return TEST_SUCCESS;
+}
+
+REGISTER_FAST_TEST(net_ipv6_autotest, true, true, test_net_ipv6);
diff --git a/lib/net/rte_ip6.h b/lib/net/rte_ip6.h
index 5354a2bd42b4..c139193e93f3 100644
--- a/lib/net/rte_ip6.h
+++ b/lib/net/rte_ip6.h
@@ -16,6 +16,7 @@
  */
 
 #include <stdint.h>
+#include <string.h>
 
 #ifdef RTE_EXEC_ENV_WINDOWS
 #include <ws2tcpip.h>
@@ -29,6 +30,7 @@
 
 #include <rte_byteorder.h>
 #include <rte_mbuf.h>
+#include <rte_memcpy.h>
 #include <rte_cksum.h>
 
 #ifdef __cplusplus
@@ -45,6 +47,121 @@ struct rte_ipv6_addr {
 	unsigned char a[RTE_IPV6_ADDR_SIZE];
 };
 
+/** Shorthand to initialize IPv6 address values */
+#define RTE_IPV6_ADDR(...) ((struct rte_ipv6_addr){.a = {__VA_ARGS__}})
+
+/**
+ * Copy an IPv6 address into another one.
+ *
+ * @param dst
+ *   The address into which to copy data.
+ * @param src
+ *   The address from which to copy.
+ */
+static inline void
+rte_ipv6_addr_cpy(struct rte_ipv6_addr *dst, const struct rte_ipv6_addr *src)
+{
+	rte_memcpy(dst, src, sizeof(*dst));
+}
+
+/**
+ * Check if two IPv6 Addresses are equal.
+ */
+static inline bool
+rte_ipv6_addr_eq(const struct rte_ipv6_addr *a, const struct rte_ipv6_addr *b)
+{
+	return memcmp(a, b, sizeof(*a)) == 0;
+}
+
+/**
+ * Mask an IPv6 address using the specified depth.
+ *
+ * Leave untouched one bit per unit in the depth variable and set the rest to 0.
+ *
+ * @param ip
+ *   The address to mask.
+ * @param depth
+ *   All bits starting from this bit number will be set to zero.
+ */
+static inline void
+rte_ipv6_addr_mask(struct rte_ipv6_addr *ip, uint8_t depth)
+{
+	if (depth < RTE_IPV6_MAX_DEPTH) {
+		uint8_t d = depth / 8;
+		uint8_t mask = ~(UINT8_MAX >> (depth % 8));
+		ip->a[d] &= mask;
+		d++;
+		memset(&ip->a[d], 0, sizeof(*ip) - d);
+	}
+}
+
+/**
+ * Check if two IPv6 addresses belong to the same network prefix.
+ *
+ * @param a
+ *  The first address or network.
+ * @param b
+ *  The second address or network.
+ * @param depth
+ *  The network prefix length.
+ */
+static inline bool
+rte_ipv6_addr_eq_prefix(const struct rte_ipv6_addr *a, const struct rte_ipv6_addr *b, uint8_t depth)
+{
+	if (depth < RTE_IPV6_MAX_DEPTH) {
+		uint8_t d = depth / 8;
+		uint8_t mask = ~(UINT8_MAX >> (depth % 8));
+
+		if ((a->a[d] ^ b->a[d]) & mask)
+			return false;
+
+		return memcmp(a, b, d) == 0;
+	}
+	return rte_ipv6_addr_eq(a, b);
+}
+
+/**
+ * Get the depth of a given IPv6 address mask.
+ *
+ * This function does not handle masks with "holes" and will return the number
+ * of consecurive bits set to 1 starting from the beginning of the mask.
+ *
+ * @param mask
+ *   The address mask.
+ */
+static inline uint8_t
+rte_ipv6_mask_depth(const struct rte_ipv6_addr *mask)
+{
+	uint8_t depth = 0;
+
+	for (int i = 0; i < RTE_IPV6_ADDR_SIZE; i++) {
+		uint8_t m = mask->a[i];
+		if (m == 0xff) {
+			depth += 8;
+		} else {
+			while (m & 0x80) {
+				m <<= 1;
+				depth++;
+			}
+			break;
+		}
+	}
+
+	return depth;
+}
+
+#define RTE_IPV6_ADDR_UNSPEC RTE_IPV6_ADDR(0)
+
+/**
+ * Check if an IPv6 address is unspecified as defined in RFC 4291, section 2.5.2.
+ */
+static inline bool
+rte_ipv6_addr_is_unspec(const struct rte_ipv6_addr *ip)
+{
+	struct rte_ipv6_addr unspec = RTE_IPV6_ADDR_UNSPEC;
+	return rte_ipv6_addr_eq(ip, &unspec);
+}
+
 /**
  * IPv6 Header
  */
-- 
2.46.1


  parent reply	other threads:[~2024-10-01  8:18 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 01/15] net: split raw checksum functions in separate header Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 02/15] net: split ipv6 symbols " Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 03/15] net: add structure for ipv6 addresses Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 04/15] net: use ipv6 structure for header addresses Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 05/15] fib6,rib6,lpm6: use ipv6 addr struct Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 06/15] net: add ipv6 address utilities Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 07/15] fib6,rib6,lpm6: use ipv6 utils Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 08/15] graph,node: use ipv6 addr struct and utils Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 09/15] pipeline: use ipv6 addr struct Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 10/15] ipsec: " Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 11/15] thash: " Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 12/15] gro: " Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 13/15] rte_flow: " Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 14/15] rib6,fib6,lpm6: remove duplicate constants Robin Jarry
2024-08-21 16:25 ` [PATCH dpdk v1 15/15] net: add utilities for well known ipv6 address types Robin Jarry
2024-08-21 22:28 ` [PATCH dpdk v1 00/15] IPv6 APIs overhaul Morten Brørup
2024-08-22 14:13 ` Stephen Hemminger
2024-08-22 15:13   ` Morten Brørup
2024-08-22 15:27     ` Robin Jarry
2024-08-22 18:41       ` Morten Brørup
2024-08-22 15:14   ` Robin Jarry
2024-08-22 15:16   ` Robin Jarry
2024-10-01  8:17 ` [PATCH dpdk v2 00/16] " Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 01/16] net: split raw checksum functions in separate header Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 02/16] net: split ipv6 symbols " Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 03/16] net: add structure for ipv6 addresses Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 04/16] net: use ipv6 structure for header addresses Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 05/16] fib6,rib6,lpm6: use ipv6 addr struct Robin Jarry
2024-10-01  8:17   ` Robin Jarry [this message]
2024-10-01 15:35     ` [PATCH dpdk v2 06/16] net: add ipv6 address utilities Stephen Hemminger
2024-10-01  8:17   ` [PATCH dpdk v2 07/16] fib6,rib6,lpm6: use ipv6 utils Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 08/16] graph,node: use ipv6 addr struct and utils Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 09/16] pipeline: use ipv6 addr struct Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 10/16] ipsec: " Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 11/16] thash: " Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 12/16] gro: " Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 13/16] rte_flow: " Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 14/16] rib6,fib6,lpm6: remove duplicate constants Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 15/16] net: add utilities for well known ipv6 address types Robin Jarry
2024-10-01  8:17   ` [PATCH dpdk v2 16/16] ipv6: add function to check ipv6 version Robin Jarry

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241001081728.301272-7-rjarry@redhat.com \
    --to=rjarry@redhat.com \
    --cc=dev@dpdk.org \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).