Support testing inline reassembly with multi seg in
inline ipsec multi seg test command.
Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
---
app/test/test_security_inline_proto.c | 17 ++++--
app/test/test_security_inline_proto_vectors.h | 53 ++++++++++++++++++-
2 files changed, 64 insertions(+), 6 deletions(-)
@@ -1624,6 +1624,8 @@ inline_ipsec_testsuite_setup(void)
* Without SG mode, default value is picked.
*/
plaintext_len = local_port_conf.rxmode.mtu - 256;
+ } else {
+ plaintext_len = 0;
}
return 0;
@@ -1934,6 +1936,7 @@ test_inline_ip_reassembly(const void *testdata)
const struct reassembly_vector *td = testdata;
struct ip_reassembly_test_packet full_pkt;
struct ip_reassembly_test_packet frags[MAX_FRAGS];
+ uint16_t extra_data, extra_data_sum = 0;
struct ipsec_test_flags flags = {0};
int i = 0;
@@ -1945,14 +1948,22 @@ test_inline_ip_reassembly(const void *testdata)
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];
+
+ /* Add extra data for multi-seg test on all fragments except last one */
+ extra_data = 0;
+ if (plaintext_len && reassembly_td.frags[i]->len < plaintext_len &&
+ (i != reassembly_td.nb_frags - 1))
+ extra_data = ((plaintext_len - reassembly_td.frags[i]->len) & ~0x7ULL);
+
test_vector_payload_populate(reassembly_td.frags[i],
- (i == 0) ? true : false);
+ (i == 0) ? true : false, extra_data, extra_data_sum);
+ extra_data_sum += extra_data;
}
+ test_vector_payload_populate(reassembly_td.full_pkt, true, extra_data_sum, 0);
return test_ipsec_with_reassembly(&reassembly_td, &flags);
}
@@ -2667,8 +2678,6 @@ test_ipsec_inline_proto_pkt_esn_antireplay4096(const void *test_data)
return test_ipsec_inline_proto_pkt_esn_antireplay(test_data, 4096);
}
-
-
static struct unit_test_suite inline_ipsec_testsuite = {
.suite_name = "Inline IPsec Ethernet Device Unit Test Suite",
.unit_test_cases = {
@@ -17,7 +17,7 @@ uint8_t dummy_ipv6_eth_hdr[] = {
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x86, 0xdd,
};
-#define MAX_FRAG_LEN 1500
+#define MAX_FRAG_LEN IPSEC_TEXT_MAX_LEN
#define MAX_FRAGS 6
#define MAX_PKT_LEN (MAX_FRAG_LEN * MAX_FRAGS)
@@ -468,9 +468,13 @@ struct ip_reassembly_test_packet pkt_ipv4_udp_p3_f5 = {
static inline void
test_vector_payload_populate(struct ip_reassembly_test_packet *pkt,
- bool first_frag)
+ bool first_frag, uint16_t extra_data, uint16_t extra_data_sum)
{
+ bool is_ipv6 = ((pkt->data[0] >> 4) == 0x6);
uint32_t i = pkt->l4_offset;
+ uint16_t len, off;
+ size_t ext_len = 0;
+ int proto;
/**
* For non-fragmented packets and first frag, skip 8 bytes from
@@ -479,6 +483,51 @@ test_vector_payload_populate(struct ip_reassembly_test_packet *pkt,
if (first_frag)
i += 8;
+ /* Fixup header and checksum */
+ if (extra_data || extra_data_sum) {
+ if (is_ipv6) {
+ struct rte_ipv6_hdr *hdr = (struct rte_ipv6_hdr *)pkt->data;
+ struct rte_ipv6_fragment_ext *frag_ext;
+ uint8_t *p = pkt->data;
+ uint16_t old_off;
+
+ len = rte_be_to_cpu_16(hdr->payload_len) + extra_data;
+ hdr->payload_len = rte_cpu_to_be_16(len);
+
+ /* Find frag extension header to add to frag offset */
+ if (extra_data_sum) {
+ proto = hdr->proto;
+ p += sizeof(struct rte_ipv6_hdr);
+ while (proto != IPPROTO_FRAGMENT &&
+ (proto = rte_ipv6_get_next_ext(p, proto, &ext_len) >= 0))
+ p += ext_len;
+
+ /* Found fragment header, update the frag offset */
+ if (proto == IPPROTO_FRAGMENT) {
+ frag_ext = (struct rte_ipv6_fragment_ext *)p;
+ old_off = rte_be_to_cpu_16(frag_ext->frag_data);
+ off = old_off & 0xFFF8;
+ off += extra_data_sum;
+ frag_ext->frag_data = rte_cpu_to_be_16(off |
+ (old_off & 0x7));
+ }
+ }
+ } else {
+ struct rte_ipv4_hdr *hdr = (struct rte_ipv4_hdr *)pkt->data;
+ uint16_t old_off = rte_be_to_cpu_16(hdr->fragment_offset);
+
+ len = rte_be_to_cpu_16(hdr->total_length) + extra_data;
+ off = old_off & 0x1FFF;
+ off += (extra_data_sum >> 3);
+
+ hdr->total_length = rte_cpu_to_be_16(len);
+ hdr->fragment_offset = rte_cpu_to_be_16(off | (old_off & 0xe000));
+ hdr->hdr_checksum = 0;
+ hdr->hdr_checksum = rte_ipv4_cksum(hdr);
+ }
+ pkt->len += extra_data;
+ }
+
for (; i < pkt->len; i++)
pkt->data[i] = 0x58;
}