- /* Pseudo Header for IPv4/UDP/TCP checksum */
- union ipv4_psd_header {
- struct {
- uint32_t src_addr; /* IP address of source host. */
- uint32_t dst_addr; /* IP address of destination host(s). */
- uint8_t zero; /* zero. */
- uint8_t proto; /* L4 protocol type. */
- uint16_t len; /* L4 length. */
- } __attribute__((__packed__));
- uint16_t u16_arr[0];
- } psd_hdr;
-
- psd_hdr.src_addr = ip_hdr->src_addr;
- psd_hdr.dst_addr = ip_hdr->dst_addr;
- psd_hdr.zero = 0;
- psd_hdr.proto = ip_hdr->next_proto_id;
- psd_hdr.len = rte_cpu_to_be_16((uint16_t)(rte_be_to_cpu_16(ip_hdr->total_length)
- - sizeof(struct ipv4_hdr)));
- return get_16b_sum(psd_hdr.u16_arr, sizeof(psd_hdr));
+ struct ether_hdr *eth_hdr;
+
+ /* check udp destination port, 4789 is the default vxlan port
+ * (rfc7348) or that the rx offload flag is set (i40e only
+ * currently) */
+ if (udp_hdr->dst_port != _htons(4789) &&
+ RTE_ETH_IS_TUNNEL_PKT(pkt_type) == 0)
+ return;
+
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ eth_hdr = (struct ether_hdr *)((char *)udp_hdr +
+ sizeof(struct udp_hdr) +
+ sizeof(struct vxlan_hdr));
+
+ parse_ethernet(eth_hdr, info);
+ info->l2_len += ETHER_VXLAN_HLEN; /* add udp + vxlan */
+}
+
+/* Parse a gre header */
+static void
+parse_gre(struct simple_gre_hdr *gre_hdr, struct testpmd_offload_info *info)
+{
+ struct ether_hdr *eth_hdr;
+ struct ipv4_hdr *ipv4_hdr;
+ struct ipv6_hdr *ipv6_hdr;
+ uint8_t gre_len = 0;
+
+ /* check which fields are supported */
+ if ((gre_hdr->flags & _htons(~GRE_SUPPORTED_FIELDS)) != 0)
+ return;
+
+ gre_len += sizeof(struct simple_gre_hdr);
+
+ if (gre_hdr->flags & _htons(GRE_KEY_PRESENT))
+ gre_len += GRE_KEY_LEN;
+
+ if (gre_hdr->proto == _htons(ETHER_TYPE_IPv4)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ ipv4_hdr = (struct ipv4_hdr *)((char *)gre_hdr + gre_len);
+
+ parse_ipv4(ipv4_hdr, info);
+ info->ethertype = _htons(ETHER_TYPE_IPv4);
+ info->l2_len = 0;
+
+ } else if (gre_hdr->proto == _htons(ETHER_TYPE_IPv6)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ ipv6_hdr = (struct ipv6_hdr *)((char *)gre_hdr + gre_len);
+
+ info->ethertype = _htons(ETHER_TYPE_IPv6);
+ parse_ipv6(ipv6_hdr, info);
+ info->l2_len = 0;
+
+ } else if (gre_hdr->proto == _htons(ETHER_TYPE_TEB)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ eth_hdr = (struct ether_hdr *)((char *)gre_hdr + gre_len);
+
+ parse_ethernet(eth_hdr, info);
+ } else
+ return;
+
+ info->l2_len += gre_len;