This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, master has been updated via 8caae505c35444706cff8815c41821d80e791403 (commit) via 4b6787c84e020c350a03ec47d12e1ef68ddb6300 (commit) via 4142652b8eb397963bec48610bdb9ab6599e65fb (commit) via 60777ba4309911df0780bd8de6d96524bc2ca03c (commit) via b2632ac253a3b9f5ba7a4174acf6abe295ec3550 (commit) via 79f5c103310c36dc213a552b9534f68ce8df1132 (commit) via 2c99a9dc1978c9178e711d264aaaca2bc4702352 (commit) from 88ba35773c76c871a222fe48a0dac05765c39936 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 8caae505c35444706cff8815c41821d80e791403 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Wed Apr 11 17:29:19 2018 +0300
validation: ipsec: validate outbound checksumming support
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Petri Savolainen petri.savolainen@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/validation/api/ipsec/ipsec.c b/test/validation/api/ipsec/ipsec.c index 91a66d0b..31a6f9b5 100644 --- a/test/validation/api/ipsec/ipsec.c +++ b/test/validation/api/ipsec/ipsec.c @@ -938,6 +938,7 @@ int ipsec_config(odp_instance_t ODP_UNUSED inst) odp_ipsec_config_init(&ipsec_config); ipsec_config.inbound_mode = suite_context.inbound_op_mode; ipsec_config.outbound_mode = suite_context.outbound_op_mode; + ipsec_config.outbound.all_chksum = ~0; ipsec_config.inbound.default_queue = suite_context.queue; ipsec_config.inbound.parse_level = ODP_PROTO_LAYER_ALL; ipsec_config.inbound.chksums.all_chksum = ~0; diff --git a/test/validation/api/ipsec/ipsec_test_out.c b/test/validation/api/ipsec/ipsec_test_out.c index 5089dfa7..59c631b5 100644 --- a/test/validation/api/ipsec/ipsec_test_out.c +++ b/test/validation/api/ipsec/ipsec_test_out.c @@ -1155,6 +1155,36 @@ static void test_out_dummy_esp_null_sha256_tun_ipv6(void) ipsec_sa_destroy(sa); }
+static void test_out_ipv4_udp_esp_null_sha256(void) +{ + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + ipsec_sa_param_fill(¶m, + false, false, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256, + NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_ipv4_udp, + .out_pkt = 1, + .out = { + { .status.warn.all = 0, + .status.error.all = 0, + .pkt_out = &pkt_ipv4_udp_esp_null_sha256 }, + }, + }; + + ipsec_check_out_one(&test, sa); + + ipsec_sa_destroy(sa); +} + static void ipsec_test_capability(void) { odp_ipsec_capability_t capa; @@ -1218,5 +1248,7 @@ odp_testinfo_t ipsec_out_suite[] = { ipsec_check_esp_null_sha256), ODP_TEST_INFO_CONDITIONAL(test_out_dummy_esp_null_sha256_tun_ipv6, ipsec_check_esp_null_sha256), + ODP_TEST_INFO_CONDITIONAL(test_out_ipv4_udp_esp_null_sha256, + ipsec_check_esp_null_sha256), ODP_TEST_INFO_NULL, }; diff --git a/test/validation/api/ipsec/test_vectors.h b/test/validation/api/ipsec/test_vectors.h index 0f133f01..289b8008 100644 --- a/test/validation/api/ipsec/test_vectors.h +++ b/test/validation/api/ipsec/test_vectors.h @@ -1883,4 +1883,63 @@ static const ipsec_test_packet pkt_test_nodata = { 0x0a, 0x0b, 0x0c, 0x0d, }, }; + +static const ipsec_test_packet pkt_ipv4_udp = { + .len = 76, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH - not a part of RFC, added for simplicity */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x08, 0x00, + + /* IP */ + 0x45, 0x00, 0x00, 0x3e, 0x69, 0x8f, 0x00, 0x00, + 0x80, 0x11, 0x00, 0x00, 0xc0, 0xa8, 0x01, 0x02, + 0xc0, 0xa8, 0x01, 0x01, + + /* UDP */ + 0x0a, 0x98, 0x00, 0x35, 0x00, 0x2a, 0x00, 0x00, + 0xb2, 0xd0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x73, 0x69, 0x70, + 0x09, 0x63, 0x79, 0x62, 0x65, 0x72, 0x63, 0x69, + 0x74, 0x79, 0x02, 0x64, 0x6b, 0x00, 0x00, 0x01, + 0x00, 0x01, + }, +}; + +static const ipsec_test_packet pkt_ipv4_udp_esp_null_sha256 = { + .len = 102, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH - not a part of RFC, added for simplicity */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x08, 0x00, + + /* IP */ + 0x45, 0x00, 0x00, 0x58, 0x69, 0x8f, 0x00, 0x00, + 0x80, 0x32, 0x4d, 0x91, 0xc0, 0xa8, 0x01, 0x02, + 0xc0, 0xa8, 0x01, 0x01, + + /* ESP */ + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + + /* UDP */ + 0x0a, 0x98, 0x00, 0x35, 0x00, 0x2a, 0x23, 0x43, + 0xb2, 0xd0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x73, 0x69, 0x70, + 0x09, 0x63, 0x79, 0x62, 0x65, 0x72, 0x63, 0x69, + 0x74, 0x79, 0x02, 0x64, 0x6b, 0x00, 0x00, 0x01, + 0x00, 0x01, + + /* ESP TRL */ + 0x00, 0x11, 0x2d, 0x4a, 0x06, 0x9f, 0x97, 0xcf, + 0xa3, 0x05, 0xea, 0x90, 0x7a, 0xf6, 0x6b, 0x0a, + 0x3f, 0xc7, + }, +}; + #endif
commit 4b6787c84e020c350a03ec47d12e1ef68ddb6300 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Wed Apr 11 17:28:46 2018 +0300
linux-gen: ipsec: implement outbound checksumming support
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Petri Savolainen petri.savolainen@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index 65f7361b..782cbf45 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -826,6 +826,7 @@ static int ipsec_out_tunnel_parse_ipv4(ipsec_state_t *state, state->out_tunnel.ip_tos = ipv4hdr->tos; state->out_tunnel.ip_df = _ODP_IPV4HDR_FLAGS_DONT_FRAG(flags); state->out_tunnel.ip_flabel = 0; + state->ip_next_hdr = ipv4hdr->proto;
return 0; } @@ -1295,6 +1296,41 @@ static void ipsec_out_ah_post(ipsec_state_t *state, odp_packet_t pkt) } }
+#define OL_TX_CHKSUM_PKT(_cfg, _proto, _ovr_set, _ovr) \ + (_proto && (_ovr_set ? _ovr : _cfg)) + +static void ipsec_out_checksums(odp_packet_t pkt, + ipsec_state_t *state) +{ + odp_bool_t ipv4_chksum_pkt, udp_chksum_pkt, tcp_chksum_pkt; + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + odp_ipsec_outbound_config_t outbound = ipsec_config.outbound; + + ipv4_chksum_pkt = OL_TX_CHKSUM_PKT(outbound.chksum.inner_ipv4, + state->is_ipv4, + pkt_hdr->p.flags.l3_chksum_set, + pkt_hdr->p.flags.l3_chksum); + udp_chksum_pkt = OL_TX_CHKSUM_PKT(outbound.chksum.inner_udp, + state->ip_next_hdr == + _ODP_IPPROTO_UDP, + pkt_hdr->p.flags.l4_chksum_set, + pkt_hdr->p.flags.l4_chksum); + tcp_chksum_pkt = OL_TX_CHKSUM_PKT(outbound.chksum.inner_tcp, + state->ip_next_hdr == + _ODP_IPPROTO_TCP, + pkt_hdr->p.flags.l4_chksum_set, + pkt_hdr->p.flags.l4_chksum); + + if (ipv4_chksum_pkt) + _odp_packet_ipv4_chksum_insert(pkt); + + if (tcp_chksum_pkt) + _odp_packet_tcp_chksum_insert(pkt); + + if (udp_chksum_pkt) + _odp_packet_udp_chksum_insert(pkt); +} + static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, odp_ipsec_sa_t sa, odp_packet_t *pkt_out, @@ -1354,6 +1390,9 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
if (state.ip_tot_len + state.ip_offset != odp_packet_len(pkt)) rc = -1; + + if (rc == 0) + ipsec_out_checksums(pkt, &state); } else { if (state.is_ipv4) rc = ipsec_out_tunnel_parse_ipv4(&state, ipsec_sa); @@ -1371,6 +1410,8 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, goto err; }
+ ipsec_out_checksums(pkt, &state); + if (ipsec_sa->tun_ipv4) rc = ipsec_out_tunnel_ipv4(&pkt, &state, ipsec_sa, opt->flag.ip_param ?
commit 4142652b8eb397963bec48610bdb9ab6599e65fb Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Sat Jan 13 05:13:03 2018 +0300
validation: ipsec: fix packet checksums
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Petri Savolainen petri.savolainen@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/validation/api/ipsec/ipsec.c b/test/validation/api/ipsec/ipsec.c index 7c82d85a..91a66d0b 100644 --- a/test/validation/api/ipsec/ipsec.c +++ b/test/validation/api/ipsec/ipsec.c @@ -940,6 +940,7 @@ int ipsec_config(odp_instance_t ODP_UNUSED inst) ipsec_config.outbound_mode = suite_context.outbound_op_mode; ipsec_config.inbound.default_queue = suite_context.queue; ipsec_config.inbound.parse_level = ODP_PROTO_LAYER_ALL; + ipsec_config.inbound.chksums.all_chksum = ~0;
if (ODP_IPSEC_OK != odp_ipsec_config(&ipsec_config)) return -1; diff --git a/test/validation/api/ipsec/test_vectors.h b/test/validation/api/ipsec/test_vectors.h index 5b357a16..0f133f01 100644 --- a/test/validation/api/ipsec/test_vectors.h +++ b/test/validation/api/ipsec/test_vectors.h @@ -269,7 +269,7 @@ static const ODP_UNUSED ipsec_test_packet pkt_ipv4_icmp_0_ah_sha256_1_bad1 = {
/* IP */ 0x45, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x33, 0xab, 0xd9, 0xc0, 0xa8, 0x6f, 0x02, + 0x40, 0x33, 0xab, 0xdb, 0xc0, 0xa8, 0x6f, 0x02, 0xc0, 0xa8, 0xde, 0x02,
/* AH */ @@ -669,7 +669,7 @@ static const ODP_UNUSED ipsec_test_packet pkt_ipv4_icmp_0_esp_aes_cbc_null_1 = {
/* IP */ 0x45, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x32, 0xab, 0xca, 0xc0, 0xa8, 0x6f, 0x02, + 0x40, 0x32, 0xab, 0xda, 0xc0, 0xa8, 0x6f, 0x02, 0xc0, 0xa8, 0xde, 0x02,
/* ESP */ @@ -1499,7 +1499,7 @@ static const ipsec_test_packet pkt_mcgrew_gcm_test_2_esp = {
/* IP - not a part of RFC, added for simplicity */ 0x45, 0x00, 0x00, 0x74, 0x69, 0x8f, 0x00, 0x00, - 0x80, 0x32, 0x4d, 0x76, 0xc0, 0xa8, 0x01, 0x02, + 0x80, 0x32, 0x4d, 0x75, 0xc0, 0xa8, 0x01, 0x02, 0xc0, 0xa8, 0x01, 0x01,
/* ESP */ @@ -1557,7 +1557,7 @@ static const ipsec_test_packet pkt_mcgrew_gcm_test_3_esp = {
/* IP - not a part of RFC, added for simplicity */ 0x45, 0x00, 0x00, 0x68, 0x69, 0x8f, 0x00, 0x00, - 0x80, 0x32, 0x4d, 0x82, 0xc0, 0xa8, 0x01, 0x02, + 0x80, 0x32, 0x4d, 0x81, 0xc0, 0xa8, 0x01, 0x02, 0xc0, 0xa8, 0x01, 0x01,
/* ESP */ @@ -1615,7 +1615,7 @@ static const ipsec_test_packet pkt_mcgrew_gcm_test_4_esp = {
/* IP - not a part of RFC, added for simplicity */ 0x45, 0x00, 0x00, 0x74, 0x69, 0x8f, 0x00, 0x00, - 0x80, 0x32, 0x4d, 0x76, 0xc0, 0xa8, 0x01, 0x02, + 0x80, 0x32, 0x4d, 0x75, 0xc0, 0xa8, 0x01, 0x02, 0xc0, 0xa8, 0x01, 0x01,
/* ESP */ @@ -1730,7 +1730,7 @@ static const ipsec_test_packet pkt_mcgrew_gcm_test_15_esp = {
/* IP - not a part of RFC, added for simplicity */ 0x45, 0x00, 0x00, 0x68, 0x69, 0x8f, 0x00, 0x00, - 0x80, 0x32, 0x4d, 0xb2, 0xc0, 0xa8, 0x01, 0x02, + 0x80, 0x32, 0x4d, 0x81, 0xc0, 0xa8, 0x01, 0x02, 0xc0, 0xa8, 0x01, 0x01,
/* ESP */
commit 60777ba4309911df0780bd8de6d96524bc2ca03c Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Apr 6 15:24:46 2018 +0300
validation: verify IPv4 and UDP checksum validation and generation
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Petri Savolainen petri.savolainen@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/validation/api/pktio/pktio.c b/test/validation/api/pktio/pktio.c index e82a9683..09367d4e 100644 --- a/test/validation/api/pktio/pktio.c +++ b/test/validation/api/pktio/pktio.c @@ -296,7 +296,7 @@ static uint32_t pktio_init_packet(odp_packet_t pkt) return pktio_pkt_set_seq(pkt); }
-static int pktio_fixup_checksums(odp_packet_t pkt) +static int pktio_zero_checksums(odp_packet_t pkt) { odph_ipv4hdr_t *ip; odph_udphdr_t *udp; @@ -312,8 +312,20 @@ static int pktio_fixup_checksums(odp_packet_t pkt) udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, &len);
ip->chksum = 0; - odph_ipv4_csum_update(pkt); udp->chksum = 0; + + return 0; +} + +static int pktio_fixup_checksums(odp_packet_t pkt) +{ + odph_udphdr_t *udp; + + pktio_zero_checksums(pkt); + + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); + + odph_ipv4_csum_update(pkt); udp->chksum = odph_ipv4_udp_chksum(pkt);
return 0; @@ -407,10 +419,14 @@ static int flush_input_queue(odp_pktio_t pktio, odp_pktin_mode_t imode) return 0; }
-static int create_packets(odp_packet_t pkt_tbl[], uint32_t pkt_seq[], int num, - odp_pktio_t pktio_src, odp_pktio_t pktio_dst) +static int create_packets_cs(odp_packet_t pkt_tbl[], + uint32_t pkt_seq[], + int num, + odp_pktio_t pktio_src, + odp_pktio_t pktio_dst, + odp_bool_t fix_cs) { - int i; + int i, ret;
for (i = 0; i < num; i++) { pkt_tbl[i] = odp_packet_alloc(default_pkt_pool, packet_len); @@ -425,7 +441,11 @@ static int create_packets(odp_packet_t pkt_tbl[], uint32_t pkt_seq[], int num,
pktio_pkt_set_macs(pkt_tbl[i], pktio_src, pktio_dst);
- if (pktio_fixup_checksums(pkt_tbl[i]) != 0) { + if (fix_cs) + ret = pktio_fixup_checksums(pkt_tbl[i]); + else + ret = pktio_zero_checksums(pkt_tbl[i]); + if (ret != 0) { odp_packet_free(pkt_tbl[i]); break; } @@ -434,6 +454,13 @@ static int create_packets(odp_packet_t pkt_tbl[], uint32_t pkt_seq[], int num, return i; }
+static int create_packets(odp_packet_t pkt_tbl[], uint32_t pkt_seq[], int num, + odp_pktio_t pktio_src, odp_pktio_t pktio_dst) +{ + return create_packets_cs(pkt_tbl, pkt_seq, num, pktio_src, pktio_dst, + true); +} + static int get_packets(pktio_info_t *pktio_rx, odp_packet_t pkt_tbl[], int num, txrx_mode_e mode) { @@ -1894,6 +1921,416 @@ static void pktio_test_pktin_ts(void) } }
+static void pktio_test_chksum(void (*config_fn)(odp_pktio_t, odp_pktio_t), + void (*prep_fn)(odp_packet_t pkt), + void (*test_fn)(odp_packet_t pkt)) +{ + odp_pktio_t pktio_tx, pktio_rx; + odp_pktio_t pktio[MAX_NUM_IFACES] = {ODP_PKTIO_INVALID}; + pktio_info_t pktio_rx_info; + odp_pktout_queue_t pktout_queue; + odp_packet_t pkt_tbl[TX_BATCH_LEN]; + uint32_t pkt_seq[TX_BATCH_LEN]; + int ret; + int i, num_rx; + + CU_ASSERT_FATAL(num_ifaces >= 1); + + /* Open and configure interfaces */ + for (i = 0; i < num_ifaces; ++i) { + pktio[i] = create_pktio(i, ODP_PKTIN_MODE_DIRECT, + ODP_PKTOUT_MODE_DIRECT); + CU_ASSERT_FATAL(pktio[i] != ODP_PKTIO_INVALID); + } + + pktio_tx = pktio[0]; + pktio_rx = (num_ifaces > 1) ? pktio[1] : pktio_tx; + pktio_rx_info.id = pktio_rx; + pktio_rx_info.inq = ODP_QUEUE_INVALID; + pktio_rx_info.in_mode = ODP_PKTIN_MODE_DIRECT; + + config_fn(pktio_tx, pktio_rx); + + for (i = 0; i < num_ifaces; ++i) { + CU_ASSERT_FATAL(odp_pktio_start(pktio[i]) == 0); + _pktio_wait_linkup(pktio[i]); + } + + ret = create_packets_cs(pkt_tbl, pkt_seq, TX_BATCH_LEN, pktio_tx, + pktio_rx, false); + CU_ASSERT_FATAL(ret == TX_BATCH_LEN); + + ret = odp_pktout_queue(pktio_tx, &pktout_queue, 1); + CU_ASSERT_FATAL(ret > 0); + + for (i = 0; i < TX_BATCH_LEN; i++) + if (prep_fn) + prep_fn(pkt_tbl[i]); + + send_packets(pktout_queue, pkt_tbl, TX_BATCH_LEN); + num_rx = wait_for_packets(&pktio_rx_info, pkt_tbl, pkt_seq, + TX_BATCH_LEN, TXRX_MODE_MULTI, + ODP_TIME_SEC_IN_NS); + CU_ASSERT(num_rx == TX_BATCH_LEN); + for (i = 0; i < num_rx; i++) { + test_fn(pkt_tbl[i]); + odp_packet_free(pkt_tbl[i]); + } + + for (i = 0; i < num_ifaces; i++) { + CU_ASSERT_FATAL(odp_pktio_stop(pktio[i]) == 0); + CU_ASSERT_FATAL(odp_pktio_close(pktio[i]) == 0); + } +} + +static int pktio_check_chksum_in_ipv4(void) +{ + odp_pktio_t pktio; + odp_pktio_capability_t capa; + odp_pktio_param_t pktio_param; + int idx = (num_ifaces == 1) ? 0 : 1; + int ret; + + odp_pktio_param_init(&pktio_param); + pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT; + + pktio = odp_pktio_open(iface_name[idx], pool[idx], &pktio_param); + if (pktio == ODP_PKTIO_INVALID) + return ODP_TEST_INACTIVE; + + ret = odp_pktio_capability(pktio, &capa); + (void)odp_pktio_close(pktio); + + if (ret < 0 || + !capa.config.pktin.bit.ipv4_chksum) + return ODP_TEST_INACTIVE; + + return ODP_TEST_ACTIVE; +} + +static void pktio_test_chksum_in_ipv4_config(odp_pktio_t pktio_tx ODP_UNUSED, + odp_pktio_t pktio_rx) +{ + odp_pktio_capability_t capa; + odp_pktio_config_t config; + + CU_ASSERT_FATAL(odp_pktio_capability(pktio_rx, &capa) == 0); + CU_ASSERT_FATAL(capa.config.pktin.bit.ipv4_chksum); + + odp_pktio_config_init(&config); + config.pktin.bit.ipv4_chksum = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_rx, &config) == 0); +} + +static void pktio_test_chksum_in_ipv4_prep(odp_packet_t pkt) +{ + odph_ipv4_csum_update(pkt); +} + +static void pktio_test_chksum_in_ipv4_test(odp_packet_t pkt) +{ + CU_ASSERT(odp_packet_l3_chksum_status(pkt) == ODP_PACKET_CHKSUM_OK); +} + +static void pktio_test_chksum_in_ipv4(void) +{ + pktio_test_chksum(pktio_test_chksum_in_ipv4_config, + pktio_test_chksum_in_ipv4_prep, + pktio_test_chksum_in_ipv4_test); +} + +static int pktio_check_chksum_in_udp(void) +{ + odp_pktio_t pktio; + odp_pktio_capability_t capa; + odp_pktio_param_t pktio_param; + int idx = (num_ifaces == 1) ? 0 : 1; + int ret; + + odp_pktio_param_init(&pktio_param); + pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT; + + pktio = odp_pktio_open(iface_name[idx], pool[idx], &pktio_param); + if (pktio == ODP_PKTIO_INVALID) + return ODP_TEST_INACTIVE; + + ret = odp_pktio_capability(pktio, &capa); + (void)odp_pktio_close(pktio); + + if (ret < 0 || + !capa.config.pktin.bit.udp_chksum) + return ODP_TEST_INACTIVE; + + return ODP_TEST_ACTIVE; +} + +static void pktio_test_chksum_in_udp_config(odp_pktio_t pktio_tx ODP_UNUSED, + odp_pktio_t pktio_rx) +{ + odp_pktio_capability_t capa; + odp_pktio_config_t config; + + CU_ASSERT_FATAL(odp_pktio_capability(pktio_rx, &capa) == 0); + CU_ASSERT_FATAL(capa.config.pktin.bit.udp_chksum); + + odp_pktio_config_init(&config); + config.pktin.bit.udp_chksum = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_rx, &config) == 0); +} + +static void pktio_test_chksum_in_udp_prep(odp_packet_t pkt) +{ + odp_packet_has_ipv4_set(pkt, 1); + odp_packet_has_udp_set(pkt, 1); + odph_ipv4_csum_update(pkt); + odph_udp_chksum_set(pkt); +} + +static void pktio_test_chksum_in_udp_test(odp_packet_t pkt) +{ + CU_ASSERT(odp_packet_l4_chksum_status(pkt) == ODP_PACKET_CHKSUM_OK); +} + +static void pktio_test_chksum_in_udp(void) +{ + pktio_test_chksum(pktio_test_chksum_in_udp_config, + pktio_test_chksum_in_udp_prep, + pktio_test_chksum_in_udp_test); +} + +static int pktio_check_chksum_out_ipv4(void) +{ + odp_pktio_t pktio; + odp_pktio_capability_t capa; + odp_pktio_param_t pktio_param; + int ret; + + odp_pktio_param_init(&pktio_param); + pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT; + + pktio = odp_pktio_open(iface_name[0], pool[0], &pktio_param); + if (pktio == ODP_PKTIO_INVALID) + return ODP_TEST_INACTIVE; + + ret = odp_pktio_capability(pktio, &capa); + (void)odp_pktio_close(pktio); + + if (ret < 0 || + !capa.config.pktout.bit.ipv4_chksum_ena || + !capa.config.pktout.bit.ipv4_chksum) + return ODP_TEST_INACTIVE; + + return ODP_TEST_ACTIVE; +} + +static void pktio_test_chksum_out_ipv4_config(odp_pktio_t pktio_tx, + odp_pktio_t pktio_rx ODP_UNUSED) +{ + odp_pktio_capability_t capa; + odp_pktio_config_t config; + + CU_ASSERT_FATAL(odp_pktio_capability(pktio_tx, &capa) == 0); + CU_ASSERT_FATAL(capa.config.pktout.bit.ipv4_chksum_ena); + CU_ASSERT_FATAL(capa.config.pktout.bit.ipv4_chksum); + + odp_pktio_config_init(&config); + config.pktout.bit.ipv4_chksum_ena = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_tx, &config) == 0); +} + +static void pktio_test_chksum_out_ipv4_test(odp_packet_t pkt) +{ + odph_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL); + + CU_ASSERT(ip != NULL); + if (ip != NULL) + CU_ASSERT(ip->chksum != 0); +} + +static void pktio_test_chksum_out_ipv4_no_ovr_prep(odp_packet_t pkt) +{ + odp_packet_l3_chksum_insert(pkt, false); +} + +static void pktio_test_chksum_out_ipv4_no_ovr_test(odp_packet_t pkt) +{ + odph_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL); + + CU_ASSERT(ip != NULL); + if (ip != NULL) + CU_ASSERT(ip->chksum == 0); +} + +static void pktio_test_chksum_out_ipv4_no_ovr(void) +{ + pktio_test_chksum(pktio_test_chksum_out_ipv4_config, + pktio_test_chksum_out_ipv4_no_ovr_prep, + pktio_test_chksum_out_ipv4_no_ovr_test); +} + +static void pktio_test_chksum_out_ipv4_ovr_prep(odp_packet_t pkt) +{ + odp_packet_l3_chksum_insert(pkt, true); +} + +static void pktio_test_chksum_out_ipv4_ovr_test(odp_packet_t pkt) +{ + odph_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL); + + CU_ASSERT(ip != NULL); + if (ip != NULL) + CU_ASSERT(ip->chksum != 0); +} + +static void pktio_test_chksum_out_ipv4_ovr(void) +{ + pktio_test_chksum(pktio_test_chksum_out_ipv4_config, + pktio_test_chksum_out_ipv4_ovr_prep, + pktio_test_chksum_out_ipv4_ovr_test); +} + +static void pktio_test_chksum_out_ipv4_pktio_config(odp_pktio_t pktio_tx, + odp_pktio_t pktio_rx + ODP_UNUSED) +{ + odp_pktio_capability_t capa; + odp_pktio_config_t config; + + CU_ASSERT_FATAL(odp_pktio_capability(pktio_tx, &capa) == 0); + CU_ASSERT_FATAL(capa.config.pktout.bit.ipv4_chksum_ena); + CU_ASSERT_FATAL(capa.config.pktout.bit.ipv4_chksum); + + odp_pktio_config_init(&config); + config.pktout.bit.ipv4_chksum_ena = 1; + config.pktout.bit.ipv4_chksum = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_tx, &config) == 0); +} + +static void pktio_test_chksum_out_ipv4_pktio(void) +{ + pktio_test_chksum(pktio_test_chksum_out_ipv4_pktio_config, + NULL, + pktio_test_chksum_out_ipv4_test); +} + +static int pktio_check_chksum_out_udp(void) +{ + odp_pktio_t pktio; + odp_pktio_capability_t capa; + odp_pktio_param_t pktio_param; + int ret; + + odp_pktio_param_init(&pktio_param); + pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT; + + pktio = odp_pktio_open(iface_name[0], pool[0], &pktio_param); + if (pktio == ODP_PKTIO_INVALID) + return ODP_TEST_INACTIVE; + + ret = odp_pktio_capability(pktio, &capa); + (void)odp_pktio_close(pktio); + + if (ret < 0 || + !capa.config.pktout.bit.udp_chksum_ena || + !capa.config.pktout.bit.udp_chksum) + return ODP_TEST_INACTIVE; + + return ODP_TEST_ACTIVE; +} + +static void pktio_test_chksum_out_udp_config(odp_pktio_t pktio_tx, + odp_pktio_t pktio_rx ODP_UNUSED) +{ + odp_pktio_capability_t capa; + odp_pktio_config_t config; + + CU_ASSERT_FATAL(odp_pktio_capability(pktio_tx, &capa) == 0); + CU_ASSERT_FATAL(capa.config.pktout.bit.udp_chksum_ena); + CU_ASSERT_FATAL(capa.config.pktout.bit.udp_chksum); + + odp_pktio_config_init(&config); + config.pktout.bit.udp_chksum_ena = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_tx, &config) == 0); +} + +static void pktio_test_chksum_out_udp_test(odp_packet_t pkt) +{ + odph_udphdr_t *udp = odp_packet_l4_ptr(pkt, NULL); + + CU_ASSERT(udp != NULL); + if (udp != NULL) { + CU_ASSERT(udp->chksum != 0); + CU_ASSERT(!odph_udp_chksum_verify(pkt)); + } +} + +static void pktio_test_chksum_out_udp_no_ovr_prep(odp_packet_t pkt) +{ + odph_ipv4_csum_update(pkt); + odp_packet_l4_chksum_insert(pkt, false); +} + +static void pktio_test_chksum_out_udp_no_ovr_test(odp_packet_t pkt) +{ + odph_udphdr_t *udp = odp_packet_l4_ptr(pkt, NULL); + + CU_ASSERT(udp != NULL); + if (udp != NULL) + CU_ASSERT(udp->chksum == 0); +} + +static void pktio_test_chksum_out_udp_no_ovr(void) +{ + pktio_test_chksum(pktio_test_chksum_out_udp_config, + pktio_test_chksum_out_udp_no_ovr_prep, + pktio_test_chksum_out_udp_no_ovr_test); +} + +static void pktio_test_chksum_out_udp_ovr_prep(odp_packet_t pkt) +{ + odp_packet_l4_chksum_insert(pkt, true); +} + +static void pktio_test_chksum_out_udp_ovr_test(odp_packet_t pkt) +{ + odph_udphdr_t *udp = odp_packet_l4_ptr(pkt, NULL); + + CU_ASSERT(udp != NULL); + if (udp != NULL) + CU_ASSERT(udp->chksum != 0); +} + +static void pktio_test_chksum_out_udp_ovr(void) +{ + pktio_test_chksum(pktio_test_chksum_out_udp_config, + pktio_test_chksum_out_udp_ovr_prep, + pktio_test_chksum_out_udp_ovr_test); +} + +static void pktio_test_chksum_out_udp_pktio_config(odp_pktio_t pktio_tx, + odp_pktio_t pktio_rx + ODP_UNUSED) +{ + odp_pktio_capability_t capa; + odp_pktio_config_t config; + + CU_ASSERT_FATAL(odp_pktio_capability(pktio_tx, &capa) == 0); + CU_ASSERT_FATAL(capa.config.pktout.bit.udp_chksum_ena); + CU_ASSERT_FATAL(capa.config.pktout.bit.udp_chksum); + + odp_pktio_config_init(&config); + config.pktout.bit.udp_chksum_ena = 1; + config.pktout.bit.udp_chksum = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_tx, &config) == 0); +} + +static void pktio_test_chksum_out_udp_pktio(void) +{ + pktio_test_chksum(pktio_test_chksum_out_udp_pktio_config, + NULL, + pktio_test_chksum_out_udp_test); +} + static int create_pool(const char *iface, int num) { char pool_name[ODP_POOL_NAME_LEN]; @@ -2034,6 +2471,22 @@ odp_testinfo_t pktio_suite_unsegmented[] = { pktio_check_statistics_counters), ODP_TEST_INFO_CONDITIONAL(pktio_test_pktin_ts, pktio_check_pktin_ts), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_in_ipv4, + pktio_check_chksum_in_ipv4), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_in_udp, + pktio_check_chksum_in_udp), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_ipv4_no_ovr, + pktio_check_chksum_out_ipv4), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_ipv4_pktio, + pktio_check_chksum_out_ipv4), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_ipv4_ovr, + pktio_check_chksum_out_ipv4), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_udp_no_ovr, + pktio_check_chksum_out_udp), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_udp_pktio, + pktio_check_chksum_out_udp), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_udp_ovr, + pktio_check_chksum_out_udp), ODP_TEST_INFO_NULL };
commit b2632ac253a3b9f5ba7a4174acf6abe295ec3550 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Apr 6 15:23:37 2018 +0300
linux-gen: pktio: loop: support IPv4/TCP/UDP checksum generation
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Petri Savolainen petri.savolainen@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c index 7fc0fd61..fc80e801 100644 --- a/platform/linux-generic/pktio/loop.c +++ b/platform/linux-generic/pktio/loop.c @@ -15,6 +15,7 @@ #include <odp_debug_internal.h> #include <odp/api/plat/packet_flag_inlines.h> #include <odp/api/hints.h> +#include <odp/api/plat/byteorder_inlines.h> #include <odp_queue_if.h>
#include <protocols/eth.h> @@ -32,6 +33,7 @@ static const char pktio_loop_mac[] = {0x02, 0xe9, 0x34, 0x80, 0x73, 0x01};
static int loopback_stats_reset(pktio_entry_t *pktio_entry); +static int loopback_init_capability(pktio_entry_t *pktio_entry);
static int loopback_open(odp_pktio_t id, pktio_entry_t *pktio_entry, const char *devname, odp_pool_t pool ODP_UNUSED) @@ -61,6 +63,7 @@ static int loopback_open(odp_pktio_t id, pktio_entry_t *pktio_entry, return -1;
loopback_stats_reset(pktio_entry); + loopback_init_capability(pktio_entry);
return 0; } @@ -172,6 +175,85 @@ static int loopback_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, return num_rx; }
+#define OL_TX_CHKSUM_PKT(_cfg, _capa, _proto, _ovr_set, _ovr) \ + (_capa && _proto && (_ovr_set ? _ovr : _cfg)) + +static inline int check_proto(void *l3_hdr, + uint32_t l3_len, + odp_bool_t *l3_proto_v4, + uint8_t *l4_proto) +{ + uint8_t l3_proto_ver = _ODP_IPV4HDR_VER(*(uint8_t *)l3_hdr); + + if (l3_proto_ver == _ODP_IPV4 && l3_len >= _ODP_IPV4HDR_LEN) { + _odp_ipv4hdr_t *ip = l3_hdr; + uint16_t frag_offset = _odp_be_to_cpu_16(ip->frag_offset); + + *l3_proto_v4 = 1; + if (!_ODP_IPV4HDR_IS_FRAGMENT(frag_offset)) + *l4_proto = ip->proto; + else + *l4_proto = 255; + + return 0; + } else if (l3_proto_ver == _ODP_IPV6 && l3_len >= _ODP_IPV6HDR_LEN) { + _odp_ipv6hdr_t *ipv6 = l3_hdr; + + *l3_proto_v4 = 0; + *l4_proto = ipv6->next_hdr; + + /* FIXME: check that packet is not a fragment !!! + * Might require parsing headers spanning several segments, so + * not implemented yet. */ + return 0; + } + + return -1; +} + +static inline void loopback_fix_checksums(odp_packet_t pkt, + odp_pktout_config_opt_t *pktout_cfg, + odp_pktout_config_opt_t *pktout_capa) +{ + odp_bool_t l3_proto_v4 = false; + uint8_t l4_proto; + void *l3_hdr; + uint32_t l3_len; + odp_bool_t ipv4_chksum_pkt, udp_chksum_pkt, tcp_chksum_pkt; + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + + l3_hdr = odp_packet_l3_ptr(pkt, &l3_len); + + if (l3_hdr == NULL || + check_proto(l3_hdr, l3_len, &l3_proto_v4, &l4_proto)) + return; + + ipv4_chksum_pkt = OL_TX_CHKSUM_PKT(pktout_cfg->bit.ipv4_chksum, + pktout_capa->bit.ipv4_chksum, + l3_proto_v4, + pkt_hdr->p.flags.l3_chksum_set, + pkt_hdr->p.flags.l3_chksum); + udp_chksum_pkt = OL_TX_CHKSUM_PKT(pktout_cfg->bit.udp_chksum, + pktout_capa->bit.udp_chksum, + l4_proto == _ODP_IPPROTO_UDP, + pkt_hdr->p.flags.l4_chksum_set, + pkt_hdr->p.flags.l4_chksum); + tcp_chksum_pkt = OL_TX_CHKSUM_PKT(pktout_cfg->bit.tcp_chksum, + pktout_capa->bit.tcp_chksum, + l4_proto == _ODP_IPPROTO_TCP, + pkt_hdr->p.flags.l4_chksum_set, + pkt_hdr->p.flags.l4_chksum); + + if (ipv4_chksum_pkt) + _odp_packet_ipv4_chksum_insert(pkt); + + if (tcp_chksum_pkt) + _odp_packet_tcp_chksum_insert(pkt); + + if (udp_chksum_pkt) + _odp_packet_udp_chksum_insert(pkt); +} + static int loopback_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, const odp_packet_t pkt_tbl[], int num) { @@ -182,6 +264,9 @@ static int loopback_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, int nb_tx = 0; uint32_t bytes = 0; uint32_t out_octets_tbl[num]; + odp_pktout_config_opt_t *pktout_cfg = &pktio_entry->s.config.pktout; + odp_pktout_config_opt_t *pktout_capa = + &pktio_entry->s.capa.config.pktout;
if (odp_unlikely(num > QUEUE_MULTI_MAX)) num = QUEUE_MULTI_MAX; @@ -218,6 +303,9 @@ static int loopback_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, packet_subtype_set(pkt_tbl[i], ODP_EVENT_PACKET_BASIC); }
+ for (i = 0; i < nb_tx; ++i) + loopback_fix_checksums(pkt_tbl[i], pktout_cfg, pktout_capa); + odp_ticketlock_lock(&pktio_entry->s.txl);
queue = queue_fn->from_ext(pktio_entry->s.pkt_loop.loopq); @@ -255,9 +343,10 @@ static int loopback_link_status(pktio_entry_t *pktio_entry ODP_UNUSED) return 1; }
-static int loopback_capability(pktio_entry_t *pktio_entry ODP_UNUSED, - odp_pktio_capability_t *capa) +static int loopback_init_capability(pktio_entry_t *pktio_entry) { + odp_pktio_capability_t *capa = &pktio_entry->s.capa; + memset(capa, 0, sizeof(odp_pktio_capability_t));
capa->max_input_queues = 1; @@ -267,9 +356,26 @@ static int loopback_capability(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_config_init(&capa->config); capa->config.pktin.bit.ts_all = 1; capa->config.pktin.bit.ts_ptp = 1; + capa->config.pktout.bit.ipv4_chksum = 1; + capa->config.pktout.bit.tcp_chksum = 1; + capa->config.pktout.bit.udp_chksum = 1; capa->config.inbound_ipsec = 1; capa->config.outbound_ipsec = 1;
+ capa->config.pktout.bit.ipv4_chksum_ena = + capa->config.pktout.bit.ipv4_chksum; + capa->config.pktout.bit.udp_chksum_ena = + capa->config.pktout.bit.udp_chksum; + capa->config.pktout.bit.tcp_chksum_ena = + capa->config.pktout.bit.tcp_chksum; + + return 0; +} + +static int loopback_capability(pktio_entry_t *pktio_entry ODP_UNUSED, + odp_pktio_capability_t *capa) +{ + *capa = pktio_entry->s.capa; return 0; }
commit 79f5c103310c36dc213a552b9534f68ce8df1132 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Mon Apr 9 15:45:55 2018 +0300
linux-gen: packet: l4 checksum insertion support
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Petri Savolainen petri.savolainen@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index cb1c3849..be17cac8 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -304,6 +304,8 @@ int _odp_packet_cmp_data(odp_packet_t pkt, uint32_t offset, const void *s, uint32_t len);
int _odp_packet_ipv4_chksum_insert(odp_packet_t pkt); +int _odp_packet_tcp_chksum_insert(odp_packet_t pkt); +int _odp_packet_udp_chksum_insert(odp_packet_t pkt);
#ifdef __cplusplus } diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 8170c812..d4b19fee 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -1910,6 +1910,92 @@ int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt) return dst_uarea_size < src_uarea_size; }
+/* Simple implementation of ones complement sum. + * Based on RFC1071 and its errata. + */ +typedef union { + uint16_t w; + uint8_t b[2]; +} swap_buf_t; + +static uint32_t segment_sum16_32(const uint8_t *p, + uint32_t len, + uint32_t offset) + +{ + uint32_t sum = 0; + + /* Include second part of 16-bit short word split between segments */ + if (len > 0 && (offset % 2)) { + swap_buf_t sw; + + sw.b[0] = 0; + sw.b[1] = *p++; + sum = sw.w; + len--; + } + + /* + * If pointer is 16-bit aligned, we can do fast path calculation. + * If it is not, we sum hi and lo bytes separately and then sum them. + */ + if ((uintptr_t)p % 2) { + uint32_t sum1 = 0, sum2 = 0; + + while (len > 1) { + sum1 += *p++; + sum2 += *p++; + len -= 2; + } +#if (ODP_BYTE_ORDER == ODP_BIG_ENDIAN) + sum += sum2 + (sum1 << 8); +#else + sum += sum1 + (sum2 << 8); +#endif + } else { + while (len > 1) { + sum += *(const uint16_t *)(uintptr_t)p; + p += 2; + len -= 2; + } + } + + /* Add left-over byte, if any */ + if (len > 0) { + swap_buf_t sw; + + sw.b[0] = *p; + sw.b[1] = 0; + sum += sw.w; + } + + return sum; +} + +static uint32_t packet_sum16_32(odp_packet_hdr_t *pkt_hdr, + uint32_t offset, + uint32_t len) +{ + uint32_t sum = 0; + + if (offset + len > pkt_hdr->frame_len) + return 0; + + while (len > 0) { + uint32_t seglen = 0; /* GCC */ + void *mapaddr = packet_map(pkt_hdr, offset, &seglen, NULL); + + if (seglen > len) + seglen = len; + + sum += segment_sum16_32(mapaddr, seglen, offset); + len -= seglen; + offset += seglen; + } + + return sum; +} + /** Parser helper function for Ethernet packets */ static inline uint16_t parse_eth(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset, uint32_t frame_len) @@ -2291,6 +2377,11 @@ static inline int packet_ipv4_chksum(odp_packet_t pkt, }
#define _ODP_IPV4HDR_CSUM_OFFSET ODP_OFFSETOF(_odp_ipv4hdr_t, chksum) +#define _ODP_IPV4ADDR_OFFSSET ODP_OFFSETOF(_odp_ipv4hdr_t, src_addr) +#define _ODP_IPV6ADDR_OFFSSET ODP_OFFSETOF(_odp_ipv6hdr_t, src_addr) +#define _ODP_IPV4HDR_CSUM_OFFSET ODP_OFFSETOF(_odp_ipv4hdr_t, chksum) +#define _ODP_UDP_LEN_OFFSET ODP_OFFSETOF(_odp_udphdr_t, length) +#define _ODP_UDP_CSUM_OFFSET ODP_OFFSETOF(_odp_udphdr_t, chksum)
/** * Calculate and fill in IPv4 checksum @@ -2324,6 +2415,96 @@ int _odp_packet_ipv4_chksum_insert(odp_packet_t pkt) 2, &chksum); }
+static int _odp_packet_tcp_udp_chksum_insert(odp_packet_t pkt, uint16_t proto) +{ + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + uint32_t zero = 0; + uint32_t sum; + uint16_t l3_ver; + uint16_t chksum; + uint32_t chksum_offset; + + if (pkt_hdr->p.l3_offset == ODP_PACKET_OFFSET_INVALID) + return -1; + if (pkt_hdr->p.l4_offset == ODP_PACKET_OFFSET_INVALID) + return -1; + + odp_packet_copy_to_mem(pkt, pkt_hdr->p.l3_offset, 2, &l3_ver); + + if (_ODP_IPV4HDR_VER(l3_ver) == _ODP_IPV4) + sum = packet_sum16_32(pkt_hdr, + pkt_hdr->p.l3_offset + + _ODP_IPV4ADDR_OFFSSET, + 2 * _ODP_IPV4ADDR_LEN); + else + sum = packet_sum16_32(pkt_hdr, + pkt_hdr->p.l3_offset + + _ODP_IPV6ADDR_OFFSSET, + 2 * _ODP_IPV6ADDR_LEN); +#if ODP_BYTE_ORDER == ODP_BIG_ENDIAN + sum += proto; +#else + sum += proto << 8; +#endif + + if (proto == _ODP_IPPROTO_TCP) { + sum += _odp_cpu_to_be_16(pkt_hdr->frame_len - + pkt_hdr->p.l4_offset); + chksum_offset = pkt_hdr->p.l4_offset + _ODP_UDP_CSUM_OFFSET; + } else { + sum += packet_sum16_32(pkt_hdr, + pkt_hdr->p.l4_offset + + _ODP_UDP_LEN_OFFSET, + 2); + chksum_offset = pkt_hdr->p.l4_offset + _ODP_UDP_CSUM_OFFSET; + } + odp_packet_copy_from_mem(pkt, chksum_offset, 2, &zero); + + sum += packet_sum16_32(pkt_hdr, + pkt_hdr->p.l4_offset, + pkt_hdr->frame_len - + pkt_hdr->p.l4_offset); + + /* Not more than two additions */ + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + + chksum = ~sum; + + if (proto == _ODP_IPPROTO_UDP && chksum == 0) + chksum = 0xffff; + + return odp_packet_copy_from_mem(pkt, + chksum_offset, + 2, &chksum); +} + +/** + * Calculate and fill in TCP checksum + * + * @param pkt ODP packet + * + * @retval 0 on success + * @retval <0 on failure + */ +int _odp_packet_tcp_chksum_insert(odp_packet_t pkt) +{ + return _odp_packet_tcp_udp_chksum_insert(pkt, _ODP_IPPROTO_TCP); +} + +/** + * Calculate and fill in UDP checksum + * + * @param pkt ODP packet + * + * @retval 0 on success + * @retval <0 on failure + */ +int _odp_packet_udp_chksum_insert(odp_packet_t pkt) +{ + return _odp_packet_tcp_udp_chksum_insert(pkt, _ODP_IPPROTO_UDP); +} + /** * Simple packet parser */
commit 2c99a9dc1978c9178e711d264aaaca2bc4702352 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Mon Apr 2 22:52:11 2018 +0300
linux-gen: packet: IPv4 checksum insertion
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Petri Savolainen petri.savolainen@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 75b4ce9e..cb1c3849 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -303,6 +303,8 @@ int _odp_packet_set_data(odp_packet_t pkt, uint32_t offset, int _odp_packet_cmp_data(odp_packet_t pkt, uint32_t offset, const void *s, uint32_t len);
+int _odp_packet_ipv4_chksum_insert(odp_packet_t pkt); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index 1e90cea0..65f7361b 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -162,67 +162,10 @@ static odp_ipsec_packet_result_t *ipsec_pkt_result(odp_packet_t packet) return &packet_hdr(packet)->ipsec_ctx; }
-static inline int _odp_ipv4_csum(odp_packet_t pkt, - uint32_t offset, - _odp_ipv4hdr_t *ip, - odp_u16sum_t *chksum) -{ - unsigned nleft = _ODP_IPV4HDR_IHL(ip->ver_ihl) * 4; - uint16_t buf[nleft / 2]; - int res; - - if (odp_unlikely(nleft < sizeof(*ip))) - return -1; - ip->chksum = 0; - memcpy(buf, ip, sizeof(*ip)); - res = odp_packet_copy_to_mem(pkt, offset + sizeof(*ip), - nleft - sizeof(*ip), - buf + sizeof(*ip) / 2); - if (odp_unlikely(res < 0)) - return res; - - *chksum = ~odp_chksum_ones_comp16(buf, nleft); - - return 0; -} - -#define _ODP_IPV4HDR_CSUM_OFFSET ODP_OFFSETOF(_odp_ipv4hdr_t, chksum) #define _ODP_IPV4HDR_PROTO_OFFSET ODP_OFFSETOF(_odp_ipv4hdr_t, proto) #define _ODP_IPV6HDR_NHDR_OFFSET ODP_OFFSETOF(_odp_ipv6hdr_t, next_hdr) #define _ODP_IPV6HDREXT_NHDR_OFFSET ODP_OFFSETOF(_odp_ipv6hdr_ext_t, next_hdr)
-/** - * Calculate and fill in IPv4 checksum - * - * @param pkt ODP packet - * - * @retval 0 on success - * @retval <0 on failure - */ -static inline int _odp_ipv4_csum_update(odp_packet_t pkt) -{ - uint32_t offset; - _odp_ipv4hdr_t ip; - odp_u16sum_t chksum; - int res; - - offset = odp_packet_l3_offset(pkt); - if (offset == ODP_PACKET_OFFSET_INVALID) - return -1; - - res = odp_packet_copy_to_mem(pkt, offset, sizeof(ip), &ip); - if (odp_unlikely(res < 0)) - return res; - - res = _odp_ipv4_csum(pkt, offset, &ip, &chksum); - if (odp_unlikely(res < 0)) - return res; - - return odp_packet_copy_from_mem(pkt, - offset + _ODP_IPV4HDR_CSUM_OFFSET, - 2, &chksum); -} - #define ipv4_hdr_len(ip) (_ODP_IPV4HDR_IHL((ip)->ver_ihl) * 4)
static const uint8_t ipsec_padding[255] = { @@ -815,7 +758,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt, ipv4hdr->tot_len = _odp_cpu_to_be_16(state.ip_tot_len); else ipv4hdr->ttl -= ipsec_sa->dec_ttl; - _odp_ipv4_csum_update(pkt); + _odp_packet_ipv4_chksum_insert(pkt); } else if (state.is_ipv6 && odp_packet_len(pkt) > _ODP_IPV6HDR_LEN) { _odp_ipv6hdr_t *ipv6hdr = odp_packet_l3_ptr(pkt, NULL);
@@ -1238,7 +1181,7 @@ static int ipsec_out_esp(odp_packet_t *pkt, static void ipsec_out_esp_post(ipsec_state_t *state, odp_packet_t pkt) { if (state->is_ipv4) - _odp_ipv4_csum_update(pkt); + _odp_packet_ipv4_chksum_insert(pkt); }
static int ipsec_out_ah(odp_packet_t *pkt, @@ -1343,7 +1286,7 @@ static void ipsec_out_ah_post(ipsec_state_t *state, odp_packet_t pkt) ipv4hdr->tos = state->ah_ipv4.tos; ipv4hdr->frag_offset = state->ah_ipv4.frag_offset;
- _odp_ipv4_csum_update(pkt); + _odp_packet_ipv4_chksum_insert(pkt); } else { _odp_ipv6hdr_t *ipv6hdr = odp_packet_l3_ptr(pkt, NULL);
@@ -1500,7 +1443,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, else if (ODP_IPSEC_AH == ipsec_sa->proto) ipsec_out_ah_post(&state, pkt);
- _odp_ipv4_csum_update(pkt); + _odp_packet_ipv4_chksum_insert(pkt);
*pkt_out = pkt; return ipsec_sa; diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 462c8a4c..8170c812 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -2266,6 +2266,64 @@ int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, seg_len, layer, ethtype); }
+static inline int packet_ipv4_chksum(odp_packet_t pkt, + uint32_t offset, + _odp_ipv4hdr_t *ip, + odp_u16sum_t *chksum) +{ + unsigned int nleft = _ODP_IPV4HDR_IHL(ip->ver_ihl) * 4; + uint16_t buf[nleft / 2]; + int res; + + if (odp_unlikely(nleft < sizeof(*ip))) + return -1; + ip->chksum = 0; + memcpy(buf, ip, sizeof(*ip)); + res = odp_packet_copy_to_mem(pkt, offset + sizeof(*ip), + nleft - sizeof(*ip), + buf + sizeof(*ip) / 2); + if (odp_unlikely(res < 0)) + return res; + + *chksum = ~odp_chksum_ones_comp16(buf, nleft); + + return 0; +} + +#define _ODP_IPV4HDR_CSUM_OFFSET ODP_OFFSETOF(_odp_ipv4hdr_t, chksum) + +/** + * Calculate and fill in IPv4 checksum + * + * @param pkt ODP packet + * + * @retval 0 on success + * @retval <0 on failure + */ +int _odp_packet_ipv4_chksum_insert(odp_packet_t pkt) +{ + uint32_t offset; + _odp_ipv4hdr_t ip; + odp_u16sum_t chksum; + int res; + + offset = odp_packet_l3_offset(pkt); + if (offset == ODP_PACKET_OFFSET_INVALID) + return -1; + + res = odp_packet_copy_to_mem(pkt, offset, sizeof(ip), &ip); + if (odp_unlikely(res < 0)) + return res; + + res = packet_ipv4_chksum(pkt, offset, &ip, &chksum); + if (odp_unlikely(res < 0)) + return res; + + return odp_packet_copy_from_mem(pkt, + offset + _ODP_IPV4HDR_CSUM_OFFSET, + 2, &chksum); +} + /** * Simple packet parser */
-----------------------------------------------------------------------
Summary of changes: .../linux-generic/include/odp_packet_internal.h | 4 + platform/linux-generic/odp_ipsec.c | 106 ++--- platform/linux-generic/odp_packet.c | 239 +++++++++++ platform/linux-generic/pktio/loop.c | 110 ++++- test/validation/api/ipsec/ipsec.c | 2 + test/validation/api/ipsec/ipsec_test_out.c | 32 ++ test/validation/api/ipsec/test_vectors.h | 71 +++- test/validation/api/pktio/pktio.c | 465 ++++++++++++++++++++- 8 files changed, 954 insertions(+), 75 deletions(-)
hooks/post-receive