From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from proxy.6wind.com (host.76.145.23.62.rev.coltfrance.com [62.23.145.76]) by dpdk.org (Postfix) with ESMTP id 3C1672BD4 for ; Mon, 29 Aug 2016 16:35:53 +0200 (CEST) Received: from glumotte.dev.6wind.com (unknown [10.16.0.195]) by proxy.6wind.com (Postfix) with ESMTP id 0DCE224E35; Mon, 29 Aug 2016 16:35:53 +0200 (CEST) From: Olivier Matz To: dev@dpdk.org Cc: cunming.liang@intel.com, john.mcnamara@intel.com, andrey.chilikin@intel.com, konstantin.ananyev@intel.com Date: Mon, 29 Aug 2016 16:35:27 +0200 Message-Id: <1472481335-21226-9-git-send-email-olivier.matz@6wind.com> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1472481335-21226-1-git-send-email-olivier.matz@6wind.com> References: <1467733310-20875-1-git-send-email-olivier.matz@6wind.com> <1472481335-21226-1-git-send-email-olivier.matz@6wind.com> Subject: [dpdk-dev] [PATCH v2 08/16] net: support Ip tunnels in software packet type parser X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Aug 2016 14:35:53 -0000 Add support of IP and IP6 tunnels in rte_net_get_ptype(). We need to duplicate some code because the packet types do not have the same value for a given protocol between inner and outer. Signed-off-by: Jean Dao Signed-off-by: Olivier Matz --- lib/librte_net/rte_net.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++- lib/librte_net/rte_net.h | 1 + 2 files changed, 156 insertions(+), 3 deletions(-) diff --git a/lib/librte_net/rte_net.c b/lib/librte_net/rte_net.c index d20cc65..d921db8 100644 --- a/lib/librte_net/rte_net.c +++ b/lib/librte_net/rte_net.c @@ -93,6 +93,79 @@ ptype_l4(uint8_t proto) return ptype_l4_proto[proto]; } +/* get inner l3 packet type from ip6 next protocol */ +static uint32_t +ptype_inner_l3_ip6(uint8_t ip6_proto) +{ + static const uint32_t ptype_inner_ip6_ext_proto_map[256] = { + [IPPROTO_HOPOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT - + RTE_PTYPE_INNER_L3_IPV6, + [IPPROTO_ROUTING] = RTE_PTYPE_INNER_L3_IPV6_EXT - + RTE_PTYPE_INNER_L3_IPV6, + [IPPROTO_FRAGMENT] = RTE_PTYPE_INNER_L3_IPV6_EXT - + RTE_PTYPE_INNER_L3_IPV6, + [IPPROTO_ESP] = RTE_PTYPE_INNER_L3_IPV6_EXT - + RTE_PTYPE_INNER_L3_IPV6, + [IPPROTO_AH] = RTE_PTYPE_INNER_L3_IPV6_EXT - + RTE_PTYPE_INNER_L3_IPV6, + [IPPROTO_DSTOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT - + RTE_PTYPE_INNER_L3_IPV6, + }; + + return RTE_PTYPE_INNER_L3_IPV6 + + ptype_inner_ip6_ext_proto_map[ip6_proto]; +} + +/* get inner l3 packet type from ip version and header length */ +static uint32_t +ptype_inner_l3_ip(uint8_t ipv_ihl) +{ + static const uint32_t ptype_inner_l3_ip_proto_map[256] = { + [0x45] = RTE_PTYPE_INNER_L3_IPV4, + [0x46] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x47] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x48] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x49] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x4A] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x4B] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x4C] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x4D] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x4E] = RTE_PTYPE_INNER_L3_IPV4_EXT, + [0x4F] = RTE_PTYPE_INNER_L3_IPV4_EXT, + }; + + return ptype_inner_l3_ip_proto_map[ipv_ihl]; +} + +/* get inner l4 packet type from proto */ +static uint32_t +ptype_inner_l4(uint8_t proto) +{ + static const uint32_t ptype_inner_l4_proto[256] = { + [IPPROTO_UDP] = RTE_PTYPE_INNER_L4_UDP, + [IPPROTO_TCP] = RTE_PTYPE_INNER_L4_TCP, + [IPPROTO_SCTP] = RTE_PTYPE_INNER_L4_SCTP, + }; + + return ptype_inner_l4_proto[proto]; +} + +/* get the tunnel packet type if any, update proto. */ +static uint32_t +ptype_tunnel(uint16_t *proto) +{ + switch (*proto) { + case IPPROTO_IPIP: + *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + return RTE_PTYPE_TUNNEL_IP; + case IPPROTO_IPV6: + *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv6); + return RTE_PTYPE_TUNNEL_IP; /* IP is also valid for IPv6 */ + default: + return 0; + } +} + /* get the ipv4 header length */ static uint8_t ip4_hlen(const struct ipv4_hdr *hdr) @@ -207,9 +280,8 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, pkt_type |= ptype_l3_ip(ip4h->version_ihl); hdr_lens->l3_len = ip4_hlen(ip4h); off += hdr_lens->l3_len; - if (ip4h->fragment_offset & - rte_cpu_to_be_16(IPV4_HDR_OFFSET_MASK | - IPV4_HDR_MF_FLAG)) { + if (ip4h->fragment_offset & rte_cpu_to_be_16( + IPV4_HDR_OFFSET_MASK | IPV4_HDR_MF_FLAG)) { pkt_type |= RTE_PTYPE_L4_FRAG; hdr_lens->l4_len = 0; return pkt_type; @@ -245,6 +317,7 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP) { hdr_lens->l4_len = sizeof(struct udp_hdr); + return pkt_type; } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) { const struct tcp_hdr *th; struct tcp_hdr th_copy; @@ -254,10 +327,89 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, return pkt_type & (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK); hdr_lens->l4_len = (th->data_off & 0xf0) >> 2; + return pkt_type; } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_SCTP) { hdr_lens->l4_len = sizeof(struct sctp_hdr); + return pkt_type; } else { hdr_lens->l4_len = 0; + pkt_type |= ptype_tunnel(&proto); + hdr_lens->tunnel_len = 0; + } + + /* same job for inner header: we need to duplicate the code + * because the packet types do not have the same value. + */ + hdr_lens->inner_l2_len = 0; + + if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) { + const struct ipv4_hdr *ip4h; + struct ipv4_hdr ip4h_copy; + + ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy); + if (unlikely(ip4h == NULL)) + return pkt_type; + + pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl); + hdr_lens->inner_l3_len = ip4_hlen(ip4h); + off += hdr_lens->inner_l3_len; + if (ip4h->fragment_offset & + rte_cpu_to_be_16(IPV4_HDR_OFFSET_MASK | + IPV4_HDR_MF_FLAG)) { + pkt_type |= RTE_PTYPE_INNER_L4_FRAG; + hdr_lens->inner_l4_len = 0; + return pkt_type; + } + proto = ip4h->next_proto_id; + pkt_type |= ptype_inner_l4(proto); + } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv6)) { + const struct ipv6_hdr *ip6h; + struct ipv6_hdr ip6h_copy; + int frag = 0; + + ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy); + if (unlikely(ip6h == NULL)) + return pkt_type; + + proto = ip6h->proto; + hdr_lens->inner_l3_len = sizeof(*ip6h); + off += hdr_lens->inner_l3_len; + pkt_type |= ptype_inner_l3_ip6(proto); + if ((pkt_type & RTE_PTYPE_INNER_L3_MASK) == + RTE_PTYPE_INNER_L3_IPV6_EXT) { + uint32_t prev_off; + + prev_off = off; + proto = skip_ip6_ext(proto, m, &off, &frag); + hdr_lens->inner_l3_len += off - prev_off; + } + if (proto == 0) + return pkt_type; + if (frag) { + pkt_type |= RTE_PTYPE_INNER_L4_FRAG; + hdr_lens->inner_l4_len = 0; + return pkt_type; + } + pkt_type |= ptype_inner_l4(proto); + } + + if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP) { + hdr_lens->inner_l4_len = sizeof(struct udp_hdr); + } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == + RTE_PTYPE_INNER_L4_TCP) { + const struct tcp_hdr *th; + struct tcp_hdr th_copy; + + th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy); + if (unlikely(th == NULL)) + return pkt_type & (RTE_PTYPE_INNER_L2_MASK | + RTE_PTYPE_INNER_L3_MASK); + hdr_lens->inner_l4_len = (th->data_off & 0xf0) >> 2; + } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == + RTE_PTYPE_INNER_L4_SCTP) { + hdr_lens->inner_l4_len = sizeof(struct sctp_hdr); + } else { + hdr_lens->inner_l4_len = 0; } return pkt_type; diff --git a/lib/librte_net/rte_net.h b/lib/librte_net/rte_net.h index 1224b0e..f433389 100644 --- a/lib/librte_net/rte_net.h +++ b/lib/librte_net/rte_net.h @@ -68,6 +68,7 @@ struct rte_net_hdr_lens { * L2: Ether, Vlan, QinQ * L3: IPv4, IPv6 * L4: TCP, UDP, SCTP + * Tunnels: IPv4, IPv6 * * @param m * The packet mbuf to be parsed. -- 2.8.1