Currently, ixgbe `rte_flow` parsing requires a mask for TCP and UDP items. This means TCP and UDP FDIR rules can only be programmed as port-based matches, while protocol-only matches are rejected even though they are supported in hardware.
Allow TCP and UDP items without a mask so `rte_flow` can express broad L4 matches that care about the protocol only. This makes TCP and UDP handling consistent with SCTP. Signed-off-by: Anatoly Burakov <[email protected]> --- drivers/net/intel/ixgbe/ixgbe_flow.c | 130 ++++++++++++++------------- 1 file changed, 67 insertions(+), 63 deletions(-) diff --git a/drivers/net/intel/ixgbe/ixgbe_flow.c b/drivers/net/intel/ixgbe/ixgbe_flow.c index a6fcfe7574..eae81462f6 100644 --- a/drivers/net/intel/ixgbe/ixgbe_flow.c +++ b/drivers/net/intel/ixgbe/ixgbe_flow.c @@ -2055,42 +2055,44 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, item, "Not supported last point for range"); return -rte_errno; } - /** - * Only care about src & dst ports, - * others should be masked. - */ - if (!item->mask) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, "Not supported by fdir filter"); - return -rte_errno; - } - rule->b_mask = TRUE; tcp_mask = item->mask; - if (tcp_mask->hdr.sent_seq || - tcp_mask->hdr.recv_ack || - tcp_mask->hdr.data_off || - tcp_mask->hdr.tcp_flags || - tcp_mask->hdr.rx_win || - tcp_mask->hdr.cksum || - tcp_mask->hdr.tcp_urp) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, "Not supported by fdir filter"); - return -rte_errno; - } - rule->mask.src_port_mask = tcp_mask->hdr.src_port; - rule->mask.dst_port_mask = tcp_mask->hdr.dst_port; + if (tcp_mask != NULL) { + /** + * Only care about src & dst ports, + * others should be masked. + */ + rule->b_mask = TRUE; + if (tcp_mask->hdr.sent_seq || + tcp_mask->hdr.recv_ack || + tcp_mask->hdr.data_off || + tcp_mask->hdr.tcp_flags || + tcp_mask->hdr.rx_win || + tcp_mask->hdr.cksum || + tcp_mask->hdr.tcp_urp) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + rule->mask.src_port_mask = tcp_mask->hdr.src_port; + rule->mask.dst_port_mask = tcp_mask->hdr.dst_port; - if (item->spec) { - rule->b_spec = TRUE; - tcp_spec = item->spec; - rule->ixgbe_fdir.formatted.src_port = - tcp_spec->hdr.src_port; - rule->ixgbe_fdir.formatted.dst_port = - tcp_spec->hdr.dst_port; + if (item->spec) { + rule->b_spec = TRUE; + tcp_spec = item->spec; + rule->ixgbe_fdir.formatted.src_port = + tcp_spec->hdr.src_port; + rule->ixgbe_fdir.formatted.dst_port = + tcp_spec->hdr.dst_port; + } + } else if (item->spec != NULL) { + /* No port mask means protocol-only match; spec is invalid. */ + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; } item = next_no_fuzzy_pattern(pattern, item); @@ -2120,37 +2122,39 @@ ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev, item, "Not supported last point for range"); return -rte_errno; } - /** - * Only care about src & dst ports, - * others should be masked. - */ - if (!item->mask) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, "Not supported by fdir filter"); - return -rte_errno; - } - rule->b_mask = TRUE; udp_mask = item->mask; - if (udp_mask->hdr.dgram_len || - udp_mask->hdr.dgram_cksum) { - memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, "Not supported by fdir filter"); - return -rte_errno; - } - rule->mask.src_port_mask = udp_mask->hdr.src_port; - rule->mask.dst_port_mask = udp_mask->hdr.dst_port; + if (udp_mask != NULL) { + /** + * Only care about src & dst ports, + * others should be masked. + */ + rule->b_mask = TRUE; + if (udp_mask->hdr.dgram_len || + udp_mask->hdr.dgram_cksum) { + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; + } + rule->mask.src_port_mask = udp_mask->hdr.src_port; + rule->mask.dst_port_mask = udp_mask->hdr.dst_port; - if (item->spec) { - rule->b_spec = TRUE; - udp_spec = item->spec; - rule->ixgbe_fdir.formatted.src_port = - udp_spec->hdr.src_port; - rule->ixgbe_fdir.formatted.dst_port = - udp_spec->hdr.dst_port; + if (item->spec) { + rule->b_spec = TRUE; + udp_spec = item->spec; + rule->ixgbe_fdir.formatted.src_port = + udp_spec->hdr.src_port; + rule->ixgbe_fdir.formatted.dst_port = + udp_spec->hdr.dst_port; + } + } else if (item->spec != NULL) { + /* No port mask means protocol-only match; spec is invalid. */ + memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, "Not supported by fdir filter"); + return -rte_errno; } item = next_no_fuzzy_pattern(pattern, item); -- 2.47.3

