From: Dmitry Eremin-Solenikov <dmitry.ereminsoleni...@linaro.org>

Add functions to set and verify SCTP packet checksum.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsoleni...@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: dc28824415ea510e3ef62e47f7640bf4a8420fde
 ** Merge commit sha: b482f9618a6edb2a2f2491ee5a7af757eab93b24
 **/
 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..ac273dd01 100644
--- a/helper/chksum.c
+++ b/helper/chksum.c
@@ -9,6 +9,7 @@
 #include <odp.h>
 #include <odp/helper/ip.h>
 #include <odp/helper/udp.h>
+#include <odp/helper/sctp.h>
 #include <odp/helper/tcp.h>
 #include <odp/helper/chksum.h>
 #include <stddef.h>
@@ -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;
+}
diff --git a/helper/include/odp/helper/chksum.h 
b/helper/include/odp/helper/chksum.h
index c03abeb7b..28695ea88 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.
+ * @return             0 upon success and < 0 upon 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.
+ * @return             Returns < 0 upon an error.  Returns 1 upon no error and
+ *                     the incoming chksum field is 0 (disabled), else returns 0
+ *                     if the incoming chksum field is correct, else returns 2
+ *                     when the chksum field is incorrect.
+ */
+int odph_sctp_chksum_verify(odp_packet_t odp_pkt);
+
 /**
  * @}
  */

Reply via email to