net/ice: support drop any and steer all to queue
[dpdk.git] / drivers / net / ice / ice_switch_filter.c
index d5add64..36c9bff 100644 (file)
@@ -206,6 +206,7 @@ static struct ice_flow_parser ice_switch_perm_parser;
 
 static struct
 ice_pattern_match_item ice_switch_pattern_dist_list[] = {
+       {pattern_any,                                   ICE_INSET_NONE,                         ICE_INSET_NONE,                         ICE_INSET_NONE},
        {pattern_ethertype,                             ICE_SW_INSET_ETHER,                     ICE_INSET_NONE,                         ICE_INSET_NONE},
        {pattern_ethertype_vlan,                        ICE_SW_INSET_MAC_VLAN,                  ICE_INSET_NONE,                         ICE_INSET_NONE},
        {pattern_ethertype_qinq,                        ICE_SW_INSET_MAC_QINQ,                  ICE_INSET_NONE,                         ICE_INSET_NONE},
@@ -289,6 +290,7 @@ ice_pattern_match_item ice_switch_pattern_dist_list[] = {
 
 static struct
 ice_pattern_match_item ice_switch_pattern_perm_list[] = {
+       {pattern_any,                                   ICE_INSET_NONE,                         ICE_INSET_NONE,                         ICE_INSET_NONE},
        {pattern_ethertype,                             ICE_SW_INSET_ETHER,                     ICE_INSET_NONE,                         ICE_INSET_NONE},
        {pattern_ethertype_vlan,                        ICE_SW_INSET_MAC_VLAN,                  ICE_INSET_NONE,                         ICE_INSET_NONE},
        {pattern_ethertype_qinq,                        ICE_SW_INSET_MAC_QINQ,                  ICE_INSET_NONE,                         ICE_INSET_NONE},
@@ -400,6 +402,14 @@ ice_switch_create(struct ice_adapter *ad,
                        "lookup list should not be NULL");
                goto error;
        }
+
+       if (ice_dcf_adminq_need_retry(ad)) {
+               rte_flow_error_set(error, EAGAIN,
+                       RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+                       "DCF is not on");
+               goto error;
+       }
+
        ret = ice_add_adv_rule(hw, list, lkups_cnt, rule_info, &rule_added);
        if (!ret) {
                filter_conf_ptr = rte_zmalloc("ice_switch_filter",
@@ -423,7 +433,12 @@ ice_switch_create(struct ice_adapter *ad,
 
                flow->rule = filter_conf_ptr;
        } else {
-               rte_flow_error_set(error, EINVAL,
+               if (ice_dcf_adminq_need_retry(ad))
+                       ret = -EAGAIN;
+               else
+                       ret = -EINVAL;
+
+               rte_flow_error_set(error, -ret,
                        RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
                        "switch filter create flow fail");
                goto error;
@@ -475,9 +490,21 @@ ice_switch_destroy(struct ice_adapter *ad,
                return -rte_errno;
        }
 
+       if (ice_dcf_adminq_need_retry(ad)) {
+               rte_flow_error_set(error, EAGAIN,
+                       RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+                       "DCF is not on");
+               return -rte_errno;
+       }
+
        ret = ice_rem_adv_rule_by_id(hw, &filter_conf_ptr->sw_query_data);
        if (ret) {
-               rte_flow_error_set(error, EINVAL,
+               if (ice_dcf_adminq_need_retry(ad))
+                       ret = -EAGAIN;
+               else
+                       ret = -EINVAL;
+
+               rte_flow_error_set(error, -ret,
                        RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
                        "fail to destroy switch filter rule");
                return -rte_errno;
@@ -557,6 +584,10 @@ ice_switch_parse_pattern(const struct rte_flow_item pattern[],
                item_type = item->type;
 
                switch (item_type) {
+               case RTE_FLOW_ITEM_TYPE_ANY:
+                       *tun_type = ICE_SW_TUN_AND_NON_TUN;
+                       break;
+
                case RTE_FLOW_ITEM_TYPE_ETH:
                        eth_spec = item->spec;
                        eth_mask = item->mask;
@@ -1926,8 +1957,12 @@ ice_switch_redirect(struct ice_adapter *ad,
                    struct rte_flow *flow,
                    struct ice_flow_redirect *rd)
 {
-       struct ice_rule_query_data *rdata = flow->rule;
+       struct ice_rule_query_data *rdata;
+       struct ice_switch_filter_conf *filter_conf_ptr =
+               (struct ice_switch_filter_conf *)flow->rule;
+       struct ice_rule_query_data added_rdata = { 0 };
        struct ice_adv_fltr_mgmt_list_entry *list_itr;
+       struct ice_adv_lkup_elem *lkups_ref = NULL;
        struct ice_adv_lkup_elem *lkups_dp = NULL;
        struct LIST_HEAD_TYPE *list_head;
        struct ice_adv_rule_info rinfo;
@@ -1936,6 +1971,8 @@ ice_switch_redirect(struct ice_adapter *ad,
        uint16_t lkups_cnt;
        int ret;
 
+       rdata = &filter_conf_ptr->sw_query_data;
+
        if (rdata->vsi_handle != rd->vsi_handle)
                return 0;
 
@@ -1946,59 +1983,117 @@ ice_switch_redirect(struct ice_adapter *ad,
        if (rd->type != ICE_FLOW_REDIRECT_VSI)
                return -ENOTSUP;
 
-       list_head = &sw->recp_list[rdata->rid].filt_rules;
-       LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_adv_fltr_mgmt_list_entry,
-                           list_entry) {
-               rinfo = list_itr->rule_info;
-               if ((rinfo.fltr_rule_id == rdata->rule_id &&
-                   rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI &&
-                   rinfo.sw_act.vsi_handle == rd->vsi_handle) ||
-                   (rinfo.fltr_rule_id == rdata->rule_id &&
-                   rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST)){
-                       lkups_cnt = list_itr->lkups_cnt;
-                       lkups_dp = (struct ice_adv_lkup_elem *)
-                               ice_memdup(hw, list_itr->lkups,
-                                          sizeof(*list_itr->lkups) *
-                                          lkups_cnt, ICE_NONDMA_TO_NONDMA);
-
-                       if (!lkups_dp) {
-                               PMD_DRV_LOG(ERR, "Failed to allocate memory.");
-                               return -EINVAL;
-                       }
+       switch (filter_conf_ptr->fltr_status) {
+       case ICE_SW_FLTR_ADDED:
+               list_head = &sw->recp_list[rdata->rid].filt_rules;
+               LIST_FOR_EACH_ENTRY(list_itr, list_head,
+                                   ice_adv_fltr_mgmt_list_entry,
+                                   list_entry) {
+                       rinfo = list_itr->rule_info;
+                       if ((rinfo.fltr_rule_id == rdata->rule_id &&
+                           rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI &&
+                           rinfo.sw_act.vsi_handle == rd->vsi_handle) ||
+                           (rinfo.fltr_rule_id == rdata->rule_id &&
+                           rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST)){
+                               lkups_cnt = list_itr->lkups_cnt;
+
+                               lkups_dp = (struct ice_adv_lkup_elem *)
+                                       ice_memdup(hw, list_itr->lkups,
+                                                  sizeof(*list_itr->lkups) *
+                                                  lkups_cnt,
+                                                  ICE_NONDMA_TO_NONDMA);
+                               if (!lkups_dp) {
+                                       PMD_DRV_LOG(ERR,
+                                                   "Failed to allocate memory.");
+                                       return -EINVAL;
+                               }
+                               lkups_ref = lkups_dp;
 
-                       if (rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST) {
-                               rinfo.sw_act.vsi_handle = rd->vsi_handle;
-                               rinfo.sw_act.fltr_act = ICE_FWD_TO_VSI;
+                               if (rinfo.sw_act.fltr_act ==
+                                   ICE_FWD_TO_VSI_LIST) {
+                                       rinfo.sw_act.vsi_handle =
+                                               rd->vsi_handle;
+                                       rinfo.sw_act.fltr_act = ICE_FWD_TO_VSI;
+                               }
+                               break;
                        }
-                       break;
                }
-       }
 
-       if (!lkups_dp)
+               if (!lkups_ref)
+                       return -EINVAL;
+
+               goto rmv_rule;
+       case ICE_SW_FLTR_RMV_FAILED_ON_RIDRECT:
+               /* Recover VSI context */
+               hw->vsi_ctx[rd->vsi_handle]->vsi_num = filter_conf_ptr->vsi_num;
+               rinfo = filter_conf_ptr->rule_info;
+               lkups_cnt = filter_conf_ptr->lkups_num;
+               lkups_ref = filter_conf_ptr->lkups;
+
+               if (rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST) {
+                       rinfo.sw_act.vsi_handle = rd->vsi_handle;
+                       rinfo.sw_act.fltr_act = ICE_FWD_TO_VSI;
+               }
+
+               goto rmv_rule;
+       case ICE_SW_FLTR_ADD_FAILED_ON_RIDRECT:
+               rinfo = filter_conf_ptr->rule_info;
+               lkups_cnt = filter_conf_ptr->lkups_num;
+               lkups_ref = filter_conf_ptr->lkups;
+
+               goto add_rule;
+       default:
                return -EINVAL;
+       }
+
+rmv_rule:
+       if (ice_dcf_adminq_need_retry(ad)) {
+               PMD_DRV_LOG(WARNING, "DCF is not on");
+               ret = -EAGAIN;
+               goto out;
+       }
 
        /* Remove the old rule */
-       ret = ice_rem_adv_rule(hw, list_itr->lkups,
-                              lkups_cnt, &rinfo);
+       ret = ice_rem_adv_rule(hw, lkups_ref, lkups_cnt, &rinfo);
        if (ret) {
                PMD_DRV_LOG(ERR, "Failed to delete the old rule %d",
                            rdata->rule_id);
+               filter_conf_ptr->fltr_status =
+                       ICE_SW_FLTR_RMV_FAILED_ON_RIDRECT;
                ret = -EINVAL;
                goto out;
        }
 
+add_rule:
+       if (ice_dcf_adminq_need_retry(ad)) {
+               PMD_DRV_LOG(WARNING, "DCF is not on");
+               ret = -EAGAIN;
+               goto out;
+       }
+
        /* Update VSI context */
        hw->vsi_ctx[rd->vsi_handle]->vsi_num = rd->new_vsi_num;
 
        /* Replay the rule */
-       ret = ice_add_adv_rule(hw, lkups_dp, lkups_cnt,
-                              &rinfo, rdata);
+       ret = ice_add_adv_rule(hw, lkups_ref, lkups_cnt,
+                              &rinfo, &added_rdata);
        if (ret) {
                PMD_DRV_LOG(ERR, "Failed to replay the rule");
+               filter_conf_ptr->fltr_status =
+                       ICE_SW_FLTR_ADD_FAILED_ON_RIDRECT;
                ret = -EINVAL;
+       } else {
+               filter_conf_ptr->sw_query_data = added_rdata;
+               /* Save VSI number for failure recover */
+               filter_conf_ptr->vsi_num = rd->new_vsi_num;
+               filter_conf_ptr->fltr_status = ICE_SW_FLTR_ADDED;
        }
 
 out:
+       if (ret == -EINVAL)
+               if (ice_dcf_adminq_need_retry(ad))
+                       ret = -EAGAIN;
+
        ice_free(hw, lkups_dp);
        return ret;
 }