From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <hyonkim@cisco.com>
Received: from rcdn-iport-8.cisco.com (rcdn-iport-8.cisco.com [173.37.86.79])
 by dpdk.org (Postfix) with ESMTP id DC8614C8F;
 Thu, 28 Feb 2019 08:05:59 +0100 (CET)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
 d=cisco.com; i=@cisco.com; l=4058; q=dns/txt; s=iport;
 t=1551337560; x=1552547160;
 h=from:to:cc:subject:date:message-id:in-reply-to: references;
 bh=fari03nMWiH7RL1Syo4YrEl7wR62zhIXiwbUqVq61qE=;
 b=buVa8974Zis3I4K2gIt3GAHjBztNYlCrhsw8cUEKgj3TVK5oWsWU9Xtg
 pFHGvjYYjFRowCTjtSv5Oduu0joEAjsqpeAbnwUCv9zoh3F87cURFSmLV
 OLmG4miCptHb14pk2DiR9eEhyExX6hb1NZMSb0hawWysYIDmL4e0Y4KLJ 8=;
X-IronPort-AV: E=Sophos;i="5.58,422,1544486400"; d="scan'208";a="523882831"
Received: from alln-core-3.cisco.com ([173.36.13.136])
 by rcdn-iport-8.cisco.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;
 28 Feb 2019 07:05:58 +0000
Received: from cisco.com (savbu-usnic-a.cisco.com [10.193.184.48])
 by alln-core-3.cisco.com (8.15.2/8.15.2) with ESMTP id x1S75wGn020457;
 Thu, 28 Feb 2019 07:05:58 GMT
Received: by cisco.com (Postfix, from userid 508933)
 id 79E7520F2001; Wed, 27 Feb 2019 23:05:58 -0800 (PST)
From: Hyong Youb Kim <hyonkim@cisco.com>
To: Ferruh Yigit <ferruh.yigit@intel.com>
Cc: dev@dpdk.org, John Daley <johndale@cisco.com>,
 Hyong Youb Kim <hyonkim@cisco.com>, stable@dpdk.org
Date: Wed, 27 Feb 2019 23:03:13 -0800
Message-Id: <20190228070317.17002-12-hyonkim@cisco.com>
X-Mailer: git-send-email 2.16.2
In-Reply-To: <20190228070317.17002-1-hyonkim@cisco.com>
References: <20190228070317.17002-1-hyonkim@cisco.com>
X-Outbound-SMTP-Client: 10.193.184.48, savbu-usnic-a.cisco.com
X-Outbound-Node: alln-core-3.cisco.com
Subject: [dpdk-dev] [PATCH 11/15] net/enic: fix a couple issues with VXLAN
	match
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Thu, 28 Feb 2019 07:06:00 -0000

The filter API does not have flags for "match VXLAN". Explicitly set
the UDP destination port and mask in the L4 pattern. Otherwise, UDP
packets with non-VXLAN ports may be falsely reported as VXLAN.

1400 series VIC adapters have hardware VXLAN parsing. The L5 buffer on
the NIC starts with the inner Ethernet header, and the VXLAN header is
now in the L4 buffer following the UDP header. So the VXLAN spec/mask
needs to be in the L4 pattern, not L5. Older models still expect the
VXLAN spec/mask in the L5 pattern. Fix up the L4/L5 patterns
accordingly.

Fixes: 6ced137607d0 ("net/enic: flow API for NICs with advanced filters enabled")
Cc: stable@dpdk.org

Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
---
 drivers/net/enic/enic_flow.c | 46 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/net/enic/enic_flow.c b/drivers/net/enic/enic_flow.c
index ffc6ce1da..da43b31dc 100644
--- a/drivers/net/enic/enic_flow.c
+++ b/drivers/net/enic/enic_flow.c
@@ -830,12 +830,23 @@ enic_copy_item_vxlan_v2(struct copy_item_args *arg)
 	const struct rte_flow_item_vxlan *spec = item->spec;
 	const struct rte_flow_item_vxlan *mask = item->mask;
 	struct filter_generic_1 *gp = &enic_filter->u.generic_1;
+	struct udp_hdr *udp;
 
 	FLOW_TRACE();
 
 	if (*inner_ofst)
 		return EINVAL;
 
+	/*
+	 * The NIC filter API has no flags for "match vxlan". Set UDP port to
+	 * avoid false positives.
+	 */
+	gp->mask_flags |= FILTER_GENERIC_1_UDP;
+	gp->val_flags |= FILTER_GENERIC_1_UDP;
+	udp = (struct udp_hdr *)gp->layer[FILTER_GENERIC_1_L4].mask;
+	udp->dst_port = 0xffff;
+	udp = (struct udp_hdr *)gp->layer[FILTER_GENERIC_1_L4].val;
+	udp->dst_port = RTE_BE16(4789);
 	/* Match all if no spec */
 	if (!spec)
 		return 0;
@@ -931,6 +942,36 @@ item_stacking_valid(enum rte_flow_item_type prev_item,
 	return 0;
 }
 
+/*
+ * Fix up the L5 layer.. HW vxlan parsing removes vxlan header from L5.
+ * Instead it is in L4 following the UDP header. Append the vxlan
+ * pattern to L4 (udp) and shift any inner packet pattern in L5.
+ */
+static void
+fixup_l5_layer(struct enic *enic, struct filter_generic_1 *gp,
+	       uint8_t inner_ofst)
+{
+	uint8_t layer[FILTER_GENERIC_1_KEY_LEN];
+	uint8_t inner;
+	uint8_t vxlan;
+
+	if (!(inner_ofst > 0 && enic->vxlan))
+		return;
+	FLOW_TRACE();
+	vxlan = sizeof(struct vxlan_hdr);
+	memcpy(gp->layer[FILTER_GENERIC_1_L4].mask + sizeof(struct udp_hdr),
+	       gp->layer[FILTER_GENERIC_1_L5].mask, vxlan);
+	memcpy(gp->layer[FILTER_GENERIC_1_L4].val + sizeof(struct udp_hdr),
+	       gp->layer[FILTER_GENERIC_1_L5].val, vxlan);
+	inner = inner_ofst - vxlan;
+	memset(layer, 0, sizeof(layer));
+	memcpy(layer, gp->layer[FILTER_GENERIC_1_L5].mask + vxlan, inner);
+	memcpy(gp->layer[FILTER_GENERIC_1_L5].mask, layer, sizeof(layer));
+	memset(layer, 0, sizeof(layer));
+	memcpy(layer, gp->layer[FILTER_GENERIC_1_L5].val + vxlan, inner);
+	memcpy(gp->layer[FILTER_GENERIC_1_L5].val, layer, sizeof(layer));
+}
+
 /**
  * Build the intenal enic filter structure from the provided pattern. The
  * pattern is validated as the items are copied.
@@ -945,6 +986,7 @@ item_stacking_valid(enum rte_flow_item_type prev_item,
 static int
 enic_copy_filter(const struct rte_flow_item pattern[],
 		 const struct enic_filter_cap *cap,
+		 struct enic *enic,
 		 struct filter_v2 *enic_filter,
 		 struct rte_flow_error *error)
 {
@@ -989,6 +1031,8 @@ enic_copy_filter(const struct rte_flow_item pattern[],
 		prev_item = item->type;
 		is_first_item = 0;
 	}
+	fixup_l5_layer(enic, &enic_filter->u.generic_1, inner_ofst);
+
 	return 0;
 
 item_not_supported:
@@ -1481,7 +1525,7 @@ enic_flow_parse(struct rte_eth_dev *dev,
 		return -rte_errno;
 	}
 	enic_filter->type = enic->flow_filter_mode;
-	ret = enic_copy_filter(pattern, enic_filter_cap,
+	ret = enic_copy_filter(pattern, enic_filter_cap, enic,
 				       enic_filter, error);
 	return ret;
 }
-- 
2.16.2