net/i40e: add flow create function
authorBeilei Xing <beilei.xing@intel.com>
Fri, 6 Jan 2017 05:27:12 +0000 (13:27 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:40:54 +0000 (19:40 +0100)
This patch adds i40e_flow_create function to create a
rule. It will check if a flow matches ethertype filter
or flow director filter or tunnel filter, if the flow
matches some kind of filter, then set the filter to HW.

Signed-off-by: Beilei Xing <beilei.xing@intel.com>
Acked-by: Jingjing Wu <jingjing.wu@intel.com>
drivers/net/i40e/i40e_ethdev.c
drivers/net/i40e/i40e_ethdev.h
drivers/net/i40e/i40e_fdir.c
drivers/net/i40e/i40e_flow.c

index 0a7310d..b690850 100644 (file)
@@ -350,9 +350,6 @@ static int i40e_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,
 static int i40e_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
                                        struct rte_eth_udp_tunnel *udp_tunnel);
 static void i40e_filter_input_set_init(struct i40e_pf *pf);
-static int i40e_ethertype_filter_set(struct i40e_pf *pf,
-                       struct rte_eth_ethertype_filter *filter,
-                       bool add);
 static int i40e_ethertype_filter_handle(struct rte_eth_dev *dev,
                                enum rte_filter_op filter_op,
                                void *arg);
@@ -1377,6 +1374,7 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
        struct rte_intr_handle *intr_handle;
        struct i40e_hw *hw;
        struct i40e_filter_control_settings settings;
+       struct rte_flow *p_flow;
        int ret;
        uint8_t aq_fail = 0;
 
@@ -1428,6 +1426,12 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
        i40e_rm_tunnel_filter_list(pf);
        i40e_rm_fdir_filter_list(pf);
 
+       /* Remove all flows */
+       while ((p_flow = TAILQ_FIRST(&pf->flow_list))) {
+               TAILQ_REMOVE(&pf->flow_list, p_flow, node);
+               rte_free(p_flow);
+       }
+
        return 0;
 }
 
@@ -1492,6 +1496,8 @@ i40e_dev_configure(struct rte_eth_dev *dev)
                }
        }
 
+       TAILQ_INIT(&pf->flow_list);
+
        return 0;
 
 err_dcb:
@@ -6722,7 +6728,7 @@ i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
        return 0;
 }
 
-static int
+int
 i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
                        struct rte_eth_tunnel_filter_conf *tunnel_filter,
                        uint8_t add)
@@ -8367,7 +8373,7 @@ i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
  * Configure ethertype filter, which can director packet by filtering
  * with mac address and ether_type or only ether_type
  */
-static int
+int
 i40e_ethertype_filter_set(struct i40e_pf *pf,
                        struct rte_eth_ethertype_filter *filter,
                        bool add)
index a628f0a..0ce8de2 100644 (file)
@@ -540,6 +540,17 @@ struct i40e_mirror_rule {
 
 TAILQ_HEAD(i40e_mirror_rule_list, i40e_mirror_rule);
 
+/*
+ * Struct to store flow created.
+ */
+struct rte_flow {
+       TAILQ_ENTRY(rte_flow) node;
+       enum rte_filter_type filter_type;
+       void *rule;
+};
+
+TAILQ_HEAD(i40e_flow_list, rte_flow);
+
 /*
  * Structure to store private data specific for PF instance.
  */
@@ -597,6 +608,7 @@ struct i40e_pf {
        bool floating_veb; /* The flag to use the floating VEB */
        /* The floating enable flag for the specific VF */
        bool floating_veb_list[I40E_MAX_VF];
+       struct i40e_flow_list flow_list;
 };
 
 enum pending_msg {
@@ -774,6 +786,15 @@ i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
 int i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
                              struct i40e_tunnel_filter_input *input);
 uint64_t i40e_get_default_input_set(uint16_t pctype);
+int i40e_ethertype_filter_set(struct i40e_pf *pf,
+                             struct rte_eth_ethertype_filter *filter,
+                             bool add);
+int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
+                            const struct rte_eth_fdir_filter *filter,
+                            bool add);
+int i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
+                              struct rte_eth_tunnel_filter_conf *tunnel_filter,
+                              uint8_t add);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
        RTE_DEV_TO_PCI((eth_dev)->device)
index f89dbc9..91d91aa 100644 (file)
@@ -1099,7 +1099,7 @@ i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct rte_eth_fdir_input *input)
  * @filter: fdir filter entry
  * @add: 0 - delete, 1 - add
  */
-static int
+int
 i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
                            const struct rte_eth_fdir_filter *filter,
                            bool add)
index ed87624..d4d9f50 100644 (file)
@@ -63,6 +63,11 @@ static int i40e_flow_validate(struct rte_eth_dev *dev,
                              const struct rte_flow_item pattern[],
                              const struct rte_flow_action actions[],
                              struct rte_flow_error *error);
+static struct rte_flow *i40e_flow_create(struct rte_eth_dev *dev,
+                                        const struct rte_flow_attr *attr,
+                                        const struct rte_flow_item pattern[],
+                                        const struct rte_flow_action actions[],
+                                        struct rte_flow_error *error);
 static int
 i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
                                  const struct rte_flow_item *pattern,
@@ -111,9 +116,11 @@ static int i40e_flow_parse_tunnel_filter(struct rte_eth_dev *dev,
 
 const struct rte_flow_ops i40e_flow_ops = {
        .validate = i40e_flow_validate,
+       .create = i40e_flow_create,
 };
 
 union i40e_filter_t cons_filter;
+enum rte_filter_type cons_filter_type = RTE_ETH_FILTER_NONE;
 
 /* Pattern matched ethertype filter */
 static enum rte_flow_item_type pattern_ethertype[] = {
@@ -615,6 +622,8 @@ i40e_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
        if (ret)
                return ret;
 
+       cons_filter_type = RTE_ETH_FILTER_ETHERTYPE;
+
        return ret;
 }
 
@@ -1093,6 +1102,8 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
        if (ret)
                return ret;
 
+       cons_filter_type = RTE_ETH_FILTER_FDIR;
+
        if (dev->data->dev_conf.fdir_conf.mode !=
            RTE_FDIR_MODE_PERFECT) {
                rte_flow_error_set(error, ENOTSUP,
@@ -1454,6 +1465,8 @@ i40e_flow_parse_tunnel_filter(struct rte_eth_dev *dev,
        if (ret)
                return ret;
 
+       cons_filter_type = RTE_ETH_FILTER_TUNNEL;
+
        return ret;
 }
 
@@ -1525,3 +1538,67 @@ i40e_flow_validate(struct rte_eth_dev *dev,
 
        return ret;
 }
+
+static struct rte_flow *
+i40e_flow_create(struct rte_eth_dev *dev,
+                const struct rte_flow_attr *attr,
+                const struct rte_flow_item pattern[],
+                const struct rte_flow_action actions[],
+                struct rte_flow_error *error)
+{
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct rte_flow *flow;
+       int ret;
+
+       flow = rte_zmalloc("i40e_flow", sizeof(struct rte_flow), 0);
+       if (!flow) {
+               rte_flow_error_set(error, ENOMEM,
+                                  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+                                  "Failed to allocate memory");
+               return flow;
+       }
+
+       ret = i40e_flow_validate(dev, attr, pattern, actions, error);
+       if (ret < 0)
+               return NULL;
+
+       switch (cons_filter_type) {
+       case RTE_ETH_FILTER_ETHERTYPE:
+               ret = i40e_ethertype_filter_set(pf,
+                                       &cons_filter.ethertype_filter, 1);
+               if (ret)
+                       goto free_flow;
+               flow->rule = TAILQ_LAST(&pf->ethertype.ethertype_list,
+                                       i40e_ethertype_filter_list);
+               break;
+       case RTE_ETH_FILTER_FDIR:
+               ret = i40e_add_del_fdir_filter(dev,
+                                      &cons_filter.fdir_filter, 1);
+               if (ret)
+                       goto free_flow;
+               flow->rule = TAILQ_LAST(&pf->fdir.fdir_list,
+                                       i40e_fdir_filter_list);
+               break;
+       case RTE_ETH_FILTER_TUNNEL:
+               ret = i40e_dev_tunnel_filter_set(pf,
+                                        &cons_filter.tunnel_filter, 1);
+               if (ret)
+                       goto free_flow;
+               flow->rule = TAILQ_LAST(&pf->tunnel.tunnel_list,
+                                       i40e_tunnel_filter_list);
+               break;
+       default:
+               goto free_flow;
+       }
+
+       flow->filter_type = cons_filter_type;
+       TAILQ_INSERT_TAIL(&pf->flow_list, flow, node);
+       return flow;
+
+free_flow:
+       rte_flow_error_set(error, -ret,
+                          RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+                          "Failed to create flow.");
+       rte_free(flow);
+       return NULL;
+}