@@ -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;
+}
@@ -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);
+
/**
* @}
*/