[v6,4/7] test/security: add inline IPsec reassembly cases

Message ID 20220513073201.2320812-5-gakhil@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: akhil goyal
Headers
Series app/test: add inline IPsec and reassembly cases |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Akhil Goyal May 13, 2022, 7:31 a.m. UTC
  Added unit test cases for IP reassembly of inline IPsec
inbound scenarios.
In these cases, known test vectors of fragments are first
processed for inline outbound processing and then received
back on loopback interface for inbound processing along with
IP reassembly of the corresponding decrypted packets.
The resultant plain text reassembled packet is compared with
original unfragmented packet.

In this patch, cases are added for 2/4/5 fragments for both
IPv4 and IPv6 packets. A few negative test cases are also added
like incomplete fragments, out of place fragments, duplicate
fragments.

Signed-off-by: Akhil Goyal <gakhil@marvell.com>
Acked-by: Fan Zhang <roy.fan.zhang@intel.com>
---
 app/test/test_security_inline_proto.c         | 423 ++++++++++-
 app/test/test_security_inline_proto_vectors.h | 684 ++++++++++++++++++
 2 files changed, 1106 insertions(+), 1 deletion(-)
  

Patch

diff --git a/app/test/test_security_inline_proto.c b/app/test/test_security_inline_proto.c
index a44a4f9b04..2aa7072512 100644
--- a/app/test/test_security_inline_proto.c
+++ b/app/test/test_security_inline_proto.c
@@ -41,6 +41,9 @@  test_inline_ipsec(void)
 #define MAX_TRAFFIC_BURST		2048
 #define NB_MBUF				10240
 
+#define ENCAP_DECAP_BURST_SZ		33
+#define APP_REASS_TIMEOUT		10
+
 extern struct ipsec_test_data pkt_aes_128_gcm;
 extern struct ipsec_test_data pkt_aes_192_gcm;
 extern struct ipsec_test_data pkt_aes_256_gcm;
@@ -94,6 +97,8 @@  uint16_t port_id;
 
 static uint64_t link_mbps;
 
+static int ip_reassembly_dynfield_offset = -1;
+
 static struct rte_flow *default_flow[RTE_MAX_ETHPORTS];
 
 /* Create Inline IPsec session */
@@ -530,6 +535,349 @@  destroy_default_flow(uint16_t portid)
 struct rte_mbuf **tx_pkts_burst;
 struct rte_mbuf **rx_pkts_burst;
 
+static int
+compare_pkt_data(struct rte_mbuf *m, uint8_t *ref, unsigned int tot_len)
+{
+	unsigned int len;
+	unsigned int nb_segs = m->nb_segs;
+	unsigned int matched = 0;
+	struct rte_mbuf *save = m;
+
+	while (m) {
+		len = tot_len;
+		if (len > m->data_len)
+			len = m->data_len;
+		if (len != 0) {
+			if (memcmp(rte_pktmbuf_mtod(m, char *),
+					ref + matched, len)) {
+				printf("\n====Reassembly case failed: Data Mismatch");
+				rte_hexdump(stdout, "Reassembled",
+					rte_pktmbuf_mtod(m, char *),
+					len);
+				rte_hexdump(stdout, "reference",
+					ref + matched,
+					len);
+				return TEST_FAILED;
+			}
+		}
+		tot_len -= len;
+		matched += len;
+		m = m->next;
+	}
+
+	if (tot_len) {
+		printf("\n====Reassembly case failed: Data Missing %u",
+		       tot_len);
+		printf("\n====nb_segs %u, tot_len %u", nb_segs, tot_len);
+		rte_pktmbuf_dump(stderr, save, -1);
+		return TEST_FAILED;
+	}
+	return TEST_SUCCESS;
+}
+
+static inline bool
+is_ip_reassembly_incomplete(struct rte_mbuf *mbuf)
+{
+	static uint64_t ip_reassembly_dynflag;
+	int ip_reassembly_dynflag_offset;
+
+	if (ip_reassembly_dynflag == 0) {
+		ip_reassembly_dynflag_offset = rte_mbuf_dynflag_lookup(
+			RTE_MBUF_DYNFLAG_IP_REASSEMBLY_INCOMPLETE_NAME, NULL);
+		if (ip_reassembly_dynflag_offset < 0)
+			return false;
+		ip_reassembly_dynflag = RTE_BIT64(ip_reassembly_dynflag_offset);
+	}
+
+	return (mbuf->ol_flags & ip_reassembly_dynflag) != 0;
+}
+
+static void
+free_mbuf(struct rte_mbuf *mbuf)
+{
+	rte_eth_ip_reassembly_dynfield_t dynfield;
+
+	if (!mbuf)
+		return;
+
+	if (!is_ip_reassembly_incomplete(mbuf)) {
+		rte_pktmbuf_free(mbuf);
+	} else {
+		if (ip_reassembly_dynfield_offset < 0)
+			return;
+
+		while (mbuf) {
+			dynfield = *RTE_MBUF_DYNFIELD(mbuf,
+					ip_reassembly_dynfield_offset,
+					rte_eth_ip_reassembly_dynfield_t *);
+			rte_pktmbuf_free(mbuf);
+			mbuf = dynfield.next_frag;
+		}
+	}
+}
+
+
+static int
+get_and_verify_incomplete_frags(struct rte_mbuf *mbuf,
+				struct reassembly_vector *vector)
+{
+	rte_eth_ip_reassembly_dynfield_t *dynfield[MAX_PKT_BURST];
+	int j = 0, ret;
+	/**
+	 * IP reassembly offload is incomplete, and fragments are listed in
+	 * dynfield which can be reassembled in SW.
+	 */
+	printf("\nHW IP Reassembly is not complete; attempt SW IP Reassembly,"
+		"\nMatching with original frags.");
+
+	if (ip_reassembly_dynfield_offset < 0)
+		return -1;
+
+	printf("\ncomparing frag: %d", j);
+	/* Skip Ethernet header comparison */
+	rte_pktmbuf_adj(mbuf, RTE_ETHER_HDR_LEN);
+	ret = compare_pkt_data(mbuf, vector->frags[j]->data,
+				vector->frags[j]->len);
+	if (ret)
+		return ret;
+	j++;
+	dynfield[j] = RTE_MBUF_DYNFIELD(mbuf, ip_reassembly_dynfield_offset,
+					rte_eth_ip_reassembly_dynfield_t *);
+	printf("\ncomparing frag: %d", j);
+	/* Skip Ethernet header comparison */
+	rte_pktmbuf_adj(dynfield[j]->next_frag, RTE_ETHER_HDR_LEN);
+	ret = compare_pkt_data(dynfield[j]->next_frag, vector->frags[j]->data,
+			vector->frags[j]->len);
+	if (ret)
+		return ret;
+
+	while ((dynfield[j]->nb_frags > 1) &&
+			is_ip_reassembly_incomplete(dynfield[j]->next_frag)) {
+		j++;
+		dynfield[j] = RTE_MBUF_DYNFIELD(dynfield[j-1]->next_frag,
+					ip_reassembly_dynfield_offset,
+					rte_eth_ip_reassembly_dynfield_t *);
+		printf("\ncomparing frag: %d", j);
+		/* Skip Ethernet header comparison */
+		rte_pktmbuf_adj(dynfield[j]->next_frag, RTE_ETHER_HDR_LEN);
+		ret = compare_pkt_data(dynfield[j]->next_frag,
+				vector->frags[j]->data, vector->frags[j]->len);
+		if (ret)
+			return ret;
+	}
+	return ret;
+}
+
+static int
+test_ipsec_with_reassembly(struct reassembly_vector *vector,
+		const struct ipsec_test_flags *flags)
+{
+	struct rte_security_session *out_ses[ENCAP_DECAP_BURST_SZ] = {0};
+	struct rte_security_session *in_ses[ENCAP_DECAP_BURST_SZ] = {0};
+	struct rte_eth_ip_reassembly_params reass_capa = {0};
+	struct rte_security_session_conf sess_conf_out = {0};
+	struct rte_security_session_conf sess_conf_in = {0};
+	unsigned int nb_tx, burst_sz, nb_sent = 0;
+	struct rte_crypto_sym_xform cipher_out = {0};
+	struct rte_crypto_sym_xform auth_out = {0};
+	struct rte_crypto_sym_xform aead_out = {0};
+	struct rte_crypto_sym_xform cipher_in = {0};
+	struct rte_crypto_sym_xform auth_in = {0};
+	struct rte_crypto_sym_xform aead_in = {0};
+	struct ipsec_test_data sa_data = {0};
+	struct rte_security_ctx *ctx;
+	unsigned int i, nb_rx = 0, j;
+	uint32_t ol_flags;
+	int ret = 0;
+
+	burst_sz = vector->burst ? ENCAP_DECAP_BURST_SZ : 1;
+	nb_tx = vector->nb_frags * burst_sz;
+
+	rte_eth_dev_stop(port_id);
+	if (ret != 0) {
+		printf("rte_eth_dev_stop: err=%s, port=%u\n",
+			       rte_strerror(-ret), port_id);
+		return ret;
+	}
+	rte_eth_ip_reassembly_capability_get(port_id, &reass_capa);
+	if (reass_capa.max_frags < vector->nb_frags)
+		return TEST_SKIPPED;
+	if (reass_capa.timeout_ms > APP_REASS_TIMEOUT) {
+		reass_capa.timeout_ms = APP_REASS_TIMEOUT;
+		rte_eth_ip_reassembly_conf_set(port_id, &reass_capa);
+	}
+
+	ret = rte_eth_dev_start(port_id);
+	if (ret < 0) {
+		printf("rte_eth_dev_start: err=%d, port=%d\n",
+			ret, port_id);
+		return ret;
+	}
+
+	memset(tx_pkts_burst, 0, sizeof(tx_pkts_burst[0]) * nb_tx);
+	memset(rx_pkts_burst, 0, sizeof(rx_pkts_burst[0]) * nb_tx);
+
+	for (i = 0; i < nb_tx; i += vector->nb_frags) {
+		for (j = 0; j < vector->nb_frags; j++) {
+			tx_pkts_burst[i+j] = init_packet(mbufpool,
+						vector->frags[j]->data,
+						vector->frags[j]->len);
+			if (tx_pkts_burst[i+j] == NULL) {
+				ret = -1;
+				printf("\n packed init failed\n");
+				goto out;
+			}
+		}
+	}
+
+	for (i = 0; i < burst_sz; i++) {
+		memcpy(&sa_data, vector->sa_data,
+				sizeof(struct ipsec_test_data));
+		/* Update SPI for every new SA */
+		sa_data.ipsec_xform.spi += i;
+		sa_data.ipsec_xform.direction =
+					RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
+		if (sa_data.aead) {
+			sess_conf_out.crypto_xform = &aead_out;
+		} else {
+			sess_conf_out.crypto_xform = &cipher_out;
+			sess_conf_out.crypto_xform->next = &auth_out;
+		}
+
+		/* Create Inline IPsec outbound session. */
+		ret = create_inline_ipsec_session(&sa_data, port_id,
+				&out_ses[i], &ctx, &ol_flags, flags,
+				&sess_conf_out);
+		if (ret) {
+			printf("\nInline outbound session create failed\n");
+			goto out;
+		}
+	}
+
+	j = 0;
+	for (i = 0; i < nb_tx; i++) {
+		if (ol_flags & RTE_SECURITY_TX_OLOAD_NEED_MDATA)
+			rte_security_set_pkt_metadata(ctx,
+				out_ses[j], tx_pkts_burst[i], NULL);
+		tx_pkts_burst[i]->ol_flags |= RTE_MBUF_F_TX_SEC_OFFLOAD;
+
+		/* Move to next SA after nb_frags */
+		if ((i + 1) % vector->nb_frags == 0)
+			j++;
+	}
+
+	for (i = 0; i < burst_sz; i++) {
+		memcpy(&sa_data, vector->sa_data,
+				sizeof(struct ipsec_test_data));
+		/* Update SPI for every new SA */
+		sa_data.ipsec_xform.spi += i;
+		sa_data.ipsec_xform.direction =
+					RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+
+		if (sa_data.aead) {
+			sess_conf_in.crypto_xform = &aead_in;
+		} else {
+			sess_conf_in.crypto_xform = &auth_in;
+			sess_conf_in.crypto_xform->next = &cipher_in;
+		}
+		/* Create Inline IPsec inbound session. */
+		ret = create_inline_ipsec_session(&sa_data, port_id, &in_ses[i],
+				&ctx, &ol_flags, flags, &sess_conf_in);
+		if (ret) {
+			printf("\nInline inbound session create failed\n");
+			goto out;
+		}
+	}
+
+	/* Retrieve reassembly dynfield offset if available */
+	if (ip_reassembly_dynfield_offset < 0 && vector->nb_frags > 1)
+		ip_reassembly_dynfield_offset = rte_mbuf_dynfield_lookup(
+				RTE_MBUF_DYNFIELD_IP_REASSEMBLY_NAME, NULL);
+
+
+	ret = create_default_flow(port_id);
+	if (ret)
+		goto out;
+
+	nb_sent = rte_eth_tx_burst(port_id, 0, tx_pkts_burst, nb_tx);
+	if (nb_sent != nb_tx) {
+		ret = -1;
+		printf("\nFailed to tx %u pkts", nb_tx);
+		goto out;
+	}
+
+	rte_delay_ms(1);
+
+	/* Retry few times before giving up */
+	nb_rx = 0;
+	j = 0;
+	do {
+		nb_rx += rte_eth_rx_burst(port_id, 0, &rx_pkts_burst[nb_rx],
+					  nb_tx - nb_rx);
+		j++;
+		if (nb_rx >= nb_tx)
+			break;
+		rte_delay_ms(1);
+	} while (j < 5 || !nb_rx);
+
+	/* Check for minimum number of Rx packets expected */
+	if ((vector->nb_frags == 1 && nb_rx != nb_tx) ||
+	    (vector->nb_frags > 1 && nb_rx < burst_sz)) {
+		printf("\nreceived less Rx pkts(%u) pkts\n", nb_rx);
+		ret = TEST_FAILED;
+		goto out;
+	}
+
+	for (i = 0; i < nb_rx; i++) {
+		if (vector->nb_frags > 1 &&
+		    is_ip_reassembly_incomplete(rx_pkts_burst[i])) {
+			ret = get_and_verify_incomplete_frags(rx_pkts_burst[i],
+							      vector);
+			if (ret != TEST_SUCCESS)
+				break;
+			continue;
+		}
+
+		if (rx_pkts_burst[i]->ol_flags &
+		    RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED ||
+		    !(rx_pkts_burst[i]->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD)) {
+			printf("\nsecurity offload failed\n");
+			ret = TEST_FAILED;
+			break;
+		}
+
+		if (vector->full_pkt->len + RTE_ETHER_HDR_LEN !=
+				rx_pkts_burst[i]->pkt_len) {
+			printf("\nreassembled/decrypted packet length mismatch\n");
+			ret = TEST_FAILED;
+			break;
+		}
+		rte_pktmbuf_adj(rx_pkts_burst[i], RTE_ETHER_HDR_LEN);
+		ret = compare_pkt_data(rx_pkts_burst[i],
+				       vector->full_pkt->data,
+				       vector->full_pkt->len);
+		if (ret != TEST_SUCCESS)
+			break;
+	}
+
+out:
+	destroy_default_flow(port_id);
+
+	/* Clear session data. */
+	for (i = 0; i < burst_sz; i++) {
+		if (out_ses[i])
+			rte_security_session_destroy(ctx, out_ses[i]);
+		if (in_ses[i])
+			rte_security_session_destroy(ctx, in_ses[i]);
+	}
+
+	for (i = nb_sent; i < nb_tx; i++)
+		free_mbuf(tx_pkts_burst[i]);
+	for (i = 0; i < nb_rx; i++)
+		free_mbuf(rx_pkts_burst[i]);
+	return ret;
+}
+
 static int
 test_ipsec_inline_proto_process(struct ipsec_test_data *td,
 		struct ipsec_test_data *res_d,
@@ -779,6 +1127,7 @@  ut_setup_inline_ipsec(void)
 static void
 ut_teardown_inline_ipsec(void)
 {
+	struct rte_eth_ip_reassembly_params reass_conf = {0};
 	uint16_t portid;
 	int ret;
 
@@ -788,6 +1137,9 @@  ut_teardown_inline_ipsec(void)
 		if (ret != 0)
 			printf("rte_eth_dev_stop: err=%s, port=%u\n",
 			       rte_strerror(-ret), portid);
+
+		/* Clear reassembly configuration */
+		rte_eth_ip_reassembly_conf_set(portid, &reass_conf);
 	}
 }
 
@@ -890,6 +1242,36 @@  inline_ipsec_testsuite_teardown(void)
 	}
 }
 
+static int
+test_inline_ip_reassembly(const void *testdata)
+{
+	struct reassembly_vector reassembly_td = {0};
+	const struct reassembly_vector *td = testdata;
+	struct ip_reassembly_test_packet full_pkt;
+	struct ip_reassembly_test_packet frags[MAX_FRAGS];
+	struct ipsec_test_flags flags = {0};
+	int i = 0;
+
+	reassembly_td.sa_data = td->sa_data;
+	reassembly_td.nb_frags = td->nb_frags;
+	reassembly_td.burst = td->burst;
+
+	memcpy(&full_pkt, td->full_pkt,
+			sizeof(struct ip_reassembly_test_packet));
+	reassembly_td.full_pkt = &full_pkt;
+
+	test_vector_payload_populate(reassembly_td.full_pkt, true);
+	for (; i < reassembly_td.nb_frags; i++) {
+		memcpy(&frags[i], td->frags[i],
+			sizeof(struct ip_reassembly_test_packet));
+		reassembly_td.frags[i] = &frags[i];
+		test_vector_payload_populate(reassembly_td.frags[i],
+				(i == 0) ? true : false);
+	}
+
+	return test_ipsec_with_reassembly(&reassembly_td, &flags);
+}
+
 static int
 test_ipsec_inline_proto_known_vec(const void *test_data)
 {
@@ -1036,7 +1418,46 @@  static struct unit_test_suite inline_ipsec_testsuite  = {
 			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
 			test_ipsec_inline_proto_display_list),
 
-
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv4 Reassembly with 2 fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv4_2frag_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv6 Reassembly with 2 fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv6_2frag_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv4 Reassembly with 4 fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv4_4frag_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv6 Reassembly with 4 fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv6_4frag_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv4 Reassembly with 5 fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv4_5frag_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv6 Reassembly with 5 fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv6_5frag_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv4 Reassembly with incomplete fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv4_incomplete_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv4 Reassembly with overlapping fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv4_overlap_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv4 Reassembly with out of order fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv4_out_of_order_vector),
+		TEST_CASE_NAMED_WITH_DATA(
+			"IPv4 Reassembly with burst of 4 fragments",
+			ut_setup_inline_ipsec, ut_teardown_inline_ipsec,
+			test_inline_ip_reassembly, &ipv4_4frag_burst_vector),
 
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	},
diff --git a/app/test/test_security_inline_proto_vectors.h b/app/test/test_security_inline_proto_vectors.h
index d1074da36a..c18965d80f 100644
--- a/app/test/test_security_inline_proto_vectors.h
+++ b/app/test/test_security_inline_proto_vectors.h
@@ -17,4 +17,688 @@  uint8_t dummy_ipv6_eth_hdr[] = {
 		0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x86, 0xdd,
 };
 
+#define MAX_FRAG_LEN		 1500
+#define MAX_FRAGS		 6
+#define MAX_PKT_LEN		 (MAX_FRAG_LEN * MAX_FRAGS)
+
+struct ip_reassembly_test_packet {
+	uint32_t len;
+	uint32_t l4_offset;
+	uint8_t data[MAX_PKT_LEN];
+};
+
+struct reassembly_vector {
+	/* input/output text in struct ipsec_test_data are not used */
+	struct ipsec_test_data *sa_data;
+	struct ip_reassembly_test_packet *full_pkt;
+	struct ip_reassembly_test_packet *frags[MAX_FRAGS];
+	uint16_t nb_frags;
+	bool burst;
+};
+
+/* The source file includes below test vectors */
+/* IPv6:
+ *
+ *	1) pkt_ipv6_udp_p1
+ *		pkt_ipv6_udp_p1_f1
+ *		pkt_ipv6_udp_p1_f2
+ *
+ *	2) pkt_ipv6_udp_p2
+ *		pkt_ipv6_udp_p2_f1
+ *		pkt_ipv6_udp_p2_f2
+ *		pkt_ipv6_udp_p2_f3
+ *		pkt_ipv6_udp_p2_f4
+ *
+ *	3) pkt_ipv6_udp_p3
+ *		pkt_ipv6_udp_p3_f1
+ *		pkt_ipv6_udp_p3_f2
+ *		pkt_ipv6_udp_p3_f3
+ *		pkt_ipv6_udp_p3_f4
+ *		pkt_ipv6_udp_p3_f5
+ */
+
+/* IPv4:
+ *
+ *	1) pkt_ipv4_udp_p1
+ *		pkt_ipv4_udp_p1_f1
+ *		pkt_ipv4_udp_p1_f2
+ *
+ *	2) pkt_ipv4_udp_p2
+ *		pkt_ipv4_udp_p2_f1
+ *		pkt_ipv4_udp_p2_f2
+ *		pkt_ipv4_udp_p2_f3
+ *		pkt_ipv4_udp_p2_f4
+ *
+ *	3) pkt_ipv4_udp_p3
+ *		pkt_ipv4_udp_p3_f1
+ *		pkt_ipv4_udp_p3_f2
+ *		pkt_ipv4_udp_p3_f3
+ *		pkt_ipv4_udp_p3_f4
+ *		pkt_ipv4_udp_p3_f5
+ */
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p1 = {
+	.len = 1500,
+	.l4_offset = 40,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0xb4, 0x2C, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x05, 0xb4, 0x2b, 0xe8,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p1_f1 = {
+	.len = 1384,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0x40, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x00, 0x01, 0x5c, 0x92, 0xac, 0xf1,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x05, 0xb4, 0x2b, 0xe8,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p1_f2 = {
+	.len = 172,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x00, 0x84, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x05, 0x38, 0x5c, 0x92, 0xac, 0xf1,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p2 = {
+	.len = 4482,
+	.l4_offset = 40,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x11, 0x5a, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x11, 0x5a, 0x8a, 0x11,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p2_f1 = {
+	.len = 1384,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0x40, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x00, 0x01, 0x64, 0x6c, 0x68, 0x9f,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x11, 0x5a, 0x8a, 0x11,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p2_f2 = {
+	.len = 1384,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0x40, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x05, 0x39, 0x64, 0x6c, 0x68, 0x9f,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p2_f3 = {
+	.len = 1384,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0x40, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x0a, 0x71, 0x64, 0x6c, 0x68, 0x9f,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p2_f4 = {
+	.len = 482,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x01, 0xba, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x0f, 0xa8, 0x64, 0x6c, 0x68, 0x9f,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p3 = {
+	.len = 5782,
+	.l4_offset = 40,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x16, 0x6e, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x16, 0x6e, 0x2f, 0x99,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p3_f1 = {
+	.len = 1384,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0x40, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x00, 0x01, 0x65, 0xcf, 0x5a, 0xae,
+
+		/* UDP */
+		0x80, 0x00, 0x27, 0x10, 0x16, 0x6e, 0x2f, 0x99,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p3_f2 = {
+	.len = 1384,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0x40, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x05, 0x39, 0x65, 0xcf, 0x5a, 0xae,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p3_f3 = {
+	.len = 1384,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0x40, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x0a, 0x71, 0x65, 0xcf, 0x5a, 0xae,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p3_f4 = {
+	.len = 1384,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x05, 0x40, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x0f, 0xa9, 0x65, 0xcf, 0x5a, 0xae,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv6_udp_p3_f5 = {
+	.len = 446,
+	.l4_offset = 48,
+	.data = {
+		/* IP */
+		0x60, 0x00, 0x00, 0x00, 0x01, 0x96, 0x2c, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x02,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x02,
+		0x11, 0x00, 0x14, 0xe0, 0x65, 0xcf, 0x5a, 0xae,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p1 = {
+	.len = 1500,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0xdc, 0x00, 0x01, 0x00, 0x00,
+		0x40, 0x11, 0x66, 0x0d, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x05, 0xc8, 0xb8, 0x4c,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p1_f1 = {
+	.len = 1420,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0x8c, 0x00, 0x01, 0x20, 0x00,
+		0x40, 0x11, 0x46, 0x5d, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x05, 0xc8, 0xb8, 0x4c,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p1_f2 = {
+	.len = 100,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x00, 0x64, 0x00, 0x01, 0x00, 0xaf,
+		0x40, 0x11, 0x6a, 0xd6, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p2 = {
+	.len = 4482,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x11, 0x82, 0x00, 0x02, 0x00, 0x00,
+		0x40, 0x11, 0x5a, 0x66, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x11, 0x6e, 0x16, 0x76,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p2_f1 = {
+	.len = 1420,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0x8c, 0x00, 0x02, 0x20, 0x00,
+		0x40, 0x11, 0x46, 0x5c, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x11, 0x6e, 0x16, 0x76,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p2_f2 = {
+	.len = 1420,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0x8c, 0x00, 0x02, 0x20, 0xaf,
+		0x40, 0x11, 0x45, 0xad, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p2_f3 = {
+	.len = 1420,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0x8c, 0x00, 0x02, 0x21, 0x5e,
+		0x40, 0x11, 0x44, 0xfe, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p2_f4 = {
+	.len = 282,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x01, 0x1a, 0x00, 0x02, 0x02, 0x0d,
+		0x40, 0x11, 0x68, 0xc1, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p3 = {
+	.len = 5782,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x16, 0x96, 0x00, 0x03, 0x00, 0x00,
+		0x40, 0x11, 0x55, 0x51, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x08, 0x00, 0x27, 0x10, 0x16, 0x82, 0xbb, 0xfd,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p3_f1 = {
+	.len = 1420,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0x8c, 0x00, 0x03, 0x20, 0x00,
+		0x40, 0x11, 0x46, 0x5b, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+
+		/* UDP */
+		0x80, 0x00, 0x27, 0x10, 0x16, 0x82, 0xbb, 0xfd,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p3_f2 = {
+	.len = 1420,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0x8c, 0x00, 0x03, 0x20, 0xaf,
+		0x40, 0x11, 0x45, 0xac, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p3_f3 = {
+	.len = 1420,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0x8c, 0x00, 0x03, 0x21, 0x5e,
+		0x40, 0x11, 0x44, 0xfd, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p3_f4 = {
+	.len = 1420,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x05, 0x8c, 0x00, 0x03, 0x22, 0x0d,
+		0x40, 0x11, 0x44, 0x4e, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+	},
+};
+
+struct ip_reassembly_test_packet pkt_ipv4_udp_p3_f5 = {
+	.len = 182,
+	.l4_offset = 20,
+	.data = {
+		/* IP */
+		0x45, 0x00, 0x00, 0xb6, 0x00, 0x03, 0x02, 0xbc,
+		0x40, 0x11, 0x68, 0x75, 0x0d, 0x00, 0x00, 0x02,
+		0x02, 0x00, 0x00, 0x02,
+	},
+};
+
+static inline void
+test_vector_payload_populate(struct ip_reassembly_test_packet *pkt,
+		bool first_frag)
+{
+	uint32_t i = pkt->l4_offset;
+
+	/**
+	 * For non-fragmented packets and first frag, skip 8 bytes from
+	 * l4_offset for UDP header.
+	 */
+	if (first_frag)
+		i += 8;
+
+	for (; i < pkt->len; i++)
+		pkt->data[i] = 0x58;
+}
+
+struct ipsec_test_data conf_aes_128_gcm = {
+	.key = {
+		.data = {
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+			0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+		},
+	},
+
+	.salt = {
+		.data = {
+			0xca, 0xfe, 0xba, 0xbe
+		},
+		.len = 4,
+	},
+
+	.iv = {
+		.data = {
+			0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88
+		},
+	},
+
+	.ipsec_xform = {
+		.spi = 0xa5f8,
+		.salt = 0xbebafeca,
+		.options.esn = 0,
+		.options.udp_encap = 0,
+		.options.copy_dscp = 0,
+		.options.copy_flabel = 0,
+		.options.copy_df = 0,
+		.options.dec_ttl = 0,
+		.options.ecn = 0,
+		.options.stats = 0,
+		.options.tunnel_hdr_verify = 0,
+		.options.ip_csum_enable = 0,
+		.options.l4_csum_enable = 0,
+		.options.ip_reassembly_en = 1,
+		.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+		.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+		.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+		.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4,
+		.replay_win_sz = 0,
+	},
+
+	.aead = true,
+
+	.xform = {
+		.aead = {
+			.next = NULL,
+			.type = RTE_CRYPTO_SYM_XFORM_AEAD,
+			.aead = {
+				.op = RTE_CRYPTO_AEAD_OP_ENCRYPT,
+				.algo = RTE_CRYPTO_AEAD_AES_GCM,
+				.key.length = 16,
+				.iv.length = 12,
+				.iv.offset = 0,
+				.digest_length = 16,
+				.aad_length = 12,
+			},
+		},
+	},
+};
+
+struct ipsec_test_data conf_aes_128_gcm_v6_tunnel = {
+	.key = {
+		.data = {
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+			0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+		},
+	},
+
+	.salt = {
+		.data = {
+			0xca, 0xfe, 0xba, 0xbe
+		},
+		.len = 4,
+	},
+
+	.iv = {
+		.data = {
+			0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88
+		},
+	},
+
+	.ipsec_xform = {
+		.spi = 0xa5f8,
+		.salt = 0xbebafeca,
+		.options.esn = 0,
+		.options.udp_encap = 0,
+		.options.copy_dscp = 0,
+		.options.copy_flabel = 0,
+		.options.copy_df = 0,
+		.options.dec_ttl = 0,
+		.options.ecn = 0,
+		.options.stats = 0,
+		.options.tunnel_hdr_verify = 0,
+		.options.ip_csum_enable = 0,
+		.options.l4_csum_enable = 0,
+		.options.ip_reassembly_en = 1,
+		.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+		.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+		.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+		.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4,
+		.replay_win_sz = 0,
+	},
+
+	.aead = true,
+
+	.xform = {
+		.aead = {
+			.next = NULL,
+			.type = RTE_CRYPTO_SYM_XFORM_AEAD,
+			.aead = {
+				.op = RTE_CRYPTO_AEAD_OP_ENCRYPT,
+				.algo = RTE_CRYPTO_AEAD_AES_GCM,
+				.key.length = 16,
+				.iv.length = 12,
+				.iv.offset = 0,
+				.digest_length = 16,
+				.aad_length = 12,
+			},
+		},
+	},
+};
+
+const struct reassembly_vector ipv4_2frag_vector = {
+	.sa_data = &conf_aes_128_gcm,
+	.full_pkt = &pkt_ipv4_udp_p1,
+	.frags[0] = &pkt_ipv4_udp_p1_f1,
+	.frags[1] = &pkt_ipv4_udp_p1_f2,
+	.nb_frags = 2,
+	.burst = false,
+};
+
+const struct reassembly_vector ipv6_2frag_vector = {
+	.sa_data = &conf_aes_128_gcm_v6_tunnel,
+	.full_pkt = &pkt_ipv6_udp_p1,
+	.frags[0] = &pkt_ipv6_udp_p1_f1,
+	.frags[1] = &pkt_ipv6_udp_p1_f2,
+	.nb_frags = 2,
+	.burst = false,
+};
+
+const struct reassembly_vector ipv4_4frag_vector = {
+	.sa_data = &conf_aes_128_gcm,
+	.full_pkt = &pkt_ipv4_udp_p2,
+	.frags[0] = &pkt_ipv4_udp_p2_f1,
+	.frags[1] = &pkt_ipv4_udp_p2_f2,
+	.frags[2] = &pkt_ipv4_udp_p2_f3,
+	.frags[3] = &pkt_ipv4_udp_p2_f4,
+	.nb_frags = 4,
+	.burst = false,
+};
+
+const struct reassembly_vector ipv6_4frag_vector = {
+	.sa_data = &conf_aes_128_gcm_v6_tunnel,
+	.full_pkt = &pkt_ipv6_udp_p2,
+	.frags[0] = &pkt_ipv6_udp_p2_f1,
+	.frags[1] = &pkt_ipv6_udp_p2_f2,
+	.frags[2] = &pkt_ipv6_udp_p2_f3,
+	.frags[3] = &pkt_ipv6_udp_p2_f4,
+	.nb_frags = 4,
+	.burst = false,
+};
+const struct reassembly_vector ipv4_5frag_vector = {
+	.sa_data = &conf_aes_128_gcm,
+	.full_pkt = &pkt_ipv4_udp_p3,
+	.frags[0] = &pkt_ipv4_udp_p3_f1,
+	.frags[1] = &pkt_ipv4_udp_p3_f2,
+	.frags[2] = &pkt_ipv4_udp_p3_f3,
+	.frags[3] = &pkt_ipv4_udp_p3_f4,
+	.frags[4] = &pkt_ipv4_udp_p3_f5,
+	.nb_frags = 5,
+	.burst = false,
+};
+const struct reassembly_vector ipv6_5frag_vector = {
+	.sa_data = &conf_aes_128_gcm_v6_tunnel,
+	.full_pkt = &pkt_ipv6_udp_p3,
+	.frags[0] = &pkt_ipv6_udp_p3_f1,
+	.frags[1] = &pkt_ipv6_udp_p3_f2,
+	.frags[2] = &pkt_ipv6_udp_p3_f3,
+	.frags[3] = &pkt_ipv6_udp_p3_f4,
+	.frags[4] = &pkt_ipv6_udp_p3_f5,
+	.nb_frags = 5,
+	.burst = false,
+};
+/* Negative test cases. */
+const struct reassembly_vector ipv4_incomplete_vector = {
+	.sa_data = &conf_aes_128_gcm,
+	.full_pkt = &pkt_ipv4_udp_p2,
+	.frags[0] = &pkt_ipv4_udp_p2_f1,
+	.frags[1] = &pkt_ipv4_udp_p2_f2,
+	.nb_frags = 2,
+	.burst = false,
+};
+const struct reassembly_vector ipv4_overlap_vector = {
+	.sa_data = &conf_aes_128_gcm,
+	.full_pkt = &pkt_ipv4_udp_p1,
+	.frags[0] = &pkt_ipv4_udp_p1_f1,
+	.frags[1] = &pkt_ipv4_udp_p1_f1, /* Overlap */
+	.frags[2] = &pkt_ipv4_udp_p1_f2,
+	.nb_frags = 3,
+	.burst = false,
+};
+const struct reassembly_vector ipv4_out_of_order_vector = {
+	.sa_data = &conf_aes_128_gcm,
+	.full_pkt = &pkt_ipv4_udp_p2,
+	.frags[0] = &pkt_ipv4_udp_p2_f1,
+	.frags[1] = &pkt_ipv4_udp_p2_f3,
+	.frags[2] = &pkt_ipv4_udp_p2_f4,
+	.frags[3] = &pkt_ipv4_udp_p2_f2, /* out of order */
+	.nb_frags = 4,
+	.burst = false,
+};
+const struct reassembly_vector ipv4_4frag_burst_vector = {
+	.sa_data = &conf_aes_128_gcm,
+	.full_pkt = &pkt_ipv4_udp_p2,
+	.frags[0] = &pkt_ipv4_udp_p2_f1,
+	.frags[1] = &pkt_ipv4_udp_p2_f2,
+	.frags[2] = &pkt_ipv4_udp_p2_f3,
+	.frags[3] = &pkt_ipv4_udp_p2_f4,
+	.nb_frags = 4,
+	.burst = true,
+};
+
 #endif