From patchwork Tue Aug 21 16:59:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,1/12] validation: pktio: check sctp flag in parser tests X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144750 Message-Id: <1534870807-18456-2-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 16:59:56 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ test/validation/api/pktio/parser.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/validation/api/pktio/parser.c b/test/validation/api/pktio/parser.c index 76df47b1c..f22a62555 100644 --- a/test/validation/api/pktio/parser.c +++ b/test/validation/api/pktio/parser.c @@ -301,6 +301,7 @@ static void parser_test_ipv4_icmp(void) CU_ASSERT(!odp_packet_has_ipv6(pkt)); CU_ASSERT(!odp_packet_has_tcp(pkt)); CU_ASSERT(!odp_packet_has_udp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } @@ -318,6 +319,7 @@ static void parser_test_ipv4_tcp(void) CU_ASSERT(!odp_packet_has_ipv6(pkt)); CU_ASSERT(!odp_packet_has_udp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } @@ -335,6 +337,7 @@ static void parser_test_ipv4_udp(void) CU_ASSERT(!odp_packet_has_ipv6(pkt)); CU_ASSERT(!odp_packet_has_tcp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } @@ -353,6 +356,7 @@ static void parser_test_vlan_ipv4_udp(void) CU_ASSERT(!odp_packet_has_ipv6(pkt)); CU_ASSERT(!odp_packet_has_tcp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } @@ -372,6 +376,7 @@ static void parser_test_vlan_qinq_ipv4_udp(void) CU_ASSERT(!odp_packet_has_ipv6(pkt)); CU_ASSERT(!odp_packet_has_tcp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } @@ -390,6 +395,7 @@ static void parser_test_ipv6_icmp(void) CU_ASSERT(!odp_packet_has_ipv4(pkt)); CU_ASSERT(!odp_packet_has_tcp(pkt)); CU_ASSERT(!odp_packet_has_udp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } @@ -407,6 +413,7 @@ static void parser_test_ipv6_tcp(void) CU_ASSERT(!odp_packet_has_ipv4(pkt)); CU_ASSERT(!odp_packet_has_udp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } @@ -424,6 +431,7 @@ static void parser_test_ipv6_udp(void) CU_ASSERT(!odp_packet_has_ipv4(pkt)); CU_ASSERT(!odp_packet_has_tcp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } @@ -442,6 +450,7 @@ static void parser_test_vlan_ipv6_udp(void) CU_ASSERT(!odp_packet_has_ipv4(pkt)); CU_ASSERT(!odp_packet_has_tcp(pkt)); + CU_ASSERT(!odp_packet_has_sctp(pkt)); odp_packet_free(pkt); } From patchwork Tue Aug 21 16:59:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,2/12] validation: pktio: fix checks in pktio tests X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144751 Message-Id: <1534870807-18456-3-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 16:59:57 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov - cleanly close PktI/O if packet creation has failed - verify UDP checksum in UDP checksum override test Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ test/validation/api/pktio/pktio.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/validation/api/pktio/pktio.c b/test/validation/api/pktio/pktio.c index 09367d4ea..625cc325e 100644 --- a/test/validation/api/pktio/pktio.c +++ b/test/validation/api/pktio/pktio.c @@ -1958,7 +1958,14 @@ static void pktio_test_chksum(void (*config_fn)(odp_pktio_t, odp_pktio_t), ret = create_packets_cs(pkt_tbl, pkt_seq, TX_BATCH_LEN, pktio_tx, pktio_rx, false); - CU_ASSERT_FATAL(ret == TX_BATCH_LEN); + CU_ASSERT(ret == TX_BATCH_LEN); + if (ret != TX_BATCH_LEN) { + 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); + } + return; + } ret = odp_pktout_queue(pktio_tx, &pktout_queue, 1); CU_ASSERT_FATAL(ret > 0); @@ -2296,8 +2303,10 @@ 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) + if (udp != NULL) { CU_ASSERT(udp->chksum != 0); + CU_ASSERT(!odph_udp_chksum_verify(pkt)); + } } static void pktio_test_chksum_out_udp_ovr(void) From patchwork Tue Aug 21 16:59:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,3/12] test/common: add IPv6 SCTP packet X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144752 Message-Id: <1534870807-18456-4-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 16:59:58 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ test/common/test_packet_parser.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/common/test_packet_parser.h b/test/common/test_packet_parser.h index 2d02b98c3..0f17e8568 100644 --- a/test/common/test_packet_parser.h +++ b/test/common/test_packet_parser.h @@ -168,6 +168,32 @@ static const uint8_t test_packet_ipv4_sctp[] = { 0x79, 0x74, 0x65, 0x73, 0x2E }; +/* IPv6 SCTP + * - chunk type: payload data + */ +static const uint8_t test_packet_ipv6_sctp[] = { + 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x04, 0x00, 0x86, 0xDD, 0x60, 0x30, + 0x00, 0x00, 0x00, 0x63, 0x84, 0xFF, 0xFE, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x09, 0xFF, 0xFE, 0x00, 0x04, 0x00, 0x35, 0x55, + 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, + 0x77, 0x77, 0x88, 0x88, 0x88, 0x88, 0x04, 0xD2, + 0x16, 0x2E, 0xDE, 0xAD, 0xBE, 0xEF, 0x31, 0x44, + 0xE3, 0xFE, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, + 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x6D, 0x79, 0x20, 0x64, 0x75, 0x6D, + 0x6D, 0x79, 0x20, 0x70, 0x61, 0x79, 0x6C, 0x6F, + 0x61, 0x64, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, + 0x67, 0x2E, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6C, + 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x6F, 0x66, + 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, + 0x37, 0x31, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x2E +}; + static const uint8_t test_packet_ipv4_ipsec_ah[] = { /* ETH */ 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, From patchwork Tue Aug 21 16:59:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,4/12] validation: pktio: parser: add SCTP test X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144753 Message-Id: <1534870807-18456-5-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 16:59:59 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Add SCTP packet parsing test, checking that protocol is properly recognized. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ test/validation/api/pktio/parser.c | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/validation/api/pktio/parser.c b/test/validation/api/pktio/parser.c index f22a62555..db37c1c5b 100644 --- a/test/validation/api/pktio/parser.c +++ b/test/validation/api/pktio/parser.c @@ -381,6 +381,24 @@ static void parser_test_vlan_qinq_ipv4_udp(void) odp_packet_free(pkt); } +static void parser_test_ipv4_sctp(void) +{ + odp_packet_t pkt; + + pkt = loopback_packet(pktio_a, pktio_b, test_packet_ipv4_sctp, + sizeof(test_packet_ipv4_sctp)); + CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); + CU_ASSERT(odp_packet_has_eth(pkt)); + CU_ASSERT(odp_packet_has_ipv4(pkt)); + CU_ASSERT(odp_packet_has_sctp(pkt)); + + CU_ASSERT(!odp_packet_has_ipv6(pkt)); + CU_ASSERT(!odp_packet_has_tcp(pkt)); + CU_ASSERT(!odp_packet_has_udp(pkt)); + + odp_packet_free(pkt); +} + static void parser_test_ipv6_icmp(void) { odp_packet_t pkt; @@ -455,6 +473,24 @@ static void parser_test_vlan_ipv6_udp(void) odp_packet_free(pkt); } +static void parser_test_ipv6_sctp(void) +{ + odp_packet_t pkt; + + pkt = loopback_packet(pktio_a, pktio_b, test_packet_ipv6_sctp, + sizeof(test_packet_ipv6_sctp)); + CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); + CU_ASSERT(odp_packet_has_eth(pkt)); + CU_ASSERT(odp_packet_has_ipv6(pkt)); + CU_ASSERT(odp_packet_has_sctp(pkt)); + + CU_ASSERT(!odp_packet_has_ipv4(pkt)); + CU_ASSERT(!odp_packet_has_tcp(pkt)); + CU_ASSERT(!odp_packet_has_udp(pkt)); + + odp_packet_free(pkt); +} + int parser_suite_init(void) { int i; @@ -564,9 +600,11 @@ odp_testinfo_t parser_suite[] = { ODP_TEST_INFO(parser_test_ipv4_udp), ODP_TEST_INFO_CONDITIONAL(parser_test_vlan_ipv4_udp, loop_pktio), ODP_TEST_INFO_CONDITIONAL(parser_test_vlan_qinq_ipv4_udp, loop_pktio), + ODP_TEST_INFO(parser_test_ipv4_sctp), ODP_TEST_INFO(parser_test_ipv6_icmp), ODP_TEST_INFO(parser_test_ipv6_tcp), ODP_TEST_INFO(parser_test_ipv6_udp), ODP_TEST_INFO_CONDITIONAL(parser_test_vlan_ipv6_udp, loop_pktio), + ODP_TEST_INFO(parser_test_ipv6_sctp), ODP_TEST_INFO_NULL }; From patchwork Tue Aug 21 17:00:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,5/12] helper: add SCTP protocol header X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144755 Message-Id: <1534870807-18456-6-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 17:00:00 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ helper/Makefile.am | 1 + helper/include/odp/helper/ip.h | 2 ++ helper/include/odp/helper/odph_api.h | 1 + helper/include/odp/helper/sctp.h | 49 ++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 helper/include/odp/helper/sctp.h diff --git a/helper/Makefile.am b/helper/Makefile.am index d1b0359cc..518a6a944 100644 --- a/helper/Makefile.am +++ b/helper/Makefile.am @@ -22,6 +22,7 @@ helperinclude_HEADERS = \ include/odp/helper/odph_hashtable.h\ include/odp/helper/odph_iplookuptable.h\ include/odp/helper/odph_lineartable.h\ + include/odp/helper/sctp.h \ include/odp/helper/strong_types.h\ include/odp/helper/tcp.h\ include/odp/helper/table.h\ diff --git a/helper/include/odp/helper/ip.h b/helper/include/odp/helper/ip.h index cdc430627..b5bfed78c 100644 --- a/helper/include/odp/helper/ip.h +++ b/helper/include/odp/helper/ip.h @@ -259,6 +259,8 @@ typedef struct ODP_PACKED { #define ODPH_IPPROTO_AH 0x33 /**< Authentication Header (51) */ #define ODPH_IPPROTO_ESP 0x32 /**< Encapsulating Security Payload (50) */ #define ODPH_IPPROTO_ICMPV6 0x3A /**< Internet Control Message Protocol (58) */ +#define ODPH_IPPROTO_SCTP 0x84 /**< Stream Control Transmission protocol + (132) */ #define ODPH_IPPROTO_INVALID 0xFF /**< Reserved invalid by IANA */ /**@}*/ diff --git a/helper/include/odp/helper/odph_api.h b/helper/include/odp/helper/odph_api.h index 8ad8a27fe..d46ab2ad2 100644 --- a/helper/include/odp/helper/odph_api.h +++ b/helper/include/odp/helper/odph_api.h @@ -27,6 +27,7 @@ extern "C" { #include #include #include +#include #include #include #include diff --git a/helper/include/odp/helper/sctp.h b/helper/include/odp/helper/sctp.h new file mode 100644 index 000000000..c81bd6313 --- /dev/null +++ b/helper/include/odp/helper/sctp.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2014-2018, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP SCTP header + */ + +#ifndef ODPH_SCTP_H_ +#define ODPH_SCTP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** @addtogroup odph_header ODPH HEADER + * @{ + */ + +/** SCTP header length */ +#define ODPH_SCTPHDR_LEN 12 + +/** SCTP header */ +typedef struct ODP_PACKED { + odp_u16be_t src_port; /**< Source port */ + odp_u16be_t dst_port; /**< Destination port */ + odp_u32be_t tag; /**< Verification tag */ + odp_u32be_t chksum; /**< SCTP header and data checksum */ +} odph_sctphdr_t; + +/** @internal Compile time assert */ +ODP_STATIC_ASSERT(sizeof(odph_sctphdr_t) == ODPH_SCTPHDR_LEN, + "ODPH_SCTPHDR_T__SIZE_ERROR"); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif From patchwork Tue Aug 21 17:00:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,6/12] helper: add SCTP handling functions X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144754 Message-Id: <1534870807-18456-7-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 17:00:01 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Add functions to set and verify SCTP packet checksum. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ helper/chksum.c | 75 ++++++++++++++++++++++++++++++ helper/include/odp/helper/chksum.h | 42 +++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/helper/chksum.c b/helper/chksum.c index da5625a78..7c7c20a2f 100644 --- a/helper/chksum.c +++ b/helper/chksum.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -351,3 +352,77 @@ int odph_udp_tcp_chksum(odp_packet_t odp_pkt, return ret_code; } + +static uint32_t odph_packet_crc32c(odp_packet_t pkt, + uint32_t offset, + uint32_t length, + uint32_t init_val) +{ + uint32_t sum = init_val; + + if (offset + length > odp_packet_len(pkt)) + return sum; + + while (length > 0) { + uint32_t seg_len; + void *data = odp_packet_offset(pkt, offset, &seg_len, NULL); + + if (seg_len > length) + seg_len = length; + + sum = odp_hash_crc32c(data, seg_len, sum); + length -= seg_len; + offset += seg_len; + } + + return sum; +} + +int odph_sctp_chksum_set(odp_packet_t pkt) +{ + uint32_t l4_offset = odp_packet_l4_offset(pkt); + uint32_t sum = 0; + + if (!odp_packet_has_sctp(pkt)) + return -1; + + if (l4_offset == ODP_PACKET_OFFSET_INVALID) + return -1; + + odp_packet_copy_from_mem(pkt, + l4_offset + ODPH_SCTPHDR_LEN - 4, + 4, + &sum); + + sum = ~odph_packet_crc32c(pkt, l4_offset, + odp_packet_len(pkt) - l4_offset, + ~0); + return odp_packet_copy_from_mem(pkt, + l4_offset + ODPH_SCTPHDR_LEN - 4, + 4, + &sum); +} + +int odph_sctp_chksum_verify(odp_packet_t pkt) +{ + uint32_t l4_offset = odp_packet_l4_offset(pkt); + uint32_t sum; + uint32_t temp = 0; + + if (!odp_packet_has_sctp(pkt)) + return -1; + + sum = odph_packet_crc32c(pkt, l4_offset, + ODPH_SCTPHDR_LEN - 4, + ~0); + sum = odp_hash_crc32c(&temp, 4, sum); + sum = ~odph_packet_crc32c(pkt, l4_offset + ODPH_SCTPHDR_LEN, + odp_packet_len(pkt) - l4_offset - + ODPH_SCTPHDR_LEN, + sum); + + odp_packet_copy_to_mem(pkt, l4_offset + ODPH_SCTPHDR_LEN - 4, + 4, &temp); + + return (temp == sum) ? 0 : 2; +} diff --git a/helper/include/odp/helper/chksum.h b/helper/include/odp/helper/chksum.h index c03abeb7b..148b98601 100644 --- a/helper/include/odp/helper/chksum.h +++ b/helper/include/odp/helper/chksum.h @@ -189,6 +189,48 @@ static inline int odph_udp_chksum_verify(odp_packet_t odp_pkt) return odph_udp_tcp_chksum(odp_pkt, ODPH_CHKSUM_VERIFY, NULL); } +/** + * Generate SCTP checksum + * + * This function supports SCTP over either IPv4 or IPV6 - including handling + * any IPv4 header options and any IPv6 extension headers. However it + * does not handle tunneled pkts (i.e. any case where there is more than + * one IPv4/IPv6 header). + * This function also handles non-contiguous pkts. In particular it can + * handle arbitrary packet segmentation, including cases where the segments + * are not 2 byte aligned, nor have a length that is a multiple of 2. This + * function also can handle jumbo frames (at least up to 10K). + * + * This function will insert the calculated CRC32-c checksum into the proper + * location in the SCTP header. + * + * @param odp_pkt Calculate and insert chksum for this SCTP pkt, which can + * be over IPv4 or IPv6. + * @retval 0 on success + * @retval <0 on failure + */ +int odph_sctp_chksum_set(odp_packet_t odp_pkt); + +/** + * Verify SCTP checksum + * + * This function supports SCTP over either IPv4 or IPV6 - including handling + * any IPv4 header options and any IPv6 extension headers. However it + * does not handle tunneled pkts (i.e. any case where there is more than + * one IPv4/IPv6 header). + * This function also handles non-contiguous pkts. In particular it can + * handle arbitrary packet segmentation, including cases where the segments + * are not 2 byte aligned, nor have a length that is a multiple of 2. This + * function also can handle jumbo frames (at least up to 10K). + * + * @param odp_pkt Calculate and compare the chksum for this SCTP pkt, + * which can be over IPv4 or IPv6. + * @retval <0 on failure + * @retval 0 if the incoming chksum field is correct + * @retval 2 when the chksum field is incorrect + */ +int odph_sctp_chksum_verify(odp_packet_t odp_pkt); + /** * @} */ From patchwork Tue Aug 21 17:00:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,7/12] linux-gen: add SCTP protocol header X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144756 Message-Id: <1534870807-18456-8-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 17:00:02 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ platform/linux-generic/Makefile.am | 1 + .../linux-generic/include/protocols/sctp.h | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 platform/linux-generic/include/protocols/sctp.h diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 13101cfdc..80f968756 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -142,6 +142,7 @@ noinst_HEADERS = \ include/protocols/eth.h \ include/protocols/ip.h \ include/protocols/ipsec.h \ + include/protocols/sctp.h \ include/protocols/tcp.h \ include/protocols/thash.h \ include/protocols/udp.h diff --git a/platform/linux-generic/include/protocols/sctp.h b/platform/linux-generic/include/protocols/sctp.h new file mode 100644 index 000000000..dea8a8a6e --- /dev/null +++ b/platform/linux-generic/include/protocols/sctp.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2016-2018, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP SCTP header + */ + +#ifndef ODP_SCTP_H_ +#define ODP_SCTP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** @addtogroup odp_header ODP HEADER + * @{ + */ + +/** SCTP header length */ +#define _ODP_SCTPHDR_LEN 12 + +/** SCTP header */ +typedef struct ODP_PACKED { + odp_u16be_t src_port; /**< Source port */ + odp_u16be_t dst_port; /**< Destination port */ + odp_u32be_t tag; /**< Verification tag */ + odp_u32be_t chksum; /**< SCTP header and data checksum */ +} _odp_sctphdr_t; + +/** @internal Compile time assert */ +ODP_STATIC_ASSERT(sizeof(_odp_sctphdr_t) == _ODP_SCTPHDR_LEN, + "_ODP_SCTPHDR_T__SIZE_ERROR"); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif From patchwork Tue Aug 21 17:00:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,8/12] linux-gen: packet: parse SCTP packets and verify checksum X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144759 Message-Id: <1534870807-18456-9-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 17:00:03 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Verify SCTP packet checksums. Use CRC32-c as requied by RFC3309 instead of original Adler-32. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ .../odp/api/plat/packet_inline_types.h | 7 +-- platform/linux-generic/odp_packet.c | 54 +++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/platform/linux-generic/include/odp/api/plat/packet_inline_types.h b/platform/linux-generic/include/odp/api/plat/packet_inline_types.h index 9a285fe4a..255102988 100644 --- a/platform/linux-generic/include/odp/api/plat/packet_inline_types.h +++ b/platform/linux-generic/include/odp/api/plat/packet_inline_types.h @@ -111,7 +111,7 @@ typedef union { uint32_t all_flags; struct { - uint32_t reserved1: 11; + uint32_t reserved1: 10; /* * Init flags @@ -135,6 +135,7 @@ typedef union { uint32_t l3_chksum_err: 1; /* L3 checksum error */ uint32_t tcp_err: 1; /* TCP error */ uint32_t udp_err: 1; /* UDP error */ + uint32_t sctp_err: 1; /* SCTP error */ uint32_t l4_chksum_err: 1; /* L4 checksum error */ uint32_t ipsec_err: 1; /* IPsec error */ uint32_t crypto_err: 1; /* Crypto packet operation error */ @@ -142,9 +143,9 @@ typedef union { /* Flag groups */ struct { - uint32_t reserved2: 11; + uint32_t reserved2: 10; uint32_t other: 13; /* All other flags */ - uint32_t error: 8; /* All error flags */ + uint32_t error: 9; /* All error flags */ } all; } _odp_packet_flags_t; diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 11f8bd43d..885aec8d8 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -2298,6 +2299,34 @@ static inline void parse_udp(packet_parser_t *prs, const uint8_t **parseptr, *parseptr += sizeof(_odp_udphdr_t); } +/** + * Parser helper function for SCTP + */ +static inline void parse_sctp(packet_parser_t *prs, const uint8_t **parseptr, + uint16_t sctp_len, + odp_proto_chksums_t chksums, + uint32_t *l4_part_sum) +{ + if (odp_unlikely(sctp_len < sizeof(_odp_sctphdr_t))) { + prs->flags.sctp_err = 1; + return; + } + + if (chksums.chksum.sctp && + !prs->input_flags.ipfrag) { + const _odp_sctphdr_t *sctp = + (const _odp_sctphdr_t *)*parseptr; + uint32_t crc = ~0; + uint32_t zero = 0; + + crc = odp_hash_crc32c(sctp, sizeof(*sctp) - 4, crc); + crc = odp_hash_crc32c(&zero, 4, crc); + *l4_part_sum = crc; + } + + *parseptr += sizeof(_odp_sctphdr_t); +} + static inline int packet_parse_common_l3_l4(packet_parser_t *prs, const uint8_t *parseptr, uint32_t offset, @@ -2388,6 +2417,8 @@ int packet_parse_common_l3_l4(packet_parser_t *prs, const uint8_t *parseptr, case _ODP_IPPROTO_SCTP: prs->input_flags.sctp = 1; + parse_sctp(prs, &parseptr, frame_len - prs->l4_offset, chksums, + l4_part_sum); break; case _ODP_IPPROTO_NO_NEXT: @@ -2626,6 +2657,29 @@ static int packet_l4_chksum(odp_packet_hdr_t *pkt_hdr, } } + if (chksums.chksum.sctp && + pkt_hdr->p.input_flags.sctp && + !pkt_hdr->p.input_flags.ipfrag) { + uint32_t sum = ~packet_sum_crc32c(pkt_hdr, + pkt_hdr->p.l4_offset + + _ODP_SCTPHDR_LEN, + pkt_hdr->frame_len - + pkt_hdr->p.l4_offset - + _ODP_SCTPHDR_LEN, + l4_part_sum); + _odp_sctphdr_t *sctp = packet_map(pkt_hdr, + pkt_hdr->p.l4_offset, + NULL, NULL); + + pkt_hdr->p.input_flags.l4_chksum_done = 1; + if (sum != sctp->chksum) { + pkt_hdr->p.flags.l4_chksum_err = 1; + pkt_hdr->p.flags.sctp_err = 1; + ODP_DBG("SCTP chksum fail (%x/%x)!\n", sum, + sctp->chksum); + } + } + return pkt_hdr->p.flags.all_flags != 0; } From patchwork Tue Aug 21 17:00:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,9/12] linux-gen: packet: support SCTP packet insertion X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144758 Message-Id: <1534870807-18456-10-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 17:00:04 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Add support for insertion of checksum into SCTP packets. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ .../include/odp_packet_internal.h | 2 + platform/linux-generic/odp_packet.c | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 4b5127d93..0dccc97da 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -308,6 +308,8 @@ int _odp_packet_cmp_data(odp_packet_t pkt, uint32_t offset, 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); +int _odp_packet_sctp_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 885aec8d8..ae63ef4a3 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -2017,6 +2017,31 @@ static uint16_t packet_sum_ones_comp16(odp_packet_hdr_t *pkt_hdr, return sum; } +static uint32_t packet_sum_crc32c(odp_packet_hdr_t *pkt_hdr, + uint32_t offset, + uint32_t len, + uint32_t init_val) +{ + uint32_t sum = init_val; + + if (offset + len > pkt_hdr->frame_len) + return sum; + + while (len > 0) { + uint32_t seglen = 0; /* GCC */ + void *mapaddr = packet_map(pkt_hdr, offset, &seglen, NULL); + + if (seglen > len) + seglen = len; + + sum = odp_hash_crc32c(mapaddr, seglen, sum); + 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) @@ -2617,6 +2642,30 @@ int _odp_packet_udp_chksum_insert(odp_packet_t pkt) return _odp_packet_tcp_udp_chksum_insert(pkt, _ODP_IPPROTO_UDP); } +/** + * Calculate and fill in SCTP checksum + * + * @param pkt ODP packet + * + * @retval 0 on success + * @retval <0 on failure + */ +int _odp_packet_sctp_chksum_insert(odp_packet_t pkt) +{ + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + uint32_t sum; + + if (pkt_hdr->p.l4_offset == ODP_PACKET_OFFSET_INVALID) + return -1; + + sum = 0; + odp_packet_copy_from_mem(pkt, pkt_hdr->p.l4_offset + 8, 4, &sum); + sum = ~packet_sum_crc32c(pkt_hdr, pkt_hdr->p.l4_offset, + pkt_hdr->frame_len - pkt_hdr->p.l4_offset, + ~0); + return odp_packet_copy_from_mem(pkt, pkt_hdr->p.l4_offset + 8, 4, &sum); +} + static int packet_l4_chksum(odp_packet_hdr_t *pkt_hdr, odp_proto_chksums_t chksums, uint32_t l4_part_sum) From patchwork Tue Aug 21 17:00:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,10/12] linux-gen: pktio: loop: handle SCTP checksums X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144760 Message-Id: <1534870807-18456-11-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 17:00:05 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Add code to emulate hardware SCTP checksumming support over loop device (as it is done for IPv4/TCP/UDP). Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ platform/linux-generic/pktio/loop.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c index 2d8b843d6..e01dd4585 100644 --- a/platform/linux-generic/pktio/loop.c +++ b/platform/linux-generic/pktio/loop.c @@ -236,7 +236,8 @@ static inline void loopback_fix_checksums(odp_packet_t pkt, uint8_t l4_proto; void *l3_hdr; uint32_t l3_len; - odp_bool_t ipv4_chksum_pkt, udp_chksum_pkt, tcp_chksum_pkt; + odp_bool_t ipv4_chksum_pkt, udp_chksum_pkt, tcp_chksum_pkt, + sctp_chksum_pkt; odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); l3_hdr = odp_packet_l3_ptr(pkt, &l3_len); @@ -260,6 +261,11 @@ static inline void loopback_fix_checksums(odp_packet_t pkt, l4_proto == _ODP_IPPROTO_TCP, pkt_hdr->p.flags.l4_chksum_set, pkt_hdr->p.flags.l4_chksum); + sctp_chksum_pkt = OL_TX_CHKSUM_PKT(pktout_cfg->bit.sctp_chksum, + pktout_capa->bit.sctp_chksum, + l4_proto == _ODP_IPPROTO_SCTP, + pkt_hdr->p.flags.l4_chksum_set, + pkt_hdr->p.flags.l4_chksum); if (ipv4_chksum_pkt) _odp_packet_ipv4_chksum_insert(pkt); @@ -269,6 +275,9 @@ static inline void loopback_fix_checksums(odp_packet_t pkt, if (udp_chksum_pkt) _odp_packet_udp_chksum_insert(pkt); + + if (sctp_chksum_pkt) + _odp_packet_sctp_chksum_insert(pkt); } static int loopback_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, @@ -376,9 +385,11 @@ static int loopback_init_capability(pktio_entry_t *pktio_entry) capa->config.pktin.bit.ipv4_chksum = 1; capa->config.pktin.bit.tcp_chksum = 1; capa->config.pktin.bit.udp_chksum = 1; + capa->config.pktin.bit.sctp_chksum = 1; capa->config.pktout.bit.ipv4_chksum = 1; capa->config.pktout.bit.tcp_chksum = 1; capa->config.pktout.bit.udp_chksum = 1; + capa->config.pktout.bit.sctp_chksum = 1; capa->config.inbound_ipsec = 1; capa->config.outbound_ipsec = 1; @@ -388,6 +399,8 @@ static int loopback_init_capability(pktio_entry_t *pktio_entry) capa->config.pktout.bit.udp_chksum; capa->config.pktout.bit.tcp_chksum_ena = capa->config.pktout.bit.tcp_chksum; + capa->config.pktout.bit.sctp_chksum_ena = + capa->config.pktout.bit.sctp_chksum; return 0; } From patchwork Tue Aug 21 17:00:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6, 11/12] linux-gen: ipsec: insert checksum into SCTP packets if required X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144757 Message-Id: <1534870807-18456-12-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 17:00:06 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ platform/linux-generic/odp_ipsec.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index d10100f53..1bc549c22 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -1306,7 +1306,8 @@ static void ipsec_out_ah_post(ipsec_state_t *state, odp_packet_t pkt) 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_bool_t ipv4_chksum_pkt, udp_chksum_pkt, tcp_chksum_pkt, + sctp_chksum_pkt; odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); odp_ipsec_outbound_config_t outbound = ipsec_config.outbound; @@ -1325,6 +1326,12 @@ static void ipsec_out_checksums(odp_packet_t pkt, pkt_hdr->p.flags.l4_chksum_set, pkt_hdr->p.flags.l4_chksum); + sctp_chksum_pkt = OL_TX_CHKSUM_PKT(outbound.chksum.inner_sctp, + state->ip_next_hdr == + _ODP_IPPROTO_SCTP, + pkt_hdr->p.flags.l4_chksum_set, + pkt_hdr->p.flags.l4_chksum); + if (ipv4_chksum_pkt) _odp_packet_ipv4_chksum_insert(pkt); @@ -1333,6 +1340,9 @@ static void ipsec_out_checksums(odp_packet_t pkt, if (udp_chksum_pkt) _odp_packet_udp_chksum_insert(pkt); + + if (sctp_chksum_pkt) + _odp_packet_sctp_chksum_insert(pkt); } static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, From patchwork Tue Aug 21 17:00:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v6,12/12] validation: pktio: add SCTP checksum tests X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 144761 Message-Id: <1534870807-18456-13-git-send-email-odpbot@yandex.ru> To: lng-odp@lists.linaro.org Date: Tue, 21 Aug 2018 17:00:07 +0000 From: Github ODP bot List-Id: "The OpenDataPlane \(ODP\) List" From: Dmitry Eremin-Solenikov Add tests validating SCTP checksumming on pkt out and checksum verification on pkt in. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 674 (lumag:sctp-checksum) ** https://github.com/Linaro/odp/pull/674 ** Patch: https://github.com/Linaro/odp/pull/674.patch ** Base sha: f6c423a7d29e2c7d6d890cbc098a398d0d7e1288 ** Merge commit sha: d4f772b36da26684194cb0452a01b8da1ba7e3e1 **/ test/validation/api/pktio/pktio.c | 415 +++++++++++++++++++++++++++--- 1 file changed, 381 insertions(+), 34 deletions(-) diff --git a/test/validation/api/pktio/pktio.c b/test/validation/api/pktio/pktio.c index 625cc325e..3f0826744 100644 --- a/test/validation/api/pktio/pktio.c +++ b/test/validation/api/pktio/pktio.c @@ -164,7 +164,7 @@ static void pktio_pkt_set_macs(odp_packet_t pkt, odp_pktio_t src, odp_pktio_t ds CU_ASSERT(ret <= ODP_PKTIO_MACADDR_MAXSIZE); } -static uint32_t pktio_pkt_set_seq(odp_packet_t pkt) +static uint32_t pktio_pkt_set_seq(odp_packet_t pkt, size_t l4_hdr_len) { static uint32_t tstseq; size_t off; @@ -180,7 +180,7 @@ static uint32_t pktio_pkt_set_seq(odp_packet_t pkt) head.magic = TEST_SEQ_MAGIC; head.seq = tstseq; - off += ODPH_UDPHDR_LEN; + off += l4_hdr_len; if (odp_packet_copy_from_mem(pkt, off, sizeof(head), &head) != 0) return TEST_SEQ_INVALID; @@ -194,7 +194,7 @@ static uint32_t pktio_pkt_set_seq(odp_packet_t pkt) return head.seq; } -static uint32_t pktio_pkt_seq(odp_packet_t pkt) +static uint32_t pktio_pkt_seq_hdr(odp_packet_t pkt, size_t l4_hdr_len) { size_t off; uint32_t seq = TEST_SEQ_INVALID; @@ -212,7 +212,7 @@ static uint32_t pktio_pkt_seq(odp_packet_t pkt) return TEST_SEQ_INVALID; } - off += ODPH_UDPHDR_LEN; + off += l4_hdr_len; if (odp_packet_copy_to_mem(pkt, off, sizeof(head), &head) != 0) { fprintf(stderr, "error: header copy failed\n"); return TEST_SEQ_INVALID; @@ -250,11 +250,15 @@ static uint32_t pktio_pkt_seq(odp_packet_t pkt) return seq; } -static uint32_t pktio_init_packet(odp_packet_t pkt) +static uint32_t pktio_pkt_seq(odp_packet_t pkt) +{ + return pktio_pkt_seq_hdr(pkt, ODPH_UDPHDR_LEN); +} + +static void pktio_init_packet_eth_ipv4(odp_packet_t pkt, uint8_t proto) { odph_ethhdr_t *eth; odph_ipv4hdr_t *ip; - odph_udphdr_t *udp; char *buf; uint16_t seq; uint8_t src_mac[ODP_PKTIO_MACADDR_MAXSIZE] = PKTIO_SRC_MAC; @@ -278,11 +282,22 @@ static uint32_t pktio_init_packet(odp_packet_t pkt) ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN; ip->tot_len = odp_cpu_to_be_16(pkt_len - ODPH_ETHHDR_LEN); ip->ttl = 128; - ip->proto = ODPH_IPPROTO_UDP; + ip->proto = proto; seq = odp_atomic_fetch_inc_u32(&ip_seq); ip->id = odp_cpu_to_be_16(seq); ip->chksum = 0; odph_ipv4_csum_update(pkt); +} + +static uint32_t pktio_init_packet_udp(odp_packet_t pkt) +{ + odph_udphdr_t *udp; + char *buf; + int pkt_len = odp_packet_len(pkt); + + buf = odp_packet_data(pkt); + + pktio_init_packet_eth_ipv4(pkt, ODPH_IPPROTO_UDP); /* UDP */ odp_packet_l4_offset_set(pkt, ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); @@ -293,40 +308,76 @@ static uint32_t pktio_init_packet(odp_packet_t pkt) ODPH_ETHHDR_LEN - ODPH_IPV4HDR_LEN); udp->chksum = 0; - return pktio_pkt_set_seq(pkt); + return pktio_pkt_set_seq(pkt, ODPH_UDPHDR_LEN); +} + +static uint32_t pktio_init_packet_sctp(odp_packet_t pkt) +{ + odph_sctphdr_t *sctp; + char *buf; + + buf = odp_packet_data(pkt); + + pktio_init_packet_eth_ipv4(pkt, ODPH_IPPROTO_SCTP); + + /* SCTP */ + odp_packet_l4_offset_set(pkt, ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); + sctp = (odph_sctphdr_t *)(buf + ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); + sctp->src_port = odp_cpu_to_be_16(12049); + sctp->dst_port = odp_cpu_to_be_16(12050); + sctp->tag = 0; + sctp->chksum = 0; + + return pktio_pkt_set_seq(pkt, ODPH_SCTPHDR_LEN); } static int pktio_zero_checksums(odp_packet_t pkt) { odph_ipv4hdr_t *ip; - odph_udphdr_t *udp; uint32_t len; ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, &len); - if (ip->proto != ODPH_IPPROTO_UDP) { + ip->chksum = 0; + + if (ip->proto == ODPH_IPPROTO_UDP) { + odph_udphdr_t *udp; + + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, &len); + udp->chksum = 0; + } else if (ip->proto == ODPH_IPPROTO_SCTP) { + odph_sctphdr_t *sctp; + + sctp = (odph_sctphdr_t *)odp_packet_l4_ptr(pkt, &len); + sctp->chksum = 0; + } else { CU_FAIL("unexpected L4 protocol"); return -1; } - udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, &len); - - ip->chksum = 0; - udp->chksum = 0; - return 0; } static int pktio_fixup_checksums(odp_packet_t pkt) { - odph_udphdr_t *udp; + odph_ipv4hdr_t *ip; 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); + + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); + if (ip->proto == ODPH_IPPROTO_UDP) { + odph_udphdr_t *udp; + + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); + udp->chksum = odph_ipv4_udp_chksum(pkt); + } else if (ip->proto == ODPH_IPPROTO_SCTP) { + odph_sctp_chksum_set(pkt); + } else { + CU_FAIL("unexpected L4 protocol"); + return -1; + } return 0; } @@ -419,12 +470,12 @@ static int flush_input_queue(odp_pktio_t pktio, odp_pktin_mode_t imode) return 0; } -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) +static int create_packets_udp(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, ret; @@ -433,7 +484,7 @@ static int create_packets_cs(odp_packet_t pkt_tbl[], if (pkt_tbl[i] == ODP_PACKET_INVALID) break; - pkt_seq[i] = pktio_init_packet(pkt_tbl[i]); + pkt_seq[i] = pktio_init_packet_udp(pkt_tbl[i]); if (pkt_seq[i] == TEST_SEQ_INVALID) { odp_packet_free(pkt_tbl[i]); break; @@ -454,11 +505,42 @@ static int create_packets_cs(odp_packet_t pkt_tbl[], return i; } +static int create_packets_sctp(odp_packet_t pkt_tbl[], + uint32_t pkt_seq[], + int num, + odp_pktio_t pktio_src, + odp_pktio_t pktio_dst) +{ + int i, ret; + + for (i = 0; i < num; i++) { + pkt_tbl[i] = odp_packet_alloc(default_pkt_pool, packet_len); + if (pkt_tbl[i] == ODP_PACKET_INVALID) + break; + + pkt_seq[i] = pktio_init_packet_sctp(pkt_tbl[i]); + if (pkt_seq[i] == TEST_SEQ_INVALID) { + odp_packet_free(pkt_tbl[i]); + break; + } + + pktio_pkt_set_macs(pkt_tbl[i], pktio_src, pktio_dst); + + ret = pktio_zero_checksums(pkt_tbl[i]); + if (ret != 0) { + odp_packet_free(pkt_tbl[i]); + break; + } + } + + 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); + return create_packets_udp(pkt_tbl, pkt_seq, num, pktio_src, pktio_dst, + true); } static int get_packets(pktio_info_t *pktio_rx, odp_packet_t pkt_tbl[], @@ -506,9 +588,9 @@ static int get_packets(pktio_info_t *pktio_rx, odp_packet_t pkt_tbl[], return num_pkts; } -static int wait_for_packets(pktio_info_t *pktio_rx, odp_packet_t pkt_tbl[], - uint32_t seq_tbl[], int num, txrx_mode_e mode, - uint64_t ns) +static int wait_for_packets_hdr(pktio_info_t *pktio_rx, odp_packet_t pkt_tbl[], + uint32_t seq_tbl[], int num, txrx_mode_e mode, + uint64_t ns, size_t l4_hdr_len) { odp_time_t wait_time, end; int num_rx = 0; @@ -525,7 +607,8 @@ static int wait_for_packets(pktio_info_t *pktio_rx, odp_packet_t pkt_tbl[], break; for (i = 0; i < n; ++i) { - if (pktio_pkt_seq(pkt_tmp[i]) == seq_tbl[num_rx]) + if (pktio_pkt_seq_hdr(pkt_tmp[i], l4_hdr_len) == + seq_tbl[num_rx]) pkt_tbl[num_rx++] = pkt_tmp[i]; else odp_packet_free(pkt_tmp[i]); @@ -535,6 +618,14 @@ static int wait_for_packets(pktio_info_t *pktio_rx, odp_packet_t pkt_tbl[], return num_rx; } +static int wait_for_packets(pktio_info_t *pktio_rx, odp_packet_t pkt_tbl[], + uint32_t seq_tbl[], int num, txrx_mode_e mode, + uint64_t ns) +{ + return wait_for_packets_hdr(pktio_rx, pkt_tbl, seq_tbl, num, mode, ns, + ODPH_UDPHDR_LEN); +} + static int recv_packets_tmo(odp_pktio_t pktio, odp_packet_t pkt_tbl[], uint32_t seq_tbl[], int num, recv_tmo_mode_e mode, uint64_t tmo, uint64_t ns, int no_pkt) @@ -1956,8 +2047,8 @@ static void pktio_test_chksum(void (*config_fn)(odp_pktio_t, odp_pktio_t), _pktio_wait_linkup(pktio[i]); } - ret = create_packets_cs(pkt_tbl, pkt_seq, TX_BATCH_LEN, pktio_tx, - pktio_rx, false); + ret = create_packets_udp(pkt_tbl, pkt_seq, TX_BATCH_LEN, pktio_tx, + pktio_rx, false); CU_ASSERT(ret == TX_BATCH_LEN); if (ret != TX_BATCH_LEN) { for (i = 0; i < num_ifaces; i++) { @@ -1990,6 +2081,75 @@ static void pktio_test_chksum(void (*config_fn)(odp_pktio_t, odp_pktio_t), } } +static void pktio_test_chksum_sctp(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_sctp(pkt_tbl, pkt_seq, TX_BATCH_LEN, pktio_tx, + pktio_rx); + CU_ASSERT(ret == TX_BATCH_LEN); + if (ret != TX_BATCH_LEN) { + 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); + } + return; + } + + 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_hdr(&pktio_rx_info, pkt_tbl, pkt_seq, + TX_BATCH_LEN, TXRX_MODE_MULTI, + ODP_TIME_SEC_IN_NS, ODPH_SCTPHDR_LEN); + 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; @@ -2105,6 +2265,65 @@ static void pktio_test_chksum_in_udp(void) pktio_test_chksum_in_udp_test); } +static int pktio_check_chksum_in_sctp(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.sctp_chksum) + return ODP_TEST_INACTIVE; + + return ODP_TEST_ACTIVE; +} + +static void pktio_test_chksum_in_sctp_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.sctp_chksum); + + odp_pktio_config_init(&config); + config.pktin.bit.sctp_chksum = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_rx, &config) == 0); +} + +static void pktio_test_chksum_in_sctp_prep(odp_packet_t pkt) +{ + odp_packet_has_ipv4_set(pkt, 1); + odp_packet_has_sctp_set(pkt, 1); + odph_ipv4_csum_update(pkt); + odph_sctp_chksum_set(pkt); +} + +static void pktio_test_chksum_in_sctp_test(odp_packet_t pkt) +{ + CU_ASSERT(odp_packet_l4_chksum_status(pkt) == ODP_PACKET_CHKSUM_OK); +} + +static void pktio_test_chksum_in_sctp(void) +{ + pktio_test_chksum_sctp(pktio_test_chksum_in_sctp_config, + pktio_test_chksum_in_sctp_prep, + pktio_test_chksum_in_sctp_test); +} + static int pktio_check_chksum_out_ipv4(void) { odp_pktio_t pktio; @@ -2340,6 +2559,126 @@ static void pktio_test_chksum_out_udp_pktio(void) pktio_test_chksum_out_udp_test); } +static int pktio_check_chksum_out_sctp(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.sctp_chksum_ena || + !capa.config.pktout.bit.sctp_chksum) + return ODP_TEST_INACTIVE; + + return ODP_TEST_ACTIVE; +} + +static void pktio_test_chksum_out_sctp_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.sctp_chksum_ena); + CU_ASSERT_FATAL(capa.config.pktout.bit.sctp_chksum); + + odp_pktio_config_init(&config); + config.pktout.bit.sctp_chksum_ena = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_tx, &config) == 0); +} + +static void pktio_test_chksum_out_sctp_test(odp_packet_t pkt) +{ + odph_sctphdr_t *sctp = odp_packet_l4_ptr(pkt, NULL); + + CU_ASSERT(sctp != NULL); + if (sctp != NULL) { + CU_ASSERT(sctp->chksum != 0); + CU_ASSERT(!odph_sctp_chksum_verify(pkt)); + } +} + +static void pktio_test_chksum_out_sctp_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_sctp_no_ovr_test(odp_packet_t pkt) +{ + odph_sctphdr_t *sctp = odp_packet_l4_ptr(pkt, NULL); + + CU_ASSERT(sctp != NULL); + if (sctp != NULL) + CU_ASSERT(sctp->chksum == 0); +} + +static void pktio_test_chksum_out_sctp_no_ovr(void) +{ + pktio_test_chksum_sctp(pktio_test_chksum_out_sctp_config, + pktio_test_chksum_out_sctp_no_ovr_prep, + pktio_test_chksum_out_sctp_no_ovr_test); +} + +static void pktio_test_chksum_out_sctp_ovr_prep(odp_packet_t pkt) +{ + odp_packet_l4_chksum_insert(pkt, true); +} + +static void pktio_test_chksum_out_sctp_ovr_test(odp_packet_t pkt) +{ + odph_sctphdr_t *sctp = odp_packet_l4_ptr(pkt, NULL); + + CU_ASSERT(sctp != NULL); + if (sctp != NULL) { + CU_ASSERT(sctp->chksum != 0); + CU_ASSERT(!odph_sctp_chksum_verify(pkt)); + } +} + +static void pktio_test_chksum_out_sctp_ovr(void) +{ + pktio_test_chksum_sctp(pktio_test_chksum_out_sctp_config, + pktio_test_chksum_out_sctp_ovr_prep, + pktio_test_chksum_out_sctp_ovr_test); +} + +static void pktio_test_chksum_out_sctp_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.sctp_chksum_ena); + CU_ASSERT_FATAL(capa.config.pktout.bit.sctp_chksum); + + odp_pktio_config_init(&config); + config.pktout.bit.sctp_chksum_ena = 1; + config.pktout.bit.sctp_chksum = 1; + CU_ASSERT_FATAL(odp_pktio_config(pktio_tx, &config) == 0); +} + +static void pktio_test_chksum_out_sctp_pktio(void) +{ + pktio_test_chksum_sctp(pktio_test_chksum_out_sctp_pktio_config, + NULL, + pktio_test_chksum_out_sctp_test); +} + static int create_pool(const char *iface, int num) { char pool_name[ODP_POOL_NAME_LEN]; @@ -2484,6 +2823,8 @@ odp_testinfo_t pktio_suite_unsegmented[] = { 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_in_sctp, + pktio_check_chksum_in_sctp), 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, @@ -2496,6 +2837,12 @@ odp_testinfo_t pktio_suite_unsegmented[] = { pktio_check_chksum_out_udp), ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_udp_ovr, pktio_check_chksum_out_udp), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_sctp_no_ovr, + pktio_check_chksum_out_sctp), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_sctp_pktio, + pktio_check_chksum_out_sctp), + ODP_TEST_INFO_CONDITIONAL(pktio_test_chksum_out_sctp_ovr, + pktio_check_chksum_out_sctp), ODP_TEST_INFO_NULL };