The raw patthern is required to be two hex bytes on hardware, but it is
string in the raw item. So the length of raw spec should be 4, and the
string should be converted to the two hex bytes. And relative of raw
spec is supported to be optical.

Fixes: b973ee26747a ("net/txgbe: parse flow director filter")
Cc: sta...@dpdk.org

Signed-off-by: Jiawen Wu <jiawe...@trustnetic.com>
---
 drivers/net/txgbe/txgbe_ethdev.h |  5 ++-
 drivers/net/txgbe/txgbe_fdir.c   | 24 +++++++++++++--
 drivers/net/txgbe/txgbe_flow.c   | 53 ++++++++++++++++++++++++--------
 3 files changed, 67 insertions(+), 15 deletions(-)

diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h
index 36d51fcbb8..0a3c634937 100644
--- a/drivers/net/txgbe/txgbe_ethdev.h
+++ b/drivers/net/txgbe/txgbe_ethdev.h
@@ -116,11 +116,13 @@ struct txgbe_fdir_rule {
        uint32_t soft_id; /* an unique value for this rule */
        uint8_t queue; /* assigned rx queue */
        uint8_t flex_bytes_offset;
+       bool flex_relative;
 };
 
 struct txgbe_hw_fdir_info {
        struct txgbe_hw_fdir_mask mask;
        uint8_t     flex_bytes_offset;
+       bool        flex_relative;
        uint16_t    collision;
        uint16_t    free;
        uint16_t    maxhash;
@@ -561,8 +563,9 @@ void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t 
direction,
  */
 int txgbe_fdir_configure(struct rte_eth_dev *dev);
 int txgbe_fdir_set_input_mask(struct rte_eth_dev *dev);
+uint16_t txgbe_fdir_get_flex_base(struct txgbe_fdir_rule *rule);
 int txgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
-                                   uint16_t offset);
+                                   uint16_t offset, uint16_t flex_base);
 int txgbe_fdir_filter_program(struct rte_eth_dev *dev,
                              struct txgbe_fdir_rule *rule,
                              bool del, bool update);
diff --git a/drivers/net/txgbe/txgbe_fdir.c b/drivers/net/txgbe/txgbe_fdir.c
index f627ab681d..75bf30c00c 100644
--- a/drivers/net/txgbe/txgbe_fdir.c
+++ b/drivers/net/txgbe/txgbe_fdir.c
@@ -258,9 +258,24 @@ txgbe_fdir_store_input_mask(struct rte_eth_dev *dev)
        return 0;
 }
 
+uint16_t
+txgbe_fdir_get_flex_base(struct txgbe_fdir_rule *rule)
+{
+       if (!rule->flex_relative)
+               return TXGBE_FDIRFLEXCFG_BASE_MAC;
+
+       if (rule->input.flow_type & TXGBE_ATR_L4TYPE_MASK)
+               return TXGBE_FDIRFLEXCFG_BASE_PAY;
+
+       if (rule->input.flow_type & TXGBE_ATR_L3TYPE_MASK)
+               return TXGBE_FDIRFLEXCFG_BASE_L3;
+
+       return TXGBE_FDIRFLEXCFG_BASE_L2;
+}
+
 int
 txgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
-                               uint16_t offset)
+                               uint16_t offset, uint16_t flex_base)
 {
        struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
        int i;
@@ -268,7 +283,7 @@ txgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
        for (i = 0; i < 64; i++) {
                uint32_t flexreg, flex;
                flexreg = rd32(hw, TXGBE_FDIRFLEXCFG(i / 4));
-               flex = TXGBE_FDIRFLEXCFG_BASE_MAC;
+               flex = flex_base;
                flex |= TXGBE_FDIRFLEXCFG_OFST(offset / 2);
                flexreg &= ~(TXGBE_FDIRFLEXCFG_ALL(~0UL, i % 4));
                flexreg |= TXGBE_FDIRFLEXCFG_ALL(flex, i % 4);
@@ -910,6 +925,11 @@ txgbe_fdir_flush(struct rte_eth_dev *dev)
        info->add = 0;
        info->remove = 0;
 
+       memset(&info->mask, 0, sizeof(struct txgbe_hw_fdir_mask));
+       info->mask_added = false;
+       info->flex_relative = false;
+       info->flex_bytes_offset = 0;
+
        return ret;
 }
 
diff --git a/drivers/net/txgbe/txgbe_flow.c b/drivers/net/txgbe/txgbe_flow.c
index 269f0b54e3..8670c3e1d7 100644
--- a/drivers/net/txgbe/txgbe_flow.c
+++ b/drivers/net/txgbe/txgbe_flow.c
@@ -2066,6 +2066,8 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev 
__rte_unused,
 
        /* Get the flex byte info */
        if (item->type == RTE_FLOW_ITEM_TYPE_RAW) {
+               uint16_t pattern = 0;
+
                /* Not supported last point for range*/
                if (item->last) {
                        rte_flow_error_set(error, EINVAL,
@@ -2082,6 +2084,7 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev 
__rte_unused,
                        return -rte_errno;
                }
 
+               rule->b_mask = TRUE;
                raw_mask = item->mask;
 
                /* check mask */
@@ -2098,19 +2101,21 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev 
__rte_unused,
                        return -rte_errno;
                }
 
+               rule->b_spec = TRUE;
                raw_spec = item->spec;
 
                /* check spec */
-               if (raw_spec->relative != 0 ||
-                   raw_spec->search != 0 ||
+               if (raw_spec->search != 0 ||
                    raw_spec->reserved != 0 ||
                    raw_spec->offset > TXGBE_MAX_FLX_SOURCE_OFF ||
                    raw_spec->offset % 2 ||
                    raw_spec->limit != 0 ||
-                   raw_spec->length != 2 ||
+                   raw_spec->length != 4 ||
                    /* pattern can't be 0xffff */
                    (raw_spec->pattern[0] == 0xff &&
-                    raw_spec->pattern[1] == 0xff)) {
+                    raw_spec->pattern[1] == 0xff &&
+                    raw_spec->pattern[2] == 0xff &&
+                    raw_spec->pattern[3] == 0xff)) {
                        memset(rule, 0, sizeof(struct txgbe_fdir_rule));
                        rte_flow_error_set(error, EINVAL,
                                RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2120,7 +2125,9 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev 
__rte_unused,
 
                /* check pattern mask */
                if (raw_mask->pattern[0] != 0xff ||
-                   raw_mask->pattern[1] != 0xff) {
+                   raw_mask->pattern[1] != 0xff ||
+                   raw_mask->pattern[2] != 0xff ||
+                   raw_mask->pattern[3] != 0xff) {
                        memset(rule, 0, sizeof(struct txgbe_fdir_rule));
                        rte_flow_error_set(error, EINVAL,
                                RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2129,10 +2136,19 @@ txgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev 
__rte_unused,
                }
 
                rule->mask.flex_bytes_mask = 0xffff;
-               rule->input.flex_bytes =
-                       (((uint16_t)raw_spec->pattern[1]) << 8) |
-                       raw_spec->pattern[0];
+               /* Convert pattern string to hex bytes */
+               if (sscanf((const char *)raw_spec->pattern, "%hx", &pattern) != 
1) {
+                       memset(rule, 0, sizeof(struct txgbe_fdir_rule));
+                       rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ITEM,
+                               item, "Failed to parse raw pattern");
+                       return -rte_errno;
+               }
+               rule->input.flex_bytes = (pattern & 0x00FF) << 8;
+               rule->input.flex_bytes |= (pattern & 0xFF00) >> 8;
+
                rule->flex_bytes_offset = raw_spec->offset;
+               rule->flex_relative = raw_spec->relative;
        }
 
        if (item->type != RTE_FLOW_ITEM_TYPE_END) {
@@ -2836,10 +2852,16 @@ txgbe_flow_create(struct rte_eth_dev *dev,
                                fdir_info->mask = fdir_rule.mask;
                                fdir_info->flex_bytes_offset =
                                        fdir_rule.flex_bytes_offset;
+                               fdir_info->flex_relative = 
fdir_rule.flex_relative;
+
+                               if (fdir_rule.mask.flex_bytes_mask) {
+                                       uint16_t flex_base;
 
-                               if (fdir_rule.mask.flex_bytes_mask)
+                                       flex_base = 
txgbe_fdir_get_flex_base(&fdir_rule);
                                        txgbe_fdir_set_flexbytes_offset(dev,
-                                               fdir_rule.flex_bytes_offset);
+                                                                       
fdir_rule.flex_bytes_offset,
+                                                                       
flex_base);
+                               }
 
                                ret = txgbe_fdir_set_input_mask(dev);
                                if (ret)
@@ -2861,7 +2883,9 @@ txgbe_flow_create(struct rte_eth_dev *dev,
                                }
 
                                if (fdir_info->flex_bytes_offset !=
-                                               fdir_rule.flex_bytes_offset)
+                                   fdir_rule.flex_bytes_offset ||
+                                   fdir_info->flex_relative !=
+                                   fdir_rule.flex_relative)
                                        goto out;
                        }
                }
@@ -3089,8 +3113,13 @@ txgbe_flow_destroy(struct rte_eth_dev *dev,
                        TAILQ_REMOVE(&filter_fdir_list,
                                fdir_rule_ptr, entries);
                        rte_free(fdir_rule_ptr);
-                       if (TAILQ_EMPTY(&filter_fdir_list))
+                       if (TAILQ_EMPTY(&filter_fdir_list)) {
+                               memset(&fdir_info->mask, 0,
+                                       sizeof(struct txgbe_hw_fdir_mask));
                                fdir_info->mask_added = false;
+                               fdir_info->flex_relative = false;
+                               fdir_info->flex_bytes_offset = 0;
+                       }
                }
                break;
        case RTE_ETH_FILTER_L2_TUNNEL:
-- 
2.48.1

Reply via email to