net/sfc: fix filter exceptions logic

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>
This commit is contained in:
Igor Romanov 2018-07-14 08:38:23 +01:00 committed by Ferruh Yigit
parent 3126df2237
commit b0df5b32ae
3 changed files with 35 additions and 6 deletions

View File

@ -75,6 +75,7 @@ int
sfc_filter_attach(struct sfc_adapter *sa) sfc_filter_attach(struct sfc_adapter *sa)
{ {
int rc; int rc;
unsigned int i;
sfc_log_init(sa, "entry"); sfc_log_init(sa, "entry");
@ -88,6 +89,19 @@ sfc_filter_attach(struct sfc_adapter *sa)
efx_filter_fini(sa->nic); 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"); sfc_log_init(sa, "done");
return 0; return 0;

View File

@ -25,6 +25,16 @@ struct sfc_filter {
uint32_t *supported_match; uint32_t *supported_match;
/** List of flow rules */ /** List of flow rules */
struct sfc_flow_list flow_list; 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; struct sfc_adapter;

View File

@ -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 * Check whether the spec maps to a hardware filter which is known to be
* ineffective despite being valid. * ineffective despite being valid.
* *
* @param filter[in]
* SFC filter with list of supported filters.
* @param spec[in] * @param spec[in]
* SFC flow specification. * SFC flow specification.
*/ */
static boolean_t 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; unsigned int i;
uint16_t ether_type; 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_ETHER_TYPE |
EFX_FILTER_MATCH_LOC_MAC)) { EFX_FILTER_MATCH_LOC_MAC)) {
ether_type = spec->filters[i].efs_ether_type; ether_type = spec->filters[i].efs_ether_type;
if (ether_type == EFX_ETHER_TYPE_IPV4 || if (filter->supports_ip_proto_or_addr_filter &&
ether_type == EFX_ETHER_TYPE_IPV6) (ether_type == EFX_ETHER_TYPE_IPV4 ||
ether_type == EFX_ETHER_TYPE_IPV6))
return B_TRUE; return B_TRUE;
} else if (sfc_flow_is_match_with_vids(match_flags, } else if (sfc_flow_is_match_with_vids(match_flags,
EFX_FILTER_MATCH_ETHER_TYPE | 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_IP_PROTO |
EFX_FILTER_MATCH_LOC_MAC)) { EFX_FILTER_MATCH_LOC_MAC)) {
ip_proto = spec->filters[i].efs_ip_proto; ip_proto = spec->filters[i].efs_ip_proto;
if (ip_proto == EFX_IPPROTO_TCP || if (filter->supports_rem_or_local_port_filter &&
ip_proto == EFX_IPPROTO_UDP) (ip_proto == EFX_IPPROTO_TCP ||
ip_proto == EFX_IPPROTO_UDP))
return B_TRUE; return B_TRUE;
} }
} }
@ -2154,7 +2159,7 @@ sfc_flow_validate_match_flags(struct sfc_adapter *sa,
return rc; 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_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"The flow rule pattern is unsupported"); "The flow rule pattern is unsupported");