[v6,8/12] linux-gen: packet: parse SCTP packets and verify checksum

Message ID 1534870807-18456-9-git-send-email-odpbot@yandex.ru
State New
Headers show
Series
  • SCTP checksums support
Related show

Commit Message

Github ODP bot Aug. 21, 2018, 5 p.m.
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>


Verify SCTP packet checksums. Use CRC32-c as requied by RFC3309 instead
of original Adler-32.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>

---
/** 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(-)

Patch

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 <protocols/eth.h>
 #include <protocols/ip.h>
+#include <protocols/sctp.h>
 #include <protocols/tcp.h>
 #include <protocols/udp.h>
 
@@ -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;
 }