]> git.dujemihanovic.xyz Git - linux.git/commitdiff
ice: fix adding different tunnels
authorMichal Swiatkowski <michal.swiatkowski@linux.intel.com>
Mon, 22 Nov 2021 15:39:25 +0000 (16:39 +0100)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Tue, 7 Dec 2021 21:21:01 +0000 (13:21 -0800)
Adding filters with the same values inside for VXLAN and Geneve causes HW
error, because it looks exactly the same. To choose between different
type of tunnels new recipe is needed. Add storing tunnel types in
creating recipes function and start checking it in finding function.

Change getting open tunnels function to return port on correct tunnel
type. This is needed to copy correct port to dummy packet.

Block user from adding enc_dst_port via tc flower, because VXLAN and
Geneve filters can be created only with destination port which was
previously opened.

Fixes: 8b032a55c1bd5 ("ice: low level support for tunnels")
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Tested-by: Sandeep Penigalapati <sandeep.penigalapati@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
drivers/net/ethernet/intel/ice/ice_fdir.c
drivers/net/ethernet/intel/ice/ice_flex_pipe.c
drivers/net/ethernet/intel/ice/ice_flex_pipe.h
drivers/net/ethernet/intel/ice/ice_switch.c
drivers/net/ethernet/intel/ice/ice_tc_lib.c

index 38960bcc384c03f94439977feefb27cdb96aff7a..b6e7f47c8c78fd68ddf7c4f863a8383d1e41e6ca 100644 (file)
@@ -1268,7 +1268,7 @@ ice_fdir_write_all_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input,
                bool is_tun = tun == ICE_FD_HW_SEG_TUN;
                int err;
 
-               if (is_tun && !ice_get_open_tunnel_port(&pf->hw, &port_num))
+               if (is_tun && !ice_get_open_tunnel_port(&pf->hw, &port_num, TNL_ALL))
                        continue;
                err = ice_fdir_write_fltr(pf, input, add, is_tun);
                if (err)
@@ -1652,7 +1652,7 @@ int ice_add_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)
        }
 
        /* return error if not an update and no available filters */
-       fltrs_needed = ice_get_open_tunnel_port(hw, &tunnel_port) ? 2 : 1;
+       fltrs_needed = ice_get_open_tunnel_port(hw, &tunnel_port, TNL_ALL) ? 2 : 1;
        if (!ice_fdir_find_fltr_by_idx(hw, fsp->location) &&
            ice_fdir_num_avail_fltr(hw, pf->vsi[vsi->idx]) < fltrs_needed) {
                dev_err(dev, "Failed to add filter.  The maximum number of flow director filters has been reached.\n");
index cbd8424631e32a0a854bd468da9a70b41fb88ea6..4dca009bdd50f2fb7771ab5ac25d0b7863119d01 100644 (file)
@@ -924,7 +924,7 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
                memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len);
                loc = pkt;
        } else {
-               if (!ice_get_open_tunnel_port(hw, &tnl_port))
+               if (!ice_get_open_tunnel_port(hw, &tnl_port, TNL_ALL))
                        return ICE_ERR_DOES_NOT_EXIST;
                if (!ice_fdir_pkt[idx].tun_pkt)
                        return ICE_ERR_PARAM;
index 23cfcceb1536dcac3cebf75cad36e58dd622c60f..6ad1c255972439a0dc60e256428f062e5138bf13 100644 (file)
@@ -1899,9 +1899,11 @@ static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld)
  * ice_get_open_tunnel_port - retrieve an open tunnel port
  * @hw: pointer to the HW structure
  * @port: returns open port
+ * @type: type of tunnel, can be TNL_LAST if it doesn't matter
  */
 bool
-ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port)
+ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port,
+                        enum ice_tunnel_type type)
 {
        bool res = false;
        u16 i;
@@ -1909,7 +1911,8 @@ ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port)
        mutex_lock(&hw->tnl_lock);
 
        for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
-               if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].port) {
+               if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].port &&
+                   (type == TNL_LAST || type == hw->tnl.tbl[i].type)) {
                        *port = hw->tnl.tbl[i].port;
                        res = true;
                        break;
index 344c2637facda3c821f1fed4f81ae13214334c92..a2863f38fd1fd5f6ef32d8375a5acbb31e4c2be9 100644 (file)
@@ -33,7 +33,8 @@ enum ice_status
 ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt,
                   unsigned long *bm, struct list_head *fv_list);
 bool
-ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port);
+ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port,
+                        enum ice_tunnel_type type);
 int ice_udp_tunnel_set_port(struct net_device *netdev, unsigned int table,
                            unsigned int idx, struct udp_tunnel_info *ti);
 int ice_udp_tunnel_unset_port(struct net_device *netdev, unsigned int table,
index 793f4a9fc2cdb03fc233c4800eb52f546bdb89ac..183d9303389064dcd819eb0ed1f9173d333e6794 100644 (file)
@@ -3796,10 +3796,13 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
  * ice_find_recp - find a recipe
  * @hw: pointer to the hardware structure
  * @lkup_exts: extension sequence to match
+ * @tun_type: type of recipe tunnel
  *
  * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found.
  */
-static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts)
+static u16
+ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts,
+             enum ice_sw_tunnel_type tun_type)
 {
        bool refresh_required = true;
        struct ice_sw_recipe *recp;
@@ -3860,8 +3863,9 @@ static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts)
                        }
                        /* If for "i"th recipe the found was never set to false
                         * then it means we found our match
+                        * Also tun type of recipe needs to be checked
                         */
-                       if (found)
+                       if (found && recp[i].tun_type == tun_type)
                                return i; /* Return the recipe ID */
                }
        }
@@ -4651,11 +4655,12 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
        }
 
        /* Look for a recipe which matches our requested fv / mask list */
-       *rid = ice_find_recp(hw, lkup_exts);
+       *rid = ice_find_recp(hw, lkup_exts, rinfo->tun_type);
        if (*rid < ICE_MAX_NUM_RECIPES)
                /* Success if found a recipe that match the existing criteria */
                goto err_unroll;
 
+       rm->tun_type = rinfo->tun_type;
        /* Recipe we need does not exist, add a recipe */
        status = ice_add_sw_recipe(hw, rm, profiles);
        if (status)
@@ -4958,11 +4963,13 @@ ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
 
        switch (tun_type) {
        case ICE_SW_TUN_VXLAN:
+               if (!ice_get_open_tunnel_port(hw, &open_port, TNL_VXLAN))
+                       return ICE_ERR_CFG;
+               break;
        case ICE_SW_TUN_GENEVE:
-               if (!ice_get_open_tunnel_port(hw, &open_port))
+               if (!ice_get_open_tunnel_port(hw, &open_port, TNL_GENEVE))
                        return ICE_ERR_CFG;
                break;
-
        default:
                /* Nothing needs to be done for this tunnel type */
                return 0;
@@ -5555,7 +5562,7 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
        if (status)
                return status;
 
-       rid = ice_find_recp(hw, &lkup_exts);
+       rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type);
        /* If did not find a recipe that match the existing criteria */
        if (rid == ICE_MAX_NUM_RECIPES)
                return ICE_ERR_PARAM;
index 384439a267ad2ca93e53bfb54c32a1902941dcc0..25cca5c4ae575bbc237ddaa63c434231ce074d90 100644 (file)
@@ -795,7 +795,8 @@ ice_parse_tunnel_attr(struct net_device *dev, struct flow_rule *rule,
                headers->l3_mask.ttl = match.mask->ttl;
        }
 
-       if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
+       if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS) &&
+           fltr->tunnel_type != TNL_VXLAN && fltr->tunnel_type != TNL_GENEVE) {
                struct flow_match_ports match;
 
                flow_rule_match_enc_ports(rule, &match);