net/sfc: fix filter exceptions logic

Message ID 1531553903-11440-1-git-send-email-arybchenko@solarflare.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series net/sfc: fix filter exceptions logic |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Andrew Rybchenko July 14, 2018, 7:38 a.m. UTC
  From: Igor Romanov <Igor.Romanov@oktetlabs.ru>

Now exception logic handles these cases:

When FW variant does not support filters with transport ports, but
IP protocol filters are supported, TCP/UDP protocol filters may be
used. When FW variant does not support filters with IPv4/6 addresses
or IP protocol, but filters with EtherType are supported, IPv4 and
IPv6 EtherTypes may be used

Fixes: 096dba799b4a ("net/sfc: avoid creation of ineffective flow rules")
Cc: stable@dpdk.org

Signed-off-by: Igor Romanov <Igor.Romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/net/sfc/sfc_filter.c | 14 ++++++++++++++
 drivers/net/sfc/sfc_filter.h | 10 ++++++++++
 drivers/net/sfc/sfc_flow.c   | 17 +++++++++++------
 3 files changed, 35 insertions(+), 6 deletions(-)
  

Comments

Ferruh Yigit July 18, 2018, 12:53 p.m. UTC | #1
On 7/14/2018 8:38 AM, Andrew Rybchenko wrote:
> From: Igor Romanov <Igor.Romanov@oktetlabs.ru>
> 
> Now exception logic handles these cases:
> 
> When FW variant does not support filters with transport ports, but
> IP protocol filters are supported, TCP/UDP protocol filters may be
> used. When FW variant does not support filters with IPv4/6 addresses
> or IP protocol, but filters with EtherType are supported, IPv4 and
> IPv6 EtherTypes may be used
> 
> Fixes: 096dba799b4a ("net/sfc: avoid creation of ineffective flow rules")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Igor Romanov <Igor.Romanov@oktetlabs.ru>
> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>

Applied to dpdk-next-net/master, thanks.
  

Patch

diff --git a/drivers/net/sfc/sfc_filter.c b/drivers/net/sfc/sfc_filter.c
index 77e2ea562..6ff380a36 100644
--- a/drivers/net/sfc/sfc_filter.c
+++ b/drivers/net/sfc/sfc_filter.c
@@ -75,6 +75,7 @@  int
 sfc_filter_attach(struct sfc_adapter *sa)
 {
 	int rc;
+	unsigned int i;
 
 	sfc_log_init(sa, "entry");
 
@@ -88,6 +89,19 @@  sfc_filter_attach(struct sfc_adapter *sa)
 
 	efx_filter_fini(sa->nic);
 
+	sa->filter.supports_ip_proto_or_addr_filter = B_FALSE;
+	sa->filter.supports_rem_or_local_port_filter = B_FALSE;
+	for (i = 0; i < sa->filter.supported_match_num; ++i) {
+		if (sa->filter.supported_match[i] &
+		    (EFX_FILTER_MATCH_IP_PROTO | EFX_FILTER_MATCH_LOC_HOST |
+		     EFX_FILTER_MATCH_REM_HOST))
+			sa->filter.supports_ip_proto_or_addr_filter = B_TRUE;
+
+		if (sa->filter.supported_match[i] &
+		    (EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_REM_PORT))
+			sa->filter.supports_rem_or_local_port_filter = B_TRUE;
+	}
+
 	sfc_log_init(sa, "done");
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_filter.h b/drivers/net/sfc/sfc_filter.h
index d3e1c2f9c..64ab114e0 100644
--- a/drivers/net/sfc/sfc_filter.h
+++ b/drivers/net/sfc/sfc_filter.h
@@ -25,6 +25,16 @@  struct sfc_filter {
 	uint32_t			*supported_match;
 	/** List of flow rules */
 	struct sfc_flow_list		flow_list;
+	/**
+	 * Supports any of ip_proto, remote host or local host
+	 * filters. This flag is used for filter match exceptions
+	 */
+	boolean_t			supports_ip_proto_or_addr_filter;
+	/**
+	 * Supports any of remote port or local port filters.
+	 * This flag is used for filter match exceptions
+	 */
+	boolean_t			supports_rem_or_local_port_filter;
 };
 
 struct sfc_adapter;
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 18387415e..bfb7b24f0 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2095,11 +2095,14 @@  sfc_flow_is_match_with_vids(efx_filter_match_flags_t match_flags,
  * Check whether the spec maps to a hardware filter which is known to be
  * ineffective despite being valid.
  *
+ * @param filter[in]
+ *   SFC filter with list of supported filters.
  * @param spec[in]
  *   SFC flow specification.
  */
 static boolean_t
-sfc_flow_is_match_flags_exception(struct sfc_flow_spec *spec)
+sfc_flow_is_match_flags_exception(struct sfc_filter *filter,
+				  struct sfc_flow_spec *spec)
 {
 	unsigned int i;
 	uint16_t ether_type;
@@ -2115,8 +2118,9 @@  sfc_flow_is_match_flags_exception(struct sfc_flow_spec *spec)
 						EFX_FILTER_MATCH_ETHER_TYPE |
 						EFX_FILTER_MATCH_LOC_MAC)) {
 			ether_type = spec->filters[i].efs_ether_type;
-			if (ether_type == EFX_ETHER_TYPE_IPV4 ||
-			    ether_type == EFX_ETHER_TYPE_IPV6)
+			if (filter->supports_ip_proto_or_addr_filter &&
+			    (ether_type == EFX_ETHER_TYPE_IPV4 ||
+			     ether_type == EFX_ETHER_TYPE_IPV6))
 				return B_TRUE;
 		} else if (sfc_flow_is_match_with_vids(match_flags,
 				EFX_FILTER_MATCH_ETHER_TYPE |
@@ -2126,8 +2130,9 @@  sfc_flow_is_match_flags_exception(struct sfc_flow_spec *spec)
 				EFX_FILTER_MATCH_IP_PROTO |
 				EFX_FILTER_MATCH_LOC_MAC)) {
 			ip_proto = spec->filters[i].efs_ip_proto;
-			if (ip_proto == EFX_IPPROTO_TCP ||
-			    ip_proto == EFX_IPPROTO_UDP)
+			if (filter->supports_rem_or_local_port_filter &&
+			    (ip_proto == EFX_IPPROTO_TCP ||
+			     ip_proto == EFX_IPPROTO_UDP))
 				return B_TRUE;
 		}
 	}
@@ -2154,7 +2159,7 @@  sfc_flow_validate_match_flags(struct sfc_adapter *sa,
 			return rc;
 	}
 
-	if (sfc_flow_is_match_flags_exception(&flow->spec)) {
+	if (sfc_flow_is_match_flags_exception(&sa->filter, &flow->spec)) {
 		rte_flow_error_set(error, ENOTSUP,
 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
 			"The flow rule pattern is unsupported");