diff options
author | Bill Fischofer <bill.fischofer@linaro.org> | 2014-12-16 14:30:39 +0200 |
---|---|---|
committer | Maxim Uvarov <maxim.uvarov@linaro.org> | 2014-12-16 19:03:39 +0300 |
commit | ee8c83fe0bb17298cc52b9b0cfd54b8c62e9211c (patch) | |
tree | fb80192a5f9ea355e07c9cd1e190cdaf0b11bb78 /platform/linux-generic | |
parent | 26245a03e6d2a6a187ceccf812a729038af1789a (diff) |
linux-generic: packet: improve packet parsing
Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
Signed-off-by: Taras Kondratiuk <taras.kondratiuk@linaro.org>
Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org>
Reviewed-by: Petri Savolainen <petri.savolainen@linaro.org>
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'platform/linux-generic')
-rw-r--r-- | platform/linux-generic/include/odp_packet_internal.h | 31 | ||||
-rw-r--r-- | platform/linux-generic/odp_packet.c | 458 | ||||
-rw-r--r-- | platform/linux-generic/odp_packet_socket.c | 59 |
3 files changed, 328 insertions, 220 deletions
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 9338ec238..83d0e923e 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -44,6 +44,7 @@ typedef union { uint32_t vlan:1; /**< VLAN hdr found */ uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */ + uint32_t snap:1; /**< SNAP */ uint32_t arp:1; /**< ARP */ uint32_t ipv4:1; /**< IPv4 */ @@ -54,6 +55,7 @@ typedef union { uint32_t udp:1; /**< UDP */ uint32_t tcp:1; /**< TCP */ + uint32_t tcpopt:1; /**< TCP options present */ uint32_t sctp:1; /**< SCTP */ uint32_t icmp:1; /**< ICMP */ }; @@ -71,7 +73,9 @@ typedef union { struct { /* Bitfield flags for each detected error */ + uint32_t app_error:1; /**< Error bit for application use */ uint32_t frame_len:1; /**< Frame length error */ + uint32_t snap_len:1; /**< Snap length error */ uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD */ uint32_t ip_err:1; /**< IP error, checks TBD */ uint32_t tcp_err:1; /**< TCP error, checks TBD */ @@ -91,7 +95,10 @@ typedef union { struct { /* Bitfield flags for each output option */ - uint32_t l4_chksum:1; /**< Request L4 checksum calculation */ + uint32_t l3_chksum_set:1; /**< L3 chksum bit is valid */ + uint32_t l3_chksum:1; /**< L3 chksum override */ + uint32_t l4_chksum_set:1; /**< L3 chksum bit is valid */ + uint32_t l4_chksum:1; /**< L4 chksum override */ }; } output_flags_t; @@ -112,13 +119,19 @@ typedef struct { uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */ uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */ uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also ICMP) */ + uint32_t payload_offset; /**< offset to payload */ + + uint32_t vlan_s_tag; /**< Parsed 1st VLAN header (S-TAG) */ + uint32_t vlan_c_tag; /**< Parsed 2nd VLAN header (C-TAG) */ + uint32_t l3_protocol; /**< Parsed L3 protocol */ + uint32_t l3_len; /**< Layer 3 length */ + uint32_t l4_protocol; /**< Parsed L4 protocol */ + uint32_t l4_len; /**< Layer 4 length */ uint32_t frame_len; uint32_t headroom; uint32_t tailroom; - uint64_t user_ctx; /* user context */ - odp_pktio_t input; } odp_packet_hdr_t; @@ -138,11 +151,6 @@ static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt) } /** - * Parse packet and set internal metadata - */ -void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset); - -/** * Initialize packet buffer */ static inline void packet_init(pool_entry_t *pool, @@ -184,8 +192,15 @@ static inline void *packet_map(odp_packet_hdr_t *pkt_hdr, pkt_hdr->headroom + pkt_hdr->frame_len); } +static inline void packet_set_len(odp_packet_t pkt, uint32_t len) +{ + odp_packet_hdr(pkt)->frame_len = len; +} + odp_packet_t _odp_packet_alloc(odp_buffer_pool_t pool_hdl); +int _odp_packet_parse(odp_packet_t pkt); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index e5899fda5..ff05849f5 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -12,15 +12,12 @@ #include <odph_eth.h> #include <odph_ip.h> +#include <odph_tcp.h> +#include <odph_udp.h> #include <string.h> #include <stdio.h> -static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, - odph_ipv4hdr_t *ipv4, size_t *offset_out); -static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, - odph_ipv6hdr_t *ipv6, size_t *offset_out); - /* * * Alloc and free @@ -200,172 +197,6 @@ int odp_packet_seg_count(odp_packet_t pkt) return odp_packet_hdr(pkt)->buf_hdr.segcount; } - -/** - * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP - * - * Internal function: caller is resposible for passing only valid packet handles - * , lengths and offsets (usually done&called in packet input). - * - * @param pkt Packet handle - * @param len Packet length in bytes - * @param frame_offset Byte offset to L2 header - */ -void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset) -{ - odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); - odph_ethhdr_t *eth; - odph_vlanhdr_t *vlan; - odph_ipv4hdr_t *ipv4; - odph_ipv6hdr_t *ipv6; - uint16_t ethtype; - size_t offset = 0; - uint8_t ip_proto = 0; - - pkt_hdr->input_flags.eth = 1; - pkt_hdr->l2_offset = frame_offset; - pkt_hdr->frame_len = len; - - if (len > ODPH_ETH_LEN_MAX) - pkt_hdr->input_flags.jumbo = 1; - - /* Assume valid L2 header, no CRC/FCS check in SW */ - pkt_hdr->input_flags.l2 = 1; - pkt_hdr->l2_offset = frame_offset; - - eth = (odph_ethhdr_t *)odp_packet_data(pkt); - ethtype = odp_be_to_cpu_16(eth->type); - vlan = (odph_vlanhdr_t *)ð->type; - - if (ethtype == ODPH_ETHTYPE_VLAN_OUTER) { - pkt_hdr->input_flags.vlan_qinq = 1; - ethtype = odp_be_to_cpu_16(vlan->tpid); - offset += sizeof(odph_vlanhdr_t); - vlan = &vlan[1]; - } - - if (ethtype == ODPH_ETHTYPE_VLAN) { - pkt_hdr->input_flags.vlan = 1; - ethtype = odp_be_to_cpu_16(vlan->tpid); - offset += sizeof(odph_vlanhdr_t); - } - - /* Set l3_offset+flag only for known ethtypes */ - switch (ethtype) { - case ODPH_ETHTYPE_IPV4: - pkt_hdr->input_flags.ipv4 = 1; - pkt_hdr->input_flags.l3 = 1; - pkt_hdr->l3_offset = frame_offset + ODPH_ETHHDR_LEN + offset; - ipv4 = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); - ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset); - break; - case ODPH_ETHTYPE_IPV6: - pkt_hdr->input_flags.ipv6 = 1; - pkt_hdr->input_flags.l3 = 1; - pkt_hdr->l3_offset = frame_offset + ODPH_ETHHDR_LEN + offset; - ipv6 = (odph_ipv6hdr_t *)odp_packet_l3_ptr(pkt, NULL); - ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset); - break; - case ODPH_ETHTYPE_ARP: - pkt_hdr->input_flags.arp = 1; - /* fall through */ - default: - ip_proto = 0; - break; - } - - switch (ip_proto) { - case ODPH_IPPROTO_UDP: - pkt_hdr->input_flags.udp = 1; - pkt_hdr->input_flags.l4 = 1; - pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; - break; - case ODPH_IPPROTO_TCP: - pkt_hdr->input_flags.tcp = 1; - pkt_hdr->input_flags.l4 = 1; - pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; - break; - case ODPH_IPPROTO_SCTP: - pkt_hdr->input_flags.sctp = 1; - pkt_hdr->input_flags.l4 = 1; - pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; - break; - case ODPH_IPPROTO_ICMP: - pkt_hdr->input_flags.icmp = 1; - pkt_hdr->input_flags.l4 = 1; - pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; - break; - default: - /* 0 or unhandled IP protocols, don't set L4 flag+offset */ - if (pkt_hdr->input_flags.ipv6) { - /* IPv6 next_hdr is not L4, mark as IP-option instead */ - pkt_hdr->input_flags.ipopt = 1; - } - break; - } -} - -static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, - odph_ipv4hdr_t *ipv4, size_t *offset_out) -{ - uint8_t ihl; - uint16_t frag_offset; - - ihl = ODPH_IPV4HDR_IHL(ipv4->ver_ihl); - if (odp_unlikely(ihl < ODPH_IPV4HDR_IHL_MIN)) { - pkt_hdr->error_flags.ip_err = 1; - return 0; - } - - if (odp_unlikely(ihl > ODPH_IPV4HDR_IHL_MIN)) { - pkt_hdr->input_flags.ipopt = 1; - return 0; - } - - /* 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) - */ - frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); - if (odp_unlikely(ODPH_IPV4HDR_IS_FRAGMENT(frag_offset))) { - pkt_hdr->input_flags.ipfrag = 1; - return 0; - } - - if (ipv4->proto == ODPH_IPPROTO_ESP || - ipv4->proto == ODPH_IPPROTO_AH) { - pkt_hdr->input_flags.ipsec = 1; - return 0; - } - - /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after return */ - - *offset_out = sizeof(uint32_t) * ihl; - return ipv4->proto; -} - -static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, - odph_ipv6hdr_t *ipv6, size_t *offset_out) -{ - if (ipv6->next_hdr == ODPH_IPPROTO_ESP || - ipv6->next_hdr == ODPH_IPPROTO_AH) { - pkt_hdr->input_flags.ipopt = 1; - pkt_hdr->input_flags.ipsec = 1; - return 0; - } - - if (odp_unlikely(ipv6->next_hdr == ODPH_IPPROTO_FRAG)) { - pkt_hdr->input_flags.ipopt = 1; - pkt_hdr->input_flags.ipfrag = 1; - return 0; - } - - /* Don't step through more extensions */ - *offset_out = ODPH_IPV6HDR_LEN; - return ipv6->next_hdr; -} - void odp_packet_print(odp_packet_t pkt) { int max_len = 512; @@ -458,3 +289,288 @@ odp_packet_t _odp_packet_alloc(odp_buffer_pool_t pool_hdl) return (odp_packet_t)buffer_alloc(pool_hdl, pool->s.params.buf_size); } + +/** + * Parser helper function for IPv4 + */ +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, + uint8_t **parseptr, uint32_t *offset) +{ + odph_ipv4hdr_t *ipv4 = (odph_ipv4hdr_t *)*parseptr; + uint8_t ver = ODPH_IPV4HDR_VER(ipv4->ver_ihl); + uint8_t ihl = ODPH_IPV4HDR_IHL(ipv4->ver_ihl); + uint16_t frag_offset; + + pkt_hdr->l3_len = odp_be_to_cpu_16(ipv4->tot_len); + + if (odp_unlikely(ihl < ODPH_IPV4HDR_IHL_MIN) || + odp_unlikely(ver != 4) || + (pkt_hdr->l3_len > pkt_hdr->frame_len - *offset)) { + pkt_hdr->error_flags.ip_err = 1; + return 0; + } + + *offset += ihl * 4; + *parseptr += ihl * 4; + + if (odp_unlikely(ihl > ODPH_IPV4HDR_IHL_MIN)) + pkt_hdr->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) + */ + frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); + if (odp_unlikely(ODPH_IPV4HDR_IS_FRAGMENT(frag_offset))) + pkt_hdr->input_flags.ipfrag = 1; + + return ipv4->proto; +} + +/** + * Parser helper function for IPv6 + */ +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, + uint8_t **parseptr, uint32_t *offset) +{ + odph_ipv6hdr_t *ipv6 = (odph_ipv6hdr_t *)*parseptr; + odph_ipv6hdr_ext_t *ipv6ext; + + pkt_hdr->l3_len = odp_be_to_cpu_16(ipv6->payload_len); + + /* Basic sanity checks on IPv6 header */ + if ((ipv6->ver_tc_flow >> 28) != 6 || + pkt_hdr->l3_len > pkt_hdr->frame_len - *offset) { + pkt_hdr->error_flags.ip_err = 1; + return 0; + } + + /* Skip past IPv6 header */ + *offset += sizeof(odph_ipv6hdr_t); + *parseptr += sizeof(odph_ipv6hdr_t); + + + /* Skip past any IPv6 extension headers */ + if (ipv6->next_hdr == ODPH_IPPROTO_HOPOPTS || + ipv6->next_hdr == ODPH_IPPROTO_ROUTE) { + pkt_hdr->input_flags.ipopt = 1; + + do { + ipv6ext = (odph_ipv6hdr_ext_t *)*parseptr; + uint16_t extlen = 8 + ipv6ext->ext_len * 8; + + *offset += extlen; + *parseptr += extlen; + } while ((ipv6ext->next_hdr == ODPH_IPPROTO_HOPOPTS || + ipv6ext->next_hdr == ODPH_IPPROTO_ROUTE) && + *offset < pkt_hdr->frame_len); + + if (*offset >= pkt_hdr->l3_offset + ipv6->payload_len) { + pkt_hdr->error_flags.ip_err = 1; + return 0; + } + + if (ipv6ext->next_hdr == ODPH_IPPROTO_FRAG) + pkt_hdr->input_flags.ipfrag = 1; + + return ipv6ext->next_hdr; + } + + if (odp_unlikely(ipv6->next_hdr == ODPH_IPPROTO_FRAG)) { + pkt_hdr->input_flags.ipopt = 1; + pkt_hdr->input_flags.ipfrag = 1; + } + + return ipv6->next_hdr; +} + +/** + * Parser helper function for TCP + */ +static inline void parse_tcp(odp_packet_hdr_t *pkt_hdr, + uint8_t **parseptr, uint32_t *offset) +{ + odph_tcphdr_t *tcp = (odph_tcphdr_t *)*parseptr; + + if (tcp->hl < sizeof(odph_tcphdr_t)/sizeof(uint32_t)) + pkt_hdr->error_flags.tcp_err = 1; + else if ((uint32_t)tcp->hl * 4 > sizeof(odph_tcphdr_t)) + pkt_hdr->input_flags.tcpopt = 1; + + pkt_hdr->l4_len = pkt_hdr->l3_len + + pkt_hdr->l3_offset - pkt_hdr->l4_offset; + + *offset += (uint32_t)tcp->hl * 4; + *parseptr += (uint32_t)tcp->hl * 4; +} + +/** + * Parser helper function for UDP + */ +static inline void parse_udp(odp_packet_hdr_t *pkt_hdr, + uint8_t **parseptr, uint32_t *offset) +{ + odph_udphdr_t *udp = (odph_udphdr_t *)*parseptr; + uint32_t udplen = odp_be_to_cpu_16(udp->length); + + if (udplen < sizeof(odph_udphdr_t) || + udplen > (pkt_hdr->l3_len + + pkt_hdr->l3_offset - pkt_hdr->l4_offset)) { + pkt_hdr->error_flags.udp_err = 1; + } + + pkt_hdr->l4_len = udplen; + + *offset += sizeof(odph_udphdr_t); + *parseptr += sizeof(odph_udphdr_t); +} + +/** + * Simple packet parser + */ + +int _odp_packet_parse(odp_packet_t pkt) +{ + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); + odph_ethhdr_t *eth; + odph_vlanhdr_t *vlan; + uint16_t ethtype; + uint8_t *parseptr; + uint32_t offset, seglen; + uint8_t ip_proto = 0; + + /* Reset parser metadata for new parse */ + pkt_hdr->error_flags.all = 0; + pkt_hdr->input_flags.all = 0; + pkt_hdr->output_flags.all = 0; + pkt_hdr->l2_offset = 0; + pkt_hdr->l3_offset = 0; + pkt_hdr->l4_offset = 0; + pkt_hdr->payload_offset = 0; + pkt_hdr->vlan_s_tag = 0; + pkt_hdr->vlan_c_tag = 0; + pkt_hdr->l3_protocol = 0; + pkt_hdr->l4_protocol = 0; + + /* We only support Ethernet for now */ + pkt_hdr->input_flags.eth = 1; + + /* Detect jumbo frames */ + if (pkt_hdr->frame_len > ODPH_ETH_LEN_MAX) + pkt_hdr->input_flags.jumbo = 1; + + /* Assume valid L2 header, no CRC/FCS check in SW */ + pkt_hdr->input_flags.l2 = 1; + + eth = (odph_ethhdr_t *)packet_map(pkt_hdr, 0, &seglen); + offset = sizeof(odph_ethhdr_t); + parseptr = (uint8_t *)ð->type; + ethtype = odp_be_to_cpu_16(*((uint16_t *)(void *)parseptr)); + + /* Parse the VLAN header(s), if present */ + if (ethtype == ODPH_ETHTYPE_VLAN_OUTER) { + pkt_hdr->input_flags.vlan_qinq = 1; + pkt_hdr->input_flags.vlan = 1; + vlan = (odph_vlanhdr_t *)(void *)parseptr; + pkt_hdr->vlan_s_tag = ((ethtype << 16) | + odp_be_to_cpu_16(vlan->tci)); + offset += sizeof(odph_vlanhdr_t); + parseptr += sizeof(odph_vlanhdr_t); + ethtype = odp_be_to_cpu_16(*((uint16_t *)(void *)parseptr)); + } + + if (ethtype == ODPH_ETHTYPE_VLAN) { + pkt_hdr->input_flags.vlan = 1; + vlan = (odph_vlanhdr_t *)(void *)parseptr; + pkt_hdr->vlan_c_tag = ((ethtype << 16) | + odp_be_to_cpu_16(vlan->tci)); + offset += sizeof(odph_vlanhdr_t); + parseptr += sizeof(odph_vlanhdr_t); + ethtype = odp_be_to_cpu_16(*((uint16_t *)(void *)parseptr)); + } + + /* Check for SNAP vs. DIX */ + if (ethtype < ODPH_ETH_LEN_MAX) { + pkt_hdr->input_flags.snap = 1; + if (ethtype > pkt_hdr->frame_len - offset) { + pkt_hdr->error_flags.snap_len = 1; + goto parse_exit; + } + offset += 8; + parseptr += 8; + ethtype = odp_be_to_cpu_16(*((uint16_t *)(void *)parseptr)); + } + + /* Consume Ethertype for Layer 3 parse */ + parseptr += 2; + + /* Set l3_offset+flag only for known ethtypes */ + pkt_hdr->input_flags.l3 = 1; + pkt_hdr->l3_offset = offset; + pkt_hdr->l3_protocol = ethtype; + + /* Parse Layer 3 headers */ + switch (ethtype) { + case ODPH_ETHTYPE_IPV4: + pkt_hdr->input_flags.ipv4 = 1; + ip_proto = parse_ipv4(pkt_hdr, &parseptr, &offset); + break; + + case ODPH_ETHTYPE_IPV6: + pkt_hdr->input_flags.ipv6 = 1; + ip_proto = parse_ipv6(pkt_hdr, &parseptr, &offset); + break; + + case ODPH_ETHTYPE_ARP: + pkt_hdr->input_flags.arp = 1; + ip_proto = 255; /* Reserved invalid by IANA */ + break; + + default: + pkt_hdr->input_flags.l3 = 0; + ip_proto = 255; /* Reserved invalid by IANA */ + } + + /* Set l4_offset+flag only for known ip_proto */ + pkt_hdr->input_flags.l4 = 1; + pkt_hdr->l4_offset = offset; + pkt_hdr->l4_protocol = ip_proto; + + /* Parse Layer 4 headers */ + switch (ip_proto) { + case ODPH_IPPROTO_ICMP: + pkt_hdr->input_flags.icmp = 1; + break; + + case ODPH_IPPROTO_TCP: + pkt_hdr->input_flags.tcp = 1; + parse_tcp(pkt_hdr, &parseptr, &offset); + break; + + case ODPH_IPPROTO_UDP: + pkt_hdr->input_flags.udp = 1; + parse_udp(pkt_hdr, &parseptr, &offset); + break; + + case ODPH_IPPROTO_AH: + case ODPH_IPPROTO_ESP: + pkt_hdr->input_flags.ipsec = 1; + break; + + default: + pkt_hdr->input_flags.l4 = 0; + break; + } + + /* + * Anything beyond what we parse here is considered payload. + * Note: Payload is really only relevant for TCP and UDP. For + * all other protocols, the payload offset will point to the + * final header (ARP, ICMP, AH, ESP, or IP Fragment). + */ + pkt_hdr->payload_offset = offset; + +parse_exit: + return pkt_hdr->error_flags.all != 0; +} diff --git a/platform/linux-generic/odp_packet_socket.c b/platform/linux-generic/odp_packet_socket.c index ead5d2f84..284906530 100644 --- a/platform/linux-generic/odp_packet_socket.c +++ b/platform/linux-generic/odp_packet_socket.c @@ -34,6 +34,7 @@ #include <errno.h> #include <sys/syscall.h> +#include <odp.h> #include <odp_packet_socket.h> #include <odp_packet_internal.h> #include <odp_align_internal.h> @@ -42,8 +43,6 @@ #include <odph_eth.h> #include <odph_ip.h> -#include <odp_packet.h> -#include <odp_spinlock.h> /** Provide a sendmmsg wrapper for systems with no libc or kernel support. * As it is implemented as a weak symbol, it has zero effect on systems @@ -207,28 +206,19 @@ int setup_pkt_sock(pkt_sock_t *const pkt_sock, const char *netdev, unsigned int if_idx; struct ifreq ethreq; struct sockaddr_ll sa_ll; - odp_packet_t pkt; - uint8_t *pkt_buf; - uint8_t *l2_hdr; if (pool == ODP_BUFFER_POOL_INVALID) return -1; pkt_sock->pool = pool; - pkt = _odp_packet_alloc(pool); - if (!odp_packet_is_valid(pkt)) - return -1; - - pkt_buf = odp_packet_addr(pkt); - l2_hdr = ETHBUF_ALIGN(pkt_buf); /* Store eth buffer offset for pkt buffers from this pool */ - pkt_sock->frame_offset = (uintptr_t)l2_hdr - (uintptr_t)pkt_buf; + pkt_sock->frame_offset = 0; /* pkt buffer size */ - pkt_sock->buf_size = odp_packet_buf_size(pkt); + pkt_sock->buf_size = odp_buffer_pool_segment_size(pool); /* max frame len taking into account the l2-offset */ - pkt_sock->max_frame_len = pkt_sock->buf_size - pkt_sock->frame_offset; - - odp_packet_free(pkt); + pkt_sock->max_frame_len = pkt_sock->buf_size - + odp_buffer_pool_headroom(pool) - + odp_buffer_pool_tailroom(pool); odp_spinlock_lock(&raw_sockets_lock); @@ -319,7 +309,6 @@ int recv_pkt_sock_basic(pkt_sock_t *const pkt_sock, int const sockfd = pkt_sock->sockfd; odp_packet_t pkt = ODP_PACKET_INVALID; uint8_t *pkt_buf; - uint8_t *l2_hdr; int nb_rx = 0; /* recvfrom: @@ -337,10 +326,9 @@ int recv_pkt_sock_basic(pkt_sock_t *const pkt_sock, break; } - pkt_buf = odp_packet_addr(pkt); - l2_hdr = pkt_buf + pkt_sock->frame_offset; + pkt_buf = odp_packet_data(pkt); - recv_bytes = recvfrom(sockfd, l2_hdr, + recv_bytes = recvfrom(sockfd, pkt_buf, pkt_sock->max_frame_len, MSG_DONTWAIT, (struct sockaddr *)&sll, &addrlen); /* no data or error: free recv buf and break out of loop */ @@ -351,7 +339,8 @@ int recv_pkt_sock_basic(pkt_sock_t *const pkt_sock, continue; /* Parse and set packet header data */ - odp_packet_parse(pkt, recv_bytes, pkt_sock->frame_offset); + packet_set_len(pkt, recv_bytes); + _odp_packet_parse(pkt); pkt_table[nb_rx] = pkt; pkt = ODP_PACKET_INVALID; @@ -433,7 +422,7 @@ int recv_pkt_sock_mmsg(pkt_sock_t *const pkt_sock, if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID)) break; - pkt_buf = odp_packet_addr(pkt_table[i]); + pkt_buf = odp_packet_data(pkt_table[i]); l2_hdr = pkt_buf + pkt_sock->frame_offset; iovecs[i].iov_base = l2_hdr; iovecs[i].iov_len = pkt_sock->max_frame_len; @@ -456,8 +445,8 @@ int recv_pkt_sock_mmsg(pkt_sock_t *const pkt_sock, } /* Parse and set packet header data */ - odp_packet_parse(pkt_table[i], msgvec[i].msg_len, - pkt_sock->frame_offset); + packet_set_len(pkt_table[i], msgvec[i].msg_len); + _odp_packet_parse(pkt_table[i]); pkt_table[nb_rx] = pkt_table[i]; nb_rx++; @@ -570,7 +559,6 @@ static inline void mmap_tx_user_ready(struct tpacket2_hdr *hdr) static inline unsigned pkt_mmap_v2_rx(int sock, struct ring *ring, odp_packet_t pkt_table[], unsigned len, odp_buffer_pool_t pool, - size_t frame_offset, unsigned char if_mac[]) { union frame_map ppd; @@ -607,14 +595,14 @@ static inline unsigned pkt_mmap_v2_rx(int sock, struct ring *ring, if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID)) break; - l2_hdr = odp_packet_addr(pkt_table[i]) - + frame_offset; + packet_set_len(pkt_table[i], pkt_len); + l2_hdr = odp_packet_data(pkt_table[i]); memcpy(l2_hdr, pkt_buf, pkt_len); mmap_rx_user_ready(ppd.raw); /* Parse and set packet header data */ - odp_packet_parse(pkt_table[i], pkt_len, frame_offset); + _odp_packet_parse(pkt_table[i]); frame_num = next_frame_num; i++; @@ -837,9 +825,6 @@ static int mmap_store_hw_addr(pkt_sock_mmap_t *const pkt_sock, int setup_pkt_sock_mmap(pkt_sock_mmap_t *const pkt_sock, const char *netdev, odp_buffer_pool_t pool, int fanout) { - odp_packet_t pkt; - uint8_t *pkt_buf; - uint8_t *l2_hdr; int if_idx; int ret = 0; @@ -848,16 +833,8 @@ int setup_pkt_sock_mmap(pkt_sock_mmap_t *const pkt_sock, const char *netdev, if (pool == ODP_BUFFER_POOL_INVALID) return -1; - pkt = _odp_packet_alloc(pool); - if (!odp_packet_is_valid(pkt)) - return -1; - - pkt_buf = odp_packet_addr(pkt); - l2_hdr = ETHBUF_ALIGN(pkt_buf); /* Store eth buffer offset for pkt buffers from this pool */ - pkt_sock->frame_offset = (uintptr_t)l2_hdr - (uintptr_t)pkt_buf; - - odp_packet_free(pkt); + pkt_sock->frame_offset = 0; pkt_sock->pool = pool; pkt_sock->sockfd = mmap_pkt_socket(); @@ -924,7 +901,7 @@ int recv_pkt_sock_mmap(pkt_sock_mmap_t *const pkt_sock, { return pkt_mmap_v2_rx(pkt_sock->rx_ring.sock, &pkt_sock->rx_ring, pkt_table, len, pkt_sock->pool, - pkt_sock->frame_offset, pkt_sock->if_mac); + pkt_sock->if_mac); } /* |