diff mbox series

[net] ice: fix adding different tunnels

Message ID 20211116093606.10635-1-michal.swiatkowski@intel.com
State Superseded
Headers show
Series [net] ice: fix adding different tunnels | expand

Commit Message

Michal Swiatkowski Nov. 16, 2021, 9:36 a.m. UTC
From: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>

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
creatig 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>
---
 .../net/ethernet/intel/ice/ice_ethtool_fdir.c   |  4 ++--
 drivers/net/ethernet/intel/ice/ice_fdir.c       |  2 +-
 drivers/net/ethernet/intel/ice/ice_flex_pipe.c  |  6 ++++--
 drivers/net/ethernet/intel/ice/ice_flex_pipe.h  |  3 ++-
 drivers/net/ethernet/intel/ice/ice_switch.c     | 17 ++++++++++++-----
 drivers/net/ethernet/intel/ice/ice_tc_lib.c     |  3 ++-
 6 files changed, 23 insertions(+), 12 deletions(-)

Comments

Michal Swiatkowski Nov. 17, 2021, 5:33 a.m. UTC | #1
On Tue, Nov 16, 2021 at 10:36:06AM +0100, Michal Swiatkowski wrote:
> From: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> 
> 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
> creatig 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>
> ---
>  .../net/ethernet/intel/ice/ice_ethtool_fdir.c   |  4 ++--
>  drivers/net/ethernet/intel/ice/ice_fdir.c       |  2 +-
>  drivers/net/ethernet/intel/ice/ice_flex_pipe.c  |  6 ++++--
>  drivers/net/ethernet/intel/ice/ice_flex_pipe.h  |  3 ++-
>  drivers/net/ethernet/intel/ice/ice_switch.c     | 17 ++++++++++++-----
>  drivers/net/ethernet/intel/ice/ice_tc_lib.c     |  3 ++-
>  6 files changed, 23 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
> index 68ac0be68107..bbc64d6ce4cd 100644
> --- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
> +++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
> @@ -1258,7 +1258,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)
> @@ -1642,7 +1642,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");
> diff --git a/drivers/net/ethernet/intel/ice/ice_fdir.c b/drivers/net/ethernet/intel/ice/ice_fdir.c
> index 9970ac3884f6..bbef6f4366de 100644
> --- a/drivers/net/ethernet/intel/ice/ice_fdir.c
> +++ b/drivers/net/ethernet/intel/ice/ice_fdir.c
> @@ -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 -ENOENT;
>  		if (!ice_fdir_pkt[idx].tun_pkt)
>  			return -EINVAL;
> diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c
> index b12da3cda78b..d98d7e00d542 100644
> --- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c
> +++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c
> @@ -2042,7 +2042,8 @@ static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld)
>   * @port: returns open port
>   */
>  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;
> @@ -2050,7 +2051,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;
> diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
> index 1c2be376a537..dd602285c78e 100644
> --- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
> +++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
> @@ -90,7 +90,8 @@ int
>  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,
> diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
> index c1dbac5f8d6b..8948580bdab0 100644
> --- a/drivers/net/ethernet/intel/ice/ice_switch.c
> +++ b/drivers/net/ethernet/intel/ice/ice_switch.c
> @@ -3795,7 +3795,9 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
>   *
>   * 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;
> @@ -3856,8 +3858,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 */
>  		}
>  	}
> @@ -4647,11 +4650,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)
> @@ -4954,8 +4958,11 @@ 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 -EIO;
> +		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 -EIO;
>  		break;
>  
> @@ -5551,7 +5558,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 -EINVAL;
> diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
> index f243dacda8a0..e8feb41e6dbe 100644
> --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c
> +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
> @@ -800,7 +800,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);
> -- 
> 2.31.1
> 

Please ignore it, I sent it from wrong mail, sorry.

> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
index 68ac0be68107..bbc64d6ce4cd 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
@@ -1258,7 +1258,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)
@@ -1642,7 +1642,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");
diff --git a/drivers/net/ethernet/intel/ice/ice_fdir.c b/drivers/net/ethernet/intel/ice/ice_fdir.c
index 9970ac3884f6..bbef6f4366de 100644
--- a/drivers/net/ethernet/intel/ice/ice_fdir.c
+++ b/drivers/net/ethernet/intel/ice/ice_fdir.c
@@ -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 -ENOENT;
 		if (!ice_fdir_pkt[idx].tun_pkt)
 			return -EINVAL;
diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c
index b12da3cda78b..d98d7e00d542 100644
--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c
+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c
@@ -2042,7 +2042,8 @@  static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld)
  * @port: returns open port
  */
 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;
@@ -2050,7 +2051,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;
diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
index 1c2be376a537..dd602285c78e 100644
--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h
@@ -90,7 +90,8 @@  int
 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,
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index c1dbac5f8d6b..8948580bdab0 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -3795,7 +3795,9 @@  static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
  *
  * 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;
@@ -3856,8 +3858,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 */
 		}
 	}
@@ -4647,11 +4650,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)
@@ -4954,8 +4958,11 @@  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 -EIO;
+		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 -EIO;
 		break;
 
@@ -5551,7 +5558,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 -EINVAL;
diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
index f243dacda8a0..e8feb41e6dbe 100644
--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
@@ -800,7 +800,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);