[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