net/ice/base: allow profile based switch rules
authorQi Zhang <qi.z.zhang@intel.com>
Mon, 30 Mar 2020 11:45:30 +0000 (19:45 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:05 +0000 (13:57 +0200)
Switch rules usually match packet fields to take actions. Add capability
to add a switch rule that does not match any packet fields, but instead
matches the profile that the packet hits in the switch block.

Signed-off-by: Dan Nowlin <dan.nowlin@intel.com>
Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Qiming Yang <qiming.yang@intel.com>
drivers/net/ice/base/ice_protocol_type.h
drivers/net/ice/base/ice_switch.c
drivers/net/ice/base/ice_switch.h

index eda7172..a63ef0c 100644 (file)
@@ -61,6 +61,9 @@ enum ice_sw_tunnel_type {
                         */
        ICE_SW_TUN_GTP,
        ICE_SW_TUN_PPPOE,
+       ICE_SW_TUN_PROFID_IPV6_ESP,
+       ICE_SW_TUN_PROFID_IPV6_AH,
+       ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3,
        ICE_ALL_TUNNELS /* All tunnel types including NVGRE */
 };
 
index 103894f..83fb40f 100644 (file)
@@ -5147,6 +5147,19 @@ ice_create_first_fit_recp_def(struct ice_hw *hw,
 
        *recp_cnt = 0;
 
+       if (!lkup_exts->n_val_words) {
+               struct ice_recp_grp_entry *entry;
+
+               entry = (struct ice_recp_grp_entry *)
+                       ice_malloc(hw, sizeof(*entry));
+               if (!entry)
+                       return ICE_ERR_NO_MEMORY;
+               LIST_ADD(&entry->l_entry, rg_list);
+               grp = &entry->r_group;
+               (*recp_cnt)++;
+               grp->n_val_pairs = 0;
+       }
+
        /* Walk through every word in the rule to check if it is not done. If so
         * then this word needs to be part of a new recipe.
         */
@@ -5679,6 +5692,9 @@ ice_get_fv(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
        u8 *prot_ids;
        u16 i;
 
+       if (!lkups_cnt)
+               return ICE_SUCCESS;
+
        prot_ids = (u8 *)ice_calloc(hw, lkups_cnt, sizeof(*prot_ids));
        if (!prot_ids)
                return ICE_ERR_NO_MEMORY;
@@ -5736,6 +5752,8 @@ ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
 {
        enum ice_prof_type prof_type;
 
+       ice_zero_bitmap(bm, ICE_MAX_NUM_PROFILES);
+
        switch (rinfo->tun_type) {
        case ICE_NON_TUN:
                prof_type = ICE_PROF_NON_TUN;
@@ -5756,6 +5774,15 @@ ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
        case ICE_SW_TUN_PPPOE:
                prof_type = ICE_PROF_TUN_PPPOE;
                break;
+       case ICE_SW_TUN_PROFID_IPV6_ESP:
+               ice_set_bit(ICE_PROFID_IPV6_ESP, bm);
+               return;
+       case ICE_SW_TUN_PROFID_IPV6_AH:
+               ice_set_bit(ICE_PROFID_IPV6_AH, bm);
+               return;
+       case ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3:
+               ice_set_bit(ICE_PROFID_MAC_IPV6_L2TPV3, bm);
+               return;
        case ICE_SW_TUN_AND_NON_TUN:
        default:
                prof_type = ICE_PROF_ALL;
@@ -5765,6 +5792,27 @@ ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
        ice_get_sw_fv_bitmap(hw, prof_type, bm);
 }
 
+/**
+ * ice_is_prof_rule - determine if rule type is a profile rule
+ * @type: the rule type
+ *
+ * if the rule type is a profile rule, that means that there no field value
+ * match required, in this case just a profile hit is required.
+ */
+static bool ice_is_prof_rule(enum ice_sw_tunnel_type type)
+{
+       switch (type) {
+       case ICE_SW_TUN_PROFID_IPV6_ESP:
+       case ICE_SW_TUN_PROFID_IPV6_AH:
+       case ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3:
+               return true;
+       default:
+               break;
+       }
+
+       return false;
+}
+
 /**
  * ice_add_adv_recipe - Add an advanced recipe that is not part of the default
  * @hw: pointer to hardware structure
@@ -5790,7 +5838,7 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
        bool match_tun = false;
        u8 i;
 
-       if (!lkups_cnt)
+       if (!ice_is_prof_rule(rinfo->tun_type) && !lkups_cnt)
                return ICE_ERR_PARAM;
 
        lkup_exts = (struct ice_prot_lkup_ext *)
@@ -5864,6 +5912,26 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
        if (status)
                goto err_unroll;
 
+       /* An empty FV list means to use all the profiles returned in the
+        * profile bitmap
+        */
+       if (LIST_EMPTY(&rm->fv_list)) {
+               u16 j;
+
+               for (j = 0; j < ICE_MAX_NUM_PROFILES; j++)
+                       if (ice_is_bit_set(fv_bitmap, j)) {
+                               struct ice_sw_fv_list_entry *fvl;
+
+                               fvl = (struct ice_sw_fv_list_entry *)
+                                       ice_malloc(hw, sizeof(*fvl));
+                               if (!fvl)
+                                       goto err_unroll;
+                               fvl->fv_ptr = NULL;
+                               fvl->profile_id = j;
+                               LIST_ADD(&fvl->list_entry, &rm->fv_list);
+                       }
+       }
+
        /* get bitmap of all profiles the recipe will be associated with */
        ice_zero_bitmap(profiles, ICE_MAX_NUM_PROFILES);
        LIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry,
@@ -6453,6 +6521,7 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
        struct ice_switch_info *sw;
        enum ice_status status;
        const u8 *pkt = NULL;
+       bool prof_rule;
        u16 word_cnt;
        u32 act = 0;
        u8 q_rgn;
@@ -6463,7 +6532,8 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
                ice_init_prof_result_bm(hw);
        }
 
-       if (!lkups_cnt)
+       prof_rule = ice_is_prof_rule(rinfo->tun_type);
+       if (!prof_rule && !lkups_cnt)
                return ICE_ERR_PARAM;
 
        /* get # of words we need to match */
@@ -6476,8 +6546,14 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
                        if (ptr[j] != 0)
                                word_cnt++;
        }
-       if (!word_cnt || word_cnt > ICE_MAX_CHAIN_WORDS)
-               return ICE_ERR_PARAM;
+
+       if (prof_rule) {
+               if (word_cnt > ICE_MAX_CHAIN_WORDS)
+                       return ICE_ERR_PARAM;
+       } else {
+               if (!word_cnt || word_cnt > ICE_MAX_CHAIN_WORDS)
+                       return ICE_ERR_PARAM;
+       }
 
        /* make sure that we can locate a dummy packet */
        ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type, &pkt, &pkt_len,
@@ -6608,7 +6684,7 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
        adv_fltr->lkups = (struct ice_adv_lkup_elem *)
                ice_memdup(hw, lkups, lkups_cnt * sizeof(*lkups),
                           ICE_NONDMA_TO_NONDMA);
-       if (!adv_fltr->lkups) {
+       if (!adv_fltr->lkups && !prof_rule) {
                status = ICE_ERR_NO_MEMORY;
                goto err_ice_add_adv_rule;
        }
index c01fa8a..30f3746 100644 (file)
 #define ICE_FLTR_TX BIT(1)
 #define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX)
 
+/* Switch Profile IDs for Profile related switch rules */
+#define ICE_PROFID_IPV6_ESP            72
+#define ICE_PROFID_IPV6_AH             74
+#define ICE_PROFID_MAC_IPV6_L2TPV3     78
+
 /* Worst case buffer length for ice_aqc_opc_get_res_alloc */
 #define ICE_MAX_RES_TYPES 0x80
 #define ICE_AQ_GET_RES_ALLOC_BUF_LEN \