DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH dpdk v1 00/15] IPv6 APIs overhaul
@ 2024-08-21 16:25 Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 01/15] net: split raw checksum functions in separate header Robin Jarry
                   ` (16 more replies)
  0 siblings, 17 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev
  Cc: Morten Brørup, Stephen Hemminger, Vladimir Medvedkin,
	Konstantin Ananyev, Bruce Richardson

Hi everyone,

As discussed recently [1], here is a first draft of the IPv6 APIs rework. The
API change was announced before the 24.07 release [2]. This series is intended
for 24.11.

[1] http://inbox.dpdk.org/dev/D2SR8T1H39CJ.JRQFI6JEH0OX@redhat.com/
[2] https://git.dpdk.org/dpdk/commit/?id=835d4c41e0ab58a115c2170c886ba6d3cc1b5764

I tried to keep the patches as small as possible; unfortunately some of them
are quite big and cannot be broken down if we want to preserve a bisectable
tree.

Let me know what you think.

Thanks!

Cc: Morten Brørup <mb@smartsharesystems.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Cc: Konstantin Ananyev <konstantin.ananyev@huawei.com>
Cc: Bruce Richardson <bruce.richardson@intel.com>

Robin Jarry (15):
  net: split raw checksum functions in separate header
  net: split ipv6 symbols in separate header
  net: add structure for ipv6 addresses
  net: use ipv6 structure for header addresses
  fib6,rib6,lpm6: use ipv6 addr struct
  net: add ipv6 address utilities
  fib6,rib6,lpm6: use ipv6 utils
  graph,node: use ipv6 addr struct and utils
  pipeline: use ipv6 addr struct
  ipsec: use ipv6 addr struct
  thash: use ipv6 addr struct
  gro: use ipv6 addr struct
  rte_flow: use ipv6 addr struct
  rib6,fib6,lpm6: remove duplicate constants
  net: add utilities for well known ipv6 address types

 app/graph/ethdev.c                          |   40 +-
 app/graph/ethdev.h                          |    9 +-
 app/graph/ip6_route.c                       |   47 +-
 app/graph/meson.build                       |    2 +-
 app/graph/neigh.c                           |   22 +-
 app/graph/neigh_priv.h                      |    4 +-
 app/graph/route.h                           |    8 +-
 app/test-fib/main.c                         |   51 +-
 app/test-flow-perf/actions_gen.c            |    4 +-
 app/test-flow-perf/items_gen.c              |    4 +-
 app/test-pipeline/pipeline_hash.c           |    4 +-
 app/test-pipeline/pipeline_lpm_ipv6.c       |   10 +-
 app/test-sad/main.c                         |   24 +-
 app/test/meson.build                        |    1 +
 app/test/packet_burst_generator.c           |    5 +-
 app/test/test_cryptodev_security_ipsec.c    |    1 +
 app/test/test_fib6.c                        |   93 +-
 app/test/test_fib6_perf.c                   |    8 +-
 app/test/test_ipfrag.c                      |    4 +-
 app/test/test_ipsec_sad.c                   |   44 +-
 app/test/test_lpm6.c                        |  523 ++---
 app/test/test_lpm6_data.h                   | 2025 ++++++++++---------
 app/test/test_lpm6_perf.c                   |   10 +-
 app/test/test_net_ipv6.c                    |  203 ++
 app/test/test_reassembly_perf.c             |   20 +-
 app/test/test_rib6.c                        |   65 +-
 app/test/test_table_combined.c              |    2 +-
 app/test/test_table_tables.c                |    8 +-
 app/test/test_thash.c                       |   46 +-
 drivers/common/cnxk/cnxk_security.c         |    1 +
 drivers/crypto/cnxk/cn9k_cryptodev_ops.c    |    1 +
 drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c |    1 +
 drivers/net/bnxt/bnxt_flow.c                |   12 +-
 drivers/net/bonding/rte_eth_bond_pmd.c      |    4 +-
 drivers/net/cxgbe/cxgbe_flow.c              |   18 +-
 drivers/net/dpaa2/dpaa2_flow.c              |   22 +-
 drivers/net/hinic/hinic_pmd_flow.c          |    6 +-
 drivers/net/hinic/hinic_pmd_tx.c            |    2 +-
 drivers/net/hns3/hns3_flow.c                |    8 +-
 drivers/net/i40e/i40e_flow.c                |   12 +-
 drivers/net/iavf/iavf_fdir.c                |    8 +-
 drivers/net/iavf/iavf_fsub.c                |    8 +-
 drivers/net/iavf/iavf_ipsec_crypto.c        |    6 +-
 drivers/net/ice/ice_fdir_filter.c           |   12 +-
 drivers/net/ice/ice_switch_filter.c         |   16 +-
 drivers/net/igc/igc_flow.c                  |    4 +-
 drivers/net/ixgbe/ixgbe_flow.c              |   12 +-
 drivers/net/ixgbe/ixgbe_ipsec.c             |    4 +-
 drivers/net/mlx5/hws/mlx5dr_definer.c       |   36 +-
 drivers/net/mlx5/mlx5_flow.c                |    6 +-
 drivers/net/mlx5/mlx5_flow_dv.c             |   16 +-
 drivers/net/mlx5/mlx5_flow_hw.c             |   10 +-
 drivers/net/mlx5/mlx5_flow_verbs.c          |    8 +-
 drivers/net/nfp/flower/nfp_flower_flow.c    |   36 +-
 drivers/net/nfp/nfp_net_flow.c              |   44 +-
 drivers/net/qede/qede_filter.c              |    4 +-
 drivers/net/sfc/sfc_flow.c                  |   28 +-
 drivers/net/tap/tap_flow.c                  |    8 +-
 drivers/net/txgbe/txgbe_flow.c              |   12 +-
 drivers/net/txgbe/txgbe_ipsec.c             |    4 +-
 examples/ip_fragmentation/main.c            |   24 +-
 examples/ip_pipeline/cli.c                  |   12 +-
 examples/ip_pipeline/pipeline.c             |   17 +-
 examples/ip_pipeline/thread.c               |    2 +-
 examples/ip_reassembly/main.c               |   24 +-
 examples/ipsec-secgw/flow.c                 |   12 +-
 examples/ipsec-secgw/ipsec.c                |    8 +-
 examples/ipsec-secgw/ipsec_lpm_neon.h       |    7 +-
 examples/ipsec-secgw/ipsec_worker.c         |    6 +-
 examples/ipsec-secgw/ipsec_worker.h         |    4 +-
 examples/ipsec-secgw/rt.c                   |   22 +-
 examples/ipsec-secgw/sa.c                   |    4 +-
 examples/ipsec-secgw/sad.h                  |   12 +-
 examples/l3fwd-graph/main.c                 |   30 +-
 examples/l3fwd/l3fwd_fib.c                  |   39 +-
 examples/l3fwd/l3fwd_lpm.c                  |    8 +-
 examples/l3fwd/l3fwd_route.h                |    7 +-
 examples/l3fwd/lpm_route_parse.c            |    6 +-
 lib/ethdev/rte_flow.h                       |   23 +-
 lib/fib/meson.build                         |    4 +-
 lib/fib/rte_fib6.c                          |   19 +-
 lib/fib/rte_fib6.h                          |   15 +-
 lib/fib/trie.c                              |  117 +-
 lib/fib/trie.h                              |   18 +-
 lib/fib/trie_avx512.c                       |   38 +-
 lib/fib/trie_avx512.h                       |   10 +-
 lib/gro/gro_tcp6.c                          |    8 +-
 lib/gro/gro_tcp6.h                          |    6 +-
 lib/hash/rte_thash.h                        |   29 +-
 lib/ip_frag/rte_ip_frag.h                   |    1 +
 lib/ip_frag/rte_ipv6_reassembly.c           |    4 +-
 lib/ipsec/iph.h                             |    1 +
 lib/ipsec/rte_ipsec_sad.h                   |    7 +-
 lib/lpm/meson.build                         |    1 +
 lib/lpm/rte_lpm6.c                          |  147 +-
 lib/lpm/rte_lpm6.h                          |   17 +-
 lib/net/meson.build                         |    2 +
 lib/net/rte_cksum.h                         |  189 ++
 lib/net/rte_ip.h                            |  467 +----
 lib/net/rte_ip6.h                           |  580 ++++++
 lib/net/rte_net.c                           |    1 +
 lib/net/rte_net.h                           |    1 +
 lib/node/ip6_lookup.c                       |   21 +-
 lib/node/rte_node_ip6_api.h                 |    3 +-
 lib/pipeline/rte_swx_ipsec.c                |    7 +-
 lib/pipeline/rte_table_action.c             |   45 +-
 lib/pipeline/rte_table_action.h             |    7 +-
 lib/rib/meson.build                         |    2 +-
 lib/rib/rte_rib6.c                          |  112 +-
 lib/rib/rte_rib6.h                          |   27 +-
 lib/table/rte_table_lpm_ipv6.c              |   12 +-
 lib/table/rte_table_lpm_ipv6.h              |    4 +-
 lib/vhost/virtio_net.c                      |    1 +
 113 files changed, 3147 insertions(+), 2699 deletions(-)
 create mode 100644 app/test/test_net_ipv6.c
 create mode 100644 lib/net/rte_cksum.h
 create mode 100644 lib/net/rte_ip6.h

-- 
2.46.0


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

* [PATCH dpdk v1 01/15] net: split raw checksum functions in separate header
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 02/15] net: split ipv6 symbols " Robin Jarry
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev

The checksum functions are used by both ipv4 and ipv6 functions. In
preparation of moving ipv6 symbols to a new header, move the checksum
related symbols to another dedicated header.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 lib/net/meson.build |   1 +
 lib/net/rte_cksum.h | 189 ++++++++++++++++++++++++++++++++++++++++++++
 lib/net/rte_ip.h    | 148 +---------------------------------
 3 files changed, 191 insertions(+), 147 deletions(-)
 create mode 100644 lib/net/rte_cksum.h

diff --git a/lib/net/meson.build b/lib/net/meson.build
index 0b691389495a..2e65bd19b7d4 100644
--- a/lib/net/meson.build
+++ b/lib/net/meson.build
@@ -3,6 +3,7 @@
 
 headers = files(
         'rte_ip.h',
+        'rte_cksum.h',
         'rte_tcp.h',
         'rte_udp.h',
         'rte_tls.h',
diff --git a/lib/net/rte_cksum.h b/lib/net/rte_cksum.h
new file mode 100644
index 000000000000..8deceab51508
--- /dev/null
+++ b/lib/net/rte_cksum.h
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 1982, 1986, 1990, 1993
+ *      The Regents of the University of California.
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#ifndef _RTE_CKSUM_H_
+#define _RTE_CKSUM_H_
+
+/**
+ * @file
+ *
+ * Protocol independent checksum utilities.
+ */
+
+#include <stdint.h>
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#endif
+
+#include <rte_mbuf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @internal Calculate a sum of all words in the buffer.
+ * Helper routine for the rte_raw_cksum().
+ *
+ * @param buf
+ *   Pointer to the buffer.
+ * @param len
+ *   Length of the buffer.
+ * @param sum
+ *   Initial value of the sum.
+ * @return
+ *   sum += Sum of all words in the buffer.
+ */
+static inline uint32_t
+__rte_raw_cksum(const void *buf, size_t len, uint32_t sum)
+{
+	const void *end;
+
+	for (end = RTE_PTR_ADD(buf, RTE_ALIGN_FLOOR(len, sizeof(uint16_t)));
+	     buf != end; buf = RTE_PTR_ADD(buf, sizeof(uint16_t))) {
+		uint16_t v;
+
+		memcpy(&v, buf, sizeof(uint16_t));
+		sum += v;
+	}
+
+	/* if length is odd, keeping it byte order independent */
+	if (unlikely(len % 2)) {
+		uint16_t left = 0;
+
+		memcpy(&left, end, 1);
+		sum += left;
+	}
+
+	return sum;
+}
+
+/**
+ * @internal Reduce a sum to the non-complemented checksum.
+ * Helper routine for the rte_raw_cksum().
+ *
+ * @param sum
+ *   Value of the sum.
+ * @return
+ *   The non-complemented checksum.
+ */
+static inline uint16_t
+__rte_raw_cksum_reduce(uint32_t sum)
+{
+	sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
+	sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
+	return (uint16_t)sum;
+}
+
+/**
+ * Process the non-complemented checksum of a buffer.
+ *
+ * @param buf
+ *   Pointer to the buffer.
+ * @param len
+ *   Length of the buffer.
+ * @return
+ *   The non-complemented checksum.
+ */
+static inline uint16_t
+rte_raw_cksum(const void *buf, size_t len)
+{
+	uint32_t sum;
+
+	sum = __rte_raw_cksum(buf, len, 0);
+	return __rte_raw_cksum_reduce(sum);
+}
+
+/**
+ * Compute the raw (non complemented) checksum of a packet.
+ *
+ * @param m
+ *   The pointer to the mbuf.
+ * @param off
+ *   The offset in bytes to start the checksum.
+ * @param len
+ *   The length in bytes of the data to checksum.
+ * @param cksum
+ *   A pointer to the checksum, filled on success.
+ * @return
+ *   0 on success, -1 on error (bad length or offset).
+ */
+static inline int
+rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len,
+	uint16_t *cksum)
+{
+	const struct rte_mbuf *seg;
+	const char *buf;
+	uint32_t sum, tmp;
+	uint32_t seglen, done;
+
+	/* easy case: all data in the first segment */
+	if (off + len <= rte_pktmbuf_data_len(m)) {
+		*cksum = rte_raw_cksum(rte_pktmbuf_mtod_offset(m,
+				const char *, off), len);
+		return 0;
+	}
+
+	if (unlikely(off + len > rte_pktmbuf_pkt_len(m)))
+		return -1; /* invalid params, return a dummy value */
+
+	/* else browse the segment to find offset */
+	seglen = 0;
+	for (seg = m; seg != NULL; seg = seg->next) {
+		seglen = rte_pktmbuf_data_len(seg);
+		if (off < seglen)
+			break;
+		off -= seglen;
+	}
+	RTE_ASSERT(seg != NULL);
+	if (seg == NULL)
+		return -1;
+	seglen -= off;
+	buf = rte_pktmbuf_mtod_offset(seg, const char *, off);
+	if (seglen >= len) {
+		/* all in one segment */
+		*cksum = rte_raw_cksum(buf, len);
+		return 0;
+	}
+
+	/* hard case: process checksum of several segments */
+	sum = 0;
+	done = 0;
+	for (;;) {
+		tmp = __rte_raw_cksum(buf, seglen, 0);
+		if (done & 1)
+			tmp = rte_bswap16((uint16_t)tmp);
+		sum += tmp;
+		done += seglen;
+		if (done == len)
+			break;
+		seg = seg->next;
+		buf = rte_pktmbuf_mtod(seg, const char *);
+		seglen = rte_pktmbuf_data_len(seg);
+		if (seglen > len - done)
+			seglen = len - done;
+	}
+
+	*cksum = __rte_raw_cksum_reduce(sum);
+	return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CKSUM_H_ */
diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h
index 0d103d4127e8..0ae7c0565047 100644
--- a/lib/net/rte_ip.h
+++ b/lib/net/rte_ip.h
@@ -30,6 +30,7 @@
 
 #include <rte_byteorder.h>
 #include <rte_mbuf.h>
+#include <rte_cksum.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -144,153 +145,6 @@ rte_ipv4_hdr_len(const struct rte_ipv4_hdr *ipv4_hdr)
 		RTE_IPV4_IHL_MULTIPLIER);
 }
 
-/**
- * @internal Calculate a sum of all words in the buffer.
- * Helper routine for the rte_raw_cksum().
- *
- * @param buf
- *   Pointer to the buffer.
- * @param len
- *   Length of the buffer.
- * @param sum
- *   Initial value of the sum.
- * @return
- *   sum += Sum of all words in the buffer.
- */
-static inline uint32_t
-__rte_raw_cksum(const void *buf, size_t len, uint32_t sum)
-{
-	const void *end;
-
-	for (end = RTE_PTR_ADD(buf, RTE_ALIGN_FLOOR(len, sizeof(uint16_t)));
-	     buf != end; buf = RTE_PTR_ADD(buf, sizeof(uint16_t))) {
-		uint16_t v;
-
-		memcpy(&v, buf, sizeof(uint16_t));
-		sum += v;
-	}
-
-	/* if length is odd, keeping it byte order independent */
-	if (unlikely(len % 2)) {
-		uint16_t left = 0;
-
-		memcpy(&left, end, 1);
-		sum += left;
-	}
-
-	return sum;
-}
-
-/**
- * @internal Reduce a sum to the non-complemented checksum.
- * Helper routine for the rte_raw_cksum().
- *
- * @param sum
- *   Value of the sum.
- * @return
- *   The non-complemented checksum.
- */
-static inline uint16_t
-__rte_raw_cksum_reduce(uint32_t sum)
-{
-	sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
-	sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
-	return (uint16_t)sum;
-}
-
-/**
- * Process the non-complemented checksum of a buffer.
- *
- * @param buf
- *   Pointer to the buffer.
- * @param len
- *   Length of the buffer.
- * @return
- *   The non-complemented checksum.
- */
-static inline uint16_t
-rte_raw_cksum(const void *buf, size_t len)
-{
-	uint32_t sum;
-
-	sum = __rte_raw_cksum(buf, len, 0);
-	return __rte_raw_cksum_reduce(sum);
-}
-
-/**
- * Compute the raw (non complemented) checksum of a packet.
- *
- * @param m
- *   The pointer to the mbuf.
- * @param off
- *   The offset in bytes to start the checksum.
- * @param len
- *   The length in bytes of the data to checksum.
- * @param cksum
- *   A pointer to the checksum, filled on success.
- * @return
- *   0 on success, -1 on error (bad length or offset).
- */
-static inline int
-rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len,
-	uint16_t *cksum)
-{
-	const struct rte_mbuf *seg;
-	const char *buf;
-	uint32_t sum, tmp;
-	uint32_t seglen, done;
-
-	/* easy case: all data in the first segment */
-	if (off + len <= rte_pktmbuf_data_len(m)) {
-		*cksum = rte_raw_cksum(rte_pktmbuf_mtod_offset(m,
-				const char *, off), len);
-		return 0;
-	}
-
-	if (unlikely(off + len > rte_pktmbuf_pkt_len(m)))
-		return -1; /* invalid params, return a dummy value */
-
-	/* else browse the segment to find offset */
-	seglen = 0;
-	for (seg = m; seg != NULL; seg = seg->next) {
-		seglen = rte_pktmbuf_data_len(seg);
-		if (off < seglen)
-			break;
-		off -= seglen;
-	}
-	RTE_ASSERT(seg != NULL);
-	if (seg == NULL)
-		return -1;
-	seglen -= off;
-	buf = rte_pktmbuf_mtod_offset(seg, const char *, off);
-	if (seglen >= len) {
-		/* all in one segment */
-		*cksum = rte_raw_cksum(buf, len);
-		return 0;
-	}
-
-	/* hard case: process checksum of several segments */
-	sum = 0;
-	done = 0;
-	for (;;) {
-		tmp = __rte_raw_cksum(buf, seglen, 0);
-		if (done & 1)
-			tmp = rte_bswap16((uint16_t)tmp);
-		sum += tmp;
-		done += seglen;
-		if (done == len)
-			break;
-		seg = seg->next;
-		buf = rte_pktmbuf_mtod(seg, const char *);
-		seglen = rte_pktmbuf_data_len(seg);
-		if (seglen > len - done)
-			seglen = len - done;
-	}
-
-	*cksum = __rte_raw_cksum_reduce(sum);
-	return 0;
-}
-
 /**
  * Process the IPv4 checksum of an IPv4 header.
  *
-- 
2.46.0


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

* [PATCH dpdk v1 02/15] net: split ipv6 symbols in separate header
  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 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 03/15] net: add structure for ipv6 addresses Robin Jarry
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Akhil Goyal, Fan Zhang, Nithin Dabilpuram, Kiran Kumar K,
	Sunil Kumar Kori, Satha Rao, Harman Kalra, Ankur Dwivedi,
	Anoob Joseph, Tejasree Kondoj, Gagandeep Singh, Hemant Agrawal,
	Cristian Dumitrescu, Ori Kam, Thomas Monjalon, Ferruh Yigit,
	Andrew Rybchenko, Yipeng Wang, Sameh Gobriel, Bruce Richardson,
	Vladimir Medvedkin, Konstantin Ananyev, Maxime Coquelin,
	Chenbo Xia

Move all ipv6 related symbols to a dedicated header. Update all code
accordingly.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test/packet_burst_generator.c           |   1 +
 app/test/test_cryptodev_security_ipsec.c    |   1 +
 drivers/common/cnxk/cnxk_security.c         |   1 +
 drivers/crypto/cnxk/cn9k_cryptodev_ops.c    |   1 +
 drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c |   1 +
 examples/ip_pipeline/pipeline.c             |   1 +
 lib/ethdev/rte_flow.h                       |   1 +
 lib/hash/rte_thash.h                        |   1 +
 lib/ip_frag/rte_ip_frag.h                   |   1 +
 lib/ipsec/iph.h                             |   1 +
 lib/net/meson.build                         |   1 +
 lib/net/rte_ip.h                            | 319 ------------------
 lib/net/{rte_ip.h => rte_ip6.h}             | 352 +-------------------
 lib/net/rte_net.c                           |   1 +
 lib/net/rte_net.h                           |   1 +
 lib/pipeline/rte_swx_ipsec.c                |   1 +
 lib/pipeline/rte_table_action.c             |   1 +
 lib/vhost/virtio_net.c                      |   1 +
 18 files changed, 22 insertions(+), 665 deletions(-)
 copy lib/net/{rte_ip.h => rte_ip6.h} (50%)

diff --git a/app/test/packet_burst_generator.c b/app/test/packet_burst_generator.c
index 867a88da0055..2cd34abc1a65 100644
--- a/app/test/packet_burst_generator.c
+++ b/app/test/packet_burst_generator.c
@@ -5,6 +5,7 @@
 #include <rte_byteorder.h>
 #include <rte_mbuf.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_os_shim.h>
 
 #include "packet_burst_generator.h"
diff --git a/app/test/test_cryptodev_security_ipsec.c b/app/test/test_cryptodev_security_ipsec.c
index 1aba1ad9934b..9ac4a6e599b0 100644
--- a/app/test/test_cryptodev_security_ipsec.c
+++ b/app/test/test_cryptodev_security_ipsec.c
@@ -6,6 +6,7 @@
 #include <rte_cryptodev.h>
 #include <rte_esp.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_security.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
diff --git a/drivers/common/cnxk/cnxk_security.c b/drivers/common/cnxk/cnxk_security.c
index 15b0bedf43e2..e275d6cad3ea 100644
--- a/drivers/common/cnxk/cnxk_security.c
+++ b/drivers/common/cnxk/cnxk_security.c
@@ -2,6 +2,7 @@
  * Copyright(C) 2021 Marvell.
  */
 
+#include <rte_ip6.h>
 #include <rte_udp.h>
 
 #include "cnxk_security.h"
diff --git a/drivers/crypto/cnxk/cn9k_cryptodev_ops.c b/drivers/crypto/cnxk/cn9k_cryptodev_ops.c
index f443cb9563ec..a3c737ef40f7 100644
--- a/drivers/crypto/cnxk/cn9k_cryptodev_ops.c
+++ b/drivers/crypto/cnxk/cn9k_cryptodev_ops.c
@@ -6,6 +6,7 @@
 #include <cryptodev_pmd.h>
 #include <rte_event_crypto_adapter.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_vect.h>
 
 #include "roc_cpt.h"
diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
index c1f7181d5587..5bf690e3d82a 100644
--- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
+++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
@@ -10,6 +10,7 @@
 #include <unistd.h>
 
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_udp.h>
 #include <rte_mbuf.h>
 #include <rte_cryptodev.h>
diff --git a/examples/ip_pipeline/pipeline.c b/examples/ip_pipeline/pipeline.c
index 63352257c6e9..301c52d061be 100644
--- a/examples/ip_pipeline/pipeline.c
+++ b/examples/ip_pipeline/pipeline.c
@@ -7,6 +7,7 @@
 
 #include <rte_common.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_tcp.h>
 
 #include <rte_string_fns.h>
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index f864578f806b..3a3ab781c494 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -23,6 +23,7 @@
 #include <rte_arp.h>
 #include <rte_icmp.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_sctp.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
diff --git a/lib/hash/rte_thash.h b/lib/hash/rte_thash.h
index 30b657e67a7d..af40afd2d475 100644
--- a/lib/hash/rte_thash.h
+++ b/lib/hash/rte_thash.h
@@ -23,6 +23,7 @@ extern "C" {
 
 #include <rte_byteorder.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_common.h>
 #include <rte_thash_gfni.h>
 
diff --git a/lib/ip_frag/rte_ip_frag.h b/lib/ip_frag/rte_ip_frag.h
index 2ad318096b7b..cb06d5f5977a 100644
--- a/lib/ip_frag/rte_ip_frag.h
+++ b/lib/ip_frag/rte_ip_frag.h
@@ -23,6 +23,7 @@ extern "C" {
 #include <rte_malloc.h>
 #include <rte_memory.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_byteorder.h>
 
 struct rte_mbuf;
diff --git a/lib/ipsec/iph.h b/lib/ipsec/iph.h
index 861f16905ad0..815a3c90d76b 100644
--- a/lib/ipsec/iph.h
+++ b/lib/ipsec/iph.h
@@ -6,6 +6,7 @@
 #define _IPH_H_
 
 #include <rte_ip.h>
+#include <rte_ip6.h>
 
 /**
  * @file iph.h
diff --git a/lib/net/meson.build b/lib/net/meson.build
index 2e65bd19b7d4..35ac334a18cf 100644
--- a/lib/net/meson.build
+++ b/lib/net/meson.build
@@ -3,6 +3,7 @@
 
 headers = files(
         'rte_ip.h',
+        'rte_ip6.h',
         'rte_cksum.h',
         'rte_tcp.h',
         'rte_udp.h',
diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip.h
index 0ae7c0565047..e3c8d0163f64 100644
--- a/lib/net/rte_ip.h
+++ b/lib/net/rte_ip.h
@@ -374,325 +374,6 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m,
 	return 0;
 }
 
-/**
- * IPv6 Header
- */
-struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label. */
-	rte_be16_t payload_len;	/**< IP payload size, including ext. headers */
-	uint8_t  proto;		/**< Protocol, next header. */
-	uint8_t  hop_limits;	/**< Hop limits. */
-	uint8_t  src_addr[16];	/**< IP address of source host. */
-	uint8_t  dst_addr[16];	/**< IP address of destination host(s). */
-} __rte_packed;
-
-/* IPv6 routing extension type definition. */
-#define RTE_IPV6_SRCRT_TYPE_4 4
-
-/**
- * IPv6 Routing Extension Header
- */
-struct rte_ipv6_routing_ext {
-	uint8_t next_hdr;			/**< Protocol, next header. */
-	uint8_t hdr_len;			/**< Header length. */
-	uint8_t type;				/**< Extension header type. */
-	uint8_t segments_left;			/**< Valid segments number. */
-	__extension__
-	union {
-		rte_be32_t flags;		/**< Packet control data per type. */
-		struct {
-			uint8_t last_entry;	/**< The last_entry field of SRH */
-			uint8_t flag;		/**< Packet flag. */
-			rte_be16_t tag;		/**< Packet tag. */
-		};
-	};
-	/* Next are 128-bit IPv6 address fields to describe segments. */
-} __rte_packed;
-
-/* IPv6 vtc_flow: IPv / TC / flow_label */
-#define RTE_IPV6_HDR_FL_SHIFT 0
-#define RTE_IPV6_HDR_TC_SHIFT 20
-#define RTE_IPV6_HDR_FL_MASK	((1u << RTE_IPV6_HDR_TC_SHIFT) - 1)
-#define RTE_IPV6_HDR_TC_MASK	(0xff << RTE_IPV6_HDR_TC_SHIFT)
-#define RTE_IPV6_HDR_DSCP_MASK	(0xfc << RTE_IPV6_HDR_TC_SHIFT)
-#define RTE_IPV6_HDR_ECN_MASK	(0x03 << RTE_IPV6_HDR_TC_SHIFT)
-#define RTE_IPV6_HDR_ECN_CE	RTE_IPV6_HDR_ECN_MASK
-
-#define RTE_IPV6_MIN_MTU 1280 /**< Minimum MTU for IPv6, see RFC 8200. */
-
-/**
- * Process the pseudo-header checksum of an IPv6 header.
- *
- * Depending on the ol_flags, the pseudo-header checksum expected by the
- * drivers is not the same. For instance, when TSO is enabled, the IPv6
- * payload length must not be included in the packet.
- *
- * When ol_flags is 0, it computes the standard pseudo-header checksum.
- *
- * @param ipv6_hdr
- *   The pointer to the contiguous IPv6 header.
- * @param ol_flags
- *   The ol_flags of the associated mbuf.
- * @return
- *   The non-complemented checksum to set in the L4 header.
- */
-static inline uint16_t
-rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags)
-{
-	uint32_t sum;
-	struct {
-		rte_be32_t len;   /* L4 length. */
-		rte_be32_t proto; /* L4 protocol - top 3 bytes must be zero */
-	} psd_hdr;
-
-	psd_hdr.proto = (uint32_t)(ipv6_hdr->proto << 24);
-	if (ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG)) {
-		psd_hdr.len = 0;
-	} else {
-		psd_hdr.len = ipv6_hdr->payload_len;
-	}
-
-	sum = __rte_raw_cksum(ipv6_hdr->src_addr,
-		sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr),
-		0);
-	sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum);
-	return __rte_raw_cksum_reduce(sum);
-}
-
-/**
- * @internal Calculate the non-complemented IPv6 L4 checksum
- */
-static inline uint16_t
-__rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr)
-{
-	uint32_t cksum;
-	uint32_t l4_len;
-
-	l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len);
-
-	cksum = rte_raw_cksum(l4_hdr, l4_len);
-	cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0);
-
-	cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
-
-	return (uint16_t)cksum;
-}
-
-/**
- * Process the IPv6 UDP or TCP checksum.
- *
- * The IPv6 header must not be followed by extension headers. The layer 4
- * checksum must be set to 0 in the L4 header by the caller.
- *
- * @param ipv6_hdr
- *   The pointer to the contiguous IPv6 header.
- * @param l4_hdr
- *   The pointer to the beginning of the L4 header.
- * @return
- *   The complemented checksum to set in the L4 header.
- */
-static inline uint16_t
-rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr)
-{
-	uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr);
-
-	cksum = ~cksum;
-
-	/*
-	 * Per RFC 768: If the computed checksum is zero for UDP,
-	 * it is transmitted as all ones
-	 * (the equivalent in one's complement arithmetic).
-	 */
-	if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP)
-		cksum = 0xffff;
-
-	return cksum;
-}
-
-/**
- * @internal Calculate the non-complemented IPv6 L4 checksum of a packet
- */
-static inline uint16_t
-__rte_ipv6_udptcp_cksum_mbuf(const struct rte_mbuf *m,
-			     const struct rte_ipv6_hdr *ipv6_hdr,
-			     uint16_t l4_off)
-{
-	uint16_t raw_cksum;
-	uint32_t cksum;
-
-	if (unlikely(l4_off > m->pkt_len))
-		return 0; /* invalid params, return a dummy value */
-
-	if (rte_raw_cksum_mbuf(m, l4_off, rte_be_to_cpu_16(ipv6_hdr->payload_len), &raw_cksum))
-		return 0;
-
-	cksum = raw_cksum + rte_ipv6_phdr_cksum(ipv6_hdr, 0);
-
-	cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
-
-	return (uint16_t)cksum;
-}
-
-/**
- * Process the IPv6 UDP or TCP checksum of a packet.
- *
- * The IPv6 header must not be followed by extension headers. The layer 4
- * checksum must be set to 0 in the L4 header by the caller.
- *
- * @param m
- *   The pointer to the mbuf.
- * @param ipv6_hdr
- *   The pointer to the contiguous IPv6 header.
- * @param l4_off
- *   The offset in bytes to start L4 checksum.
- * @return
- *   The complemented checksum to set in the L4 header.
- */
-static inline uint16_t
-rte_ipv6_udptcp_cksum_mbuf(const struct rte_mbuf *m,
-			   const struct rte_ipv6_hdr *ipv6_hdr, uint16_t l4_off)
-{
-	uint16_t cksum = __rte_ipv6_udptcp_cksum_mbuf(m, ipv6_hdr, l4_off);
-
-	cksum = ~cksum;
-
-	/*
-	 * Per RFC 768: If the computed checksum is zero for UDP,
-	 * it is transmitted as all ones
-	 * (the equivalent in one's complement arithmetic).
-	 */
-	if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP)
-		cksum = 0xffff;
-
-	return cksum;
-}
-
-/**
- * Validate the IPv6 UDP or TCP checksum.
- *
- * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0:
- * this is either invalid or means no checksum in some situations. See 8.1
- * (Upper-Layer Checksums) in RFC 8200.
- *
- * @param ipv6_hdr
- *   The pointer to the contiguous IPv6 header.
- * @param l4_hdr
- *   The pointer to the beginning of the L4 header.
- * @return
- *   Return 0 if the checksum is correct, else -1.
- */
-static inline int
-rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr,
-			     const void *l4_hdr)
-{
-	uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr);
-
-	if (cksum != 0xffff)
-		return -1;
-
-	return 0;
-}
-
-/**
- * Validate the IPv6 UDP or TCP checksum of a packet.
- *
- * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0:
- * this is either invalid or means no checksum in some situations. See 8.1
- * (Upper-Layer Checksums) in RFC 8200.
- *
- * @param m
- *   The pointer to the mbuf.
- * @param ipv6_hdr
- *   The pointer to the contiguous IPv6 header.
- * @param l4_off
- *   The offset in bytes to start L4 checksum.
- * @return
- *   Return 0 if the checksum is correct, else -1.
- */
-static inline int
-rte_ipv6_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m,
-				  const struct rte_ipv6_hdr *ipv6_hdr,
-				  uint16_t l4_off)
-{
-	uint16_t cksum = __rte_ipv6_udptcp_cksum_mbuf(m, ipv6_hdr, l4_off);
-
-	if (cksum != 0xffff)
-		return -1;
-
-	return 0;
-}
-
-/** IPv6 fragment extension header. */
-#define	RTE_IPV6_EHDR_MF_SHIFT	0
-#define	RTE_IPV6_EHDR_MF_MASK	1
-#define	RTE_IPV6_EHDR_FO_SHIFT	3
-#define	RTE_IPV6_EHDR_FO_MASK	(~((1 << RTE_IPV6_EHDR_FO_SHIFT) - 1))
-#define	RTE_IPV6_EHDR_FO_ALIGN	(1 << RTE_IPV6_EHDR_FO_SHIFT)
-
-#define RTE_IPV6_FRAG_USED_MASK	(RTE_IPV6_EHDR_MF_MASK | RTE_IPV6_EHDR_FO_MASK)
-
-#define RTE_IPV6_GET_MF(x)	((x) & RTE_IPV6_EHDR_MF_MASK)
-#define RTE_IPV6_GET_FO(x)	((x) >> RTE_IPV6_EHDR_FO_SHIFT)
-
-#define RTE_IPV6_SET_FRAG_DATA(fo, mf)	\
-	(((fo) & RTE_IPV6_EHDR_FO_MASK) | ((mf) & RTE_IPV6_EHDR_MF_MASK))
-
-struct rte_ipv6_fragment_ext {
-	uint8_t next_header;	/**< Next header type */
-	uint8_t reserved;	/**< Reserved */
-	rte_be16_t frag_data;	/**< All fragmentation data */
-	rte_be32_t id;		/**< Packet ID */
-} __rte_packed;
-
-/* IPv6 fragment extension header size */
-#define RTE_IPV6_FRAG_HDR_SIZE	sizeof(struct rte_ipv6_fragment_ext)
-
-/**
- * Parse next IPv6 header extension
- *
- * This function checks if proto number is an IPv6 extensions and parses its
- * data if so, providing information on next header and extension length.
- *
- * @param p
- *   Pointer to an extension raw data.
- * @param proto
- *   Protocol number extracted from the "next header" field from
- *   the IPv6 header or the previous extension.
- * @param ext_len
- *   Extension data length.
- * @return
- *   next protocol number if proto is an IPv6 extension, -EINVAL otherwise
- */
-static inline int
-rte_ipv6_get_next_ext(const uint8_t *p, int proto, size_t *ext_len)
-{
-	int next_proto;
-
-	switch (proto) {
-	case IPPROTO_AH:
-		next_proto = *p++;
-		*ext_len = (*p + 2) * sizeof(uint32_t);
-		break;
-
-	case IPPROTO_HOPOPTS:
-	case IPPROTO_ROUTING:
-	case IPPROTO_DSTOPTS:
-		next_proto = *p++;
-		*ext_len = (*p + 1) * sizeof(uint64_t);
-		break;
-
-	case IPPROTO_FRAGMENT:
-		next_proto = *p;
-		*ext_len = RTE_IPV6_FRAG_HDR_SIZE;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return next_proto;
-}
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/net/rte_ip.h b/lib/net/rte_ip6.h
similarity index 50%
copy from lib/net/rte_ip.h
copy to lib/net/rte_ip6.h
index 0ae7c0565047..9ed737d5eb81 100644
--- a/lib/net/rte_ip.h
+++ b/lib/net/rte_ip6.h
@@ -6,13 +6,13 @@
  * All rights reserved.
  */
 
-#ifndef _RTE_IP_H_
-#define _RTE_IP_H_
+#ifndef _RTE_IP6_H_
+#define _RTE_IP6_H_
 
 /**
  * @file
  *
- * IP-related defines
+ * IPv6-related defines
  */
 
 #include <stdint.h>
@@ -24,7 +24,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <netinet/ip.h>
 #include <netinet/ip6.h>
 #endif
 
@@ -36,344 +35,6 @@
 extern "C" {
 #endif
 
-/**
- * IPv4 Header
- */
-struct rte_ipv4_hdr {
-	__extension__
-	union {
-		uint8_t version_ihl;    /**< version and header length */
-		struct {
-#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
-			uint8_t ihl:4;     /**< header length */
-			uint8_t version:4; /**< version */
-#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
-			uint8_t version:4; /**< version */
-			uint8_t ihl:4;     /**< header length */
-#endif
-		};
-	};
-	uint8_t  type_of_service;	/**< type of service */
-	rte_be16_t total_length;	/**< length of packet */
-	rte_be16_t packet_id;		/**< packet ID */
-	rte_be16_t fragment_offset;	/**< fragmentation offset */
-	uint8_t  time_to_live;		/**< time to live */
-	uint8_t  next_proto_id;		/**< protocol ID */
-	rte_be16_t hdr_checksum;	/**< header checksum */
-	rte_be32_t src_addr;		/**< source address */
-	rte_be32_t dst_addr;		/**< destination address */
-} __rte_packed;
-
-/** Create IPv4 address */
-#define RTE_IPV4(a, b, c, d) ((uint32_t)(((a) & 0xff) << 24) | \
-					   (((b) & 0xff) << 16) | \
-					   (((c) & 0xff) << 8)  | \
-					   ((d) & 0xff))
-
-/** Maximal IPv4 packet length (including a header) */
-#define RTE_IPV4_MAX_PKT_LEN        65535
-
-/** Internet header length mask for version_ihl field */
-#define RTE_IPV4_HDR_IHL_MASK	(0x0f)
-/**
- * Internet header length field multiplier (IHL field specifies overall header
- * length in number of 4-byte words)
- */
-#define RTE_IPV4_IHL_MULTIPLIER	(4)
-
-/* Type of Service fields */
-#define RTE_IPV4_HDR_DSCP_MASK	(0xfc)
-#define RTE_IPV4_HDR_ECN_MASK	(0x03)
-#define RTE_IPV4_HDR_ECN_CE	RTE_IPV4_HDR_ECN_MASK
-
-/* Fragment Offset * Flags. */
-#define	RTE_IPV4_HDR_DF_SHIFT	14
-#define	RTE_IPV4_HDR_MF_SHIFT	13
-#define	RTE_IPV4_HDR_FO_SHIFT	3
-
-#define	RTE_IPV4_HDR_DF_FLAG	(1 << RTE_IPV4_HDR_DF_SHIFT)
-#define	RTE_IPV4_HDR_MF_FLAG	(1 << RTE_IPV4_HDR_MF_SHIFT)
-
-#define	RTE_IPV4_HDR_OFFSET_MASK	((1 << RTE_IPV4_HDR_MF_SHIFT) - 1)
-
-#define	RTE_IPV4_HDR_OFFSET_UNITS	8
-
-/* IPv4 options */
-#define RTE_IPV4_HDR_OPT_EOL       0
-#define RTE_IPV4_HDR_OPT_NOP       1
-#define RTE_IPV4_HDR_OPT_COPIED(v) ((v) & 0x80)
-#define RTE_IPV4_HDR_OPT_MAX_LEN   40
-
-/*
- * IPv4 address types
- */
-#define RTE_IPV4_ANY              ((uint32_t)0x00000000) /**< 0.0.0.0 */
-#define RTE_IPV4_LOOPBACK         ((uint32_t)0x7f000001) /**< 127.0.0.1 */
-#define RTE_IPV4_BROADCAST        ((uint32_t)0xe0000000) /**< 224.0.0.0 */
-#define RTE_IPV4_ALLHOSTS_GROUP   ((uint32_t)0xe0000001) /**< 224.0.0.1 */
-#define RTE_IPV4_ALLRTRS_GROUP    ((uint32_t)0xe0000002) /**< 224.0.0.2 */
-#define RTE_IPV4_MAX_LOCAL_GROUP  ((uint32_t)0xe00000ff) /**< 224.0.0.255 */
-
-/*
- * IPv4 Multicast-related macros
- */
-#define RTE_IPV4_MIN_MCAST \
-	RTE_IPV4(224, 0, 0, 0)          /**< Minimal IPv4-multicast address */
-#define RTE_IPV4_MAX_MCAST \
-	RTE_IPV4(239, 255, 255, 255)    /**< Maximum IPv4 multicast address */
-
-#define RTE_IS_IPV4_MCAST(x) \
-	((x) >= RTE_IPV4_MIN_MCAST && (x) <= RTE_IPV4_MAX_MCAST)
-	/**< check if IPv4 address is multicast */
-
-/* IPv4 default fields values */
-#define RTE_IPV4_MIN_IHL    (0x5)
-#define RTE_IPV4_VHL_DEF    ((IPVERSION << 4) | RTE_IPV4_MIN_IHL)
-
-/**
- * Get the length of an IPv4 header.
- *
- * @param ipv4_hdr
- *   Pointer to the IPv4 header.
- * @return
- *   The length of the IPv4 header (with options if present) in bytes.
- */
-static inline uint8_t
-rte_ipv4_hdr_len(const struct rte_ipv4_hdr *ipv4_hdr)
-{
-	return (uint8_t)((ipv4_hdr->version_ihl & RTE_IPV4_HDR_IHL_MASK) *
-		RTE_IPV4_IHL_MULTIPLIER);
-}
-
-/**
- * Process the IPv4 checksum of an IPv4 header.
- *
- * The checksum field must be set to 0 by the caller.
- *
- * @param ipv4_hdr
- *   The pointer to the contiguous IPv4 header.
- * @return
- *   The complemented checksum to set in the IP packet.
- */
-static inline uint16_t
-rte_ipv4_cksum(const struct rte_ipv4_hdr *ipv4_hdr)
-{
-	uint16_t cksum;
-	cksum = rte_raw_cksum(ipv4_hdr, rte_ipv4_hdr_len(ipv4_hdr));
-	return (uint16_t)~cksum;
-}
-
-/**
- * Process the pseudo-header checksum of an IPv4 header.
- *
- * The checksum field must be set to 0 by the caller.
- *
- * Depending on the ol_flags, the pseudo-header checksum expected by the
- * drivers is not the same. For instance, when TSO is enabled, the IP
- * payload length must not be included in the packet.
- *
- * When ol_flags is 0, it computes the standard pseudo-header checksum.
- *
- * @param ipv4_hdr
- *   The pointer to the contiguous IPv4 header.
- * @param ol_flags
- *   The ol_flags of the associated mbuf.
- * @return
- *   The non-complemented checksum to set in the L4 header.
- */
-static inline uint16_t
-rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags)
-{
-	struct ipv4_psd_header {
-		uint32_t src_addr; /* IP address of source host. */
-		uint32_t dst_addr; /* IP address of destination host. */
-		uint8_t  zero;     /* zero. */
-		uint8_t  proto;    /* L4 protocol type. */
-		uint16_t len;      /* L4 length. */
-	} psd_hdr;
-
-	uint32_t l3_len;
-
-	psd_hdr.src_addr = ipv4_hdr->src_addr;
-	psd_hdr.dst_addr = ipv4_hdr->dst_addr;
-	psd_hdr.zero = 0;
-	psd_hdr.proto = ipv4_hdr->next_proto_id;
-	if (ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG)) {
-		psd_hdr.len = 0;
-	} else {
-		l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length);
-		psd_hdr.len = rte_cpu_to_be_16((uint16_t)(l3_len -
-			rte_ipv4_hdr_len(ipv4_hdr)));
-	}
-	return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr));
-}
-
-/**
- * @internal Calculate the non-complemented IPv4 L4 checksum
- */
-static inline uint16_t
-__rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr)
-{
-	uint32_t cksum;
-	uint32_t l3_len, l4_len;
-	uint8_t ip_hdr_len;
-
-	ip_hdr_len = rte_ipv4_hdr_len(ipv4_hdr);
-	l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length);
-	if (l3_len < ip_hdr_len)
-		return 0;
-
-	l4_len = l3_len - ip_hdr_len;
-
-	cksum = rte_raw_cksum(l4_hdr, l4_len);
-	cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0);
-
-	cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
-
-	return (uint16_t)cksum;
-}
-
-/**
- * Process the IPv4 UDP or TCP checksum.
- *
- * The layer 4 checksum must be set to 0 in the L4 header by the caller.
- *
- * @param ipv4_hdr
- *   The pointer to the contiguous IPv4 header.
- * @param l4_hdr
- *   The pointer to the beginning of the L4 header.
- * @return
- *   The complemented checksum to set in the L4 header.
- */
-static inline uint16_t
-rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr)
-{
-	uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr);
-
-	cksum = ~cksum;
-
-	/*
-	 * Per RFC 768: If the computed checksum is zero for UDP,
-	 * it is transmitted as all ones
-	 * (the equivalent in one's complement arithmetic).
-	 */
-	if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP)
-		cksum = 0xffff;
-
-	return cksum;
-}
-
-/**
- * @internal Calculate the non-complemented IPv4 L4 checksum of a packet
- */
-static inline uint16_t
-__rte_ipv4_udptcp_cksum_mbuf(const struct rte_mbuf *m,
-			     const struct rte_ipv4_hdr *ipv4_hdr,
-			     uint16_t l4_off)
-{
-	uint16_t raw_cksum;
-	uint32_t cksum;
-	uint16_t len;
-
-	if (unlikely(l4_off > m->pkt_len))
-		return 0; /* invalid params, return a dummy value */
-
-	len = rte_be_to_cpu_16(ipv4_hdr->total_length) - (uint16_t)rte_ipv4_hdr_len(ipv4_hdr);
-
-	if (rte_raw_cksum_mbuf(m, l4_off, len, &raw_cksum))
-		return 0;
-
-	cksum = raw_cksum + rte_ipv4_phdr_cksum(ipv4_hdr, 0);
-
-	cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
-
-	return (uint16_t)cksum;
-}
-
-/**
- * Compute the IPv4 UDP/TCP checksum of a packet.
- *
- * @param m
- *   The pointer to the mbuf.
- * @param ipv4_hdr
- *   The pointer to the contiguous IPv4 header.
- * @param l4_off
- *   The offset in bytes to start L4 checksum.
- * @return
- *   The complemented checksum to set in the L4 header.
- */
-static inline uint16_t
-rte_ipv4_udptcp_cksum_mbuf(const struct rte_mbuf *m,
-			   const struct rte_ipv4_hdr *ipv4_hdr, uint16_t l4_off)
-{
-	uint16_t cksum = __rte_ipv4_udptcp_cksum_mbuf(m, ipv4_hdr, l4_off);
-
-	cksum = ~cksum;
-
-	/*
-	 * Per RFC 768: If the computed checksum is zero for UDP,
-	 * it is transmitted as all ones
-	 * (the equivalent in one's complement arithmetic).
-	 */
-	if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP)
-		cksum = 0xffff;
-
-	return cksum;
-}
-
-/**
- * Validate the IPv4 UDP or TCP checksum.
- *
- * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0
- * (i.e. no checksum).
- *
- * @param ipv4_hdr
- *   The pointer to the contiguous IPv4 header.
- * @param l4_hdr
- *   The pointer to the beginning of the L4 header.
- * @return
- *   Return 0 if the checksum is correct, else -1.
- */
-static inline int
-rte_ipv4_udptcp_cksum_verify(const struct rte_ipv4_hdr *ipv4_hdr,
-			     const void *l4_hdr)
-{
-	uint16_t cksum = __rte_ipv4_udptcp_cksum(ipv4_hdr, l4_hdr);
-
-	if (cksum != 0xffff)
-		return -1;
-
-	return 0;
-}
-
-/**
- * Verify the IPv4 UDP/TCP checksum of a packet.
- *
- * In case of UDP, the caller must first check if udp_hdr->dgram_cksum is 0
- * (i.e. no checksum).
- *
- * @param m
- *   The pointer to the mbuf.
- * @param ipv4_hdr
- *   The pointer to the contiguous IPv4 header.
- * @param l4_off
- *   The offset in bytes to start L4 checksum.
- * @return
- *   Return 0 if the checksum is correct, else -1.
- */
-static inline int
-rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m,
-				  const struct rte_ipv4_hdr *ipv4_hdr,
-				  uint16_t l4_off)
-{
-	uint16_t cksum = __rte_ipv4_udptcp_cksum_mbuf(m, ipv4_hdr, l4_off);
-
-	if (cksum != 0xffff)
-		return -1;
-
-	return 0;
-}
-
 /**
  * IPv6 Header
  */
@@ -446,11 +107,10 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags)
 	} psd_hdr;
 
 	psd_hdr.proto = (uint32_t)(ipv6_hdr->proto << 24);
-	if (ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG)) {
+	if (ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG))
 		psd_hdr.len = 0;
-	} else {
+	else
 		psd_hdr.len = ipv6_hdr->payload_len;
-	}
 
 	sum = __rte_raw_cksum(ipv6_hdr->src_addr,
 		sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr),
@@ -697,4 +357,4 @@ rte_ipv6_get_next_ext(const uint8_t *p, int proto, size_t *ext_len)
 }
 #endif
 
-#endif /* _RTE_IP_H_ */
+#endif /* _RTE_IP6_H_ */
diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
index d680accc1631..13aef6147ab0 100644
--- a/lib/net/rte_net.c
+++ b/lib/net/rte_net.c
@@ -9,6 +9,7 @@
 #include <rte_byteorder.h>
 #include <rte_ether.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
 #include <rte_sctp.h>
diff --git a/lib/net/rte_net.h b/lib/net/rte_net.h
index cdc6cf956df2..a47beb60adf0 100644
--- a/lib/net/rte_net.h
+++ b/lib/net/rte_net.h
@@ -10,6 +10,7 @@ extern "C" {
 #endif
 
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_udp.h>
 #include <rte_tcp.h>
 
diff --git a/lib/pipeline/rte_swx_ipsec.c b/lib/pipeline/rte_swx_ipsec.c
index 73e8211b2818..56a401d0fa63 100644
--- a/lib/pipeline/rte_swx_ipsec.c
+++ b/lib/pipeline/rte_swx_ipsec.c
@@ -11,6 +11,7 @@
 #include <rte_common.h>
 #include <rte_random.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_tailq.h>
 #include <rte_eal_memconfig.h>
 #include <rte_ring.h>
diff --git a/lib/pipeline/rte_table_action.c b/lib/pipeline/rte_table_action.c
index 87c3e0e2c935..ebbdd3f4cebe 100644
--- a/lib/pipeline/rte_table_action.c
+++ b/lib/pipeline/rte_table_action.c
@@ -11,6 +11,7 @@
 #include <rte_memcpy.h>
 #include <rte_ether.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
 #include <rte_vxlan.h>
diff --git a/lib/vhost/virtio_net.c b/lib/vhost/virtio_net.c
index 370402d84903..d4dcc811c55f 100644
--- a/lib/vhost/virtio_net.c
+++ b/lib/vhost/virtio_net.c
@@ -11,6 +11,7 @@
 #include <rte_net.h>
 #include <rte_ether.h>
 #include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_dmadev.h>
 #include <rte_vhost.h>
 #include <rte_tcp.h>
-- 
2.46.0


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

* [PATCH dpdk v1 03/15] net: add structure for ipv6 addresses
  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 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 04/15] net: use ipv6 structure for header addresses Robin Jarry
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev

There is currently no structure defined for IPv6 addresses. Introduce
one that is simply a uint8_t array of 16 elements without any union. The
idea is to ensure this structure alignment is 1 so that it can be mapped
directly on unaligned packet memory.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 lib/net/rte_ip6.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/lib/net/rte_ip6.h b/lib/net/rte_ip6.h
index 9ed737d5eb81..f948f95db7ca 100644
--- a/lib/net/rte_ip6.h
+++ b/lib/net/rte_ip6.h
@@ -35,6 +35,16 @@
 extern "C" {
 #endif
 
+#define RTE_IPV6_ADDR_SIZE 16
+#define RTE_IPV6_MAX_DEPTH 128
+
+/**
+ * IPv6 Address
+ */
+struct rte_ipv6_addr {
+	unsigned char a[RTE_IPV6_ADDR_SIZE];
+};
+
 /**
  * IPv6 Header
  */
-- 
2.46.0


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

* [PATCH dpdk v1 04/15] net: use ipv6 structure for header addresses
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (2 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 03/15] net: add structure for ipv6 addresses Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 05/15] fib6,rib6,lpm6: use ipv6 addr struct Robin Jarry
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Wisam Jaddo, Cristian Dumitrescu, Konstantin Ananyev,
	Yipeng Wang, Sameh Gobriel, Bruce Richardson, Vladimir Medvedkin,
	Ajit Khaparde, Somnath Kotur, Chas Williams, Min Hu (Connor),
	Potnuri Bharat Teja, Hemant Agrawal, Sachin Saxena, Ziyang Xuan,
	Xiaoyun Wang, Jie Hai, Yisen Zhuang, Jingjing Wu,
	Dariusz Sosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
	Suanming Mou, Matan Azrad, Chaoyong He, Devendra Singh Rawat,
	Alok Prasad, Andrew Rybchenko, Stephen Hemminger, Jiawen Wu,
	Jian Wang, Radu Nicolau, Akhil Goyal, Thomas Monjalon,
	Ferruh Yigit, Nithin Dabilpuram, Pavan Nikhilesh

The rte_ipv6_hdr uses ad-hoc uint8_t[16] arrays to represent addresses.
Replace these arrays with the previously introduced rte_ipv6_addr
structure. Adapt all code accordingly.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test-flow-perf/items_gen.c           |  4 +--
 app/test-pipeline/pipeline_hash.c        |  4 +--
 app/test/packet_burst_generator.c        |  4 +--
 app/test/test_ipfrag.c                   |  4 +--
 app/test/test_reassembly_perf.c          | 20 +++++------
 app/test/test_thash.c                    |  8 ++---
 drivers/net/bnxt/bnxt_flow.c             | 12 +++----
 drivers/net/bonding/rte_eth_bond_pmd.c   |  4 +--
 drivers/net/cxgbe/cxgbe_flow.c           | 14 ++++----
 drivers/net/dpaa2/dpaa2_flow.c           | 22 ++++++------
 drivers/net/hinic/hinic_pmd_flow.c       |  6 ++--
 drivers/net/hinic/hinic_pmd_tx.c         |  2 +-
 drivers/net/hns3/hns3_flow.c             |  8 ++---
 drivers/net/i40e/i40e_flow.c             | 12 +++----
 drivers/net/iavf/iavf_fdir.c             |  8 ++---
 drivers/net/iavf/iavf_fsub.c             |  8 ++---
 drivers/net/iavf/iavf_ipsec_crypto.c     |  6 ++--
 drivers/net/ice/ice_fdir_filter.c        | 12 +++----
 drivers/net/ice/ice_switch_filter.c      | 16 ++++-----
 drivers/net/igc/igc_flow.c               |  4 +--
 drivers/net/ixgbe/ixgbe_flow.c           | 12 +++----
 drivers/net/ixgbe/ixgbe_ipsec.c          |  4 +--
 drivers/net/mlx5/hws/mlx5dr_definer.c    | 36 +++++++++----------
 drivers/net/mlx5/mlx5_flow.c             |  6 ++--
 drivers/net/mlx5/mlx5_flow_dv.c          | 16 +++++----
 drivers/net/mlx5/mlx5_flow_hw.c          | 10 +++---
 drivers/net/mlx5/mlx5_flow_verbs.c       |  8 ++---
 drivers/net/nfp/flower/nfp_flower_flow.c | 34 ++++++++++--------
 drivers/net/nfp/nfp_net_flow.c           | 44 +++++++++++++-----------
 drivers/net/qede/qede_filter.c           |  4 +--
 drivers/net/sfc/sfc_flow.c               | 28 +++++++--------
 drivers/net/tap/tap_flow.c               |  8 ++---
 drivers/net/txgbe/txgbe_flow.c           | 12 +++----
 drivers/net/txgbe/txgbe_ipsec.c          |  4 +--
 examples/ip_fragmentation/main.c         |  2 +-
 examples/ip_pipeline/pipeline.c          | 16 ++++-----
 examples/ip_reassembly/main.c            |  2 +-
 examples/ipsec-secgw/flow.c              | 12 +++----
 examples/ipsec-secgw/ipsec.c             |  8 ++---
 examples/ipsec-secgw/sa.c                |  4 +--
 examples/ipsec-secgw/sad.h               | 10 +++---
 examples/l3fwd/l3fwd_fib.c               |  2 +-
 examples/l3fwd/l3fwd_lpm.c               |  4 +--
 lib/ethdev/rte_flow.h                    |  6 ++--
 lib/hash/rte_thash.h                     | 12 +++----
 lib/ip_frag/rte_ipv6_reassembly.c        |  4 +--
 lib/net/rte_ip6.h                        |  6 ++--
 lib/node/ip6_lookup.c                    | 10 +++---
 lib/pipeline/rte_swx_ipsec.c             |  6 ++--
 lib/pipeline/rte_table_action.c          | 24 ++++++-------
 50 files changed, 276 insertions(+), 256 deletions(-)

diff --git a/app/test-flow-perf/items_gen.c b/app/test-flow-perf/items_gen.c
index 4ae72509d445..c740e1838ffb 100644
--- a/app/test-flow-perf/items_gen.c
+++ b/app/test-flow-perf/items_gen.c
@@ -78,8 +78,8 @@ add_ipv6(struct rte_flow_item *items,
 	for (i = 0; i < 16; i++) {
 		/* Currently src_ip is limited to 32 bit */
 		if (i < 4)
-			ipv6_specs[ti].hdr.src_addr[15 - i] = para.src_ip >> (i * 8);
-		ipv6_masks[ti].hdr.src_addr[15 - i] = 0xff;
+			ipv6_specs[ti].hdr.src_addr.a[15 - i] = para.src_ip >> (i * 8);
+		ipv6_masks[ti].hdr.src_addr.a[15 - i] = 0xff;
 	}
 
 	items[items_counter].type = RTE_FLOW_ITEM_TYPE_IPV6;
diff --git a/app/test-pipeline/pipeline_hash.c b/app/test-pipeline/pipeline_hash.c
index cab9c2098014..194e5c5dcc53 100644
--- a/app/test-pipeline/pipeline_hash.c
+++ b/app/test-pipeline/pipeline_hash.c
@@ -432,7 +432,6 @@ app_main_loop_rx_metadata(void) {
 				struct rte_ipv4_hdr *ip_hdr;
 				struct rte_ipv6_hdr *ipv6_hdr;
 				uint32_t ip_dst;
-				uint8_t *ipv6_dst;
 				uint32_t *signature, *k32;
 
 				m = app.mbuf_rx.array[j];
@@ -452,9 +451,8 @@ app_main_loop_rx_metadata(void) {
 				} else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
 					ipv6_hdr = (struct rte_ipv6_hdr *)
 						&m_data[sizeof(struct rte_ether_hdr)];
-					ipv6_dst = ipv6_hdr->dst_addr;
 
-					memcpy(key, ipv6_dst, 16);
+					memcpy(key, &ipv6_hdr->dst_addr, 16);
 				} else
 					continue;
 
diff --git a/app/test/packet_burst_generator.c b/app/test/packet_burst_generator.c
index 2cd34abc1a65..76a409a56452 100644
--- a/app/test/packet_burst_generator.c
+++ b/app/test/packet_burst_generator.c
@@ -149,8 +149,8 @@ initialize_ipv6_header(struct rte_ipv6_hdr *ip_hdr, uint8_t *src_addr,
 	ip_hdr->proto = IPPROTO_UDP;
 	ip_hdr->hop_limits = IP_DEFTTL;
 
-	rte_memcpy(ip_hdr->src_addr, src_addr, sizeof(ip_hdr->src_addr));
-	rte_memcpy(ip_hdr->dst_addr, dst_addr, sizeof(ip_hdr->dst_addr));
+	rte_memcpy(&ip_hdr->src_addr, src_addr, sizeof(ip_hdr->src_addr));
+	rte_memcpy(&ip_hdr->dst_addr, dst_addr, sizeof(ip_hdr->dst_addr));
 
 	return (uint16_t) (pkt_data_len + sizeof(struct rte_ipv6_hdr));
 }
diff --git a/app/test/test_ipfrag.c b/app/test/test_ipfrag.c
index 8e4df220a214..4053bd9f0f79 100644
--- a/app/test/test_ipfrag.c
+++ b/app/test/test_ipfrag.c
@@ -238,8 +238,8 @@ v6_allocate_packet_of(struct rte_mbuf *b, int fill, size_t s, uint8_t ttl,
 	hdr->proto = proto;
 	hdr->hop_limits = ttl;
 
-	memset(hdr->src_addr, 0x08, sizeof(hdr->src_addr));
-	memset(hdr->dst_addr, 0x04, sizeof(hdr->src_addr));
+	memset(hdr->src_addr.a, 0x08, sizeof(hdr->src_addr));
+	memset(hdr->dst_addr.a, 0x04, sizeof(hdr->src_addr));
 }
 
 static inline void
diff --git a/app/test/test_reassembly_perf.c b/app/test/test_reassembly_perf.c
index 3912179022fc..70112c1f62da 100644
--- a/app/test/test_reassembly_perf.c
+++ b/app/test/test_reassembly_perf.c
@@ -340,17 +340,17 @@ ipv6_frag_fill_data(struct rte_mbuf **mbuf, uint8_t nb_frags, uint32_t flow_id,
 			rte_cpu_to_be_16(pkt_len - sizeof(struct rte_ipv6_hdr));
 		ip_hdr->proto = IPPROTO_FRAGMENT;
 		ip_hdr->hop_limits = IP_DEFTTL;
-		memcpy(ip_hdr->src_addr, ip6_addr, sizeof(ip_hdr->src_addr));
-		memcpy(ip_hdr->dst_addr, ip6_addr, sizeof(ip_hdr->dst_addr));
-		ip_hdr->src_addr[7] = (flow_id >> 16) & 0xf;
-		ip_hdr->src_addr[7] |= 0x10;
-		ip_hdr->src_addr[8] = (flow_id >> 8) & 0xff;
-		ip_hdr->src_addr[9] = flow_id & 0xff;
+		memcpy(&ip_hdr->src_addr, ip6_addr, sizeof(ip_hdr->src_addr));
+		memcpy(&ip_hdr->dst_addr, ip6_addr, sizeof(ip_hdr->dst_addr));
+		ip_hdr->src_addr.a[7] = (flow_id >> 16) & 0xf;
+		ip_hdr->src_addr.a[7] |= 0x10;
+		ip_hdr->src_addr.a[8] = (flow_id >> 8) & 0xff;
+		ip_hdr->src_addr.a[9] = flow_id & 0xff;
 
-		ip_hdr->dst_addr[7] = (flow_id >> 16) & 0xf;
-		ip_hdr->dst_addr[7] |= 0x20;
-		ip_hdr->dst_addr[8] = (flow_id >> 8) & 0xff;
-		ip_hdr->dst_addr[9] = flow_id & 0xff;
+		ip_hdr->dst_addr.a[7] = (flow_id >> 16) & 0xf;
+		ip_hdr->dst_addr.a[7] |= 0x20;
+		ip_hdr->dst_addr.a[8] = (flow_id >> 8) & 0xff;
+		ip_hdr->dst_addr.a[9] = flow_id & 0xff;
 
 		frag_hdr->next_header = IPPROTO_UDP;
 		frag_hdr->reserved = 0;
diff --git a/app/test/test_thash.c b/app/test/test_thash.c
index 65d42fd90085..952da6a52954 100644
--- a/app/test/test_thash.c
+++ b/app/test/test_thash.c
@@ -145,10 +145,10 @@ test_toeplitz_hash_calc(void)
 	}
 	for (i = 0; i < RTE_DIM(v6_tbl); i++) {
 		/*Fill ipv6 hdr*/
-		for (j = 0; j < RTE_DIM(ipv6_hdr.src_addr); j++)
-			ipv6_hdr.src_addr[j] = v6_tbl[i].src_ip[j];
-		for (j = 0; j < RTE_DIM(ipv6_hdr.dst_addr); j++)
-			ipv6_hdr.dst_addr[j] = v6_tbl[i].dst_ip[j];
+		for (j = 0; j < RTE_DIM(ipv6_hdr.src_addr.a); j++)
+			ipv6_hdr.src_addr.a[j] = v6_tbl[i].src_ip[j];
+		for (j = 0; j < RTE_DIM(ipv6_hdr.dst_addr.a); j++)
+			ipv6_hdr.dst_addr.a[j] = v6_tbl[i].dst_ip[j];
 		/*Load and convert ipv6 address into tuple*/
 		rte_thash_load_v6_addrs(&ipv6_hdr, &tuple);
 		tuple.v6.sport = v6_tbl[i].src_port;
diff --git a/drivers/net/bnxt/bnxt_flow.c b/drivers/net/bnxt/bnxt_flow.c
index f25bc6ff78c7..bdc47ee78755 100644
--- a/drivers/net/bnxt/bnxt_flow.c
+++ b/drivers/net/bnxt/bnxt_flow.c
@@ -424,22 +424,22 @@ bnxt_validate_and_parse_flow_type(const struct rte_flow_attr *attr,
 					EM_FLOW_ALLOC_INPUT_EN_DST_IPADDR;
 
 			rte_memcpy(filter->src_ipaddr,
-				   ipv6_spec->hdr.src_addr, 16);
+				   &ipv6_spec->hdr.src_addr, 16);
 			rte_memcpy(filter->dst_ipaddr,
-				   ipv6_spec->hdr.dst_addr, 16);
+				   &ipv6_spec->hdr.dst_addr, 16);
 
-			if (!bnxt_check_zero_bytes(ipv6_mask->hdr.src_addr,
+			if (!bnxt_check_zero_bytes(ipv6_mask->hdr.src_addr.a,
 						   16)) {
 				rte_memcpy(filter->src_ipaddr_mask,
-					   ipv6_mask->hdr.src_addr, 16);
+					   &ipv6_mask->hdr.src_addr, 16);
 				en |= !use_ntuple ? 0 :
 				    NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
 			}
 
-			if (!bnxt_check_zero_bytes(ipv6_mask->hdr.dst_addr,
+			if (!bnxt_check_zero_bytes(ipv6_mask->hdr.dst_addr.a,
 						   16)) {
 				rte_memcpy(filter->dst_ipaddr_mask,
-					   ipv6_mask->hdr.dst_addr, 16);
+					   &ipv6_mask->hdr.dst_addr, 16);
 				en |= !use_ntuple ? 0 :
 				     NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
 			}
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index c40d18d128b6..b89732f4a28a 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -690,9 +690,9 @@ static inline uint32_t
 ipv6_hash(struct rte_ipv6_hdr *ipv6_hdr)
 {
 	unaligned_uint32_t *word_src_addr =
-		(unaligned_uint32_t *)&(ipv6_hdr->src_addr[0]);
+		(unaligned_uint32_t *)&ipv6_hdr->src_addr;
 	unaligned_uint32_t *word_dst_addr =
-		(unaligned_uint32_t *)&(ipv6_hdr->dst_addr[0]);
+		(unaligned_uint32_t *)&ipv6_hdr->dst_addr;
 
 	return (word_src_addr[0] ^ word_dst_addr[0]) ^
 			(word_src_addr[1] ^ word_dst_addr[1]) ^
diff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c
index f5787c247f1f..37c566b131e9 100644
--- a/drivers/net/cxgbe/cxgbe_flow.c
+++ b/drivers/net/cxgbe/cxgbe_flow.c
@@ -411,15 +411,15 @@ ch_rte_parsetype_ipv6(const void *dmask, const struct rte_flow_item *item,
 			      RTE_IPV6_HDR_TC_SHIFT,
 			      tos);
 
-	if (memcmp(val->hdr.dst_addr, z, sizeof(val->hdr.dst_addr)) ||
+	if (memcmp(&val->hdr.dst_addr, z, sizeof(val->hdr.dst_addr)) ||
 	    (umask &&
-	     memcmp(umask->hdr.dst_addr, z, sizeof(umask->hdr.dst_addr))))
+	     memcmp(&umask->hdr.dst_addr, z, sizeof(umask->hdr.dst_addr))))
 		CXGBE_FILL_FS_MEMCPY(val->hdr.dst_addr, mask->hdr.dst_addr,
 				     lip);
 
-	if (memcmp(val->hdr.src_addr, z, sizeof(val->hdr.src_addr)) ||
+	if (memcmp(&val->hdr.src_addr, z, sizeof(val->hdr.src_addr)) ||
 	    (umask &&
-	     memcmp(umask->hdr.src_addr, z, sizeof(umask->hdr.src_addr))))
+	     memcmp(&umask->hdr.src_addr, z, sizeof(umask->hdr.src_addr))))
 		CXGBE_FILL_FS_MEMCPY(val->hdr.src_addr, mask->hdr.src_addr,
 				     fip);
 
@@ -918,12 +918,14 @@ static struct chrte_fparse parseitem[] = {
 		.fptr  = ch_rte_parsetype_ipv6,
 		.dmask = &(const struct rte_flow_item_ipv6) {
 			.hdr = {
-				.src_addr =
+				.src_addr = { .a =
 					"\xff\xff\xff\xff\xff\xff\xff\xff"
 					"\xff\xff\xff\xff\xff\xff\xff\xff",
-				.dst_addr =
+				},
+				.dst_addr = { .a =
 					"\xff\xff\xff\xff\xff\xff\xff\xff"
 					"\xff\xff\xff\xff\xff\xff\xff\xff",
+				},
 				.vtc_flow = RTE_BE32(0xff000000),
 			},
 		},
diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c
index 6c7bac4d483a..5f762d319477 100644
--- a/drivers/net/dpaa2/dpaa2_flow.c
+++ b/drivers/net/dpaa2/dpaa2_flow.c
@@ -117,12 +117,14 @@ static const struct rte_flow_item_ipv4 dpaa2_flow_item_ipv4_mask = {
 
 static const struct rte_flow_item_ipv6 dpaa2_flow_item_ipv6_mask = {
 	.hdr = {
-		.src_addr =
+		.src_addr = { .a =
 			"\xff\xff\xff\xff\xff\xff\xff\xff"
 			"\xff\xff\xff\xff\xff\xff\xff\xff",
-		.dst_addr =
+		},
+		.dst_addr = { .a =
 			"\xff\xff\xff\xff\xff\xff\xff\xff"
 			"\xff\xff\xff\xff\xff\xff\xff\xff",
+		},
 		.proto = 0xff
 	},
 };
@@ -1480,16 +1482,16 @@ dpaa2_configure_flow_generic_ip(
 		mask_ipv4->hdr.dst_addr)) {
 		flow->ipaddr_rule.ipaddr_type = FLOW_IPV4_ADDR;
 	} else if (mask_ipv6 &&
-		(memcmp((const char *)mask_ipv6->hdr.src_addr,
+		(memcmp(&mask_ipv6->hdr.src_addr,
 				zero_cmp, NH_FLD_IPV6_ADDR_SIZE) ||
-		memcmp((const char *)mask_ipv6->hdr.dst_addr,
+		memcmp(&mask_ipv6->hdr.dst_addr,
 				zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
 		flow->ipaddr_rule.ipaddr_type = FLOW_IPV6_ADDR;
 	}
 
 	if ((mask_ipv4 && mask_ipv4->hdr.src_addr) ||
 		(mask_ipv6 &&
-			memcmp((const char *)mask_ipv6->hdr.src_addr,
+			memcmp(&mask_ipv6->hdr.src_addr,
 				zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
 		index = dpaa2_flow_extract_search(
 				&priv->extract.qos_key_extract.dpkg,
@@ -1528,13 +1530,13 @@ dpaa2_configure_flow_generic_ip(
 		if (spec_ipv4)
 			key = &spec_ipv4->hdr.src_addr;
 		else
-			key = &spec_ipv6->hdr.src_addr[0];
+			key = &spec_ipv6->hdr.src_addr;
 		if (mask_ipv4) {
 			mask = &mask_ipv4->hdr.src_addr;
 			size = NH_FLD_IPV4_ADDR_SIZE;
 			prot = NET_PROT_IPV4;
 		} else {
-			mask = &mask_ipv6->hdr.src_addr[0];
+			mask = &mask_ipv6->hdr.src_addr;
 			size = NH_FLD_IPV6_ADDR_SIZE;
 			prot = NET_PROT_IPV6;
 		}
@@ -1571,7 +1573,7 @@ dpaa2_configure_flow_generic_ip(
 
 	if ((mask_ipv4 && mask_ipv4->hdr.dst_addr) ||
 		(mask_ipv6 &&
-			memcmp((const char *)mask_ipv6->hdr.dst_addr,
+			memcmp(&mask_ipv6->hdr.dst_addr,
 				zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
 		index = dpaa2_flow_extract_search(
 				&priv->extract.qos_key_extract.dpkg,
@@ -1618,13 +1620,13 @@ dpaa2_configure_flow_generic_ip(
 		if (spec_ipv4)
 			key = &spec_ipv4->hdr.dst_addr;
 		else
-			key = spec_ipv6->hdr.dst_addr;
+			key = &spec_ipv6->hdr.dst_addr;
 		if (mask_ipv4) {
 			mask = &mask_ipv4->hdr.dst_addr;
 			size = NH_FLD_IPV4_ADDR_SIZE;
 			prot = NET_PROT_IPV4;
 		} else {
-			mask = &mask_ipv6->hdr.dst_addr[0];
+			mask = &mask_ipv6->hdr.dst_addr;
 			size = NH_FLD_IPV6_ADDR_SIZE;
 			prot = NET_PROT_IPV6;
 		}
diff --git a/drivers/net/hinic/hinic_pmd_flow.c b/drivers/net/hinic/hinic_pmd_flow.c
index d1a564a16303..8fdd5a35be9f 100644
--- a/drivers/net/hinic/hinic_pmd_flow.c
+++ b/drivers/net/hinic/hinic_pmd_flow.c
@@ -962,7 +962,7 @@ static int hinic_normal_item_check_ip(const struct rte_flow_item **in_out_item,
 
 		/* check ipv6 src addr mask, ipv6 src addr is 16 bytes */
 		for (i = 0; i < 16; i++) {
-			if (ipv6_mask->hdr.src_addr[i] == UINT8_MAX) {
+			if (ipv6_mask->hdr.src_addr.a[i] == UINT8_MAX) {
 				rte_flow_error_set(error, EINVAL,
 					RTE_FLOW_ERROR_TYPE_ITEM, item,
 					"Not supported by fdir filter, do not support src ipv6");
@@ -978,13 +978,13 @@ static int hinic_normal_item_check_ip(const struct rte_flow_item **in_out_item,
 		}
 
 		for (i = 0; i < 16; i++) {
-			if (ipv6_mask->hdr.dst_addr[i] == UINT8_MAX)
+			if (ipv6_mask->hdr.dst_addr.a[i] == UINT8_MAX)
 				rule->mask.dst_ipv6_mask |= 1 << i;
 		}
 
 		ipv6_spec = (const struct rte_flow_item_ipv6 *)item->spec;
 		rte_memcpy(rule->hinic_fdir.dst_ipv6,
-			   ipv6_spec->hdr.dst_addr, 16);
+			   &ipv6_spec->hdr.dst_addr, 16);
 
 		/*
 		 * Check if the next not void item is TCP or UDP or ICMP.
diff --git a/drivers/net/hinic/hinic_pmd_tx.c b/drivers/net/hinic/hinic_pmd_tx.c
index f09b1a6e1ea6..22fb0bffafcc 100644
--- a/drivers/net/hinic/hinic_pmd_tx.c
+++ b/drivers/net/hinic/hinic_pmd_tx.c
@@ -743,7 +743,7 @@ hinic_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags)
 	else
 		psd_hdr.len = ipv6_hdr->payload_len;
 
-	sum = __rte_raw_cksum(ipv6_hdr->src_addr,
+	sum = __rte_raw_cksum(&ipv6_hdr->src_addr,
 		sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr), 0);
 	sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum);
 	return __rte_raw_cksum_reduce(sum);
diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c
index 37eb2b4c3807..bf1eee506dde 100644
--- a/drivers/net/hns3/hns3_flow.c
+++ b/drivers/net/hns3/hns3_flow.c
@@ -822,10 +822,10 @@ hns3_parse_ipv6(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 						  "Only support src & dst ip,proto in IPV6");
 		}
 		net_addr_to_host(rule->key_conf.mask.src_ip,
-				 (const rte_be32_t *)ipv6_mask->hdr.src_addr,
+				 (const rte_be32_t *)&ipv6_mask->hdr.src_addr,
 				 IP_ADDR_LEN);
 		net_addr_to_host(rule->key_conf.mask.dst_ip,
-				 (const rte_be32_t *)ipv6_mask->hdr.dst_addr,
+				 (const rte_be32_t *)&ipv6_mask->hdr.dst_addr,
 				 IP_ADDR_LEN);
 		rule->key_conf.mask.ip_proto = ipv6_mask->hdr.proto;
 		if (rule->key_conf.mask.src_ip[IP_ADDR_KEY_ID])
@@ -838,10 +838,10 @@ hns3_parse_ipv6(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	ipv6_spec = item->spec;
 	net_addr_to_host(rule->key_conf.spec.src_ip,
-			 (const rte_be32_t *)ipv6_spec->hdr.src_addr,
+			 (const rte_be32_t *)&ipv6_spec->hdr.src_addr,
 			 IP_ADDR_LEN);
 	net_addr_to_host(rule->key_conf.spec.dst_ip,
-			 (const rte_be32_t *)ipv6_spec->hdr.dst_addr,
+			 (const rte_be32_t *)&ipv6_spec->hdr.dst_addr,
 			 IP_ADDR_LEN);
 	rule->key_conf.spec.ip_proto = ipv6_spec->hdr.proto;
 
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 92165c8422d5..c6857727e8be 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -1953,13 +1953,13 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 					return -rte_errno;
 				}
 
-				if (!memcmp(ipv6_mask->hdr.src_addr,
+				if (!memcmp(&ipv6_mask->hdr.src_addr,
 					    ipv6_addr_mask,
-					    RTE_DIM(ipv6_mask->hdr.src_addr)))
+					    sizeof(ipv6_mask->hdr.src_addr)))
 					input_set |= I40E_INSET_IPV6_SRC;
-				if (!memcmp(ipv6_mask->hdr.dst_addr,
+				if (!memcmp(&ipv6_mask->hdr.dst_addr,
 					    ipv6_addr_mask,
-					    RTE_DIM(ipv6_mask->hdr.dst_addr)))
+					    sizeof(ipv6_mask->hdr.dst_addr)))
 					input_set |= I40E_INSET_IPV6_DST;
 
 				if ((ipv6_mask->hdr.vtc_flow &
@@ -1987,9 +1987,9 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 					I40E_FDIR_IPTYPE_IPV6;
 
 				rte_memcpy(filter->input.flow.ipv6_flow.src_ip,
-					   ipv6_spec->hdr.src_addr, 16);
+					   &ipv6_spec->hdr.src_addr, 16);
 				rte_memcpy(filter->input.flow.ipv6_flow.dst_ip,
-					   ipv6_spec->hdr.dst_addr, 16);
+					   &ipv6_spec->hdr.dst_addr, 16);
 
 				/* Check if it is fragment. */
 				if (ipv6_spec->hdr.proto ==
diff --git a/drivers/net/iavf/iavf_fdir.c b/drivers/net/iavf/iavf_fdir.c
index 811a10287b70..321346425465 100644
--- a/drivers/net/iavf/iavf_fdir.c
+++ b/drivers/net/iavf/iavf_fdir.c
@@ -1048,14 +1048,14 @@ iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter *ad,
 								 HOP_LIMIT);
 			}
 
-			if (!memcmp(ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    RTE_DIM(ipv6_mask->hdr.src_addr))) {
+			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
+				    sizeof(ipv6_mask->hdr.src_addr))) {
 				input_set |= IAVF_INSET_IPV6_SRC;
 				VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6,
 								 SRC);
 			}
-			if (!memcmp(ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    RTE_DIM(ipv6_mask->hdr.dst_addr))) {
+			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
+				    sizeof(ipv6_mask->hdr.dst_addr))) {
 				input_set |= IAVF_INSET_IPV6_DST;
 				VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6,
 								 DST);
diff --git a/drivers/net/iavf/iavf_fsub.c b/drivers/net/iavf/iavf_fsub.c
index 74e1e7099b8c..eb5a3feab189 100644
--- a/drivers/net/iavf/iavf_fsub.c
+++ b/drivers/net/iavf/iavf_fsub.c
@@ -354,23 +354,23 @@ iavf_fsub_parse_pattern(const struct rte_flow_item pattern[],
 				}
 
 				for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
-					if (ipv6_mask->hdr.src_addr[j]) {
+					if (ipv6_mask->hdr.src_addr.a[j]) {
 						*input |= IAVF_INSET_IPV6_SRC;
 						break;
 					}
 				}
 				for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
-					if (ipv6_mask->hdr.dst_addr[j]) {
+					if (ipv6_mask->hdr.dst_addr.a[j]) {
 						*input |= IAVF_INSET_IPV6_DST;
 						break;
 					}
 				}
 
 				for (j = 0; j < IAVF_IPV6_ADDR_LENGTH; j++) {
-					if (ipv6_mask->hdr.src_addr[j])
+					if (ipv6_mask->hdr.src_addr.a[j])
 						input_set_byte++;
 
-					if (ipv6_mask->hdr.dst_addr[j])
+					if (ipv6_mask->hdr.dst_addr.a[j])
 						input_set_byte++;
 				}
 
diff --git a/drivers/net/iavf/iavf_ipsec_crypto.c b/drivers/net/iavf/iavf_ipsec_crypto.c
index 6fd45ff45f3d..17bea5880aa3 100644
--- a/drivers/net/iavf/iavf_ipsec_crypto.c
+++ b/drivers/net/iavf/iavf_ipsec_crypto.c
@@ -1738,8 +1738,8 @@ static void
 parse_ipv6_item(const struct rte_flow_item_ipv6 *item,
 		struct rte_ipv6_hdr *ipv6)
 {
-	memcpy(ipv6->src_addr, item->hdr.src_addr, 16);
-	memcpy(ipv6->dst_addr, item->hdr.dst_addr, 16);
+	memcpy(&ipv6->src_addr, &item->hdr.src_addr, 16);
+	memcpy(&ipv6->dst_addr, &item->hdr.dst_addr, 16);
 }
 
 static void
@@ -1904,7 +1904,7 @@ iavf_ipsec_flow_create(struct iavf_adapter *ad,
 			ipsec_flow->spi,
 			0,
 			0,
-			ipsec_flow->ipv6_hdr.dst_addr,
+			ipsec_flow->ipv6_hdr.dst_addr.a,
 			0,
 			ipsec_flow->is_udp,
 			ipsec_flow->udp_hdr.dst_port);
diff --git a/drivers/net/ice/ice_fdir_filter.c b/drivers/net/ice/ice_fdir_filter.c
index edd8cc8f1ab4..8c85779b5401 100644
--- a/drivers/net/ice/ice_fdir_filter.c
+++ b/drivers/net/ice/ice_fdir_filter.c
@@ -2097,11 +2097,11 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				return -rte_errno;
 			}
 
-			if (!memcmp(ipv6_mask->hdr.src_addr, ipv6_addr_mask,
-				    RTE_DIM(ipv6_mask->hdr.src_addr)))
+			if (!memcmp(&ipv6_mask->hdr.src_addr, ipv6_addr_mask,
+				    sizeof(ipv6_mask->hdr.src_addr)))
 				*input_set |= ICE_INSET_IPV6_SRC;
-			if (!memcmp(ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
-				    RTE_DIM(ipv6_mask->hdr.dst_addr)))
+			if (!memcmp(&ipv6_mask->hdr.dst_addr, ipv6_addr_mask,
+				    sizeof(ipv6_mask->hdr.dst_addr)))
 				*input_set |= ICE_INSET_IPV6_DST;
 
 			if ((ipv6_mask->hdr.vtc_flow &
@@ -2113,8 +2113,8 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
 				*input_set |= ICE_INSET_IPV6_HOP_LIMIT;
 
-			rte_memcpy(&p_v6->dst_ip, ipv6_spec->hdr.dst_addr, 16);
-			rte_memcpy(&p_v6->src_ip, ipv6_spec->hdr.src_addr, 16);
+			rte_memcpy(&p_v6->dst_ip, &ipv6_spec->hdr.dst_addr, 16);
+			rte_memcpy(&p_v6->src_ip, &ipv6_spec->hdr.src_addr, 16);
 			vtc_flow_cpu = rte_be_to_cpu_32(ipv6_spec->hdr.vtc_flow);
 			p_v6->tc = (uint8_t)(vtc_flow_cpu >> ICE_FDIR_IPV6_TC_OFFSET);
 			p_v6->proto = ipv6_spec->hdr.proto;
diff --git a/drivers/net/ice/ice_switch_filter.c b/drivers/net/ice/ice_switch_filter.c
index 122b87f625a7..28bc775a2c34 100644
--- a/drivers/net/ice/ice_switch_filter.c
+++ b/drivers/net/ice/ice_switch_filter.c
@@ -665,13 +665,13 @@ ice_switch_parse_pattern(const struct rte_flow_item pattern[],
 				}
 
 				for (j = 0; j < ICE_IPV6_ADDR_LENGTH; j++) {
-					if (ipv6_mask->hdr.src_addr[j]) {
+					if (ipv6_mask->hdr.src_addr.a[j]) {
 						*input |= ICE_INSET_IPV6_SRC;
 						break;
 					}
 				}
 				for (j = 0; j < ICE_IPV6_ADDR_LENGTH; j++) {
-					if (ipv6_mask->hdr.dst_addr[j]) {
+					if (ipv6_mask->hdr.dst_addr.a[j]) {
 						*input |= ICE_INSET_IPV6_DST;
 						break;
 					}
@@ -691,18 +691,18 @@ ice_switch_parse_pattern(const struct rte_flow_item pattern[],
 				f = &list[t].h_u.ipv6_hdr;
 				s = &list[t].m_u.ipv6_hdr;
 				for (j = 0; j < ICE_IPV6_ADDR_LENGTH; j++) {
-					if (ipv6_mask->hdr.src_addr[j]) {
+					if (ipv6_mask->hdr.src_addr.a[j]) {
 						f->src_addr[j] =
-						ipv6_spec->hdr.src_addr[j];
+						ipv6_spec->hdr.src_addr.a[j];
 						s->src_addr[j] =
-						ipv6_mask->hdr.src_addr[j];
+						ipv6_mask->hdr.src_addr.a[j];
 						input_set_byte++;
 					}
-					if (ipv6_mask->hdr.dst_addr[j]) {
+					if (ipv6_mask->hdr.dst_addr.a[j]) {
 						f->dst_addr[j] =
-						ipv6_spec->hdr.dst_addr[j];
+						ipv6_spec->hdr.dst_addr.a[j];
 						s->dst_addr[j] =
-						ipv6_mask->hdr.dst_addr[j];
+						ipv6_mask->hdr.dst_addr.a[j];
 						input_set_byte++;
 					}
 				}
diff --git a/drivers/net/igc/igc_flow.c b/drivers/net/igc/igc_flow.c
index b677a0d61340..b778ac26135a 100644
--- a/drivers/net/igc/igc_flow.c
+++ b/drivers/net/igc/igc_flow.c
@@ -435,8 +435,8 @@ igc_parse_pattern_ipv6(const struct rte_flow_item *item,
 	if (mask->hdr.vtc_flow ||
 		mask->hdr.payload_len ||
 		mask->hdr.hop_limits ||
-		!igc_is_zero_ipv6_addr(mask->hdr.src_addr) ||
-		!igc_is_zero_ipv6_addr(mask->hdr.dst_addr))
+		!igc_is_zero_ipv6_addr(&mask->hdr.src_addr) ||
+		!igc_is_zero_ipv6_addr(&mask->hdr.dst_addr))
 		return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ITEM, item,
 				"IPv6 only support protocol");
diff --git a/drivers/net/ixgbe/ixgbe_flow.c b/drivers/net/ixgbe/ixgbe_flow.c
index 687341c6b8d3..1b35ed5faabe 100644
--- a/drivers/net/ixgbe/ixgbe_flow.c
+++ b/drivers/net/ixgbe/ixgbe_flow.c
@@ -1917,9 +1917,9 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev,
 
 		/* check src addr mask */
 		for (j = 0; j < 16; j++) {
-			if (ipv6_mask->hdr.src_addr[j] == 0) {
+			if (ipv6_mask->hdr.src_addr.a[j] == 0) {
 				rule->mask.src_ipv6_mask &= ~(1 << j);
-			} else if (ipv6_mask->hdr.src_addr[j] != UINT8_MAX) {
+			} else if (ipv6_mask->hdr.src_addr.a[j] != UINT8_MAX) {
 				memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
 				rte_flow_error_set(error, EINVAL,
 					RTE_FLOW_ERROR_TYPE_ITEM,
@@ -1930,9 +1930,9 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev,
 
 		/* check dst addr mask */
 		for (j = 0; j < 16; j++) {
-			if (ipv6_mask->hdr.dst_addr[j] == 0) {
+			if (ipv6_mask->hdr.dst_addr.a[j] == 0) {
 				rule->mask.dst_ipv6_mask &= ~(1 << j);
-			} else if (ipv6_mask->hdr.dst_addr[j] != UINT8_MAX) {
+			} else if (ipv6_mask->hdr.dst_addr.a[j] != UINT8_MAX) {
 				memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
 				rte_flow_error_set(error, EINVAL,
 					RTE_FLOW_ERROR_TYPE_ITEM,
@@ -1945,9 +1945,9 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev,
 			rule->b_spec = TRUE;
 			ipv6_spec = item->spec;
 			rte_memcpy(rule->ixgbe_fdir.formatted.src_ip,
-				   ipv6_spec->hdr.src_addr, 16);
+				   &ipv6_spec->hdr.src_addr, 16);
 			rte_memcpy(rule->ixgbe_fdir.formatted.dst_ip,
-				   ipv6_spec->hdr.dst_addr, 16);
+				   &ipv6_spec->hdr.dst_addr, 16);
 		}
 
 		/**
diff --git a/drivers/net/ixgbe/ixgbe_ipsec.c b/drivers/net/ixgbe/ixgbe_ipsec.c
index d3313085560d..7615a19911ba 100644
--- a/drivers/net/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ixgbe/ixgbe_ipsec.c
@@ -681,9 +681,9 @@ ixgbe_crypto_add_ingress_sa_from_flow(const void *sess,
 			ic_session->src_ip.type = IPv6;
 			ic_session->dst_ip.type = IPv6;
 			rte_memcpy(ic_session->src_ip.ipv6,
-				   ipv6->hdr.src_addr, 16);
+				   &ipv6->hdr.src_addr, 16);
 			rte_memcpy(ic_session->dst_ip.ipv6,
-				   ipv6->hdr.dst_addr, 16);
+				   &ipv6->hdr.dst_addr, 16);
 		} else {
 			const struct rte_flow_item_ipv4 *ipv4 = ip_spec;
 			ic_session->src_ip.type = IPv4;
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c b/drivers/net/mlx5/hws/mlx5dr_definer.c
index 51a3f7be4b75..7326d2cf42a5 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.c
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.c
@@ -176,14 +176,14 @@ struct mlx5dr_definer_conv_data {
 	X(SET,		ipv6_proto,		v->hdr.proto,		rte_flow_item_ipv6) \
 	X(SET,		ipv6_routing_hdr,	IPPROTO_ROUTING,	rte_flow_item_ipv6) \
 	X(SET,		ipv6_hop_limits,	v->hdr.hop_limits,	rte_flow_item_ipv6) \
-	X(SET_BE32P,	ipv6_src_addr_127_96,	&v->hdr.src_addr[0],	rte_flow_item_ipv6) \
-	X(SET_BE32P,	ipv6_src_addr_95_64,	&v->hdr.src_addr[4],	rte_flow_item_ipv6) \
-	X(SET_BE32P,	ipv6_src_addr_63_32,	&v->hdr.src_addr[8],	rte_flow_item_ipv6) \
-	X(SET_BE32P,	ipv6_src_addr_31_0,	&v->hdr.src_addr[12],	rte_flow_item_ipv6) \
-	X(SET_BE32P,	ipv6_dst_addr_127_96,	&v->hdr.dst_addr[0],	rte_flow_item_ipv6) \
-	X(SET_BE32P,	ipv6_dst_addr_95_64,	&v->hdr.dst_addr[4],	rte_flow_item_ipv6) \
-	X(SET_BE32P,	ipv6_dst_addr_63_32,	&v->hdr.dst_addr[8],	rte_flow_item_ipv6) \
-	X(SET_BE32P,	ipv6_dst_addr_31_0,	&v->hdr.dst_addr[12],	rte_flow_item_ipv6) \
+	X(SET_BE32P,	ipv6_src_addr_127_96,	&v->hdr.src_addr.a[0],	rte_flow_item_ipv6) \
+	X(SET_BE32P,	ipv6_src_addr_95_64,	&v->hdr.src_addr.a[4],	rte_flow_item_ipv6) \
+	X(SET_BE32P,	ipv6_src_addr_63_32,	&v->hdr.src_addr.a[8],	rte_flow_item_ipv6) \
+	X(SET_BE32P,	ipv6_src_addr_31_0,	&v->hdr.src_addr.a[12],	rte_flow_item_ipv6) \
+	X(SET_BE32P,	ipv6_dst_addr_127_96,	&v->hdr.dst_addr.a[0],	rte_flow_item_ipv6) \
+	X(SET_BE32P,	ipv6_dst_addr_95_64,	&v->hdr.dst_addr.a[4],	rte_flow_item_ipv6) \
+	X(SET_BE32P,	ipv6_dst_addr_63_32,	&v->hdr.dst_addr.a[8],	rte_flow_item_ipv6) \
+	X(SET_BE32P,	ipv6_dst_addr_31_0,	&v->hdr.dst_addr.a[12],	rte_flow_item_ipv6) \
 	X(SET,		ipv6_version,		STE_IPV6,		rte_flow_item_ipv6) \
 	X(SET,		ipv6_frag,		v->has_frag_ext,	rte_flow_item_ipv6) \
 	X(SET,		icmp_protocol,		STE_ICMP,		rte_flow_item_icmp) \
@@ -1161,8 +1161,8 @@ mlx5dr_definer_conv_item_ipv6(struct mlx5dr_definer_conv_data *cd,
 	    m->has_esp_ext || m->has_dest_ext || m->has_mobil_ext ||
 	    m->has_hip_ext || m->has_shim6_ext ||
 	    (l && (l->has_frag_ext || l->hdr.vtc_flow || l->hdr.proto ||
-		   !is_mem_zero(l->hdr.src_addr, 16) ||
-		   !is_mem_zero(l->hdr.dst_addr, 16)))) {
+		   !is_mem_zero(l->hdr.src_addr.a, 16) ||
+		   !is_mem_zero(l->hdr.dst_addr.a, 16)))) {
 		rte_errno = ENOTSUP;
 		return rte_errno;
 	}
@@ -1219,56 +1219,56 @@ mlx5dr_definer_conv_item_ipv6(struct mlx5dr_definer_conv_data *cd,
 		DR_CALC_SET(fc, eth_l3, time_to_live_hop_limit, inner);
 	}
 
-	if (!is_mem_zero(m->hdr.src_addr, 4)) {
+	if (!is_mem_zero(m->hdr.src_addr.a, 4)) {
 		fc = &cd->fc[DR_CALC_FNAME(IPV6_SRC_127_96, inner)];
 		fc->item_idx = item_idx;
 		fc->tag_set = &mlx5dr_definer_ipv6_src_addr_127_96_set;
 		DR_CALC_SET(fc, ipv6_src, ipv6_address_127_96, inner);
 	}
 
-	if (!is_mem_zero(m->hdr.src_addr + 4, 4)) {
+	if (!is_mem_zero(m->hdr.src_addr.a + 4, 4)) {
 		fc = &cd->fc[DR_CALC_FNAME(IPV6_SRC_95_64, inner)];
 		fc->item_idx = item_idx;
 		fc->tag_set = &mlx5dr_definer_ipv6_src_addr_95_64_set;
 		DR_CALC_SET(fc, ipv6_src, ipv6_address_95_64, inner);
 	}
 
-	if (!is_mem_zero(m->hdr.src_addr + 8, 4)) {
+	if (!is_mem_zero(m->hdr.src_addr.a + 8, 4)) {
 		fc = &cd->fc[DR_CALC_FNAME(IPV6_SRC_63_32, inner)];
 		fc->item_idx = item_idx;
 		fc->tag_set = &mlx5dr_definer_ipv6_src_addr_63_32_set;
 		DR_CALC_SET(fc, ipv6_src, ipv6_address_63_32, inner);
 	}
 
-	if (!is_mem_zero(m->hdr.src_addr + 12, 4)) {
+	if (!is_mem_zero(m->hdr.src_addr.a + 12, 4)) {
 		fc = &cd->fc[DR_CALC_FNAME(IPV6_SRC_31_0, inner)];
 		fc->item_idx = item_idx;
 		fc->tag_set = &mlx5dr_definer_ipv6_src_addr_31_0_set;
 		DR_CALC_SET(fc, ipv6_src, ipv6_address_31_0, inner);
 	}
 
-	if (!is_mem_zero(m->hdr.dst_addr, 4)) {
+	if (!is_mem_zero(m->hdr.dst_addr.a, 4)) {
 		fc = &cd->fc[DR_CALC_FNAME(IPV6_DST_127_96, inner)];
 		fc->item_idx = item_idx;
 		fc->tag_set = &mlx5dr_definer_ipv6_dst_addr_127_96_set;
 		DR_CALC_SET(fc, ipv6_dst, ipv6_address_127_96, inner);
 	}
 
-	if (!is_mem_zero(m->hdr.dst_addr + 4, 4)) {
+	if (!is_mem_zero(m->hdr.dst_addr.a + 4, 4)) {
 		fc = &cd->fc[DR_CALC_FNAME(IPV6_DST_95_64, inner)];
 		fc->item_idx = item_idx;
 		fc->tag_set = &mlx5dr_definer_ipv6_dst_addr_95_64_set;
 		DR_CALC_SET(fc, ipv6_dst, ipv6_address_95_64, inner);
 	}
 
-	if (!is_mem_zero(m->hdr.dst_addr + 8, 4)) {
+	if (!is_mem_zero(m->hdr.dst_addr.a + 8, 4)) {
 		fc = &cd->fc[DR_CALC_FNAME(IPV6_DST_63_32, inner)];
 		fc->item_idx = item_idx;
 		fc->tag_set = &mlx5dr_definer_ipv6_dst_addr_63_32_set;
 		DR_CALC_SET(fc, ipv6_dst, ipv6_address_63_32, inner);
 	}
 
-	if (!is_mem_zero(m->hdr.dst_addr + 12, 4)) {
+	if (!is_mem_zero(m->hdr.dst_addr.a + 12, 4)) {
 		fc = &cd->fc[DR_CALC_FNAME(IPV6_DST_31_0, inner)];
 		fc->item_idx = item_idx;
 		fc->tag_set = &mlx5dr_definer_ipv6_dst_addr_31_0_set;
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 72fb3a55baf4..ba03a246fc84 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2933,12 +2933,14 @@ mlx5_flow_validate_item_ipv6(const struct rte_eth_dev *dev,
 	const struct rte_flow_item_ipv6 *spec = item->spec;
 	const struct rte_flow_item_ipv6 nic_mask = {
 		.hdr = {
-			.src_addr =
+			.src_addr = { .a =
 				"\xff\xff\xff\xff\xff\xff\xff\xff"
 				"\xff\xff\xff\xff\xff\xff\xff\xff",
-			.dst_addr =
+			},
+			.dst_addr = { .a =
 				"\xff\xff\xff\xff\xff\xff\xff\xff"
 				"\xff\xff\xff\xff\xff\xff\xff\xff",
+			},
 			.vtc_flow = RTE_BE32(0xffffffff),
 			.proto = 0xff,
 		},
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 89057edbcfc2..30b9dd898ffc 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -7697,12 +7697,14 @@ const struct rte_flow_item_ipv4 nic_ipv4_mask = {
 
 const struct rte_flow_item_ipv6 nic_ipv6_mask = {
 	.hdr = {
-		.src_addr =
+		.src_addr = { .a =
 		"\xff\xff\xff\xff\xff\xff\xff\xff"
 		"\xff\xff\xff\xff\xff\xff\xff\xff",
-		.dst_addr =
+		},
+		.dst_addr = { .a =
 		"\xff\xff\xff\xff\xff\xff\xff\xff"
 		"\xff\xff\xff\xff\xff\xff\xff\xff",
+		},
 		.vtc_flow = RTE_BE32(0xffffffff),
 		.proto = 0xff,
 		.hop_limits = 0xff,
@@ -9549,12 +9551,14 @@ flow_dv_translate_item_ipv6(void *key, const struct rte_flow_item *item,
 	const struct rte_flow_item_ipv6 *ipv6_v;
 	const struct rte_flow_item_ipv6 nic_mask = {
 		.hdr = {
-			.src_addr =
+			.src_addr = { .a =
 				"\xff\xff\xff\xff\xff\xff\xff\xff"
 				"\xff\xff\xff\xff\xff\xff\xff\xff",
-			.dst_addr =
+			},
+			.dst_addr = { .a =
 				"\xff\xff\xff\xff\xff\xff\xff\xff"
 				"\xff\xff\xff\xff\xff\xff\xff\xff",
+			},
 			.vtc_flow = RTE_BE32(0xffffffff),
 			.proto = 0xff,
 			.hop_limits = 0xff,
@@ -9577,11 +9581,11 @@ flow_dv_translate_item_ipv6(void *key, const struct rte_flow_item *item,
 	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 			     dst_ipv4_dst_ipv6.ipv6_layout.ipv6);
 	for (i = 0; i < size; ++i)
-		l24_v[i] = ipv6_m->hdr.dst_addr[i] & ipv6_v->hdr.dst_addr[i];
+		l24_v[i] = ipv6_m->hdr.dst_addr.a[i] & ipv6_v->hdr.dst_addr.a[i];
 	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 			     src_ipv4_src_ipv6.ipv6_layout.ipv6);
 	for (i = 0; i < size; ++i)
-		l24_v[i] = ipv6_m->hdr.src_addr[i] & ipv6_v->hdr.src_addr[i];
+		l24_v[i] = ipv6_m->hdr.src_addr.a[i] & ipv6_v->hdr.src_addr.a[i];
 	/* TOS. */
 	vtc_v = rte_be_to_cpu_32(ipv6_m->hdr.vtc_flow & ipv6_v->hdr.vtc_flow);
 	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, vtc_v >> 20);
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index d243b59b71cd..1b6c79a3f332 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -8250,12 +8250,14 @@ const struct rte_flow_item_ipv6 hws_nic_ipv6_mask = {
 		.payload_len = RTE_BE16(0xffff),
 		.proto = 0xff,
 		.hop_limits = 0xff,
-		.src_addr =
+		.src_addr = { .a =
 		"\xff\xff\xff\xff\xff\xff\xff\xff"
 		"\xff\xff\xff\xff\xff\xff\xff\xff",
-		.dst_addr =
+		},
+		.dst_addr = { .a =
 		"\xff\xff\xff\xff\xff\xff\xff\xff"
 		"\xff\xff\xff\xff\xff\xff\xff\xff",
+		},
 	},
 	.has_frag_ext = 1,
 };
@@ -14645,10 +14647,10 @@ flow_hw_calc_encap_hash(struct rte_eth_dev *dev,
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
 			memcpy(data.dst.ipv6_addr,
-			       ((const struct rte_flow_item_ipv6 *)(pattern->spec))->hdr.dst_addr,
+			       &((const struct rte_flow_item_ipv6 *)(pattern->spec))->hdr.dst_addr,
 			       sizeof(data.dst.ipv6_addr));
 			memcpy(data.src.ipv6_addr,
-			       ((const struct rte_flow_item_ipv6 *)(pattern->spec))->hdr.src_addr,
+			       &((const struct rte_flow_item_ipv6 *)(pattern->spec))->hdr.src_addr,
 			       sizeof(data.src.ipv6_addr));
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 3a4356c0f650..5b4a4eda3bbc 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -600,13 +600,13 @@ flow_verbs_translate_item_ipv6(struct mlx5_flow *dev_flow,
 		uint32_t vtc_flow_val;
 		uint32_t vtc_flow_mask;
 
-		memcpy(&ipv6.val.src_ip, spec->hdr.src_addr,
+		memcpy(&ipv6.val.src_ip, &spec->hdr.src_addr,
 		       RTE_DIM(ipv6.val.src_ip));
-		memcpy(&ipv6.val.dst_ip, spec->hdr.dst_addr,
+		memcpy(&ipv6.val.dst_ip, &spec->hdr.dst_addr,
 		       RTE_DIM(ipv6.val.dst_ip));
-		memcpy(&ipv6.mask.src_ip, mask->hdr.src_addr,
+		memcpy(&ipv6.mask.src_ip, &mask->hdr.src_addr,
 		       RTE_DIM(ipv6.mask.src_ip));
-		memcpy(&ipv6.mask.dst_ip, mask->hdr.dst_addr,
+		memcpy(&ipv6.mask.dst_ip, &mask->hdr.dst_addr,
 		       RTE_DIM(ipv6.mask.dst_ip));
 		vtc_flow_val = rte_be_to_cpu_32(spec->hdr.vtc_flow);
 		vtc_flow_mask = rte_be_to_cpu_32(mask->hdr.vtc_flow);
diff --git a/drivers/net/nfp/flower/nfp_flower_flow.c b/drivers/net/nfp/flower/nfp_flower_flow.c
index 0078455658ac..3f597d394b24 100644
--- a/drivers/net/nfp/flower/nfp_flower_flow.c
+++ b/drivers/net/nfp/flower/nfp_flower_flow.c
@@ -2027,18 +2027,18 @@ nfp_flow_merge_ipv6(struct nfp_flow_merge_param *param)
 
 			ipv6_gre_tun->ip_ext.tos = vtc_flow >> RTE_IPV6_HDR_TC_SHIFT;
 			ipv6_gre_tun->ip_ext.ttl = hdr->hop_limits;
-			memcpy(ipv6_gre_tun->ipv6.ipv6_src, hdr->src_addr,
+			memcpy(ipv6_gre_tun->ipv6.ipv6_src, &hdr->src_addr,
 					sizeof(ipv6_gre_tun->ipv6.ipv6_src));
-			memcpy(ipv6_gre_tun->ipv6.ipv6_dst, hdr->dst_addr,
+			memcpy(ipv6_gre_tun->ipv6.ipv6_dst, &hdr->dst_addr,
 					sizeof(ipv6_gre_tun->ipv6.ipv6_dst));
 		} else {
 			ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)(*param->mbuf_off);
 
 			ipv6_udp_tun->ip_ext.tos = vtc_flow >> RTE_IPV6_HDR_TC_SHIFT;
 			ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
-			memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
+			memcpy(ipv6_udp_tun->ipv6.ipv6_src, &hdr->src_addr,
 					sizeof(ipv6_udp_tun->ipv6.ipv6_src));
-			memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
+			memcpy(ipv6_udp_tun->ipv6.ipv6_dst, &hdr->dst_addr,
 					sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
 		}
 	} else {
@@ -2061,8 +2061,8 @@ nfp_flow_merge_ipv6(struct nfp_flow_merge_param *param)
 		ipv6->ip_ext.tos   = vtc_flow >> RTE_IPV6_HDR_TC_SHIFT;
 		ipv6->ip_ext.proto = hdr->proto;
 		ipv6->ip_ext.ttl   = hdr->hop_limits;
-		memcpy(ipv6->ipv6_src, hdr->src_addr, sizeof(ipv6->ipv6_src));
-		memcpy(ipv6->ipv6_dst, hdr->dst_addr, sizeof(ipv6->ipv6_dst));
+		memcpy(ipv6->ipv6_src, &hdr->src_addr, sizeof(ipv6->ipv6_src));
+		memcpy(ipv6->ipv6_dst, &hdr->dst_addr, sizeof(ipv6->ipv6_dst));
 
 ipv6_end:
 		*param->mbuf_off += sizeof(struct nfp_flower_ipv6);
@@ -2518,10 +2518,14 @@ static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 				.vtc_flow   = RTE_BE32(0x0ff00000),
 				.proto      = 0xff,
 				.hop_limits = 0xff,
-				.src_addr   = "\xff\xff\xff\xff\xff\xff\xff\xff"
+				.src_addr   = { .a =
+					"\xff\xff\xff\xff\xff\xff\xff\xff"
 					"\xff\xff\xff\xff\xff\xff\xff\xff",
-				.dst_addr   = "\xff\xff\xff\xff\xff\xff\xff\xff"
+				},
+				.dst_addr   = { .a =
+					"\xff\xff\xff\xff\xff\xff\xff\xff"
 					"\xff\xff\xff\xff\xff\xff\xff\xff",
+				},
 			},
 			.has_frag_ext = 1,
 		},
@@ -3324,8 +3328,8 @@ nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
 	struct nfp_flower_cmsg_tun_neigh_v6 payload;
 
 	tun->payload.v6_flag = 1;
-	memcpy(tun->payload.dst.dst_ipv6, ipv6->hdr.dst_addr, sizeof(tun->payload.dst.dst_ipv6));
-	memcpy(tun->payload.src.src_ipv6, ipv6->hdr.src_addr, sizeof(tun->payload.src.src_ipv6));
+	memcpy(tun->payload.dst.dst_ipv6, &ipv6->hdr.dst_addr, sizeof(tun->payload.dst.dst_ipv6));
+	memcpy(tun->payload.src.src_ipv6, &ipv6->hdr.src_addr, sizeof(tun->payload.src.src_ipv6));
 	memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
 	memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
 
@@ -3345,8 +3349,8 @@ nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
 			sizeof(struct nfp_flower_meta_tci));
 
 	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
-	memcpy(payload.dst_ipv6, ipv6->hdr.dst_addr, sizeof(payload.dst_ipv6));
-	memcpy(payload.src_ipv6, ipv6->hdr.src_addr, sizeof(payload.src_ipv6));
+	memcpy(payload.dst_ipv6, &ipv6->hdr.dst_addr, sizeof(payload.dst_ipv6));
+	memcpy(payload.src_ipv6, &ipv6->hdr.src_addr, sizeof(payload.src_ipv6));
 	memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
 	memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
 	payload.common.port_id = port->in_port;
@@ -3573,7 +3577,7 @@ nfp_flow_action_vxlan_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
 
 	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
 	memset(pre_tun, 0, act_pre_size);
-	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr.a);
 
 	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
 	memset(set_tun, 0, act_set_size);
@@ -3944,7 +3948,7 @@ nfp_flow_action_geneve_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
 
 	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
 	memset(pre_tun, 0, act_pre_size);
-	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr.a);
 
 	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
 	memset(set_tun, 0, act_set_size);
@@ -4021,7 +4025,7 @@ nfp_flow_action_nvgre_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
 
 	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
 	memset(pre_tun, 0, act_pre_size);
-	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr.a);
 
 	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
 	memset(set_tun, 0, act_set_size);
diff --git a/drivers/net/nfp/nfp_net_flow.c b/drivers/net/nfp/nfp_net_flow.c
index 2c7801ed41f4..aa3fa08ddf25 100644
--- a/drivers/net/nfp/nfp_net_flow.c
+++ b/drivers/net/nfp/nfp_net_flow.c
@@ -294,28 +294,28 @@ nfp_net_flow_merge_ipv6(struct rte_flow *nfp_flow,
 
 	ipv6->l4_protocol_mask = mask->hdr.proto;
 	for (i = 0; i < sizeof(ipv6->src_ipv6); i += 4) {
-		ipv6->src_ipv6_mask[i] = mask->hdr.src_addr[i + 3];
-		ipv6->src_ipv6_mask[i + 1] = mask->hdr.src_addr[i + 2];
-		ipv6->src_ipv6_mask[i + 2] = mask->hdr.src_addr[i + 1];
-		ipv6->src_ipv6_mask[i + 3] = mask->hdr.src_addr[i];
+		ipv6->src_ipv6_mask[i] = mask->hdr.src_addr.a[i + 3];
+		ipv6->src_ipv6_mask[i + 1] = mask->hdr.src_addr.a[i + 2];
+		ipv6->src_ipv6_mask[i + 2] = mask->hdr.src_addr.a[i + 1];
+		ipv6->src_ipv6_mask[i + 3] = mask->hdr.src_addr.a[i];
 
-		ipv6->dst_ipv6_mask[i] = mask->hdr.dst_addr[i + 3];
-		ipv6->dst_ipv6_mask[i + 1] = mask->hdr.dst_addr[i + 2];
-		ipv6->dst_ipv6_mask[i + 2] = mask->hdr.dst_addr[i + 1];
-		ipv6->dst_ipv6_mask[i + 3] = mask->hdr.dst_addr[i];
+		ipv6->dst_ipv6_mask[i] = mask->hdr.dst_addr.a[i + 3];
+		ipv6->dst_ipv6_mask[i + 1] = mask->hdr.dst_addr.a[i + 2];
+		ipv6->dst_ipv6_mask[i + 2] = mask->hdr.dst_addr.a[i + 1];
+		ipv6->dst_ipv6_mask[i + 3] = mask->hdr.dst_addr.a[i];
 	}
 
 	ipv6->l4_protocol = spec->hdr.proto;
 	for (i = 0; i < sizeof(ipv6->src_ipv6); i += 4) {
-		ipv6->src_ipv6[i] = spec->hdr.src_addr[i + 3];
-		ipv6->src_ipv6[i + 1] = spec->hdr.src_addr[i + 2];
-		ipv6->src_ipv6[i + 2] = spec->hdr.src_addr[i + 1];
-		ipv6->src_ipv6[i + 3] = spec->hdr.src_addr[i];
+		ipv6->src_ipv6[i] = spec->hdr.src_addr.a[i + 3];
+		ipv6->src_ipv6[i + 1] = spec->hdr.src_addr.a[i + 2];
+		ipv6->src_ipv6[i + 2] = spec->hdr.src_addr.a[i + 1];
+		ipv6->src_ipv6[i + 3] = spec->hdr.src_addr.a[i];
 
-		ipv6->dst_ipv6[i] = spec->hdr.dst_addr[i + 3];
-		ipv6->dst_ipv6[i + 1] = spec->hdr.dst_addr[i + 2];
-		ipv6->dst_ipv6[i + 2] = spec->hdr.dst_addr[i + 1];
-		ipv6->dst_ipv6[i + 3] = spec->hdr.dst_addr[i];
+		ipv6->dst_ipv6[i] = spec->hdr.dst_addr.a[i + 3];
+		ipv6->dst_ipv6[i + 1] = spec->hdr.dst_addr.a[i + 2];
+		ipv6->dst_ipv6[i + 2] = spec->hdr.dst_addr.a[i + 1];
+		ipv6->dst_ipv6[i + 3] = spec->hdr.dst_addr.a[i];
 	}
 
 	return 0;
@@ -403,10 +403,14 @@ static const struct nfp_net_flow_item_proc nfp_net_flow_item_proc_list[] = {
 		.mask_support = &(const struct rte_flow_item_ipv6){
 			.hdr = {
 				.proto    = 0xff,
-				.src_addr = "\xff\xff\xff\xff\xff\xff\xff\xff"
-						"\xff\xff\xff\xff\xff\xff\xff\xff",
-				.dst_addr = "\xff\xff\xff\xff\xff\xff\xff\xff"
-						"\xff\xff\xff\xff\xff\xff\xff\xff",
+				.src_addr = { .a =
+					"\xff\xff\xff\xff\xff\xff\xff\xff"
+					"\xff\xff\xff\xff\xff\xff\xff\xff",
+				},
+				.dst_addr = { .a =
+					"\xff\xff\xff\xff\xff\xff\xff\xff"
+					"\xff\xff\xff\xff\xff\xff\xff\xff",
+				},
 			},
 		},
 		.mask_default = &rte_flow_item_ipv6_mask,
diff --git a/drivers/net/qede/qede_filter.c b/drivers/net/qede/qede_filter.c
index d98266eac55c..14fb4338e9c7 100644
--- a/drivers/net/qede/qede_filter.c
+++ b/drivers/net/qede/qede_filter.c
@@ -794,9 +794,9 @@ qede_flow_parse_pattern(__rte_unused struct rte_eth_dev *dev,
 
 				spec = pattern->spec;
 				memcpy(flow->entry.tuple.src_ipv6,
-				       spec->hdr.src_addr, IPV6_ADDR_LEN);
+				       &spec->hdr.src_addr, IPV6_ADDR_LEN);
 				memcpy(flow->entry.tuple.dst_ipv6,
-				       spec->hdr.dst_addr, IPV6_ADDR_LEN);
+				       &spec->hdr.dst_addr, IPV6_ADDR_LEN);
 				flow->entry.tuple.eth_proto =
 					RTE_ETHER_TYPE_IPV6;
 			}
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 1b50aefe5c48..0a812d9928ab 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -575,14 +575,14 @@ sfc_flow_parse_ipv6(const struct rte_flow_item *item,
 	const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6);
 	const struct rte_flow_item_ipv6 supp_mask = {
 		.hdr = {
-			.src_addr = { 0xff, 0xff, 0xff, 0xff,
-				      0xff, 0xff, 0xff, 0xff,
-				      0xff, 0xff, 0xff, 0xff,
-				      0xff, 0xff, 0xff, 0xff },
-			.dst_addr = { 0xff, 0xff, 0xff, 0xff,
-				      0xff, 0xff, 0xff, 0xff,
-				      0xff, 0xff, 0xff, 0xff,
-				      0xff, 0xff, 0xff, 0xff },
+			.src_addr = { .a =
+				"\xff\xff\xff\xff\xff\xff\xff\xff"
+				"\xff\xff\xff\xff\xff\xff\xff\xff",
+			},
+			.dst_addr = { .a =
+				"\xff\xff\xff\xff\xff\xff\xff\xff"
+				"\xff\xff\xff\xff\xff\xff\xff\xff",
+			},
 			.proto = 0xff,
 		}
 	};
@@ -618,28 +618,28 @@ sfc_flow_parse_ipv6(const struct rte_flow_item *item,
 	 * IPv6 addresses are in big-endian byte order in item and in
 	 * efx_spec
 	 */
-	if (memcmp(mask->hdr.src_addr, supp_mask.hdr.src_addr,
+	if (memcmp(&mask->hdr.src_addr, &supp_mask.hdr.src_addr,
 		   sizeof(mask->hdr.src_addr)) == 0) {
 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
 
 		RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) !=
 				 sizeof(spec->hdr.src_addr));
-		rte_memcpy(&efx_spec->efs_rem_host, spec->hdr.src_addr,
+		rte_memcpy(&efx_spec->efs_rem_host, &spec->hdr.src_addr,
 			   sizeof(efx_spec->efs_rem_host));
-	} else if (!sfc_flow_is_zero(mask->hdr.src_addr,
+	} else if (!sfc_flow_is_zero(mask->hdr.src_addr.a,
 				     sizeof(mask->hdr.src_addr))) {
 		goto fail_bad_mask;
 	}
 
-	if (memcmp(mask->hdr.dst_addr, supp_mask.hdr.dst_addr,
+	if (memcmp(&mask->hdr.dst_addr, &supp_mask.hdr.dst_addr,
 		   sizeof(mask->hdr.dst_addr)) == 0) {
 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
 
 		RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) !=
 				 sizeof(spec->hdr.dst_addr));
-		rte_memcpy(&efx_spec->efs_loc_host, spec->hdr.dst_addr,
+		rte_memcpy(&efx_spec->efs_loc_host, &spec->hdr.dst_addr,
 			   sizeof(efx_spec->efs_loc_host));
-	} else if (!sfc_flow_is_zero(mask->hdr.dst_addr,
+	} else if (!sfc_flow_is_zero(mask->hdr.dst_addr.a,
 				     sizeof(mask->hdr.dst_addr))) {
 		goto fail_bad_mask;
 	}
diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c
index 0a90c0487b46..8f5a8d64587b 100644
--- a/drivers/net/tap/tap_flow.c
+++ b/drivers/net/tap/tap_flow.c
@@ -209,11 +209,11 @@ static const struct tap_flow_items tap_flow_items[] = {
 			       RTE_FLOW_ITEM_TYPE_TCP),
 		.mask = &(const struct rte_flow_item_ipv6){
 			.hdr = {
-				.src_addr = {
+				.src_addr = { .a =
 					"\xff\xff\xff\xff\xff\xff\xff\xff"
 					"\xff\xff\xff\xff\xff\xff\xff\xff",
 				},
-				.dst_addr = {
+				.dst_addr = { .a =
 					"\xff\xff\xff\xff\xff\xff\xff\xff"
 					"\xff\xff\xff\xff\xff\xff\xff\xff",
 				},
@@ -617,13 +617,13 @@ tap_flow_create_ipv6(const struct rte_flow_item *item, void *data)
 		info->eth_type = htons(ETH_P_IPV6);
 	if (!spec)
 		return 0;
-	if (memcmp(mask->hdr.dst_addr, empty_addr, 16)) {
+	if (memcmp(&mask->hdr.dst_addr, empty_addr, 16)) {
 		tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_DST,
 			   sizeof(spec->hdr.dst_addr), &spec->hdr.dst_addr);
 		tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_DST_MASK,
 			   sizeof(mask->hdr.dst_addr), &mask->hdr.dst_addr);
 	}
-	if (memcmp(mask->hdr.src_addr, empty_addr, 16)) {
+	if (memcmp(&mask->hdr.src_addr, empty_addr, 16)) {
 		tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_SRC,
 			   sizeof(spec->hdr.src_addr), &spec->hdr.src_addr);
 		tap_nlattr_add(&msg->nh, TCA_FLOWER_KEY_IPV6_SRC_MASK,
diff --git a/drivers/net/txgbe/txgbe_flow.c b/drivers/net/txgbe/txgbe_flow.c
index 7ef52d0b0fcd..5d2dd453687c 100644
--- a/drivers/net/txgbe/txgbe_flow.c
+++ b/drivers/net/txgbe/txgbe_flow.c
@@ -1807,9 +1807,9 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev __rte_unused,
 
 		/* check src addr mask */
 		for (j = 0; j < 16; j++) {
-			if (ipv6_mask->hdr.src_addr[j] == UINT8_MAX) {
+			if (ipv6_mask->hdr.src_addr.a[j] == UINT8_MAX) {
 				rule->mask.src_ipv6_mask |= 1 << j;
-			} else if (ipv6_mask->hdr.src_addr[j] != 0) {
+			} else if (ipv6_mask->hdr.src_addr.a[j] != 0) {
 				memset(rule, 0, sizeof(struct txgbe_fdir_rule));
 				rte_flow_error_set(error, EINVAL,
 					RTE_FLOW_ERROR_TYPE_ITEM,
@@ -1820,9 +1820,9 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev __rte_unused,
 
 		/* check dst addr mask */
 		for (j = 0; j < 16; j++) {
-			if (ipv6_mask->hdr.dst_addr[j] == UINT8_MAX) {
+			if (ipv6_mask->hdr.dst_addr.a[j] == UINT8_MAX) {
 				rule->mask.dst_ipv6_mask |= 1 << j;
-			} else if (ipv6_mask->hdr.dst_addr[j] != 0) {
+			} else if (ipv6_mask->hdr.dst_addr.a[j] != 0) {
 				memset(rule, 0, sizeof(struct txgbe_fdir_rule));
 				rte_flow_error_set(error, EINVAL,
 					RTE_FLOW_ERROR_TYPE_ITEM,
@@ -1835,9 +1835,9 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev __rte_unused,
 			rule->b_spec = TRUE;
 			ipv6_spec = item->spec;
 			rte_memcpy(rule->input.src_ip,
-				   ipv6_spec->hdr.src_addr, 16);
+				   &ipv6_spec->hdr.src_addr, 16);
 			rte_memcpy(rule->input.dst_ip,
-				   ipv6_spec->hdr.dst_addr, 16);
+				   &ipv6_spec->hdr.dst_addr, 16);
 		}
 
 		/**
diff --git a/drivers/net/txgbe/txgbe_ipsec.c b/drivers/net/txgbe/txgbe_ipsec.c
index f9f8108fb894..4bad7fc76d42 100644
--- a/drivers/net/txgbe/txgbe_ipsec.c
+++ b/drivers/net/txgbe/txgbe_ipsec.c
@@ -659,9 +659,9 @@ txgbe_crypto_add_ingress_sa_from_flow(const void *sess,
 			ic_session->src_ip.type = IPv6;
 			ic_session->dst_ip.type = IPv6;
 			rte_memcpy(ic_session->src_ip.ipv6,
-				   ipv6->hdr.src_addr, 16);
+				   &ipv6->hdr.src_addr, 16);
 			rte_memcpy(ic_session->dst_ip.ipv6,
-				   ipv6->hdr.dst_addr, 16);
+				   &ipv6->hdr.dst_addr, 16);
 		} else {
 			const struct rte_flow_item_ipv4 *ipv4 = ip_spec;
 			ic_session->src_ip.type = IPv4;
diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c
index 736eae6f05ee..4c0fa5054a2e 100644
--- a/examples/ip_fragmentation/main.c
+++ b/examples/ip_fragmentation/main.c
@@ -311,7 +311,7 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf,
 		ip_hdr = rte_pktmbuf_mtod(m, struct rte_ipv6_hdr *);
 
 		/* Find destination port */
-		if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr,
+		if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr.a,
 						&next_hop) == 0 &&
 				(enabled_port_mask & 1 << next_hop) != 0) {
 			port_out = next_hop;
diff --git a/examples/ip_pipeline/pipeline.c b/examples/ip_pipeline/pipeline.c
index 301c52d061be..d08f8c24c80f 100644
--- a/examples/ip_pipeline/pipeline.c
+++ b/examples/ip_pipeline/pipeline.c
@@ -638,7 +638,7 @@ static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
 		.size = sizeof(uint32_t),
 		.field_index = 1,
 		.input_index = 1,
-		.offset = offsetof(struct rte_ipv6_hdr, src_addr[0]),
+		.offset = offsetof(struct rte_ipv6_hdr, src_addr.a[0]),
 	},
 
 	[2] = {
@@ -646,7 +646,7 @@ static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
 		.size = sizeof(uint32_t),
 		.field_index = 2,
 		.input_index = 2,
-		.offset = offsetof(struct rte_ipv6_hdr, src_addr[4]),
+		.offset = offsetof(struct rte_ipv6_hdr, src_addr.a[4]),
 	},
 
 	[3] = {
@@ -654,7 +654,7 @@ static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
 		.size = sizeof(uint32_t),
 		.field_index = 3,
 		.input_index = 3,
-		.offset = offsetof(struct rte_ipv6_hdr, src_addr[8]),
+		.offset = offsetof(struct rte_ipv6_hdr, src_addr.a[8]),
 	},
 
 	[4] = {
@@ -662,7 +662,7 @@ static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
 		.size = sizeof(uint32_t),
 		.field_index = 4,
 		.input_index = 4,
-		.offset = offsetof(struct rte_ipv6_hdr, src_addr[12]),
+		.offset = offsetof(struct rte_ipv6_hdr, src_addr.a[12]),
 	},
 
 	/* Destination IP address (IPv6) */
@@ -671,7 +671,7 @@ static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
 		.size = sizeof(uint32_t),
 		.field_index = 5,
 		.input_index = 5,
-		.offset = offsetof(struct rte_ipv6_hdr, dst_addr[0]),
+		.offset = offsetof(struct rte_ipv6_hdr, dst_addr.a[0]),
 	},
 
 	[6] = {
@@ -679,7 +679,7 @@ static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
 		.size = sizeof(uint32_t),
 		.field_index = 6,
 		.input_index = 6,
-		.offset = offsetof(struct rte_ipv6_hdr, dst_addr[4]),
+		.offset = offsetof(struct rte_ipv6_hdr, dst_addr.a[4]),
 	},
 
 	[7] = {
@@ -687,7 +687,7 @@ static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
 		.size = sizeof(uint32_t),
 		.field_index = 7,
 		.input_index = 7,
-		.offset = offsetof(struct rte_ipv6_hdr, dst_addr[8]),
+		.offset = offsetof(struct rte_ipv6_hdr, dst_addr.a[8]),
 	},
 
 	[8] = {
@@ -695,7 +695,7 @@ static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
 		.size = sizeof(uint32_t),
 		.field_index = 8,
 		.input_index = 8,
-		.offset = offsetof(struct rte_ipv6_hdr, dst_addr[12]),
+		.offset = offsetof(struct rte_ipv6_hdr, dst_addr.a[12]),
 	},
 
 	/* Source Port */
diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c
index c7019078f7b4..4da692eb23e6 100644
--- a/examples/ip_reassembly/main.c
+++ b/examples/ip_reassembly/main.c
@@ -400,7 +400,7 @@ reassemble(struct rte_mbuf *m, uint16_t portid, uint32_t queue,
 		}
 
 		/* Find destination port */
-		if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr,
+		if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr.a,
 						&next_hop) == 0 &&
 				(enabled_port_mask & 1 << next_hop) != 0) {
 			dst_port = next_hop;
diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c
index 05a62c3020fa..8a0c79e1510a 100644
--- a/examples/ipsec-secgw/flow.c
+++ b/examples/ipsec-secgw/flow.c
@@ -85,7 +85,7 @@ ipv6_hdr_print(struct rte_ipv6_hdr *hdr)
 {
 	uint8_t *addr;
 
-	addr = hdr->src_addr;
+	addr = hdr->src_addr.a;
 	printf("src: %4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx \t",
 	       (uint16_t)((addr[0] << 8) | addr[1]),
 	       (uint16_t)((addr[2] << 8) | addr[3]),
@@ -96,7 +96,7 @@ ipv6_hdr_print(struct rte_ipv6_hdr *hdr)
 	       (uint16_t)((addr[12] << 8) | addr[13]),
 	       (uint16_t)((addr[14] << 8) | addr[15]));
 
-	addr = hdr->dst_addr;
+	addr = hdr->dst_addr.a;
 	printf("dst: %4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx:%4hx",
 	       (uint16_t)((addr[0] << 8) | addr[1]),
 	       (uint16_t)((addr[2] << 8) | addr[3]),
@@ -196,8 +196,8 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 				if (status->status < 0)
 					return;
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr,
-						  rule->ipv6.mask.hdr.src_addr,
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr.a,
+						  rule->ipv6.mask.hdr.src_addr.a,
 						  tokens[ti], status))
 					return;
 			}
@@ -205,8 +205,8 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens,
 				INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
 				if (status->status < 0)
 					return;
-				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr,
-						  rule->ipv6.mask.hdr.dst_addr,
+				if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr.a,
+						  rule->ipv6.mask.hdr.dst_addr.a,
 						  tokens[ti], status))
 					return;
 			}
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index b52b0ffc3d22..ebde28639c12 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -529,9 +529,9 @@ create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 			sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
 			sa->pattern[1].spec = &sa->ipv6_spec;
 
-			memcpy(sa->ipv6_spec.hdr.dst_addr,
+			memcpy(&sa->ipv6_spec.hdr.dst_addr,
 				sa->dst.ip.ip6.ip6_b, 16);
-			memcpy(sa->ipv6_spec.hdr.src_addr,
+			memcpy(&sa->ipv6_spec.hdr.src_addr,
 			       sa->src.ip.ip6.ip6_b, 16);
 		} else if (IS_IP4(sa->flags)) {
 			sa->pattern[1].mask = &rte_flow_item_ipv4_mask;
@@ -735,9 +735,9 @@ create_ipsec_esp_flow(struct ipsec_sa *sa)
 		sa->pattern[1].mask = &rte_flow_item_ipv6_mask;
 		sa->pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
 		sa->pattern[1].spec = &sa->ipv6_spec;
-		memcpy(sa->ipv6_spec.hdr.dst_addr,
+		memcpy(&sa->ipv6_spec.hdr.dst_addr,
 			sa->dst.ip.ip6.ip6_b, sizeof(sa->dst.ip.ip6.ip6_b));
-		memcpy(sa->ipv6_spec.hdr.src_addr,
+		memcpy(&sa->ipv6_spec.hdr.src_addr,
 			sa->src.ip.ip6.ip6_b, sizeof(sa->src.ip.ip6.ip6_b));
 		sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
 		sa->pattern[2].spec = &sa->esp_spec;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index c4bac17cd77c..1a0afd2ed2e8 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -1571,8 +1571,8 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size,
 	};
 
 	if (IS_IP6_TUNNEL(lsa->flags)) {
-		memcpy(v6.src_addr, lsa->src.ip.ip6.ip6_b, sizeof(v6.src_addr));
-		memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b, sizeof(v6.dst_addr));
+		memcpy(&v6.src_addr, lsa->src.ip.ip6.ip6_b, sizeof(v6.src_addr));
+		memcpy(&v6.dst_addr, lsa->dst.ip.ip6.ip6_b, sizeof(v6.dst_addr));
 	}
 
 	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6);
diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h
index 3224b6252c8d..fdb1d2ef1790 100644
--- a/examples/ipsec-secgw/sad.h
+++ b/examples/ipsec-secgw/sad.h
@@ -5,6 +5,8 @@
 #ifndef __SAD_H__
 #define __SAD_H__
 
+#include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_ipsec_sad.h>
 
 #define SA_CACHE_SZ	128
@@ -37,8 +39,8 @@ cmp_sa_key(struct ipsec_sa *sa, int is_v4, struct rte_ipv4_hdr *ipv4,
 			(sa->dst.ip.ip4 == ipv4->dst_addr)) ||
 			/* IPv6 check */
 			(!is_v4 && (sa_type == IP6_TUNNEL) &&
-			(!memcmp(sa->src.ip.ip6.ip6, ipv6->src_addr, 16)) &&
-			(!memcmp(sa->dst.ip.ip6.ip6, ipv6->dst_addr, 16))))
+			(!memcmp(sa->src.ip.ip6.ip6, &ipv6->src_addr, 16)) &&
+			(!memcmp(sa->dst.ip.ip6.ip6, &ipv6->dst_addr, 16))))
 		return 1;
 
 	return 0;
@@ -128,9 +130,9 @@ sad_lookup(struct ipsec_sad *sad, struct rte_mbuf *pkts[],
 				}
 			}
 			v6[nb_v6].spi = esp->spi;
-			memcpy(v6[nb_v6].dip, ipv6->dst_addr,
+			memcpy(v6[nb_v6].dip, &ipv6->dst_addr,
 					sizeof(ipv6->dst_addr));
-			memcpy(v6[nb_v6].sip, ipv6->src_addr,
+			memcpy(v6[nb_v6].sip, &ipv6->src_addr,
 					sizeof(ipv6->src_addr));
 			keys_v6[nb_v6] = (const union rte_ipsec_sad_key *)
 						&v6[nb_v6];
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index f38b19af3f57..4a9534e9dbef 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -65,7 +65,7 @@ fib_parse_packet(struct rte_mbuf *mbuf,
 	/* IPv6 */
 	else {
 		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
-		rte_mov16(ipv6, (const uint8_t *)ipv6_hdr->dst_addr);
+		rte_mov16(ipv6, ipv6_hdr->dst_addr.a);
 		*ip_type = 0;
 		(*ipv6_cnt)++;
 	}
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index e8fd95aae9ce..422fdb70054d 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -62,7 +62,7 @@ lpm_get_ipv6_dst_port(const struct rte_ipv6_hdr *ipv6_hdr,
 		      uint16_t portid,
 		      struct rte_lpm6 *ipv6_l3fwd_lookup_struct)
 {
-	const uint8_t *dst_ip = ipv6_hdr->dst_addr;
+	const uint8_t *dst_ip = ipv6_hdr->dst_addr.a;
 	uint32_t next_hop;
 
 	if (rte_lpm6_lookup(ipv6_l3fwd_lookup_struct, dst_ip, &next_hop) == 0)
@@ -122,7 +122,7 @@ lpm_get_dst_port_with_ipv4(const struct lcore_conf *qconf, struct rte_mbuf *pkt,
 		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
 
 		return (uint16_t) ((rte_lpm6_lookup(qconf->ipv6_lookup_struct,
-				ipv6_hdr->dst_addr, &next_hop) == 0)
+				ipv6_hdr->dst_addr.a, &next_hop) == 0)
 				? next_hop : portid);
 
 	}
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 3a3ab781c494..b3ede7ccdaef 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -1006,12 +1006,14 @@ struct rte_flow_item_ipv6 {
 #ifndef __cplusplus
 static const struct rte_flow_item_ipv6 rte_flow_item_ipv6_mask = {
 	.hdr = {
-		.src_addr =
+		.src_addr = { .a =
 			"\xff\xff\xff\xff\xff\xff\xff\xff"
 			"\xff\xff\xff\xff\xff\xff\xff\xff",
-		.dst_addr =
+		},
+		.dst_addr = { .a =
 			"\xff\xff\xff\xff\xff\xff\xff\xff"
 			"\xff\xff\xff\xff\xff\xff\xff\xff",
+		},
 	},
 };
 #endif
diff --git a/lib/hash/rte_thash.h b/lib/hash/rte_thash.h
index af40afd2d475..9aaaacfd5fa4 100644
--- a/lib/hash/rte_thash.h
+++ b/lib/hash/rte_thash.h
@@ -140,24 +140,24 @@ rte_thash_load_v6_addrs(const struct rte_ipv6_hdr *orig,
 			union rte_thash_tuple *targ)
 {
 #ifdef RTE_ARCH_X86
-	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
+	__m128i ipv6 = _mm_loadu_si128((const __m128i *)&orig->src_addr);
 	*(__m128i *)targ->v6.src_addr =
 			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
-	ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
+	ipv6 = _mm_loadu_si128((const __m128i *)&orig->dst_addr);
 	*(__m128i *)targ->v6.dst_addr =
 			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
 #elif defined(__ARM_NEON)
-	uint8x16_t ipv6 = vld1q_u8((uint8_t const *)orig->src_addr);
+	uint8x16_t ipv6 = vld1q_u8((uint8_t const *)&orig->src_addr);
 	vst1q_u8((uint8_t *)targ->v6.src_addr, vrev32q_u8(ipv6));
-	ipv6 = vld1q_u8((uint8_t const *)orig->dst_addr);
+	ipv6 = vld1q_u8((uint8_t const *)&orig->dst_addr);
 	vst1q_u8((uint8_t *)targ->v6.dst_addr, vrev32q_u8(ipv6));
 #else
 	int i;
 	for (i = 0; i < 4; i++) {
 		*((uint32_t *)targ->v6.src_addr + i) =
-			rte_be_to_cpu_32(*((const uint32_t *)orig->src_addr + i));
+			rte_be_to_cpu_32(*((const uint32_t *)orig->src_addr.a + i));
 		*((uint32_t *)targ->v6.dst_addr + i) =
-			rte_be_to_cpu_32(*((const uint32_t *)orig->dst_addr + i));
+			rte_be_to_cpu_32(*((const uint32_t *)orig->dst_addr.a + i));
 	}
 #endif
 }
diff --git a/lib/ip_frag/rte_ipv6_reassembly.c b/lib/ip_frag/rte_ipv6_reassembly.c
index 88863a98d1fe..9471ce5333d7 100644
--- a/lib/ip_frag/rte_ipv6_reassembly.c
+++ b/lib/ip_frag/rte_ipv6_reassembly.c
@@ -143,8 +143,8 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 	int32_t ip_len;
 	int32_t trim;
 
-	rte_memcpy(&key.src_dst[0], ip_hdr->src_addr, 16);
-	rte_memcpy(&key.src_dst[2], ip_hdr->dst_addr, 16);
+	rte_memcpy(&key.src_dst[0], &ip_hdr->src_addr, 16);
+	rte_memcpy(&key.src_dst[2], &ip_hdr->dst_addr, 16);
 
 	key.id = frag_hdr->id;
 	key.key_len = IPV6_KEYLEN;
diff --git a/lib/net/rte_ip6.h b/lib/net/rte_ip6.h
index f948f95db7ca..58cab86895eb 100644
--- a/lib/net/rte_ip6.h
+++ b/lib/net/rte_ip6.h
@@ -53,8 +53,8 @@ struct rte_ipv6_hdr {
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers */
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */
-	uint8_t  src_addr[16];	/**< IP address of source host. */
-	uint8_t  dst_addr[16];	/**< IP address of destination host(s). */
+	struct rte_ipv6_addr src_addr;	/**< IP address of source host. */
+	struct rte_ipv6_addr dst_addr;	/**< IP address of destination host(s). */
 } __rte_packed;
 
 /* IPv6 routing extension type definition. */
@@ -122,7 +122,7 @@ rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags)
 	else
 		psd_hdr.len = ipv6_hdr->payload_len;
 
-	sum = __rte_raw_cksum(ipv6_hdr->src_addr,
+	sum = __rte_raw_cksum(&ipv6_hdr->src_addr,
 		sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr),
 		0);
 	sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum);
diff --git a/lib/node/ip6_lookup.c b/lib/node/ip6_lookup.c
index 309964f60fd6..6bbcf14e2aa8 100644
--- a/lib/node/ip6_lookup.c
+++ b/lib/node/ip6_lookup.c
@@ -112,28 +112,28 @@ ip6_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(ip_batch[0], ipv6_hdr->dst_addr, 16);
+		rte_memcpy(ip_batch[0], &ipv6_hdr->dst_addr, 16);
 
 		/* Extract DIP of mbuf1 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf1, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(ip_batch[1], ipv6_hdr->dst_addr, 16);
+		rte_memcpy(ip_batch[1], &ipv6_hdr->dst_addr, 16);
 
 		/* Extract DIP of mbuf2 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf2, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(ip_batch[2], ipv6_hdr->dst_addr, 16);
+		rte_memcpy(ip_batch[2], &ipv6_hdr->dst_addr, 16);
 
 		/* Extract DIP of mbuf3 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf3, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(ip_batch[3], ipv6_hdr->dst_addr, 16);
+		rte_memcpy(ip_batch[3], &ipv6_hdr->dst_addr, 16);
 
 		rte_lpm6_lookup_bulk_func(lpm6, ip_batch, next_hop, 4);
 
@@ -223,7 +223,7 @@ ip6_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node,
 		/* Extract TTL as IPv6 hdr is in cache */
 		node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits;
 
-		rc = rte_lpm6_lookup(lpm6, ipv6_hdr->dst_addr, &next_hop);
+		rc = rte_lpm6_lookup(lpm6, ipv6_hdr->dst_addr.a, &next_hop);
 		next_hop = (rc == 0) ? next_hop : drop_nh;
 
 		node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop;
diff --git a/lib/pipeline/rte_swx_ipsec.c b/lib/pipeline/rte_swx_ipsec.c
index 56a401d0fa63..5920178f38e5 100644
--- a/lib/pipeline/rte_swx_ipsec.c
+++ b/lib/pipeline/rte_swx_ipsec.c
@@ -1387,13 +1387,11 @@ tunnel_ipv6_header_set(struct rte_ipv6_hdr *h, struct rte_swx_ipsec_sa_params *p
 		.payload_len = 0, /* Cannot be pre-computed. */
 		.proto = IPPROTO_ESP,
 		.hop_limits = 64,
-		.src_addr = {0},
-		.dst_addr = {0},
 	};
 
 	memcpy(h, &ipv6_hdr, sizeof(ipv6_hdr));
-	memcpy(h->src_addr, p->encap.tunnel.ipv6.src_addr.s6_addr, 16);
-	memcpy(h->dst_addr, p->encap.tunnel.ipv6.dst_addr.s6_addr, 16);
+	memcpy(&h->src_addr, p->encap.tunnel.ipv6.src_addr.s6_addr, 16);
+	memcpy(&h->dst_addr, p->encap.tunnel.ipv6.dst_addr.s6_addr, 16);
 }
 
 /* IPsec library SA parameters. */
diff --git a/lib/pipeline/rte_table_action.c b/lib/pipeline/rte_table_action.c
index ebbdd3f4cebe..a04d5121e1f0 100644
--- a/lib/pipeline/rte_table_action.c
+++ b/lib/pipeline/rte_table_action.c
@@ -872,10 +872,10 @@ encap_vxlan_apply(void *data,
 			d->ipv6.payload_len = 0; /* not pre-computed */
 			d->ipv6.proto = IP_PROTO_UDP;
 			d->ipv6.hop_limits = p->vxlan.ipv6.hop_limit;
-			memcpy(d->ipv6.src_addr,
+			memcpy(&d->ipv6.src_addr,
 				p->vxlan.ipv6.sa,
 				sizeof(p->vxlan.ipv6.sa));
-			memcpy(d->ipv6.dst_addr,
+			memcpy(&d->ipv6.dst_addr,
 				p->vxlan.ipv6.da,
 				sizeof(p->vxlan.ipv6.da));
 
@@ -907,10 +907,10 @@ encap_vxlan_apply(void *data,
 			d->ipv6.payload_len = 0; /* not pre-computed */
 			d->ipv6.proto = IP_PROTO_UDP;
 			d->ipv6.hop_limits = p->vxlan.ipv6.hop_limit;
-			memcpy(d->ipv6.src_addr,
+			memcpy(&d->ipv6.src_addr,
 				p->vxlan.ipv6.sa,
 				sizeof(p->vxlan.ipv6.sa));
-			memcpy(d->ipv6.dst_addr,
+			memcpy(&d->ipv6.dst_addr,
 				p->vxlan.ipv6.da,
 				sizeof(p->vxlan.ipv6.da));
 
@@ -1437,12 +1437,12 @@ pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
 			uint16_t tcp_cksum;
 
 			tcp_cksum = nat_ipv6_tcp_udp_checksum_update(tcp->cksum,
-				(uint16_t *)ip->src_addr,
+				(uint16_t *)&ip->src_addr,
 				(uint16_t *)data->addr,
 				tcp->src_port,
 				data->port);
 
-			rte_memcpy(ip->src_addr, data->addr, 16);
+			rte_memcpy(&ip->src_addr, data->addr, 16);
 			tcp->src_port = data->port;
 			tcp->cksum = tcp_cksum;
 		} else {
@@ -1450,12 +1450,12 @@ pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
 			uint16_t udp_cksum;
 
 			udp_cksum = nat_ipv6_tcp_udp_checksum_update(udp->dgram_cksum,
-				(uint16_t *)ip->src_addr,
+				(uint16_t *)&ip->src_addr,
 				(uint16_t *)data->addr,
 				udp->src_port,
 				data->port);
 
-			rte_memcpy(ip->src_addr, data->addr, 16);
+			rte_memcpy(&ip->src_addr, data->addr, 16);
 			udp->src_port = data->port;
 			udp->dgram_cksum = udp_cksum;
 		}
@@ -1465,12 +1465,12 @@ pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
 			uint16_t tcp_cksum;
 
 			tcp_cksum = nat_ipv6_tcp_udp_checksum_update(tcp->cksum,
-				(uint16_t *)ip->dst_addr,
+				(uint16_t *)&ip->dst_addr,
 				(uint16_t *)data->addr,
 				tcp->dst_port,
 				data->port);
 
-			rte_memcpy(ip->dst_addr, data->addr, 16);
+			rte_memcpy(&ip->dst_addr, data->addr, 16);
 			tcp->dst_port = data->port;
 			tcp->cksum = tcp_cksum;
 		} else {
@@ -1478,12 +1478,12 @@ pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
 			uint16_t udp_cksum;
 
 			udp_cksum = nat_ipv6_tcp_udp_checksum_update(udp->dgram_cksum,
-				(uint16_t *)ip->dst_addr,
+				(uint16_t *)&ip->dst_addr.a,
 				(uint16_t *)data->addr,
 				udp->dst_port,
 				data->port);
 
-			rte_memcpy(ip->dst_addr, data->addr, 16);
+			rte_memcpy(&ip->dst_addr, data->addr, 16);
 			udp->dst_port = data->port;
 			udp->dgram_cksum = udp_cksum;
 		}
-- 
2.46.0


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

* [PATCH dpdk v1 05/15] fib6,rib6,lpm6: use ipv6 addr struct
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (3 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 04/15] net: use ipv6 structure for header addresses Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 06/15] net: add ipv6 address utilities Robin Jarry
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Vladimir Medvedkin, Cristian Dumitrescu, Bruce Richardson,
	Konstantin Ananyev, Wathsala Vithanage, Radu Nicolau,
	Akhil Goyal, Nithin Dabilpuram, Pavan Nikhilesh

Replace ad-hoc uint8_t[16] array types in the API of rte_fib6, rte_rib6
and rte_lpm6. Update all code accordingly.

Unfortunately, these three libraries are strongly intertwined, it is not
possible to split this change in separate commits.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test-fib/main.c                   |   51 +-
 app/test-pipeline/pipeline_lpm_ipv6.c |   10 +-
 app/test/test_fib6.c                  |   52 +-
 app/test/test_fib6_perf.c             |    8 +-
 app/test/test_lpm6.c                  |  523 +++----
 app/test/test_lpm6_data.h             | 2025 +++++++++++++------------
 app/test/test_lpm6_perf.c             |   10 +-
 app/test/test_rib6.c                  |   65 +-
 app/test/test_table_combined.c        |    2 +-
 app/test/test_table_tables.c          |    8 +-
 examples/ip_fragmentation/main.c      |   24 +-
 examples/ip_pipeline/thread.c         |    2 +-
 examples/ip_reassembly/main.c         |   24 +-
 examples/ipsec-secgw/ipsec_lpm_neon.h |    7 +-
 examples/ipsec-secgw/ipsec_worker.c   |    6 +-
 examples/ipsec-secgw/ipsec_worker.h   |    4 +-
 examples/ipsec-secgw/rt.c             |   22 +-
 examples/l3fwd/l3fwd_fib.c            |   39 +-
 examples/l3fwd/l3fwd_lpm.c            |    8 +-
 examples/l3fwd/l3fwd_route.h          |    7 +-
 examples/l3fwd/lpm_route_parse.c      |    6 +-
 lib/fib/meson.build                   |    4 +-
 lib/fib/rte_fib6.c                    |   13 +-
 lib/fib/rte_fib6.h                    |   11 +-
 lib/fib/trie.c                        |   99 +-
 lib/fib/trie.h                        |   16 +-
 lib/fib/trie_avx512.c                 |   38 +-
 lib/fib/trie_avx512.h                 |   10 +-
 lib/lpm/meson.build                   |    1 +
 lib/lpm/rte_lpm6.c                    |  106 +-
 lib/lpm/rte_lpm6.h                    |   14 +-
 lib/node/ip6_lookup.c                 |   16 +-
 lib/rib/meson.build                   |    2 +-
 lib/rib/rte_rib6.c                    |   74 +-
 lib/rib/rte_rib6.h                    |   13 +-
 lib/table/rte_table_lpm_ipv6.c        |   12 +-
 lib/table/rte_table_lpm_ipv6.h        |    4 +-
 37 files changed, 1681 insertions(+), 1655 deletions(-)

diff --git a/app/test-fib/main.c b/app/test-fib/main.c
index c49bfe8bcec3..a43a0ae4df5d 100644
--- a/app/test-fib/main.c
+++ b/app/test-fib/main.c
@@ -123,7 +123,7 @@ struct rt_rule_4 {
 };
 
 struct rt_rule_6 {
-	uint8_t		addr[16];
+	struct rte_ipv6_addr addr;
 	uint8_t		depth;
 	uint64_t	nh;
 };
@@ -306,15 +306,15 @@ shuffle_rt_6(struct rt_rule_6 *rt, int n)
 
 	for (i = 0; i < n; i++) {
 		j = rte_rand() % n;
-		memcpy(tmp.addr, rt[i].addr, 16);
+		memcpy(&tmp.addr, &rt[i].addr, 16);
 		tmp.depth = rt[i].depth;
 		tmp.nh = rt[i].nh;
 
-		memcpy(rt[i].addr, rt[j].addr, 16);
+		memcpy(&rt[i].addr, &rt[j].addr, 16);
 		rt[i].depth = rt[j].depth;
 		rt[i].nh = rt[j].nh;
 
-		memcpy(rt[j].addr, tmp.addr, 16);
+		memcpy(&rt[j].addr, &tmp.addr, 16);
 		rt[j].depth = tmp.depth;
 		rt[j].nh = tmp.nh;
 	}
@@ -364,7 +364,7 @@ gen_random_rt_6(struct rt_rule_6 *rt, int nh_sz)
 	uint32_t a, i, j, k = 0;
 
 	if (config.nb_routes_per_depth[0] != 0) {
-		memset(rt[k].addr, 0, 16);
+		memset(&rt[k].addr, 0, 16);
 		rt[k].depth = 0;
 		rt[k++].nh = rte_rand() & get_max_nh(nh_sz);
 	}
@@ -380,7 +380,7 @@ gen_random_rt_6(struct rt_rule_6 *rt, int nh_sz)
 				uint64_t rnd_val = get_rnd_rng((uint64_t)edge,
 					(uint64_t)(edge + step));
 				rnd = rte_cpu_to_be_32(rnd_val << (32 - i));
-				complete_v6_addr((uint32_t *)rt[k].addr,
+				complete_v6_addr((uint32_t *)&rt[k].addr,
 					rnd, a);
 				rt[k].depth = (a * 32) + i;
 				rt[k].nh = rte_rand() & get_max_nh(nh_sz);
@@ -390,19 +390,19 @@ gen_random_rt_6(struct rt_rule_6 *rt, int nh_sz)
 }
 
 static inline void
-set_rnd_ipv6(uint8_t *addr, uint8_t *route, int depth)
+set_rnd_ipv6(struct rte_ipv6_addr *addr, struct rte_ipv6_addr *route, int depth)
 {
 	int i;
 
 	for (i = 0; i < 16; i++)
-		addr[i] = rte_rand();
+		addr->a[i] = rte_rand();
 
 	for (i = 0; i < 16; i++) {
 		if (depth >= 8)
-			addr[i] = route[i];
+			addr->a[i] = route->a[i];
 		else if (depth > 0) {
-			addr[i] &= (uint16_t)UINT8_MAX >> depth;
-			addr[i] |= route[i] & UINT8_MAX << (8 - depth);
+			addr->a[i] &= (uint16_t)UINT8_MAX >> depth;
+			addr->a[i] |= route->a[i] & UINT8_MAX << (8 - depth);
 		} else
 			return;
 		depth -= 8;
@@ -413,7 +413,7 @@ static void
 gen_rnd_lookup_tbl(int af)
 {
 	uint32_t *tbl4 = config.lookup_tbl;
-	uint8_t *tbl6 = config.lookup_tbl;
+	struct rte_ipv6_addr *tbl6 = config.lookup_tbl;
 	struct rt_rule_4 *rt4 = (struct rt_rule_4 *)config.rt;
 	struct rt_rule_6 *rt6 = (struct rt_rule_6 *)config.rt;
 	uint32_t i, j;
@@ -432,11 +432,10 @@ gen_rnd_lookup_tbl(int af)
 		for (i = 0, j = 0; i < config.nb_lookup_ips;
 				i++, j = (j + 1) % config.nb_routes) {
 			if ((rte_rand() % 100) < config.rnd_lookup_ips_ratio) {
-				set_rnd_ipv6(&tbl6[i * 16], rt6[j].addr, 0);
+				set_rnd_ipv6(&tbl6[i], &rt6[j].addr, 0);
 				config.nb_lookup_ips_rnd++;
 			} else {
-				set_rnd_ipv6(&tbl6[i * 16], rt6[j].addr,
-					rt6[j].depth);
+				set_rnd_ipv6(&tbl6[i], &rt6[j].addr, rt6[j].depth);
 			}
 		}
 	}
@@ -522,7 +521,7 @@ parse_rt_6(FILE *f)
 			s = NULL;
 		}
 
-		ret = _inet_net_pton(AF_INET6, in[RT_PREFIX], rt[j].addr);
+		ret = _inet_net_pton(AF_INET6, in[RT_PREFIX], &rt[j].addr);
 		if (ret < 0)
 			return ret;
 
@@ -1023,7 +1022,7 @@ dump_rt_6(struct rt_rule_6 *rt)
 	}
 
 	for (i = 0; i < config.nb_routes; i++) {
-		fprintf(f, NIPQUAD6_FMT"/%d %"PRIu64"\n", NIPQUAD6(rt[i].addr),
+		fprintf(f, NIPQUAD6_FMT"/%d %"PRIu64"\n", NIPQUAD6(&rt[i].addr),
 			rt[i].depth, rt[i].nh);
 
 	}
@@ -1043,7 +1042,7 @@ run_v6(void)
 	int ret = 0;
 	struct rte_lpm6	*lpm = NULL;
 	struct rte_lpm6_config lpm_conf;
-	uint8_t *tbl6;
+	struct rte_ipv6_addr *tbl6;
 	uint64_t fib_nh[BURST_SZ];
 	int32_t lpm_nh[BURST_SZ];
 
@@ -1094,7 +1093,7 @@ run_v6(void)
 	for (k = config.print_fract, i = 0; k > 0; k--) {
 		start = rte_rdtsc_precise();
 		for (j = 0; j < (config.nb_routes - i) / k; j++) {
-			ret = rte_fib6_add(fib, rt[i + j].addr,
+			ret = rte_fib6_add(fib, &rt[i + j].addr,
 				rt[i + j].depth, rt[i + j].nh);
 			if (unlikely(ret != 0)) {
 				printf("Can not add a route to FIB, err %d\n",
@@ -1120,7 +1119,7 @@ run_v6(void)
 		for (k = config.print_fract, i = 0; k > 0; k--) {
 			start = rte_rdtsc_precise();
 			for (j = 0; j < (config.nb_routes - i) / k; j++) {
-				ret = rte_lpm6_add(lpm, rt[i + j].addr,
+				ret = rte_lpm6_add(lpm, &rt[i + j].addr,
 					rt[i + j].depth, rt[i + j].nh);
 				if (ret != 0) {
 					if (rt[i + j].depth == 0)
@@ -1139,7 +1138,7 @@ run_v6(void)
 	acc = 0;
 	for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
 		start = rte_rdtsc_precise();
-		ret = rte_fib6_lookup_bulk(fib, (uint8_t (*)[16])(tbl6 + i*16),
+		ret = rte_fib6_lookup_bulk(fib, &tbl6[i],
 			fib_nh, BURST_SZ);
 		acc += rte_rdtsc_precise() - start;
 		if (ret != 0) {
@@ -1154,7 +1153,7 @@ run_v6(void)
 		for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
 			start = rte_rdtsc_precise();
 			ret = rte_lpm6_lookup_bulk_func(lpm,
-				(uint8_t (*)[16])(tbl6 + i*16),
+				&tbl6[i],
 				lpm_nh, BURST_SZ);
 			acc += rte_rdtsc_precise() - start;
 			if (ret != 0) {
@@ -1166,10 +1165,10 @@ run_v6(void)
 
 		for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
 			rte_fib6_lookup_bulk(fib,
-				(uint8_t (*)[16])(tbl6 + i*16),
+				&tbl6[i],
 				fib_nh, BURST_SZ);
 			rte_lpm6_lookup_bulk_func(lpm,
-				(uint8_t (*)[16])(tbl6 + i*16),
+				&tbl6[i],
 				lpm_nh, BURST_SZ);
 			for (j = 0; j < BURST_SZ; j++) {
 				if ((fib_nh[j] != (uint32_t)lpm_nh[j]) &&
@@ -1186,7 +1185,7 @@ run_v6(void)
 	for (k = config.print_fract, i = 0; k > 0; k--) {
 		start = rte_rdtsc_precise();
 		for (j = 0; j < (config.nb_routes - i) / k; j++)
-			rte_fib6_delete(fib, rt[i + j].addr, rt[i + j].depth);
+			rte_fib6_delete(fib, &rt[i + j].addr, rt[i + j].depth);
 
 		printf("AVG FIB delete %"PRIu64"\n",
 			(rte_rdtsc_precise() - start) / j);
@@ -1197,7 +1196,7 @@ run_v6(void)
 		for (k = config.print_fract, i = 0; k > 0; k--) {
 			start = rte_rdtsc_precise();
 			for (j = 0; j < (config.nb_routes - i) / k; j++)
-				rte_lpm6_delete(lpm, rt[i + j].addr,
+				rte_lpm6_delete(lpm, &rt[i + j].addr,
 					rt[i + j].depth);
 
 			printf("AVG LPM delete %"PRIu64"\n",
diff --git a/app/test-pipeline/pipeline_lpm_ipv6.c b/app/test-pipeline/pipeline_lpm_ipv6.c
index 207ffbeff00f..cfebfbbc81ca 100644
--- a/app/test-pipeline/pipeline_lpm_ipv6.c
+++ b/app/test-pipeline/pipeline_lpm_ipv6.c
@@ -127,16 +127,16 @@ app_main_loop_worker_pipeline_lpm_ipv6(void) {
 
 		ip = rte_bswap32(i << (24 -
 			rte_popcount32(app.n_ports - 1)));
-		memcpy(key.ip, &ip, sizeof(uint32_t));
+		memcpy(&key.ip, &ip, sizeof(uint32_t));
 
 		printf("Adding rule to IPv6 LPM table (IPv6 destination = "
 			"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:"
 			"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%u => "
 			"port out = %u)\n",
-			key.ip[0], key.ip[1], key.ip[2], key.ip[3],
-			key.ip[4], key.ip[5], key.ip[6], key.ip[7],
-			key.ip[8], key.ip[9], key.ip[10], key.ip[11],
-			key.ip[12], key.ip[13], key.ip[14], key.ip[15],
+			key.ip.a[0], key.ip.a[1], key.ip.a[2], key.ip.a[3],
+			key.ip.a[4], key.ip.a[5], key.ip.a[6], key.ip.a[7],
+			key.ip.a[8], key.ip.a[9], key.ip.a[10], key.ip.a[11],
+			key.ip.a[12], key.ip.a[13], key.ip.a[14], key.ip.a[15],
 			key.depth, i);
 
 		status = rte_pipeline_table_entry_add(p, table_id, &key, &entry,
diff --git a/app/test/test_fib6.c b/app/test/test_fib6.c
index 2f836238fbf7..c3b947d789bb 100644
--- a/app/test/test_fib6.c
+++ b/app/test/test_fib6.c
@@ -147,7 +147,7 @@ test_add_del_invalid(void)
 	struct rte_fib6 *fib = NULL;
 	struct rte_fib6_conf config;
 	uint64_t nh = 100;
-	uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE] = {0};
+	struct rte_ipv6_addr ip = {0};
 	int ret;
 	uint8_t depth = 24;
 
@@ -157,12 +157,12 @@ test_add_del_invalid(void)
 	config.type = RTE_FIB6_DUMMY;
 
 	/* rte_fib6_add: fib == NULL */
-	ret = rte_fib6_add(NULL, ip, depth, nh);
+	ret = rte_fib6_add(NULL, &ip, depth, nh);
 	RTE_TEST_ASSERT(ret < 0,
 		"Call succeeded with invalid parameters\n");
 
 	/* rte_fib6_delete: fib == NULL */
-	ret = rte_fib6_delete(NULL, ip, depth);
+	ret = rte_fib6_delete(NULL, &ip, depth);
 	RTE_TEST_ASSERT(ret < 0,
 		"Call succeeded with invalid parameters\n");
 
@@ -171,12 +171,12 @@ test_add_del_invalid(void)
 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
 
 	/* rte_fib6_add: depth > RTE_FIB6_MAXDEPTH */
-	ret = rte_fib6_add(fib, ip, RTE_FIB6_MAXDEPTH + 1, nh);
+	ret = rte_fib6_add(fib, &ip, RTE_FIB6_MAXDEPTH + 1, nh);
 	RTE_TEST_ASSERT(ret < 0,
 		"Call succeeded with invalid parameters\n");
 
 	/* rte_fib6_delete: depth > RTE_FIB6_MAXDEPTH */
-	ret = rte_fib6_delete(fib, ip, RTE_FIB6_MAXDEPTH + 1);
+	ret = rte_fib6_delete(fib, &ip, RTE_FIB6_MAXDEPTH + 1);
 	RTE_TEST_ASSERT(ret < 0,
 		"Call succeeded with invalid parameters\n");
 
@@ -212,8 +212,8 @@ test_get_invalid(void)
  */
 static int
 lookup_and_check_asc(struct rte_fib6 *fib,
-	uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE],
-	uint8_t ip_missing[][RTE_FIB6_IPV6_ADDR_SIZE], uint64_t def_nh,
+	struct rte_ipv6_addr *ip_arr,
+	struct rte_ipv6_addr *ip_missing, uint64_t def_nh,
 	uint32_t n)
 {
 	uint64_t nh_arr[RTE_FIB6_MAXDEPTH];
@@ -240,8 +240,8 @@ lookup_and_check_asc(struct rte_fib6 *fib,
 
 static int
 lookup_and_check_desc(struct rte_fib6 *fib,
-	uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE],
-	uint8_t ip_missing[][RTE_FIB6_IPV6_ADDR_SIZE], uint64_t def_nh,
+	struct rte_ipv6_addr *ip_arr,
+	struct rte_ipv6_addr *ip_missing, uint64_t def_nh,
 	uint32_t n)
 {
 	uint64_t nh_arr[RTE_FIB6_MAXDEPTH];
@@ -270,61 +270,61 @@ static int
 check_fib(struct rte_fib6 *fib)
 {
 	uint64_t def_nh = 100;
-	uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE];
-	uint8_t ip_add[RTE_FIB6_IPV6_ADDR_SIZE] = {0};
-	uint8_t ip_missing[1][RTE_FIB6_IPV6_ADDR_SIZE] = { {255} };
+	struct rte_ipv6_addr ip_arr[RTE_FIB6_MAXDEPTH];
+	struct rte_ipv6_addr ip_add = {.a = {[0] = 128}};
+	struct rte_ipv6_addr ip_missing = {
+		.a = {[0] = 127, [1 ... 15] = 255},
+	};
 	uint32_t i, j;
 	int ret;
 
-	ip_add[0] = 128;
-	ip_missing[0][0] = 127;
 	for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
 		for (j = 0; j < RTE_FIB6_IPV6_ADDR_SIZE; j++) {
-			ip_arr[i][j] = ip_add[j] |
+			ip_arr[i].a[j] = ip_add.a[j] |
 				~get_msk_part(RTE_FIB6_MAXDEPTH - i, j);
 		}
 	}
 
-	ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
+	ret = lookup_and_check_desc(fib, ip_arr, &ip_missing, def_nh, 0);
 	RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
 
 	for (i = 1; i <= RTE_FIB6_MAXDEPTH; i++) {
-		ret = rte_fib6_add(fib, ip_add, i, i);
+		ret = rte_fib6_add(fib, &ip_add, i, i);
 		RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
-		ret = lookup_and_check_asc(fib, ip_arr, ip_missing, def_nh, i);
+		ret = lookup_and_check_asc(fib, ip_arr, &ip_missing, def_nh, i);
 		RTE_TEST_ASSERT(ret == TEST_SUCCESS,
 			"Lookup and check fails\n");
 	}
 
 	for (i = RTE_FIB6_MAXDEPTH; i > 1; i--) {
-		ret = rte_fib6_delete(fib, ip_add, i);
+		ret = rte_fib6_delete(fib, &ip_add, i);
 		RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
-		ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
+		ret = lookup_and_check_asc(fib, ip_arr, &ip_missing,
 			def_nh, i - 1);
 
 		RTE_TEST_ASSERT(ret == TEST_SUCCESS,
 			"Lookup and check fails\n");
 	}
-	ret = rte_fib6_delete(fib, ip_add, i);
+	ret = rte_fib6_delete(fib, &ip_add, i);
 	RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
-	ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
+	ret = lookup_and_check_desc(fib, ip_arr, &ip_missing, def_nh, 0);
 	RTE_TEST_ASSERT(ret == TEST_SUCCESS,
 		"Lookup and check fails\n");
 
 	for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
-		ret = rte_fib6_add(fib, ip_add, RTE_FIB6_MAXDEPTH - i,
+		ret = rte_fib6_add(fib, &ip_add, RTE_FIB6_MAXDEPTH - i,
 			RTE_FIB6_MAXDEPTH - i);
 		RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
-		ret = lookup_and_check_desc(fib, ip_arr, ip_missing,
+		ret = lookup_and_check_desc(fib, ip_arr, &ip_missing,
 			def_nh, i + 1);
 		RTE_TEST_ASSERT(ret == TEST_SUCCESS,
 			"Lookup and check fails\n");
 	}
 
 	for (i = 1; i <= RTE_FIB6_MAXDEPTH; i++) {
-		ret = rte_fib6_delete(fib, ip_add, i);
+		ret = rte_fib6_delete(fib, &ip_add, i);
 		RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
-		ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh,
+		ret = lookup_and_check_desc(fib, ip_arr, &ip_missing, def_nh,
 			RTE_FIB6_MAXDEPTH - i);
 		RTE_TEST_ASSERT(ret == TEST_SUCCESS,
 			"Lookup and check fails\n");
diff --git a/app/test/test_fib6_perf.c b/app/test/test_fib6_perf.c
index fe713e7094e5..d51bbdbdd6fa 100644
--- a/app/test/test_fib6_perf.c
+++ b/app/test/test_fib6_perf.c
@@ -73,7 +73,7 @@ test_fib6_perf(void)
 	uint64_t next_hop_add;
 	int status = 0;
 	int64_t count = 0;
-	uint8_t ip_batch[NUM_IPS_ENTRIES][16];
+	struct rte_ipv6_addr ip_batch[NUM_IPS_ENTRIES];
 	uint64_t next_hops[NUM_IPS_ENTRIES];
 
 	conf.type = RTE_FIB6_TRIE;
@@ -101,7 +101,7 @@ test_fib6_perf(void)
 
 	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
 		next_hop_add = (i & ((1 << 14) - 1)) + 1;
-		if (rte_fib6_add(fib, large_route_table[i].ip,
+		if (rte_fib6_add(fib, &large_route_table[i].ip,
 				large_route_table[i].depth, next_hop_add) == 0)
 			status++;
 	}
@@ -117,7 +117,7 @@ test_fib6_perf(void)
 	count = 0;
 
 	for (i = 0; i < NUM_IPS_ENTRIES; i++)
-		memcpy(ip_batch[i], large_ips_table[i].ip, 16);
+		memcpy(&ip_batch[i], &large_ips_table[i].ip, 16);
 
 	for (i = 0; i < ITERATIONS; i++) {
 
@@ -140,7 +140,7 @@ test_fib6_perf(void)
 
 	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
 		/* rte_fib_delete(fib, ip, depth) */
-		status += rte_fib6_delete(fib, large_route_table[i].ip,
+		status += rte_fib6_delete(fib, &large_route_table[i].ip,
 				large_route_table[i].depth);
 	}
 
diff --git a/app/test/test_lpm6.c b/app/test/test_lpm6.c
index 1d8a0afa1155..b0b662593116 100644
--- a/app/test/test_lpm6.c
+++ b/app/test/test_lpm6.c
@@ -93,27 +93,28 @@ rte_lpm6_test tests6[] = {
 #define PASS 0
 
 static void
-IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
-		uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10,
-		uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15,
-		uint8_t b16)
+IPv6(struct rte_ipv6_addr *ip,
+	uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4,
+	uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8,
+	uint8_t b9, uint8_t b10, uint8_t b11, uint8_t b12,
+	uint8_t b13, uint8_t b14, uint8_t b15, uint8_t b16)
 {
-	ip[0] = b1;
-	ip[1] = b2;
-	ip[2] = b3;
-	ip[3] = b4;
-	ip[4] = b5;
-	ip[5] = b6;
-	ip[6] = b7;
-	ip[7] = b8;
-	ip[8] = b9;
-	ip[9] = b10;
-	ip[10] = b11;
-	ip[11] = b12;
-	ip[12] = b13;
-	ip[13] = b14;
-	ip[14] = b15;
-	ip[15] = b16;
+	ip->a[0] = b1;
+	ip->a[1] = b2;
+	ip->a[2] = b3;
+	ip->a[3] = b4;
+	ip->a[4] = b5;
+	ip->a[5] = b6;
+	ip->a[6] = b7;
+	ip->a[7] = b8;
+	ip->a[8] = b9;
+	ip->a[9] = b10;
+	ip->a[10] = b11;
+	ip->a[11] = b12;
+	ip->a[12] = b13;
+	ip->a[13] = b14;
+	ip->a[14] = b15;
+	ip->a[15] = b16;
 }
 
 /*
@@ -250,7 +251,7 @@ test4(void)
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
 
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth = 24, next_hop = 100;
 	int32_t status = 0;
 
@@ -259,7 +260,7 @@ test4(void)
 	config.flags = 0;
 
 	/* rte_lpm6_add: lpm == NULL */
-	status = rte_lpm6_add(NULL, ip, depth, next_hop);
+	status = rte_lpm6_add(NULL, &ip, depth, next_hop);
 	TEST_LPM_ASSERT(status < 0);
 
 	/*Create valid lpm to use in rest of test. */
@@ -267,11 +268,11 @@ test4(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	/* rte_lpm6_add: depth < 1 */
-	status = rte_lpm6_add(lpm, ip, 0, next_hop);
+	status = rte_lpm6_add(lpm, &ip, 0, next_hop);
 	TEST_LPM_ASSERT(status < 0);
 
 	/* rte_lpm6_add: depth > MAX_DEPTH */
-	status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
+	status = rte_lpm6_add(lpm, &ip, (MAX_DEPTH + 1), next_hop);
 	TEST_LPM_ASSERT(status < 0);
 
 	rte_lpm6_free(lpm);
@@ -288,7 +289,7 @@ test5(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth = 24;
 	int32_t status = 0;
 
@@ -297,7 +298,7 @@ test5(void)
 	config.flags = 0;
 
 	/* rte_lpm_delete: lpm == NULL */
-	status = rte_lpm6_delete(NULL, ip, depth);
+	status = rte_lpm6_delete(NULL, &ip, depth);
 	TEST_LPM_ASSERT(status < 0);
 
 	/*Create valid lpm to use in rest of test. */
@@ -305,11 +306,11 @@ test5(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	/* rte_lpm_delete: depth < 1 */
-	status = rte_lpm6_delete(lpm, ip, 0);
+	status = rte_lpm6_delete(lpm, &ip, 0);
 	TEST_LPM_ASSERT(status < 0);
 
 	/* rte_lpm_delete: depth > MAX_DEPTH */
-	status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1));
+	status = rte_lpm6_delete(lpm, &ip, (MAX_DEPTH + 1));
 	TEST_LPM_ASSERT(status < 0);
 
 	rte_lpm6_free(lpm);
@@ -326,7 +327,7 @@ test6(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint32_t next_hop_return = 0;
 	int32_t status = 0;
 
@@ -335,7 +336,7 @@ test6(void)
 	config.flags = 0;
 
 	/* rte_lpm6_lookup: lpm == NULL */
-	status = rte_lpm6_lookup(NULL, ip, &next_hop_return);
+	status = rte_lpm6_lookup(NULL, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status < 0);
 
 	/*Create valid lpm to use in rest of test. */
@@ -347,7 +348,7 @@ test6(void)
 	TEST_LPM_ASSERT(status < 0);
 
 	/* rte_lpm6_lookup: next_hop = NULL */
-	status = rte_lpm6_lookup(lpm, ip, NULL);
+	status = rte_lpm6_lookup(lpm, &ip, NULL);
 	TEST_LPM_ASSERT(status < 0);
 
 	rte_lpm6_free(lpm);
@@ -364,7 +365,7 @@ test7(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[10][16];
+	struct rte_ipv6_addr ips[10];
 	int32_t next_hop_return[10];
 	int32_t status = 0;
 
@@ -373,7 +374,7 @@ test7(void)
 	config.flags = 0;
 
 	/* rte_lpm6_lookup: lpm == NULL */
-	status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10);
+	status = rte_lpm6_lookup_bulk_func(NULL, ips, next_hop_return, RTE_DIM(ips));
 	TEST_LPM_ASSERT(status < 0);
 
 	/*Create valid lpm to use in rest of test. */
@@ -381,11 +382,11 @@ test7(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	/* rte_lpm6_lookup: ip = NULL */
-	status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10);
+	status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, RTE_DIM(ips));
 	TEST_LPM_ASSERT(status < 0);
 
 	/* rte_lpm6_lookup: next_hop = NULL */
-	status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10);
+	status = rte_lpm6_lookup_bulk_func(lpm, ips, NULL, RTE_DIM(ips));
 	TEST_LPM_ASSERT(status < 0);
 
 	rte_lpm6_free(lpm);
@@ -402,7 +403,7 @@ test8(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[10][16];
+	struct rte_ipv6_addr ips[10];
 	uint8_t depth[10];
 	int32_t status = 0;
 
@@ -411,7 +412,7 @@ test8(void)
 	config.flags = 0;
 
 	/* rte_lpm6_delete: lpm == NULL */
-	status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10);
+	status = rte_lpm6_delete_bulk_func(NULL, ips, depth, RTE_DIM(ips));
 	TEST_LPM_ASSERT(status < 0);
 
 	/*Create valid lpm to use in rest of test. */
@@ -419,11 +420,11 @@ test8(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	/* rte_lpm6_delete: ip = NULL */
-	status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10);
+	status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, RTE_DIM(ips));
 	TEST_LPM_ASSERT(status < 0);
 
 	/* rte_lpm6_delete: next_hop = NULL */
-	status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10);
+	status = rte_lpm6_delete_bulk_func(lpm, ips, NULL, RTE_DIM(ips));
 	TEST_LPM_ASSERT(status < 0);
 
 	rte_lpm6_free(lpm);
@@ -441,7 +442,7 @@ test9(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth = 16;
 	uint32_t next_hop_add = 100, next_hop_return = 0;
 	int32_t status = 0;
@@ -454,21 +455,21 @@ test9(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	for (i = 0; i < UINT8_MAX; i++) {
-		ip[2] = i;
-		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+		ip.a[2] = i;
+		status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 		TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 	}
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
 	for (i = 0; i < UINT8_MAX; i++) {
-		ip[2] = i;
-		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+		ip.a[2] = i;
+		status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 		TEST_LPM_ASSERT(status == -ENOENT);
 	}
 
@@ -486,7 +487,7 @@ test10(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth;
 	uint32_t next_hop_add = 100;
 	int32_t status = 0;
@@ -501,20 +502,20 @@ test10(void)
 
 	for (i = 1; i < 128; i++) {
 		depth = (uint8_t)i;
-		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+		status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 		TEST_LPM_ASSERT(status == 0);
 	}
 
 	depth = 128;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == -ENOSPC);
 
 	depth = 127;
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 128;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	rte_lpm6_free(lpm);
@@ -531,7 +532,7 @@ test11(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth;
 	uint32_t next_hop_add = 100;
 	int32_t status = 0;
@@ -544,37 +545,37 @@ test11(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	depth = 128;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	ip[0] = 1;
+	ip.a[0] = 1;
 	depth = 25;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 33;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 41;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 49;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == -ENOSPC);
 
 	depth = 41;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	rte_lpm6_free(lpm);
@@ -592,7 +593,7 @@ test12(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth;
 	uint32_t next_hop_add = 100;
 	int32_t status = 0;
@@ -605,16 +606,16 @@ test12(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	depth = 128;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	ip[0] = 1;
+	ip.a[0] = 1;
 	depth = 41;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 49;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == -ENOSPC);
 
 	rte_lpm6_free(lpm);
@@ -631,7 +632,7 @@ test13(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth;
 	uint32_t next_hop_add = 100;
 	int32_t status = 0;
@@ -644,23 +645,23 @@ test13(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	depth = 1;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 2;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 3;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == -ENOSPC);
 
 	depth = 2;
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 3;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	rte_lpm6_free(lpm);
@@ -679,7 +680,7 @@ test14(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth = 25;
 	uint32_t next_hop_add = 100;
 	int32_t status = 0;
@@ -693,24 +694,24 @@ test14(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	for (i = 0; i < 256; i++) {
-		ip[0] = (uint8_t)i;
-		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+		ip.a[0] = (uint8_t)i;
+		status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 		TEST_LPM_ASSERT(status == 0);
 	}
 
-	ip[0] = 255;
-	ip[1] = 1;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	ip.a[0] = 255;
+	ip.a[1] = 1;
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == -ENOSPC);
 
-	ip[0] = 255;
-	ip[1] = 0;
-	status = rte_lpm6_delete(lpm, ip, depth);
+	ip.a[0] = 255;
+	ip.a[1] = 0;
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	ip[0] = 255;
-	ip[1] = 1;
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	ip.a[0] = 255;
+	ip.a[1] = 1;
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	rte_lpm6_free(lpm);
@@ -726,7 +727,7 @@ test15(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth = 24;
 	uint32_t next_hop_add = 100, next_hop_return = 0;
 	int32_t status = 0;
@@ -738,16 +739,16 @@ test15(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_free(lpm);
@@ -763,7 +764,7 @@ test16(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip = {.a = {12, 12, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
 	uint8_t depth = 128;
 	uint32_t next_hop_add = 100, next_hop_return = 0;
 	int32_t status = 0;
@@ -775,16 +776,16 @@ test16(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_free(lpm);
@@ -806,9 +807,13 @@ test17(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
-			255,255,255,255,255,255,255};
-	uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	struct rte_ipv6_addr ip1 = {
+		.a = {
+			127, 255, 255, 255, 255, 255, 255, 255,
+			255, 255, 255, 255, 255, 255, 255, 255
+		},
+	};
+	struct rte_ipv6_addr ip2 = {.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
 	uint8_t depth;
 	uint32_t next_hop_add, next_hop_return;
 	int32_t status = 0;
@@ -825,14 +830,14 @@ test17(void)
 		/* Let the next_hop_add value = depth. Just for change. */
 		next_hop_add = depth;
 
-		status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
+		status = rte_lpm6_add(lpm, &ip2, depth, next_hop_add);
 		TEST_LPM_ASSERT(status == 0);
 
 		/* Check IP in first half of tbl24 which should be empty. */
-		status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
+		status = rte_lpm6_lookup(lpm, &ip1, &next_hop_return);
 		TEST_LPM_ASSERT(status == -ENOENT);
 
-		status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
+		status = rte_lpm6_lookup(lpm, &ip2, &next_hop_return);
 		TEST_LPM_ASSERT((status == 0) &&
 			(next_hop_return == next_hop_add));
 	}
@@ -841,10 +846,10 @@ test17(void)
 	for (depth = 16; depth >= 1; depth--) {
 		next_hop_add = (depth - 1);
 
-		status = rte_lpm6_delete(lpm, ip2, depth);
+		status = rte_lpm6_delete(lpm, &ip2, depth);
 		TEST_LPM_ASSERT(status == 0);
 
-		status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
+		status = rte_lpm6_lookup(lpm, &ip2, &next_hop_return);
 
 		if (depth != 1) {
 			TEST_LPM_ASSERT((status == 0) &&
@@ -854,7 +859,7 @@ test17(void)
 			TEST_LPM_ASSERT(status == -ENOENT);
 		}
 
-		status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
+		status = rte_lpm6_lookup(lpm, &ip1, &next_hop_return);
 		TEST_LPM_ASSERT(status == -ENOENT);
 	}
 
@@ -874,7 +879,7 @@ test18(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[16], ip_1[16], ip_2[16];
+	struct rte_ipv6_addr ip, ip_1, ip_2;
 	uint8_t depth, depth_1, depth_2;
 	uint32_t next_hop_add, next_hop_add_1,
 			next_hop_add_2, next_hop_return;
@@ -885,58 +890,58 @@ test18(void)
 	config.flags = 0;
 
 	/* Add & lookup to hit invalid TBL24 entry */
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 24;
 	next_hop_add = 100;
 
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_delete_all(lpm);
 
 	/* Add & lookup to hit valid TBL24 entry not extended */
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 23;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
 	depth = 24;
 	next_hop_add = 101;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
 	depth = 24;
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
 	depth = 23;
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_delete_all(lpm);
@@ -944,37 +949,37 @@ test18(void)
 	/* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
 	 * entry.
 	 */
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 32;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 32;
 	next_hop_add = 101;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 32;
 	next_hop_add = 100;
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_delete_all(lpm);
@@ -982,38 +987,38 @@ test18(void)
 	/* Add & lookup to hit valid extended TBL24 entry with valid TBL8
 	 * entry
 	 */
-	IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth_1 = 25;
 	next_hop_add_1 = 101;
 
-	IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth_2 = 32;
 	next_hop_add_2 = 102;
 
 	next_hop_return = 0;
 
-	status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
+	status = rte_lpm6_add(lpm, &ip_1, depth_1, next_hop_add_1);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_1, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
 
-	status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
+	status = rte_lpm6_add(lpm, &ip_2, depth_2, next_hop_add_2);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_2, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
 
-	status = rte_lpm6_delete(lpm, ip_2, depth_2);
+	status = rte_lpm6_delete(lpm, &ip_2, depth_2);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_2, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
 
-	status = rte_lpm6_delete(lpm, ip_1, depth_1);
+	status = rte_lpm6_delete(lpm, &ip_1, depth_1);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_1, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_free(lpm);
@@ -1037,7 +1042,7 @@ test19(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[16];
+	struct rte_ipv6_addr ip;
 	uint8_t depth;
 	uint32_t next_hop_add, next_hop_return;
 	int32_t status = 0;
@@ -1052,35 +1057,35 @@ test19(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 16;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_delete_all(lpm);
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 25;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
 	rte_lpm6_delete_all(lpm);
@@ -1090,45 +1095,45 @@ test19(void)
 	 * (& delete & lookup)
 	 */
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 24;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 32;
 	next_hop_add = 101;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	next_hop_add = 100;
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 24;
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
-	IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 32;
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_delete_all(lpm);
@@ -1138,28 +1143,28 @@ test19(void)
 	 * (& delete & lookup)
 	 */
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 24;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
 	next_hop_add = 101;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_delete_all(lpm);
@@ -1169,56 +1174,56 @@ test19(void)
 	 * (& delete & lookup)
 	 */
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 32;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
 	next_hop_add = 101;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_delete_all(lpm);
 
 	/* Delete a rule that is not present in the TBL24 & lookup */
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 24;
 	next_hop_add = 100;
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status < 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_delete_all(lpm);
 
 	/* Delete a rule that is not present in the TBL8 & lookup */
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 32;
 	next_hop_add = 100;
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status < 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_free(lpm);
@@ -1236,7 +1241,7 @@ test20(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[16];
+	struct rte_ipv6_addr ip;
 	uint8_t depth;
 	uint32_t next_hop_add, next_hop_return;
 	int32_t status = 0;
@@ -1248,45 +1253,45 @@ test20(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 24;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
 	depth = 128;
 	next_hop_add = 101;
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	next_hop_add = 100;
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 24;
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
 	depth = 128;
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT(status == -ENOENT);
 
 	rte_lpm6_free(lpm);
@@ -1304,7 +1309,7 @@ test21(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip_batch[4][16];
+	struct rte_ipv6_addr ip_batch[4];
 	uint8_t depth;
 	uint32_t next_hop_add;
 	int32_t next_hop_return[4];
@@ -1317,28 +1322,28 @@ test21(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 48;
 	next_hop_add = 100;
 
-	status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip_batch[0], depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 48;
 	next_hop_add = 101;
 
-	status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip_batch[1], depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 48;
 	next_hop_add = 102;
 
-	status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip_batch[2], depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
 			next_hop_return, 4);
@@ -1363,7 +1368,7 @@ test22(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip_batch[5][16];
+	struct rte_ipv6_addr ip_batch[5];
 	uint8_t depth[5];
 	uint32_t next_hop_add;
 	int32_t next_hop_return[5];
@@ -1378,39 +1383,39 @@ test22(void)
 
 	/* Adds 5 rules and look them up */
 
-	IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth[0] = 48;
 	next_hop_add = 101;
 
-	status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
+	status = rte_lpm6_add(lpm, &ip_batch[0], depth[0], next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth[1] = 48;
 	next_hop_add = 102;
 
-	status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
+	status = rte_lpm6_add(lpm, &ip_batch[1], depth[1], next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth[2] = 48;
 	next_hop_add = 103;
 
-	status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
+	status = rte_lpm6_add(lpm, &ip_batch[2], depth[2], next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth[3] = 48;
 	next_hop_add = 104;
 
-	status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
+	status = rte_lpm6_add(lpm, &ip_batch[3], depth[3], next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth[4] = 48;
 	next_hop_add = 105;
 
-	status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
+	status = rte_lpm6_add(lpm, &ip_batch[4], depth[4], next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
@@ -1443,11 +1448,11 @@ test22(void)
 
 	/* Use the delete_bulk function to delete two, one invalid. Lookup again */
 
-	IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
 	TEST_LPM_ASSERT(status == 0);
 
-	IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
 			next_hop_return, 5);
 	TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
@@ -1481,7 +1486,7 @@ test23(void)
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
 	uint32_t i;
-	uint8_t ip[16];
+	struct rte_ipv6_addr ip;
 	uint8_t depth;
 	uint32_t next_hop_add, next_hop_return;
 	int32_t status = 0;
@@ -1493,22 +1498,22 @@ test23(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	IPv6(&ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 	depth = 128;
 	next_hop_add = 100;
 
 	for (i = 0; i < 30; i++) {
-		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+		status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 		TEST_LPM_ASSERT(status == 0);
 
-		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+		status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 		TEST_LPM_ASSERT((status == 0) &&
 				(next_hop_return == next_hop_add));
 
-		status = rte_lpm6_delete(lpm, ip, depth);
+		status = rte_lpm6_delete(lpm, &ip, depth);
 		TEST_LPM_ASSERT(status == 0);
 
-		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+		status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 		TEST_LPM_ASSERT(status == -ENOENT);
 	}
 
@@ -1565,7 +1570,7 @@ test25(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[16];
+	struct rte_ipv6_addr ip;
 	uint32_t i;
 	uint8_t depth;
 	uint32_t next_hop_add, next_hop_return, next_hop_expected;
@@ -1579,10 +1584,10 @@ test25(void)
 	TEST_LPM_ASSERT(lpm != NULL);
 
 	for (i = 0; i < 1000; i++) {
-		memcpy(ip, large_route_table[i].ip, 16);
+		memcpy(&ip, &large_route_table[i].ip, 16);
 		depth = large_route_table[i].depth;
 		next_hop_add = large_route_table[i].next_hop;
-		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+		status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 		TEST_LPM_ASSERT(status == 0);
 	}
 
@@ -1590,10 +1595,10 @@ test25(void)
 	generate_large_ips_table(1);
 
 	for (i = 0; i < 100000; i++) {
-		memcpy(ip, large_ips_table[i].ip, 16);
+		memcpy(&ip, &large_ips_table[i].ip, 16);
 		next_hop_expected = large_ips_table[i].next_hop;
 
-		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+		status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 		TEST_LPM_ASSERT((status == 0) &&
 				(next_hop_return == next_hop_expected));
 	}
@@ -1615,9 +1620,15 @@ test26(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	struct rte_ipv6_addr ip_10_32 = {
+		.a = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	};
+	struct rte_ipv6_addr ip_10_24 = {
+		.a = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	};
+	struct rte_ipv6_addr ip_20_25 = {
+		.a = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	};
 	uint8_t d_ip_10_32 = 32;
 	uint8_t	d_ip_10_24 = 24;
 	uint8_t	d_ip_20_25 = 25;
@@ -1634,29 +1645,26 @@ test26(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32,
-			next_hop_ip_10_32)) < 0)
-		return -1;
+	status = rte_lpm6_add(lpm, &ip_10_32, d_ip_10_32, next_hop_ip_10_32);
+	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_10_32, &next_hop_return);
 	uint32_t test_hop_10_32 = next_hop_return;
 	TEST_LPM_ASSERT(status == 0);
 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
 
-	if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24,
-			next_hop_ip_10_24)) < 0)
-			return -1;
+	status = rte_lpm6_add(lpm, &ip_10_24, d_ip_10_24, next_hop_ip_10_24);
+	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_10_24, &next_hop_return);
 	uint32_t test_hop_10_24 = next_hop_return;
 	TEST_LPM_ASSERT(status == 0);
 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
 
-	if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25,
-			next_hop_ip_20_25)) < 0)
-		return -1;
+	status = rte_lpm6_add(lpm, &ip_20_25, d_ip_20_25, next_hop_ip_20_25);
+	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_20_25, &next_hop_return);
 	uint32_t test_hop_20_25 = next_hop_return;
 	TEST_LPM_ASSERT(status == 0);
 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
@@ -1671,11 +1679,11 @@ test26(void)
 		return -1;
 	}
 
-	status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_10_32, &next_hop_return);
 	TEST_LPM_ASSERT(status == 0);
 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
 
-	status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip_10_24, &next_hop_return);
 	TEST_LPM_ASSERT(status == 0);
 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
 
@@ -1695,7 +1703,12 @@ test27(void)
 {
 		struct rte_lpm6 *lpm = NULL;
 		struct rte_lpm6_config config;
-		uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0};
+		struct rte_ipv6_addr ip = {
+			.a = {
+				128, 128, 128, 128, 128, 128, 128, 128,
+				128, 128, 128, 128, 128, 128, 0, 0
+			},
+		};
 		uint8_t depth = 128;
 		uint32_t next_hop_add = 100, next_hop_return;
 		int32_t status = 0;
@@ -1710,19 +1723,19 @@ test27(void)
 
 		depth = 128;
 		next_hop_add = 128;
-		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+		status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 		TEST_LPM_ASSERT(status == 0);
 
 		depth = 112;
 		next_hop_add = 112;
-		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+		status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 		TEST_LPM_ASSERT(status == 0);
 
 		for (i = 0; i < 256; i++) {
-			ip[14] = (uint8_t)i;
+			ip.a[14] = i;
 			for (j = 0; j < 256; j++) {
-				ip[15] = (uint8_t)j;
-				status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+				ip.a[15] = j;
+				status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 				if (i == 0 && j == 0)
 					TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
 				else
@@ -1746,7 +1759,9 @@ test28(void)
 {
 	struct rte_lpm6 *lpm = NULL;
 	struct rte_lpm6_config config;
-	uint8_t ip[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	struct rte_ipv6_addr ip = {
+		.a = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+	};
 	uint8_t depth = 16;
 	uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0;
 	int32_t status = 0;
@@ -1758,13 +1773,13 @@ test28(void)
 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
 	TEST_LPM_ASSERT(lpm != NULL);
 
-	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+	status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
 	TEST_LPM_ASSERT(status == 0);
 
-	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+	status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
 
-	status = rte_lpm6_delete(lpm, ip, depth);
+	status = rte_lpm6_delete(lpm, &ip, depth);
 	TEST_LPM_ASSERT(status == 0);
 	rte_lpm6_free(lpm);
 
diff --git a/app/test/test_lpm6_data.h b/app/test/test_lpm6_data.h
index 8ddb59563ee4..d9cb4cebb35d 100644
--- a/app/test/test_lpm6_data.h
+++ b/app/test/test_lpm6_data.h
@@ -7,16 +7,17 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+#include <rte_ip6.h>
 #include <rte_random.h>
 
 struct rules_tbl_entry {
-	uint8_t ip[16];
+	struct rte_ipv6_addr ip;
 	uint8_t depth;
 	uint8_t next_hop;
 };
 
 struct ips_tbl_entry {
-	uint8_t ip[16];
+	struct rte_ipv6_addr ip;
 	uint8_t next_hop;
 };
 
@@ -29,1006 +30,1006 @@ struct ips_tbl_entry {
  */
 
 static struct rules_tbl_entry large_route_table[] = {
-	{{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 146},
-	{{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 141},
-	{{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 67, 23},
-	{{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 97, 252},
-	{{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 6},
-	{{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 137},
-	{{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 9},
-	{{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 82, 9},
-	{{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 120, 163},
-	{{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 79, 197},
-	{{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 249},
-	{{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 88},
-	{{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 104},
-	{{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 36},
-	{{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 239},
-	{{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 201},
-	{{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 94},
-	{{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 241},
-	{{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 239},
-	{{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 151},
-	{{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 137},
-	{{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 231},
-	{{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 11},
-	{{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 96, 20},
-	{{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 68},
-	{{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 101, 64},
-	{{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 152},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 217},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 101},
-	{{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 58},
-	{{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 254},
-	{{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 148},
-	{{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126, 126},
-	{{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 123, 76},
-	{{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 240},
-	{{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 33},
-	{{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 47},
-	{{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 109, 41},
-	{{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 72},
-	{{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 43},
-	{{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 68, 26},
-	{{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 139},
-	{{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 219},
-	{{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 105},
-	{{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 210},
-	{{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 151},
-	{{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 28},
-	{{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 64},
-	{{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 121, 9},
-	{{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 92, 250},
-	{{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 200},
-	{{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 127, 132},
-	{{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 71, 182},
-	{{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 102, 7},
-	{{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 100, 146},
-	{{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 70, 98},
-	{{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 86, 179},
-	{{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 77, 245},
-	{{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
-	{{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 5},
-	{{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 169},
-	{{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 52},
-	{{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 177},
-	{{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 74},
-	{{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 122, 212},
-	{{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 122, 238},
-	{{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 18},
-	{{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 75, 155},
-	{{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 97},
-	{{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 8},
-	{{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 123},
-	{{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 92, 11},
-	{{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 211},
-	{{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 116},
-	{{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 57},
-	{{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 108, 178},
-	{{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 102, 93},
-	{{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 92, 3},
-	{{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 121, 162},
-	{{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 109, 125},
-	{{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 33},
-	{{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 254},
-	{{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 74, 66},
-	{{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 4},
-	{{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 86, 122},
-	{{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 59},
-	{{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 117, 99},
-	{{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 41},
-	{{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 112},
-	{{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 85, 255},
-	{{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 106},
-	{{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 170},
-	{{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 86},
-	{{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 79, 155},
-	{{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 65},
-	{{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 39},
-	{{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 90, 162},
-	{{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 69},
-	{{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 163},
-	{{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 90, 116},
-	{{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 19},
-	{{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 48},
-	{{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 230},
-	{{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 78, 155},
-	{{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 96, 158},
-	{{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 113, 252},
-	{{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 110, 176},
-	{{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 66, 211},
-	{{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 15},
-	{{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 68, 95},
-	{{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 169},
-	{{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 249},
-	{{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 105, 61},
-	{{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 63},
-	{{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 43},
-	{{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 81, 228},
-	{{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 78, 165},
-	{{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
-	{{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 211},
-	{{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 210},
-	{{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 99, 61},
-	{{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 120},
-	{{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 94},
-	{{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 153},
-	{{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 221},
-	{{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 87, 163},
-	{{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 106, 188},
-	{{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 124, 15},
-	{{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 28},
-	{{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 84, 240},
-	{{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 93, 59},
-	{{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 90, 195},
-	{{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 66, 10},
-	{{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 88, 206},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 137},
-	{{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 225},
-	{{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 223},
-	{{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 29},
-	{{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 103, 166},
-	{{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 80, 178},
-	{{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 38},
-	{{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 141},
-	{{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 116, 230},
-	{{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 99, 124},
-	{{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 118, 54},
-	{{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 162},
-	{{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 32},
-	{{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 102, 237},
-	{{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 215},
-	{{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 138},
-	{{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 118, 73},
-	{{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 90, 43},
-	{{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 112, 88},
-	{{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 119, 91},
-	{{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 69, 140},
-	{{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 65},
-	{{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 122, 201},
-	{{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 72, 69},
-	{{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 170},
-	{{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 192},
-	{{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 89, 21},
-	{{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 35},
-	{{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 71, 235},
-	{{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 240},
-	{{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 136},
-	{{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 186},
-	{{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 95, 174},
-	{{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 79, 153},
-	{{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 118},
-	{{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 113},
-	{{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 58},
-	{{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 101, 206},
-	{{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 111, 42},
-	{{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 230},
-	{{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 67, 6},
-	{{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 254},
-	{{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 108, 214},
-	{{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 107, 43},
-	{{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 178},
-	{{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 179},
-	{{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 87, 236},
-	{{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 98, 184},
-	{{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 91, 95},
-	{{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 127, 152},
-	{{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 113},
-	{{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 108, 137},
-	{{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 224},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 61},
-	{{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 205},
-	{{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 124, 170},
-	{{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 117},
-	{{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 70, 225},
-	{{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 72, 34},
-	{{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 5},
-	{{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 92},
-	{{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 230},
-	{{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 112, 61},
-	{{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 117, 221},
-	{{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 121, 105},
-	{{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 181},
-	{{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 79, 110},
-	{{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 86, 103},
-	{{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 123, 218},
-	{{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 146},
-	{{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 90},
-	{{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 108, 197},
-	{{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 103, 158},
-	{{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 81, 118},
-	{{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 95},
-	{{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 152},
-	{{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 239},
-	{{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 48},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 228},
-	{{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 247},
-	{{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 85, 12},
-	{{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 129},
-	{{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 50},
-	{{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 128, 250},
-	{{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 77, 249},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 230},
-	{{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 92, 228},
-	{{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 181},
-	{{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 206},
-	{{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 122},
-	{{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 72, 81},
-	{{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 95, 175},
-	{{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 118, 170},
-	{{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 174},
-	{{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 104},
-	{{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 114, 113},
-	{{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 80, 89},
-	{{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 113, 151},
-	{{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 108},
-	{{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 224},
-	{{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 95},
-	{{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 173},
-	{{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 93, 176},
-	{{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 119, 84},
-	{{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 78, 104},
-	{{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 236},
-	{{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 116, 153},
-	{{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 190},
-	{{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 202},
-	{{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 54},
-	{{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 156},
-	{{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 126, 245},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 218},
-	{{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 93, 72},
-	{{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 112, 183},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 183},
-	{{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 241},
-	{{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 106},
-	{{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 180},
-	{{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 96, 142},
-	{{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 100, 6},
-	{{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 118, 33},
-	{{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 224},
-	{{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 78, 14},
-	{{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 149},
-	{{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 108, 131},
-	{{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 121, 133},
-	{{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 89, 33},
-	{{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 204},
-	{{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 43},
-	{{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 168},
-	{{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 180},
-	{{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 112, 208},
-	{{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 90, 25},
-	{{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 111, 50},
-	{{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 109, 110},
-	{{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 109, 21},
-	{{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 147},
-	{{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 56},
-	{{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 117, 144},
-	{{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 100, 198},
-	{{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 90, 235},
-	{{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 105},
-	{{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 138},
-	{{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 122},
-	{{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 65, 193},
-	{{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 231},
-	{{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 250},
-	{{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 86, 24},
-	{{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 191},
-	{{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 117, 111},
-	{{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 111, 205},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 133},
-	{{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122, 122},
-	{{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 87, 227},
-	{{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 53},
-	{{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 72, 224},
-	{{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 199},
-	{{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 79},
-	{{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 19},
-	{{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 96, 211},
-	{{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 120, 6},
-	{{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 121, 143},
-	{{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 135},
-	{{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 109, 21},
-	{{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 220},
-	{{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 68, 151},
-	{{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 111},
-	{{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 63},
-	{{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 112},
-	{{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 48},
-	{{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 126, 100},
-	{{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 156},
-	{{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 95, 120},
-	{{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 5},
-	{{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 103},
-	{{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 84},
-	{{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 101, 24},
-	{{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 86, 81},
-	{{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 96},
-	{{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 121, 6},
-	{{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 119, 40},
-	{{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 143},
-	{{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 68, 69},
-	{{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 92, 48},
-	{{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 115},
-	{{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 115, 130},
-	{{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 86, 57},
-	{{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 97},
-	{{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 146},
-	{{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 117, 194},
-	{{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 114, 129},
-	{{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 97, 159},
-	{{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 117, 242},
-	{{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 104, 162},
-	{{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 102, 140},
-	{{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 113, 77},
-	{{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 82, 121},
-	{{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 69, 102},
-	{{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 28},
-	{{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 89, 154},
-	{{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 76, 39},
-	{{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 78, 163},
-	{{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 68, 42},
-	{{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 92, 207},
-	{{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 25},
-	{{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 150},
-	{{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 76, 103},
-	{{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 71, 155},
-	{{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 96, 142},
-	{{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 112, 2},
-	{{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 59},
-	{{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 112},
-	{{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 166},
-	{{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 73, 62},
-	{{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 176},
-	{{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 100, 6},
-	{{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 26},
-	{{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 6},
-	{{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 13},
-	{{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 41},
-	{{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 135},
-	{{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 93, 171},
-	{{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 20},
-	{{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 89, 119},
-	{{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 112, 49},
-	{{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 141},
-	{{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 132},
-	{{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 105, 176},
-	{{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 186},
-	{{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 93},
-	{{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 111, 242},
-	{{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 163},
-	{{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 184},
-	{{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 68, 188},
-	{{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 126, 193},
-	{{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 78, 63},
-	{{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 115, 160},
-	{{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 117, 251},
-	{{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 72, 228},
-	{{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 72, 168},
-	{{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 194},
-	{{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 166},
-	{{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 122, 210},
-	{{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 89, 254},
-	{{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 75, 49},
-	{{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 96, 95},
-	{{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 193},
-	{{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 155},
-	{{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 133},
-	{{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 10},
-	{{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 31},
-	{{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 127, 98},
-	{{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 96, 22},
-	{{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 214},
-	{{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 217},
-	{{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 98, 102},
-	{{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 83, 169},
-	{{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 152},
-	{{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 103, 214},
-	{{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 99, 178},
-	{{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 164},
-	{{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 15},
-	{{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 76, 94},
-	{{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 70, 239},
-	{{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 73, 82},
-	{{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 54},
-	{{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 98, 47},
-	{{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 84, 214},
-	{{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 215},
-	{{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 84, 153},
-	{{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 122, 245},
-	{{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 118},
-	{{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 123, 128},
-	{{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 7},
-	{{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 80, 152},
-	{{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 114, 248},
-	{{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 85, 143},
-	{{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 159},
-	{{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 11},
-	{{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 110},
-	{{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 97, 181},
-	{{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 121, 4},
-	{{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 101},
-	{{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 38},
-	{{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 78, 57},
-	{{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 142},
-	{{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 184},
-	{{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 91},
-	{{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 224},
-	{{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 78, 114},
-	{{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 118, 184},
-	{{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 215},
-	{{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 120, 167},
-	{{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 89, 233},
-	{{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 101},
-	{{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 67, 139},
-	{{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 79, 32},
-	{{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 57},
-	{{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 91, 151},
-	{{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 0},
-	{{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 227},
-	{{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 118, 124},
-	{{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 104, 228},
-	{{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 64},
-	{{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 179},
-	{{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 70, 107},
-	{{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 104, 206},
-	{{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 68, 95},
-	{{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 96, 219},
-	{{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 119, 138},
-	{{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 84},
-	{{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 161},
-	{{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 25},
-	{{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 107, 113},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 46},
-	{{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 72},
-	{{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 93, 230},
-	{{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 117, 142},
-	{{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 134},
-	{{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 112, 100},
-	{{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 109, 45},
-	{{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 219},
-	{{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 52},
-	{{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 83, 240},
-	{{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 90, 13},
-	{{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 84, 191},
-	{{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 106, 95},
-	{{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 65},
-	{{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 195},
-	{{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 103, 21},
-	{{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 114},
-	{{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 92},
-	{{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 237},
-	{{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 125, 172},
-	{{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 98, 116},
-	{{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 54},
-	{{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 203},
-	{{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 74},
-	{{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 96, 220},
-	{{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 219},
-	{{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 179},
-	{{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 194},
-	{{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 187},
-	{{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 79},
-	{{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 87},
-	{{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 126},
-	{{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 106},
-	{{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 96},
-	{{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 45},
-	{{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 110, 8},
-	{{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 226},
-	{{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 222},
-	{{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 71, 218},
-	{{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 116, 59},
-	{{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 80},
-	{{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 177},
-	{{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 98, 44},
-	{{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 93, 206},
-	{{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 64},
-	{{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 96, 236},
-	{{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 101},
-	{{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 49},
-	{{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 179},
-	{{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 109, 112},
-	{{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 96, 31},
-	{{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 111},
-	{{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 86, 65},
-	{{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 78, 222},
-	{{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 4},
-	{{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 67},
-	{{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 109, 197},
-	{{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 121},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 167},
-	{{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 140},
-	{{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 106, 193},
-	{{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 90, 47},
-	{{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 187},
-	{{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 102},
-	{{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 237},
-	{{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 103, 237},
-	{{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 107, 115},
-	{{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 84, 217},
-	{{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 79, 21},
-	{{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 113, 3},
-	{{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 62},
-	{{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 80},
-	{{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 184},
-	{{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 80, 197},
-	{{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 63},
-	{{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 99, 62},
-	{{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 114, 231},
-	{{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 158},
-	{{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 101, 118},
-	{{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 237},
-	{{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 79, 15},
-	{{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 122, 84},
-	{{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 119, 205},
-	{{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 82, 220},
-	{{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 42},
-	{{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 144},
-	{{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 74},
-	{{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 89},
-	{{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 88, 77},
-	{{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 94, 2},
-	{{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 75},
-	{{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 65, 18},
-	{{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 246},
-	{{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 114, 10},
-	{{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 207},
-	{{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 68, 41},
-	{{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 89, 102},
-	{{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118, 118},
-	{{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 146},
-	{{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 104, 122},
-	{{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 107, 6},
-	{{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 18},
-	{{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 70, 83},
-	{{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 99, 90},
-	{{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 140},
-	{{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 242},
-	{{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 31},
-	{{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 111, 9},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 230},
-	{{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 50},
-	{{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 34},
-	{{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 11},
-	{{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 71},
-	{{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 146},
-	{{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 124, 249},
-	{{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 143},
-	{{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 110, 17},
-	{{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 119, 60},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 162},
-	{{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 5},
-	{{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 139},
-	{{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 8},
-	{{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 114, 246},
-	{{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 171},
-	{{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 88, 206},
-	{{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 163},
-	{{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 166},
-	{{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 128},
-	{{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 59},
-	{{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 179},
-	{{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 124, 87},
-	{{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 114, 29},
-	{{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 91, 184},
-	{{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 45},
-	{{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 144},
-	{{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 114, 119},
-	{{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 113},
-	{{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 82, 50},
-	{{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 207},
-	{{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 3},
-	{{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 13},
-	{{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 42},
-	{{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 31},
-	{{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 94, 30},
-	{{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 94},
-	{{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 71, 190},
-	{{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 238},
-	{{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 20},
-	{{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 84},
-	{{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 108},
-	{{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 89, 136},
-	{{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 93, 196},
-	{{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 67},
-	{{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 104},
-	{{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 15},
-	{{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 128, 237},
-	{{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 116, 224},
-	{{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 179},
-	{{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 84},
-	{{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 65},
-	{{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 178},
-	{{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 154},
-	{{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 106},
-	{{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 125},
-	{{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 118},
-	{{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 73, 52},
-	{{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 173},
-	{{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 113, 8},
-	{{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 74, 211},
-	{{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 253},
-	{{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 47},
-	{{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 112, 73},
-	{{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 192},
-	{{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 128, 55},
-	{{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 94, 147},
-	{{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 125, 86},
-	{{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 82, 16},
-	{{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 111, 167},
-	{{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 148},
-	{{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 66},
-	{{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 104, 70},
-	{{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 166},
-	{{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 109},
-	{{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 226},
-	{{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 8},
-	{{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 85, 218},
-	{{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 78, 54},
-	{{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 67, 48},
-	{{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 244},
-	{{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 74, 50},
-	{{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 173},
-	{{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 84, 245},
-	{{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 121, 54},
-	{{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 113, 86},
-	{{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 115},
-	{{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 144},
-	{{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 89, 171},
-	{{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 93, 231},
-	{{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 88, 34},
-	{{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 225},
-	{{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 174},
-	{{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 113, 37},
-	{{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 121, 39},
-	{{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 59},
-	{{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 96},
-	{{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 147},
-	{{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 110, 56},
-	{{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 111, 234},
-	{{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 199},
-	{{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 69, 191},
-	{{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 235},
-	{{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 45},
-	{{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 67, 164},
-	{{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 121, 130},
-	{{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 166},
-	{{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 140},
-	{{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 118, 47},
-	{{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 111, 148},
-	{{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 103},
-	{{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 116, 94},
-	{{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 85},
-	{{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 109, 250},
-	{{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 153},
-	{{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 125, 182},
-	{{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 94, 23},
-	{{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 108, 38},
-	{{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 110, 121},
-	{{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 87, 146},
-	{{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 138},
-	{{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 94, 149},
-	{{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 88, 232},
-	{{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 255},
-	{{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 148},
-	{{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 117},
-	{{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 237},
-	{{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 113},
-	{{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 162},
-	{{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 225},
-	{{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 92, 210},
-	{{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 34},
-	{{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 224},
-	{{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 143},
-	{{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 68, 216},
-	{{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 120, 239},
-	{{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 111, 54},
-	{{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 35},
-	{{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 119, 230},
-	{{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 234},
-	{{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 115, 70},
-	{{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 246},
-	{{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 127, 217},
-	{{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 128, 201},
-	{{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 49},
-	{{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 2},
-	{{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 64},
-	{{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 239},
-	{{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 116, 47},
-	{{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 80, 43},
-	{{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 94, 17},
-	{{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 5},
-	{{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 81, 240},
-	{{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 197},
-	{{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 84, 192},
-	{{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 160},
-	{{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 84, 199},
-	{{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 127, 217},
-	{{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 83, 75},
-	{{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 106, 222},
-	{{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 85, 39},
-	{{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 9},
-	{{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 217},
-	{{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 142},
-	{{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 18},
-	{{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 104, 180},
-	{{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 205},
-	{{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 251},
-	{{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 178},
-	{{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 198},
-	{{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 84},
-	{{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 66, 128},
-	{{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 97, 75},
-	{{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 101, 192},
-	{{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 114, 60},
-	{{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 169},
-	{{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 10},
-	{{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 118, 64},
-	{{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 127, 182},
-	{{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 29},
-	{{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 39},
-	{{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 93},
-	{{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 75, 228},
-	{{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 236},
-	{{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 190},
-	{{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 217},
-	{{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 93, 74},
-	{{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 180},
-	{{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 91},
-	{{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 230},
-	{{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 175},
-	{{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 75, 171},
-	{{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 120, 202},
-	{{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 113},
-	{{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 96, 187},
-	{{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 120, 38},
-	{{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 35},
-	{{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 115},
-	{{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 18},
-	{{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 34},
-	{{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 87, 75},
-	{{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 232},
-	{{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 91, 154},
-	{{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 195},
-	{{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 70, 122},
-	{{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 97},
-	{{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 220},
-	{{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 80},
-	{{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 77, 133},
-	{{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 93},
-	{{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 110, 176},
-	{{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 95, 68},
-	{{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 103, 247},
-	{{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 240},
-	{{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 74, 83},
-	{{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 132},
-	{{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 217},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 214},
-	{{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 193},
-	{{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 71, 61},
-	{{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 65},
-	{{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 91, 108},
-	{{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 244},
-	{{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 95, 194},
-	{{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 124, 82},
-	{{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 116, 45},
-	{{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 224},
-	{{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 17},
-	{{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 133},
-	{{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 85, 125},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 42},
-	{{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 96, 140},
-	{{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 91},
-	{{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 92},
-	{{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 125},
-	{{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 106, 249},
-	{{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 202},
-	{{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 107},
-	{{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 124},
-	{{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 57},
-	{{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 92, 181},
-	{{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 107},
-	{{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 128, 101},
-	{{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 102},
-	{{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 136},
-	{{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 114},
-	{{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 215},
-	{{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 79, 249},
-	{{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 88, 29},
-	{{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 71},
-	{{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 127, 112},
-	{{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 72},
-	{{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 73, 155},
-	{{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 66},
-	{{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 91, 77},
-	{{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 109},
-	{{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 72, 37},
-	{{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 91, 56},
-	{{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 103, 5},
-	{{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 15},
-	{{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 183},
-	{{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 105, 171},
-	{{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 112, 202},
-	{{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 136},
-	{{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 107},
-	{{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 87, 193},
-	{{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 4},
-	{{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 96, 68},
-	{{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 40},
-	{{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 255},
-	{{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 108},
-	{{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 219},
-	{{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 108, 12},
-	{{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 84},
-	{{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 96, 33},
-	{{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 91, 199},
-	{{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 52},
-	{{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 113, 184},
-	{{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 124},
-	{{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 109, 128},
-	{{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 255},
-	{{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 105, 146},
-	{{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 172},
-	{{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 70, 116},
-	{{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 189},
-	{{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 70, 10},
-	{{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 98, 184},
-	{{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 98},
-	{{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 37},
-	{{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 174},
-	{{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 251},
-	{{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 115},
-	{{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 107, 252},
-	{{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 176},
-	{{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 91, 155},
-	{{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 124, 36},
-	{{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 88, 202},
-	{{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 208},
-	{{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 77, 158},
-	{{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 72, 136},
-	{{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 191},
-	{{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 120, 126},
-	{{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 128, 139},
-	{{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 216},
-	{{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 93},
-	{{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 196},
-	{{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 81, 119},
-	{{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 104, 93},
-	{{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 96, 183},
-	{{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 207},
-	{{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 102},
-	{{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 36},
-	{{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 93, 41},
-	{{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 70},
-	{{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 218},
-	{{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 120, 226},
-	{{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 114, 25},
-	{{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 98, 6},
-	{{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 26},
-	{{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 149},
-	{{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 127},
-	{{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 144},
-	{{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 213},
-	{{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 115},
-	{{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 83, 146},
-	{{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 58},
-	{{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 222},
-	{{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 16},
-	{{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 65, 169},
-	{{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 175},
-	{{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 3},
-	{{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 96, 2},
-	{{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 193},
-	{{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 118, 151},
-	{{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 182},
-	{{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 148},
-	{{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 53},
-	{{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 87},
-	{{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 73, 235},
-	{{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 51},
-	{{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 116, 11},
-	{{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 68, 28},
-	{{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 96, 73},
-	{{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 216},
-	{{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 99},
-	{{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 35},
-	{{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 127, 195},
-	{{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 108, 176},
-	{{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 87, 217},
-	{{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 126, 244},
-	{{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 125},
-	{{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 219},
-	{{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 165},
-	{{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 117, 6},
-	{{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 47},
-	{{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 73},
-	{{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 98},
-	{{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 21},
-	{{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 142},
-	{{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 93, 34},
-	{{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 74, 41},
-	{{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 80},
-	{{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 11},
-	{{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 254},
-	{{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 95},
-	{{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 8},
-	{{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 212},
-	{{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 95, 217},
-	{{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 15},
-	{{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 84, 66},
-	{{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 122},
-	{{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 97, 12},
-	{{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 71, 171},
-	{{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 106, 42},
-	{{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 194},
-	{{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 107, 237},
-	{{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 93, 151},
-	{{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 109, 238},
-	{{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 128},
-	{{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 227},
-	{{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 127, 138},
-	{{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 60},
-	{{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 148},
-	{{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 128, 129},
-	{{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 202},
-	{{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 81, 88},
-	{{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 90, 3},
-	{{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 108, 243},
-	{{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 80, 95},
-	{{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 87, 255},
-	{{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 48},
-	{{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 38},
-	{{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 115, 20},
-	{{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 41},
-	{{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 92, 133},
-	{{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 95, 189},
-	{{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 95, 151},
-	{{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 68, 100},
-	{{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 118},
-	{{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 164},
-	{{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 98, 71},
-	{{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 251},
-	{{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 51},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 185},
-	{{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 144},
-	{{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 84, 51},
-	{{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 87, 32},
-	{{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 70, 137},
-	{{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 2},
-	{{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 163},
-	{{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 100, 162},
-	{{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 192},
-	{{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 185},
-	{{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 51},
-	{{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 93},
-	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 159},
-	{{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 72, 189},
-	{{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 248},
-	{{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 123, 38},
-	{{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 76, 167},
-	{{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 28},
-	{{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 125, 37},
-	{{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 107, 234},
-	{{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 70},
-	{{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 108, 50},
-	{{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 171},
-	{{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 113, 236},
-	{{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 3},
-	{{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 86, 64},
-	{{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 108, 213},
-	{{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 15},
-	{{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 145},
-	{{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 27},
-	{{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 127, 75},
-	{{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 123, 76},
-	{{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 113, 247},
-	{{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 121},
-	{{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 214},
-	{{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 221},
-	{{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 102},
-	{{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 191},
-	{{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 197},
-	{{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 79, 106},
+{{.a = {66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 146},
+{{.a = {107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 141},
+{{.a = {247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}}, 67, 23},
+{{.a = {48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}}, 97, 252},
+{{.a = {5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 6},
+{{.a = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 137},
+{{.a = {12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 31, 9},
+{{.a = {1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}}, 82, 9},
+{{.a = {215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}}, 120, 163},
+{{.a = {178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}}, 79, 197},
+{{.a = {212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 249},
+{{.a = {92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 88},
+{{.a = {118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 52, 104},
+{{.a = {86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 36},
+{{.a = {79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 239},
+{{.a = {163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}}, 67, 201},
+{{.a = {31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 94},
+{{.a = {108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 241},
+{{.a = {247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 239},
+{{.a = {24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}}, 66, 151},
+{{.a = {245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 12, 137},
+{{.a = {44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 41, 231},
+{{.a = {184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 44, 11},
+{{.a = {51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}}, 96, 20},
+{{.a = {48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 15, 68},
+{{.a = {143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}}, 101, 64},
+{{.a = {121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 152},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 6, 217},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2, 101},
+{{.a = {111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 15, 58},
+{{.a = {162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 27, 254},
+{{.a = {76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 148},
+{{.a = {80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}}, 126, 126},
+{{.a = {80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}}, 123, 76},
+{{.a = {39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 240},
+{{.a = {20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 33},
+{{.a = {125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 25, 47},
+{{.a = {26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}}, 109, 41},
+{{.a = {102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 72},
+{{.a = {85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 43},
+{{.a = {61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}}, 68, 26},
+{{.a = {0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 139},
+{{.a = {170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 219},
+{{.a = {61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 105},
+{{.a = {33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 210},
+{{.a = {51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 17, 151},
+{{.a = {106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 28},
+{{.a = {192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 64},
+{{.a = {239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}}, 121, 9},
+{{.a = {141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}}, 92, 250},
+{{.a = {110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}}, 66, 200},
+{{.a = {134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}}, 127, 132},
+{{.a = {253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}}, 71, 182},
+{{.a = {211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}}, 102, 7},
+{{.a = {200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}}, 100, 146},
+{{.a = {107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}}, 70, 98},
+{{.a = {93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}}, 86, 179},
+{{.a = {32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}}, 77, 245},
+{{.a = {167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}}, 64, 2},
+{{.a = {241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 17, 5},
+{{.a = {143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}}, 66, 169},
+{{.a = {167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 52},
+{{.a = {241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 177},
+{{.a = {238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 27, 74},
+{{.a = {203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}}, 122, 212},
+{{.a = {111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}}, 122, 238},
+{{.a = {59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 18},
+{{.a = {110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}}, 75, 155},
+{{.a = {152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 97},
+{{.a = {118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 8},
+{{.a = {70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 123},
+{{.a = {253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}}, 92, 11},
+{{.a = {166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 211},
+{{.a = {43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 20, 116},
+{{.a = {94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 57},
+{{.a = {182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}}, 108, 178},
+{{.a = {152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}}, 102, 93},
+{{.a = {106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}}, 92, 3},
+{{.a = {32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}}, 121, 162},
+{{.a = {79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}}, 109, 125},
+{{.a = {106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 33},
+{{.a = {190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 254},
+{{.a = {156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}}, 74, 66},
+{{.a = {64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 30, 4},
+{{.a = {115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}}, 86, 122},
+{{.a = {18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 59},
+{{.a = {55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}}, 117, 99},
+{{.a = {153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 27, 41},
+{{.a = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 112},
+{{.a = {49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}}, 85, 255},
+{{.a = {201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 44, 106},
+{{.a = {158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 170},
+{{.a = {5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 86},
+{{.a = {34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}}, 79, 155},
+{{.a = {21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 35, 65},
+{{.a = {203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 36, 39},
+{{.a = {211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}}, 90, 162},
+{{.a = {77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 69},
+{{.a = {158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}}, 64, 163},
+{{.a = {61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}}, 90, 116},
+{{.a = {241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 53, 19},
+{{.a = {61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 36, 48},
+{{.a = {102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 230},
+{{.a = {74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}}, 78, 155},
+{{.a = {44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}}, 96, 158},
+{{.a = {67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}}, 113, 252},
+{{.a = {209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}}, 110, 176},
+{{.a = {4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}}, 66, 211},
+{{.a = {158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 15},
+{{.a = {85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}}, 68, 95},
+{{.a = {181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 169},
+{{.a = {26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 44, 249},
+{{.a = {5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}}, 105, 61},
+{{.a = {211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 23, 63},
+{{.a = {117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 14, 43},
+{{.a = {103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}}, 81, 228},
+{{.a = {192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}}, 78, 165},
+{{.a = {199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}}, 64, 3},
+{{.a = {157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 57, 211},
+{{.a = {27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 210},
+{{.a = {72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}}, 99, 61},
+{{.a = {34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 120},
+{{.a = {215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 94},
+{{.a = {31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 41, 153},
+{{.a = {153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 221},
+{{.a = {162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}}, 87, 163},
+{{.a = {218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}}, 106, 188},
+{{.a = {200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}}, 124, 15},
+{{.a = {74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}}, 63, 28},
+{{.a = {163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}}, 84, 240},
+{{.a = {20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}}, 93, 59},
+{{.a = {95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}}, 90, 195},
+{{.a = {155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}}, 66, 10},
+{{.a = {179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}}, 88, 206},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2, 137},
+{{.a = {3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 225},
+{{.a = {13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 223},
+{{.a = {117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 15, 29},
+{{.a = {164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}}, 103, 166},
+{{.a = {40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}}, 80, 178},
+{{.a = {222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 38},
+{{.a = {174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 141},
+{{.a = {6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}}, 116, 230},
+{{.a = {75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}}, 99, 124},
+{{.a = {38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}}, 118, 54},
+{{.a = {111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 162},
+{{.a = {105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 32},
+{{.a = {143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}}, 102, 237},
+{{.a = {30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 7, 215},
+{{.a = {14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 138},
+{{.a = {14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}}, 118, 73},
+{{.a = {22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}}, 90, 43},
+{{.a = {11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}}, 112, 88},
+{{.a = {14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}}, 119, 91},
+{{.a = {15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}}, 69, 140},
+{{.a = {0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 37, 65},
+{{.a = {178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}}, 122, 201},
+{{.a = {118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}}, 72, 69},
+{{.a = {21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 35, 170},
+{{.a = {5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 192},
+{{.a = {47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}}, 89, 21},
+{{.a = {242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 35},
+{{.a = {121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}}, 71, 235},
+{{.a = {9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 21, 240},
+{{.a = {45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 30, 136},
+{{.a = {127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}}, 60, 186},
+{{.a = {247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}}, 95, 174},
+{{.a = {126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}}, 79, 153},
+{{.a = {3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 35, 118},
+{{.a = {167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}}, 60, 113},
+{{.a = {76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 6, 58},
+{{.a = {58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}}, 101, 206},
+{{.a = {254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}}, 111, 42},
+{{.a = {77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 230},
+{{.a = {65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}}, 67, 6},
+{{.a = {47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 254},
+{{.a = {172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}}, 108, 214},
+{{.a = {254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}}, 107, 43},
+{{.a = {113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}}, 67, 178},
+{{.a = {178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 179},
+{{.a = {229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}}, 87, 236},
+{{.a = {156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}}, 98, 184},
+{{.a = {28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}}, 91, 95},
+{{.a = {217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}}, 127, 152},
+{{.a = {64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2, 113},
+{{.a = {85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}}, 108, 137},
+{{.a = {104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 224},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 6, 61},
+{{.a = {241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 41, 205},
+{{.a = {29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}}, 124, 170},
+{{.a = {58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 53, 117},
+{{.a = {213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}}, 70, 225},
+{{.a = {164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}}, 72, 34},
+{{.a = {186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 17, 5},
+{{.a = {237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 92},
+{{.a = {155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 230},
+{{.a = {35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}}, 112, 61},
+{{.a = {207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}}, 117, 221},
+{{.a = {86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}}, 121, 105},
+{{.a = {104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 181},
+{{.a = {205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}}, 79, 110},
+{{.a = {117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}}, 86, 103},
+{{.a = {74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}}, 123, 218},
+{{.a = {12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 56, 146},
+{{.a = {11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}}, 67, 90},
+{{.a = {235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}}, 108, 197},
+{{.a = {35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}}, 103, 158},
+{{.a = {174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}}, 81, 118},
+{{.a = {65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 95},
+{{.a = {253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 152},
+{{.a = {111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 239},
+{{.a = {202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 48},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5, 228},
+{{.a = {244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 30, 247},
+{{.a = {151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}}, 85, 12},
+{{.a = {60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 129},
+{{.a = {208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 50},
+{{.a = {126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}}, 128, 250},
+{{.a = {217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}}, 77, 249},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 1, 230},
+{{.a = {145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}}, 92, 228},
+{{.a = {108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}}, 64, 181},
+{{.a = {153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 206},
+{{.a = {22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}}, 63, 122},
+{{.a = {158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}}, 72, 81},
+{{.a = {236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}}, 95, 175},
+{{.a = {94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}}, 118, 170},
+{{.a = {187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 174},
+{{.a = {90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 104},
+{{.a = {194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}}, 114, 113},
+{{.a = {24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}}, 80, 89},
+{{.a = {231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}}, 113, 151},
+{{.a = {225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 108},
+{{.a = {136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 7, 224},
+{{.a = {250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 95},
+{{.a = {72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 14, 173},
+{{.a = {185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}}, 93, 176},
+{{.a = {57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}}, 119, 84},
+{{.a = {254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}}, 78, 104},
+{{.a = {247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 236},
+{{.a = {50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}}, 116, 153},
+{{.a = {62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 190},
+{{.a = {53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 202},
+{{.a = {198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 54},
+{{.a = {189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 156},
+{{.a = {110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}}, 126, 245},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 6, 218},
+{{.a = {74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}}, 93, 72},
+{{.a = {31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}}, 112, 183},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2, 183},
+{{.a = {63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 241},
+{{.a = {53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 106},
+{{.a = {184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 180},
+{{.a = {222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}}, 96, 142},
+{{.a = {199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}}, 100, 6},
+{{.a = {44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}}, 118, 33},
+{{.a = {33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 224},
+{{.a = {54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}}, 78, 14},
+{{.a = {241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 149},
+{{.a = {221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}}, 108, 131},
+{{.a = {102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}}, 121, 133},
+{{.a = {107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}}, 89, 33},
+{{.a = {54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 204},
+{{.a = {149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 52, 43},
+{{.a = {95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 168},
+{{.a = {63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 180},
+{{.a = {64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}}, 112, 208},
+{{.a = {113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}}, 90, 25},
+{{.a = {75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}}, 111, 50},
+{{.a = {52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}}, 109, 110},
+{{.a = {248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}}, 109, 21},
+{{.a = {136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 36, 147},
+{{.a = {1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 43, 56},
+{{.a = {181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}}, 117, 144},
+{{.a = {191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}}, 100, 198},
+{{.a = {201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}}, 90, 235},
+{{.a = {143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 38, 105},
+{{.a = {65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 138},
+{{.a = {136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 122},
+{{.a = {94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}}, 65, 193},
+{{.a = {236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 43, 231},
+{{.a = {1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}}, 64, 250},
+{{.a = {83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}}, 86, 24},
+{{.a = {76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 191},
+{{.a = {10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}}, 117, 111},
+{{.a = {74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}}, 111, 205},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 1, 133},
+{{.a = {127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}}, 122, 122},
+{{.a = {201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}}, 87, 227},
+{{.a = {147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 53},
+{{.a = {93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}}, 72, 224},
+{{.a = {144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 26, 199},
+{{.a = {116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 17, 79},
+{{.a = {142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 21, 19},
+{{.a = {97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}}, 96, 211},
+{{.a = {114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}}, 120, 6},
+{{.a = {224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}}, 121, 143},
+{{.a = {139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 31, 135},
+{{.a = {203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}}, 109, 21},
+{{.a = {237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 38, 220},
+{{.a = {182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}}, 68, 151},
+{{.a = {245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}}, 60, 111},
+{{.a = {107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 20, 63},
+{{.a = {119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 57, 112},
+{{.a = {178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 41, 48},
+{{.a = {109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}}, 126, 100},
+{{.a = {126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}}, 60, 156},
+{{.a = {211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}}, 95, 120},
+{{.a = {252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 5},
+{{.a = {192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 103},
+{{.a = {64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 84},
+{{.a = {225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}}, 101, 24},
+{{.a = {208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}}, 86, 81},
+{{.a = {178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 96},
+{{.a = {56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}}, 121, 6},
+{{.a = {80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}}, 119, 40},
+{{.a = {129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 143},
+{{.a = {85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}}, 68, 69},
+{{.a = {56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}}, 92, 48},
+{{.a = {229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}}, 64, 115},
+{{.a = {5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}}, 115, 130},
+{{.a = {24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}}, 86, 57},
+{{.a = {247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 97},
+{{.a = {12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 146},
+{{.a = {160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}}, 117, 194},
+{{.a = {152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}}, 114, 129},
+{{.a = {77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}}, 97, 159},
+{{.a = {183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}}, 117, 242},
+{{.a = {37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}}, 104, 162},
+{{.a = {198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}}, 102, 140},
+{{.a = {144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}}, 113, 77},
+{{.a = {68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}}, 82, 121},
+{{.a = {252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}}, 69, 102},
+{{.a = {28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 23, 28},
+{{.a = {24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}}, 89, 154},
+{{.a = {63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}}, 76, 39},
+{{.a = {56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}}, 78, 163},
+{{.a = {134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}}, 68, 42},
+{{.a = {143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}}, 92, 207},
+{{.a = {235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 25},
+{{.a = {46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 150},
+{{.a = {171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}}, 76, 103},
+{{.a = {220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}}, 71, 155},
+{{.a = {228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}}, 96, 142},
+{{.a = {195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}}, 112, 2},
+{{.a = {25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 59},
+{{.a = {160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 112},
+{{.a = {26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 48, 166},
+{{.a = {250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}}, 73, 62},
+{{.a = {175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 176},
+{{.a = {92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}}, 100, 6},
+{{.a = {45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 26},
+{{.a = {120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5, 6},
+{{.a = {216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5, 13},
+{{.a = {135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 37, 41},
+{{.a = {221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 36, 135},
+{{.a = {95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}}, 93, 171},
+{{.a = {202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 20},
+{{.a = {147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}}, 89, 119},
+{{.a = {137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}}, 112, 49},
+{{.a = {224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 141},
+{{.a = {250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 132},
+{{.a = {66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}}, 105, 176},
+{{.a = {76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 12, 186},
+{{.a = {120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}}, 67, 93},
+{{.a = {137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}}, 111, 242},
+{{.a = {255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 163},
+{{.a = {128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 184},
+{{.a = {45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}}, 68, 188},
+{{.a = {151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}}, 126, 193},
+{{.a = {148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}}, 78, 63},
+{{.a = {145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}}, 115, 160},
+{{.a = {78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}}, 117, 251},
+{{.a = {74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}}, 72, 228},
+{{.a = {89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}}, 72, 168},
+{{.a = {97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 194},
+{{.a = {213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 166},
+{{.a = {5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}}, 122, 210},
+{{.a = {77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}}, 89, 254},
+{{.a = {101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}}, 75, 49},
+{{.a = {58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}}, 96, 95},
+{{.a = {160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 193},
+{{.a = {94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 155},
+{{.a = {236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 15, 133},
+{{.a = {168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 38, 10},
+{{.a = {86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 31},
+{{.a = {232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}}, 127, 98},
+{{.a = {55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}}, 96, 22},
+{{.a = {142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 20, 214},
+{{.a = {213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 217},
+{{.a = {117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}}, 98, 102},
+{{.a = {120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}}, 83, 169},
+{{.a = {222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 27, 152},
+{{.a = {254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}}, 103, 214},
+{{.a = {192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}}, 99, 178},
+{{.a = {237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 164},
+{{.a = {6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 7, 15},
+{{.a = {71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}}, 76, 94},
+{{.a = {18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}}, 70, 239},
+{{.a = {32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}}, 73, 82},
+{{.a = {203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 54},
+{{.a = {56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}}, 98, 47},
+{{.a = {120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}}, 84, 214},
+{{.a = {64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 37, 215},
+{{.a = {91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}}, 84, 153},
+{{.a = {159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}}, 122, 245},
+{{.a = {123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 118},
+{{.a = {67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}}, 123, 128},
+{{.a = {103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 7},
+{{.a = {246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}}, 80, 152},
+{{.a = {205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}}, 114, 248},
+{{.a = {70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}}, 85, 143},
+{{.a = {250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 30, 159},
+{{.a = {122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 11},
+{{.a = {27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 31, 110},
+{{.a = {239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}}, 97, 181},
+{{.a = {144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}}, 121, 4},
+{{.a = {73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}}, 67, 101},
+{{.a = {18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 38},
+{{.a = {23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}}, 78, 57},
+{{.a = {200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 17, 142},
+{{.a = {181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 184},
+{{.a = {135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 27, 91},
+{{.a = {200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 41, 224},
+{{.a = {70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}}, 78, 114},
+{{.a = {158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}}, 118, 184},
+{{.a = {2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 215},
+{{.a = {33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}}, 120, 167},
+{{.a = {160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}}, 89, 233},
+{{.a = {32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 101},
+{{.a = {207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}}, 67, 139},
+{{.a = {210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}}, 79, 32},
+{{.a = {95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 57},
+{{.a = {129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}}, 91, 151},
+{{.a = {103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 0},
+{{.a = {41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}}, 63, 227},
+{{.a = {42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}}, 118, 124},
+{{.a = {165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}}, 104, 228},
+{{.a = {158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 27, 64},
+{{.a = {124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 25, 179},
+{{.a = {232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}}, 70, 107},
+{{.a = {70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}}, 104, 206},
+{{.a = {146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}}, 68, 95},
+{{.a = {162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}}, 96, 219},
+{{.a = {161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}}, 119, 138},
+{{.a = {248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 53, 84},
+{{.a = {8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 161},
+{{.a = {142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 52, 25},
+{{.a = {138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}}, 107, 113},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2, 46},
+{{.a = {175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}}, 63, 72},
+{{.a = {82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}}, 93, 230},
+{{.a = {227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}}, 117, 142},
+{{.a = {205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 41, 134},
+{{.a = {63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}}, 112, 100},
+{{.a = {213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}}, 109, 45},
+{{.a = {126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 30, 219},
+{{.a = {160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 52},
+{{.a = {137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}}, 83, 240},
+{{.a = {123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}}, 90, 13},
+{{.a = {163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}}, 84, 191},
+{{.a = {225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}}, 106, 95},
+{{.a = {91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 65},
+{{.a = {209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 195},
+{{.a = {57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}}, 103, 21},
+{{.a = {112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 114},
+{{.a = {102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 31, 92},
+{{.a = {137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 237},
+{{.a = {136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}}, 125, 172},
+{{.a = {57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}}, 98, 116},
+{{.a = {55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 54},
+{{.a = {44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 203},
+{{.a = {53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 74},
+{{.a = {227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}}, 96, 220},
+{{.a = {105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}}, 67, 219},
+{{.a = {96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 179},
+{{.a = {118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}}, 61, 194},
+{{.a = {101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 187},
+{{.a = {245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 79},
+{{.a = {0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 87},
+{{.a = {92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 126},
+{{.a = {125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 106},
+{{.a = {56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 96},
+{{.a = {184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 45},
+{{.a = {143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}}, 110, 8},
+{{.a = {30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 226},
+{{.a = {224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 36, 222},
+{{.a = {123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}}, 71, 218},
+{{.a = {166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}}, 116, 59},
+{{.a = {75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 80},
+{{.a = {197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 177},
+{{.a = {249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}}, 98, 44},
+{{.a = {180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}}, 93, 206},
+{{.a = {123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 27, 64},
+{{.a = {5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}}, 96, 236},
+{{.a = {159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 101},
+{{.a = {42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 26, 49},
+{{.a = {205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 179},
+{{.a = {19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}}, 109, 112},
+{{.a = {96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}}, 96, 31},
+{{.a = {120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 41, 111},
+{{.a = {110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}}, 86, 65},
+{{.a = {226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}}, 78, 222},
+{{.a = {89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 4},
+{{.a = {167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}}, 67, 67},
+{{.a = {57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}}, 109, 197},
+{{.a = {63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 121},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 1, 167},
+{{.a = {15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 38, 140},
+{{.a = {216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}}, 106, 193},
+{{.a = {158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}}, 90, 47},
+{{.a = {238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 21, 187},
+{{.a = {63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 56, 102},
+{{.a = {59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 237},
+{{.a = {2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}}, 103, 237},
+{{.a = {3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}}, 107, 115},
+{{.a = {17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}}, 84, 217},
+{{.a = {115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}}, 79, 21},
+{{.a = {191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}}, 113, 3},
+{{.a = {97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 48, 62},
+{{.a = {32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 80},
+{{.a = {29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 184},
+{{.a = {207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}}, 80, 197},
+{{.a = {129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 63},
+{{.a = {50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}}, 99, 62},
+{{.a = {105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}}, 114, 231},
+{{.a = {151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}}, 67, 158},
+{{.a = {236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}}, 101, 118},
+{{.a = {14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 30, 237},
+{{.a = {46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}}, 79, 15},
+{{.a = {88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}}, 122, 84},
+{{.a = {229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}}, 119, 205},
+{{.a = {121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}}, 82, 220},
+{{.a = {44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 42},
+{{.a = {209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 144},
+{{.a = {184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 37, 74},
+{{.a = {60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 89},
+{{.a = {18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}}, 88, 77},
+{{.a = {57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}}, 94, 2},
+{{.a = {168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 14, 75},
+{{.a = {64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}}, 65, 18},
+{{.a = {212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 246},
+{{.a = {155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}}, 114, 10},
+{{.a = {94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 14, 207},
+{{.a = {19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}}, 68, 41},
+{{.a = {24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}}, 89, 102},
+{{.a = {115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}}, 118, 118},
+{{.a = {250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 146},
+{{.a = {203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}}, 104, 122},
+{{.a = {196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}}, 107, 6},
+{{.a = {137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 18},
+{{.a = {236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}}, 70, 83},
+{{.a = {129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}}, 99, 90},
+{{.a = {7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 140},
+{{.a = {112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 242},
+{{.a = {167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 31},
+{{.a = {44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}}, 111, 9},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 1, 230},
+{{.a = {156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 50},
+{{.a = {67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 41, 34},
+{{.a = {134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 17, 11},
+{{.a = {35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8, 71},
+{{.a = {46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 146},
+{{.a = {82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}}, 124, 249},
+{{.a = {78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 39, 143},
+{{.a = {231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}}, 110, 17},
+{{.a = {38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}}, 119, 60},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 1, 162},
+{{.a = {95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 12, 5},
+{{.a = {17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 139},
+{{.a = {18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 39, 8},
+{{.a = {30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}}, 114, 246},
+{{.a = {18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 171},
+{{.a = {52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}}, 88, 206},
+{{.a = {166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 163},
+{{.a = {221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 166},
+{{.a = {94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 128},
+{{.a = {27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 31, 59},
+{{.a = {218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 179},
+{{.a = {9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}}, 124, 87},
+{{.a = {7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}}, 114, 29},
+{{.a = {47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}}, 91, 184},
+{{.a = {51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 14, 45},
+{{.a = {28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 144},
+{{.a = {34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}}, 114, 119},
+{{.a = {2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}}, 64, 113},
+{{.a = {51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}}, 82, 50},
+{{.a = {170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 56, 207},
+{{.a = {151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 21, 3},
+{{.a = {16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 13},
+{{.a = {205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}}, 59, 42},
+{{.a = {48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 31},
+{{.a = {179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}}, 94, 30},
+{{.a = {179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 94},
+{{.a = {17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}}, 71, 190},
+{{.a = {132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}}, 59, 238},
+{{.a = {16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 30, 20},
+{{.a = {189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 84},
+{{.a = {111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 108},
+{{.a = {118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}}, 89, 136},
+{{.a = {173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}}, 93, 196},
+{{.a = {26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 67},
+{{.a = {231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 12, 104},
+{{.a = {93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 15},
+{{.a = {53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}}, 128, 237},
+{{.a = {9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}}, 116, 224},
+{{.a = {99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 36, 179},
+{{.a = {18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}}, 67, 84},
+{{.a = {169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 65},
+{{.a = {136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5, 178},
+{{.a = {131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 154},
+{{.a = {75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 27, 106},
+{{.a = {212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}}, 67, 125},
+{{.a = {158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 118},
+{{.a = {7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}}, 73, 52},
+{{.a = {173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 173},
+{{.a = {109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}}, 113, 8},
+{{.a = {174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}}, 74, 211},
+{{.a = {22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}}, 61, 253},
+{{.a = {169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}}, 59, 47},
+{{.a = {154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}}, 112, 73},
+{{.a = {6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 192},
+{{.a = {216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}}, 128, 55},
+{{.a = {72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}}, 94, 147},
+{{.a = {150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}}, 125, 86},
+{{.a = {58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}}, 82, 16},
+{{.a = {7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}}, 111, 167},
+{{.a = {92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}}, 67, 148},
+{{.a = {169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 66},
+{{.a = {161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}}, 104, 70},
+{{.a = {71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 166},
+{{.a = {48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 44, 109},
+{{.a = {144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5, 226},
+{{.a = {223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 8},
+{{.a = {154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}}, 85, 218},
+{{.a = {1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}}, 78, 54},
+{{.a = {31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}}, 67, 48},
+{{.a = {14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 244},
+{{.a = {14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}}, 74, 50},
+{{.a = {122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 173},
+{{.a = {246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}}, 84, 245},
+{{.a = {77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}}, 121, 54},
+{{.a = {171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}}, 113, 86},
+{{.a = {128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2, 115},
+{{.a = {12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 144},
+{{.a = {255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}}, 89, 171},
+{{.a = {244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}}, 93, 231},
+{{.a = {221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}}, 88, 34},
+{{.a = {216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 53, 225},
+{{.a = {180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 38, 174},
+{{.a = {110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}}, 113, 37},
+{{.a = {27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}}, 121, 39},
+{{.a = {186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 23, 59},
+{{.a = {243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 96},
+{{.a = {160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 147},
+{{.a = {78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}}, 110, 56},
+{{.a = {201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}}, 111, 234},
+{{.a = {41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 199},
+{{.a = {91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}}, 69, 191},
+{{.a = {113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 235},
+{{.a = {181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 20, 45},
+{{.a = {87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}}, 67, 164},
+{{.a = {205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}}, 121, 130},
+{{.a = {136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 166},
+{{.a = {2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 140},
+{{.a = {222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}}, 118, 47},
+{{.a = {101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}}, 111, 148},
+{{.a = {96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 103},
+{{.a = {46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}}, 116, 94},
+{{.a = {111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 85},
+{{.a = {58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}}, 109, 250},
+{{.a = {141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 153},
+{{.a = {170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}}, 125, 182},
+{{.a = {34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}}, 94, 23},
+{{.a = {222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}}, 108, 38},
+{{.a = {179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}}, 110, 121},
+{{.a = {10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}}, 87, 146},
+{{.a = {210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 138},
+{{.a = {183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}}, 94, 149},
+{{.a = {29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}}, 88, 232},
+{{.a = {75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 255},
+{{.a = {92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 148},
+{{.a = {103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 48, 117},
+{{.a = {32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 14, 237},
+{{.a = {7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 113},
+{{.a = {167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 57, 162},
+{{.a = {21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 21, 225},
+{{.a = {92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}}, 92, 210},
+{{.a = {84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 34},
+{{.a = {126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 224},
+{{.a = {4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 143},
+{{.a = {239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}}, 68, 216},
+{{.a = {254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}}, 120, 239},
+{{.a = {225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}}, 111, 54},
+{{.a = {223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 35},
+{{.a = {235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}}, 119, 230},
+{{.a = {1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 234},
+{{.a = {149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}}, 115, 70},
+{{.a = {105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 246},
+{{.a = {189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}}, 127, 217},
+{{.a = {193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}}, 128, 201},
+{{.a = {110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 17, 49},
+{{.a = {3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 57, 2},
+{{.a = {81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 38, 64},
+{{.a = {168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 239},
+{{.a = {106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}}, 116, 47},
+{{.a = {46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}}, 80, 43},
+{{.a = {152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}}, 94, 17},
+{{.a = {109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 26, 5},
+{{.a = {100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}}, 81, 240},
+{{.a = {153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 197},
+{{.a = {43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}}, 84, 192},
+{{.a = {61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 160},
+{{.a = {119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}}, 84, 199},
+{{.a = {254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}}, 127, 217},
+{{.a = {176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}}, 83, 75},
+{{.a = {170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}}, 106, 222},
+{{.a = {102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}}, 85, 39},
+{{.a = {124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 9},
+{{.a = {192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 217},
+{{.a = {208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 25, 142},
+{{.a = {188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 18},
+{{.a = {114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}}, 104, 180},
+{{.a = {195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 56, 205},
+{{.a = {146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}}, 57, 251},
+{{.a = {185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 178},
+{{.a = {138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}}, 59, 198},
+{{.a = {69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 84},
+{{.a = {90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}}, 66, 128},
+{{.a = {20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}}, 97, 75},
+{{.a = {158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}}, 101, 192},
+{{.a = {125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}}, 114, 60},
+{{.a = {222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}}, 63, 169},
+{{.a = {104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 10},
+{{.a = {172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}}, 118, 64},
+{{.a = {190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}}, 127, 182},
+{{.a = {119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 29},
+{{.a = {160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 39},
+{{.a = {170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 93},
+{{.a = {234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}}, 75, 228},
+{{.a = {147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 236},
+{{.a = {182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 56, 190},
+{{.a = {116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 217},
+{{.a = {211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}}, 93, 74},
+{{.a = {148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 61, 180},
+{{.a = {172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 91},
+{{.a = {215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 230},
+{{.a = {151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 52, 175},
+{{.a = {73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}}, 75, 171},
+{{.a = {203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}}, 120, 202},
+{{.a = {251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 113},
+{{.a = {217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}}, 96, 187},
+{{.a = {16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}}, 120, 38},
+{{.a = {111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 26, 35},
+{{.a = {69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 38, 115},
+{{.a = {187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 18},
+{{.a = {230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 39, 34},
+{{.a = {179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}}, 87, 75},
+{{.a = {11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 232},
+{{.a = {217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}}, 91, 154},
+{{.a = {6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 195},
+{{.a = {157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}}, 70, 122},
+{{.a = {225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 97},
+{{.a = {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5, 220},
+{{.a = {166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 7, 80},
+{{.a = {29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}}, 77, 133},
+{{.a = {138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 38, 93},
+{{.a = {229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}}, 110, 176},
+{{.a = {6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}}, 95, 68},
+{{.a = {163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}}, 103, 247},
+{{.a = {2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 240},
+{{.a = {174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}}, 74, 83},
+{{.a = {5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 132},
+{{.a = {46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 217},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 214},
+{{.a = {233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 193},
+{{.a = {172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}}, 71, 61},
+{{.a = {241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 39, 65},
+{{.a = {31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}}, 91, 108},
+{{.a = {201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 244},
+{{.a = {187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}}, 95, 194},
+{{.a = {251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}}, 124, 82},
+{{.a = {66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}}, 116, 45},
+{{.a = {209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 48, 224},
+{{.a = {40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 17},
+{{.a = {72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 44, 133},
+{{.a = {171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}}, 85, 125},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 42},
+{{.a = {20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}}, 96, 140},
+{{.a = {243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 91},
+{{.a = {89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 48, 92},
+{{.a = {187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 125},
+{{.a = {172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}}, 106, 249},
+{{.a = {254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 202},
+{{.a = {80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 107},
+{{.a = {222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 13, 124},
+{{.a = {219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 53, 57},
+{{.a = {124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}}, 92, 181},
+{{.a = {195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 107},
+{{.a = {83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}}, 128, 101},
+{{.a = {112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 102},
+{{.a = {44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 136},
+{{.a = {41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 114},
+{{.a = {159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 215},
+{{.a = {42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}}, 79, 249},
+{{.a = {185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}}, 88, 29},
+{{.a = {22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 44, 71},
+{{.a = {122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}}, 127, 112},
+{{.a = {93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 31, 72},
+{{.a = {129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}}, 73, 155},
+{{.a = {30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}}, 61, 66},
+{{.a = {176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}}, 91, 77},
+{{.a = {96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 109},
+{{.a = {82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}}, 72, 37},
+{{.a = {242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}}, 91, 56},
+{{.a = {251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}}, 103, 5},
+{{.a = {62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 25, 15},
+{{.a = {214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 183},
+{{.a = {207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}}, 105, 171},
+{{.a = {196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}}, 112, 202},
+{{.a = {152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5, 136},
+{{.a = {9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 37, 107},
+{{.a = {89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}}, 87, 193},
+{{.a = {23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 52, 4},
+{{.a = {48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}}, 96, 68},
+{{.a = {252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 7, 40},
+{{.a = {20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 39, 255},
+{{.a = {167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 108},
+{{.a = {91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 14, 219},
+{{.a = {24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}}, 108, 12},
+{{.a = {156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 84},
+{{.a = {148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}}, 96, 33},
+{{.a = {38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}}, 91, 199},
+{{.a = {156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 52},
+{{.a = {100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}}, 113, 184},
+{{.a = {13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 124},
+{{.a = {29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}}, 109, 128},
+{{.a = {15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 255},
+{{.a = {80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}}, 105, 146},
+{{.a = {16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 24, 172},
+{{.a = {169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}}, 70, 116},
+{{.a = {144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}}, 66, 189},
+{{.a = {170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}}, 70, 10},
+{{.a = {232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}}, 98, 184},
+{{.a = {170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 33, 98},
+{{.a = {152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 37},
+{{.a = {174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 174},
+{{.a = {74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}}, 67, 251},
+{{.a = {167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 115},
+{{.a = {83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}}, 107, 252},
+{{.a = {83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 176},
+{{.a = {22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}}, 91, 155},
+{{.a = {250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}}, 124, 36},
+{{.a = {220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}}, 88, 202},
+{{.a = {160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5, 208},
+{{.a = {247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}}, 77, 158},
+{{.a = {78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}}, 72, 136},
+{{.a = {105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 191},
+{{.a = {14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}}, 120, 126},
+{{.a = {247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}}, 128, 139},
+{{.a = {136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 25, 216},
+{{.a = {100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 29, 93},
+{{.a = {80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 196},
+{{.a = {233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}}, 81, 119},
+{{.a = {107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}}, 104, 93},
+{{.a = {39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}}, 96, 183},
+{{.a = {10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 52, 207},
+{{.a = {151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 102},
+{{.a = {210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 19, 36},
+{{.a = {52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}}, 93, 41},
+{{.a = {123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 70},
+{{.a = {180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}}, 63, 218},
+{{.a = {77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}}, 120, 226},
+{{.a = {88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}}, 114, 25},
+{{.a = {90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}}, 98, 6},
+{{.a = {35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 26},
+{{.a = {103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 52, 149},
+{{.a = {50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 46, 127},
+{{.a = {140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}}, 62, 144},
+{{.a = {99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 56, 213},
+{{.a = {19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 115},
+{{.a = {153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}}, 83, 146},
+{{.a = {160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 26, 58},
+{{.a = {234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 222},
+{{.a = {97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 16},
+{{.a = {99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}}, 65, 169},
+{{.a = {169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 175},
+{{.a = {134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 3},
+{{.a = {231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}}, 96, 2},
+{{.a = {189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 36, 193},
+{{.a = {143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}}, 118, 151},
+{{.a = {32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 182},
+{{.a = {220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 148},
+{{.a = {206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 42, 53},
+{{.a = {152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 11, 87},
+{{.a = {58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}}, 73, 235},
+{{.a = {84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 23, 51},
+{{.a = {106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}}, 116, 11},
+{{.a = {53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}}, 68, 28},
+{{.a = {240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}}, 96, 73},
+{{.a = {234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 216},
+{{.a = {191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 16, 99},
+{{.a = {200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 35},
+{{.a = {29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}}, 127, 195},
+{{.a = {241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}}, 108, 176},
+{{.a = {77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}}, 87, 217},
+{{.a = {105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}}, 126, 244},
+{{.a = {160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 125},
+{{.a = {41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 219},
+{{.a = {116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 165},
+{{.a = {75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}}, 117, 6},
+{{.a = {229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 53, 47},
+{{.a = {83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 23, 73},
+{{.a = {151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 47, 98},
+{{.a = {171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 52, 21},
+{{.a = {7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 32, 142},
+{{.a = {103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}}, 93, 34},
+{{.a = {65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}}, 74, 41},
+{{.a = {235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 55, 80},
+{{.a = {156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 22, 11},
+{{.a = {92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}}, 58, 254},
+{{.a = {253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 45, 95},
+{{.a = {189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 40, 8},
+{{.a = {30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 14, 212},
+{{.a = {81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}}, 95, 217},
+{{.a = {126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 57, 15},
+{{.a = {42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}}, 84, 66},
+{{.a = {68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 122},
+{{.a = {183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}}, 97, 12},
+{{.a = {131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}}, 71, 171},
+{{.a = {31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}}, 106, 42},
+{{.a = {179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 28, 194},
+{{.a = {147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}}, 107, 237},
+{{.a = {177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}}, 93, 151},
+{{.a = {201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}}, 109, 238},
+{{.a = {4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}}, 59, 128},
+{{.a = {81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 26, 227},
+{{.a = {18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}}, 127, 138},
+{{.a = {31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 60},
+{{.a = {115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 18, 148},
+{{.a = {116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}}, 128, 129},
+{{.a = {117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 202},
+{{.a = {120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}}, 81, 88},
+{{.a = {87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}}, 90, 3},
+{{.a = {237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}}, 108, 243},
+{{.a = {214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}}, 80, 95},
+{{.a = {87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}}, 87, 255},
+{{.a = {0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 26, 48},
+{{.a = {227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 50, 38},
+{{.a = {174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}}, 115, 20},
+{{.a = {39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 43, 41},
+{{.a = {141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}}, 92, 133},
+{{.a = {93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}}, 95, 189},
+{{.a = {44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}}, 95, 151},
+{{.a = {213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}}, 68, 100},
+{{.a = {25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 49, 118},
+{{.a = {113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 34, 164},
+{{.a = {149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}}, 98, 71},
+{{.a = {39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 251},
+{{.a = {81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 57, 51},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3, 185},
+{{.a = {140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 144},
+{{.a = {6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}}, 84, 51},
+{{.a = {2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}}, 87, 32},
+{{.a = {112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}}, 70, 137},
+{{.a = {203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}}, 60, 2},
+{{.a = {99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}}, 63, 163},
+{{.a = {114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}}, 100, 162},
+{{.a = {161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10, 192},
+{{.a = {233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 36, 185},
+{{.a = {28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}}, 59, 51},
+{{.a = {146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 93},
+{{.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2, 159},
+{{.a = {141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}}, 72, 189},
+{{.a = {164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 21, 248},
+{{.a = {35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}}, 123, 38},
+{{.a = {193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}}, 76, 167},
+{{.a = {109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 28},
+{{.a = {160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}}, 125, 37},
+{{.a = {196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}}, 107, 234},
+{{.a = {228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9, 70},
+{{.a = {154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}}, 108, 50},
+{{.a = {41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 51, 171},
+{{.a = {81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}}, 113, 236},
+{{.a = {112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 4, 3},
+{{.a = {164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}}, 86, 64},
+{{.a = {138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}}, 108, 213},
+{{.a = {209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 54, 15},
+{{.a = {131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 20, 145},
+{{.a = {165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 57, 27},
+{{.a = {179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}}, 127, 75},
+{{.a = {98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}}, 123, 76},
+{{.a = {107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}}, 113, 247},
+{{.a = {143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 43, 121},
+{{.a = {155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 30, 214},
+{{.a = {58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 26, 221},
+{{.a = {92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}}, 63, 102},
+{{.a = {64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2, 191},
+{{.a = {63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 39, 197},
+{{.a = {234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}}, 79, 106},
 };
 
 #define  NUM_ROUTE_ENTRIES RTE_DIM(large_route_table)
@@ -1067,19 +1068,19 @@ static inline void mask_ip6_prefix(uint8_t *ip_out,
 /* check if IPv6 address ip[] match the rule with IPv6 address ip_rule[]
  * and depth. if matched, return 0, else return -1.
  */
-static inline int check_lpm6_rule(uint8_t *ip,
-	const uint8_t *ip_rule, uint8_t depth)
+static inline int check_lpm6_rule(const struct rte_ipv6_addr *ip,
+	const struct rte_ipv6_addr *ip_rule, uint8_t depth)
 {
 	int k;
 	uint8_t mask;
 
 	for (k = 0; k < 16; k++) {
 		if (depth >= 8) {
-			if (ip[k] != ip_rule[k])
+			if (ip->a[k] != ip_rule->a[k])
 				return -1;
 		} else if (depth > 0) {
 			mask = (uint8_t)((unsigned int)(-1) << (8 - depth));
-			if ((ip[k] & mask) == (ip_rule[k] & mask))
+			if ((ip->a[k] & mask) == (ip_rule->a[k] & mask))
 				return 0;
 			else
 				return -1;
@@ -1098,7 +1099,7 @@ static inline int check_lpm6_rule(uint8_t *ip,
  * if found that some item in rule[] is matched return 0,
  * else return -1;
  */
-static int get_next_hop(uint8_t *ip, uint8_t *next_hop,
+static int get_next_hop(const struct rte_ipv6_addr *ip, uint8_t *next_hop,
 	const struct rules_tbl_entry *rule, int rule_num)
 {
 	int i;
@@ -1107,7 +1108,7 @@ static int get_next_hop(uint8_t *ip, uint8_t *next_hop,
 
 	for (i = 0; i < rule_num; i++) {
 		if (rule[i].depth >= max_depth) {
-			result = check_lpm6_rule(ip, rule[i].ip, rule[i].depth);
+			result = check_lpm6_rule(ip, &rule[i].ip, rule[i].depth);
 			if (result == 0) {
 				*next_hop = rule[i].next_hop;
 				max_depth = rule[i].depth;
@@ -1131,12 +1132,12 @@ static void generate_large_ips_table(int gen_expected_next_hop)
 
 	for (i = 0; i < NUM_IPS_ENTRIES; i++) {
 		for (j = 0; j < 16; j++)
-			large_ips_table[i].ip[j] = rte_rand();
+			large_ips_table[i].ip.a[j] = rte_rand();
 	}
 
 	for (k = j = 0, i = 0; i < NUM_IPS_ENTRIES; i++) {
-		mask_ip6_prefix(large_ips_table[i].ip,
-			large_route_table[j].ip, large_route_table[j].depth);
+		mask_ip6_prefix(large_ips_table[i].ip.a,
+			large_route_table[j].ip.a, large_route_table[j].depth);
 		k++;
 		if (k == (NUM_IPS_ENTRIES / NUM_ROUTE_ENTRIES)) {
 			j++;
@@ -1150,7 +1151,7 @@ static void generate_large_ips_table(int gen_expected_next_hop)
 		return;
 
 	for (k = 0; k < NUM_IPS_ENTRIES; k++)
-		get_next_hop(large_ips_table[k].ip,
+		get_next_hop(&large_ips_table[k].ip,
 				&(large_ips_table[k].next_hop),
 				large_route_table,
 				NUM_ROUTE_ENTRIES);
diff --git a/app/test/test_lpm6_perf.c b/app/test/test_lpm6_perf.c
index c847dcb18375..0f9e3698c4da 100644
--- a/app/test/test_lpm6_perf.c
+++ b/app/test/test_lpm6_perf.c
@@ -82,7 +82,7 @@ test_lpm6_perf(void)
 	begin = rte_rdtsc();
 
 	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
-		if (rte_lpm6_add(lpm, large_route_table[i].ip,
+		if (rte_lpm6_add(lpm, &large_route_table[i].ip,
 				large_route_table[i].depth, next_hop_add) == 0)
 			status++;
 	}
@@ -101,7 +101,7 @@ test_lpm6_perf(void)
 		begin = rte_rdtsc();
 
 		for (j = 0; j < NUM_IPS_ENTRIES; j ++) {
-			if (rte_lpm6_lookup(lpm, large_ips_table[j].ip,
+			if (rte_lpm6_lookup(lpm, &large_ips_table[j].ip,
 					&next_hop_return) != 0)
 				count++;
 		}
@@ -117,11 +117,11 @@ test_lpm6_perf(void)
 	total_time = 0;
 	count = 0;
 
-	uint8_t ip_batch[NUM_IPS_ENTRIES][16];
+	struct rte_ipv6_addr ip_batch[NUM_IPS_ENTRIES];
 	int32_t next_hops[NUM_IPS_ENTRIES];
 
 	for (i = 0; i < NUM_IPS_ENTRIES; i++)
-		memcpy(ip_batch[i], large_ips_table[i].ip, 16);
+		memcpy(&ip_batch[i], &large_ips_table[i].ip, 16);
 
 	for (i = 0; i < ITERATIONS; i ++) {
 
@@ -144,7 +144,7 @@ test_lpm6_perf(void)
 
 	for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
 		/* rte_lpm_delete(lpm, ip, depth) */
-		status += rte_lpm6_delete(lpm, large_route_table[i].ip,
+		status += rte_lpm6_delete(lpm, &large_route_table[i].ip,
 				large_route_table[i].depth);
 	}
 
diff --git a/app/test/test_rib6.c b/app/test/test_rib6.c
index 33596fddb4e5..f3b6f1474348 100644
--- a/app/test/test_rib6.c
+++ b/app/test/test_rib6.c
@@ -6,7 +6,7 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
-#include <rte_ip.h>
+#include <rte_ip6.h>
 #include <rte_rib6.h>
 
 #include "test.h"
@@ -118,14 +118,14 @@ test_insert_invalid(void)
 	struct rte_rib6 *rib = NULL;
 	struct rte_rib6_node *node, *node1;
 	struct rte_rib6_conf config;
-	uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {0};
+	struct rte_ipv6_addr ip = {0};
 	uint8_t depth = 24;
 
 	config.max_nodes = MAX_RULES;
 	config.ext_sz = 0;
 
 	/* rte_rib6_insert: rib == NULL */
-	node = rte_rib6_insert(NULL, ip, depth);
+	node = rte_rib6_insert(NULL, &ip, depth);
 	RTE_TEST_ASSERT(node == NULL,
 		"Call succeeded with invalid parameters\n");
 
@@ -134,14 +134,14 @@ test_insert_invalid(void)
 	RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 
 	/* rte_rib6_insert: depth > MAX_DEPTH */
-	node = rte_rib6_insert(rib, ip, MAX_DEPTH + 1);
+	node = rte_rib6_insert(rib, &ip, MAX_DEPTH + 1);
 	RTE_TEST_ASSERT(node == NULL,
 		"Call succeeded with invalid parameters\n");
 
 	/* insert the same ip/depth twice*/
-	node = rte_rib6_insert(rib, ip, depth);
+	node = rte_rib6_insert(rib, &ip, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
-	node1 = rte_rib6_insert(rib, ip, depth);
+	node1 = rte_rib6_insert(rib, &ip, depth);
 	RTE_TEST_ASSERT(node1 == NULL,
 		"Call succeeded with invalid parameters\n");
 
@@ -162,9 +162,10 @@ test_get_fn(void)
 	struct rte_rib6_node *node;
 	struct rte_rib6_conf config;
 	void *ext;
-	uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {192, 0, 2, 0, 0, 0, 0, 0,
-						0, 0, 0, 0, 0, 0, 0, 0};
-	uint8_t ip_ret[RTE_RIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr ip = {
+		.a = {192, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	};
+	struct rte_ipv6_addr ip_ret;
 	uint64_t nh_set = 10;
 	uint64_t nh_ret;
 	uint8_t depth = 24;
@@ -177,11 +178,11 @@ test_get_fn(void)
 	rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
 	RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 
-	node = rte_rib6_insert(rib, ip, depth);
+	node = rte_rib6_insert(rib, &ip, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 
 	/* test rte_rib6_get_ip() with incorrect args */
-	ret = rte_rib6_get_ip(NULL, ip_ret);
+	ret = rte_rib6_get_ip(NULL, &ip_ret);
 	RTE_TEST_ASSERT(ret < 0,
 		"Call succeeded with invalid parameters\n");
 	ret = rte_rib6_get_ip(node, NULL);
@@ -215,8 +216,8 @@ test_get_fn(void)
 		"Call succeeded with invalid parameters\n");
 
 	/* check the return values */
-	ret = rte_rib6_get_ip(node, ip_ret);
-	RTE_TEST_ASSERT((ret == 0) && (rte_rib6_is_equal(ip_ret, ip)),
+	ret = rte_rib6_get_ip(node, &ip_ret);
+	RTE_TEST_ASSERT((ret == 0) && (rte_rib6_is_equal(ip_ret.a, ip.a)),
 		"Failed to get proper node ip\n");
 	ret = rte_rib6_get_depth(node, &depth_ret);
 	RTE_TEST_ASSERT((ret == 0) && (depth_ret == depth),
@@ -243,8 +244,9 @@ test_basic(void)
 	struct rte_rib6_node *node;
 	struct rte_rib6_conf config;
 
-	uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {192, 0, 2, 0, 0, 0, 0, 0,
-						0, 0, 0, 0, 0, 0, 0, 0};
+	struct rte_ipv6_addr ip = {
+		.a = {192, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	};
 	uint64_t next_hop_add = 10;
 	uint64_t next_hop_return;
 	uint8_t depth = 24;
@@ -256,21 +258,21 @@ test_basic(void)
 	rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
 	RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 
-	node = rte_rib6_insert(rib, ip, depth);
+	node = rte_rib6_insert(rib, &ip, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 
 	status = rte_rib6_set_nh(node, next_hop_add);
 	RTE_TEST_ASSERT(status == 0,
 		"Failed to set rte_rib_node field\n");
 
-	node = rte_rib6_lookup(rib, ip);
+	node = rte_rib6_lookup(rib, &ip);
 	RTE_TEST_ASSERT(node != NULL, "Failed to lookup\n");
 
 	status = rte_rib6_get_nh(node, &next_hop_return);
 	RTE_TEST_ASSERT((status == 0) && (next_hop_add == next_hop_return),
 		"Failed to get proper nexthop\n");
 
-	node = rte_rib6_lookup_exact(rib, ip, depth);
+	node = rte_rib6_lookup_exact(rib, &ip, depth);
 	RTE_TEST_ASSERT(node != NULL,
 		"Failed to lookup\n");
 
@@ -278,12 +280,12 @@ test_basic(void)
 	RTE_TEST_ASSERT((status == 0) && (next_hop_add == next_hop_return),
 		"Failed to get proper nexthop\n");
 
-	rte_rib6_remove(rib, ip, depth);
+	rte_rib6_remove(rib, &ip, depth);
 
-	node = rte_rib6_lookup(rib, ip);
+	node = rte_rib6_lookup(rib, &ip);
 	RTE_TEST_ASSERT(node == NULL,
 		"Lookup returns non existent rule\n");
-	node = rte_rib6_lookup_exact(rib, ip, depth);
+	node = rte_rib6_lookup_exact(rib, &ip, depth);
 	RTE_TEST_ASSERT(node == NULL,
 		"Lookup returns non existent rule\n");
 
@@ -299,12 +301,15 @@ test_tree_traversal(void)
 	struct rte_rib6_node *node;
 	struct rte_rib6_conf config;
 
-	uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 130, 0, 0, 0, 0,
-						0, 0, 0, 0, 0, 0, 0, 0};
-	uint8_t ip1[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 0, 0, 0, 0, 0,
-						0, 0, 0, 0, 0, 0, 0, 0};
-	uint8_t ip2[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 130, 0, 0, 0, 0,
-						0, 0, 0, 0, 0, 0, 0, 80};
+	struct rte_ipv6_addr ip = {
+		.a = {10, 0, 2, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	};
+	struct rte_ipv6_addr ip1 = {
+		.a = {10, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	};
+	struct rte_ipv6_addr ip2 = {
+		.a = {10, 0, 2, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80},
+	};
 	uint8_t depth = 126;
 
 	config.max_nodes = MAX_RULES;
@@ -313,13 +318,13 @@ test_tree_traversal(void)
 	rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
 	RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
 
-	node = rte_rib6_insert(rib, ip1, depth);
+	node = rte_rib6_insert(rib, &ip1, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
-	node = rte_rib6_insert(rib, ip2, depth);
+	node = rte_rib6_insert(rib, &ip2, depth);
 	RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
 
 	node = NULL;
-	node = rte_rib6_get_nxt(rib, ip, 32, node, RTE_RIB6_GET_NXT_ALL);
+	node = rte_rib6_get_nxt(rib, &ip, 32, node, RTE_RIB6_GET_NXT_ALL);
 	RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
 
 	rte_rib6_free(rib);
diff --git a/app/test/test_table_combined.c b/app/test/test_table_combined.c
index 1c2efe649ded..04503baa5180 100644
--- a/app/test/test_table_combined.c
+++ b/app/test/test_table_combined.c
@@ -362,7 +362,7 @@ test_table_lpm_ipv6_combined(void)
 	struct rte_table_lpm_ipv6_key lpm_ipv6_key = {
 		.depth = 16,
 	};
-	memset(lpm_ipv6_key.ip, 0xad, 16);
+	memset(&lpm_ipv6_key.ip, 0xad, 16);
 
 	struct table_packets table_packets;
 
diff --git a/app/test/test_table_tables.c b/app/test/test_table_tables.c
index 26908e6112fc..920aa555cbd2 100644
--- a/app/test/test_table_tables.c
+++ b/app/test/test_table_tables.c
@@ -525,10 +525,10 @@ test_table_lpm_ipv6(void)
 	/* Add */
 	struct rte_table_lpm_ipv6_key lpm_key;
 
-	lpm_key.ip[0] = 0xad;
-	lpm_key.ip[1] = 0xad;
-	lpm_key.ip[2] = 0xad;
-	lpm_key.ip[3] = 0xad;
+	lpm_key.ip.a[0] = 0xad;
+	lpm_key.ip.a[1] = 0xad;
+	lpm_key.ip.a[2] = 0xad;
+	lpm_key.ip.a[3] = 0xad;
 
 	table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
 	if (table == NULL)
diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c
index 4c0fa5054a2e..611b5818d88c 100644
--- a/examples/ip_fragmentation/main.c
+++ b/examples/ip_fragmentation/main.c
@@ -184,21 +184,21 @@ struct l3fwd_ipv4_route l3fwd_ipv4_route_array[] = {
  */
 
 struct l3fwd_ipv6_route {
-	uint8_t ip[IPV6_ADDR_LEN];
+	struct rte_ipv6_addr ip;
 	uint8_t depth;
 	uint8_t if_out;
 };
 
 /* Default l3fwd_ipv6_route_array table. 8< */
 static struct l3fwd_ipv6_route l3fwd_ipv6_route_array[] = {
-	{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 0},
-	{{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 1},
-	{{3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 2},
-	{{4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 3},
-	{{5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 4},
-	{{6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 5},
-	{{7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 6},
-	{{8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 7},
+	{{.a = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 0},
+	{{.a = {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 1},
+	{{.a = {3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 2},
+	{{.a = {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 3},
+	{{.a = {5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 4},
+	{{.a = {6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 5},
+	{{.a = {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 6},
+	{{.a = {8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 7},
 };
 /* >8 End of default l3fwd_ipv6_route_array table. */
 
@@ -311,7 +311,7 @@ l3fwd_simple_forward(struct rte_mbuf *m, struct lcore_queue_conf *qconf,
 		ip_hdr = rte_pktmbuf_mtod(m, struct rte_ipv6_hdr *);
 
 		/* Find destination port */
-		if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr.a,
+		if (rte_lpm6_lookup(rxq->lpm6, &ip_hdr->dst_addr,
 						&next_hop) == 0 &&
 				(enabled_port_mask & 1 << next_hop) != 0) {
 			port_out = next_hop;
@@ -751,7 +751,7 @@ init_routing_table(void)
 			/* populate the LPM6 table */
 			for (i = 0; i < RTE_DIM(l3fwd_ipv6_route_array); i++) {
 				ret = rte_lpm6_add(lpm6,
-					l3fwd_ipv6_route_array[i].ip,
+					&l3fwd_ipv6_route_array[i].ip,
 					l3fwd_ipv6_route_array[i].depth,
 					l3fwd_ipv6_route_array[i].if_out);
 
@@ -764,7 +764,7 @@ init_routing_table(void)
 				RTE_LOG(INFO, IP_FRAG, "Socket %i: adding route " IPv6_BYTES_FMT
 						"/%d (port %d)\n",
 					socket,
-					IPv6_BYTES(l3fwd_ipv6_route_array[i].ip),
+					IPv6_BYTES(l3fwd_ipv6_route_array[i].ip.a),
 					l3fwd_ipv6_route_array[i].depth,
 					l3fwd_ipv6_route_array[i].if_out);
 			}
diff --git a/examples/ip_pipeline/thread.c b/examples/ip_pipeline/thread.c
index 8a912dc1b392..9d8082b73080 100644
--- a/examples/ip_pipeline/thread.c
+++ b/examples/ip_pipeline/thread.c
@@ -2563,7 +2563,7 @@ match_convert(struct table_rule_match *mh,
 			ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
 			ml->lpm_ipv4.depth = mh->match.lpm.depth;
 		} else {
-			memcpy(ml->lpm_ipv6.ip,
+			memcpy(&ml->lpm_ipv6.ip,
 				mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
 			ml->lpm_ipv6.depth = mh->match.lpm.depth;
 		}
diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c
index 4da692eb23e6..06383cc36289 100644
--- a/examples/ip_reassembly/main.c
+++ b/examples/ip_reassembly/main.c
@@ -205,21 +205,21 @@ struct l3fwd_ipv4_route l3fwd_ipv4_route_array[] = {
  */
 
 struct l3fwd_ipv6_route {
-	uint8_t ip[IPV6_ADDR_LEN];
+	struct rte_ipv6_addr ip;
 	uint8_t depth;
 	uint8_t if_out;
 };
 
 /* Default l3fwd_ipv6_route_array table. 8< */
 static struct l3fwd_ipv6_route l3fwd_ipv6_route_array[] = {
-	{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 0},
-	{{2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 1},
-	{{3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 2},
-	{{4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 3},
-	{{5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 4},
-	{{6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 5},
-	{{7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 6},
-	{{8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 48, 7},
+	{{.a = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 0},
+	{{.a = {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 1},
+	{{.a = {3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 2},
+	{{.a = {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 3},
+	{{.a = {5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 4},
+	{{.a = {6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 5},
+	{{.a = {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 6},
+	{{.a = {8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}, 48, 7},
 };
 /* >8 End of default l3fwd_ipv6_route_array table. */
 
@@ -400,7 +400,7 @@ reassemble(struct rte_mbuf *m, uint16_t portid, uint32_t queue,
 		}
 
 		/* Find destination port */
-		if (rte_lpm6_lookup(rxq->lpm6, ip_hdr->dst_addr.a,
+		if (rte_lpm6_lookup(rxq->lpm6, &ip_hdr->dst_addr,
 						&next_hop) == 0 &&
 				(enabled_port_mask & 1 << next_hop) != 0) {
 			dst_port = next_hop;
@@ -797,7 +797,7 @@ init_routing_table(void)
 			/* populate the LPM6 table */
 			for (i = 0; i < RTE_DIM(l3fwd_ipv6_route_array); i++) {
 				ret = rte_lpm6_add(lpm6,
-					l3fwd_ipv6_route_array[i].ip,
+					&l3fwd_ipv6_route_array[i].ip,
 					l3fwd_ipv6_route_array[i].depth,
 					l3fwd_ipv6_route_array[i].if_out);
 
@@ -810,7 +810,7 @@ init_routing_table(void)
 				RTE_LOG(INFO, IP_RSMBL, "Socket %i: adding route " IPv6_BYTES_FMT
 						"/%d (port %d)\n",
 					socket,
-					IPv6_BYTES(l3fwd_ipv6_route_array[i].ip),
+					IPv6_BYTES(l3fwd_ipv6_route_array[i].ip.a),
 					l3fwd_ipv6_route_array[i].depth,
 					l3fwd_ipv6_route_array[i].if_out);
 			}
diff --git a/examples/ipsec-secgw/ipsec_lpm_neon.h b/examples/ipsec-secgw/ipsec_lpm_neon.h
index 9573f53ae957..865b9624a86e 100644
--- a/examples/ipsec-secgw/ipsec_lpm_neon.h
+++ b/examples/ipsec-secgw/ipsec_lpm_neon.h
@@ -5,6 +5,8 @@
 #ifndef IPSEC_LPM_NEON_H
 #define IPSEC_LPM_NEON_H
 
+#include <rte_ip6.h>
+
 #include <arm_neon.h>
 #include "ipsec_neon.h"
 
@@ -114,7 +116,7 @@ process_single_pkt(struct rt_ctx *rt_ctx, struct rte_mbuf *pkt,
 static inline void
 route6_pkts_neon(struct rt_ctx *rt_ctx, struct rte_mbuf **pkts, int nb_rx)
 {
-	uint8_t dst_ip6[MAX_PKT_BURST][16];
+	struct rte_ipv6_addr dst_ip6[MAX_PKT_BURST];
 	uint16_t dst_port[MAX_PKT_BURST];
 	struct rte_ether_hdr *eth_hdr;
 	struct rte_ipv6_hdr *ipv6_hdr;
@@ -142,8 +144,7 @@ route6_pkts_neon(struct rt_ctx *rt_ctx, struct rte_mbuf **pkts, int nb_rx)
 			 * required to get the hop
 			 */
 			ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
-			memcpy(&dst_ip6[lpm_pkts][0],
-					ipv6_hdr->dst_addr, 16);
+			memcpy(&dst_ip6[lpm_pkts], &ipv6_hdr->dst_addr, 16);
 			lpm_pkts++;
 		}
 	}
diff --git a/examples/ipsec-secgw/ipsec_worker.c b/examples/ipsec-secgw/ipsec_worker.c
index c9c43ebd2b99..3a83b7c0bf4b 100644
--- a/examples/ipsec-secgw/ipsec_worker.c
+++ b/examples/ipsec-secgw/ipsec_worker.c
@@ -298,7 +298,7 @@ route4_pkt(struct rte_mbuf *pkt, struct rt_ctx *rt_ctx)
 static inline uint16_t
 route6_pkt(struct rte_mbuf *pkt, struct rt_ctx *rt_ctx)
 {
-	uint8_t dst_ip[16];
+	struct rte_ipv6_addr dst_ip;
 	uint8_t *ip6_dst;
 	uint16_t offset;
 	uint32_t hop;
@@ -306,9 +306,9 @@ route6_pkt(struct rte_mbuf *pkt, struct rt_ctx *rt_ctx)
 
 	offset = RTE_ETHER_HDR_LEN + offsetof(struct ip6_hdr, ip6_dst);
 	ip6_dst = rte_pktmbuf_mtod_offset(pkt, uint8_t *, offset);
-	memcpy(&dst_ip[0], ip6_dst, 16);
+	memcpy(&dst_ip, ip6_dst, 16);
 
-	ret = rte_lpm6_lookup((struct rte_lpm6 *)rt_ctx, dst_ip, &hop);
+	ret = rte_lpm6_lookup((struct rte_lpm6 *)rt_ctx, &dst_ip, &hop);
 
 	if (ret == 0) {
 		/* We have a hit */
diff --git a/examples/ipsec-secgw/ipsec_worker.h b/examples/ipsec-secgw/ipsec_worker.h
index 8f6a1c06aa7f..8f9616129362 100644
--- a/examples/ipsec-secgw/ipsec_worker.h
+++ b/examples/ipsec-secgw/ipsec_worker.h
@@ -560,7 +560,7 @@ static __rte_always_inline void
 route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint32_t nb_pkts)
 {
 	int32_t hop[MAX_PKT_BURST * 2];
-	uint8_t dst_ip[MAX_PKT_BURST * 2][16];
+	struct rte_ipv6_addr dst_ip[MAX_PKT_BURST * 2];
 	struct rte_ether_hdr *ethhdr;
 	uint8_t *ip6_dst;
 	uint32_t pkt_hop = 0;
@@ -586,7 +586,7 @@ route6_pkts(struct rt_ctx *rt_ctx, struct rte_mbuf *pkts[], uint32_t nb_pkts)
 			offset = offsetof(struct ip6_hdr, ip6_dst);
 			ip6_dst = rte_pktmbuf_mtod_offset(pkt, uint8_t *,
 					offset);
-			memcpy(&dst_ip[lpm_pkts][0], ip6_dst, 16);
+			memcpy(&dst_ip[lpm_pkts], ip6_dst, 16);
 			lpm_pkts++;
 		}
 	}
diff --git a/examples/ipsec-secgw/rt.c b/examples/ipsec-secgw/rt.c
index ce854ccb6018..059fc0c8f28c 100644
--- a/examples/ipsec-secgw/rt.c
+++ b/examples/ipsec-secgw/rt.c
@@ -25,7 +25,7 @@ struct ip4_route {
 };
 
 struct ip6_route {
-	uint8_t ip[16];
+	struct rte_ipv6_addr ip;
 	uint8_t depth;
 	uint8_t if_out;
 };
@@ -99,7 +99,7 @@ parse_rt_tokens(char **tokens, uint32_t n_tokens,
 					tokens[ti]);
 				if (status->status < 0)
 					return;
-				memcpy(route_ipv6->ip, ip.s6_addr, 16);
+				memcpy(&route_ipv6->ip, ip.s6_addr, 16);
 				route_ipv6->depth = (uint8_t)depth;
 			}
 		}
@@ -183,7 +183,7 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id)
 
 	/* populate the LPM table */
 	for (i = 0; i < nb_rt_ip6; i++) {
-		ret = rte_lpm6_add(lpm6, rt_ip6[i].ip, rt_ip6[i].depth,
+		ret = rte_lpm6_add(lpm6, &rt_ip6[i].ip, rt_ip6[i].depth,
 				rt_ip6[i].if_out);
 		if (ret < 0)
 			rte_exit(EXIT_FAILURE, "Fail to add entry num %u to %s "
@@ -191,14 +191,14 @@ rt_init(struct socket_ctx *ctx, int32_t socket_id)
 
 		printf("LPM6: Adding route "
 			" %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hhx (%hhx)\n",
-			(uint16_t)((rt_ip6[i].ip[0] << 8) | rt_ip6[i].ip[1]),
-			(uint16_t)((rt_ip6[i].ip[2] << 8) | rt_ip6[i].ip[3]),
-			(uint16_t)((rt_ip6[i].ip[4] << 8) | rt_ip6[i].ip[5]),
-			(uint16_t)((rt_ip6[i].ip[6] << 8) | rt_ip6[i].ip[7]),
-			(uint16_t)((rt_ip6[i].ip[8] << 8) | rt_ip6[i].ip[9]),
-			(uint16_t)((rt_ip6[i].ip[10] << 8) | rt_ip6[i].ip[11]),
-			(uint16_t)((rt_ip6[i].ip[12] << 8) | rt_ip6[i].ip[13]),
-			(uint16_t)((rt_ip6[i].ip[14] << 8) | rt_ip6[i].ip[15]),
+			(uint16_t)((rt_ip6[i].ip.a[0] << 8) | rt_ip6[i].ip.a[1]),
+			(uint16_t)((rt_ip6[i].ip.a[2] << 8) | rt_ip6[i].ip.a[3]),
+			(uint16_t)((rt_ip6[i].ip.a[4] << 8) | rt_ip6[i].ip.a[5]),
+			(uint16_t)((rt_ip6[i].ip.a[6] << 8) | rt_ip6[i].ip.a[7]),
+			(uint16_t)((rt_ip6[i].ip.a[8] << 8) | rt_ip6[i].ip.a[9]),
+			(uint16_t)((rt_ip6[i].ip.a[10] << 8) | rt_ip6[i].ip.a[11]),
+			(uint16_t)((rt_ip6[i].ip.a[12] << 8) | rt_ip6[i].ip.a[13]),
+			(uint16_t)((rt_ip6[i].ip.a[14] << 8) | rt_ip6[i].ip.a[15]),
 			rt_ip6[i].depth, rt_ip6[i].if_out);
 	}
 
diff --git a/examples/l3fwd/l3fwd_fib.c b/examples/l3fwd/l3fwd_fib.c
index 4a9534e9dbef..046aa1027b5c 100644
--- a/examples/l3fwd/l3fwd_fib.c
+++ b/examples/l3fwd/l3fwd_fib.c
@@ -46,7 +46,7 @@ static struct rte_fib6 *ipv6_l3fwd_fib_lookup_struct[NB_SOCKETS];
 static inline void
 fib_parse_packet(struct rte_mbuf *mbuf,
 		uint32_t *ipv4, uint32_t *ipv4_cnt,
-		uint8_t ipv6[RTE_FIB6_IPV6_ADDR_SIZE],
+		struct rte_ipv6_addr *ipv6,
 		uint32_t *ipv6_cnt, uint8_t *ip_type)
 {
 	struct rte_ether_hdr *eth_hdr;
@@ -65,7 +65,7 @@ fib_parse_packet(struct rte_mbuf *mbuf,
 	/* IPv6 */
 	else {
 		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
-		rte_mov16(ipv6, ipv6_hdr->dst_addr.a);
+		rte_mov16(ipv6->a, ipv6_hdr->dst_addr.a);
 		*ip_type = 0;
 		(*ipv6_cnt)++;
 	}
@@ -120,7 +120,7 @@ fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
 		uint16_t portid, struct lcore_conf *qconf)
 {
 	uint32_t ipv4_arr[nb_rx];
-	uint8_t ipv6_arr[nb_rx][RTE_FIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr ipv6_arr[nb_rx];
 	uint16_t hops[nb_rx];
 	uint64_t hopsv4[nb_rx], hopsv6[nb_rx];
 	uint8_t type_arr[nb_rx];
@@ -140,7 +140,7 @@ fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
 				i + FIB_PREFETCH_OFFSET], void *));
 		fib_parse_packet(pkts_burst[i],
 				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
-				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&ipv6_arr[ipv6_cnt], &ipv6_cnt,
 				&type_arr[i]);
 	}
 
@@ -148,7 +148,7 @@ fib_send_packets(int nb_rx, struct rte_mbuf **pkts_burst,
 	for (; i < nb_rx; i++)
 		fib_parse_packet(pkts_burst[i],
 				&ipv4_arr[ipv4_cnt], &ipv4_cnt,
-				ipv6_arr[ipv6_cnt], &ipv6_cnt,
+				&ipv6_arr[ipv6_cnt], &ipv6_cnt,
 				&type_arr[i]);
 
 	/* Lookup IPv4 hops if IPv4 packets are present. */
@@ -270,7 +270,7 @@ fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
 	unsigned int lcore_id;
 
 	uint32_t ipv4_arr[MAX_PKT_BURST];
-	uint8_t ipv6_arr[MAX_PKT_BURST][RTE_FIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr ipv6_arr[MAX_PKT_BURST];
 	uint64_t hopsv4[MAX_PKT_BURST], hopsv6[MAX_PKT_BURST];
 	uint16_t nh, hops[MAX_PKT_BURST];
 	uint8_t type_arr[MAX_PKT_BURST];
@@ -323,7 +323,7 @@ fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
 
 			fib_parse_packet(events[i].mbuf,
 					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
-					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&ipv6_arr[ipv6_cnt], &ipv6_cnt,
 					&type_arr[i]);
 		}
 
@@ -340,7 +340,7 @@ fib_event_loop(struct l3fwd_event_resources *evt_rsrc,
 
 			fib_parse_packet(events[i].mbuf,
 					&ipv4_arr[ipv4_cnt], &ipv4_cnt,
-					ipv6_arr[ipv6_cnt], &ipv6_cnt,
+					&ipv6_arr[ipv6_cnt], &ipv6_cnt,
 					&type_arr[i]);
 		}
 
@@ -436,7 +436,7 @@ fib_event_main_loop_tx_q_burst(__rte_unused void *dummy)
 
 static __rte_always_inline void
 fib_process_event_vector(struct rte_event_vector *vec, uint8_t *type_arr,
-			 uint8_t **ipv6_arr, uint64_t *hopsv4, uint64_t *hopsv6,
+			 struct rte_ipv6_addr *ipv6_arr, uint64_t *hopsv4, uint64_t *hopsv6,
 			 uint32_t *ipv4_arr, uint16_t *hops)
 {
 	uint32_t ipv4_arr_assem, ipv6_arr_assem;
@@ -463,13 +463,13 @@ fib_process_event_vector(struct rte_event_vector *vec, uint8_t *type_arr,
 		rte_prefetch0(rte_pktmbuf_mtod(mbufs[i + FIB_PREFETCH_OFFSET],
 					       void *));
 		fib_parse_packet(mbufs[i], &ipv4_arr[ipv4_cnt], &ipv4_cnt,
-				 ipv6_arr[ipv6_cnt], &ipv6_cnt, &type_arr[i]);
+				 &ipv6_arr[ipv6_cnt], &ipv6_cnt, &type_arr[i]);
 	}
 
 	/* Parse remaining packet info. */
 	for (; i < vec->nb_elem; i++)
 		fib_parse_packet(mbufs[i], &ipv4_arr[ipv4_cnt], &ipv4_cnt,
-				 ipv6_arr[ipv6_cnt], &ipv6_cnt, &type_arr[i]);
+				 &ipv6_arr[ipv6_cnt], &ipv6_cnt, &type_arr[i]);
 
 	/* Lookup IPv4 hops if IPv4 packets are present. */
 	if (likely(ipv4_cnt > 0))
@@ -480,7 +480,7 @@ fib_process_event_vector(struct rte_event_vector *vec, uint8_t *type_arr,
 	if (ipv6_cnt > 0)
 		rte_fib6_lookup_bulk(
 			lconf->ipv6_lookup_struct,
-			(uint8_t(*)[RTE_FIB6_IPV6_ADDR_SIZE])ipv6_arr, hopsv6,
+			ipv6_arr, hopsv6,
 			ipv6_cnt);
 
 	/* Assign ports looked up in fib depending on IPv4 or IPv6 */
@@ -522,7 +522,8 @@ fib_event_loop_vector(struct l3fwd_event_resources *evt_rsrc,
 	const uint8_t event_d_id = evt_rsrc->event_d_id;
 	const uint16_t deq_len = evt_rsrc->deq_depth;
 	struct rte_event events[MAX_PKT_BURST];
-	uint8_t *type_arr, **ipv6_arr, *ptr;
+	uint8_t *type_arr;
+	struct rte_ipv6_addr *ipv6_arr;
 	int nb_enq = 0, nb_deq = 0, i;
 	uint64_t *hopsv4, *hopsv6;
 	uint32_t *ipv4_arr;
@@ -533,7 +534,7 @@ fib_event_loop_vector(struct l3fwd_event_resources *evt_rsrc,
 		"vector_fib",
 		(sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint64_t) +
 		 sizeof(uint64_t) + sizeof(uint16_t) + sizeof(uint8_t *) +
-		 (sizeof(uint8_t) * RTE_FIB6_IPV6_ADDR_SIZE)) *
+		 sizeof(struct rte_ipv6_addr)) *
 			evt_rsrc->vector_size,
 		RTE_CACHE_LINE_SIZE);
 	if (mem == 0)
@@ -543,11 +544,7 @@ fib_event_loop_vector(struct l3fwd_event_resources *evt_rsrc,
 	hopsv4 = (uint64_t *)&type_arr[evt_rsrc->vector_size];
 	hopsv6 = (uint64_t *)&hopsv4[evt_rsrc->vector_size];
 	hops = (uint16_t *)&hopsv6[evt_rsrc->vector_size];
-	ipv6_arr = (uint8_t **)&hops[evt_rsrc->vector_size];
-
-	ptr = (uint8_t *)&ipv6_arr[evt_rsrc->vector_size];
-	for (i = 0; i < evt_rsrc->vector_size; i++)
-		ipv6_arr[i] = &ptr[RTE_FIB6_IPV6_ADDR_SIZE + i];
+	ipv6_arr = (struct rte_ipv6_addr *)&hops[evt_rsrc->vector_size];
 
 	if (event_p_id < 0) {
 		rte_free((void *)mem);
@@ -732,7 +729,7 @@ setup_fib(const int socketid)
 		rte_eth_dev_info_get(route_base_v6[i].if_out,
 				     &dev_info);
 		ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid],
-			route_base_v6[i].ip_8,
+			&route_base_v6[i].ip6,
 			route_base_v6[i].depth,
 			route_base_v6[i].if_out);
 
@@ -744,7 +741,7 @@ setup_fib(const int socketid)
 					i, socketid);
 		}
 
-		if (inet_ntop(AF_INET6, route_base_v6[i].ip_8,
+		if (inet_ntop(AF_INET6, &route_base_v6[i].ip6,
 				abuf, sizeof(abuf)) != NULL) {
 			printf("FIB: Adding route %s / %d (%d) [%s]\n", abuf,
 			       route_base_v6[i].depth,
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 422fdb70054d..fc4f5878fcd8 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -62,7 +62,7 @@ lpm_get_ipv6_dst_port(const struct rte_ipv6_hdr *ipv6_hdr,
 		      uint16_t portid,
 		      struct rte_lpm6 *ipv6_l3fwd_lookup_struct)
 {
-	const uint8_t *dst_ip = ipv6_hdr->dst_addr.a;
+	const struct rte_ipv6_addr *dst_ip = &ipv6_hdr->dst_addr;
 	uint32_t next_hop;
 
 	if (rte_lpm6_lookup(ipv6_l3fwd_lookup_struct, dst_ip, &next_hop) == 0)
@@ -122,7 +122,7 @@ lpm_get_dst_port_with_ipv4(const struct lcore_conf *qconf, struct rte_mbuf *pkt,
 		ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
 
 		return (uint16_t) ((rte_lpm6_lookup(qconf->ipv6_lookup_struct,
-				ipv6_hdr->dst_addr.a, &next_hop) == 0)
+				&ipv6_hdr->dst_addr, &next_hop) == 0)
 				? next_hop : portid);
 
 	}
@@ -635,7 +635,7 @@ setup_lpm(const int socketid)
 		rte_eth_dev_info_get(route_base_v6[i].if_out,
 				     &dev_info);
 		ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid],
-			route_base_v6[i].ip_8,
+			&route_base_v6[i].ip6,
 			route_base_v6[i].depth,
 			route_base_v6[i].if_out);
 
@@ -647,7 +647,7 @@ setup_lpm(const int socketid)
 		}
 
 		printf("LPM: Adding route %s / %d (%d) [%s]\n",
-		       inet_ntop(AF_INET6, route_base_v6[i].ip_8, abuf,
+		       inet_ntop(AF_INET6, &route_base_v6[i].ip6, abuf,
 				 sizeof(abuf)),
 		       route_base_v6[i].depth,
 		       route_base_v6[i].if_out, rte_dev_name(dev_info.device));
diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h
index 467c4d285915..ceabf4fa8e3c 100644
--- a/examples/l3fwd/l3fwd_route.h
+++ b/examples/l3fwd/l3fwd_route.h
@@ -2,6 +2,8 @@
  * Copyright(c) 2021 Intel Corporation
  */
 
+#include <rte_ip6.h>
+
 /* Log file related character defs. */
 #define COMMENT_LEAD_CHAR	('#')
 #define ROUTE_LEAD_CHAR		('R')
@@ -53,10 +55,7 @@ struct ipv6_5tuple {
 struct lpm_route_rule {
 	union {
 		uint32_t ip;
-		union {
-			uint32_t ip_32[IPV6_ADDR_U32];
-			uint8_t ip_8[IPV6_ADDR_LEN];
-		};
+		struct rte_ipv6_addr ip6;
 	};
 	uint8_t depth;
 	uint8_t if_out;
diff --git a/examples/l3fwd/lpm_route_parse.c b/examples/l3fwd/lpm_route_parse.c
index f2028d79e180..d553ebdbcc5c 100644
--- a/examples/l3fwd/lpm_route_parse.c
+++ b/examples/l3fwd/lpm_route_parse.c
@@ -108,7 +108,7 @@ lpm_parse_v6_rule(char *str, struct lpm_route_rule *v)
 			return -EINVAL;
 	}
 
-	rc = lpm_parse_v6_net(in[CB_FLD_DST_ADDR], v->ip_32, &v->depth);
+	rc = lpm_parse_v6_net(in[CB_FLD_DST_ADDR], (uint32_t *)&v->ip6, &v->depth);
 
 	GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
 
@@ -164,8 +164,8 @@ lpm_add_default_v6_rules(void)
 	route_base_v6 = calloc(route_num_v6, rule_size);
 
 	for (i = 0; i < (unsigned int)route_num_v6; i++) {
-		memcpy(route_base_v6[i].ip_8, ipv6_l3fwd_route_array[i].ip,
-			   sizeof(route_base_v6[i].ip_8));
+		memcpy(&route_base_v6[i].ip, ipv6_l3fwd_route_array[i].ip,
+			   sizeof(route_base_v6[i].ip));
 		route_base_v6[i].depth = ipv6_l3fwd_route_array[i].depth;
 		route_base_v6[i].if_out = ipv6_l3fwd_route_array[i].if_out;
 	}
diff --git a/lib/fib/meson.build b/lib/fib/meson.build
index 6795f41a0ad2..268007ef6c93 100644
--- a/lib/fib/meson.build
+++ b/lib/fib/meson.build
@@ -10,7 +10,7 @@ endif
 
 sources = files('rte_fib.c', 'rte_fib6.c', 'dir24_8.c', 'trie.c')
 headers = files('rte_fib.h', 'rte_fib6.h')
-deps += ['rib']
+deps += ['net', 'rib']
 
 # compile AVX512 version if:
 # we are building 64-bit binary AND binutils can generate proper code
@@ -54,7 +54,7 @@ if dpdk_conf.has('RTE_ARCH_X86_64') and binutils_ok
         if cc.has_argument('-mavx512bw')
             trie_avx512_tmp = static_library('trie_avx512_tmp',
                 'trie_avx512.c',
-                dependencies: static_rte_eal,
+                dependencies: [static_rte_eal, static_rte_net],
                 c_args: cflags + ['-mavx512f', \
                     '-mavx512dq', '-mavx512bw'])
             objs += trie_avx512_tmp.extract_objects('trie_avx512.c')
diff --git a/lib/fib/rte_fib6.c b/lib/fib/rte_fib6.c
index 9ad990724a8b..d95cac79cbb5 100644
--- a/lib/fib/rte_fib6.c
+++ b/lib/fib/rte_fib6.c
@@ -14,6 +14,7 @@
 #include <rte_malloc.h>
 #include <rte_string_fns.h>
 
+#include <rte_ip6.h>
 #include <rte_rib6.h>
 #include <rte_fib6.h>
 
@@ -49,7 +50,7 @@ struct rte_fib6 {
 };
 
 static void
-dummy_lookup(void *fib_p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+dummy_lookup(void *fib_p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, const unsigned int n)
 {
 	unsigned int i;
@@ -57,7 +58,7 @@ dummy_lookup(void *fib_p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
 	struct rte_rib6_node *node;
 
 	for (i = 0; i < n; i++) {
-		node = rte_rib6_lookup(fib->rib, ips[i]);
+		node = rte_rib6_lookup(fib->rib, &ips[i]);
 		if (node != NULL)
 			rte_rib6_get_nh(node, &next_hops[i]);
 		else
@@ -66,7 +67,7 @@ dummy_lookup(void *fib_p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
 }
 
 static int
-dummy_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
+dummy_modify(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth, uint64_t next_hop, int op)
 {
 	struct rte_rib6_node *node;
@@ -118,7 +119,7 @@ init_dataplane(struct rte_fib6 *fib, __rte_unused int socket_id,
 }
 
 int
-rte_fib6_add(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
+rte_fib6_add(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth, uint64_t next_hop)
 {
 	if ((fib == NULL) || (ip == NULL) || (fib->modify == NULL) ||
@@ -128,7 +129,7 @@ rte_fib6_add(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
 }
 
 int
-rte_fib6_delete(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
+rte_fib6_delete(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth)
 {
 	if ((fib == NULL) || (ip == NULL) || (fib->modify == NULL) ||
@@ -139,7 +140,7 @@ rte_fib6_delete(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
 
 int
 rte_fib6_lookup_bulk(struct rte_fib6 *fib,
-	uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+	const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, int n)
 {
 	FIB6_RETURN_IF_TRUE((fib == NULL) || (ips == NULL) ||
diff --git a/lib/fib/rte_fib6.h b/lib/fib/rte_fib6.h
index 2eb8b8267647..d26a0c7c0b77 100644
--- a/lib/fib/rte_fib6.h
+++ b/lib/fib/rte_fib6.h
@@ -17,6 +17,7 @@
 
 #include <stdint.h>
 
+#include <rte_ip6.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,11 +38,11 @@ enum rte_fib6_type {
 
 /** Modify FIB function */
 typedef int (*rte_fib6_modify_fn_t)(struct rte_fib6 *fib,
-	const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE], uint8_t depth,
+	const struct rte_ipv6_addr *ip, uint8_t depth,
 	uint64_t next_hop, int op);
 /** FIB bulk lookup function */
 typedef void (*rte_fib6_lookup_fn_t)(void *fib,
-	uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+	const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, const unsigned int n);
 
 enum rte_fib6_op {
@@ -134,7 +135,7 @@ rte_fib6_free(struct rte_fib6 *fib);
  *   0 on success, negative value otherwise
  */
 int
-rte_fib6_add(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
+rte_fib6_add(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth, uint64_t next_hop);
 
 /**
@@ -151,7 +152,7 @@ rte_fib6_add(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
  */
 int
 rte_fib6_delete(struct rte_fib6 *fib,
-	const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE], uint8_t depth);
+	const struct rte_ipv6_addr *ip, uint8_t depth);
 
 /**
  * Lookup multiple IP addresses in the FIB.
@@ -172,7 +173,7 @@ rte_fib6_delete(struct rte_fib6 *fib,
  */
 int
 rte_fib6_lookup_bulk(struct rte_fib6 *fib,
-	uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+	const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, int n);
 
 /**
diff --git a/lib/fib/trie.c b/lib/fib/trie.c
index 09470e7287cc..bd0c7ec63b7f 100644
--- a/lib/fib/trie.c
+++ b/lib/fib/trie.c
@@ -225,7 +225,7 @@ tbl8_recycle(struct rte_trie_tbl *dp, void *par, uint64_t tbl8_idx)
 
 #define BYTE_SIZE	8
 static inline uint32_t
-get_idx(const uint8_t *ip, uint32_t prev_idx, int bytes, int first_byte)
+get_idx(const struct rte_ipv6_addr *ip, uint32_t prev_idx, int bytes, int first_byte)
 {
 	int i;
 	uint32_t idx = 0;
@@ -233,7 +233,7 @@ get_idx(const uint8_t *ip, uint32_t prev_idx, int bytes, int first_byte)
 
 	for (i = first_byte; i < (first_byte + bytes); i++) {
 		bitshift = (int8_t)(((first_byte + bytes - 1) - i)*BYTE_SIZE);
-		idx |= ip[i] <<  bitshift;
+		idx |= ip->a[i] <<  bitshift;
 	}
 	return (prev_idx * TRIE_TBL8_GRP_NUM_ENT) + idx;
 }
@@ -280,7 +280,7 @@ recycle_root_path(struct rte_trie_tbl *dp, const uint8_t *ip_part,
 }
 
 static inline int
-build_common_root(struct rte_trie_tbl *dp, const uint8_t *ip,
+build_common_root(struct rte_trie_tbl *dp, const struct rte_ipv6_addr *ip,
 	int common_bytes, void **tbl)
 {
 	void *tbl_ptr = NULL;
@@ -355,8 +355,8 @@ write_edge(struct rte_trie_tbl *dp, const uint8_t *ip_part, uint64_t next_hop,
 #define TBL8_LEN	(RTE_FIB6_IPV6_ADDR_SIZE - TBL24_BYTES)
 
 static int
-install_to_dp(struct rte_trie_tbl *dp, const uint8_t *ledge, const uint8_t *r,
-	uint64_t next_hop)
+install_to_dp(struct rte_trie_tbl *dp, const struct rte_ipv6_addr *ledge,
+	const struct rte_ipv6_addr *r, uint64_t next_hop)
 {
 	void *common_root_tbl;
 	void *ent;
@@ -364,18 +364,18 @@ install_to_dp(struct rte_trie_tbl *dp, const uint8_t *ledge, const uint8_t *r,
 	int i;
 	int common_bytes;
 	int llen, rlen;
-	uint8_t redge[16];
+	struct rte_ipv6_addr redge;
 
 	/* decrement redge by 1*/
-	rte_rib6_copy_addr(redge, r);
+	rte_rib6_copy_addr(redge.a, r->a);
 	for (i = 15; i >= 0; i--) {
-		redge[i]--;
-		if (redge[i] != 0xff)
+		redge.a[i]--;
+		if (redge.a[i] != 0xff)
 			break;
 	}
 
 	for (common_bytes = 0; common_bytes < 15; common_bytes++) {
-		if (ledge[common_bytes] != redge[common_bytes])
+		if (ledge->a[common_bytes] != redge.a[common_bytes])
 			break;
 	}
 
@@ -386,14 +386,14 @@ install_to_dp(struct rte_trie_tbl *dp, const uint8_t *ledge, const uint8_t *r,
 	uint8_t first_tbl8_byte = RTE_MAX(common_bytes, TBL24_BYTES);
 
 	for (i = IPV6_MAX_IDX; i > first_tbl8_byte; i--) {
-		if (ledge[i] != 0)
+		if (ledge->a[i] != 0)
 			break;
 	}
 
 	llen = i - first_tbl8_byte + (common_bytes < 3);
 
 	for (i = IPV6_MAX_IDX; i > first_tbl8_byte; i--) {
-		if (redge[i] != UINT8_MAX)
+		if (redge.a[i] != UINT8_MAX)
 			break;
 	}
 	rlen = i - first_tbl8_byte + (common_bytes < 3);
@@ -403,10 +403,10 @@ install_to_dp(struct rte_trie_tbl *dp, const uint8_t *ledge, const uint8_t *r,
 	uint8_t first_idx_len = (common_bytes < 3) ? 3 : 1;
 
 	uint32_t left_idx = get_idx(ledge, 0, first_idx_len, first_byte_idx);
-	uint32_t right_idx = get_idx(redge, 0, first_idx_len, first_byte_idx);
+	uint32_t right_idx = get_idx(&redge, 0, first_idx_len, first_byte_idx);
 
 	ent = get_tbl_p_by_idx(common_root_tbl, left_idx, dp->nh_sz);
-	ret = write_edge(dp, &ledge[first_tbl8_byte + !(common_bytes < 3)],
+	ret = write_edge(dp, &ledge->a[first_tbl8_byte + !(common_bytes < 3)],
 		next_hop, llen, LEDGE, ent);
 	if (ret < 0)
 		return ret;
@@ -418,7 +418,7 @@ install_to_dp(struct rte_trie_tbl *dp, const uint8_t *ledge, const uint8_t *r,
 			right_idx - (left_idx + 1));
 	}
 	ent = get_tbl_p_by_idx(common_root_tbl, right_idx, dp->nh_sz);
-	ret = write_edge(dp, &redge[first_tbl8_byte + !((common_bytes < 3))],
+	ret = write_edge(dp, &redge.a[first_tbl8_byte + !((common_bytes < 3))],
 		next_hop, rlen, REDGE, ent);
 	if (ret < 0)
 		return ret;
@@ -426,12 +426,12 @@ install_to_dp(struct rte_trie_tbl *dp, const uint8_t *ledge, const uint8_t *r,
 	uint8_t	common_tbl8 = (common_bytes < TBL24_BYTES) ?
 			0 : common_bytes - (TBL24_BYTES - 1);
 	ent = get_tbl24_p(dp, ledge, dp->nh_sz);
-	recycle_root_path(dp, ledge + TBL24_BYTES, common_tbl8, ent);
+	recycle_root_path(dp, ledge->a + TBL24_BYTES, common_tbl8, ent);
 	return 0;
 }
 
 static void
-get_nxt_net(uint8_t *ip, uint8_t depth)
+get_nxt_net(struct rte_ipv6_addr *ip, uint8_t depth)
 {
 	int i;
 	uint8_t part_depth;
@@ -440,12 +440,12 @@ get_nxt_net(uint8_t *ip, uint8_t depth)
 	for (i = 0, part_depth = depth; part_depth > 8; part_depth -= 8, i++)
 		;
 
-	prev_byte = ip[i];
-	ip[i] += 1 << (8 - part_depth);
-	if (ip[i] < prev_byte) {
+	prev_byte = ip->a[i];
+	ip->a[i] += 1 << (8 - part_depth);
+	if (ip->a[i] < prev_byte) {
 		while (i > 0) {
-			ip[--i] += 1;
-			if (ip[i] != 0)
+			ip->a[--i] += 1;
+			if (ip->a[i] != 0)
 				break;
 		}
 	}
@@ -461,19 +461,18 @@ v6_addr_is_zero(const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE])
 
 static int
 modify_dp(struct rte_trie_tbl *dp, struct rte_rib6 *rib,
-	const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
+	const struct rte_ipv6_addr *ip,
 	uint8_t depth, uint64_t next_hop)
 {
 	struct rte_rib6_node *tmp = NULL;
-	uint8_t ledge[RTE_FIB6_IPV6_ADDR_SIZE];
-	uint8_t redge[RTE_FIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr ledge, redge;
 	int ret;
 	uint8_t tmp_depth;
 
 	if (next_hop > get_max_nh(dp->nh_sz))
 		return -EINVAL;
 
-	rte_rib6_copy_addr(ledge, ip);
+	rte_rib6_copy_addr(ledge.a, ip->a);
 	do {
 		tmp = rte_rib6_get_nxt(rib, ip, depth, tmp,
 			RTE_RIB6_GET_NXT_COVER);
@@ -481,32 +480,30 @@ modify_dp(struct rte_trie_tbl *dp, struct rte_rib6 *rib,
 			rte_rib6_get_depth(tmp, &tmp_depth);
 			if (tmp_depth == depth)
 				continue;
-			rte_rib6_get_ip(tmp, redge);
-			if (rte_rib6_is_equal(ledge, redge)) {
-				get_nxt_net(ledge, tmp_depth);
+			rte_rib6_get_ip(tmp, &redge);
+			if (rte_rib6_is_equal(ledge.a, redge.a)) {
+				get_nxt_net(&ledge, tmp_depth);
 				continue;
 			}
-			ret = install_to_dp(dp, ledge, redge,
-				next_hop);
+			ret = install_to_dp(dp, &ledge, &redge, next_hop);
 			if (ret != 0)
 				return ret;
-			get_nxt_net(redge, tmp_depth);
-			rte_rib6_copy_addr(ledge, redge);
+			get_nxt_net(&redge, tmp_depth);
+			rte_rib6_copy_addr(ledge.a, redge.a);
 			/*
 			 * we got to the end of address space
 			 * and wrapped around
 			 */
-			if (v6_addr_is_zero(ledge))
+			if (v6_addr_is_zero(ledge.a))
 				break;
 		} else {
-			rte_rib6_copy_addr(redge, ip);
-			get_nxt_net(redge, depth);
-			if (rte_rib6_is_equal(ledge, redge) &&
-					!v6_addr_is_zero(ledge))
+			rte_rib6_copy_addr(redge.a, ip->a);
+			get_nxt_net(&redge, depth);
+			if (rte_rib6_is_equal(ledge.a, redge.a) &&
+					!v6_addr_is_zero(ledge.a))
 				break;
 
-			ret = install_to_dp(dp, ledge, redge,
-				next_hop);
+			ret = install_to_dp(dp, &ledge, &redge, next_hop);
 			if (ret != 0)
 				return ret;
 		}
@@ -516,7 +513,7 @@ modify_dp(struct rte_trie_tbl *dp, struct rte_rib6 *rib,
 }
 
 int
-trie_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
+trie_modify(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth, uint64_t next_hop, int op)
 {
 	struct rte_trie_tbl *dp;
@@ -524,7 +521,7 @@ trie_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
 	struct rte_rib6_node *tmp = NULL;
 	struct rte_rib6_node *node;
 	struct rte_rib6_node *parent;
-	uint8_t	ip_masked[RTE_FIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr ip_masked;
 	int i, ret = 0;
 	uint64_t par_nh, node_nh;
 	uint8_t tmp_depth, depth_diff = 0, parent_depth = 24;
@@ -538,10 +535,10 @@ trie_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
 	RTE_ASSERT(rib);
 
 	for (i = 0; i < RTE_FIB6_IPV6_ADDR_SIZE; i++)
-		ip_masked[i] = ip[i] & get_msk_part(depth, i);
+		ip_masked.a[i] = ip->a[i] & get_msk_part(depth, i);
 
 	if (depth > 24) {
-		tmp = rte_rib6_get_nxt(rib, ip_masked,
+		tmp = rte_rib6_get_nxt(rib, &ip_masked,
 			RTE_ALIGN_FLOOR(depth, 8), NULL,
 			RTE_RIB6_GET_NXT_COVER);
 		if (tmp == NULL) {
@@ -555,14 +552,14 @@ trie_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
 			depth_diff = depth_diff >> 3;
 		}
 	}
-	node = rte_rib6_lookup_exact(rib, ip_masked, depth);
+	node = rte_rib6_lookup_exact(rib, &ip_masked, depth);
 	switch (op) {
 	case RTE_FIB6_ADD:
 		if (node != NULL) {
 			rte_rib6_get_nh(node, &node_nh);
 			if (node_nh == next_hop)
 				return 0;
-			ret = modify_dp(dp, rib, ip_masked, depth, next_hop);
+			ret = modify_dp(dp, rib, &ip_masked, depth, next_hop);
 			if (ret == 0)
 				rte_rib6_set_nh(node, next_hop);
 			return 0;
@@ -572,7 +569,7 @@ trie_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
 				dp->number_tbl8s - depth_diff))
 			return -ENOSPC;
 
-		node = rte_rib6_insert(rib, ip_masked, depth);
+		node = rte_rib6_insert(rib, &ip_masked, depth);
 		if (node == NULL)
 			return -rte_errno;
 		rte_rib6_set_nh(node, next_hop);
@@ -582,9 +579,9 @@ trie_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
 			if (par_nh == next_hop)
 				return 0;
 		}
-		ret = modify_dp(dp, rib, ip_masked, depth, next_hop);
+		ret = modify_dp(dp, rib, &ip_masked, depth, next_hop);
 		if (ret != 0) {
-			rte_rib6_remove(rib, ip_masked, depth);
+			rte_rib6_remove(rib, &ip_masked, depth);
 			return ret;
 		}
 
@@ -599,10 +596,10 @@ trie_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
 			rte_rib6_get_nh(parent, &par_nh);
 			rte_rib6_get_nh(node, &node_nh);
 			if (par_nh != node_nh)
-				ret = modify_dp(dp, rib, ip_masked, depth,
+				ret = modify_dp(dp, rib, &ip_masked, depth,
 					par_nh);
 		} else
-			ret = modify_dp(dp, rib, ip_masked, depth, dp->def_nh);
+			ret = modify_dp(dp, rib, &ip_masked, depth, dp->def_nh);
 
 		if (ret != 0)
 			return ret;
diff --git a/lib/fib/trie.h b/lib/fib/trie.h
index 2c20184a26a3..6e235edaf89c 100644
--- a/lib/fib/trie.h
+++ b/lib/fib/trie.h
@@ -8,6 +8,8 @@
 
 #include <stdalign.h>
 
+#include <rte_fib6.h>
+
 /**
  * @file
  * RTE IPv6 Longest Prefix Match (LPM)
@@ -42,13 +44,13 @@ struct rte_trie_tbl {
 };
 
 static inline uint32_t
-get_tbl24_idx(const uint8_t *ip)
+get_tbl24_idx(const struct rte_ipv6_addr *ip)
 {
-	return ip[0] << 16|ip[1] << 8|ip[2];
+	return ip->a[0] << 16|ip->a[1] << 8|ip->a[2];
 }
 
 static inline void *
-get_tbl24_p(struct rte_trie_tbl *dp, const uint8_t *ip, uint8_t nh_sz)
+get_tbl24_p(struct rte_trie_tbl *dp, const struct rte_ipv6_addr *ip, uint8_t nh_sz)
 {
 	uint32_t tbl24_idx;
 
@@ -107,7 +109,7 @@ is_entry_extended(uint64_t ent)
 
 #define LOOKUP_FUNC(suffix, type, nh_sz)				\
 static inline void rte_trie_lookup_bulk_##suffix(void *p,		\
-	uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],				\
+	const struct rte_ipv6_addr *ips,				\
 	uint64_t *next_hops, const unsigned int n)			\
 {									\
 	struct rte_trie_tbl *dp = (struct rte_trie_tbl *)p;		\
@@ -115,10 +117,10 @@ static inline void rte_trie_lookup_bulk_##suffix(void *p,		\
 	uint32_t i, j;							\
 									\
 	for (i = 0; i < n; i++) {					\
-		tmp = ((type *)dp->tbl24)[get_tbl24_idx(&ips[i][0])];	\
+		tmp = ((type *)dp->tbl24)[get_tbl24_idx(&ips[i])];	\
 		j = 3;							\
 		while (is_entry_extended(tmp)) {			\
-			tmp = ((type *)dp->tbl8)[ips[i][j++] +		\
+			tmp = ((type *)dp->tbl8)[ips[i].a[j++] +	\
 				((tmp >> 1) * TRIE_TBL8_GRP_NUM_ENT)];	\
 		}							\
 		next_hops[i] = tmp >> 1;				\
@@ -138,7 +140,7 @@ rte_fib6_lookup_fn_t
 trie_get_lookup_fn(void *p, enum rte_fib6_lookup_type type);
 
 int
-trie_modify(struct rte_fib6 *fib, const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE],
+trie_modify(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth, uint64_t next_hop, int op);
 
 #endif /* _TRIE_H_ */
diff --git a/lib/fib/trie_avx512.c b/lib/fib/trie_avx512.c
index d4d70d84bf60..f49482a95dfa 100644
--- a/lib/fib/trie_avx512.c
+++ b/lib/fib/trie_avx512.c
@@ -9,7 +9,7 @@
 #include "trie_avx512.h"
 
 static __rte_always_inline void
-transpose_x16(uint8_t ips[16][RTE_FIB6_IPV6_ADDR_SIZE],
+transpose_x16(const struct rte_ipv6_addr *ips,
 	__m512i *first, __m512i *second, __m512i *third, __m512i *fourth)
 {
 	__m512i tmp1, tmp2, tmp3, tmp4;
@@ -21,10 +21,10 @@ transpose_x16(uint8_t ips[16][RTE_FIB6_IPV6_ADDR_SIZE],
 	};
 
 	/* load all ip addresses */
-	tmp1 = _mm512_loadu_si512(&ips[0][0]);
-	tmp2 = _mm512_loadu_si512(&ips[4][0]);
-	tmp3 = _mm512_loadu_si512(&ips[8][0]);
-	tmp4 = _mm512_loadu_si512(&ips[12][0]);
+	tmp1 = _mm512_loadu_si512(&ips[0]);
+	tmp2 = _mm512_loadu_si512(&ips[4]);
+	tmp3 = _mm512_loadu_si512(&ips[8]);
+	tmp4 = _mm512_loadu_si512(&ips[12]);
 
 	/* transpose 4 byte chunks of 16 ips */
 	tmp5 = _mm512_unpacklo_epi32(tmp1, tmp2);
@@ -48,7 +48,7 @@ transpose_x16(uint8_t ips[16][RTE_FIB6_IPV6_ADDR_SIZE],
 }
 
 static __rte_always_inline void
-transpose_x8(uint8_t ips[8][RTE_FIB6_IPV6_ADDR_SIZE],
+transpose_x8(const struct rte_ipv6_addr *ips,
 	__m512i *first, __m512i *second)
 {
 	__m512i tmp1, tmp2, tmp3, tmp4;
@@ -57,8 +57,8 @@ transpose_x8(uint8_t ips[8][RTE_FIB6_IPV6_ADDR_SIZE],
 		},
 	};
 
-	tmp1 = _mm512_loadu_si512(&ips[0][0]);
-	tmp2 = _mm512_loadu_si512(&ips[4][0]);
+	tmp1 = _mm512_loadu_si512(&ips[0]);
+	tmp2 = _mm512_loadu_si512(&ips[4]);
 
 	tmp3 = _mm512_unpacklo_epi64(tmp1, tmp2);
 	*first = _mm512_permutexvar_epi64(perm_idxes.z, tmp3);
@@ -67,7 +67,7 @@ transpose_x8(uint8_t ips[8][RTE_FIB6_IPV6_ADDR_SIZE],
 }
 
 static __rte_always_inline void
-trie_vec_lookup_x16x2(void *p, uint8_t ips[32][RTE_FIB6_IPV6_ADDR_SIZE],
+trie_vec_lookup_x16x2(void *p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, int size)
 {
 	struct rte_trie_tbl *dp = (struct rte_trie_tbl *)p;
@@ -213,7 +213,7 @@ trie_vec_lookup_x16x2(void *p, uint8_t ips[32][RTE_FIB6_IPV6_ADDR_SIZE],
 }
 
 static void
-trie_vec_lookup_x8x2_8b(void *p, uint8_t ips[16][RTE_FIB6_IPV6_ADDR_SIZE],
+trie_vec_lookup_x8x2_8b(void *p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops)
 {
 	struct rte_trie_tbl *dp = (struct rte_trie_tbl *)p;
@@ -306,40 +306,40 @@ trie_vec_lookup_x8x2_8b(void *p, uint8_t ips[16][RTE_FIB6_IPV6_ADDR_SIZE],
 }
 
 void
-rte_trie_vec_lookup_bulk_2b(void *p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+rte_trie_vec_lookup_bulk_2b(void *p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, const unsigned int n)
 {
 	uint32_t i;
 	for (i = 0; i < (n / 32); i++) {
-		trie_vec_lookup_x16x2(p, (uint8_t (*)[16])&ips[i * 32][0],
+		trie_vec_lookup_x16x2(p, &ips[i * 32],
 				next_hops + i * 32, sizeof(uint16_t));
 	}
-	rte_trie_lookup_bulk_2b(p, (uint8_t (*)[16])&ips[i * 32][0],
+	rte_trie_lookup_bulk_2b(p, &ips[i * 32],
 			next_hops + i * 32, n - i * 32);
 }
 
 void
-rte_trie_vec_lookup_bulk_4b(void *p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+rte_trie_vec_lookup_bulk_4b(void *p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, const unsigned int n)
 {
 	uint32_t i;
 	for (i = 0; i < (n / 32); i++) {
-		trie_vec_lookup_x16x2(p, (uint8_t (*)[16])&ips[i * 32][0],
+		trie_vec_lookup_x16x2(p, &ips[i * 32],
 				next_hops + i * 32, sizeof(uint32_t));
 	}
-	rte_trie_lookup_bulk_4b(p, (uint8_t (*)[16])&ips[i * 32][0],
+	rte_trie_lookup_bulk_4b(p, &ips[i * 32],
 			next_hops + i * 32, n - i * 32);
 }
 
 void
-rte_trie_vec_lookup_bulk_8b(void *p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+rte_trie_vec_lookup_bulk_8b(void *p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, const unsigned int n)
 {
 	uint32_t i;
 	for (i = 0; i < (n / 16); i++) {
-		trie_vec_lookup_x8x2_8b(p, (uint8_t (*)[16])&ips[i * 16][0],
+		trie_vec_lookup_x8x2_8b(p, &ips[i * 16],
 				next_hops + i * 16);
 	}
-	rte_trie_lookup_bulk_8b(p, (uint8_t (*)[16])&ips[i * 16][0],
+	rte_trie_lookup_bulk_8b(p, &ips[i * 16],
 			next_hops + i * 16, n - i * 16);
 }
diff --git a/lib/fib/trie_avx512.h b/lib/fib/trie_avx512.h
index ef8c7f0e3474..1028a4899fc7 100644
--- a/lib/fib/trie_avx512.h
+++ b/lib/fib/trie_avx512.h
@@ -5,16 +5,20 @@
 #ifndef _TRIE_AVX512_H_
 #define _TRIE_AVX512_H_
 
+#include <stdint.h>
+
+struct rte_ipv6_addr;
+
 void
-rte_trie_vec_lookup_bulk_2b(void *p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+rte_trie_vec_lookup_bulk_2b(void *p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, const unsigned int n);
 
 void
-rte_trie_vec_lookup_bulk_4b(void *p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+rte_trie_vec_lookup_bulk_4b(void *p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, const unsigned int n);
 
 void
-rte_trie_vec_lookup_bulk_8b(void *p, uint8_t ips[][RTE_FIB6_IPV6_ADDR_SIZE],
+rte_trie_vec_lookup_bulk_8b(void *p, const struct rte_ipv6_addr *ips,
 	uint64_t *next_hops, const unsigned int n);
 
 #endif /* _TRIE_AVX512_H_ */
diff --git a/lib/lpm/meson.build b/lib/lpm/meson.build
index ae30f80b69c8..fae4f79fb938 100644
--- a/lib/lpm/meson.build
+++ b/lib/lpm/meson.build
@@ -20,3 +20,4 @@ indirect_headers += files(
 )
 deps += ['hash']
 deps += ['rcu']
+deps += ['net']
diff --git a/lib/lpm/rte_lpm6.c b/lib/lpm/rte_lpm6.c
index 5bc17601ab71..d3f1c8485f5f 100644
--- a/lib/lpm/rte_lpm6.c
+++ b/lib/lpm/rte_lpm6.c
@@ -67,14 +67,14 @@ struct rte_lpm6_tbl_entry {
 
 /** Rules tbl entry structure. */
 struct rte_lpm6_rule {
-	uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE]; /**< Rule IP address. */
+	struct rte_ipv6_addr ip; /**< Rule IP address. */
 	uint32_t next_hop; /**< Rule next hop. */
 	uint8_t depth; /**< Rule depth. */
 };
 
 /** Rules tbl entry key. */
 struct rte_lpm6_rule_key {
-	uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE]; /**< Rule IP address. */
+	struct rte_ipv6_addr ip; /**< Rule IP address. */
 	uint32_t depth; /**< Rule depth. */
 };
 
@@ -213,9 +213,9 @@ tbl8_available(struct rte_lpm6 *lpm)
  *	  note that ip must be already masked
  */
 static inline void
-rule_key_init(struct rte_lpm6_rule_key *key, uint8_t *ip, uint8_t depth)
+rule_key_init(struct rte_lpm6_rule_key *key, const struct rte_ipv6_addr *ip, uint8_t depth)
 {
-	ip6_copy_addr(key->ip, ip);
+	ip6_copy_addr(key->ip.a, ip->a);
 	key->depth = depth;
 }
 
@@ -231,7 +231,7 @@ rebuild_lpm(struct rte_lpm6 *lpm)
 
 	while (rte_hash_iterate(lpm->rules_tbl, (void *) &rule_key,
 			(void **) &next_hop, &iter) >= 0)
-		rte_lpm6_add(lpm, rule_key->ip, rule_key->depth,
+		rte_lpm6_add(lpm, &rule_key->ip, rule_key->depth,
 			(uint32_t) next_hop);
 }
 
@@ -460,7 +460,7 @@ rule_find_with_key(struct rte_lpm6 *lpm,
 
 /* Find a rule */
 static int
-rule_find(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth,
+rule_find(struct rte_lpm6 *lpm, struct rte_ipv6_addr *ip, uint8_t depth,
 		  uint32_t *next_hop)
 {
 	struct rte_lpm6_rule_key rule_key;
@@ -481,7 +481,7 @@ rule_find(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth,
  *   <0 - error
  */
 static inline int
-rule_add(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth, uint32_t next_hop)
+rule_add(struct rte_lpm6 *lpm, struct rte_ipv6_addr *ip, uint8_t depth, uint32_t next_hop)
 {
 	int ret, rule_exist;
 	struct rte_lpm6_rule_key rule_key;
@@ -570,7 +570,7 @@ init_tbl8_header(struct rte_lpm6 *lpm, uint32_t tbl_ind,
  * of the bytes being inspected in this step.
  */
 static uint32_t
-get_bitshift(const uint8_t *ip, uint8_t first_byte, uint8_t bytes)
+get_bitshift(const struct rte_ipv6_addr *ip, uint8_t first_byte, uint8_t bytes)
 {
 	uint32_t entry_ind, i;
 	int8_t bitshift;
@@ -581,7 +581,7 @@ get_bitshift(const uint8_t *ip, uint8_t first_byte, uint8_t bytes)
 
 		if (bitshift < 0)
 			bitshift = 0;
-		entry_ind = entry_ind | ip[i-1] << bitshift;
+		entry_ind = entry_ind | ip->a[i-1] << bitshift;
 	}
 
 	return entry_ind;
@@ -596,7 +596,7 @@ get_bitshift(const uint8_t *ip, uint8_t first_byte, uint8_t bytes)
  */
 static inline int
 simulate_add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl,
-		struct rte_lpm6_tbl_entry **next_tbl, const uint8_t *ip,
+		struct rte_lpm6_tbl_entry **next_tbl, const struct rte_ipv6_addr *ip,
 		uint8_t bytes, uint8_t first_byte, uint8_t depth,
 		uint32_t *need_tbl_nb)
 {
@@ -649,7 +649,7 @@ simulate_add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl,
 static inline int
 add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl,
 		uint32_t tbl_ind, struct rte_lpm6_tbl_entry **next_tbl,
-		uint32_t *next_tbl_ind, uint8_t *ip, uint8_t bytes,
+		uint32_t *next_tbl_ind, struct rte_ipv6_addr *ip, uint8_t bytes,
 		uint8_t first_byte, uint8_t depth, uint32_t next_hop,
 		uint8_t is_new_rule)
 {
@@ -814,7 +814,7 @@ add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl,
  *    -ENOSPC not enough tbl8 left
  */
 static int
-simulate_add(struct rte_lpm6 *lpm, const uint8_t *masked_ip, uint8_t depth)
+simulate_add(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *masked_ip, uint8_t depth)
 {
 	struct rte_lpm6_tbl_entry *tbl;
 	struct rte_lpm6_tbl_entry *tbl_next = NULL;
@@ -851,7 +851,7 @@ simulate_add(struct rte_lpm6 *lpm, const uint8_t *masked_ip, uint8_t depth)
  * Add a route
  */
 int
-rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
+rte_lpm6_add(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth,
 	     uint32_t next_hop)
 {
 	struct rte_lpm6_tbl_entry *tbl;
@@ -859,7 +859,7 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
 	/* init to avoid compiler warning */
 	uint32_t tbl_next_num = 123456;
 	int status;
-	uint8_t masked_ip[RTE_LPM6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr masked_ip;
 	int i;
 
 	/* Check user arguments. */
@@ -867,16 +867,16 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
-	ip6_copy_addr(masked_ip, ip);
-	ip6_mask_addr(masked_ip, depth);
+	ip6_copy_addr(masked_ip.a, ip->a);
+	ip6_mask_addr(masked_ip.a, depth);
 
 	/* Simulate adding a new route */
-	int ret = simulate_add(lpm, masked_ip, depth);
+	int ret = simulate_add(lpm, &masked_ip, depth);
 	if (ret < 0)
 		return ret;
 
 	/* Add the rule to the rule table. */
-	int is_new_rule = rule_add(lpm, masked_ip, depth, next_hop);
+	int is_new_rule = rule_add(lpm, &masked_ip, depth, next_hop);
 	/* If there is no space available for new rule return error. */
 	if (is_new_rule < 0)
 		return is_new_rule;
@@ -884,7 +884,7 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
 	/* Inspect the first three bytes through tbl24 on the first step. */
 	tbl = lpm->tbl24;
 	status = add_step(lpm, tbl, TBL24_IND, &tbl_next, &tbl_next_num,
-		masked_ip, ADD_FIRST_BYTE, 1, depth, next_hop,
+		&masked_ip, ADD_FIRST_BYTE, 1, depth, next_hop,
 		is_new_rule);
 	assert(status >= 0);
 
@@ -895,7 +895,7 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
 	for (i = ADD_FIRST_BYTE; i < RTE_LPM6_IPV6_ADDR_SIZE && status == 1; i++) {
 		tbl = tbl_next;
 		status = add_step(lpm, tbl, tbl_next_num, &tbl_next,
-			&tbl_next_num, masked_ip, 1, (uint8_t)(i + 1),
+			&tbl_next_num, &masked_ip, 1, (uint8_t)(i + 1),
 			depth, next_hop, is_new_rule);
 		assert(status >= 0);
 	}
@@ -910,7 +910,7 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
  */
 static inline int
 lookup_step(const struct rte_lpm6 *lpm, const struct rte_lpm6_tbl_entry *tbl,
-		const struct rte_lpm6_tbl_entry **tbl_next, const uint8_t *ip,
+		const struct rte_lpm6_tbl_entry **tbl_next, const struct rte_ipv6_addr *ip,
 		uint8_t first_byte, uint32_t *next_hop)
 {
 	uint32_t tbl8_index, tbl_entry;
@@ -922,7 +922,7 @@ lookup_step(const struct rte_lpm6 *lpm, const struct rte_lpm6_tbl_entry *tbl,
 	if ((tbl_entry & RTE_LPM6_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM6_VALID_EXT_ENTRY_BITMASK) {
 
-		tbl8_index = ip[first_byte-1] +
+		tbl8_index = ip->a[first_byte-1] +
 				((tbl_entry & RTE_LPM6_TBL8_BITMASK) *
 				RTE_LPM6_TBL8_GROUP_NUM_ENTRIES);
 
@@ -940,7 +940,7 @@ lookup_step(const struct rte_lpm6 *lpm, const struct rte_lpm6_tbl_entry *tbl,
  * Looks up an IP
  */
 int
-rte_lpm6_lookup(const struct rte_lpm6 *lpm, const uint8_t *ip,
+rte_lpm6_lookup(const struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip,
 		uint32_t *next_hop)
 {
 	const struct rte_lpm6_tbl_entry *tbl;
@@ -954,7 +954,7 @@ rte_lpm6_lookup(const struct rte_lpm6 *lpm, const uint8_t *ip,
 		return -EINVAL;
 
 	first_byte = LOOKUP_FIRST_BYTE;
-	tbl24_index = (ip[0] << BYTES2_SIZE) | (ip[1] << BYTE_SIZE) | ip[2];
+	tbl24_index = (ip->a[0] << BYTES2_SIZE) | (ip->a[1] << BYTE_SIZE) | ip->a[2];
 
 	/* Calculate pointer to the first entry to be inspected */
 	tbl = &lpm->tbl24[tbl24_index];
@@ -973,7 +973,7 @@ rte_lpm6_lookup(const struct rte_lpm6 *lpm, const uint8_t *ip,
  */
 int
 rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm,
-		uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE],
+		struct rte_ipv6_addr *ips,
 		int32_t *next_hops, unsigned int n)
 {
 	unsigned int i;
@@ -989,8 +989,8 @@ rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm,
 
 	for (i = 0; i < n; i++) {
 		first_byte = LOOKUP_FIRST_BYTE;
-		tbl24_index = (ips[i][0] << BYTES2_SIZE) |
-				(ips[i][1] << BYTE_SIZE) | ips[i][2];
+		tbl24_index = (ips[i].a[0] << BYTES2_SIZE) |
+				(ips[i].a[1] << BYTE_SIZE) | ips[i].a[2];
 
 		/* Calculate pointer to the first entry to be inspected */
 		tbl = &lpm->tbl24[tbl24_index];
@@ -999,7 +999,7 @@ rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm,
 			/* Continue inspecting following levels
 			 * until success or failure
 			 */
-			status = lookup_step(lpm, tbl, &tbl_next, ips[i],
+			status = lookup_step(lpm, tbl, &tbl_next, &ips[i],
 					first_byte++, &next_hop);
 			tbl = tbl_next;
 		} while (status == 1);
@@ -1017,10 +1017,10 @@ rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm,
  * Look for a rule in the high-level rules table
  */
 int
-rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
+rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth,
 			 uint32_t *next_hop)
 {
-	uint8_t masked_ip[RTE_LPM6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr masked_ip;
 
 	/* Check user arguments. */
 	if ((lpm == NULL) || next_hop == NULL || ip == NULL ||
@@ -1028,10 +1028,10 @@ rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
-	ip6_copy_addr(masked_ip, ip);
-	ip6_mask_addr(masked_ip, depth);
+	ip6_copy_addr(masked_ip.a, ip->a);
+	ip6_mask_addr(masked_ip.a, depth);
 
-	return rule_find(lpm, masked_ip, depth, next_hop);
+	return rule_find(lpm, &masked_ip, depth, next_hop);
 }
 
 /*
@@ -1042,7 +1042,7 @@ rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
  *   <0 on failure
  */
 static inline int
-rule_delete(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth)
+rule_delete(struct rte_lpm6 *lpm, struct rte_ipv6_addr *ip, uint8_t depth)
 {
 	int ret;
 	struct rte_lpm6_rule_key rule_key;
@@ -1067,10 +1067,10 @@ rule_delete(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth)
  */
 int
 rte_lpm6_delete_bulk_func(struct rte_lpm6 *lpm,
-		uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], uint8_t *depths,
+		struct rte_ipv6_addr *ips, uint8_t *depths,
 		unsigned n)
 {
-	uint8_t masked_ip[RTE_LPM6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr masked_ip;
 	unsigned i;
 
 	/* Check input arguments. */
@@ -1078,9 +1078,9 @@ rte_lpm6_delete_bulk_func(struct rte_lpm6 *lpm,
 		return -EINVAL;
 
 	for (i = 0; i < n; i++) {
-		ip6_copy_addr(masked_ip, ips[i]);
-		ip6_mask_addr(masked_ip, depths[i]);
-		rule_delete(lpm, masked_ip, depths[i]);
+		ip6_copy_addr(masked_ip.a, ips[i].a);
+		ip6_mask_addr(masked_ip.a, depths[i]);
+		rule_delete(lpm, &masked_ip, depths[i]);
 	}
 
 	/*
@@ -1141,7 +1141,7 @@ depth_to_mask_1b(uint8_t depth)
  * Find a less specific rule
  */
 static int
-rule_find_less_specific(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth,
+rule_find_less_specific(struct rte_lpm6 *lpm, struct rte_ipv6_addr *ip, uint8_t depth,
 	struct rte_lpm6_rule *rule)
 {
 	int ret;
@@ -1163,12 +1163,12 @@ rule_find_less_specific(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth,
 			mask = depth_to_mask_1b(mask);
 
 		rule_key.depth = depth;
-		rule_key.ip[depth >> 3] &= mask;
+		rule_key.ip.a[depth >> 3] &= mask;
 
 		ret = rule_find_with_key(lpm, &rule_key, &next_hop);
 		if (ret) {
 			rule->depth = depth;
-			ip6_copy_addr(rule->ip, rule_key.ip);
+			ip6_copy_addr(rule->ip.a, rule_key.ip.a);
 			rule->next_hop = next_hop;
 			return 1;
 		}
@@ -1181,13 +1181,13 @@ rule_find_less_specific(struct rte_lpm6 *lpm, uint8_t *ip, uint8_t depth,
  * Find range of tbl8 cells occupied by a rule
  */
 static void
-rule_find_range(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
+rule_find_range(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth,
 		  struct rte_lpm6_tbl_entry **from,
 		  struct rte_lpm6_tbl_entry **to,
 		  uint32_t *out_tbl_ind)
 {
 	uint32_t ind;
-	uint32_t first_3bytes = (uint32_t)ip[0] << 16 | ip[1] << 8 | ip[2];
+	uint32_t first_3bytes = (uint32_t)ip->a[0] << 16 | ip->a[1] << 8 | ip->a[2];
 
 	if (depth <= 24) {
 		/* rule is within the top level */
@@ -1213,7 +1213,7 @@ rule_find_range(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
 		 * until we reach the last one
 		 */
 		while (depth > 8) {
-			tbl += ip[byte];
+			tbl += ip->a[byte];
 			assert(tbl->ext_entry == 1);
 			/* go to the next level/tbl8 */
 			tbl_ind = tbl->lpm6_tbl8_gindex;
@@ -1224,7 +1224,7 @@ rule_find_range(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
 		}
 
 		/* last level/tbl8 */
-		ind = ip[byte] & depth_to_mask_1b(depth);
+		ind = ip->a[byte] & depth_to_mask_1b(depth);
 		*from = &tbl[ind];
 		ind += (1 << (8 - depth)) - 1;
 		*to = &tbl[ind];
@@ -1288,9 +1288,9 @@ remove_tbl(struct rte_lpm6 *lpm, struct rte_lpm_tbl8_hdr *tbl_hdr,
  * Deletes a rule
  */
 int
-rte_lpm6_delete(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth)
+rte_lpm6_delete(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth)
 {
-	uint8_t masked_ip[RTE_LPM6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr masked_ip;
 	struct rte_lpm6_rule lsp_rule_obj;
 	struct rte_lpm6_rule *lsp_rule;
 	int ret;
@@ -1302,21 +1302,21 @@ rte_lpm6_delete(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth)
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
-	ip6_copy_addr(masked_ip, ip);
-	ip6_mask_addr(masked_ip, depth);
+	ip6_copy_addr(masked_ip.a, ip->a);
+	ip6_mask_addr(masked_ip.a, depth);
 
 	/* Delete the rule from the rule table. */
-	ret = rule_delete(lpm, masked_ip, depth);
+	ret = rule_delete(lpm, &masked_ip, depth);
 	if (ret < 0)
 		return -ENOENT;
 
 	/* find rule cells */
-	rule_find_range(lpm, masked_ip, depth, &from, &to, &tbl_ind);
+	rule_find_range(lpm, &masked_ip, depth, &from, &to, &tbl_ind);
 
 	/* find a less specific rule (a rule with smaller depth)
 	 * note: masked_ip will be modified, don't use it anymore
 	 */
-	ret = rule_find_less_specific(lpm, masked_ip, depth,
+	ret = rule_find_less_specific(lpm, &masked_ip, depth,
 			&lsp_rule_obj);
 	lsp_rule = ret ? &lsp_rule_obj : NULL;
 
diff --git a/lib/lpm/rte_lpm6.h b/lib/lpm/rte_lpm6.h
index c93683e6240c..87392194237c 100644
--- a/lib/lpm/rte_lpm6.h
+++ b/lib/lpm/rte_lpm6.h
@@ -9,6 +9,8 @@
  * RTE Longest Prefix Match for IPv6 (LPM6)
  */
 
+#include <rte_ip6.h>
+
 #include <stdint.h>
 
 #ifdef __cplusplus
@@ -92,7 +94,7 @@ rte_lpm6_free(struct rte_lpm6 *lpm);
  *   0 on success, negative value otherwise
  */
 int
-rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
+rte_lpm6_add(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth,
 	     uint32_t next_hop);
 
 /**
@@ -111,7 +113,7 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
  *   1 if the rule exists, 0 if it does not, a negative value on failure
  */
 int
-rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
+rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth,
 			 uint32_t *next_hop);
 
 /**
@@ -127,7 +129,7 @@ rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
  *   0 on success, negative value otherwise
  */
 int
-rte_lpm6_delete(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth);
+rte_lpm6_delete(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth);
 
 /**
  * Delete a rule from the LPM table.
@@ -145,7 +147,7 @@ rte_lpm6_delete(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth);
  */
 int
 rte_lpm6_delete_bulk_func(struct rte_lpm6 *lpm,
-		uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE], uint8_t *depths, unsigned n);
+		struct rte_ipv6_addr *ips, uint8_t *depths, unsigned int n);
 
 /**
  * Delete all rules from the LPM table.
@@ -169,7 +171,7 @@ rte_lpm6_delete_all(struct rte_lpm6 *lpm);
  *   -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit
  */
 int
-rte_lpm6_lookup(const struct rte_lpm6 *lpm, const uint8_t *ip, uint32_t *next_hop);
+rte_lpm6_lookup(const struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint32_t *next_hop);
 
 /**
  * Lookup multiple IP addresses in an LPM table.
@@ -189,7 +191,7 @@ rte_lpm6_lookup(const struct rte_lpm6 *lpm, const uint8_t *ip, uint32_t *next_ho
  */
 int
 rte_lpm6_lookup_bulk_func(const struct rte_lpm6 *lpm,
-		uint8_t ips[][RTE_LPM6_IPV6_ADDR_SIZE],
+		struct rte_ipv6_addr *ips,
 		int32_t *next_hops, unsigned int n);
 
 #ifdef __cplusplus
diff --git a/lib/node/ip6_lookup.c b/lib/node/ip6_lookup.c
index 6bbcf14e2aa8..1ad6e3fd18f2 100644
--- a/lib/node/ip6_lookup.c
+++ b/lib/node/ip6_lookup.c
@@ -74,7 +74,7 @@ ip6_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node,
 	/* Get stream for the speculated next node */
 	to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs);
 	while (n_left_from >= 4) {
-		uint8_t ip_batch[4][16];
+		struct rte_ipv6_addr ip_batch[4];
 		int32_t next_hop[4];
 		uint16_t next[4];
 
@@ -112,28 +112,28 @@ ip6_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(ip_batch[0], &ipv6_hdr->dst_addr, 16);
+		rte_memcpy(&ip_batch[0], &ipv6_hdr->dst_addr, 16);
 
 		/* Extract DIP of mbuf1 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf1, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(ip_batch[1], &ipv6_hdr->dst_addr, 16);
+		rte_memcpy(&ip_batch[1], &ipv6_hdr->dst_addr, 16);
 
 		/* Extract DIP of mbuf2 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf2, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(ip_batch[2], &ipv6_hdr->dst_addr, 16);
+		rte_memcpy(&ip_batch[2], &ipv6_hdr->dst_addr, 16);
 
 		/* Extract DIP of mbuf3 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf3, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(ip_batch[3], &ipv6_hdr->dst_addr, 16);
+		rte_memcpy(&ip_batch[3], &ipv6_hdr->dst_addr, 16);
 
 		rte_lpm6_lookup_bulk_func(lpm6, ip_batch, next_hop, 4);
 
@@ -223,7 +223,7 @@ ip6_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node,
 		/* Extract TTL as IPv6 hdr is in cache */
 		node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits;
 
-		rc = rte_lpm6_lookup(lpm6, ipv6_hdr->dst_addr.a, &next_hop);
+		rc = rte_lpm6_lookup(lpm6, &ipv6_hdr->dst_addr, &next_hop);
 		next_hop = (rc == 0) ? next_hop : drop_nh;
 
 		node_mbuf_priv1(mbuf0, dyn)->nh = (uint16_t)next_hop;
@@ -278,8 +278,8 @@ rte_node_ip6_route_add(const uint8_t *ip, uint8_t depth, uint16_t next_hop,
 		if (!ip6_lookup_nm.lpm_tbl[socket])
 			continue;
 
-		ret = rte_lpm6_add(ip6_lookup_nm.lpm_tbl[socket], ip, depth,
-				   val);
+		ret = rte_lpm6_add(ip6_lookup_nm.lpm_tbl[socket],
+				   (const struct rte_ipv6_addr *)ip, depth, val);
 		if (ret < 0) {
 			node_err("ip6_lookup",
 				 "Unable to add entry %s / %d nh (%x) to LPM "
diff --git a/lib/rib/meson.build b/lib/rib/meson.build
index 7bacbb453592..e98f70848189 100644
--- a/lib/rib/meson.build
+++ b/lib/rib/meson.build
@@ -4,4 +4,4 @@
 
 sources = files('rte_rib.c', 'rte_rib6.c')
 headers = files('rte_rib.h', 'rte_rib6.h')
-deps += ['mempool']
+deps += ['net', 'mempool']
diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
index 89c8390c63be..a1ac418eb87a 100644
--- a/lib/rib/rte_rib6.c
+++ b/lib/rib/rte_rib6.c
@@ -35,7 +35,7 @@ struct rte_rib6_node {
 	struct rte_rib6_node	*right;
 	struct rte_rib6_node	*parent;
 	uint64_t		nh;
-	uint8_t			ip[RTE_RIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr	ip;
 	uint8_t			depth;
 	uint8_t			flag;
 	uint64_t ext[];
@@ -79,7 +79,7 @@ is_covered(const uint8_t ip1[RTE_RIB6_IPV6_ADDR_SIZE],
 }
 
 static inline int
-get_dir(const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth)
+get_dir(const struct rte_ipv6_addr *ip, uint8_t depth)
 {
 	uint8_t index, msk;
 
@@ -98,12 +98,12 @@ get_dir(const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth)
 	 */
 	msk = 1 << (7 - (depth & 7));
 
-	return (ip[index] & msk) != 0;
+	return (ip->a[index] & msk) != 0;
 }
 
 static inline struct rte_rib6_node *
 get_nxt_node(struct rte_rib6_node *node,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE])
+	const struct rte_ipv6_addr *ip)
 {
 	if (node->depth == RIB6_MAXDEPTH)
 		return NULL;
@@ -133,7 +133,7 @@ node_free(struct rte_rib6 *rib, struct rte_rib6_node *ent)
 
 struct rte_rib6_node *
 rte_rib6_lookup(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE])
+	const struct rte_ipv6_addr *ip)
 {
 	struct rte_rib6_node *cur;
 	struct rte_rib6_node *prev = NULL;
@@ -144,7 +144,7 @@ rte_rib6_lookup(struct rte_rib6 *rib,
 	}
 	cur = rib->tree;
 
-	while ((cur != NULL) && is_covered(ip, cur->ip, cur->depth)) {
+	while ((cur != NULL) && is_covered(ip->a, cur->ip.a, cur->depth)) {
 		if (is_valid_node(cur))
 			prev = cur;
 		cur = get_nxt_node(cur, ip);
@@ -169,10 +169,10 @@ rte_rib6_lookup_parent(struct rte_rib6_node *ent)
 
 struct rte_rib6_node *
 rte_rib6_lookup_exact(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth)
+	const struct rte_ipv6_addr *ip, uint8_t depth)
 {
 	struct rte_rib6_node *cur;
-	uint8_t tmp_ip[RTE_RIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr tmp_ip;
 	int i;
 
 	if (unlikely(rib == NULL || ip == NULL || depth > RIB6_MAXDEPTH)) {
@@ -182,19 +182,19 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
 	cur = rib->tree;
 
 	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		tmp_ip[i] = ip[i] & get_msk_part(depth, i);
+		tmp_ip.a[i] = ip->a[i] & get_msk_part(depth, i);
 
 	while (cur != NULL) {
-		if (rte_rib6_is_equal(cur->ip, tmp_ip) &&
+		if (rte_rib6_is_equal(cur->ip.a, tmp_ip.a) &&
 				(cur->depth == depth) &&
 				is_valid_node(cur))
 			return cur;
 
-		if (!(is_covered(tmp_ip, cur->ip, cur->depth)) ||
+		if (!(is_covered(tmp_ip.a, cur->ip.a, cur->depth)) ||
 				(cur->depth >= depth))
 			break;
 
-		cur = get_nxt_node(cur, tmp_ip);
+		cur = get_nxt_node(cur, &tmp_ip);
 	}
 
 	return NULL;
@@ -207,11 +207,11 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
  */
 struct rte_rib6_node *
 rte_rib6_get_nxt(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE],
+	const struct rte_ipv6_addr *ip,
 	uint8_t depth, struct rte_rib6_node *last, int flag)
 {
 	struct rte_rib6_node *tmp, *prev = NULL;
-	uint8_t tmp_ip[RTE_RIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr tmp_ip;
 	int i;
 
 	if (unlikely(rib == NULL || ip == NULL || depth > RIB6_MAXDEPTH)) {
@@ -220,19 +220,19 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 	}
 
 	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		tmp_ip[i] = ip[i] & get_msk_part(depth, i);
+		tmp_ip.a[i] = ip->a[i] & get_msk_part(depth, i);
 
 	if (last == NULL) {
 		tmp = rib->tree;
 		while ((tmp) && (tmp->depth < depth))
-			tmp = get_nxt_node(tmp, tmp_ip);
+			tmp = get_nxt_node(tmp, &tmp_ip);
 	} else {
 		tmp = last;
 		while ((tmp->parent != NULL) && (is_right_node(tmp) ||
 				(tmp->parent->right == NULL))) {
 			tmp = tmp->parent;
 			if (is_valid_node(tmp) &&
-					(is_covered(tmp->ip, tmp_ip, depth) &&
+					(is_covered(tmp->ip.a, tmp_ip.a, depth) &&
 					(tmp->depth > depth)))
 				return tmp;
 		}
@@ -240,7 +240,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 	}
 	while (tmp) {
 		if (is_valid_node(tmp) &&
-				(is_covered(tmp->ip, tmp_ip, depth) &&
+				(is_covered(tmp->ip.a, tmp_ip.a, depth) &&
 				(tmp->depth > depth))) {
 			prev = tmp;
 			if (flag == RTE_RIB6_GET_NXT_COVER)
@@ -253,7 +253,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 
 void
 rte_rib6_remove(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth)
+	const struct rte_ipv6_addr *ip, uint8_t depth)
 {
 	struct rte_rib6_node *cur, *prev, *child;
 
@@ -286,14 +286,14 @@ rte_rib6_remove(struct rte_rib6 *rib,
 
 struct rte_rib6_node *
 rte_rib6_insert(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth)
+	const struct rte_ipv6_addr *ip, uint8_t depth)
 {
 	struct rte_rib6_node **tmp;
 	struct rte_rib6_node *prev = NULL;
 	struct rte_rib6_node *new_node = NULL;
 	struct rte_rib6_node *common_node = NULL;
-	uint8_t common_prefix[RTE_RIB6_IPV6_ADDR_SIZE];
-	uint8_t tmp_ip[RTE_RIB6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr common_prefix;
+	struct rte_ipv6_addr tmp_ip;
 	int i, d;
 	uint8_t common_depth, ip_xor;
 
@@ -305,9 +305,9 @@ rte_rib6_insert(struct rte_rib6 *rib,
 	tmp = &rib->tree;
 
 	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		tmp_ip[i] = ip[i] & get_msk_part(depth, i);
+		tmp_ip.a[i] = ip->a[i] & get_msk_part(depth, i);
 
-	new_node = rte_rib6_lookup_exact(rib, tmp_ip, depth);
+	new_node = rte_rib6_lookup_exact(rib, &tmp_ip, depth);
 	if (new_node != NULL) {
 		rte_errno = EEXIST;
 		return NULL;
@@ -321,7 +321,7 @@ rte_rib6_insert(struct rte_rib6 *rib,
 	new_node->left = NULL;
 	new_node->right = NULL;
 	new_node->parent = NULL;
-	rte_rib6_copy_addr(new_node->ip, tmp_ip);
+	rte_rib6_copy_addr(new_node->ip.a, tmp_ip.a);
 	new_node->depth = depth;
 	new_node->flag = RTE_RIB_VALID_NODE;
 
@@ -340,7 +340,7 @@ rte_rib6_insert(struct rte_rib6 *rib,
 		 * but node with proper search criteria is found.
 		 * Validate intermediate node and return.
 		 */
-		if (rte_rib6_is_equal(tmp_ip, (*tmp)->ip) &&
+		if (rte_rib6_is_equal(tmp_ip.a, (*tmp)->ip.a) &&
 				(depth == (*tmp)->depth)) {
 			node_free(rib, new_node);
 			(*tmp)->flag |= RTE_RIB_VALID_NODE;
@@ -348,20 +348,20 @@ rte_rib6_insert(struct rte_rib6 *rib,
 			return *tmp;
 		}
 
-		if (!is_covered(tmp_ip, (*tmp)->ip, (*tmp)->depth) ||
+		if (!is_covered(tmp_ip.a, (*tmp)->ip.a, (*tmp)->depth) ||
 				((*tmp)->depth >= depth)) {
 			break;
 		}
 		prev = *tmp;
 
-		tmp = (get_dir(tmp_ip, (*tmp)->depth)) ? &(*tmp)->right :
+		tmp = (get_dir(&tmp_ip, (*tmp)->depth)) ? &(*tmp)->right :
 				&(*tmp)->left;
 	}
 
 	/* closest node found, new_node should be inserted in the middle */
 	common_depth = RTE_MIN(depth, (*tmp)->depth);
 	for (i = 0, d = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++) {
-		ip_xor = tmp_ip[i] ^ (*tmp)->ip[i];
+		ip_xor = tmp_ip.a[i] ^ (*tmp)->ip.a[i];
 		if (ip_xor == 0)
 			d += 8;
 		else {
@@ -373,12 +373,12 @@ rte_rib6_insert(struct rte_rib6 *rib,
 	common_depth = RTE_MIN(d, common_depth);
 
 	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		common_prefix[i] = tmp_ip[i] & get_msk_part(common_depth, i);
+		common_prefix.a[i] = tmp_ip.a[i] & get_msk_part(common_depth, i);
 
-	if (rte_rib6_is_equal(common_prefix, tmp_ip) &&
+	if (rte_rib6_is_equal(common_prefix.a, tmp_ip.a) &&
 			(common_depth == depth)) {
 		/* insert as a parent */
-		if (get_dir((*tmp)->ip, depth))
+		if (get_dir(&(*tmp)->ip, depth))
 			new_node->right = *tmp;
 		else
 			new_node->left = *tmp;
@@ -393,13 +393,13 @@ rte_rib6_insert(struct rte_rib6 *rib,
 			rte_errno = ENOMEM;
 			return NULL;
 		}
-		rte_rib6_copy_addr(common_node->ip, common_prefix);
+		rte_rib6_copy_addr(common_node->ip.a, common_prefix.a);
 		common_node->depth = common_depth;
 		common_node->flag = 0;
 		common_node->parent = (*tmp)->parent;
 		new_node->parent = common_node;
 		(*tmp)->parent = common_node;
-		if (get_dir((*tmp)->ip, common_depth) == 1) {
+		if (get_dir(&(*tmp)->ip, common_depth) == 1) {
 			common_node->left = new_node;
 			common_node->right = *tmp;
 		} else {
@@ -414,13 +414,13 @@ rte_rib6_insert(struct rte_rib6 *rib,
 
 int
 rte_rib6_get_ip(const struct rte_rib6_node *node,
-		uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE])
+		struct rte_ipv6_addr *ip)
 {
 	if (unlikely(node == NULL || ip == NULL)) {
 		rte_errno = EINVAL;
 		return -1;
 	}
-	rte_rib6_copy_addr(ip, node->ip);
+	rte_rib6_copy_addr(ip->a, node->ip.a);
 	return 0;
 }
 
@@ -604,7 +604,7 @@ rte_rib6_free(struct rte_rib6 *rib)
 
 	while ((tmp = rte_rib6_get_nxt(rib, 0, 0, tmp,
 			RTE_RIB6_GET_NXT_ALL)) != NULL)
-		rte_rib6_remove(rib, tmp->ip, tmp->depth);
+		rte_rib6_remove(rib, &tmp->ip, tmp->depth);
 
 	rte_mempool_free(rib->node_pool);
 
diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
index 775286f965f2..47dcb6d15183 100644
--- a/lib/rib/rte_rib6.h
+++ b/lib/rib/rte_rib6.h
@@ -16,6 +16,7 @@
 
 #include <rte_memcpy.h>
 #include <rte_common.h>
+#include <rte_ip6.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -124,7 +125,7 @@ get_msk_part(uint8_t depth, int byte) {
  */
 struct rte_rib6_node *
 rte_rib6_lookup(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE]);
+	const struct rte_ipv6_addr *ip);
 
 /**
  * Lookup less specific route into the RIB structure
@@ -154,7 +155,7 @@ rte_rib6_lookup_parent(struct rte_rib6_node *ent);
  */
 struct rte_rib6_node *
 rte_rib6_lookup_exact(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
+	const struct rte_ipv6_addr *ip, uint8_t depth);
 
 /**
  * Retrieve next more specific prefix from the RIB
@@ -181,7 +182,7 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
  */
 struct rte_rib6_node *
 rte_rib6_get_nxt(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE],
+	const struct rte_ipv6_addr *ip,
 	uint8_t depth, struct rte_rib6_node *last, int flag);
 
 /**
@@ -196,7 +197,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
  */
 void
 rte_rib6_remove(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
+	const struct rte_ipv6_addr *ip, uint8_t depth);
 
 /**
  * Insert prefix into the RIB
@@ -213,7 +214,7 @@ rte_rib6_remove(struct rte_rib6 *rib,
  */
 struct rte_rib6_node *
 rte_rib6_insert(struct rte_rib6 *rib,
-	const uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth);
+	const struct rte_ipv6_addr *ip, uint8_t depth);
 
 /**
  * Get an ip from rte_rib6_node
@@ -228,7 +229,7 @@ rte_rib6_insert(struct rte_rib6 *rib,
  */
 int
 rte_rib6_get_ip(const struct rte_rib6_node *node,
-		uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE]);
+		struct rte_ipv6_addr *ip);
 
 /**
  * Get a depth from rte_rib6_node
diff --git a/lib/table/rte_table_lpm_ipv6.c b/lib/table/rte_table_lpm_ipv6.c
index c1a7412f92cf..dea11130d3d5 100644
--- a/lib/table/rte_table_lpm_ipv6.c
+++ b/lib/table/rte_table_lpm_ipv6.c
@@ -207,7 +207,7 @@ rte_table_lpm_ipv6_entry_add(
 	}
 
 	/* Check if rule is already present in the table */
-	status = rte_lpm6_is_rule_present(lpm->lpm, ip_prefix->ip,
+	status = rte_lpm6_is_rule_present(lpm->lpm, &ip_prefix->ip,
 		ip_prefix->depth, &nht_pos0);
 	nht_pos0_valid = status > 0;
 
@@ -225,7 +225,7 @@ rte_table_lpm_ipv6_entry_add(
 	}
 
 	/* Add rule to low level LPM table */
-	if (rte_lpm6_add(lpm->lpm, ip_prefix->ip, ip_prefix->depth,
+	if (rte_lpm6_add(lpm->lpm, &ip_prefix->ip, ip_prefix->depth,
 		nht_pos) < 0) {
 		TABLE_LOG(ERR, "%s: LPM IPv6 rule add failed", __func__);
 		return -1;
@@ -270,7 +270,7 @@ rte_table_lpm_ipv6_entry_delete(
 	}
 
 	/* Return if rule is not present in the table */
-	status = rte_lpm6_is_rule_present(lpm->lpm, ip_prefix->ip,
+	status = rte_lpm6_is_rule_present(lpm->lpm, &ip_prefix->ip,
 		ip_prefix->depth, &nht_pos);
 	if (status < 0) {
 		TABLE_LOG(ERR, "%s: LPM IPv6 algorithmic error",
@@ -283,7 +283,7 @@ rte_table_lpm_ipv6_entry_delete(
 	}
 
 	/* Delete rule from the low-level LPM table */
-	status = rte_lpm6_delete(lpm->lpm, ip_prefix->ip, ip_prefix->depth);
+	status = rte_lpm6_delete(lpm->lpm, &ip_prefix->ip, ip_prefix->depth);
 	if (status) {
 		TABLE_LOG(ERR, "%s: LPM IPv6 rule delete failed",
 			__func__);
@@ -323,11 +323,11 @@ rte_table_lpm_ipv6_lookup(
 
 		if (pkt_mask & pkts_mask) {
 			struct rte_mbuf *pkt = pkts[i];
-			uint8_t *ip = RTE_MBUF_METADATA_UINT8_PTR(pkt,
-				lpm->offset);
+			const struct rte_ipv6_addr *ip;
 			int status;
 			uint32_t nht_pos;
 
+			ip = (struct rte_ipv6_addr *)RTE_MBUF_METADATA_UINT8_PTR(pkt, lpm->offset);
 			status = rte_lpm6_lookup(lpm->lpm, ip, &nht_pos);
 			if (status == 0) {
 				pkts_out_mask |= pkt_mask;
diff --git a/lib/table/rte_table_lpm_ipv6.h b/lib/table/rte_table_lpm_ipv6.h
index 96ddbd32c20e..d96ce1179954 100644
--- a/lib/table/rte_table_lpm_ipv6.h
+++ b/lib/table/rte_table_lpm_ipv6.h
@@ -45,7 +45,7 @@ extern "C" {
 
 #include "rte_table.h"
 
-#define RTE_LPM_IPV6_ADDR_SIZE 16
+#include <rte_ip6.h>
 
 /** LPM table parameters */
 struct rte_table_lpm_ipv6_params {
@@ -73,7 +73,7 @@ each rule covering for a multitude of lookup keys (destination IP addresses)
 that share the same data (next hop). */
 struct rte_table_lpm_ipv6_key {
 	/** IP address */
-	uint8_t ip[RTE_LPM_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr ip;
 
 	/** IP address depth. The most significant "depth" bits of the IP
 	address specify the network part of the IP address, while the rest of
-- 
2.46.0


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

* [PATCH dpdk v1 06/15] net: add ipv6 address utilities
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (4 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 05/15] fib6,rib6,lpm6: use ipv6 addr struct Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 07/15] fib6,rib6,lpm6: use ipv6 utils Robin Jarry
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev

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>
---
 app/test/meson.build     |   1 +
 app/test/test_net_ipv6.c | 129 +++++++++++++++++++++++++++++++++++++++
 lib/net/rte_ip6.h        | 112 +++++++++++++++++++++++++++++++++
 3 files changed, 242 insertions(+)
 create mode 100644 app/test/test_net_ipv6.c

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 58cab86895eb..6bc18a1c8dd6 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,116 @@ struct rte_ipv6_addr {
 	unsigned char a[RTE_IPV6_ADDR_SIZE];
 };
 
+/**
+ * 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;
+}
+
+/**
+ * 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)
+{
+	static const struct rte_ipv6_addr unspec = {0};
+	return rte_ipv6_addr_eq(ip, &unspec);
+}
+
 /**
  * IPv6 Header
  */
-- 
2.46.0


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

* [PATCH dpdk v1 07/15] fib6,rib6,lpm6: use ipv6 utils
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (5 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 06/15] net: add ipv6 address utilities Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 08/15] graph,node: use ipv6 addr struct and utils Robin Jarry
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Vladimir Medvedkin, Wathsala Vithanage, Radu Nicolau,
	Akhil Goyal, Bruce Richardson

Replace duplicated and/or private functions by some of the previously
introduced utility functions.

Mark rib6 functions that deal with ipv6 addresses as deprecated.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test/test_fib6.c                  |  9 +++--
 app/test/test_rib6.c                  |  2 +-
 examples/ipsec-secgw/ipsec_lpm_neon.h |  2 +-
 lib/fib/trie.c                        | 30 ++++++--------
 lib/lpm/rte_lpm6.c                    | 51 +++++-------------------
 lib/rib/rte_rib6.c                    | 57 +++++++++------------------
 lib/rib/rte_rib6.h                    |  8 ++++
 7 files changed, 56 insertions(+), 103 deletions(-)

diff --git a/app/test/test_fib6.c b/app/test/test_fib6.c
index c3b947d789bb..7134c4d335cd 100644
--- a/app/test/test_fib6.c
+++ b/app/test/test_fib6.c
@@ -279,9 +279,12 @@ check_fib(struct rte_fib6 *fib)
 	int ret;
 
 	for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
-		for (j = 0; j < RTE_FIB6_IPV6_ADDR_SIZE; j++) {
-			ip_arr[i].a[j] = ip_add.a[j] |
-				~get_msk_part(RTE_FIB6_MAXDEPTH - i, j);
+		rte_ipv6_addr_cpy(&ip_arr[i], &ip_add);
+		j = (RTE_FIB6_MAXDEPTH - i) / CHAR_BIT;
+		if (j < RTE_FIB6_IPV6_ADDR_SIZE) {
+			ip_arr[i].a[j] |= UINT8_MAX >> ((RTE_FIB6_MAXDEPTH - i) % CHAR_BIT);
+			for (j++; j < RTE_FIB6_IPV6_ADDR_SIZE; j++)
+				ip_arr[i].a[j] = 0xff;
 		}
 	}
 
diff --git a/app/test/test_rib6.c b/app/test/test_rib6.c
index f3b6f1474348..33288f9c26d6 100644
--- a/app/test/test_rib6.c
+++ b/app/test/test_rib6.c
@@ -217,7 +217,7 @@ test_get_fn(void)
 
 	/* check the return values */
 	ret = rte_rib6_get_ip(node, &ip_ret);
-	RTE_TEST_ASSERT((ret == 0) && (rte_rib6_is_equal(ip_ret.a, ip.a)),
+	RTE_TEST_ASSERT((ret == 0) && (rte_ipv6_addr_eq(&ip_ret, &ip)),
 		"Failed to get proper node ip\n");
 	ret = rte_rib6_get_depth(node, &depth_ret);
 	RTE_TEST_ASSERT((ret == 0) && (depth_ret == depth),
diff --git a/examples/ipsec-secgw/ipsec_lpm_neon.h b/examples/ipsec-secgw/ipsec_lpm_neon.h
index 865b9624a86e..62b4260843a3 100644
--- a/examples/ipsec-secgw/ipsec_lpm_neon.h
+++ b/examples/ipsec-secgw/ipsec_lpm_neon.h
@@ -144,7 +144,7 @@ route6_pkts_neon(struct rt_ctx *rt_ctx, struct rte_mbuf **pkts, int nb_rx)
 			 * required to get the hop
 			 */
 			ipv6_hdr = (struct rte_ipv6_hdr *)(eth_hdr + 1);
-			memcpy(&dst_ip6[lpm_pkts], &ipv6_hdr->dst_addr, 16);
+			rte_ipv6_addr_cpy(&dst_ip6[lpm_pkts], &ipv6_hdr->dst_addr);
 			lpm_pkts++;
 		}
 	}
diff --git a/lib/fib/trie.c b/lib/fib/trie.c
index bd0c7ec63b7f..8a69702eabb2 100644
--- a/lib/fib/trie.c
+++ b/lib/fib/trie.c
@@ -367,7 +367,7 @@ install_to_dp(struct rte_trie_tbl *dp, const struct rte_ipv6_addr *ledge,
 	struct rte_ipv6_addr redge;
 
 	/* decrement redge by 1*/
-	rte_rib6_copy_addr(redge.a, r->a);
+	rte_ipv6_addr_cpy(&redge, r);
 	for (i = 15; i >= 0; i--) {
 		redge.a[i]--;
 		if (redge.a[i] != 0xff)
@@ -451,14 +451,6 @@ get_nxt_net(struct rte_ipv6_addr *ip, uint8_t depth)
 	}
 }
 
-static int
-v6_addr_is_zero(const uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE])
-{
-	uint8_t ip_addr[RTE_FIB6_IPV6_ADDR_SIZE] = {0};
-
-	return rte_rib6_is_equal(ip, ip_addr);
-}
-
 static int
 modify_dp(struct rte_trie_tbl *dp, struct rte_rib6 *rib,
 	const struct rte_ipv6_addr *ip,
@@ -472,7 +464,7 @@ modify_dp(struct rte_trie_tbl *dp, struct rte_rib6 *rib,
 	if (next_hop > get_max_nh(dp->nh_sz))
 		return -EINVAL;
 
-	rte_rib6_copy_addr(ledge.a, ip->a);
+	rte_ipv6_addr_cpy(&ledge, ip);
 	do {
 		tmp = rte_rib6_get_nxt(rib, ip, depth, tmp,
 			RTE_RIB6_GET_NXT_COVER);
@@ -481,7 +473,7 @@ modify_dp(struct rte_trie_tbl *dp, struct rte_rib6 *rib,
 			if (tmp_depth == depth)
 				continue;
 			rte_rib6_get_ip(tmp, &redge);
-			if (rte_rib6_is_equal(ledge.a, redge.a)) {
+			if (rte_ipv6_addr_eq(&ledge, &redge)) {
 				get_nxt_net(&ledge, tmp_depth);
 				continue;
 			}
@@ -489,18 +481,18 @@ modify_dp(struct rte_trie_tbl *dp, struct rte_rib6 *rib,
 			if (ret != 0)
 				return ret;
 			get_nxt_net(&redge, tmp_depth);
-			rte_rib6_copy_addr(ledge.a, redge.a);
+			rte_ipv6_addr_cpy(&ledge, &redge);
 			/*
 			 * we got to the end of address space
 			 * and wrapped around
 			 */
-			if (v6_addr_is_zero(ledge.a))
+			if (rte_ipv6_addr_is_unspec(&ledge))
 				break;
 		} else {
-			rte_rib6_copy_addr(redge.a, ip->a);
+			rte_ipv6_addr_cpy(&redge, ip);
 			get_nxt_net(&redge, depth);
-			if (rte_rib6_is_equal(ledge.a, redge.a) &&
-					!v6_addr_is_zero(ledge.a))
+			if (rte_ipv6_addr_eq(&ledge, &redge) &&
+					!rte_ipv6_addr_is_unspec(&ledge))
 				break;
 
 			ret = install_to_dp(dp, &ledge, &redge, next_hop);
@@ -522,7 +514,7 @@ trie_modify(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	struct rte_rib6_node *node;
 	struct rte_rib6_node *parent;
 	struct rte_ipv6_addr ip_masked;
-	int i, ret = 0;
+	int ret = 0;
 	uint64_t par_nh, node_nh;
 	uint8_t tmp_depth, depth_diff = 0, parent_depth = 24;
 
@@ -534,8 +526,8 @@ trie_modify(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	rib = rte_fib6_get_rib(fib);
 	RTE_ASSERT(rib);
 
-	for (i = 0; i < RTE_FIB6_IPV6_ADDR_SIZE; i++)
-		ip_masked.a[i] = ip->a[i] & get_msk_part(depth, i);
+	rte_ipv6_addr_cpy(&ip_masked, ip);
+	rte_ipv6_addr_mask(&ip_masked, depth);
 
 	if (depth > 24) {
 		tmp = rte_rib6_get_nxt(rib, &ip_masked,
diff --git a/lib/lpm/rte_lpm6.c b/lib/lpm/rte_lpm6.c
index d3f1c8485f5f..642b02b32cc2 100644
--- a/lib/lpm/rte_lpm6.c
+++ b/lib/lpm/rte_lpm6.c
@@ -111,37 +111,6 @@ struct rte_lpm6 {
 			/**< LPM tbl8 table. */
 };
 
-/*
- * Takes an array of uint8_t (IPv6 address) and masks it using the depth.
- * It leaves untouched one bit per unit in the depth variable
- * and set the rest to 0.
- */
-static inline void
-ip6_mask_addr(uint8_t *ip, uint8_t depth)
-{
-	int16_t part_depth, mask;
-	int i;
-
-	part_depth = depth;
-
-	for (i = 0; i < RTE_LPM6_IPV6_ADDR_SIZE; i++) {
-		if (part_depth < BYTE_SIZE && part_depth >= 0) {
-			mask = (uint16_t)(~(UINT8_MAX >> part_depth));
-			ip[i] = (uint8_t)(ip[i] & mask);
-		} else if (part_depth < 0)
-			ip[i] = 0;
-
-		part_depth -= BYTE_SIZE;
-	}
-}
-
-/* copy ipv6 address */
-static inline void
-ip6_copy_addr(uint8_t *dst, const uint8_t *src)
-{
-	rte_memcpy(dst, src, RTE_LPM6_IPV6_ADDR_SIZE);
-}
-
 /*
  * LPM6 rule hash function
  *
@@ -215,7 +184,7 @@ tbl8_available(struct rte_lpm6 *lpm)
 static inline void
 rule_key_init(struct rte_lpm6_rule_key *key, const struct rte_ipv6_addr *ip, uint8_t depth)
 {
-	ip6_copy_addr(key->ip.a, ip->a);
+	rte_ipv6_addr_cpy(&key->ip, ip);
 	key->depth = depth;
 }
 
@@ -867,8 +836,8 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
-	ip6_copy_addr(masked_ip.a, ip->a);
-	ip6_mask_addr(masked_ip.a, depth);
+	rte_ipv6_addr_cpy(&masked_ip, ip);
+	rte_ipv6_addr_mask(&masked_ip, depth);
 
 	/* Simulate adding a new route */
 	int ret = simulate_add(lpm, &masked_ip, depth);
@@ -1028,8 +997,8 @@ rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, u
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
-	ip6_copy_addr(masked_ip.a, ip->a);
-	ip6_mask_addr(masked_ip.a, depth);
+	rte_ipv6_addr_cpy(&masked_ip, ip);
+	rte_ipv6_addr_mask(&masked_ip, depth);
 
 	return rule_find(lpm, &masked_ip, depth, next_hop);
 }
@@ -1078,8 +1047,8 @@ rte_lpm6_delete_bulk_func(struct rte_lpm6 *lpm,
 		return -EINVAL;
 
 	for (i = 0; i < n; i++) {
-		ip6_copy_addr(masked_ip.a, ips[i].a);
-		ip6_mask_addr(masked_ip.a, depths[i]);
+		rte_ipv6_addr_cpy(&masked_ip, &ips[i]);
+		rte_ipv6_addr_mask(&masked_ip, depths[i]);
 		rule_delete(lpm, &masked_ip, depths[i]);
 	}
 
@@ -1168,7 +1137,7 @@ rule_find_less_specific(struct rte_lpm6 *lpm, struct rte_ipv6_addr *ip, uint8_t
 		ret = rule_find_with_key(lpm, &rule_key, &next_hop);
 		if (ret) {
 			rule->depth = depth;
-			ip6_copy_addr(rule->ip.a, rule_key.ip.a);
+			rte_ipv6_addr_cpy(&rule->ip, &rule_key.ip);
 			rule->next_hop = next_hop;
 			return 1;
 		}
@@ -1302,8 +1271,8 @@ rte_lpm6_delete(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t de
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
-	ip6_copy_addr(masked_ip.a, ip->a);
-	ip6_mask_addr(masked_ip.a, depth);
+	rte_ipv6_addr_cpy(&masked_ip, ip);
+	rte_ipv6_addr_mask(&masked_ip, depth);
 
 	/* Delete the rule from the rule table. */
 	ret = rule_delete(lpm, &masked_ip, depth);
diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
index a1ac418eb87a..ec46c865ddf7 100644
--- a/lib/rib/rte_rib6.c
+++ b/lib/rib/rte_rib6.c
@@ -62,22 +62,6 @@ is_right_node(const struct rte_rib6_node *node)
 	return node->parent->right == node;
 }
 
-/*
- * Check if ip1 is covered by ip2/depth prefix
- */
-static inline bool
-is_covered(const uint8_t ip1[RTE_RIB6_IPV6_ADDR_SIZE],
-		const uint8_t ip2[RTE_RIB6_IPV6_ADDR_SIZE], uint8_t depth)
-{
-	int i;
-
-	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		if ((ip1[i] ^ ip2[i]) & get_msk_part(depth, i))
-			return false;
-
-	return true;
-}
-
 static inline int
 get_dir(const struct rte_ipv6_addr *ip, uint8_t depth)
 {
@@ -144,7 +128,7 @@ rte_rib6_lookup(struct rte_rib6 *rib,
 	}
 	cur = rib->tree;
 
-	while ((cur != NULL) && is_covered(ip->a, cur->ip.a, cur->depth)) {
+	while ((cur != NULL) && rte_ipv6_addr_eq_prefix(ip, &cur->ip, cur->depth)) {
 		if (is_valid_node(cur))
 			prev = cur;
 		cur = get_nxt_node(cur, ip);
@@ -173,7 +157,6 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
 {
 	struct rte_rib6_node *cur;
 	struct rte_ipv6_addr tmp_ip;
-	int i;
 
 	if (unlikely(rib == NULL || ip == NULL || depth > RIB6_MAXDEPTH)) {
 		rte_errno = EINVAL;
@@ -181,16 +164,16 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
 	}
 	cur = rib->tree;
 
-	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		tmp_ip.a[i] = ip->a[i] & get_msk_part(depth, i);
+	rte_ipv6_addr_cpy(&tmp_ip, ip);
+	rte_ipv6_addr_mask(&tmp_ip, depth);
 
 	while (cur != NULL) {
-		if (rte_rib6_is_equal(cur->ip.a, tmp_ip.a) &&
+		if (rte_ipv6_addr_eq(&cur->ip, &tmp_ip) &&
 				(cur->depth == depth) &&
 				is_valid_node(cur))
 			return cur;
 
-		if (!(is_covered(tmp_ip.a, cur->ip.a, cur->depth)) ||
+		if (!rte_ipv6_addr_eq_prefix(&tmp_ip, &cur->ip, cur->depth) ||
 				(cur->depth >= depth))
 			break;
 
@@ -212,15 +195,14 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 {
 	struct rte_rib6_node *tmp, *prev = NULL;
 	struct rte_ipv6_addr tmp_ip;
-	int i;
 
 	if (unlikely(rib == NULL || ip == NULL || depth > RIB6_MAXDEPTH)) {
 		rte_errno = EINVAL;
 		return NULL;
 	}
 
-	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		tmp_ip.a[i] = ip->a[i] & get_msk_part(depth, i);
+	rte_ipv6_addr_cpy(&tmp_ip, ip);
+	rte_ipv6_addr_mask(&tmp_ip, depth);
 
 	if (last == NULL) {
 		tmp = rib->tree;
@@ -232,7 +214,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 				(tmp->parent->right == NULL))) {
 			tmp = tmp->parent;
 			if (is_valid_node(tmp) &&
-					(is_covered(tmp->ip.a, tmp_ip.a, depth) &&
+					(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
 					(tmp->depth > depth)))
 				return tmp;
 		}
@@ -240,7 +222,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 	}
 	while (tmp) {
 		if (is_valid_node(tmp) &&
-				(is_covered(tmp->ip.a, tmp_ip.a, depth) &&
+				(rte_ipv6_addr_eq_prefix(&tmp->ip, &tmp_ip, depth) &&
 				(tmp->depth > depth))) {
 			prev = tmp;
 			if (flag == RTE_RIB6_GET_NXT_COVER)
@@ -304,8 +286,8 @@ rte_rib6_insert(struct rte_rib6 *rib,
 
 	tmp = &rib->tree;
 
-	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		tmp_ip.a[i] = ip->a[i] & get_msk_part(depth, i);
+	rte_ipv6_addr_cpy(&tmp_ip, ip);
+	rte_ipv6_addr_mask(&tmp_ip, depth);
 
 	new_node = rte_rib6_lookup_exact(rib, &tmp_ip, depth);
 	if (new_node != NULL) {
@@ -321,7 +303,7 @@ rte_rib6_insert(struct rte_rib6 *rib,
 	new_node->left = NULL;
 	new_node->right = NULL;
 	new_node->parent = NULL;
-	rte_rib6_copy_addr(new_node->ip.a, tmp_ip.a);
+	rte_ipv6_addr_cpy(&new_node->ip, &tmp_ip);
 	new_node->depth = depth;
 	new_node->flag = RTE_RIB_VALID_NODE;
 
@@ -340,15 +322,14 @@ rte_rib6_insert(struct rte_rib6 *rib,
 		 * but node with proper search criteria is found.
 		 * Validate intermediate node and return.
 		 */
-		if (rte_rib6_is_equal(tmp_ip.a, (*tmp)->ip.a) &&
-				(depth == (*tmp)->depth)) {
+		if (rte_ipv6_addr_eq(&tmp_ip, &(*tmp)->ip) && (depth == (*tmp)->depth)) {
 			node_free(rib, new_node);
 			(*tmp)->flag |= RTE_RIB_VALID_NODE;
 			++rib->cur_routes;
 			return *tmp;
 		}
 
-		if (!is_covered(tmp_ip.a, (*tmp)->ip.a, (*tmp)->depth) ||
+		if (!rte_ipv6_addr_eq_prefix(&tmp_ip, &(*tmp)->ip, (*tmp)->depth) ||
 				((*tmp)->depth >= depth)) {
 			break;
 		}
@@ -372,10 +353,10 @@ rte_rib6_insert(struct rte_rib6 *rib,
 
 	common_depth = RTE_MIN(d, common_depth);
 
-	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++)
-		common_prefix.a[i] = tmp_ip.a[i] & get_msk_part(common_depth, i);
+	rte_ipv6_addr_cpy(&common_prefix, &tmp_ip);
+	rte_ipv6_addr_mask(&common_prefix, common_depth);
 
-	if (rte_rib6_is_equal(common_prefix.a, tmp_ip.a) &&
+	if (rte_ipv6_addr_eq(&common_prefix, &tmp_ip) &&
 			(common_depth == depth)) {
 		/* insert as a parent */
 		if (get_dir(&(*tmp)->ip, depth))
@@ -393,7 +374,7 @@ rte_rib6_insert(struct rte_rib6 *rib,
 			rte_errno = ENOMEM;
 			return NULL;
 		}
-		rte_rib6_copy_addr(common_node->ip.a, common_prefix.a);
+		rte_ipv6_addr_cpy(&common_node->ip, &common_prefix);
 		common_node->depth = common_depth;
 		common_node->flag = 0;
 		common_node->parent = (*tmp)->parent;
@@ -420,7 +401,7 @@ rte_rib6_get_ip(const struct rte_rib6_node *node,
 		rte_errno = EINVAL;
 		return -1;
 	}
-	rte_rib6_copy_addr(ip->a, node->ip.a);
+	rte_ipv6_addr_cpy(ip, &node->ip);
 	return 0;
 }
 
diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
index 47dcb6d15183..fcf4169ca790 100644
--- a/lib/rib/rte_rib6.h
+++ b/lib/rib/rte_rib6.h
@@ -57,6 +57,9 @@ struct rte_rib6_conf {
  * @param src
  *  pointer from where to copy
  */
+static inline void rte_rib6_copy_addr(uint8_t *dst, const uint8_t *src)
+	__rte_deprecated_msg("replaced by rte_ipv6_addr_cpy");
+
 static inline void
 rte_rib6_copy_addr(uint8_t *dst, const uint8_t *src)
 {
@@ -77,6 +80,9 @@ rte_rib6_copy_addr(uint8_t *dst, const uint8_t *src)
  *  1 if equal
  *  0 otherwise
  */
+static inline int rte_rib6_is_equal(const uint8_t *ip1, const uint8_t *ip2)
+	__rte_deprecated_msg("replaced by rte_ipv6_addr_eq");
+
 static inline int
 rte_rib6_is_equal(const uint8_t *ip1, const uint8_t *ip2) {
 	int i;
@@ -101,6 +107,8 @@ rte_rib6_is_equal(const uint8_t *ip1, const uint8_t *ip2) {
  * @return
  *  8-bit chunk of the 128-bit IPv6 mask
  */
+static inline uint8_t get_msk_part(uint8_t depth, int byte) __rte_deprecated;
+
 static inline uint8_t
 get_msk_part(uint8_t depth, int byte) {
 	uint8_t part;
-- 
2.46.0


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

* [PATCH dpdk v1 08/15] graph,node: use ipv6 addr struct and utils
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (6 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 07/15] fib6,rib6,lpm6: use ipv6 utils Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 09/15] pipeline: use ipv6 addr struct Robin Jarry
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Sunil Kumar Kori, Rakesh Kudurumalla, Jerin Jacob,
	Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Pavan Nikhilesh

Replace ad-hoc uint8_t[16] arrays with the previously introduced IPv6
address structure.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/graph/ethdev.c          | 40 ++++++++++---------------------
 app/graph/ethdev.h          |  9 ++++---
 app/graph/ip6_route.c       | 47 +++++++++----------------------------
 app/graph/meson.build       |  2 +-
 app/graph/neigh.c           | 22 +++++++----------
 app/graph/neigh_priv.h      |  4 +++-
 app/graph/route.h           |  8 ++++---
 examples/l3fwd-graph/main.c | 30 +++++++++--------------
 lib/node/ip6_lookup.c       | 17 ++++++--------
 lib/node/rte_node_ip6_api.h |  3 ++-
 10 files changed, 65 insertions(+), 117 deletions(-)

diff --git a/app/graph/ethdev.c b/app/graph/ethdev.c
index cfc1b1856910..19c5ab685464 100644
--- a/app/graph/ethdev.c
+++ b/app/graph/ethdev.c
@@ -124,30 +124,19 @@ ethdev_portid_by_ip4(uint32_t ip, uint32_t mask)
 }
 
 int16_t
-ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask)
+ethdev_portid_by_ip6(struct rte_ipv6_addr *ip, struct rte_ipv6_addr *mask)
 {
-	int portid = -EINVAL;
 	struct ethdev *port;
-	int j;
 
 	TAILQ_FOREACH(port, &eth_node, next) {
-		for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) {
-			if (mask == NULL) {
-				if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) !=
-				    (ip[j] & port->ip6_addr.mask[j]))
-					break;
-
-			} else {
-				if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) !=
-				    (ip[j] & mask[j]))
-					break;
-			}
-		}
-		if (j == ETHDEV_IPV6_ADDR_LEN)
+		uint8_t depth = rte_ipv6_mask_depth(&port->ip6_addr.mask);
+		if (mask != NULL)
+			depth = RTE_MAX(depth, rte_ipv6_mask_depth(mask));
+		if (rte_ipv6_addr_eq_prefix(&port->ip6_addr.ip, ip, depth))
 			return port->config.port_id;
 	}
 
-	return portid;
+	return -EINVAL;
 }
 
 void
@@ -285,7 +274,7 @@ ethdev_ip6_addr_add(const char *name, struct ipv6_addr_config *config)
 {
 	struct ethdev *eth_hdl;
 	uint16_t portid = 0;
-	int rc, i;
+	int rc;
 
 	rc = rte_eth_dev_get_port_by_name(name, &portid);
 	if (rc < 0)
@@ -294,10 +283,8 @@ ethdev_ip6_addr_add(const char *name, struct ipv6_addr_config *config)
 	eth_hdl = ethdev_port_by_id(portid);
 
 	if (eth_hdl) {
-		for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) {
-			eth_hdl->ip6_addr.ip[i] = config->ip[i];
-			eth_hdl->ip6_addr.mask[i] = config->mask[i];
-		}
+		rte_ipv6_addr_cpy(&eth_hdl->ip6_addr.ip, &config->ip);
+		rte_ipv6_addr_cpy(&eth_hdl->ip6_addr.mask, &config->mask);
 		return 0;
 	}
 	rc = -EINVAL;
@@ -624,13 +611,10 @@ cmd_ethdev_dev_ip6_addr_add_parsed(void *parsed_result, __rte_unused struct cmdl
 {
 	struct cmd_ethdev_dev_ip6_addr_add_result *res = parsed_result;
 	struct ipv6_addr_config config;
-	int rc = -EINVAL, i;
+	int rc = -EINVAL;
 
-	for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++)
-		config.ip[i] = res->ip.addr.ipv6.s6_addr[i];
-
-	for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++)
-		config.mask[i] = res->mask.addr.ipv6.s6_addr[i];
+	rte_memcpy(&config.ip, &res->ip.addr.ipv6, sizeof(config.ip));
+	rte_memcpy(&config.mask, &res->mask.addr.ipv6, sizeof(config.mask));
 
 	rc = ethdev_ip6_addr_add(res->dev, &config);
 	if (rc < 0)
diff --git a/app/graph/ethdev.h b/app/graph/ethdev.h
index d0de593fc743..046689ee5fc7 100644
--- a/app/graph/ethdev.h
+++ b/app/graph/ethdev.h
@@ -6,8 +6,7 @@
 #define APP_GRAPH_ETHDEV_H
 
 #include <cmdline_parse.h>
-
-#define ETHDEV_IPV6_ADDR_LEN	16
+#include <rte_ip6.h>
 
 struct ipv4_addr_config {
 	uint32_t ip;
@@ -15,8 +14,8 @@ struct ipv4_addr_config {
 };
 
 struct ipv6_addr_config {
-	uint8_t ip[ETHDEV_IPV6_ADDR_LEN];
-	uint8_t mask[ETHDEV_IPV6_ADDR_LEN];
+	struct rte_ipv6_addr ip;
+	struct rte_ipv6_addr mask;
 };
 
 extern uint32_t enabled_port_mask;
@@ -25,7 +24,7 @@ void ethdev_start(void);
 void ethdev_stop(void);
 void *ethdev_mempool_list_by_portid(uint16_t portid);
 int16_t ethdev_portid_by_ip4(uint32_t ip, uint32_t mask);
-int16_t ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask);
+int16_t ethdev_portid_by_ip6(struct rte_ipv6_addr *ip, struct rte_ipv6_addr *mask);
 int16_t ethdev_txport_by_rxport_get(uint16_t portid_rx);
 void ethdev_list_clean(void);
 
diff --git a/app/graph/ip6_route.c b/app/graph/ip6_route.c
index 834719ecaeb4..5460e5070b42 100644
--- a/app/graph/ip6_route.c
+++ b/app/graph/ip6_route.c
@@ -11,6 +11,7 @@
 #include <cmdline_socket.h>
 
 #include <rte_node_ip6_api.h>
+#include <rte_ip6.h>
 
 #include "module_api.h"
 #include "route_priv.h"
@@ -43,38 +44,20 @@ find_route6_entry(struct route_ipv6_config *route)
 	return NULL;
 }
 
-static uint8_t
-convert_ip6_netmask_to_depth(uint8_t *netmask)
-{
-	uint8_t setbits = 0;
-	uint8_t mask;
-	int i;
-
-	for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) {
-		mask = netmask[i];
-		while (mask & 0x80) {
-			mask = mask << 1;
-			setbits++;
-		}
-	}
-
-	return setbits;
-}
-
 static int
 route6_rewirte_table_update(struct route_ipv6_config *ipv6route)
 {
 	uint8_t depth;
 	int portid;
 
-	portid = ethdev_portid_by_ip6(ipv6route->gateway, ipv6route->mask);
+	portid = ethdev_portid_by_ip6(&ipv6route->gateway, &ipv6route->mask);
 	if (portid < 0) {
 		printf("Invalid portid found to install the route\n");
 		return portid;
 	}
-	depth = convert_ip6_netmask_to_depth(ipv6route->mask);
+	depth = rte_ipv6_mask_depth(&ipv6route->mask);
 
-	return rte_node_ip6_route_add(ipv6route->ip, depth, portid,
+	return rte_node_ip6_route_add(&ipv6route->ip, depth, portid,
 			RTE_NODE_IP6_LOOKUP_NEXT_REWRITE);
 
 }
@@ -84,7 +67,6 @@ route_ip6_add(struct route_ipv6_config *route)
 {
 	struct route_ipv6_config *ipv6route;
 	int rc = -EINVAL;
-	int j;
 
 	ipv6route = find_route6_entry(route);
 	if (!ipv6route) {
@@ -95,11 +77,9 @@ route_ip6_add(struct route_ipv6_config *route)
 		return 0;
 	}
 
-	for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) {
-		ipv6route->ip[j] = route->ip[j];
-		ipv6route->mask[j] = route->mask[j];
-		ipv6route->gateway[j] = route->gateway[j];
-	}
+	rte_ipv6_addr_cpy(&ipv6route->ip, &route->ip);
+	rte_ipv6_addr_cpy(&ipv6route->mask, &route->mask);
+	rte_ipv6_addr_cpy(&ipv6route->gateway, &route->gateway);
 	ipv6route->is_used = true;
 
 	if (!graph_status_get())
@@ -154,16 +134,11 @@ cmd_ipv6_lookup_route_add_ipv6_parsed(void *parsed_result, __rte_unused struct c
 {
 	struct cmd_ipv6_lookup_route_add_ipv6_result *res = parsed_result;
 	struct route_ipv6_config config;
-	int rc = -EINVAL, i;
+	int rc = -EINVAL;
 
-	for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++)
-		config.ip[i] = res->ip.addr.ipv6.s6_addr[i];
-
-	for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++)
-		config.mask[i] = res->mask.addr.ipv6.s6_addr[i];
-
-	for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++)
-		config.gateway[i] = res->via_ip.addr.ipv6.s6_addr[i];
+	rte_memcpy(&config.ip, &res->ip.addr.ipv6, sizeof(config.ip));
+	rte_memcpy(&config.mask, &res->mask.addr.ipv6, sizeof(config.mask));
+	rte_memcpy(&config.gateway, &res->via_ip.addr.ipv6, sizeof(config.gateway));
 
 	rc = route_ip6_add(&config);
 	if (rc)
diff --git a/app/graph/meson.build b/app/graph/meson.build
index 6dc54d5ee63f..344e4a418fc0 100644
--- a/app/graph/meson.build
+++ b/app/graph/meson.build
@@ -9,7 +9,7 @@ if not build
     subdir_done()
 endif
 
-deps += ['graph', 'eal', 'lpm', 'ethdev', 'node', 'cmdline']
+deps += ['graph', 'eal', 'lpm', 'ethdev', 'node', 'cmdline', 'net']
 sources = files(
         'cli.c',
         'conn.c',
diff --git a/app/graph/neigh.c b/app/graph/neigh.c
index 79fd542c8948..0b35f4d6c294 100644
--- a/app/graph/neigh.c
+++ b/app/graph/neigh.c
@@ -62,12 +62,12 @@ find_neigh4_entry(uint32_t ip, uint64_t mac)
 }
 
 static struct neigh_ipv6_config *
-find_neigh6_entry(uint8_t *ip, uint64_t mac)
+find_neigh6_entry(struct rte_ipv6_addr *ip, uint64_t mac)
 {
 	struct neigh_ipv6_config *v6_config;
 
 	TAILQ_FOREACH(v6_config, &neigh6, next) {
-		if (!(memcmp(v6_config->ip, ip, 16)) && (v6_config->mac == mac))
+		if (rte_ipv6_addr_eq(&v6_config->ip, ip) && v6_config->mac == mac)
 			return v6_config;
 	}
 	return NULL;
@@ -82,7 +82,7 @@ ip6_rewrite_node_add(struct neigh_ipv6_config *v6_config)
 	int16_t portid = 0;
 	int rc;
 
-	portid = ethdev_portid_by_ip6(v6_config->ip, NULL);
+	portid = ethdev_portid_by_ip6(&v6_config->ip, NULL);
 	if (portid < 0) {
 		printf("Invalid portid found to add neigh\n");
 		return -EINVAL;
@@ -170,11 +170,10 @@ neigh_ip4_add(uint32_t ip, uint64_t mac)
 }
 
 static int
-neigh_ip6_add(uint8_t *ip, uint64_t mac)
+neigh_ip6_add(struct rte_ipv6_addr *ip, uint64_t mac)
 {
 	struct neigh_ipv6_config *v6_config;
 	int rc = -EINVAL;
-	int j;
 
 	v6_config = find_neigh6_entry(ip, mac);
 
@@ -184,9 +183,7 @@ neigh_ip6_add(uint8_t *ip, uint64_t mac)
 			return -ENOMEM;
 	}
 
-	for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++)
-		v6_config->ip[j] = ip[j];
-
+	rte_ipv6_addr_cpy(&v6_config->ip, ip);
 	v6_config->mac = mac;
 	v6_config->is_used = true;
 
@@ -261,19 +258,18 @@ cmd_neigh_add_ipv6_parsed(void *parsed_result, __rte_unused struct cmdline *cl,
 			  void *data __rte_unused)
 {
 	struct cmd_neigh_add_ipv6_result *res = parsed_result;
-	uint8_t ip[ETHDEV_IPV6_ADDR_LEN];
-	int rc = -EINVAL, i;
+	struct rte_ipv6_addr ip;
+	int rc = -EINVAL;
 	uint64_t mac;
 
-	for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++)
-		ip[i] = res->ip.addr.ipv6.s6_addr[i];
+	rte_memcpy(&ip, &res->ip.addr.ipv6, sizeof(ip));
 
 	if (parser_mac_read(&mac, res->mac)) {
 		printf(MSG_ARG_INVALID, "mac");
 		return;
 	}
 
-	rc = neigh_ip6_add(ip, mac);
+	rc = neigh_ip6_add(&ip, mac);
 	if (rc < 0)
 		printf(MSG_CMD_FAIL, res->neigh);
 }
diff --git a/app/graph/neigh_priv.h b/app/graph/neigh_priv.h
index 1a7106c309bc..b2a7607e01bb 100644
--- a/app/graph/neigh_priv.h
+++ b/app/graph/neigh_priv.h
@@ -5,6 +5,8 @@
 #ifndef APP_GRAPH_NEIGH_PRIV_H
 #define APP_GRAPH_NEIGH_PRIV_H
 
+#include <rte_ip6.h>
+
 #define MAX_NEIGH_ENTRIES 32
 
 struct neigh_ipv4_config {
@@ -18,7 +20,7 @@ TAILQ_HEAD(neigh4_head, neigh_ipv4_config);
 
 struct neigh_ipv6_config {
 	TAILQ_ENTRY(neigh_ipv6_config) next;
-	uint8_t ip[16];
+	struct rte_ipv6_addr ip;
 	uint64_t mac;
 	bool is_used;
 };
diff --git a/app/graph/route.h b/app/graph/route.h
index 23a7951d2dad..455aab8634d4 100644
--- a/app/graph/route.h
+++ b/app/graph/route.h
@@ -5,6 +5,8 @@
 #ifndef APP_GRAPH_ROUTE_H
 #define APP_GRAPH_ROUTE_H
 
+#include <rte_ip6.h>
+
 #define MAX_ROUTE_ENTRIES 32
 
 struct route_ipv4_config {
@@ -19,9 +21,9 @@ TAILQ_HEAD(ip4_route, route_ipv4_config);
 
 struct route_ipv6_config {
 	TAILQ_ENTRY(route_ipv6_config) next;
-	uint8_t ip[16];
-	uint8_t mask[16];
-	uint8_t gateway[16];
+	struct rte_ipv6_addr ip;
+	struct rte_ipv6_addr mask;
+	struct rte_ipv6_addr gateway;
 	bool is_used;
 };
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index a13dc011380d..c2067a05f3ef 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -151,7 +151,7 @@ struct ipv4_l3fwd_lpm_route {
 };
 
 struct ipv6_l3fwd_lpm_route {
-	uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE];
+	struct rte_ipv6_addr ip;
 	uint8_t depth;
 	uint8_t if_out;
 };
@@ -171,22 +171,14 @@ static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	(sizeof(ipv6_l3fwd_lpm_route_array) /                                  \
 	 sizeof(ipv6_l3fwd_lpm_route_array[0]))
 static struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
-	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00}, 48, 0},
-	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x01}, 48, 1},
-	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x02}, 48, 2},
-	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x03}, 48, 3},
-	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x04}, 48, 4},
-	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x05}, 48, 5},
-	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x06}, 48, 6},
-	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x02}, 48, 7},
+	{{.a = "\x20\x01\xdb\x08\x12\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, 48, 0},
+	{{.a = "\x20\x01\xdb\x08\x12\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"}, 48, 1},
+	{{.a = "\x20\x01\xdb\x08\x12\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"}, 48, 2},
+	{{.a = "\x20\x01\xdb\x08\x12\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"}, 48, 3},
+	{{.a = "\x20\x01\xdb\x08\x12\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"}, 48, 4},
+	{{.a = "\x20\x01\xdb\x08\x12\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05"}, 48, 5},
+	{{.a = "\x20\x01\xdb\x08\x12\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06"}, 48, 6},
+	{{.a = "\x20\x01\xdb\x08\x12\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"}, 48, 7},
 };
 
 static int
@@ -1371,14 +1363,14 @@ main(int argc, char **argv)
 
 		dst_port = ipv6_l3fwd_lpm_route_array[i].if_out;
 
-		memcpy(in6.s6_addr, ipv6_l3fwd_lpm_route_array[i].ip, RTE_LPM6_IPV6_ADDR_SIZE);
+		memcpy(in6.s6_addr, &ipv6_l3fwd_lpm_route_array[i].ip, RTE_IPV6_ADDR_SIZE);
 		snprintf(route_str, sizeof(route_str), "%s / %d (%d)",
 			 inet_ntop(AF_INET6, &in6, abuf, sizeof(abuf)),
 			 ipv6_l3fwd_lpm_route_array[i].depth,
 			 ipv6_l3fwd_lpm_route_array[i].if_out);
 
 		/* Use route index 'i' as next hop id */
-		ret = rte_node_ip6_route_add(ipv6_l3fwd_lpm_route_array[i].ip,
+		ret = rte_node_ip6_route_add(&ipv6_l3fwd_lpm_route_array[i].ip,
 			ipv6_l3fwd_lpm_route_array[i].depth, i,
 			RTE_NODE_IP6_LOOKUP_NEXT_REWRITE);
 
diff --git a/lib/node/ip6_lookup.c b/lib/node/ip6_lookup.c
index 1ad6e3fd18f2..0806500d86cf 100644
--- a/lib/node/ip6_lookup.c
+++ b/lib/node/ip6_lookup.c
@@ -112,28 +112,28 @@ ip6_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf0, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(&ip_batch[0], &ipv6_hdr->dst_addr, 16);
+		rte_ipv6_addr_cpy(&ip_batch[0], &ipv6_hdr->dst_addr);
 
 		/* Extract DIP of mbuf1 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf1, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf1, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(&ip_batch[1], &ipv6_hdr->dst_addr, 16);
+		rte_ipv6_addr_cpy(&ip_batch[1], &ipv6_hdr->dst_addr);
 
 		/* Extract DIP of mbuf2 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf2, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf2, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(&ip_batch[2], &ipv6_hdr->dst_addr, 16);
+		rte_ipv6_addr_cpy(&ip_batch[2], &ipv6_hdr->dst_addr);
 
 		/* Extract DIP of mbuf3 */
 		ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf3, struct rte_ipv6_hdr *,
 				sizeof(struct rte_ether_hdr));
 		/* Extract hop_limits as ipv6 hdr is in cache */
 		node_mbuf_priv1(mbuf3, dyn)->ttl = ipv6_hdr->hop_limits;
-		rte_memcpy(&ip_batch[3], &ipv6_hdr->dst_addr, 16);
+		rte_ipv6_addr_cpy(&ip_batch[3], &ipv6_hdr->dst_addr);
 
 		rte_lpm6_lookup_bulk_func(lpm6, ip_batch, next_hop, 4);
 
@@ -258,17 +258,15 @@ ip6_lookup_node_process_scalar(struct rte_graph *graph, struct rte_node *node,
 }
 
 int
-rte_node_ip6_route_add(const uint8_t *ip, uint8_t depth, uint16_t next_hop,
+rte_node_ip6_route_add(const struct rte_ipv6_addr *ip, uint8_t depth, uint16_t next_hop,
 		       enum rte_node_ip6_lookup_next next_node)
 {
 	char abuf[INET6_ADDRSTRLEN];
-	struct in6_addr in6;
 	uint8_t socket;
 	uint32_t val;
 	int ret;
 
-	memcpy(in6.s6_addr, ip, RTE_LPM6_IPV6_ADDR_SIZE);
-	inet_ntop(AF_INET6, &in6, abuf, sizeof(abuf));
+	inet_ntop(AF_INET6, ip, abuf, sizeof(abuf));
 	/* Embedded next node id into 24 bit next hop */
 	val = ((next_node << 16) | next_hop) & ((1ull << 24) - 1);
 	node_dbg("ip6_lookup", "LPM: Adding route %s / %d nh (0x%x)", abuf,
@@ -278,8 +276,7 @@ rte_node_ip6_route_add(const uint8_t *ip, uint8_t depth, uint16_t next_hop,
 		if (!ip6_lookup_nm.lpm_tbl[socket])
 			continue;
 
-		ret = rte_lpm6_add(ip6_lookup_nm.lpm_tbl[socket],
-				   (const struct rte_ipv6_addr *)ip, depth, val);
+		ret = rte_lpm6_add(ip6_lookup_nm.lpm_tbl[socket], ip, depth, val);
 		if (ret < 0) {
 			node_err("ip6_lookup",
 				 "Unable to add entry %s / %d nh (%x) to LPM "
diff --git a/lib/node/rte_node_ip6_api.h b/lib/node/rte_node_ip6_api.h
index a538dc2ea701..dc8c86184afe 100644
--- a/lib/node/rte_node_ip6_api.h
+++ b/lib/node/rte_node_ip6_api.h
@@ -21,6 +21,7 @@ extern "C" {
 
 #include <rte_common.h>
 #include <rte_compat.h>
+#include <rte_ip6.h>
 
 /**
  * IP6 lookup next nodes.
@@ -48,7 +49,7 @@ enum rte_node_ip6_lookup_next {
  *   0 on success, negative otherwise.
  */
 __rte_experimental
-int rte_node_ip6_route_add(const uint8_t *ip, uint8_t depth, uint16_t next_hop,
+int rte_node_ip6_route_add(const struct rte_ipv6_addr *ip, uint8_t depth, uint16_t next_hop,
 			   enum rte_node_ip6_lookup_next next_node);
 
 /**
-- 
2.46.0


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

* [PATCH dpdk v1 09/15] pipeline: use ipv6 addr struct
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (7 preceding siblings ...)
  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 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 10/15] ipsec: " Robin Jarry
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Cristian Dumitrescu

Update rte_table_action_ipv6_header and rte_table_action_nat_params to
use the recently added IPv6 address structure instead of uint8_t[16]
arrays.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 examples/ip_pipeline/cli.c      | 12 +++++------
 lib/pipeline/rte_table_action.c | 36 +++++++++++++--------------------
 lib/pipeline/rte_table_action.h |  7 ++++---
 3 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c
index e8269ea90c11..66fdeac8f501 100644
--- a/examples/ip_pipeline/cli.c
+++ b/examples/ip_pipeline/cli.c
@@ -3540,8 +3540,8 @@ parse_table_action_encap(char **tokens,
 				parser_read_uint8(&hop_limit, tokens[5]))
 				return 0;
 
-			memcpy(a->encap.vxlan.ipv6.sa, sa.s6_addr, 16);
-			memcpy(a->encap.vxlan.ipv6.da, da.s6_addr, 16);
+			memcpy(&a->encap.vxlan.ipv6.sa, sa.s6_addr, 16);
+			memcpy(&a->encap.vxlan.ipv6.da, da.s6_addr, 16);
 			a->encap.vxlan.ipv6.flow_label = flow_label;
 			a->encap.vxlan.ipv6.dscp = dscp;
 			a->encap.vxlan.ipv6.hop_limit = hop_limit;
@@ -3615,7 +3615,7 @@ parse_table_action_nat(char **tokens,
 			return 0;
 
 		a->nat.ip_version = 0;
-		memcpy(a->nat.addr.ipv6, addr.s6_addr, 16);
+		memcpy(&a->nat.addr.ipv6, addr.s6_addr, 16);
 		a->nat.port = port;
 		a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
 		return 4;
@@ -4956,9 +4956,9 @@ table_rule_show(const char *pipeline_name,
 						(uint32_t)a->encap.vxlan.ipv4.ttl);
 				} else {
 					fprintf(f, " ipv6 ");
-					ipv6_addr_show(f, a->encap.vxlan.ipv6.sa);
+					ipv6_addr_show(f, a->encap.vxlan.ipv6.sa.a);
 					fprintf(f, " ");
-					ipv6_addr_show(f, a->encap.vxlan.ipv6.da);
+					ipv6_addr_show(f, a->encap.vxlan.ipv6.da.a);
 					fprintf(f, " %u %u %u ",
 						a->encap.vxlan.ipv6.flow_label,
 						(uint32_t)a->encap.vxlan.ipv6.dscp,
@@ -4980,7 +4980,7 @@ table_rule_show(const char *pipeline_name,
 			if (a->nat.ip_version)
 				ipv4_addr_show(f, a->nat.addr.ipv4);
 			else
-				ipv6_addr_show(f, a->nat.addr.ipv6);
+				ipv6_addr_show(f, a->nat.addr.ipv6.a);
 			fprintf(f, " %u ", (uint32_t)(a->nat.port));
 		}
 
diff --git a/lib/pipeline/rte_table_action.c b/lib/pipeline/rte_table_action.c
index a04d5121e1f0..8479f984e4ea 100644
--- a/lib/pipeline/rte_table_action.c
+++ b/lib/pipeline/rte_table_action.c
@@ -872,12 +872,8 @@ encap_vxlan_apply(void *data,
 			d->ipv6.payload_len = 0; /* not pre-computed */
 			d->ipv6.proto = IP_PROTO_UDP;
 			d->ipv6.hop_limits = p->vxlan.ipv6.hop_limit;
-			memcpy(&d->ipv6.src_addr,
-				p->vxlan.ipv6.sa,
-				sizeof(p->vxlan.ipv6.sa));
-			memcpy(&d->ipv6.dst_addr,
-				p->vxlan.ipv6.da,
-				sizeof(p->vxlan.ipv6.da));
+			rte_ipv6_addr_cpy(&d->ipv6.src_addr, &p->vxlan.ipv6.sa);
+			rte_ipv6_addr_cpy(&d->ipv6.dst_addr, &p->vxlan.ipv6.da);
 
 			/* UDP */
 			d->udp.src_port = rte_htons(p->vxlan.udp.sp);
@@ -907,12 +903,8 @@ encap_vxlan_apply(void *data,
 			d->ipv6.payload_len = 0; /* not pre-computed */
 			d->ipv6.proto = IP_PROTO_UDP;
 			d->ipv6.hop_limits = p->vxlan.ipv6.hop_limit;
-			memcpy(&d->ipv6.src_addr,
-				p->vxlan.ipv6.sa,
-				sizeof(p->vxlan.ipv6.sa));
-			memcpy(&d->ipv6.dst_addr,
-				p->vxlan.ipv6.da,
-				sizeof(p->vxlan.ipv6.da));
+			rte_ipv6_addr_cpy(&d->ipv6.src_addr, &p->vxlan.ipv6.sa);
+			rte_ipv6_addr_cpy(&d->ipv6.dst_addr, &p->vxlan.ipv6.da);
 
 			/* UDP */
 			d->udp.src_port = rte_htons(p->vxlan.udp.sp);
@@ -1211,7 +1203,7 @@ struct nat_ipv4_data {
 } __rte_packed;
 
 struct nat_ipv6_data {
-	uint8_t addr[16];
+	struct rte_ipv6_addr addr;
 	uint16_t port;
 } __rte_packed;
 
@@ -1258,7 +1250,7 @@ nat_apply(void *data,
 	} else {
 		struct nat_ipv6_data *d = data;
 
-		memcpy(d->addr, p->addr.ipv6, sizeof(d->addr));
+		rte_ipv6_addr_cpy(&d->addr, &p->addr.ipv6);
 		d->port = rte_htons(p->port);
 	}
 
@@ -1438,11 +1430,11 @@ pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
 
 			tcp_cksum = nat_ipv6_tcp_udp_checksum_update(tcp->cksum,
 				(uint16_t *)&ip->src_addr,
-				(uint16_t *)data->addr,
+				(uint16_t *)&data->addr,
 				tcp->src_port,
 				data->port);
 
-			rte_memcpy(&ip->src_addr, data->addr, 16);
+			rte_ipv6_addr_cpy(&ip->src_addr, &data->addr);
 			tcp->src_port = data->port;
 			tcp->cksum = tcp_cksum;
 		} else {
@@ -1451,11 +1443,11 @@ pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
 
 			udp_cksum = nat_ipv6_tcp_udp_checksum_update(udp->dgram_cksum,
 				(uint16_t *)&ip->src_addr,
-				(uint16_t *)data->addr,
+				(uint16_t *)&data->addr,
 				udp->src_port,
 				data->port);
 
-			rte_memcpy(&ip->src_addr, data->addr, 16);
+			rte_ipv6_addr_cpy(&ip->src_addr, &data->addr);
 			udp->src_port = data->port;
 			udp->dgram_cksum = udp_cksum;
 		}
@@ -1466,11 +1458,11 @@ pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
 
 			tcp_cksum = nat_ipv6_tcp_udp_checksum_update(tcp->cksum,
 				(uint16_t *)&ip->dst_addr,
-				(uint16_t *)data->addr,
+				(uint16_t *)&data->addr,
 				tcp->dst_port,
 				data->port);
 
-			rte_memcpy(&ip->dst_addr, data->addr, 16);
+			rte_ipv6_addr_cpy(&ip->dst_addr, &data->addr);
 			tcp->dst_port = data->port;
 			tcp->cksum = tcp_cksum;
 		} else {
@@ -1479,11 +1471,11 @@ pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
 
 			udp_cksum = nat_ipv6_tcp_udp_checksum_update(udp->dgram_cksum,
 				(uint16_t *)&ip->dst_addr.a,
-				(uint16_t *)data->addr,
+				(uint16_t *)&data->addr,
 				udp->dst_port,
 				data->port);
 
-			rte_memcpy(&ip->dst_addr, data->addr, 16);
+			rte_ipv6_addr_cpy(&ip->dst_addr, &data->addr);
 			udp->dst_port = data->port;
 			udp->dgram_cksum = udp_cksum;
 		}
diff --git a/lib/pipeline/rte_table_action.h b/lib/pipeline/rte_table_action.h
index 5dffbeb70031..b119ac03dc6e 100644
--- a/lib/pipeline/rte_table_action.h
+++ b/lib/pipeline/rte_table_action.h
@@ -60,6 +60,7 @@ extern "C" {
 
 #include <rte_compat.h>
 #include <rte_ether.h>
+#include <rte_ip6.h>
 #include <rte_meter.h>
 #include <rte_table_hash.h>
 
@@ -419,8 +420,8 @@ struct rte_table_action_ipv4_header {
 
 /** Pre-computed IPv6 header fields for encapsulation action. */
 struct rte_table_action_ipv6_header {
-	uint8_t sa[16]; /**< Source address. */
-	uint8_t da[16]; /**< Destination address. */
+	struct rte_ipv6_addr sa; /**< Source address. */
+	struct rte_ipv6_addr da; /**< Destination address. */
 	uint32_t flow_label; /**< Flow label. */
 	uint8_t dscp; /**< DiffServ Code Point (DSCP). */
 	uint8_t hop_limit; /**< Hop Limit (HL). */
@@ -597,7 +598,7 @@ struct rte_table_action_nat_params {
 		uint32_t ipv4;
 
 		/** IPv6 address; only valid when *ip_version* is set to 0. */
-		uint8_t ipv6[16];
+		struct rte_ipv6_addr ipv6;
 	} addr;
 
 	/** Port. */
-- 
2.46.0


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

* [PATCH dpdk v1 10/15] ipsec: use ipv6 addr struct
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (8 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 09/15] pipeline: use ipv6 addr struct Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 11/15] thash: " Robin Jarry
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Konstantin Ananyev, Vladimir Medvedkin, Radu Nicolau, Akhil Goyal

Update rte_ipsec_sadv6_key to use the recently introduced IPv6 address
structure instead of ad-hoc uint8_t[16] arrays.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test-sad/main.c        | 24 ++++++++++-----------
 app/test/test_ipsec_sad.c  | 44 +++++++++++++++++++-------------------
 examples/ipsec-secgw/sad.h | 10 +++++----
 lib/ipsec/rte_ipsec_sad.h  |  7 +++---
 4 files changed, 44 insertions(+), 41 deletions(-)

diff --git a/app/test-sad/main.c b/app/test-sad/main.c
index addfc0714521..7253f6488dce 100644
--- a/app/test-sad/main.c
+++ b/app/test-sad/main.c
@@ -248,8 +248,8 @@ get_random_rules(struct rule *tbl, uint32_t nb_rules, int rule_tbl)
 						(uint64_t)(edge + step));
 			if (config.ipv6) {
 				for (j = 0; j < 16; j++) {
-					tbl[i].tuple.v6.dip[j] = rte_rand();
-					tbl[i].tuple.v6.sip[j] = rte_rand();
+					tbl[i].tuple.v6.dip.a[j] = rte_rand();
+					tbl[i].tuple.v6.sip.a[j] = rte_rand();
 				}
 			} else {
 				tbl[i].tuple.v4.dip = rte_rand();
@@ -274,9 +274,9 @@ get_random_rules(struct rule *tbl, uint32_t nb_rules, int rule_tbl)
 					(uint64_t)(edge + step));
 				if (config.ipv6) {
 					for (j = 0; j < 16; j++) {
-						tbl[i].tuple.v6.dip[j] =
+						tbl[i].tuple.v6.dip.a[j] =
 								rte_rand();
-						tbl[i].tuple.v6.sip[j] =
+						tbl[i].tuple.v6.sip.a[j] =
 								rte_rand();
 					}
 				} else {
@@ -289,11 +289,11 @@ get_random_rules(struct rule *tbl, uint32_t nb_rules, int rule_tbl)
 					config.nb_rules].tuple.v4.spi;
 				if (config.ipv6) {
 					int r_idx = i % config.nb_rules;
-					memcpy(tbl[i].tuple.v6.dip,
-						rules_tbl[r_idx].tuple.v6.dip,
+					memcpy(&tbl[i].tuple.v6.dip,
+						&rules_tbl[r_idx].tuple.v6.dip,
 						sizeof(tbl[i].tuple.v6.dip));
-					memcpy(tbl[i].tuple.v6.sip,
-						rules_tbl[r_idx].tuple.v6.sip,
+					memcpy(&tbl[i].tuple.v6.sip,
+						&rules_tbl[r_idx].tuple.v6.sip,
 						sizeof(tbl[i].tuple.v6.sip));
 				} else {
 					tbl[i].tuple.v4.dip = rules_tbl[i %
@@ -472,8 +472,8 @@ print_result(const union rte_ipsec_sad_key *key, void *res)
 	v4 = &key->v4;
 	v6 = &key->v6;
 	spi = (config.ipv6 == 0) ? v4->spi : v6->spi;
-	dip = (config.ipv6 == 0) ? &v4->dip : (const void *)v6->dip;
-	sip = (config.ipv6 == 0) ? &v4->sip : (const void *)v6->sip;
+	dip = (config.ipv6 == 0) ? &v4->dip : (const void *)&v6->dip;
+	sip = (config.ipv6 == 0) ? &v4->sip : (const void *)&v6->sip;
 
 	if (res == NULL) {
 		printf("TUPLE: ");
@@ -500,8 +500,8 @@ print_result(const union rte_ipsec_sad_key *key, void *res)
 	v4 = &rule->tuple.v4;
 	v6 = &rule->tuple.v6;
 	spi = (config.ipv6 == 0) ? v4->spi : v6->spi;
-	dip = (config.ipv6 == 0) ? &v4->dip : (const void *)v6->dip;
-	sip = (config.ipv6 == 0) ? &v4->sip : (const void *)v6->sip;
+	dip = (config.ipv6 == 0) ? &v4->dip : (const void *)&v6->dip;
+	sip = (config.ipv6 == 0) ? &v4->sip : (const void *)&v6->sip;
 	printf("\n\tpoints to RULE ID %zu ",
 		RTE_PTR_DIFF(res, rules_tbl)/sizeof(struct rule));
 	print_tuple(af, spi, dip, sip);
diff --git a/app/test/test_ipsec_sad.c b/app/test/test_ipsec_sad.c
index 7534f16f89d0..79ea8ee915dd 100644
--- a/app/test/test_ipsec_sad.c
+++ b/app/test/test_ipsec_sad.c
@@ -212,7 +212,7 @@ test_add_invalid(void)
 {
 	int status;
 	struct rte_ipsec_sadv4_key tuple_v4 = {10, 20, 30};
-	struct rte_ipsec_sadv6_key tuple_v6 = {10, {20, }, {30, } };
+	struct rte_ipsec_sadv6_key tuple_v6 = {10, {.a = {20, }}, {.a = {30, }} };
 
 	status = __test_add_invalid(0, (union rte_ipsec_sad_key *)&tuple_v4);
 	if (status != TEST_SUCCESS)
@@ -271,8 +271,8 @@ test_delete_invalid(void)
 {
 	int status;
 	struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
-	struct rte_ipsec_sadv6_key tuple_v6 = {SPI, {0xbe, 0xef, },
-			{0xf0, 0x0d, } };
+	struct rte_ipsec_sadv6_key tuple_v6 = {
+		SPI, {.a = {0xbe, 0xef, }}, {.a = {0xf0, 0x0d, }} };
 
 	status = __test_delete_invalid(0, (union rte_ipsec_sad_key *)&tuple_v4);
 	if (status != TEST_SUCCESS)
@@ -329,7 +329,7 @@ test_lookup_invalid(void)
 {
 	int status;
 	struct rte_ipsec_sadv4_key tuple_v4 = {10, 20, 30};
-	struct rte_ipsec_sadv6_key tuple_v6 = {10, {20, }, {30, } };
+	struct rte_ipsec_sadv6_key tuple_v6 = {10, {.a = {20, }}, {.a = {30, }} };
 
 	status = __test_lookup_invalid(0,
 			(union rte_ipsec_sad_key *)&tuple_v4);
@@ -405,10 +405,10 @@ test_lookup_basic(void)
 	int status;
 	struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
 	struct rte_ipsec_sadv4_key tuple_v4_1 = {SPI, BAD, BAD};
-	struct rte_ipsec_sadv6_key tuple_v6 = {SPI, {0xbe, 0xef, },
-			{0xf0, 0x0d, } };
-	struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI, {0x0b, 0xad, },
-			{0x0b, 0xad, } };
+	struct rte_ipsec_sadv6_key tuple_v6 = {
+		SPI, {.a = {0xbe, 0xef, }}, {.a = {0xf0, 0x0d, }} };
+	struct rte_ipsec_sadv6_key tuple_v6_1 = {
+		SPI, {.a = {0x0b, 0xad, }}, {.a = {0x0b, 0xad, }} };
 
 	status = __test_lookup_basic(0, (union rte_ipsec_sad_key *)&tuple_v4,
 			(union rte_ipsec_sad_key *)&tuple_v4_1);
@@ -654,14 +654,14 @@ test_lookup_adv(void)
 	struct rte_ipsec_sadv4_key tuple_v4_3 = {BAD, DIP, SIP};
 
 	/* key to install*/
-	struct rte_ipsec_sadv6_key tuple_v6 = {SPI, {0xbe, 0xef, },
-			{0xf0, 0x0d, } };
-	struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI, {0xbe, 0xef, },
-			{0x0b, 0xad, } };
-	struct rte_ipsec_sadv6_key tuple_v6_2 = {SPI, {0x0b, 0xad, },
-			{0xf0, 0x0d, } };
-	struct rte_ipsec_sadv6_key tuple_v6_3 = {BAD, {0xbe, 0xef, },
-			{0xf0, 0x0d, } };
+	struct rte_ipsec_sadv6_key tuple_v6 = {
+		SPI, {.a = {0xbe, 0xef, }}, {.a = {0xf0, 0x0d, }} };
+	struct rte_ipsec_sadv6_key tuple_v6_1 = {
+		SPI, {.a = {0xbe, 0xef, }}, {.a = {0x0b, 0xad, }} };
+	struct rte_ipsec_sadv6_key tuple_v6_2 = {
+		SPI, {.a = {0x0b, 0xad, }}, {.a = {0xf0, 0x0d, }} };
+	struct rte_ipsec_sadv6_key tuple_v6_3 = {
+		BAD, {.a = {0xbe, 0xef, }}, {.a = {0xf0, 0x0d, }} };
 
 	const union rte_ipsec_sad_key *key_arr[] = {
 				(union rte_ipsec_sad_key *)&tuple_v4,
@@ -852,12 +852,12 @@ test_lookup_order(void)
 	struct rte_ipsec_sadv4_key tuple_v4_1 = {SPI, DIP, BAD};
 	struct rte_ipsec_sadv4_key tuple_v4_2 = {SPI, BAD, SIP};
 	/* key to install*/
-	struct rte_ipsec_sadv6_key tuple_v6 = {SPI, {0xbe, 0xef, },
-			{0xf0, 0x0d, } };
-	struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI, {0xbe, 0xef, },
-			{0x0b, 0xad, } };
-	struct rte_ipsec_sadv6_key tuple_v6_2 = {SPI, {0x0b, 0xad, },
-			{0xf0, 0x0d, } };
+	struct rte_ipsec_sadv6_key tuple_v6 = {
+		SPI, {.a = {0xbe, 0xef, }}, {.a = {0xf0, 0x0d, }} };
+	struct rte_ipsec_sadv6_key tuple_v6_1 = {
+		SPI, {.a = {0xbe, 0xef, }}, {.a = {0x0b, 0xad, }} };
+	struct rte_ipsec_sadv6_key tuple_v6_2 = {
+		SPI, {.a = {0x0b, 0xad, }}, {.a = {0xf0, 0x0d, }} };
 
 	status = __test_lookup_order(0, (union rte_ipsec_sad_key *)&tuple_v4,
 			(union rte_ipsec_sad_key *)&tuple_v4_1,
diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h
index fdb1d2ef1790..4108abb9e698 100644
--- a/examples/ipsec-secgw/sad.h
+++ b/examples/ipsec-secgw/sad.h
@@ -9,6 +9,8 @@
 #include <rte_ip6.h>
 #include <rte_ipsec_sad.h>
 
+#include "ipsec.h"
+
 #define SA_CACHE_SZ	128
 #define SPI2IDX(spi, mask)	((spi) & (mask))
 
@@ -39,8 +41,8 @@ cmp_sa_key(struct ipsec_sa *sa, int is_v4, struct rte_ipv4_hdr *ipv4,
 			(sa->dst.ip.ip4 == ipv4->dst_addr)) ||
 			/* IPv6 check */
 			(!is_v4 && (sa_type == IP6_TUNNEL) &&
-			(!memcmp(sa->src.ip.ip6.ip6, &ipv6->src_addr, 16)) &&
-			(!memcmp(sa->dst.ip.ip6.ip6, &ipv6->dst_addr, 16))))
+			(!memcmp(&sa->src.ip.ip6.ip6, &ipv6->src_addr, 16)) &&
+			(!memcmp(&sa->dst.ip.ip6.ip6, &ipv6->dst_addr, 16))))
 		return 1;
 
 	return 0;
@@ -130,9 +132,9 @@ sad_lookup(struct ipsec_sad *sad, struct rte_mbuf *pkts[],
 				}
 			}
 			v6[nb_v6].spi = esp->spi;
-			memcpy(v6[nb_v6].dip, &ipv6->dst_addr,
+			memcpy(&v6[nb_v6].dip, &ipv6->dst_addr,
 					sizeof(ipv6->dst_addr));
-			memcpy(v6[nb_v6].sip, &ipv6->src_addr,
+			memcpy(&v6[nb_v6].sip, &ipv6->src_addr,
 					sizeof(ipv6->src_addr));
 			keys_v6[nb_v6] = (const union rte_ipsec_sad_key *)
 						&v6[nb_v6];
diff --git a/lib/ipsec/rte_ipsec_sad.h b/lib/ipsec/rte_ipsec_sad.h
index 0adf89d9310c..035ae4f3b3eb 100644
--- a/lib/ipsec/rte_ipsec_sad.h
+++ b/lib/ipsec/rte_ipsec_sad.h
@@ -6,8 +6,9 @@
 #ifndef _RTE_IPSEC_SAD_H_
 #define _RTE_IPSEC_SAD_H_
 
-#include <stdint.h>
+#include <rte_ip6.h>
 
+#include <stdint.h>
 
 /**
  * @file rte_ipsec_sad.h
@@ -38,8 +39,8 @@ struct rte_ipsec_sadv4_key {
 
 struct rte_ipsec_sadv6_key {
 	uint32_t spi;
-	uint8_t dip[16];
-	uint8_t sip[16];
+	struct rte_ipv6_addr dip;
+	struct rte_ipv6_addr sip;
 };
 
 union rte_ipsec_sad_key {
-- 
2.46.0


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

* [PATCH dpdk v1 11/15] thash: use ipv6 addr struct
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (9 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 10/15] ipsec: " Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 12/15] gro: " Robin Jarry
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Yipeng Wang, Sameh Gobriel, Bruce Richardson, Vladimir Medvedkin

Update rte_ipv6_tuple to use the recently added IPv6 address structure
instead of uint8_t[16] arrays.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test/test_thash.c | 46 ++++++++++++++++---------------------------
 lib/hash/rte_thash.h  | 20 +++++++++----------
 2 files changed, 27 insertions(+), 39 deletions(-)

diff --git a/app/test/test_thash.c b/app/test/test_thash.c
index 952da6a52954..262f84433461 100644
--- a/app/test/test_thash.c
+++ b/app/test/test_thash.c
@@ -25,8 +25,8 @@ struct test_thash_v4 {
 };
 
 struct test_thash_v6 {
-	uint8_t		dst_ip[16];
-	uint8_t		src_ip[16];
+	struct rte_ipv6_addr dst_ip;
+	struct rte_ipv6_addr src_ip;
 	uint16_t	dst_port;
 	uint16_t	src_port;
 	uint32_t	hash_l3;
@@ -49,25 +49,19 @@ struct test_thash_v4 v4_tbl[] = {
 
 struct test_thash_v6 v6_tbl[] = {
 /*3ffe:2501:200:3::1*/
-{{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x00, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
+{{.a = "\x3f\xfe\x25\x01\x02\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01"},
 /*3ffe:2501:200:1fff::7*/
-{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x1f, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,},
+{.a = "\x3f\xfe\x25\x01\x02\x00\x1f\xff\x00\x00\x00\x00\x00\x00\x00\x07"},
 1766, 2794, 0x2cc18cd5, 0x40207d3d},
 /*ff02::1*/
-{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
+{{.a = "\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"},
 /*3ffe:501:8::260:97ff:fe40:efab*/
-{0x3f, 0xfe, 0x05, 0x01, 0x00, 0x08, 0x00, 0x00,
-0x02, 0x60, 0x97, 0xff, 0xfe, 0x40, 0xef, 0xab,},
+{.a = "\x3f\xfe\x05\x01\x00\x08\x00\x00\x02\x60\x97\xff\xfe\x40\xef\xab"},
 4739, 14230, 0x0f0c461c, 0xdde51bbf},
 /*fe80::200:f8ff:fe21:67cf*/
-{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
+{{.a = "\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x00\xf8\xff\xfe\x21\x67\xcf"},
 /*3ffe:1900:4545:3:200:f8ff:fe21:67cf*/
-{0x3f, 0xfe, 0x19, 0x00, 0x45, 0x45, 0x00, 0x03,
-0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
+{.a = "\x3f\xfe\x19\x00\x45\x45\x00\x03\x02\x00\xf8\xff\xfe\x21\x67\xcf"},
 38024, 44251, 0x4b61e985, 0x02d1feef},
 };
 
@@ -110,7 +104,7 @@ static const uint8_t big_rss_key[] = {
 static int
 test_toeplitz_hash_calc(void)
 {
-	uint32_t i, j;
+	uint32_t i;
 	union rte_thash_tuple tuple;
 	uint32_t rss_l3, rss_l3l4;
 	uint8_t rss_key_be[RTE_DIM(default_rss_key)];
@@ -145,10 +139,8 @@ test_toeplitz_hash_calc(void)
 	}
 	for (i = 0; i < RTE_DIM(v6_tbl); i++) {
 		/*Fill ipv6 hdr*/
-		for (j = 0; j < RTE_DIM(ipv6_hdr.src_addr.a); j++)
-			ipv6_hdr.src_addr.a[j] = v6_tbl[i].src_ip[j];
-		for (j = 0; j < RTE_DIM(ipv6_hdr.dst_addr.a); j++)
-			ipv6_hdr.dst_addr.a[j] = v6_tbl[i].dst_ip[j];
+		rte_ipv6_addr_cpy(&ipv6_hdr.src_addr, &v6_tbl[i].src_ip);
+		rte_ipv6_addr_cpy(&ipv6_hdr.dst_addr, &v6_tbl[i].dst_ip);
 		/*Load and convert ipv6 address into tuple*/
 		rte_thash_load_v6_addrs(&ipv6_hdr, &tuple);
 		tuple.v6.sport = v6_tbl[i].src_port;
@@ -176,7 +168,7 @@ test_toeplitz_hash_calc(void)
 static int
 test_toeplitz_hash_gfni(void)
 {
-	uint32_t i, j;
+	uint32_t i;
 	union rte_thash_tuple tuple;
 	uint32_t rss_l3, rss_l3l4;
 	uint64_t rss_key_matrixes[RTE_DIM(default_rss_key)];
@@ -204,10 +196,8 @@ test_toeplitz_hash_gfni(void)
 	}
 
 	for (i = 0; i < RTE_DIM(v6_tbl); i++) {
-		for (j = 0; j < RTE_DIM(tuple.v6.src_addr); j++)
-			tuple.v6.src_addr[j] = v6_tbl[i].src_ip[j];
-		for (j = 0; j < RTE_DIM(tuple.v6.dst_addr); j++)
-			tuple.v6.dst_addr[j] = v6_tbl[i].dst_ip[j];
+		rte_ipv6_addr_cpy(&tuple.v6.src_addr, &v6_tbl[i].src_ip);
+		rte_ipv6_addr_cpy(&tuple.v6.dst_addr, &v6_tbl[i].dst_ip);
 		tuple.v6.sport = rte_cpu_to_be_16(v6_tbl[i].dst_port);
 		tuple.v6.dport = rte_cpu_to_be_16(v6_tbl[i].src_port);
 		rss_l3 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
@@ -299,7 +289,7 @@ enum {
 static int
 test_toeplitz_hash_gfni_bulk(void)
 {
-	uint32_t i, j;
+	uint32_t i;
 	union rte_thash_tuple tuple[2];
 	uint8_t *tuples[2];
 	uint32_t rss[2] = { 0 };
@@ -328,10 +318,8 @@ test_toeplitz_hash_gfni_bulk(void)
 		rte_memcpy(tuples[0], &tuple[0], RTE_THASH_V4_L4_LEN * 4);
 
 		/*Load IPv6 headers and copy it into the corresponding tuple*/
-		for (j = 0; j < RTE_DIM(tuple[1].v6.src_addr); j++)
-			tuple[1].v6.src_addr[j] = v6_tbl[i].src_ip[j];
-		for (j = 0; j < RTE_DIM(tuple[1].v6.dst_addr); j++)
-			tuple[1].v6.dst_addr[j] = v6_tbl[i].dst_ip[j];
+		rte_ipv6_addr_cpy(&tuple[1].v6.src_addr, &v6_tbl[i].src_ip);
+		rte_ipv6_addr_cpy(&tuple[1].v6.dst_addr, &v6_tbl[i].dst_ip);
 		tuple[1].v6.sport = rte_cpu_to_be_16(v6_tbl[i].dst_port);
 		tuple[1].v6.dport = rte_cpu_to_be_16(v6_tbl[i].src_port);
 		rte_memcpy(tuples[1], &tuple[1], RTE_THASH_V6_L4_LEN * 4);
diff --git a/lib/hash/rte_thash.h b/lib/hash/rte_thash.h
index 9aaaacfd5fa4..ddc4e345097d 100644
--- a/lib/hash/rte_thash.h
+++ b/lib/hash/rte_thash.h
@@ -89,8 +89,8 @@ struct rte_ipv4_tuple {
  * ports/sctp_tag have to be CPU byte order
  */
 struct rte_ipv6_tuple {
-	uint8_t		src_addr[16];
-	uint8_t		dst_addr[16];
+	struct rte_ipv6_addr src_addr;
+	struct rte_ipv6_addr dst_addr;
 	union {
 		struct {
 			uint16_t dport;
@@ -141,22 +141,22 @@ rte_thash_load_v6_addrs(const struct rte_ipv6_hdr *orig,
 {
 #ifdef RTE_ARCH_X86
 	__m128i ipv6 = _mm_loadu_si128((const __m128i *)&orig->src_addr);
-	*(__m128i *)targ->v6.src_addr =
+	*(__m128i *)&targ->v6.src_addr =
 			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
 	ipv6 = _mm_loadu_si128((const __m128i *)&orig->dst_addr);
-	*(__m128i *)targ->v6.dst_addr =
+	*(__m128i *)&targ->v6.dst_addr =
 			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
 #elif defined(__ARM_NEON)
-	uint8x16_t ipv6 = vld1q_u8((uint8_t const *)&orig->src_addr);
-	vst1q_u8((uint8_t *)targ->v6.src_addr, vrev32q_u8(ipv6));
-	ipv6 = vld1q_u8((uint8_t const *)&orig->dst_addr);
-	vst1q_u8((uint8_t *)targ->v6.dst_addr, vrev32q_u8(ipv6));
+	uint8x16_t ipv6 = vld1q_u8(orig->src_addr.a);
+	vst1q_u8(targ->v6.src_addr.a, vrev32q_u8(ipv6));
+	ipv6 = vld1q_u8(orig->dst_addr.a);
+	vst1q_u8(targ->v6.dst_addr.a, vrev32q_u8(ipv6));
 #else
 	int i;
 	for (i = 0; i < 4; i++) {
-		*((uint32_t *)targ->v6.src_addr + i) =
+		*((uint32_t *)targ->v6.src_addr.a + i) =
 			rte_be_to_cpu_32(*((const uint32_t *)orig->src_addr.a + i));
-		*((uint32_t *)targ->v6.dst_addr + i) =
+		*((uint32_t *)targ->v6.dst_addr.a + i) =
 			rte_be_to_cpu_32(*((const uint32_t *)orig->dst_addr.a + i));
 	}
 #endif
-- 
2.46.0


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

* [PATCH dpdk v1 12/15] gro: use ipv6 addr struct
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (10 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 11/15] thash: " Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 13/15] rte_flow: " Robin Jarry
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Jiayu Hu

Update tcp6_flow_key to use the recently introduced IPv6 address
structure instead of uint8_t[16] arrays.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 lib/gro/gro_tcp6.c | 8 ++++----
 lib/gro/gro_tcp6.h | 6 ++++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/lib/gro/gro_tcp6.c b/lib/gro/gro_tcp6.c
index 6edfb6045cf6..0c6adbf2ecdb 100644
--- a/lib/gro/gro_tcp6.c
+++ b/lib/gro/gro_tcp6.c
@@ -99,8 +99,8 @@ insert_new_flow(struct gro_tcp6_tbl *tbl,
 	dst = &(tbl->flows[flow_idx].key);
 
 	ASSIGN_COMMON_TCP_KEY((&src->cmn_key), (&dst->cmn_key));
-	memcpy(&dst->src_addr[0], &src->src_addr[0], sizeof(dst->src_addr));
-	memcpy(&dst->dst_addr[0], &src->dst_addr[0], sizeof(dst->dst_addr));
+	rte_ipv6_addr_cpy(&dst->src_addr, &src->src_addr);
+	rte_ipv6_addr_cpy(&dst->dst_addr, &src->dst_addr);
 	dst->vtc_flow = src->vtc_flow;
 
 	tbl->flows[flow_idx].start_index = item_idx;
@@ -168,8 +168,8 @@ gro_tcp6_reassemble(struct rte_mbuf *pkt,
 
 	rte_ether_addr_copy(&(eth_hdr->src_addr), &(key.cmn_key.eth_saddr));
 	rte_ether_addr_copy(&(eth_hdr->dst_addr), &(key.cmn_key.eth_daddr));
-	memcpy(&key.src_addr[0], &ipv6_hdr->src_addr, sizeof(key.src_addr));
-	memcpy(&key.dst_addr[0], &ipv6_hdr->dst_addr, sizeof(key.dst_addr));
+	rte_ipv6_addr_cpy(&key.src_addr, &ipv6_hdr->src_addr);
+	rte_ipv6_addr_cpy(&key.dst_addr, &ipv6_hdr->dst_addr);
 	key.cmn_key.src_port = tcp_hdr->src_port;
 	key.cmn_key.dst_port = tcp_hdr->dst_port;
 	key.cmn_key.recv_ack = tcp_hdr->recv_ack;
diff --git a/lib/gro/gro_tcp6.h b/lib/gro/gro_tcp6.h
index 073122f0ec84..acf3971bb6e9 100644
--- a/lib/gro/gro_tcp6.h
+++ b/lib/gro/gro_tcp6.h
@@ -5,6 +5,8 @@
 #ifndef _GRO_TCP6_H_
 #define _GRO_TCP6_H_
 
+#include <rte_ip6.h>
+
 #include "gro_tcp.h"
 
 #define GRO_TCP6_TBL_MAX_ITEM_NUM (1024UL * 1024UL)
@@ -12,8 +14,8 @@
 /* Header fields representing a TCP/IPv6 flow */
 struct tcp6_flow_key {
 	struct cmn_tcp_key cmn_key;
-	uint8_t  src_addr[16];
-	uint8_t  dst_addr[16];
+	struct rte_ipv6_addr src_addr;
+	struct rte_ipv6_addr dst_addr;
 	rte_be32_t vtc_flow;
 };
 
-- 
2.46.0


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

* [PATCH dpdk v1 13/15] rte_flow: use ipv6 addr struct
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (11 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 12/15] gro: " Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 14/15] rib6,fib6,lpm6: remove duplicate constants Robin Jarry
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Wisam Jaddo, Potnuri Bharat Teja, Chaoyong He, Ori Kam,
	Thomas Monjalon, Ferruh Yigit, Andrew Rybchenko

Update rte_flow_tunnel, rte_flow_action_set_ipv6,
rte_flow_item_icmp6_nd_na and rte_flow_item_icmp6_nd_ns to use the
recently introduced IPv6 address structure instead of uint8_t[16]
arrays.

Update all code accordingly.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test-flow-perf/actions_gen.c         |  4 ++--
 drivers/net/cxgbe/cxgbe_flow.c           |  4 ++--
 drivers/net/nfp/flower/nfp_flower_flow.c |  2 +-
 lib/ethdev/rte_flow.h                    | 16 +++++++++-------
 4 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/app/test-flow-perf/actions_gen.c b/app/test-flow-perf/actions_gen.c
index b5336e83ff9f..54fcbacb98ce 100644
--- a/app/test-flow-perf/actions_gen.c
+++ b/app/test-flow-perf/actions_gen.c
@@ -304,7 +304,7 @@ add_set_src_ipv6(struct rte_flow_action *actions,
 
 	/* IPv6 value to set is random each time */
 	for (i = 0; i < 16; i++) {
-		set_ipv6[para.core_idx].ipv6_addr[i] = ipv6 & 0xff;
+		set_ipv6[para.core_idx].ipv6_addr.a[i] = ipv6 & 0xff;
 		ipv6 = ipv6 >> 8;
 	}
 
@@ -327,7 +327,7 @@ add_set_dst_ipv6(struct rte_flow_action *actions,
 
 	/* IPv6 value to set is random each time */
 	for (i = 0; i < 16; i++) {
-		set_ipv6[para.core_idx].ipv6_addr[i] = ipv6 & 0xff;
+		set_ipv6[para.core_idx].ipv6_addr.a[i] = ipv6 & 0xff;
 		ipv6 = ipv6 >> 8;
 	}
 
diff --git a/drivers/net/cxgbe/cxgbe_flow.c b/drivers/net/cxgbe/cxgbe_flow.c
index 37c566b131e9..00c55af4bcc6 100644
--- a/drivers/net/cxgbe/cxgbe_flow.c
+++ b/drivers/net/cxgbe/cxgbe_flow.c
@@ -680,7 +680,7 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a,
 						  "found.");
 
 		ipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;
-		memcpy(fs->nat_fip, ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
+		memcpy(fs->nat_fip, &ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
 		*nmode |= 1 << 0;
 		break;
 	case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
@@ -693,7 +693,7 @@ ch_rte_parse_atype_switch(const struct rte_flow_action *a,
 						  "found.");
 
 		ipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;
-		memcpy(fs->nat_lip, ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
+		memcpy(fs->nat_lip, &ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
 		*nmode |= 1 << 1;
 		break;
 	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
diff --git a/drivers/net/nfp/flower/nfp_flower_flow.c b/drivers/net/nfp/flower/nfp_flower_flow.c
index 3f597d394b24..6db1fb141d3e 100644
--- a/drivers/net/nfp/flower/nfp_flower_flow.c
+++ b/drivers/net/nfp/flower/nfp_flower_flow.c
@@ -2978,7 +2978,7 @@ nfp_flow_action_set_ipv6(char *act_data,
 	set_ip->reserved = 0;
 
 	for (i = 0; i < 4; i++) {
-		rte_memcpy(&tmp, &set_ipv6->ipv6_addr[i * 4], 4);
+		rte_memcpy(&tmp, &set_ipv6->ipv6_addr.a[i * 4], 4);
 		set_ip->ipv6[i].exact = tmp;
 		set_ip->ipv6[i].mask = RTE_BE32(0xffffffff);
 	}
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index b3ede7ccdaef..628292c1df07 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -1505,16 +1505,17 @@ struct rte_flow_item_icmp6_nd_ns {
 	uint8_t code; /**< ICMPv6 code, normally 0. */
 	rte_be16_t checksum; /**< ICMPv6 checksum. */
 	rte_be32_t reserved; /**< Reserved, normally 0. */
-	uint8_t target_addr[16]; /**< Target address. */
+	struct rte_ipv6_addr target_addr; /**< Target address. */
 };
 
 /** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS. */
 #ifndef __cplusplus
 static const
 struct rte_flow_item_icmp6_nd_ns rte_flow_item_icmp6_nd_ns_mask = {
-	.target_addr =
+	.target_addr = {
 		"\xff\xff\xff\xff\xff\xff\xff\xff"
 		"\xff\xff\xff\xff\xff\xff\xff\xff",
+	}
 };
 #endif
 
@@ -1532,16 +1533,17 @@ struct rte_flow_item_icmp6_nd_na {
 	 * reserved (29b).
 	 */
 	rte_be32_t rso_reserved;
-	uint8_t target_addr[16]; /**< Target address. */
+	struct rte_ipv6_addr target_addr; /**< Target address. */
 };
 
 /** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA. */
 #ifndef __cplusplus
 static const
 struct rte_flow_item_icmp6_nd_na rte_flow_item_icmp6_nd_na_mask = {
-	.target_addr =
+	.target_addr = {
 		"\xff\xff\xff\xff\xff\xff\xff\xff"
 		"\xff\xff\xff\xff\xff\xff\xff\xff",
+	}
 };
 #endif
 
@@ -3812,7 +3814,7 @@ struct rte_flow_action_set_ipv4 {
  * specified outermost IPv6 header.
  */
 struct rte_flow_action_set_ipv6 {
-	uint8_t ipv6_addr[16];
+	struct rte_ipv6_addr ipv6_addr;
 };
 
 /**
@@ -5196,8 +5198,8 @@ struct rte_flow_tunnel {
 			rte_be32_t dst_addr; /**< IPv4 destination address. */
 		} ipv4;
 		struct {
-			uint8_t src_addr[16]; /**< IPv6 source address. */
-			uint8_t dst_addr[16]; /**< IPv6 destination address. */
+			struct rte_ipv6_addr src_addr; /**< IPv6 source address. */
+			struct rte_ipv6_addr dst_addr; /**< IPv6 destination address. */
 		} ipv6;
 	};
 	rte_be16_t tp_src; /**< Tunnel port source. */
-- 
2.46.0


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

* [PATCH dpdk v1 14/15] rib6,fib6,lpm6: remove duplicate constants
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (12 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 13/15] rte_flow: " Robin Jarry
@ 2024-08-21 16:25 ` Robin Jarry
  2024-08-21 16:25 ` [PATCH dpdk v1 15/15] net: add utilities for well known ipv6 address types Robin Jarry
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev, Vladimir Medvedkin, Bruce Richardson

Replace all address size and max depth macros with common ones from
rte_ip6.h.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test/test_fib6.c | 50 ++++++++++++++++++++++----------------------
 lib/fib/rte_fib6.c   |  6 +++---
 lib/fib/rte_fib6.h   |  4 ----
 lib/fib/trie.c       |  6 +++---
 lib/fib/trie.h       |  2 --
 lib/lpm/rte_lpm6.c   | 10 ++++-----
 lib/lpm/rte_lpm6.h   |  3 ---
 lib/rib/rte_rib6.c   | 11 +++++-----
 lib/rib/rte_rib6.h   |  6 ++----
 9 files changed, 43 insertions(+), 55 deletions(-)

diff --git a/app/test/test_fib6.c b/app/test/test_fib6.c
index 7134c4d335cd..812da01d6e33 100644
--- a/app/test/test_fib6.c
+++ b/app/test/test_fib6.c
@@ -170,13 +170,13 @@ test_add_del_invalid(void)
 	fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
 
-	/* rte_fib6_add: depth > RTE_FIB6_MAXDEPTH */
-	ret = rte_fib6_add(fib, &ip, RTE_FIB6_MAXDEPTH + 1, nh);
+	/* rte_fib6_add: depth > RTE_IPV6_MAX_DEPTH */
+	ret = rte_fib6_add(fib, &ip, RTE_IPV6_MAX_DEPTH + 1, nh);
 	RTE_TEST_ASSERT(ret < 0,
 		"Call succeeded with invalid parameters\n");
 
-	/* rte_fib6_delete: depth > RTE_FIB6_MAXDEPTH */
-	ret = rte_fib6_delete(fib, &ip, RTE_FIB6_MAXDEPTH + 1);
+	/* rte_fib6_delete: depth > RTE_IPV6_MAX_DEPTH */
+	ret = rte_fib6_delete(fib, &ip, RTE_IPV6_MAX_DEPTH + 1);
 	RTE_TEST_ASSERT(ret < 0,
 		"Call succeeded with invalid parameters\n");
 
@@ -216,18 +216,18 @@ lookup_and_check_asc(struct rte_fib6 *fib,
 	struct rte_ipv6_addr *ip_missing, uint64_t def_nh,
 	uint32_t n)
 {
-	uint64_t nh_arr[RTE_FIB6_MAXDEPTH];
+	uint64_t nh_arr[RTE_IPV6_MAX_DEPTH];
 	int ret;
 	uint32_t i = 0;
 
-	ret = rte_fib6_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB6_MAXDEPTH);
+	ret = rte_fib6_lookup_bulk(fib, ip_arr, nh_arr, RTE_IPV6_MAX_DEPTH);
 	RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
 
-	for (; i <= RTE_FIB6_MAXDEPTH - n; i++)
+	for (; i <= RTE_IPV6_MAX_DEPTH - n; i++)
 		RTE_TEST_ASSERT(nh_arr[i] == n,
 			"Failed to get proper nexthop\n");
 
-	for (; i < RTE_FIB6_MAXDEPTH; i++)
+	for (; i < RTE_IPV6_MAX_DEPTH; i++)
 		RTE_TEST_ASSERT(nh_arr[i] == --n,
 			"Failed to get proper nexthop\n");
 
@@ -244,18 +244,18 @@ lookup_and_check_desc(struct rte_fib6 *fib,
 	struct rte_ipv6_addr *ip_missing, uint64_t def_nh,
 	uint32_t n)
 {
-	uint64_t nh_arr[RTE_FIB6_MAXDEPTH];
+	uint64_t nh_arr[RTE_IPV6_MAX_DEPTH];
 	int ret;
 	uint32_t i = 0;
 
-	ret = rte_fib6_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB6_MAXDEPTH);
+	ret = rte_fib6_lookup_bulk(fib, ip_arr, nh_arr, RTE_IPV6_MAX_DEPTH);
 	RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
 
 	for (; i < n; i++)
-		RTE_TEST_ASSERT(nh_arr[i] == RTE_FIB6_MAXDEPTH - i,
+		RTE_TEST_ASSERT(nh_arr[i] == RTE_IPV6_MAX_DEPTH - i,
 			"Failed to get proper nexthop\n");
 
-	for (; i < RTE_FIB6_MAXDEPTH; i++)
+	for (; i < RTE_IPV6_MAX_DEPTH; i++)
 		RTE_TEST_ASSERT(nh_arr[i] == def_nh,
 			"Failed to get proper nexthop\n");
 
@@ -270,7 +270,7 @@ static int
 check_fib(struct rte_fib6 *fib)
 {
 	uint64_t def_nh = 100;
-	struct rte_ipv6_addr ip_arr[RTE_FIB6_MAXDEPTH];
+	struct rte_ipv6_addr ip_arr[RTE_IPV6_MAX_DEPTH];
 	struct rte_ipv6_addr ip_add = {.a = {[0] = 128}};
 	struct rte_ipv6_addr ip_missing = {
 		.a = {[0] = 127, [1 ... 15] = 255},
@@ -278,12 +278,12 @@ check_fib(struct rte_fib6 *fib)
 	uint32_t i, j;
 	int ret;
 
-	for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
+	for (i = 0; i < RTE_IPV6_MAX_DEPTH; i++) {
 		rte_ipv6_addr_cpy(&ip_arr[i], &ip_add);
-		j = (RTE_FIB6_MAXDEPTH - i) / CHAR_BIT;
-		if (j < RTE_FIB6_IPV6_ADDR_SIZE) {
-			ip_arr[i].a[j] |= UINT8_MAX >> ((RTE_FIB6_MAXDEPTH - i) % CHAR_BIT);
-			for (j++; j < RTE_FIB6_IPV6_ADDR_SIZE; j++)
+		j = (RTE_IPV6_MAX_DEPTH - i) / CHAR_BIT;
+		if (j < RTE_IPV6_ADDR_SIZE) {
+			ip_arr[i].a[j] |= UINT8_MAX >> ((RTE_IPV6_MAX_DEPTH - i) % CHAR_BIT);
+			for (j++; j < RTE_IPV6_ADDR_SIZE; j++)
 				ip_arr[i].a[j] = 0xff;
 		}
 	}
@@ -291,7 +291,7 @@ check_fib(struct rte_fib6 *fib)
 	ret = lookup_and_check_desc(fib, ip_arr, &ip_missing, def_nh, 0);
 	RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
 
-	for (i = 1; i <= RTE_FIB6_MAXDEPTH; i++) {
+	for (i = 1; i <= RTE_IPV6_MAX_DEPTH; i++) {
 		ret = rte_fib6_add(fib, &ip_add, i, i);
 		RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
 		ret = lookup_and_check_asc(fib, ip_arr, &ip_missing, def_nh, i);
@@ -299,7 +299,7 @@ check_fib(struct rte_fib6 *fib)
 			"Lookup and check fails\n");
 	}
 
-	for (i = RTE_FIB6_MAXDEPTH; i > 1; i--) {
+	for (i = RTE_IPV6_MAX_DEPTH; i > 1; i--) {
 		ret = rte_fib6_delete(fib, &ip_add, i);
 		RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
 		ret = lookup_and_check_asc(fib, ip_arr, &ip_missing,
@@ -314,9 +314,9 @@ check_fib(struct rte_fib6 *fib)
 	RTE_TEST_ASSERT(ret == TEST_SUCCESS,
 		"Lookup and check fails\n");
 
-	for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
-		ret = rte_fib6_add(fib, &ip_add, RTE_FIB6_MAXDEPTH - i,
-			RTE_FIB6_MAXDEPTH - i);
+	for (i = 0; i < RTE_IPV6_MAX_DEPTH; i++) {
+		ret = rte_fib6_add(fib, &ip_add, RTE_IPV6_MAX_DEPTH - i,
+			RTE_IPV6_MAX_DEPTH - i);
 		RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
 		ret = lookup_and_check_desc(fib, ip_arr, &ip_missing,
 			def_nh, i + 1);
@@ -324,11 +324,11 @@ check_fib(struct rte_fib6 *fib)
 			"Lookup and check fails\n");
 	}
 
-	for (i = 1; i <= RTE_FIB6_MAXDEPTH; i++) {
+	for (i = 1; i <= RTE_IPV6_MAX_DEPTH; i++) {
 		ret = rte_fib6_delete(fib, &ip_add, i);
 		RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
 		ret = lookup_and_check_desc(fib, ip_arr, &ip_missing, def_nh,
-			RTE_FIB6_MAXDEPTH - i);
+			RTE_IPV6_MAX_DEPTH - i);
 		RTE_TEST_ASSERT(ret == TEST_SUCCESS,
 			"Lookup and check fails\n");
 	}
diff --git a/lib/fib/rte_fib6.c b/lib/fib/rte_fib6.c
index d95cac79cbb5..9c7d4fde433a 100644
--- a/lib/fib/rte_fib6.c
+++ b/lib/fib/rte_fib6.c
@@ -71,7 +71,7 @@ dummy_modify(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth, uint64_t next_hop, int op)
 {
 	struct rte_rib6_node *node;
-	if ((fib == NULL) || (depth > RTE_FIB6_MAXDEPTH))
+	if ((fib == NULL) || (depth > RTE_IPV6_MAX_DEPTH))
 		return -EINVAL;
 
 	node = rte_rib6_lookup_exact(fib->rib, ip, depth);
@@ -123,7 +123,7 @@ rte_fib6_add(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth, uint64_t next_hop)
 {
 	if ((fib == NULL) || (ip == NULL) || (fib->modify == NULL) ||
-			(depth > RTE_FIB6_MAXDEPTH))
+			(depth > RTE_IPV6_MAX_DEPTH))
 		return -EINVAL;
 	return fib->modify(fib, ip, depth, next_hop, RTE_FIB6_ADD);
 }
@@ -133,7 +133,7 @@ rte_fib6_delete(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint8_t depth)
 {
 	if ((fib == NULL) || (ip == NULL) || (fib->modify == NULL) ||
-			(depth > RTE_FIB6_MAXDEPTH))
+			(depth > RTE_IPV6_MAX_DEPTH))
 		return -EINVAL;
 	return fib->modify(fib, ip, depth, 0, RTE_FIB6_DEL);
 }
diff --git a/lib/fib/rte_fib6.h b/lib/fib/rte_fib6.h
index d26a0c7c0b77..2e3636b3bd29 100644
--- a/lib/fib/rte_fib6.h
+++ b/lib/fib/rte_fib6.h
@@ -23,10 +23,6 @@
 extern "C" {
 #endif
 
-#define RTE_FIB6_IPV6_ADDR_SIZE		16
-/** Maximum depth value possible for IPv6 FIB. */
-#define RTE_FIB6_MAXDEPTH       128
-
 struct rte_fib6;
 struct rte_rib6;
 
diff --git a/lib/fib/trie.c b/lib/fib/trie.c
index 8a69702eabb2..7c0af20625c1 100644
--- a/lib/fib/trie.c
+++ b/lib/fib/trie.c
@@ -350,9 +350,9 @@ write_edge(struct rte_trie_tbl *dp, const uint8_t *ip_part, uint64_t next_hop,
 	return ret;
 }
 
-#define IPV6_MAX_IDX	(RTE_FIB6_IPV6_ADDR_SIZE - 1)
+#define IPV6_MAX_IDX	(RTE_IPV6_ADDR_SIZE - 1)
 #define TBL24_BYTES	3
-#define TBL8_LEN	(RTE_FIB6_IPV6_ADDR_SIZE - TBL24_BYTES)
+#define TBL8_LEN	(RTE_IPV6_ADDR_SIZE - TBL24_BYTES)
 
 static int
 install_to_dp(struct rte_trie_tbl *dp, const struct rte_ipv6_addr *ledge,
@@ -518,7 +518,7 @@ trie_modify(struct rte_fib6 *fib, const struct rte_ipv6_addr *ip,
 	uint64_t par_nh, node_nh;
 	uint8_t tmp_depth, depth_diff = 0, parent_depth = 24;
 
-	if ((fib == NULL) || (ip == NULL) || (depth > RTE_FIB6_MAXDEPTH))
+	if ((fib == NULL) || (ip == NULL) || (depth > RTE_IPV6_MAX_DEPTH))
 		return -EINVAL;
 
 	dp = rte_fib6_get_dp(fib);
diff --git a/lib/fib/trie.h b/lib/fib/trie.h
index 6e235edaf89c..77f1d95f4316 100644
--- a/lib/fib/trie.h
+++ b/lib/fib/trie.h
@@ -17,8 +17,6 @@
 
 /* @internal Total number of tbl24 entries. */
 #define TRIE_TBL24_NUM_ENT	(1 << 24)
-/* Maximum depth value possible for IPv6 LPM. */
-#define TRIE_MAX_DEPTH		128
 /* @internal Number of entries in a tbl8 group. */
 #define TRIE_TBL8_GRP_NUM_ENT	256ULL
 /* @internal Total number of tbl8 groups in the tbl8. */
diff --git a/lib/lpm/rte_lpm6.c b/lib/lpm/rte_lpm6.c
index 642b02b32cc2..c54726483a1a 100644
--- a/lib/lpm/rte_lpm6.c
+++ b/lib/lpm/rte_lpm6.c
@@ -802,7 +802,7 @@ simulate_add(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *masked_ip, uint8_
 	 * Inspect one by one the rest of the bytes until
 	 * the process is completed.
 	 */
-	for (i = ADD_FIRST_BYTE; i < RTE_LPM6_IPV6_ADDR_SIZE && ret == 1; i++) {
+	for (i = ADD_FIRST_BYTE; i < RTE_IPV6_ADDR_SIZE && ret == 1; i++) {
 		tbl = tbl_next;
 		ret = simulate_add_step(lpm, tbl, &tbl_next, masked_ip, 1,
 			(uint8_t)(i + 1), depth, &need_tbl_nb);
@@ -832,7 +832,7 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth
 	int i;
 
 	/* Check user arguments. */
-	if ((lpm == NULL) || (depth < 1) || (depth > RTE_LPM6_MAX_DEPTH))
+	if ((lpm == NULL) || (depth < 1) || (depth > RTE_IPV6_MAX_DEPTH))
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
@@ -861,7 +861,7 @@ rte_lpm6_add(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t depth
 	 * Inspect one by one the rest of the bytes until
 	 * the process is completed.
 	 */
-	for (i = ADD_FIRST_BYTE; i < RTE_LPM6_IPV6_ADDR_SIZE && status == 1; i++) {
+	for (i = ADD_FIRST_BYTE; i < RTE_IPV6_ADDR_SIZE && status == 1; i++) {
 		tbl = tbl_next;
 		status = add_step(lpm, tbl, tbl_next_num, &tbl_next,
 			&tbl_next_num, &masked_ip, 1, (uint8_t)(i + 1),
@@ -993,7 +993,7 @@ rte_lpm6_is_rule_present(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, u
 
 	/* Check user arguments. */
 	if ((lpm == NULL) || next_hop == NULL || ip == NULL ||
-			(depth < 1) || (depth > RTE_LPM6_MAX_DEPTH))
+			(depth < 1) || (depth > RTE_IPV6_MAX_DEPTH))
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
@@ -1267,7 +1267,7 @@ rte_lpm6_delete(struct rte_lpm6 *lpm, const struct rte_ipv6_addr *ip, uint8_t de
 	struct rte_lpm6_tbl_entry *from, *to;
 
 	/* Check input arguments. */
-	if ((lpm == NULL) || (depth < 1) || (depth > RTE_LPM6_MAX_DEPTH))
+	if ((lpm == NULL) || (depth < 1) || (depth > RTE_IPV6_MAX_DEPTH))
 		return -EINVAL;
 
 	/* Copy the IP and mask it to avoid modifying user's input data. */
diff --git a/lib/lpm/rte_lpm6.h b/lib/lpm/rte_lpm6.h
index 87392194237c..19b498a78d5d 100644
--- a/lib/lpm/rte_lpm6.h
+++ b/lib/lpm/rte_lpm6.h
@@ -17,9 +17,6 @@
 extern "C" {
 #endif
 
-
-#define RTE_LPM6_MAX_DEPTH               128
-#define RTE_LPM6_IPV6_ADDR_SIZE           16
 /** Max number of characters in LPM name. */
 #define RTE_LPM6_NAMESIZE                 32
 
diff --git a/lib/rib/rte_rib6.c b/lib/rib/rte_rib6.c
index ec46c865ddf7..207ece0507dd 100644
--- a/lib/rib/rte_rib6.c
+++ b/lib/rib/rte_rib6.c
@@ -20,7 +20,6 @@
 #include "rib_log.h"
 
 #define RTE_RIB_VALID_NODE	1
-#define RIB6_MAXDEPTH		128
 /* Maximum length of a RIB6 name. */
 #define RTE_RIB6_NAMESIZE	64
 
@@ -89,7 +88,7 @@ static inline struct rte_rib6_node *
 get_nxt_node(struct rte_rib6_node *node,
 	const struct rte_ipv6_addr *ip)
 {
-	if (node->depth == RIB6_MAXDEPTH)
+	if (node->depth == RTE_IPV6_MAX_DEPTH)
 		return NULL;
 
 	return (get_dir(ip, node->depth)) ? node->right : node->left;
@@ -158,7 +157,7 @@ rte_rib6_lookup_exact(struct rte_rib6 *rib,
 	struct rte_rib6_node *cur;
 	struct rte_ipv6_addr tmp_ip;
 
-	if (unlikely(rib == NULL || ip == NULL || depth > RIB6_MAXDEPTH)) {
+	if (unlikely(rib == NULL || ip == NULL || depth > RTE_IPV6_MAX_DEPTH)) {
 		rte_errno = EINVAL;
 		return NULL;
 	}
@@ -196,7 +195,7 @@ rte_rib6_get_nxt(struct rte_rib6 *rib,
 	struct rte_rib6_node *tmp, *prev = NULL;
 	struct rte_ipv6_addr tmp_ip;
 
-	if (unlikely(rib == NULL || ip == NULL || depth > RIB6_MAXDEPTH)) {
+	if (unlikely(rib == NULL || ip == NULL || depth > RTE_IPV6_MAX_DEPTH)) {
 		rte_errno = EINVAL;
 		return NULL;
 	}
@@ -279,7 +278,7 @@ rte_rib6_insert(struct rte_rib6 *rib,
 	int i, d;
 	uint8_t common_depth, ip_xor;
 
-	if (unlikely((rib == NULL || ip == NULL || depth > RIB6_MAXDEPTH))) {
+	if (unlikely((rib == NULL || ip == NULL || depth > RTE_IPV6_MAX_DEPTH))) {
 		rte_errno = EINVAL;
 		return NULL;
 	}
@@ -341,7 +340,7 @@ rte_rib6_insert(struct rte_rib6 *rib,
 
 	/* closest node found, new_node should be inserted in the middle */
 	common_depth = RTE_MIN(depth, (*tmp)->depth);
-	for (i = 0, d = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++) {
+	for (i = 0, d = 0; i < RTE_IPV6_ADDR_SIZE; i++) {
 		ip_xor = tmp_ip.a[i] ^ (*tmp)->ip.a[i];
 		if (ip_xor == 0)
 			d += 8;
diff --git a/lib/rib/rte_rib6.h b/lib/rib/rte_rib6.h
index fcf4169ca790..0e72766876ed 100644
--- a/lib/rib/rte_rib6.h
+++ b/lib/rib/rte_rib6.h
@@ -22,8 +22,6 @@
 extern "C" {
 #endif
 
-#define RTE_RIB6_IPV6_ADDR_SIZE	16
-
 /**
  * rte_rib6_get_nxt() flags
  */
@@ -65,7 +63,7 @@ rte_rib6_copy_addr(uint8_t *dst, const uint8_t *src)
 {
 	if ((dst == NULL) || (src == NULL))
 		return;
-	rte_memcpy(dst, src, RTE_RIB6_IPV6_ADDR_SIZE);
+	rte_memcpy(dst, src, RTE_IPV6_ADDR_SIZE);
 }
 
 /**
@@ -89,7 +87,7 @@ rte_rib6_is_equal(const uint8_t *ip1, const uint8_t *ip2) {
 
 	if ((ip1 == NULL) || (ip2 == NULL))
 		return 0;
-	for (i = 0; i < RTE_RIB6_IPV6_ADDR_SIZE; i++) {
+	for (i = 0; i < RTE_IPV6_ADDR_SIZE; i++) {
 		if (ip1[i] != ip2[i])
 			return 0;
 	}
-- 
2.46.0


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

* [PATCH dpdk v1 15/15] net: add utilities for well known ipv6 address types
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (13 preceding siblings ...)
  2024-08-21 16:25 ` [PATCH dpdk v1 14/15] rib6,fib6,lpm6: remove duplicate constants Robin Jarry
@ 2024-08-21 16:25 ` 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
  16 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-21 16:25 UTC (permalink / raw)
  To: dev

Add more utilities to work with IPv6 addresses. These functions will be
required in order to help building IPv6 routing applications.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
---
 app/test/test_net_ipv6.c | 74 ++++++++++++++++++++++++++++++
 lib/net/rte_ip6.h        | 98 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 172 insertions(+)

diff --git a/app/test/test_net_ipv6.c b/app/test/test_net_ipv6.c
index c2b42d67285e..b087b5c60d73 100644
--- a/app/test/test_net_ipv6.c
+++ b/app/test/test_net_ipv6.c
@@ -93,26 +93,97 @@ static int
 test_ipv6_addr_kind(void)
 {
 	TEST_ASSERT(rte_ipv6_addr_is_unspec(&zero_addr), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_linklocal(&zero_addr), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_loopback(&zero_addr), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_mcast(&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), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_linklocal(&ucast), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_loopback(&ucast), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_mcast(&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), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_linklocal(&mcast), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_loopback(&mcast), "");
+	TEST_ASSERT(rte_ipv6_addr_is_mcast(&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), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_linklocal(&lo), "");
+	TEST_ASSERT(rte_ipv6_addr_is_loopback(&lo), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_mcast(&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), "");
+	TEST_ASSERT(rte_ipv6_addr_is_linklocal(&local), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_loopback(&local), "");
+	TEST_ASSERT(!rte_ipv6_addr_is_mcast(&local), "");
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_ipv6_llocal_from_ethernet(void)
+{
+	const struct rte_ether_addr local_mac = { "\x04\x7b\xcb\x5c\x08\x44" };
+	const struct rte_ipv6_addr local_ip = {
+		"\xfe\x80\x00\x00\x00\x00\x00\x00\x04\x7b\xcb\xff\xfe\x5c\x08\x44"
+	};
+	struct rte_ipv6_addr ip;
+
+	rte_ipv6_llocal_from_ethernet(&ip, &local_mac);
+	TEST_ASSERT(rte_ipv6_addr_eq(&ip, &local_ip), "");
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_ipv6_solnode_from_addr(void)
+{
+	struct rte_ipv6_addr sol;
+
+	const struct rte_ipv6_addr llocal = {
+		"\xfe\x80\x00\x00\x00\x00\x00\x00\x04\x7b\xcb\xff\xfe\x5c\x08\x44"
+	};
+	const struct rte_ipv6_addr llocal_sol = {
+		"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x5c\x08\x44"
+	};
+	rte_ipv6_solnode_from_addr(&sol, &llocal);
+	TEST_ASSERT(rte_ipv6_addr_eq(&sol, &llocal_sol), "");
+
+	const struct rte_ipv6_addr ucast = {
+		"\x2a\x01\xcb\x00\x02\x54\x33\x00\x1b\x9f\x80\x71\x67\xcd\xbf\x20"
+	};
+	const struct rte_ipv6_addr ucast_sol = {
+		"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xcd\xbf\x20"
+	};
+	rte_ipv6_solnode_from_addr(&sol, &ucast);
+	TEST_ASSERT(rte_ipv6_addr_eq(&sol, &ucast_sol), "");
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_ether_mcast_from_ipv6(void)
+{
+	const struct rte_ether_addr mcast_mac = { "\x33\x33\xd3\x00\x02\x01" };
+	const struct rte_ipv6_addr mcast_ip = {
+		"\xff\x02\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\xd3\x00\x02\x01"
+	};
+	struct rte_ether_addr mac;
+
+	rte_ether_mcast_from_ipv6(&mac, &mcast_ip);
+	TEST_ASSERT(rte_is_same_ether_addr(&mac, &mcast_mac), "");
 
 	return TEST_SUCCESS;
 }
@@ -123,6 +194,9 @@ 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(), "");
+	TEST_ASSERT_SUCCESS(test_ipv6_llocal_from_ethernet(), "");
+	TEST_ASSERT_SUCCESS(test_ipv6_solnode_from_addr(), "");
+	TEST_ASSERT_SUCCESS(test_ether_mcast_from_ipv6(), "");
 	return TEST_SUCCESS;
 }
 
diff --git a/lib/net/rte_ip6.h b/lib/net/rte_ip6.h
index 6bc18a1c8dd6..d7eba63fe111 100644
--- a/lib/net/rte_ip6.h
+++ b/lib/net/rte_ip6.h
@@ -28,6 +28,7 @@
 #include <netinet/ip6.h>
 #endif
 
+#include <rte_ether.h>
 #include <rte_byteorder.h>
 #include <rte_mbuf.h>
 #include <rte_memcpy.h>
@@ -157,6 +158,103 @@ rte_ipv6_addr_is_unspec(const struct rte_ipv6_addr *ip)
 	return rte_ipv6_addr_eq(ip, &unspec);
 }
 
+/**
+ * Check if an IPv6 address is the loopback address as defined in RFC 4291, section 2.5.3.
+ */
+static inline bool
+rte_ipv6_addr_is_loopback(const struct rte_ipv6_addr *ip)
+{
+	static const struct rte_ipv6_addr loopback = {
+		.a = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
+	};
+	return rte_ipv6_addr_eq(ip, &loopback);
+}
+
+/**
+ * Check if an IPv6 address is link-local as defined in RFC 4291, section 2.5.6.
+ */
+static inline bool
+rte_ipv6_addr_is_linklocal(const struct rte_ipv6_addr *ip)
+{
+	static const struct rte_ipv6_addr local = {
+		.a = {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+	};
+	return rte_ipv6_addr_eq_prefix(ip, &local, 64);
+}
+
+/**
+ * Check if an IPv6 address is multicast as defined in RFC 4291, section 2.7.
+ */
+static inline bool
+rte_ipv6_addr_is_mcast(const struct rte_ipv6_addr *ip)
+{
+	return ip->a[0] == 0xff;
+}
+
+/**
+ * Generate a link-local IPv6 address from an ethernet address as specified in
+ * RFC 2464, section 5.
+ */
+static inline void
+rte_ipv6_llocal_from_ethernet(struct rte_ipv6_addr *ip, const struct rte_ether_addr *mac)
+{
+	ip->a[0] = 0xfe;
+	ip->a[1] = 0x80;
+	memset(&ip->a[2], 0, 6);
+	ip->a[8] = mac->addr_bytes[0];
+	ip->a[9] = mac->addr_bytes[1];
+	ip->a[10] = mac->addr_bytes[2];
+	ip->a[11] = 0xff;
+	ip->a[12] = 0xfe;
+	ip->a[13] = mac->addr_bytes[3];
+	ip->a[14] = mac->addr_bytes[4];
+	ip->a[15] = mac->addr_bytes[5];
+}
+
+/**
+ * Convert a unicast or anycast IPv6 address to a solicited-node multicast
+ * address as defined in RFC 4291, section 2.7.1.
+ */
+static inline void
+rte_ipv6_solnode_from_addr(struct rte_ipv6_addr *sol, const struct rte_ipv6_addr *ip)
+{
+	sol->a[0] = 0xff;
+	sol->a[1] = 0x02;
+	memset(&sol->a[2], 0, 9);
+	sol->a[11] = 0x01;
+	sol->a[12] = 0xff;
+	sol->a[13] = ip->a[13];
+	sol->a[14] = ip->a[14];
+	sol->a[15] = ip->a[15];
+}
+
+/**
+ * Generate a multicast ethernet address from a multicast IPv6 address as defined
+ * in RFC 2464, section 7.
+ */
+static inline void
+rte_ether_mcast_from_ipv6(struct rte_ether_addr *mac, const struct rte_ipv6_addr *ip)
+{
+	mac->addr_bytes[0] = 0x33;
+	mac->addr_bytes[1] = 0x33;
+	mac->addr_bytes[2] = ip->a[12];
+	mac->addr_bytes[3] = ip->a[13];
+	mac->addr_bytes[4] = ip->a[14];
+	mac->addr_bytes[5] = ip->a[15];
+}
+
+/** Well known multicast addresses as defined in RFC 4291, section 2.7.1. */
+#define RTE_IPV6_ADDR_ALLNODES_IFACE_LOCAL \
+	((struct rte_ipv6_addr){.a = {0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
+#define RTE_IPV6_ADDR_ALLNODES_LINK_LOCAL \
+	((struct rte_ipv6_addr){.a = {0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
+#define RTE_IPV6_ADDR_ALLROUTERS_IFACE_LOCAL \
+	((struct rte_ipv6_addr){.a = {0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
+#define RTE_IPV6_ADDR_ALLROUTERS_LINK_LOCAL \
+	((struct rte_ipv6_addr){.a = {0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
+#define RTE_IPV6_ADDR_ALLROUTERS_SITE_LOCAL \
+	((struct rte_ipv6_addr){.a = {0xff, 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}})
+
 /**
  * IPv6 Header
  */
-- 
2.46.0


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

* RE: [PATCH dpdk v1 00/15] IPv6 APIs overhaul
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (14 preceding siblings ...)
  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 ` Morten Brørup
  2024-08-22 14:13 ` Stephen Hemminger
  16 siblings, 0 replies; 23+ messages in thread
From: Morten Brørup @ 2024-08-21 22:28 UTC (permalink / raw)
  To: Robin Jarry, dev
  Cc: Stephen Hemminger, Vladimir Medvedkin, Konstantin Ananyev,
	Bruce Richardson

> From: Robin Jarry [mailto:rjarry@redhat.com]
> Sent: Wednesday, 21 August 2024 18.25
> 
> Hi everyone,
> 
> As discussed recently [1], here is a first draft of the IPv6 APIs
> rework. The
> API change was announced before the 24.07 release [2]. This series is
> intended
> for 24.11.
> 
> [1] http://inbox.dpdk.org/dev/D2SR8T1H39CJ.JRQFI6JEH0OX@redhat.com/
> [2]
> https://git.dpdk.org/dpdk/commit/?id=835d4c41e0ab58a115c2170c886ba6d3cc1
> b5764
> 
> I tried to keep the patches as small as possible; unfortunately some of
> them
> are quite big and cannot be broken down if we want to preserve a
> bisectable
> tree.
> 
> Let me know what you think.
> 
> Thanks!
> 
> Cc: Morten Brørup <mb@smartsharesystems.com>
> Cc: Stephen Hemminger <stephen@networkplumber.org>
> Cc: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> Cc: Konstantin Ananyev <konstantin.ananyev@huawei.com>
> Cc: Bruce Richardson <bruce.richardson@intel.com>
> 
> Robin Jarry (15):
>   net: split raw checksum functions in separate header
>   net: split ipv6 symbols in separate header
>   net: add structure for ipv6 addresses
>   net: use ipv6 structure for header addresses
>   fib6,rib6,lpm6: use ipv6 addr struct
>   net: add ipv6 address utilities
>   fib6,rib6,lpm6: use ipv6 utils
>   graph,node: use ipv6 addr struct and utils
>   pipeline: use ipv6 addr struct
>   ipsec: use ipv6 addr struct
>   thash: use ipv6 addr struct
>   gro: use ipv6 addr struct
>   rte_flow: use ipv6 addr struct
>   rib6,fib6,lpm6: remove duplicate constants
>   net: add utilities for well known ipv6 address types

LGTM.

For the series,
Acked-by: Morten Brørup <mb@smartsharesystems.com>


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

* Re: [PATCH dpdk v1 00/15] IPv6 APIs overhaul
  2024-08-21 16:25 [PATCH dpdk v1 00/15] IPv6 APIs overhaul Robin Jarry
                   ` (15 preceding siblings ...)
  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
                     ` (2 more replies)
  16 siblings, 3 replies; 23+ messages in thread
From: Stephen Hemminger @ 2024-08-22 14:13 UTC (permalink / raw)
  To: Robin Jarry
  Cc: dev, Morten Brørup, Vladimir Medvedkin, Konstantin Ananyev,
	Bruce Richardson

On Wed, 21 Aug 2024 18:25:17 +0200
Robin Jarry <rjarry@redhat.com> wrote:

> Hi everyone,
> 
> As discussed recently [1], here is a first draft of the IPv6 APIs rework. The
> API change was announced before the 24.07 release [2]. This series is intended
> for 24.11.
> 
> [1] http://inbox.dpdk.org/dev/D2SR8T1H39CJ.JRQFI6JEH0OX@redhat.com/
> [2] https://git.dpdk.org/dpdk/commit/?id=835d4c41e0ab58a115c2170c886ba6d3cc1b5764
> 
> I tried to keep the patches as small as possible; unfortunately some of them
> are quite big and cannot be broken down if we want to preserve a bisectable
> tree.
> 
> Let me know what you think.

Let me ask a couple of questions about this.

Why does DPDK need to have its own definitions of IPv4 and IPv6 addresses?
The structures in_addr and in6_addr exist on Linux, BSD, and Windows.
It creates lots of code reimplementation (see inet_ntop etc).


What advantage is there to having our own definitions?


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

* RE: [PATCH dpdk v1 00/15] IPv6 APIs overhaul
  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 15:14   ` Robin Jarry
  2024-08-22 15:16   ` Robin Jarry
  2 siblings, 1 reply; 23+ messages in thread
From: Morten Brørup @ 2024-08-22 15:13 UTC (permalink / raw)
  To: Stephen Hemminger, Robin Jarry
  Cc: dev, Vladimir Medvedkin, Konstantin Ananyev, Bruce Richardson

> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> 
> On Wed, 21 Aug 2024 18:25:17 +0200
> Robin Jarry <rjarry@redhat.com> wrote:
> 
> > Hi everyone,
> >
> > As discussed recently [1], here is a first draft of the IPv6 APIs rework.
> The
> > API change was announced before the 24.07 release [2]. This series is
> intended
> > for 24.11.
> >
> > [1] http://inbox.dpdk.org/dev/D2SR8T1H39CJ.JRQFI6JEH0OX@redhat.com/
> > [2]
> https://git.dpdk.org/dpdk/commit/?id=835d4c41e0ab58a115c2170c886ba6d3cc1b5764
> >
> > I tried to keep the patches as small as possible; unfortunately some of them
> > are quite big and cannot be broken down if we want to preserve a bisectable
> > tree.
> >
> > Let me know what you think.
> 
> Let me ask a couple of questions about this.
> 
> Why does DPDK need to have its own definitions of IPv4 and IPv6 addresses?
> The structures in_addr and in6_addr exist on Linux, BSD, and Windows.
> It creates lots of code reimplementation (see inet_ntop etc).
> 
> 
> What advantage is there to having our own definitions?

The types seem to be different in the Windows API (than in Linux/BSD):
https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.14393.0/shared/in6addr.h#L25
https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.16299.0/shared/inaddr.h#L25

Furthermore, but less important:
The existing in the Linux/BSD/Windows IPv6 address type are 2-byte aligned.
In the RFC discussion, we agreed to omit any alignment requirements for the DPDK IPv6 address, for tunneling purposes.
We could introduce 2-byte alignment later, using a union and an array of uint16_t, if beneficial.

Which makes me think...
Maybe the 'a' field in the DPDK IPv6 address structure should be named 'b' for "byte" instead, to prepare it for adding a union with a 'w' (for "word") field if we want to introduce 2-byte alignment.


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

* Re: [PATCH dpdk v1 00/15] IPv6 APIs overhaul
  2024-08-22 14:13 ` Stephen Hemminger
  2024-08-22 15:13   ` Morten Brørup
@ 2024-08-22 15:14   ` Robin Jarry
  2024-08-22 15:16   ` Robin Jarry
  2 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-22 15:14 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: dev, Morten Brørup, Vladimir Medvedkin, Konstantin Ananyev,
	Bruce Richardson

Stephen Hemminger, Aug 22, 2024 at 16:13:
> Let me ask a couple of questions about this.
>
> Why does DPDK need to have its own definitions of IPv4 and IPv6 addresses?
> The structures in_addr and in6_addr exist on Linux, BSD, and Windows.
> It creates lots of code reimplementation (see inet_ntop etc).
>
> What advantage is there to having our own definitions?

If I'm not mistaken, in6_addr is aligned on 4 bytes. Is it guaranteed 
that IPv6 headers will *always* be starting on a 4 bytes boundary? If 
not then, in6_addr cannot be mapped on unaligned packet memory.


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

* Re: [PATCH dpdk v1 00/15] IPv6 APIs overhaul
  2024-08-22 14:13 ` Stephen Hemminger
  2024-08-22 15:13   ` Morten Brørup
  2024-08-22 15:14   ` Robin Jarry
@ 2024-08-22 15:16   ` Robin Jarry
  2 siblings, 0 replies; 23+ messages in thread
From: Robin Jarry @ 2024-08-22 15:16 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: dev, Morten Brørup, Vladimir Medvedkin, Konstantin Ananyev,
	Bruce Richardson

Stephen Hemminger, Aug 22, 2024 at 16:13:
> Why does DPDK need to have its own definitions of IPv4 and IPv6 addresses?
> The structures in_addr and in6_addr exist on Linux, BSD, and Windows.
> It creates lots of code reimplementation (see inet_ntop etc).

By the way, you can call inet_ntop(AF_INET6) with the rte_ipv6_addr type 
I introduce here. It works fine.


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

* Re: [PATCH dpdk v1 00/15] IPv6 APIs overhaul
  2024-08-22 15:13   ` Morten Brørup
@ 2024-08-22 15:27     ` Robin Jarry
  2024-08-22 18:41       ` Morten Brørup
  0 siblings, 1 reply; 23+ messages in thread
From: Robin Jarry @ 2024-08-22 15:27 UTC (permalink / raw)
  To: Morten Brørup, Stephen Hemminger
  Cc: dev, Vladimir Medvedkin, Konstantin Ananyev, Bruce Richardson

Morten Brørup, Aug 22, 2024 at 17:13:
> The types seem to be different in the Windows API (than in Linux/BSD):
> https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.14393.0/shared/in6addr.h#L25
> https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.16299.0/shared/inaddr.h#L25
>
> Furthermore, but less important:
> The existing in the Linux/BSD/Windows IPv6 address type are 2-byte aligned.

At least BSD is 4 bytes aligned.

https://github.com/freebsd/freebsd-src/blob/498286d4e807d6b9e4caad22b96ebca7f16e9b18/sys/netinet6/in6.h#L91-L100

And on Linux, it depends on the libc implementation?

https://github.com/torvalds/linux/blob/872cf28b8df9c5c3a1e71a88ee750df7c2513971/include/uapi/linux/in6.h#L33

> In the RFC discussion, we agreed to omit any alignment requirements for the DPDK IPv6 address, for tunneling purposes.
> We could introduce 2-byte alignment later, using a union and an array of uint16_t, if beneficial.
>
> Which makes me think...
> Maybe the 'a' field in the DPDK IPv6 address structure should be named 'b' for "byte" instead, to prepare it for adding a union with a 'w' (for "word") field if we want to introduce 2-byte alignment.

My idea was to name the field a16 instead of w which would be confusing. 
Also, how would you name a 32 bit array field if it presented itself?


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

* RE: [PATCH dpdk v1 00/15] IPv6 APIs overhaul
  2024-08-22 15:27     ` Robin Jarry
@ 2024-08-22 18:41       ` Morten Brørup
  0 siblings, 0 replies; 23+ messages in thread
From: Morten Brørup @ 2024-08-22 18:41 UTC (permalink / raw)
  To: Robin Jarry, Stephen Hemminger
  Cc: dev, Vladimir Medvedkin, Konstantin Ananyev, Bruce Richardson

> From: Robin Jarry [mailto:rjarry@redhat.com]
> 
> Morten Brørup, Aug 22, 2024 at 17:13:

> > Maybe the 'a' field in the DPDK IPv6 address structure should be named
> 'b' for "byte" instead, to prepare it for adding a union with a 'w' (for
> "word") field if we want to introduce 2-byte alignment.
> 
> My idea was to name the field a16 instead of w which would be confusing.
> Also, how would you name a 32 bit array field if it presented itself?

Good question, I have no obvious suggestion for this.
Which again goes to show that naming is hard.

Perhaps we should lean on the names of types and functions using 32 for 32 bit versions and 64 for 64 bit variants. Then the union fields could be named a8[16], a16[8] and a32[4].

Other projects follow a convention of including the type in the variable/parameter names, e.g. the Win32 API. But DPDK doesn't, so it seems strange doing it here.


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

end of thread, other threads:[~2024-08-22 18:41 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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

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).