[PATCH 23.11] net/txgbe: fix FDIR input mask

Shani Peretz shperetz at nvidia.com
Tue Jan 6 10:54:34 CET 2026



> -----Original Message-----
> From: Jiawen Wu <jiawenwu at trustnetic.com>
> Sent: Sunday, 4 January 2026 4:54
> To: stable at dpdk.org
> Cc: Jiawen Wu <jiawenwu at trustnetic.com>
> Subject: [PATCH 23.11] net/txgbe: fix FDIR input mask
> 
> External email: Use caution opening links or attachments
> 
> 
> [ upstream commit a2d4de27109033d5061da44aed919bf46cfd7ca9 ]
> 
> Fix FDIR mask settings to comply with the hardware configuration. And mask
> out the spec field instead of manually setting it to 0.
> 
> There are some requirements of mask in hardware:
> 1) IPv4 mask should be little-endian.
> 2) Ipv6 source address mask has only 16 bits, one bit of mask
>    corresponds to one byte of spec.
> 3) IPv6 dest address is only supported to perfect match the low 8 bits,
>    so it is not taken into account for support in the driver.
> 
> Fixes: ea230dda16ad ("net/txgbe: configure flow director filter")
> 
> Signed-off-by: Jiawen Wu <jiawenwu at trustnetic.com>
> ---
>  drivers/net/txgbe/txgbe_fdir.c | 49 +++++++++++++++++++++++++++++----
> -
>  drivers/net/txgbe/txgbe_flow.c |  8 ++----
>  2 files changed, 45 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/txgbe/txgbe_fdir.c b/drivers/net/txgbe/txgbe_fdir.c
> index 8d181db33f..6b83a7379d 100644
> --- a/drivers/net/txgbe/txgbe_fdir.c
> +++ b/drivers/net/txgbe/txgbe_fdir.c
> @@ -165,6 +165,15 @@ configure_fdir_flags(const struct rte_eth_fdir_conf
> *conf,
>         return 0;
>  }
> 
> +static inline uint16_t
> +txgbe_reverse_fdir_bitmasks(uint16_t mask) {
> +       mask = ((mask & 0x5555) << 1) | ((mask & 0xAAAA) >> 1);
> +       mask = ((mask & 0x3333) << 2) | ((mask & 0xCCCC) >> 2);
> +       mask = ((mask & 0x0F0F) << 4) | ((mask & 0xF0F0) >> 4);
> +       return ((mask & 0x00FF) << 8) | ((mask & 0xFF00) >> 8); }
> +
>  int
>  txgbe_fdir_set_input_mask(struct rte_eth_dev *dev)  { @@ -206,15 +215,15
> @@ txgbe_fdir_set_input_mask(struct rte_eth_dev *dev)
>         wr32(hw, TXGBE_FDIRUDPMSK, ~fdirtcpm);
>         wr32(hw, TXGBE_FDIRSCTPMSK, ~fdirtcpm);
> 
> -       /* Store source and destination IPv4 masks (big-endian) */
> -       wr32(hw, TXGBE_FDIRSIP4MSK, ~info->mask.src_ipv4_mask);
> -       wr32(hw, TXGBE_FDIRDIP4MSK, ~info->mask.dst_ipv4_mask);
> +       /* Store source and destination IPv4 masks (little-endian) */
> +       wr32(hw, TXGBE_FDIRSIP4MSK, rte_be_to_cpu_32(~info-
> >mask.src_ipv4_mask));
> +       wr32(hw, TXGBE_FDIRDIP4MSK,
> + rte_be_to_cpu_32(~info->mask.dst_ipv4_mask));
> 
>         /*
>          * Store source and destination IPv6 masks (bit reversed)
>          */
> -       fdiripv6m = TXGBE_FDIRIP6MSK_DST(info->mask.dst_ipv6_mask) |
> -                   TXGBE_FDIRIP6MSK_SRC(info->mask.src_ipv6_mask);
> +       fdiripv6m = txgbe_reverse_fdir_bitmasks(info->mask.dst_ipv6_mask) <<
> 16;
> +       fdiripv6m |=
> + txgbe_reverse_fdir_bitmasks(info->mask.src_ipv6_mask);
>         wr32(hw, TXGBE_FDIRIP6MSK, ~fdiripv6m);
> 
>         return 0;
> @@ -636,8 +645,14 @@ fdir_write_perfect_filter(struct txgbe_hw *hw,
>         fdircmd |= TXGBE_FDIRPICMD_QP(queue);
>         fdircmd |= TXGBE_FDIRPICMD_POOL(input->vm_pool);
> 
> -       if (input->flow_type & TXGBE_ATR_L3TYPE_IPV6)
> +       if (input->flow_type & TXGBE_ATR_L3TYPE_IPV6) {
> +               /* use SIP4 to store LS Dword of the Source iPv6 address */
> +               wr32(hw, TXGBE_FDIRPISIP4, be_to_le32(input->src_ip[3]));
> +               wr32(hw, TXGBE_FDIRPISIP6(0), be_to_le32(input->src_ip[2]));
> +               wr32(hw, TXGBE_FDIRPISIP6(1), be_to_le32(input->src_ip[1]));
> +               wr32(hw, TXGBE_FDIRPISIP6(2),
> + be_to_le32(input->src_ip[0]));
>                 fdircmd |= TXGBE_FDIRPICMD_IP6;
> +       }
>         wr32(hw, TXGBE_FDIRPICMD, fdircmd);
> 
>         PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash); @@ -
> 783,6 +798,26 @@ txgbe_remove_fdir_filter(struct txgbe_hw_fdir_info
> *fdir_info,
>         return 0;
>  }
> 
> +static void
> +txgbe_fdir_mask_input(struct txgbe_hw_fdir_mask *mask,
> +                     struct txgbe_atr_input *input) {
> +       int i;
> +
> +       if (input->flow_type & TXGBE_ATR_L3TYPE_IPV6) {
> +               for (i = 0; i < 16; i++) {
> +                       if (!(mask->src_ipv6_mask & (1 << i)))
> +                               input->src_ip[i / 4] &= ~(0xFF << ((i % 4) * 8));
> +               }
> +       } else {
> +               input->src_ip[0] &= mask->src_ipv4_mask;
> +               input->dst_ip[0] &= mask->dst_ipv4_mask;
> +       }
> +
> +       input->src_port &= mask->src_port_mask;
> +       input->dst_port &= mask->dst_port_mask; }
> +
>  int
>  txgbe_fdir_filter_program(struct rte_eth_dev *dev,
>                           struct txgbe_fdir_rule *rule, @@ -805,6 +840,8 @@
> txgbe_fdir_filter_program(struct rte_eth_dev *dev,
>         if (fdir_mode >= RTE_FDIR_MODE_PERFECT)
>                 is_perfect = TRUE;
> 
> +       txgbe_fdir_mask_input(&info->mask, &rule->input);
> +
>         if (is_perfect) {
>                 fdirhash = atr_compute_perfect_hash(&rule->input,
>                                 TXGBE_DEV_FDIR_CONF(dev)->pballoc);
> diff --git a/drivers/net/txgbe/txgbe_flow.c b/drivers/net/txgbe/txgbe_flow.c
> index 8ac29a0351..006e0b9759 100644
> --- a/drivers/net/txgbe/txgbe_flow.c
> +++ b/drivers/net/txgbe/txgbe_flow.c
> @@ -1834,9 +1834,7 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev
> *dev __rte_unused,
> 
>                         /* check dst addr mask */
>                         for (j = 0; j < 16; j++) {
> -                               if (ipv6_mask->hdr.dst_addr[j] == UINT8_MAX) {
> -                                       rule->mask.dst_ipv6_mask |= 1 << j;
> -                               } else if (ipv6_mask->hdr.dst_addr[j] != 0) {
> +                               if (ipv6_mask->hdr.dst_addr[j] != 0) {
>                                         memset(rule, 0, sizeof(struct txgbe_fdir_rule));
>                                         rte_flow_error_set(error, EINVAL,
>                                                 RTE_FLOW_ERROR_TYPE_ITEM, @@ -2597,9 +2595,7
> @@ txgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr,
> 
>                         /* check dst addr mask */
>                         for (j = 0; j < 16; j++) {
> -                               if (ipv6_mask->hdr.dst_addr[j] == UINT8_MAX) {
> -                                       rule->mask.dst_ipv6_mask |= 1 << j;
> -                               } else if (ipv6_mask->hdr.dst_addr[j] != 0) {
> +                               if (ipv6_mask->hdr.dst_addr[j] != 0) {
>                                         memset(rule, 0, sizeof(struct txgbe_fdir_rule));
>                                         rte_flow_error_set(error, EINVAL,
>                                                            RTE_FLOW_ERROR_TYPE_ITEM,
> --
> 2.48.1


Hey Jiawen,
The patch will be added to 23.11

Thank you!
Shani


More information about the stable mailing list