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

Add support for insertion of checksum into SCTP packets.

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
 **/
 .../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 cd2db2ecd..90108c567 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)

Reply via email to