diff options
author | Zoltan Kiss <zoltan.kiss@linaro.org> | 2016-07-22 14:56:51 +0100 |
---|---|---|
committer | Zoltan Kiss <zoltan.kiss@linaro.org> | 2016-07-22 16:49:17 +0100 |
commit | 0e642ce9b2ac0a26198ef8d6e0c9cb0dbb549d99 (patch) | |
tree | 24cb5ac2e284a5463faa8c592df4202f27c33677 | |
parent | 05eca183585c77fa7546a4f654cea0f7a7f7b876 (diff) |
Port 072b5ca "linux-gen: packet: use packet_parser_t type argument with parser functions"
Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org>
-rw-r--r-- | platform/linux-dpdk/include/odp_packet_internal.h | 28 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_packet.c | 166 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_packet_dpdk.c | 1 |
3 files changed, 106 insertions, 89 deletions
diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h index 2693b02a1..ff6f85664 100644 --- a/platform/linux-dpdk/include/odp_packet_internal.h +++ b/platform/linux-dpdk/include/odp_packet_internal.h @@ -32,6 +32,9 @@ extern "C" { #include <rte_acl_osdep.h> +/** Minimum segment length expected by packet_parse_common() */ +#define PACKET_PARSE_SEG_LEN 96 + /** * Packet input & protocol flags */ @@ -197,9 +200,9 @@ static inline void packet_set_len(odp_packet_hdr_t *pkt_hdr, uint32_t len) rte_pktmbuf_pkt_len(&pkt_hdr->buf_hdr.mb) = len; } -static inline int packet_parse_l2_not_done(odp_packet_hdr_t *pkt_hdr) +static inline int packet_parse_l2_not_done(packet_parser_t *prs) { - return !pkt_hdr->p.input_flags.parsed_l2; + return !prs->input_flags.parsed_l2; } static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) @@ -211,21 +214,21 @@ static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt); /* Fill in parser metadata for L2 */ -static inline void packet_parse_l2(odp_packet_hdr_t *pkt_hdr) +static inline void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len) { /* Packet alloc or reset have already init other offsets and flags */ /* We only support Ethernet for now */ - pkt_hdr->p.input_flags.eth = 1; + prs->input_flags.eth = 1; /* Detect jumbo frames */ - if (odp_packet_len((odp_packet_t)pkt_hdr) > ODPH_ETH_LEN_MAX) - pkt_hdr->p.input_flags.jumbo = 1; + if (frame_len > ODPH_ETH_LEN_MAX) + prs->input_flags.jumbo = 1; /* Assume valid L2 header, no CRC/FCS check in SW */ - pkt_hdr->p.input_flags.l2 = 1; + prs->input_flags.l2 = 1; - pkt_hdr->p.input_flags.parsed_l2 = 1; + prs->input_flags.parsed_l2 = 1; } static inline void _odp_packet_reset_parse(odp_packet_t pkt) @@ -233,7 +236,7 @@ static inline void _odp_packet_reset_parse(odp_packet_t pkt) odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); pkt_hdr->p.input_flags.parsed_all = 0; - packet_parse_l2(pkt_hdr); + packet_parse_l2(&pkt_hdr->p, odp_packet_len(pkt)); } /* Perform full packet parse */ @@ -271,11 +274,8 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts) } } -int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr); - -/* DPDK will reserve RTE_PKTMBUF_HEADROOM in any case */ -ODP_STATIC_ASSERT(ODP_CONFIG_PACKET_HEADROOM == RTE_PKTMBUF_HEADROOM, - "ERROR: Headroom has to be equal to RTE_PKTMBUF_HEADROOM"); +int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr, + uint32_t pkt_len, uint32_t seg_len); /* We can't enforce tailroom reservation for received packets */ ODP_STATIC_ASSERT(ODP_CONFIG_PACKET_TAILROOM == 0, diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c index 96c634e28..08b5186f5 100644 --- a/platform/linux-dpdk/odp_packet.c +++ b/platform/linux-dpdk/odp_packet.c @@ -1152,8 +1152,8 @@ void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt) /** * Parser helper function for IPv4 */ -static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, - const uint8_t **parseptr, uint32_t *offset) +static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, + uint32_t *offset, uint32_t frame_len) { const odph_ipv4hdr_t *ipv4 = (const odph_ipv4hdr_t *)*parseptr; uint8_t ver = ODPH_IPV4HDR_VER(ipv4->ver_ihl); @@ -1161,20 +1161,20 @@ static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, uint16_t frag_offset; uint32_t dstaddr = odp_be_to_cpu_32(ipv4->dst_addr); - pkt_hdr->p.l3_len = odp_be_to_cpu_16(ipv4->tot_len); + prs->l3_len = odp_be_to_cpu_16(ipv4->tot_len); if (odp_unlikely(ihl < ODPH_IPV4HDR_IHL_MIN) || odp_unlikely(ver != 4) || - (pkt_hdr->p.l3_len > pkt_hdr->buf_hdr.mb.pkt_len - *offset)) { - pkt_hdr->p.error_flags.ip_err = 1; + (prs->l3_len > frame_len - *offset)) { + prs->error_flags.ip_err = 1; return 0; } *offset += ihl * 4; *parseptr += ihl * 4; - if (odp_unlikely(ihl > ODPH_IPV4HDR_IHL_MIN)) - pkt_hdr->p.input_flags.ipopt = 1; + 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) @@ -1182,12 +1182,12 @@ static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, * "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->p.input_flags.ipfrag = 1; + if (odp_unlikely(_ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) + prs->input_flags.ipfrag = 1; /* Handle IPv4 broadcast / multicast */ - pkt_hdr->p.input_flags.ip_bcast = (dstaddr == 0xffffffff); - pkt_hdr->p.input_flags.ip_mcast = (dstaddr >> 28) == 0xd; + prs->input_flags.ip_bcast = (dstaddr == 0xffffffff); + prs->input_flags.ip_mcast = (dstaddr >> 28) == 0xd; return ipv4->proto; } @@ -1195,26 +1195,27 @@ static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, /** * Parser helper function for IPv6 */ -static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, - const uint8_t **parseptr, uint32_t *offset) +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) { const odph_ipv6hdr_t *ipv6 = (const odph_ipv6hdr_t *)*parseptr; const odph_ipv6hdr_ext_t *ipv6ext; uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr[0]); - pkt_hdr->p.l3_len = odp_be_to_cpu_16(ipv6->payload_len) + - ODPH_IPV6HDR_LEN; + prs->l3_len = odp_be_to_cpu_16(ipv6->payload_len) + + _ODP_IPV6HDR_LEN; /* Basic sanity checks on IPv6 header */ if ((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || - pkt_hdr->p.l3_len > pkt_hdr->buf_hdr.mb.pkt_len - *offset) { - pkt_hdr->p.error_flags.ip_err = 1; + prs->l3_len > frame_len - *offset) { + prs->error_flags.ip_err = 1; return 0; } /* IPv6 broadcast / multicast flags */ - pkt_hdr->p.input_flags.ip_mcast = (dstaddr0 & 0xff000000) == 0xff000000; - pkt_hdr->p.input_flags.ip_bcast = 0; + prs->input_flags.ip_mcast = (dstaddr0 & 0xff000000) == 0xff000000; + prs->input_flags.ip_bcast = 0; /* Skip past IPv6 header */ *offset += sizeof(odph_ipv6hdr_t); @@ -1223,7 +1224,7 @@ static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, /* Skip past any IPv6 extension headers */ if (ipv6->next_hdr == ODPH_IPPROTO_HOPOPTS || ipv6->next_hdr == ODPH_IPPROTO_ROUTE) { - pkt_hdr->p.input_flags.ipopt = 1; + prs->input_flags.ipopt = 1; do { ipv6ext = (const odph_ipv6hdr_ext_t *)*parseptr; @@ -1233,23 +1234,23 @@ static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, *parseptr += extlen; } while ((ipv6ext->next_hdr == ODPH_IPPROTO_HOPOPTS || ipv6ext->next_hdr == ODPH_IPPROTO_ROUTE) && - *offset < pkt_hdr->buf_hdr.mb.pkt_len); + *offset < seg_len); - if (*offset >= pkt_hdr->p.l3_offset + + if (*offset >= prs->l3_offset + odp_be_to_cpu_16(ipv6->payload_len)) { - pkt_hdr->p.error_flags.ip_err = 1; + prs->error_flags.ip_err = 1; return 0; } if (ipv6ext->next_hdr == ODPH_IPPROTO_FRAG) - pkt_hdr->p.input_flags.ipfrag = 1; + prs->input_flags.ipfrag = 1; return ipv6ext->next_hdr; } if (odp_unlikely(ipv6->next_hdr == ODPH_IPPROTO_FRAG)) { - pkt_hdr->p.input_flags.ipopt = 1; - pkt_hdr->p.input_flags.ipfrag = 1; + prs->input_flags.ipopt = 1; + prs->input_flags.ipfrag = 1; } return ipv6->next_hdr; @@ -1258,18 +1259,18 @@ static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, /** * Parser helper function for TCP */ -static inline void parse_tcp(odp_packet_hdr_t *pkt_hdr, +static inline void parse_tcp(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset) { const odph_tcphdr_t *tcp = (const odph_tcphdr_t *)*parseptr; if (tcp->hl < sizeof(odph_tcphdr_t) / sizeof(uint32_t)) - pkt_hdr->p.error_flags.tcp_err = 1; + prs->error_flags.tcp_err = 1; else if ((uint32_t)tcp->hl * 4 > sizeof(odph_tcphdr_t)) - pkt_hdr->p.input_flags.tcpopt = 1; + prs->input_flags.tcpopt = 1; - pkt_hdr->l4_len = pkt_hdr->p.l3_len + - pkt_hdr->p.l3_offset - pkt_hdr->p.l4_offset; + prs->l4_len = prs->l3_len + + prs->l3_offset - prs->l4_offset; if (offset) *offset += (uint32_t)tcp->hl * 4; @@ -1279,26 +1280,33 @@ static inline void parse_tcp(odp_packet_hdr_t *pkt_hdr, /** * Parser helper function for UDP */ -static inline void parse_udp(odp_packet_hdr_t *pkt_hdr, +static inline void parse_udp(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset) { const odph_udphdr_t *udp = (const odph_udphdr_t *)*parseptr; uint32_t udplen = odp_be_to_cpu_16(udp->length); if (udplen < sizeof(odph_udphdr_t) || - udplen > (pkt_hdr->p.l3_len + - pkt_hdr->p.l4_offset - pkt_hdr->p.l3_offset)) { - pkt_hdr->p.error_flags.udp_err = 1; + udplen > (prs->l3_len + + prs->l4_offset - prs->l3_offset)) { + prs->error_flags.udp_err = 1; } - pkt_hdr->l4_len = udplen; + prs->l4_len = udplen; if (offset) *offset += sizeof(odph_udphdr_t); *parseptr += sizeof(odph_udphdr_t); } -int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr) +/** + * Parse common packet headers + * + * The function expects at least PACKET_PARSE_SEG_LEN bytes of data to be + * available from the ptr. + */ +int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, + uint32_t frame_len, uint32_t seg_len) { const odph_ethhdr_t *eth; const odph_vlanhdr_t *vlan; @@ -1309,15 +1317,14 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr) uint16_t macaddr0, macaddr2, macaddr4; offset = sizeof(odph_ethhdr_t); - if (packet_parse_l2_not_done(pkt_hdr)) - packet_parse_l2(pkt_hdr); + if (packet_parse_l2_not_done(prs)) + packet_parse_l2(prs, frame_len); - eth = ptr ? (const odph_ethhdr_t *)ptr : - (odph_ethhdr_t *)odp_packet_data((odp_packet_t)pkt_hdr); + eth = (const _odp_ethhdr_t *)ptr; /* Handle Ethernet broadcast/multicast addresses */ macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth)); - pkt_hdr->p.input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; + prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; if (macaddr0 == 0xffff) { macaddr2 = @@ -1326,10 +1333,10 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr) macaddr4 = odp_be_to_cpu_16(*((const uint16_t *) (const void *)eth + 2)); - pkt_hdr->p.input_flags.eth_bcast = + prs->input_flags.eth_bcast = (macaddr2 == 0xffff) && (macaddr4 == 0xffff); } else { - pkt_hdr->p.input_flags.eth_bcast = 0; + prs->input_flags.eth_bcast = 0; } /* Get Ethertype */ @@ -1338,9 +1345,9 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr) /* Check for SNAP vs. DIX */ if (ethtype < ODPH_ETH_LEN_MAX) { - pkt_hdr->p.input_flags.snap = 1; - if (ethtype > odp_packet_len((odp_packet_t)pkt_hdr) - offset) { - pkt_hdr->p.error_flags.snap_len = 1; + prs->input_flags.snap = 1; + if (ethtype > frame_len - offset) { + prs->error_flags.snap_len = 1; goto parse_exit; } ethtype = odp_be_to_cpu_16(*((const uint16_t *) @@ -1351,8 +1358,8 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr) /* Parse the VLAN header(s), if present */ if (ethtype == ODPH_ETHTYPE_VLAN_OUTER) { - pkt_hdr->p.input_flags.vlan_qinq = 1; - pkt_hdr->p.input_flags.vlan = 1; + prs->input_flags.vlan_qinq = 1; + prs->input_flags.vlan = 1; vlan = (const odph_vlanhdr_t *)parseptr; ethtype = odp_be_to_cpu_16(vlan->type); @@ -1361,7 +1368,7 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr) } if (ethtype == ODPH_ETHTYPE_VLAN) { - pkt_hdr->p.input_flags.vlan = 1; + prs->input_flags.vlan = 1; vlan = (const odph_vlanhdr_t *)parseptr; ethtype = odp_be_to_cpu_16(vlan->type); offset += sizeof(odph_vlanhdr_t); @@ -1369,71 +1376,76 @@ int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr) } /* Set l3_offset+flag only for known ethtypes */ - pkt_hdr->p.input_flags.l3 = 1; - pkt_hdr->p.l3_offset = offset; + prs->input_flags.l3 = 1; + prs->l3_offset = offset; /* Parse Layer 3 headers */ switch (ethtype) { case ODPH_ETHTYPE_IPV4: - pkt_hdr->p.input_flags.ipv4 = 1; - ip_proto = parse_ipv4(pkt_hdr, &parseptr, &offset); + prs->input_flags.ipv4 = 1; + ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len); break; case ODPH_ETHTYPE_IPV6: - pkt_hdr->p.input_flags.ipv6 = 1; - ip_proto = parse_ipv6(pkt_hdr, &parseptr, &offset); + prs->input_flags.ipv6 = 1; + ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, + seg_len); break; case ODPH_ETHTYPE_ARP: - pkt_hdr->p.input_flags.arp = 1; + prs->input_flags.arp = 1; ip_proto = 255; /* Reserved invalid by IANA */ break; default: - pkt_hdr->p.input_flags.l3 = 0; - pkt_hdr->p.l3_offset = ODP_PACKET_OFFSET_INVALID; + prs->input_flags.l3 = 0; + prs->l3_offset = ODP_PACKET_OFFSET_INVALID; ip_proto = 255; /* Reserved invalid by IANA */ } /* Set l4_offset+flag only for known ip_proto */ - pkt_hdr->p.input_flags.l4 = 1; - pkt_hdr->p.l4_offset = offset; + prs->input_flags.l4 = 1; + prs->l4_offset = offset; /* Parse Layer 4 headers */ switch (ip_proto) { case ODPH_IPPROTO_ICMP: - pkt_hdr->p.input_flags.icmp = 1; + prs->input_flags.icmp = 1; break; case ODPH_IPPROTO_TCP: - pkt_hdr->p.input_flags.tcp = 1; - parse_tcp(pkt_hdr, &parseptr, NULL); + if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) + return -1; + prs->input_flags.tcp = 1; + parse_tcp(prs, &parseptr, NULL); break; case ODPH_IPPROTO_UDP: - pkt_hdr->p.input_flags.udp = 1; - parse_udp(pkt_hdr, &parseptr, NULL); + if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) + return -1; + prs->input_flags.udp = 1; + parse_udp(prs, &parseptr, NULL); break; case ODPH_IPPROTO_AH: - pkt_hdr->p.input_flags.ipsec = 1; - pkt_hdr->p.input_flags.ipsec_ah = 1; + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_ah = 1; break; case ODPH_IPPROTO_ESP: - pkt_hdr->p.input_flags.ipsec = 1; - pkt_hdr->p.input_flags.ipsec_esp = 1; + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_esp = 1; break; default: - pkt_hdr->p.input_flags.l4 = 0; - pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID; + prs->input_flags.l4 = 0; + prs->l4_offset = ODP_PACKET_OFFSET_INVALID; break; } parse_exit: - pkt_hdr->p.input_flags.parsed_all = 1; - return pkt_hdr->p.error_flags.all != 0; + prs->input_flags.parsed_all = 1; + return prs->error_flags.all != 0; } /** @@ -1441,5 +1453,9 @@ parse_exit: */ int packet_parse_full(odp_packet_hdr_t *pkt_hdr) { - return _odp_parse_common(pkt_hdr, NULL); + uint32_t seg_len = odp_packet_seg_len((odp_packet_t)pkt_hdr); + uint32_t len = packet_len(pkt_hdr); + void *base = odp_packet_data((odp_packet_t)pkt_hdr); + + return packet_parse_common(&pkt_hdr->p, base, len, seg_len); } diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c index a1bcfc6fb..c8cc3a33b 100644 --- a/platform/linux-dpdk/odp_packet_dpdk.c +++ b/platform/linux-dpdk/odp_packet_dpdk.c @@ -425,6 +425,7 @@ static int recv_pkt_dpdk(pktio_entry_t *pktio_entry, int index, pkt_addr = odp_packet_data(pkt_table[i]); ret = cls_classify_packet(pktio_entry, pkt_addr, odp_packet_len(pkt_table[i]), + odp_packet_len(pkt_table[i]), &new_pool, &parsed_hdr); if (ret) { failed++; |