X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_flow.c;h=371648b0eef5656c8339c744d4f120a4a250c52a;hb=061ee47cf53395a6453a97dfc6881ebfc9905743;hp=5613d59a9cce9a3205f54f83220516511e603757;hpb=1613848c2cd109d525d60cb6e84c9b893ef0ccce;p=dpdk.git diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 5613d59a9c..371648b0ee 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -93,6 +93,8 @@ static sfc_flow_spec_check sfc_flow_check_unknown_dst_flags; static sfc_flow_spec_set_vals sfc_flow_set_ethertypes; static sfc_flow_spec_set_vals sfc_flow_set_ifrm_unknown_dst_flags; static sfc_flow_spec_check sfc_flow_check_ifrm_unknown_dst_flags; +static sfc_flow_spec_set_vals sfc_flow_set_outer_vid_flag; +static sfc_flow_spec_check sfc_flow_check_outer_vid_flag; static boolean_t sfc_flow_is_zero(const uint8_t *buf, unsigned int size) @@ -371,7 +373,8 @@ sfc_flow_parse_vlan(const struct rte_flow_item *item, * the outer tag and the next matches the inner tag. */ if (mask->tci == supp_mask.tci) { - vid = rte_bswap16(spec->tci); + /* Apply mask to keep VID only */ + vid = rte_bswap16(spec->tci & mask->tci); if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_OUTER_VID)) { @@ -1779,6 +1782,43 @@ sfc_flow_set_ethertypes(struct sfc_flow_spec *spec, return 0; } +/** + * Set the EFX_FILTER_MATCH_OUTER_VID match flag with value 0 + * in the same specifications after copying. + * + * @param spec[in, out] + * SFC flow specification to update. + * @param filters_count_for_one_val[in] + * How many specifications should have the same match flag, what is the + * number of specifications before copying. + * @param error[out] + * Perform verbose error reporting if not NULL. + */ +static int +sfc_flow_set_outer_vid_flag(struct sfc_flow_spec *spec, + unsigned int filters_count_for_one_val, + struct rte_flow_error *error) +{ + unsigned int i; + + if (filters_count_for_one_val != spec->count) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "Number of specifications is incorrect " + "while copying by outer VLAN ID"); + return -rte_errno; + } + + for (i = 0; i < spec->count; i++) { + spec->filters[i].efs_match_flags |= + EFX_FILTER_MATCH_OUTER_VID; + + spec->filters[i].efs_outer_vid = 0; + } + + return 0; +} + /** * Set the EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST and * EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST match flags in the same @@ -1858,6 +1898,36 @@ sfc_flow_check_ifrm_unknown_dst_flags(efx_filter_match_flags_t match, return B_FALSE; } +/** + * Check that the list of supported filters has a filter that differs + * from @p match in that it has no flag EFX_FILTER_MATCH_OUTER_VID + * in this case that filter will be used and the flag + * EFX_FILTER_MATCH_OUTER_VID is not needed. + * + * @param match[in] + * The match flags of filter. + * @param spec[in] + * Specification to be supplemented. + * @param filter[in] + * SFC filter with list of supported filters. + */ +static boolean_t +sfc_flow_check_outer_vid_flag(efx_filter_match_flags_t match, + __rte_unused efx_filter_spec_t *spec, + struct sfc_filter *filter) +{ + unsigned int i; + efx_filter_match_flags_t match_without_vid = + match & ~EFX_FILTER_MATCH_OUTER_VID; + + for (i = 0; i < filter->supported_match_num; i++) { + if (match_without_vid == filter->supported_match[i]) + return B_FALSE; + } + + return B_TRUE; +} + /* * Match flags that can be automatically added to filters. * Selecting the last minimum when searching for the copy flag ensures that the @@ -1885,6 +1955,12 @@ static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = { .set_vals = sfc_flow_set_ifrm_unknown_dst_flags, .spec_check = sfc_flow_check_ifrm_unknown_dst_flags, }, + { + .flag = EFX_FILTER_MATCH_OUTER_VID, + .vals_count = 1, + .set_vals = sfc_flow_set_outer_vid_flag, + .spec_check = sfc_flow_check_outer_vid_flag, + }, }; /* Get item from array sfc_flow_copy_flags */ @@ -2094,11 +2170,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; @@ -2114,8 +2193,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 | @@ -2125,8 +2205,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; } } @@ -2153,7 +2234,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");