diff options
author | Jere Leppänen <jere.leppanen@nokia.com> | 2022-02-02 17:01:59 +0200 |
---|---|---|
committer | Petri Savolainen <petri.savolainen@nokia.com> | 2022-03-10 09:33:44 +0200 |
commit | 3924507d7a375c1ac48760586971d3b488d54aae (patch) | |
tree | 16cd4d416457019725316ee59da4905afe121220 | |
parent | 37072db5ae3644223769ce9ea65d93ff25c9fe81 (diff) |
linux-gen: packet: move parse functions to new source files
Move packet parsing functions to new odp_parse.c and
odp_parse_internal.h files.
Signed-off-by: Jere Leppänen <jere.leppanen@nokia.com>
Reviewed-by: Matias Elo <matias.elo@nokia.com>
Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com>
-rw-r--r-- | platform/linux-generic/Makefile.am | 2 | ||||
-rw-r--r-- | platform/linux-generic/include/odp_macros_internal.h | 2 | ||||
-rw-r--r-- | platform/linux-generic/include/odp_packet_internal.h | 42 | ||||
-rw-r--r-- | platform/linux-generic/include/odp_parse_internal.h | 104 | ||||
-rw-r--r-- | platform/linux-generic/odp_packet.c | 541 | ||||
-rw-r--r-- | platform/linux-generic/odp_parse.c | 496 | ||||
-rw-r--r-- | platform/linux-generic/pktio/loop.c | 1 | ||||
-rw-r--r-- | platform/linux-generic/pktio/netmap.c | 1 | ||||
-rw-r--r-- | platform/linux-generic/pktio/pcap.c | 1 | ||||
-rw-r--r-- | platform/linux-generic/pktio/socket.c | 1 | ||||
-rw-r--r-- | platform/linux-generic/pktio/socket_mmap.c | 1 | ||||
-rw-r--r-- | platform/linux-generic/pktio/tap.c | 1 |
12 files changed, 632 insertions, 561 deletions
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index fc73925e5..0e95d96a9 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -126,6 +126,7 @@ noinst_HEADERS = \ include/odp_packet_dpdk.h \ include/odp_packet_internal.h \ include/odp_packet_io_internal.h \ + include/odp_parse_internal.h \ include/odp_socket_common.h \ include/odp_packet_io_stats_common.h \ include/odp_packet_io_stats.h \ @@ -202,6 +203,7 @@ __LIB__libodp_linux_la_SOURCES = \ odp_packet_vector.c \ odp_packet_flags.c \ odp_packet_io.c \ + odp_parse.c \ odp_pkt_queue.c \ odp_pool.c \ odp_queue_basic.c \ diff --git a/platform/linux-generic/include/odp_macros_internal.h b/platform/linux-generic/include/odp_macros_internal.h index 997e0fd5b..b8be7f938 100644 --- a/platform/linux-generic/include/odp_macros_internal.h +++ b/platform/linux-generic/include/odp_macros_internal.h @@ -35,6 +35,8 @@ extern "C" { tmp_a > tmp_b ? tmp_a : tmp_b; \ }) +#define MAX3(a, b, c) (MAX(MAX((a), (b)), (c))) + #define odp_container_of(pointer, type, member) \ ((type *)(void *)(((char *)pointer) - offsetof(type, member))) diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 6a557943c..868b4ef56 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -38,15 +38,23 @@ extern "C" { #include <stdint.h> #include <string.h> -/** Minimum segment length expected by _odp_packet_parse_common() */ -#define PACKET_PARSE_SEG_LEN 96 - ODP_STATIC_ASSERT(sizeof(_odp_packet_input_flags_t) == sizeof(uint64_t), "INPUT_FLAGS_SIZE_ERROR"); ODP_STATIC_ASSERT(sizeof(_odp_packet_flags_t) == sizeof(uint32_t), "PACKET_FLAGS_SIZE_ERROR"); +/* Packet extra data length */ +#define PKT_EXTRA_LEN 128 + +/* Packet extra data types */ +#define PKT_EXTRA_TYPE_DPDK 1 + +/* Maximum number of segments per packet */ +#define PKT_MAX_SEGS 255 + +ODP_STATIC_ASSERT(PKT_MAX_SEGS < UINT16_MAX, "PACKET_MAX_SEGS_ERROR"); + /** * Packet parser metadata */ @@ -67,17 +75,6 @@ typedef struct { uint16_t l4_offset; } packet_parser_t; -/* Packet extra data length */ -#define PKT_EXTRA_LEN 128 - -/* Packet extra data types */ -#define PKT_EXTRA_TYPE_DPDK 1 - -/* Maximum number of segments per packet */ -#define PKT_MAX_SEGS 255 - -ODP_STATIC_ASSERT(PKT_MAX_SEGS < UINT16_MAX, "PACKET_MAX_SEGS_ERROR"); - /** * Internal Packet header * @@ -198,6 +195,11 @@ static inline odp_packet_t packet_from_event_hdr(_odp_event_hdr_t *event_hdr) return (odp_packet_t)(uintptr_t)event_hdr; } +static inline uint32_t packet_first_seg_len(odp_packet_hdr_t *pkt_hdr) +{ + return pkt_hdr->seg_len; +} + static inline odp_packet_hdr_t *packet_last_seg(odp_packet_hdr_t *hdr) { while (hdr->seg_next != NULL) @@ -404,11 +406,6 @@ static inline void packet_set_len(odp_packet_hdr_t *pkt_hdr, uint32_t len) int _odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, odp_packet_t pkt[], int max_num); -/* Perform packet parse up to a given protocol layer */ -int _odp_packet_parse_layer(odp_packet_hdr_t *pkt_hdr, - odp_proto_layer_t layer, - odp_proto_chksums_t chksums); - /* Reset parser metadata for a new parse */ static inline void packet_parse_reset(odp_packet_hdr_t *pkt_hdr, int all) { @@ -458,10 +455,6 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts) } } -int _odp_packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr, - uint32_t pkt_len, uint32_t seg_len, int layer, - odp_proto_chksums_t chksums); - int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr); int _odp_packet_set_data(odp_packet_t pkt, uint32_t offset, @@ -475,6 +468,9 @@ 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); +int packet_l4_chksum(odp_packet_hdr_t *pkt_hdr, odp_proto_chksums_t chksums, + uint64_t l4_part_sum); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/include/odp_parse_internal.h b/platform/linux-generic/include/odp_parse_internal.h new file mode 100644 index 000000000..99b730a58 --- /dev/null +++ b/platform/linux-generic/include/odp_parse_internal.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2013-2018, Linaro Limited + * Copyright (c) 2019-2022, Nokia + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_PARSE_INTERNAL_H_ +#define ODP_PARSE_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp_packet_internal.h> +#include <odp_macros_internal.h> +#include <protocols/eth.h> +#include <protocols/ip.h> +#include <protocols/sctp.h> +#include <protocols/tcp.h> +#include <protocols/udp.h> +#include <odp/api/plat/packet_inline_types.h> +#include <odp/api/hints.h> +#include <odp/api/packet_io.h> +#include <odp/api/packet_types.h> +#include <stdint.h> + +/** Minimum segment length expected by _odp_packet_parse_common() */ +#define PACKET_PARSE_SEG_LEN 96 +/* + * In the worst case we look at the Ethernet header, 8 bytes of LLC/SNAP + * header and two VLAN tags in the same packet. + */ +#define PARSE_ETH_BYTES (sizeof(_odp_ethhdr_t) + 8 + 2 * sizeof(_odp_vlanhdr_t)) +#define PARSE_IPV4_BYTES (0xfU * 4) /* max IPv4 header length with options */ +/* + * Peeks 2 bytes beyond IPv6 base header without length check if there + * are extension headers. + */ +#define PARSE_IPV6_BYTES (sizeof(_odp_ipv6hdr_t) + 2) +#define PARSE_TCP_BYTES (sizeof(_odp_tcphdr_t)) +/* + * In the worst case we look at the UDP header and 4 bytes of the UDP + * payload (the non-ESP marker to distinguish IKE packets from ESP packets). + */ +#define PARSE_UDP_BYTES (sizeof(_odp_udphdr_t) + 4) +#define PARSE_SCTP_BYTES (sizeof(_odp_sctphdr_t)) + +#define PARSE_L3_L4_BYTES (MAX(PARSE_IPV4_BYTES, PARSE_IPV6_BYTES) + \ + MAX3(PARSE_TCP_BYTES, PARSE_UDP_BYTES, PARSE_SCTP_BYTES)) + +uint16_t parse_eth(packet_parser_t *prs, const uint8_t **parseptr, + uint32_t *offset, uint32_t frame_len); + +int packet_parse_common_l3_l4(packet_parser_t *prs, const uint8_t *parseptr, + uint32_t offset, + uint32_t frame_len, uint32_t seg_len, + int layer, uint16_t ethtype, + odp_proto_chksums_t chksums, + uint64_t *l4_part_sum); + +/** + * Parse common packet headers up to given layer + * + * The function expects at least PACKET_PARSE_SEG_LEN bytes of data to be + * available from the ptr. Also parse metadata must be already initialized. + */ +static inline int _odp_packet_parse_common(packet_parser_t *prs, + const uint8_t *ptr, + uint32_t frame_len, uint32_t seg_len, + int layer, + odp_proto_chksums_t chksums) +{ + uint32_t offset; + uint16_t ethtype; + const uint8_t *parseptr; + uint64_t l4_part_sum; + + parseptr = ptr; + offset = 0; + + if (odp_unlikely(layer == ODP_PROTO_LAYER_NONE)) + return 0; + + /* Assume valid L2 header, no CRC/FCS check in SW */ + prs->l2_offset = offset; + + ethtype = parse_eth(prs, &parseptr, &offset, frame_len); + + return packet_parse_common_l3_l4(prs, parseptr, offset, frame_len, + seg_len, layer, ethtype, chksums, + &l4_part_sum); +} + +/* Perform packet parse up to a given protocol layer */ +int _odp_packet_parse_layer(odp_packet_hdr_t *pkt_hdr, + odp_proto_layer_t layer, + odp_proto_chksums_t chksums); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index d89beeee3..a49c8911b 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -16,6 +16,7 @@ #include <odp/api/proto_stats.h> #include <odp/api/timer.h> +#include <odp_parse_internal.h> #include <odp_chksum_internal.h> #include <odp_debug_internal.h> #include <odp_errno_define.h> @@ -131,11 +132,6 @@ static inline uint32_t packet_seg_len(odp_packet_hdr_t *pkt_hdr, return pkt_hdr->seg_len; } -static inline uint32_t packet_first_seg_len(odp_packet_hdr_t *pkt_hdr) -{ - return pkt_hdr->seg_len; -} - static inline void *packet_tail(odp_packet_hdr_t *pkt_hdr) { odp_packet_hdr_t *last_seg = packet_last_seg(pkt_hdr); @@ -1771,500 +1767,6 @@ static uint32_t packet_sum_crc32c(odp_packet_hdr_t *pkt_hdr, return sum; } -/* - * In the worst case we look at the Ethernet header, 8 bytes of LLC/SNAP - * header and two VLAN tags in the same packet. - */ -#define PARSE_ETH_BYTES (sizeof(_odp_ethhdr_t) + 8 + 2 * sizeof(_odp_vlanhdr_t)) -/** Parser helper function for Ethernet packets - * - * Requires up to PARSE_ETH_BYTES bytes of contiguous packet data. - */ -static inline uint16_t parse_eth(packet_parser_t *prs, const uint8_t **parseptr, - uint32_t *offset, uint32_t frame_len) -{ - uint16_t ethtype; - const _odp_ethhdr_t *eth; - uint16_t macaddr0, macaddr2, macaddr4; - const _odp_vlanhdr_t *vlan; - _odp_packet_input_flags_t input_flags; - - input_flags.all = 0; - input_flags.l2 = 1; - input_flags.eth = 1; - - eth = (const _odp_ethhdr_t *)*parseptr; - - /* Detect jumbo frames */ - if (odp_unlikely(frame_len - *offset > _ODP_ETH_LEN_MAX)) - input_flags.jumbo = 1; - - /* Handle Ethernet broadcast/multicast addresses */ - macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth)); - if (odp_unlikely((macaddr0 & 0x0100) == 0x0100)) - input_flags.eth_mcast = 1; - - if (odp_unlikely(macaddr0 == 0xffff)) { - macaddr2 = - odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth + 1)); - macaddr4 = - odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth + 2)); - - if ((macaddr2 == 0xffff) && (macaddr4 == 0xffff)) - input_flags.eth_bcast = 1; - } - - /* Get Ethertype */ - ethtype = odp_be_to_cpu_16(eth->type); - *offset += sizeof(*eth); - *parseptr += sizeof(*eth); - - /* Check for SNAP vs. DIX */ - if (odp_unlikely(ethtype < _ODP_ETH_LEN_MAX)) { - input_flags.snap = 1; - if (ethtype > frame_len - *offset) { - prs->flags.snap_len_err = 1; - ethtype = 0; - goto error; - } - ethtype = odp_be_to_cpu_16(*((const uint16_t *)(uintptr_t) - (*parseptr + 6))); - *offset += 8; - *parseptr += 8; - } - - /* Parse the VLAN header(s), if present */ - if (odp_unlikely(ethtype == _ODP_ETHTYPE_VLAN_OUTER)) { - input_flags.vlan_qinq = 1; - input_flags.vlan = 1; - - vlan = (const _odp_vlanhdr_t *)*parseptr; - ethtype = odp_be_to_cpu_16(vlan->type); - *offset += sizeof(_odp_vlanhdr_t); - *parseptr += sizeof(_odp_vlanhdr_t); - } - - if (ethtype == _ODP_ETHTYPE_VLAN) { - input_flags.vlan = 1; - vlan = (const _odp_vlanhdr_t *)*parseptr; - ethtype = odp_be_to_cpu_16(vlan->type); - *offset += sizeof(_odp_vlanhdr_t); - *parseptr += sizeof(_odp_vlanhdr_t); - } - - /* - * The packet was too short for what we parsed. We just give up - * entirely without trying to parse what fits in the packet. - */ - if (odp_unlikely(*offset > frame_len)) { - input_flags.all = 0; - input_flags.l2 = 1; - ethtype = 0; - } - -error: - prs->input_flags.all |= input_flags.all; - - return ethtype; -} - -#define PARSE_IPV4_BYTES (0xfU * 4) /* max IPv4 header length with options */ -/** - * Parser helper function for IPv4 - * - * Requires up to PARSE_IPV4_BYTES bytes of contiguous packet data. - */ -static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, - uint32_t *offset, uint32_t frame_len, - odp_proto_chksums_t chksums, - uint64_t *l4_part_sum) -{ - const _odp_ipv4hdr_t *ipv4 = (const _odp_ipv4hdr_t *)*parseptr; - uint32_t dstaddr = odp_be_to_cpu_32(ipv4->dst_addr); - uint32_t l3_len = odp_be_to_cpu_16(ipv4->tot_len); - uint16_t frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); - uint8_t ver = _ODP_IPV4HDR_VER(ipv4->ver_ihl); - uint8_t ihl = _ODP_IPV4HDR_IHL(ipv4->ver_ihl); - - if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN || - ver != 4 || - sizeof(*ipv4) > frame_len - *offset || - (l3_len > frame_len - *offset))) { - prs->flags.ip_err = 1; - return 0; - } - - if (chksums.chksum.ipv4) { - prs->input_flags.l3_chksum_done = 1; - if (chksum_finalize(chksum_partial(ipv4, ihl * 4, 0)) != 0xffff) { - prs->flags.ip_err = 1; - prs->flags.l3_chksum_err = 1; - return 0; - } - } - - *offset += ihl * 4; - *parseptr += ihl * 4; - - if (chksums.chksum.udp || chksums.chksum.tcp) - *l4_part_sum = chksum_partial((const uint8_t *)&ipv4->src_addr, - 2 * _ODP_IPV4ADDR_LEN, 0); - - if (odp_unlikely(ihl > _ODP_IPV4HDR_IHL_MIN)) - prs->input_flags.ipopt = 1; - - /* A packet is a fragment if: - * "more fragments" flag is set (all fragments except the last) - * OR - * "fragment offset" field is nonzero (all fragments except the first) - */ - if (odp_unlikely(_ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) - prs->input_flags.ipfrag = 1; - - /* Handle IPv4 broadcast / multicast */ - if (odp_unlikely(dstaddr == 0xffffffff)) - prs->input_flags.ip_bcast = 1; - - if (odp_unlikely((dstaddr >> 28) == 0xe)) - prs->input_flags.ip_mcast = 1; - - return ipv4->proto; -} - -/* - * Peeks 2 bytes beyond IPv6 base header without length check if there - * are extension headers. - */ -#define PARSE_IPV6_BYTES (sizeof(_odp_ipv6hdr_t) + 2) -/** - * Parser helper function for IPv6 - * - * Requires at least PARSE_IPV6_BYTES bytes of contiguous packet data. - */ -static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, - uint32_t *offset, uint32_t frame_len, - uint32_t seg_len, - odp_proto_chksums_t chksums, - uint64_t *l4_part_sum) -{ - const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr; - const _odp_ipv6hdr_ext_t *ipv6ext; - uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr.u8[0]); - uint32_t l3_len = odp_be_to_cpu_16(ipv6->payload_len) + - _ODP_IPV6HDR_LEN; - - /* Basic sanity checks on IPv6 header */ - if (odp_unlikely((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || - sizeof(*ipv6) > frame_len - *offset || - l3_len > frame_len - *offset)) { - prs->flags.ip_err = 1; - return 0; - } - - /* IPv6 broadcast / multicast flags */ - prs->input_flags.ip_mcast = (dstaddr0 & 0xff000000) == 0xff000000; - prs->input_flags.ip_bcast = 0; - - /* Skip past IPv6 header */ - *offset += sizeof(_odp_ipv6hdr_t); - *parseptr += sizeof(_odp_ipv6hdr_t); - - if (chksums.chksum.udp || chksums.chksum.tcp) - *l4_part_sum = chksum_partial((const uint8_t *)&ipv6->src_addr, - 2 * _ODP_IPV6ADDR_LEN, 0); - - /* Skip past any IPv6 extension headers */ - if (ipv6->next_hdr == _ODP_IPPROTO_HOPOPTS || - ipv6->next_hdr == _ODP_IPPROTO_ROUTE) { - prs->input_flags.ipopt = 1; - - do { - ipv6ext = (const _odp_ipv6hdr_ext_t *)*parseptr; - uint16_t extlen = 8 + ipv6ext->ext_len * 8; - - *offset += extlen; - *parseptr += extlen; - } while ((ipv6ext->next_hdr == _ODP_IPPROTO_HOPOPTS || - ipv6ext->next_hdr == _ODP_IPPROTO_ROUTE) && - *offset < seg_len); - - if (*offset >= prs->l3_offset + - odp_be_to_cpu_16(ipv6->payload_len)) { - prs->flags.ip_err = 1; - return 0; - } - - if (ipv6ext->next_hdr == _ODP_IPPROTO_FRAG) - prs->input_flags.ipfrag = 1; - - return ipv6ext->next_hdr; - } - - if (odp_unlikely(ipv6->next_hdr == _ODP_IPPROTO_FRAG)) { - prs->input_flags.ipopt = 1; - prs->input_flags.ipfrag = 1; - } - - return ipv6->next_hdr; -} - -#define PARSE_TCP_BYTES (sizeof(_odp_tcphdr_t)) -/** - * Parser helper function for TCP - * - * Requires PARSE_TCP_BYTES bytes of contiguous packet data. - */ -static inline void parse_tcp(packet_parser_t *prs, const uint8_t **parseptr, - uint16_t tcp_len, - odp_proto_chksums_t chksums, - uint64_t *l4_part_sum) -{ - const _odp_tcphdr_t *tcp = (const _odp_tcphdr_t *)*parseptr; - uint32_t len = tcp->hl * 4; - - if (odp_unlikely(tcp->hl < sizeof(_odp_tcphdr_t) / sizeof(uint32_t))) - prs->flags.tcp_err = 1; - - if (chksums.chksum.tcp && - !prs->input_flags.ipfrag) { - *l4_part_sum += odp_cpu_to_be_16(tcp_len); -#if ODP_BYTE_ORDER == ODP_BIG_ENDIAN - *l4_part_sum += _ODP_IPPROTO_TCP; -#else - *l4_part_sum += _ODP_IPPROTO_TCP << 8; -#endif - } - - *parseptr += len; -} - -/* - * In the worst case we look at the UDP header and 4 bytes of the UDP - * payload (the non-ESP marker to distinguish IKE packets from ESP packets). - */ -#define PARSE_UDP_BYTES (sizeof(_odp_udphdr_t) + 4) -/** - * Parser helper function for UDP - * - * Requires PARSE_UDP_BYTES bytes of contiguous packet data. - */ -static inline void parse_udp(packet_parser_t *prs, const uint8_t **parseptr, - odp_proto_chksums_t chksums, - uint64_t *l4_part_sum) -{ - const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr; - uint32_t udplen = odp_be_to_cpu_16(udp->length); - uint16_t ipsec_port = odp_cpu_to_be_16(_ODP_UDP_IPSEC_PORT); - - if (odp_unlikely(udplen < sizeof(_odp_udphdr_t))) { - prs->flags.udp_err = 1; - return; - } - - if (chksums.chksum.udp && - !prs->input_flags.ipfrag) { - if (udp->chksum == 0) { - prs->input_flags.l4_chksum_done = 1; - prs->flags.l4_chksum_err = - (prs->input_flags.ipv4 != 1); - } else { - *l4_part_sum += udp->length; -#if ODP_BYTE_ORDER == ODP_BIG_ENDIAN - *l4_part_sum += _ODP_IPPROTO_UDP; -#else - *l4_part_sum += _ODP_IPPROTO_UDP << 8; -#endif - } - prs->input_flags.udp_chksum_zero = (udp->chksum == 0); - } - - if (odp_unlikely(ipsec_port == udp->dst_port && udplen > 4)) { - uint32_t val; - - memcpy(&val, udp + 1, 4); - if (val != 0) { - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_udp = 1; - } - } - - *parseptr += sizeof(_odp_udphdr_t); -} - -#define PARSE_SCTP_BYTES (sizeof(_odp_sctphdr_t)) -/** - * Parser helper function for SCTP - * - * Requires PARSE_SCTP_BYTES bytes of contiguous packet data. - */ -static inline void parse_sctp(packet_parser_t *prs, const uint8_t **parseptr, - uint16_t sctp_len, - odp_proto_chksums_t chksums, - uint64_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); -} - -#define MAX3(a, b, c) (MAX(MAX((a), (b)), (c))) -#define PARSE_L3_L4_BYTES (MAX(PARSE_IPV4_BYTES, PARSE_IPV6_BYTES) + \ - MAX3(PARSE_TCP_BYTES, PARSE_UDP_BYTES, PARSE_SCTP_BYTES)) -/* Requires up to PARSE_L3_L4_BYTES bytes of contiguous packet data. */ -static inline -int packet_parse_common_l3_l4(packet_parser_t *prs, const uint8_t *parseptr, - uint32_t offset, - uint32_t frame_len, uint32_t seg_len, - int layer, uint16_t ethtype, - odp_proto_chksums_t chksums, - uint64_t *l4_part_sum) -{ - uint8_t ip_proto; - - prs->l3_offset = offset; - - if (odp_unlikely(layer <= ODP_PROTO_LAYER_L2)) - return prs->flags.all.error != 0; - - /* Set l3 flag only for known ethtypes */ - prs->input_flags.l3 = 1; - - /* Parse Layer 3 headers */ - switch (ethtype) { - case _ODP_ETHTYPE_IPV4: - prs->input_flags.ipv4 = 1; - ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len, - chksums, l4_part_sum); - prs->l4_offset = offset; - break; - - case _ODP_ETHTYPE_IPV6: - prs->input_flags.ipv6 = 1; - ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, - seg_len, chksums, l4_part_sum); - prs->l4_offset = offset; - break; - - case _ODP_ETHTYPE_ARP: - prs->input_flags.arp = 1; - ip_proto = 255; /* Reserved invalid by IANA */ - break; - - default: - prs->input_flags.l3 = 0; - ip_proto = 255; /* Reserved invalid by IANA */ - } - - if (layer == ODP_PROTO_LAYER_L3) - return prs->flags.all.error != 0; - - /* Set l4 flag only for known ip_proto */ - prs->input_flags.l4 = 1; - - /* Parse Layer 4 headers */ - switch (ip_proto) { - case _ODP_IPPROTO_ICMPV4: - /* Fall through */ - - case _ODP_IPPROTO_ICMPV6: - prs->input_flags.icmp = 1; - break; - - case _ODP_IPPROTO_IPIP: - /* Do nothing */ - break; - - case _ODP_IPPROTO_TCP: - if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) - return -1; - prs->input_flags.tcp = 1; - parse_tcp(prs, &parseptr, frame_len - prs->l4_offset, chksums, - l4_part_sum); - break; - - case _ODP_IPPROTO_UDP: - if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) - return -1; - prs->input_flags.udp = 1; - parse_udp(prs, &parseptr, chksums, l4_part_sum); - break; - - case _ODP_IPPROTO_AH: - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_ah = 1; - break; - - case _ODP_IPPROTO_ESP: - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_esp = 1; - break; - - 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: - prs->input_flags.no_next_hdr = 1; - break; - - default: - prs->input_flags.l4 = 0; - break; - } - - return prs->flags.all.error != 0; -} - -/** - * Parse common packet headers up to given layer - * - * The function expects at least PACKET_PARSE_SEG_LEN bytes of data to be - * available from the ptr. Also parse metadata must be already initialized. - */ -int _odp_packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, - uint32_t frame_len, uint32_t seg_len, - int layer, odp_proto_chksums_t chksums) -{ - uint32_t offset; - uint16_t ethtype; - const uint8_t *parseptr; - uint64_t l4_part_sum; - - parseptr = ptr; - offset = 0; - - if (odp_unlikely(layer == ODP_PROTO_LAYER_NONE)) - return 0; - - /* Assume valid L2 header, no CRC/FCS check in SW */ - prs->l2_offset = offset; - - ethtype = parse_eth(prs, &parseptr, &offset, frame_len); - - return packet_parse_common_l3_l4(prs, parseptr, offset, frame_len, - seg_len, layer, ethtype, chksums, - &l4_part_sum); -} - static inline int packet_ipv4_chksum(odp_packet_t pkt, uint32_t offset, _odp_ipv4hdr_t *ip, @@ -2442,9 +1944,8 @@ int _odp_packet_sctp_chksum_insert(odp_packet_t pkt) 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, - uint64_t l4_part_sum) +int packet_l4_chksum(odp_packet_hdr_t *pkt_hdr, odp_proto_chksums_t chksums, + uint64_t l4_part_sum) { /* UDP chksum == 0 case is covered in parse_udp() */ if (chksums.chksum.udp && @@ -2518,42 +2019,6 @@ static int packet_l4_chksum(odp_packet_hdr_t *pkt_hdr, return pkt_hdr->p.flags.all.error != 0; } -/** - * Simple packet parser - */ -int _odp_packet_parse_layer(odp_packet_hdr_t *pkt_hdr, - odp_proto_layer_t layer, - odp_proto_chksums_t chksums) -{ - uint32_t seg_len = packet_first_seg_len(pkt_hdr); - const uint8_t *base = packet_data(pkt_hdr); - uint32_t offset = 0; - uint16_t ethtype; - uint64_t l4_part_sum = 0; - int rc; - - if (odp_unlikely(layer == ODP_PROTO_LAYER_NONE)) - return 0; - - /* Assume valid L2 header, no CRC/FCS check in SW */ - pkt_hdr->p.l2_offset = offset; - - ethtype = parse_eth(&pkt_hdr->p, &base, &offset, pkt_hdr->frame_len); - - rc = packet_parse_common_l3_l4(&pkt_hdr->p, base, offset, - pkt_hdr->frame_len, - seg_len, layer, ethtype, chksums, - &l4_part_sum); - - if (rc != 0) - return rc; - - if (layer >= ODP_PROTO_LAYER_L4) - return packet_l4_chksum(pkt_hdr, chksums, l4_part_sum); - else - return 0; -} - int odp_packet_parse(odp_packet_t pkt, uint32_t offset, const odp_packet_parse_param_t *param) { diff --git a/platform/linux-generic/odp_parse.c b/platform/linux-generic/odp_parse.c new file mode 100644 index 000000000..c89ed6dfb --- /dev/null +++ b/platform/linux-generic/odp_parse.c @@ -0,0 +1,496 @@ +/* Copyright (c) 2013-2018, Linaro Limited + * Copyright (c) 2019-2022, Nokia + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_parse_internal.h> +#include <odp_chksum_internal.h> +#include <protocols/eth.h> +#include <protocols/ip.h> +#include <protocols/sctp.h> +#include <protocols/tcp.h> +#include <protocols/udp.h> +#include <odp/api/hash.h> +#include <odp/api/packet_io.h> +#include <odp/api/packet_types.h> +#include <stdint.h> +#include <string.h> + +/** Parser helper function for Ethernet packets + * + * Requires up to PARSE_ETH_BYTES bytes of contiguous packet data. + */ +uint16_t parse_eth(packet_parser_t *prs, const uint8_t **parseptr, + uint32_t *offset, uint32_t frame_len) +{ + uint16_t ethtype; + const _odp_ethhdr_t *eth; + uint16_t macaddr0, macaddr2, macaddr4; + const _odp_vlanhdr_t *vlan; + _odp_packet_input_flags_t input_flags; + + input_flags.all = 0; + input_flags.l2 = 1; + input_flags.eth = 1; + + eth = (const _odp_ethhdr_t *)*parseptr; + + /* Detect jumbo frames */ + if (odp_unlikely(frame_len - *offset > _ODP_ETH_LEN_MAX)) + input_flags.jumbo = 1; + + /* Handle Ethernet broadcast/multicast addresses */ + macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth)); + if (odp_unlikely((macaddr0 & 0x0100) == 0x0100)) + input_flags.eth_mcast = 1; + + if (odp_unlikely(macaddr0 == 0xffff)) { + macaddr2 = + odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 1)); + macaddr4 = + odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 2)); + + if ((macaddr2 == 0xffff) && (macaddr4 == 0xffff)) + input_flags.eth_bcast = 1; + } + + /* Get Ethertype */ + ethtype = odp_be_to_cpu_16(eth->type); + *offset += sizeof(*eth); + *parseptr += sizeof(*eth); + + /* Check for SNAP vs. DIX */ + if (odp_unlikely(ethtype < _ODP_ETH_LEN_MAX)) { + input_flags.snap = 1; + if (ethtype > frame_len - *offset) { + prs->flags.snap_len_err = 1; + ethtype = 0; + goto error; + } + ethtype = odp_be_to_cpu_16(*((const uint16_t *)(uintptr_t) + (*parseptr + 6))); + *offset += 8; + *parseptr += 8; + } + + /* Parse the VLAN header(s), if present */ + if (odp_unlikely(ethtype == _ODP_ETHTYPE_VLAN_OUTER)) { + input_flags.vlan_qinq = 1; + input_flags.vlan = 1; + + vlan = (const _odp_vlanhdr_t *)*parseptr; + ethtype = odp_be_to_cpu_16(vlan->type); + *offset += sizeof(_odp_vlanhdr_t); + *parseptr += sizeof(_odp_vlanhdr_t); + } + + if (ethtype == _ODP_ETHTYPE_VLAN) { + input_flags.vlan = 1; + vlan = (const _odp_vlanhdr_t *)*parseptr; + ethtype = odp_be_to_cpu_16(vlan->type); + *offset += sizeof(_odp_vlanhdr_t); + *parseptr += sizeof(_odp_vlanhdr_t); + } + + /* + * The packet was too short for what we parsed. We just give up + * entirely without trying to parse what fits in the packet. + */ + if (odp_unlikely(*offset > frame_len)) { + input_flags.all = 0; + input_flags.l2 = 1; + ethtype = 0; + } + +error: + prs->input_flags.all |= input_flags.all; + + return ethtype; +} + +/** + * Parser helper function for IPv4 + * + * Requires up to PARSE_IPV4_BYTES bytes of contiguous packet data. + */ +static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, + uint32_t *offset, uint32_t frame_len, + odp_proto_chksums_t chksums, + uint64_t *l4_part_sum) +{ + const _odp_ipv4hdr_t *ipv4 = (const _odp_ipv4hdr_t *)*parseptr; + uint32_t dstaddr = odp_be_to_cpu_32(ipv4->dst_addr); + uint32_t l3_len = odp_be_to_cpu_16(ipv4->tot_len); + uint16_t frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); + uint8_t ver = _ODP_IPV4HDR_VER(ipv4->ver_ihl); + uint8_t ihl = _ODP_IPV4HDR_IHL(ipv4->ver_ihl); + + if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN || + ver != 4 || + sizeof(*ipv4) > frame_len - *offset || + (l3_len > frame_len - *offset))) { + prs->flags.ip_err = 1; + return 0; + } + + if (chksums.chksum.ipv4) { + prs->input_flags.l3_chksum_done = 1; + if (chksum_finalize(chksum_partial(ipv4, ihl * 4, 0)) != 0xffff) { + prs->flags.ip_err = 1; + prs->flags.l3_chksum_err = 1; + return 0; + } + } + + *offset += ihl * 4; + *parseptr += ihl * 4; + + if (chksums.chksum.udp || chksums.chksum.tcp) + *l4_part_sum = chksum_partial((const uint8_t *)&ipv4->src_addr, + 2 * _ODP_IPV4ADDR_LEN, 0); + + if (odp_unlikely(ihl > _ODP_IPV4HDR_IHL_MIN)) + prs->input_flags.ipopt = 1; + + /* A packet is a fragment if: + * "more fragments" flag is set (all fragments except the last) + * OR + * "fragment offset" field is nonzero (all fragments except the first) + */ + if (odp_unlikely(_ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) + prs->input_flags.ipfrag = 1; + + /* Handle IPv4 broadcast / multicast */ + if (odp_unlikely(dstaddr == 0xffffffff)) + prs->input_flags.ip_bcast = 1; + + if (odp_unlikely((dstaddr >> 28) == 0xe)) + prs->input_flags.ip_mcast = 1; + + return ipv4->proto; +} + +/** + * Parser helper function for IPv6 + * + * Requires at least PARSE_IPV6_BYTES bytes of contiguous packet data. + */ +static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, + uint32_t *offset, uint32_t frame_len, + uint32_t seg_len, + odp_proto_chksums_t chksums, + uint64_t *l4_part_sum) +{ + const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr; + const _odp_ipv6hdr_ext_t *ipv6ext; + uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr.u8[0]); + uint32_t l3_len = odp_be_to_cpu_16(ipv6->payload_len) + + _ODP_IPV6HDR_LEN; + + /* Basic sanity checks on IPv6 header */ + if (odp_unlikely((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || + sizeof(*ipv6) > frame_len - *offset || + l3_len > frame_len - *offset)) { + prs->flags.ip_err = 1; + return 0; + } + + /* IPv6 broadcast / multicast flags */ + prs->input_flags.ip_mcast = (dstaddr0 & 0xff000000) == 0xff000000; + prs->input_flags.ip_bcast = 0; + + /* Skip past IPv6 header */ + *offset += sizeof(_odp_ipv6hdr_t); + *parseptr += sizeof(_odp_ipv6hdr_t); + + if (chksums.chksum.udp || chksums.chksum.tcp) + *l4_part_sum = chksum_partial((const uint8_t *)&ipv6->src_addr, + 2 * _ODP_IPV6ADDR_LEN, 0); + + /* Skip past any IPv6 extension headers */ + if (ipv6->next_hdr == _ODP_IPPROTO_HOPOPTS || + ipv6->next_hdr == _ODP_IPPROTO_ROUTE) { + prs->input_flags.ipopt = 1; + + do { + ipv6ext = (const _odp_ipv6hdr_ext_t *)*parseptr; + uint16_t extlen = 8 + ipv6ext->ext_len * 8; + + *offset += extlen; + *parseptr += extlen; + } while ((ipv6ext->next_hdr == _ODP_IPPROTO_HOPOPTS || + ipv6ext->next_hdr == _ODP_IPPROTO_ROUTE) && + *offset < seg_len); + + if (*offset >= prs->l3_offset + + odp_be_to_cpu_16(ipv6->payload_len)) { + prs->flags.ip_err = 1; + return 0; + } + + if (ipv6ext->next_hdr == _ODP_IPPROTO_FRAG) + prs->input_flags.ipfrag = 1; + + return ipv6ext->next_hdr; + } + + if (odp_unlikely(ipv6->next_hdr == _ODP_IPPROTO_FRAG)) { + prs->input_flags.ipopt = 1; + prs->input_flags.ipfrag = 1; + } + + return ipv6->next_hdr; +} + +/** + * Parser helper function for TCP + * + * Requires PARSE_TCP_BYTES bytes of contiguous packet data. + */ +static inline void parse_tcp(packet_parser_t *prs, const uint8_t **parseptr, + uint16_t tcp_len, + odp_proto_chksums_t chksums, + uint64_t *l4_part_sum) +{ + const _odp_tcphdr_t *tcp = (const _odp_tcphdr_t *)*parseptr; + uint32_t len = tcp->hl * 4; + + if (odp_unlikely(tcp->hl < sizeof(_odp_tcphdr_t) / sizeof(uint32_t))) + prs->flags.tcp_err = 1; + + if (chksums.chksum.tcp && + !prs->input_flags.ipfrag) { + *l4_part_sum += odp_cpu_to_be_16(tcp_len); +#if ODP_BYTE_ORDER == ODP_BIG_ENDIAN + *l4_part_sum += _ODP_IPPROTO_TCP; +#else + *l4_part_sum += _ODP_IPPROTO_TCP << 8; +#endif + } + + *parseptr += len; +} + +/** + * Parser helper function for UDP + * + * Requires PARSE_UDP_BYTES bytes of contiguous packet data. + */ +static inline void parse_udp(packet_parser_t *prs, const uint8_t **parseptr, + odp_proto_chksums_t chksums, + uint64_t *l4_part_sum) +{ + const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr; + uint32_t udplen = odp_be_to_cpu_16(udp->length); + uint16_t ipsec_port = odp_cpu_to_be_16(_ODP_UDP_IPSEC_PORT); + + if (odp_unlikely(udplen < sizeof(_odp_udphdr_t))) { + prs->flags.udp_err = 1; + return; + } + + if (chksums.chksum.udp && + !prs->input_flags.ipfrag) { + if (udp->chksum == 0) { + prs->input_flags.l4_chksum_done = 1; + prs->flags.l4_chksum_err = + (prs->input_flags.ipv4 != 1); + } else { + *l4_part_sum += udp->length; +#if ODP_BYTE_ORDER == ODP_BIG_ENDIAN + *l4_part_sum += _ODP_IPPROTO_UDP; +#else + *l4_part_sum += _ODP_IPPROTO_UDP << 8; +#endif + } + prs->input_flags.udp_chksum_zero = (udp->chksum == 0); + } + + if (odp_unlikely(ipsec_port == udp->dst_port && udplen > 4)) { + uint32_t val; + + memcpy(&val, udp + 1, 4); + if (val != 0) { + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_udp = 1; + } + } + + *parseptr += sizeof(_odp_udphdr_t); +} + +/** + * Parser helper function for SCTP + * + * Requires PARSE_SCTP_BYTES bytes of contiguous packet data. + */ +static inline void parse_sctp(packet_parser_t *prs, const uint8_t **parseptr, + uint16_t sctp_len, + odp_proto_chksums_t chksums, + uint64_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); +} + +/* Requires up to PARSE_L3_L4_BYTES bytes of contiguous packet data. */ +int packet_parse_common_l3_l4(packet_parser_t *prs, const uint8_t *parseptr, + uint32_t offset, + uint32_t frame_len, uint32_t seg_len, + int layer, uint16_t ethtype, + odp_proto_chksums_t chksums, + uint64_t *l4_part_sum) +{ + uint8_t ip_proto; + + prs->l3_offset = offset; + + if (odp_unlikely(layer <= ODP_PROTO_LAYER_L2)) + return prs->flags.all.error != 0; + + /* Set l3 flag only for known ethtypes */ + prs->input_flags.l3 = 1; + + /* Parse Layer 3 headers */ + switch (ethtype) { + case _ODP_ETHTYPE_IPV4: + prs->input_flags.ipv4 = 1; + ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len, + chksums, l4_part_sum); + prs->l4_offset = offset; + break; + + case _ODP_ETHTYPE_IPV6: + prs->input_flags.ipv6 = 1; + ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, + seg_len, chksums, l4_part_sum); + prs->l4_offset = offset; + break; + + case _ODP_ETHTYPE_ARP: + prs->input_flags.arp = 1; + ip_proto = 255; /* Reserved invalid by IANA */ + break; + + default: + prs->input_flags.l3 = 0; + ip_proto = 255; /* Reserved invalid by IANA */ + } + + if (layer == ODP_PROTO_LAYER_L3) + return prs->flags.all.error != 0; + + /* Set l4 flag only for known ip_proto */ + prs->input_flags.l4 = 1; + + /* Parse Layer 4 headers */ + switch (ip_proto) { + case _ODP_IPPROTO_ICMPV4: + /* Fall through */ + + case _ODP_IPPROTO_ICMPV6: + prs->input_flags.icmp = 1; + break; + + case _ODP_IPPROTO_IPIP: + /* Do nothing */ + break; + + case _ODP_IPPROTO_TCP: + if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) + return -1; + prs->input_flags.tcp = 1; + parse_tcp(prs, &parseptr, frame_len - prs->l4_offset, chksums, + l4_part_sum); + break; + + case _ODP_IPPROTO_UDP: + if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) + return -1; + prs->input_flags.udp = 1; + parse_udp(prs, &parseptr, chksums, l4_part_sum); + break; + + case _ODP_IPPROTO_AH: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_ah = 1; + break; + + case _ODP_IPPROTO_ESP: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_esp = 1; + break; + + 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: + prs->input_flags.no_next_hdr = 1; + break; + + default: + prs->input_flags.l4 = 0; + break; + } + + return prs->flags.all.error != 0; +} + +/** + * Simple packet parser + */ +int _odp_packet_parse_layer(odp_packet_hdr_t *pkt_hdr, + odp_proto_layer_t layer, + odp_proto_chksums_t chksums) +{ + uint32_t seg_len = packet_first_seg_len(pkt_hdr); + const uint8_t *base = packet_data(pkt_hdr); + uint32_t offset = 0; + uint16_t ethtype; + uint64_t l4_part_sum = 0; + int rc; + + if (odp_unlikely(layer == ODP_PROTO_LAYER_NONE)) + return 0; + + /* Assume valid L2 header, no CRC/FCS check in SW */ + pkt_hdr->p.l2_offset = offset; + + ethtype = parse_eth(&pkt_hdr->p, &base, &offset, pkt_hdr->frame_len); + + rc = packet_parse_common_l3_l4(&pkt_hdr->p, base, offset, + pkt_hdr->frame_len, + seg_len, layer, ethtype, chksums, + &l4_part_sum); + + if (rc != 0) + return rc; + + if (layer >= ODP_PROTO_LAYER_L4) + return packet_l4_chksum(pkt_hdr, chksums, l4_part_sum); + else + return 0; +} diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c index 0a81e7085..208d71d8b 100644 --- a/platform/linux-generic/pktio/loop.c +++ b/platform/linux-generic/pktio/loop.c @@ -18,6 +18,7 @@ #include <odp/api/plat/packet_flag_inlines.h> #include <odp/api/plat/queue_inlines.h> +#include <odp_parse_internal.h> #include <odp_classification_internal.h> #include <odp_debug_internal.h> #include <odp_errno_define.h> diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c index a3cde2f90..22312f79b 100644 --- a/platform/linux-generic/pktio/netmap.c +++ b/platform/linux-generic/pktio/netmap.c @@ -16,6 +16,7 @@ #include <odp/api/time.h> #include <odp/api/plat/time_inlines.h> +#include <odp_parse_internal.h> #include <odp_packet_io_internal.h> #include <odp_packet_io_stats.h> #include <odp_ethtool_stats.h> diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c index 5dd58259a..6efe0c22b 100644 --- a/platform/linux-generic/pktio/pcap.c +++ b/platform/linux-generic/pktio/pcap.c @@ -46,6 +46,7 @@ #include <odp/api/plat/packet_inlines.h> +#include <odp_parse_internal.h> #include <odp_classification_internal.h> #include <odp_debug_internal.h> #include <odp_global_data.h> diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c index e2f0cbaae..0b46f2a33 100644 --- a/platform/linux-generic/pktio/socket.c +++ b/platform/linux-generic/pktio/socket.c @@ -15,6 +15,7 @@ #include <odp/api/ticketlock.h> #include <odp_socket_common.h> +#include <odp_parse_internal.h> #include <odp_packet_internal.h> #include <odp_packet_io_internal.h> #include <odp_packet_io_stats.h> diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c index 7710fe1dc..c3c73851f 100644 --- a/platform/linux-generic/pktio/socket_mmap.c +++ b/platform/linux-generic/pktio/socket_mmap.c @@ -16,6 +16,7 @@ #include <odp/api/plat/packet_inlines.h> #include <odp_socket_common.h> +#include <odp_parse_internal.h> #include <odp_packet_internal.h> #include <odp_packet_io_internal.h> #include <odp_packet_io_stats.h> diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c index 43676d0f9..67b893417 100644 --- a/platform/linux-generic/pktio/tap.c +++ b/platform/linux-generic/pktio/tap.c @@ -38,6 +38,7 @@ #include <odp/api/plat/packet_inlines.h> +#include <odp_parse_internal.h> #include <odp_debug_internal.h> #include <odp_socket_common.h> #include <odp_packet_internal.h> |