i40e: get flow director information
authorJingjing Wu <jingjing.wu@intel.com>
Fri, 21 Nov 2014 00:46:49 +0000 (08:46 +0800)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Mon, 24 Nov 2014 23:06:04 +0000 (00:06 +0100)
implement operation to get flow director information in i40e pmd driver, includes
 - mode
 - supported flow types
 - table space
 - flexible payload size and granularity
 - configured flexible payload and mask information

Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
lib/librte_pmd_i40e/i40e_ethdev.h
lib/librte_pmd_i40e/i40e_fdir.c

index a8f87a4..f99fbea 100644 (file)
@@ -90,6 +90,7 @@ enum i40e_flxpld_layer_idx {
 #define I40E_MAX_FLXPLD_FIED        3  /* max number of flex payload fields */
 #define I40E_FDIR_BITMASK_NUM_WORD  2  /* max number of bitmask words */
 #define I40E_FDIR_MAX_FLEXWORD_NUM  8  /* max number of flexpayload words */
+#define I40E_FDIR_MAX_FLEX_LEN      16 /* len in bytes of flex payload */
 
 /* i40e flags */
 #define I40E_FLAG_RSS                   (1ULL << 0)
index 143754a..059ff3e 100644 (file)
 #define I40E_COUNTER_PF           2
 /* Statistic counter index for one pf */
 #define I40E_COUNTER_INDEX_FDIR(pf_id)   (0 + (pf_id) * I40E_COUNTER_PF)
+#define I40E_MAX_FLX_SOURCE_OFF           480
 #define I40E_FLX_OFFSET_IN_FIELD_VECTOR   50
 
+#define NONUSE_FLX_PIT_DEST_OFF 63
+#define NONUSE_FLX_PIT_FSIZE    1
+#define MK_FLX_PIT(src_offset, fsize, dst_offset) ( \
+       (((src_offset) << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT) & \
+               I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK) | \
+       (((fsize) << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) & \
+                       I40E_PRTQF_FLX_PIT_FSIZE_MASK) | \
+       ((((dst_offset) + I40E_FLX_OFFSET_IN_FIELD_VECTOR) << \
+                       I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT) & \
+                       I40E_PRTQF_FLX_PIT_DEST_OFF_MASK))
+
+#define I40E_FDIR_FLOW_TYPES ( \
+       (1 << RTE_ETH_FLOW_TYPE_UDPV4) | \
+       (1 << RTE_ETH_FLOW_TYPE_TCPV4) | \
+       (1 << RTE_ETH_FLOW_TYPE_SCTPV4) | \
+       (1 << RTE_ETH_FLOW_TYPE_IPV4_OTHER) | \
+       (1 << RTE_ETH_FLOW_TYPE_FRAG_IPV4) | \
+       (1 << RTE_ETH_FLOW_TYPE_UDPV6) | \
+       (1 << RTE_ETH_FLOW_TYPE_TCPV6) | \
+       (1 << RTE_ETH_FLOW_TYPE_SCTPV6) | \
+       (1 << RTE_ETH_FLOW_TYPE_IPV6_OTHER) | \
+       (1 << RTE_ETH_FLOW_TYPE_FRAG_IPV6))
+
+#define I40E_FLEX_WORD_MASK(off) (0x80 >> (off))
+
 static int i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq);
 static int i40e_fdir_construct_pkt(struct i40e_pf *pf,
                                     const struct rte_eth_fdir_input *fdir_input,
@@ -94,6 +120,8 @@ static int i40e_fdir_filter_programming(struct i40e_pf *pf,
                        const struct rte_eth_fdir_filter *filter,
                        bool add);
 static int i40e_fdir_flush(struct rte_eth_dev *dev);
+static void i40e_fdir_info_get(struct rte_eth_dev *dev,
+                          struct rte_eth_fdir_info *fdir);
 
 static int
 i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
@@ -861,6 +889,120 @@ i40e_fdir_flush(struct rte_eth_dev *dev)
        return 0;
 }
 
+static inline void
+i40e_fdir_info_get_flex_set(struct i40e_pf *pf,
+                       struct rte_eth_flex_payload_cfg *flex_set,
+                       uint16_t *num)
+{
+       struct i40e_fdir_flex_pit *flex_pit;
+       struct rte_eth_flex_payload_cfg *ptr = flex_set;
+       uint16_t src, dst, size, j, k;
+       uint8_t i, layer_idx;
+
+       for (layer_idx = I40E_FLXPLD_L2_IDX;
+            layer_idx <= I40E_FLXPLD_L4_IDX;
+            layer_idx++) {
+               if (layer_idx == I40E_FLXPLD_L2_IDX)
+                       ptr->type = RTE_ETH_L2_PAYLOAD;
+               else if (layer_idx == I40E_FLXPLD_L3_IDX)
+                       ptr->type = RTE_ETH_L3_PAYLOAD;
+               else if (layer_idx == I40E_FLXPLD_L4_IDX)
+                       ptr->type = RTE_ETH_L4_PAYLOAD;
+
+               for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) {
+                       flex_pit = &pf->fdir.flex_set[layer_idx *
+                               I40E_MAX_FLXPLD_FIED + i];
+                       if (flex_pit->size == 0)
+                               continue;
+                       src = flex_pit->src_offset * sizeof(uint16_t);
+                       dst = flex_pit->dst_offset * sizeof(uint16_t);
+                       size = flex_pit->size * sizeof(uint16_t);
+                       for (j = src, k = dst; j < src + size; j++, k++)
+                               ptr->src_offset[k] = j;
+               }
+               (*num)++;
+               ptr++;
+       }
+}
+
+static inline void
+i40e_fdir_info_get_flex_mask(struct i40e_pf *pf,
+                       struct rte_eth_fdir_flex_mask *flex_mask,
+                       uint16_t *num)
+{
+       struct i40e_fdir_flex_mask *mask;
+       struct rte_eth_fdir_flex_mask *ptr = flex_mask;
+       enum rte_eth_flow_type flow_type;
+       uint8_t i, j;
+       uint16_t off_bytes, mask_tmp;
+
+       for (i = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
+            i <= I40E_FILTER_PCTYPE_FRAG_IPV6;
+            i++) {
+               mask =  &pf->fdir.flex_mask[i];
+               if (!I40E_VALID_PCTYPE((enum i40e_filter_pctype)i))
+                       continue;
+               flow_type = i40e_pctype_to_flowtype((enum i40e_filter_pctype)i);
+               for (j = 0; j < I40E_FDIR_MAX_FLEXWORD_NUM; j++) {
+                       if (mask->word_mask & I40E_FLEX_WORD_MASK(j)) {
+                               ptr->mask[j * sizeof(uint16_t)] = UINT8_MAX;
+                               ptr->mask[j * sizeof(uint16_t) + 1] = UINT8_MAX;
+                       } else {
+                               ptr->mask[j * sizeof(uint16_t)] = 0x0;
+                               ptr->mask[j * sizeof(uint16_t) + 1] = 0x0;
+                       }
+               }
+               for (j = 0; j < I40E_FDIR_BITMASK_NUM_WORD; j++) {
+                       off_bytes = mask->bitmask[j].offset * sizeof(uint16_t);
+                       mask_tmp = ~mask->bitmask[j].mask;
+                       ptr->mask[off_bytes] &= I40E_HI_BYTE(mask_tmp);
+                       ptr->mask[off_bytes + 1] &= I40E_LO_BYTE(mask_tmp);
+               }
+               ptr->flow_type = flow_type;
+               ptr++;
+               (*num)++;
+       }
+}
+
+/*
+ * i40e_fdir_info_get - get information of Flow Director
+ * @pf: ethernet device to get info from
+ * @fdir: a pointer to a structure of type *rte_eth_fdir_info* to be filled with
+ *    the flow director information.
+ */
+static void
+i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+       uint16_t num_flex_set = 0;
+       uint16_t num_flex_mask = 0;
+
+       fdir->mode = (pf->flags & I40E_FLAG_FDIR) ?
+                       RTE_FDIR_MODE_PERFECT : RTE_FDIR_MODE_NONE;
+       fdir->guarant_spc =
+               (uint32_t)hw->func_caps.fd_filters_guaranteed;
+       fdir->best_spc =
+               (uint32_t)hw->func_caps.fd_filters_best_effort;
+       fdir->max_flexpayload = I40E_FDIR_MAX_FLEX_LEN;
+       fdir->flow_types_mask[0] = I40E_FDIR_FLOW_TYPES;
+       fdir->flex_payload_unit = sizeof(uint16_t);
+       fdir->flex_bitmask_unit = sizeof(uint16_t);
+       fdir->max_flex_payload_segment_num = I40E_MAX_FLXPLD_FIED;
+       fdir->flex_payload_limit = I40E_MAX_FLX_SOURCE_OFF;
+       fdir->max_flex_bitmask_num = I40E_FDIR_BITMASK_NUM_WORD;
+
+       i40e_fdir_info_get_flex_set(pf,
+                               fdir->flex_conf.flex_set,
+                               &num_flex_set);
+       i40e_fdir_info_get_flex_mask(pf,
+                               fdir->flex_conf.flex_mask,
+                               &num_flex_mask);
+
+       fdir->flex_conf.nb_payloads = num_flex_set;
+       fdir->flex_conf.nb_flexmasks = num_flex_mask;
+}
+
 /*
  * i40e_fdir_ctrl_func - deal with all operations on flow director.
  * @pf: board private structure
@@ -898,6 +1040,9 @@ i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
        case RTE_ETH_FILTER_FLUSH:
                ret = i40e_fdir_flush(dev);
                break;
+       case RTE_ETH_FILTER_INFO:
+               i40e_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg);
+               break;
        default:
                PMD_DRV_LOG(ERR, "unknown operation %u.", filter_op);
                ret = -EINVAL;