diff mbox series

[iwl-next,v2,7/7] ice: Add tracepoint for adding and removing switch rules

Message ID 20240624144530.690545-8-marcin.szycik@linux.intel.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series Switch API optimizations | expand

Checks

Context Check Description
netdev/series_format warning Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 842 this patch: 842
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 5 maintainers not CCed: jesse.brandeburg@intel.com pabeni@redhat.com anthony.l.nguyen@intel.com kuba@kernel.org edumazet@google.com
netdev/build_clang success Errors and warnings before: 849 this patch: 849
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 851 this patch: 851
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 88 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 340 this patch: 340
netdev/source_inline success Was 0 now: 0

Commit Message

Marcin Szycik June 24, 2024, 2:45 p.m. UTC
Track the number of rules and recipes added to switch. Add a tracepoint to
ice_aq_sw_rules(), which shows both rule and recipe count. This information
can be helpful when designing a set of rules to program to the hardware, as
it shows where the practical limit is. Actual limits are known (64 recipes,
32k rules), but it's hard to translate these values to how many rules the
*user* can actually create, because of extra metadata being implicitly
added, and recipe/rule chaining. Chaining combines several recipes/rules to
create a larger recipe/rule, so one large rule added by the user might
actually consume multiple rules from hardware perspective.

Rule counter is simply incremented/decremented in ice_aq_sw_rules(), since
all rules are added or removed via it.

Counting recipes is harder, as recipes can't be removed (only overwritten).
Recipes added via ice_aq_add_recipe() could end up being unused, when
there is an error in later stages of rule creation. Instead, track the
allocation and freeing of recipes, which should reflect the actual usage of
recipes (if something fails after recipe(s) were created, caller should
free them). Also, a number of recipes are loaded from NVM by default -
initialize the recipe counter with the number of these recipes on switch
initialization.

Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>
---
 drivers/net/ethernet/intel/ice/ice_common.c |  3 +++
 drivers/net/ethernet/intel/ice/ice_switch.c | 22 +++++++++++++++++++--
 drivers/net/ethernet/intel/ice/ice_trace.h  | 18 +++++++++++++++++
 drivers/net/ethernet/intel/ice/ice_type.h   |  2 ++
 4 files changed, 43 insertions(+), 2 deletions(-)

Comments

Przemek Kitszel June 25, 2024, 7:51 a.m. UTC | #1
On 6/24/24 16:45, Marcin Szycik wrote:
> Track the number of rules and recipes added to switch. Add a tracepoint to
> ice_aq_sw_rules(), which shows both rule and recipe count. This information
> can be helpful when designing a set of rules to program to the hardware, as
> it shows where the practical limit is. Actual limits are known (64 recipes,
> 32k rules), but it's hard to translate these values to how many rules the
> *user* can actually create, because of extra metadata being implicitly
> added, and recipe/rule chaining. Chaining combines several recipes/rules to
> create a larger recipe/rule, so one large rule added by the user might
> actually consume multiple rules from hardware perspective.
> 
> Rule counter is simply incremented/decremented in ice_aq_sw_rules(), since
> all rules are added or removed via it.
> 
> Counting recipes is harder, as recipes can't be removed (only overwritten).
> Recipes added via ice_aq_add_recipe() could end up being unused, when
> there is an error in later stages of rule creation. Instead, track the
> allocation and freeing of recipes, which should reflect the actual usage of
> recipes (if something fails after recipe(s) were created, caller should
> free them). Also, a number of recipes are loaded from NVM by default -
> initialize the recipe counter with the number of these recipes on switch
> initialization.
> 
> Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>
> ---
>   drivers/net/ethernet/intel/ice/ice_common.c |  3 +++
>   drivers/net/ethernet/intel/ice/ice_switch.c | 22 +++++++++++++++++++--
>   drivers/net/ethernet/intel/ice/ice_trace.h  | 18 +++++++++++++++++
>   drivers/net/ethernet/intel/ice/ice_type.h   |  2 ++
>   4 files changed, 43 insertions(+), 2 deletions(-)
> 

Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Paul Menzel June 25, 2024, 8:31 a.m. UTC | #2
Dear Marcin,


Thank you for your patch.

Am 24.06.24 um 16:45 schrieb Marcin Szycik:
> Track the number of rules and recipes added to switch. Add a tracepoint to
> ice_aq_sw_rules(), which shows both rule and recipe count. This information
> can be helpful when designing a set of rules to program to the hardware, as
> it shows where the practical limit is. Actual limits are known (64 recipes,
> 32k rules), but it's hard to translate these values to how many rules the
> *user* can actually create, because of extra metadata being implicitly
> added, and recipe/rule chaining. Chaining combines several recipes/rules to
> create a larger recipe/rule, so one large rule added by the user might
> actually consume multiple rules from hardware perspective.
> 
> Rule counter is simply incremented/decremented in ice_aq_sw_rules(), since
> all rules are added or removed via it.
> 
> Counting recipes is harder, as recipes can't be removed (only overwritten).
> Recipes added via ice_aq_add_recipe() could end up being unused, when
> there is an error in later stages of rule creation. Instead, track the
> allocation and freeing of recipes, which should reflect the actual usage of
> recipes (if something fails after recipe(s) were created, caller should
> free them). Also, a number of recipes are loaded from NVM by default -
> initialize the recipe counter with the number of these recipes on switch
> initialization.

Can you please add an example how to use the tracepoint?

> Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>
> ---
>   drivers/net/ethernet/intel/ice/ice_common.c |  3 +++
>   drivers/net/ethernet/intel/ice/ice_switch.c | 22 +++++++++++++++++++--
>   drivers/net/ethernet/intel/ice/ice_trace.h  | 18 +++++++++++++++++
>   drivers/net/ethernet/intel/ice/ice_type.h   |  2 ++
>   4 files changed, 43 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
> index 6abd1b3796ab..009716a12a26 100644
> --- a/drivers/net/ethernet/intel/ice/ice_common.c
> +++ b/drivers/net/ethernet/intel/ice/ice_common.c
> @@ -934,6 +934,9 @@ static int ice_init_fltr_mgmt_struct(struct ice_hw *hw)
>   	INIT_LIST_HEAD(&sw->vsi_list_map_head);
>   	sw->prof_res_bm_init = 0;
>   
> +	/* Initialize recipe count with default recipes read from NVM */
> +	sw->recp_cnt = ICE_SW_LKUP_LAST;
> +
>   	status = ice_init_def_sw_recp(hw);
>   	if (status) {
>   		devm_kfree(ice_hw_to_dev(hw), hw->switch_info);
> diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
> index 27828cdfe085..3caafcdc301f 100644
> --- a/drivers/net/ethernet/intel/ice/ice_switch.c
> +++ b/drivers/net/ethernet/intel/ice/ice_switch.c
> @@ -3,6 +3,7 @@
>   
>   #include "ice_lib.h"
>   #include "ice_switch.h"
> +#include "ice_trace.h"
>   
>   #define ICE_ETH_DA_OFFSET		0
>   #define ICE_ETH_ETHTYPE_OFFSET		12
> @@ -1961,6 +1962,15 @@ ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
>   	    hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
>   		status = -ENOENT;
>   
> +	if (!status) {
> +		if (opc == ice_aqc_opc_add_sw_rules)
> +			hw->switch_info->rule_cnt += num_rules;
> +		else if (opc == ice_aqc_opc_remove_sw_rules)
> +			hw->switch_info->rule_cnt -= num_rules;
> +	}
> +
> +	trace_ice_aq_sw_rules(hw->switch_info);
> +
>   	return status;
>   }
>   
> @@ -2181,8 +2191,10 @@ int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
>   	sw_buf->res_type = cpu_to_le16(res_type);
>   	status = ice_aq_alloc_free_res(hw, sw_buf, buf_len,
>   				       ice_aqc_opc_alloc_res);
> -	if (!status)
> +	if (!status) {
>   		*rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp);
> +		hw->switch_info->recp_cnt++;
> +	}
>   
>   	return status;
>   }
> @@ -2196,7 +2208,13 @@ int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
>    */
>   static int ice_free_recipe_res(struct ice_hw *hw, u16 rid)
>   {
> -	return ice_free_hw_res(hw, ICE_AQC_RES_TYPE_RECIPE, 1, &rid);
> +	int status;
> +
> +	status = ice_free_hw_res(hw, ICE_AQC_RES_TYPE_RECIPE, 1, &rid);
> +	if (!status)
> +		hw->switch_info->recp_cnt--;
> +
> +	return status;
>   }
>   
>   /**
> diff --git a/drivers/net/ethernet/intel/ice/ice_trace.h b/drivers/net/ethernet/intel/ice/ice_trace.h
> index 244cddd2a9ea..07aab6e130cd 100644
> --- a/drivers/net/ethernet/intel/ice/ice_trace.h
> +++ b/drivers/net/ethernet/intel/ice/ice_trace.h
> @@ -330,6 +330,24 @@ DEFINE_EVENT(ice_esw_br_port_template,
>   	     TP_ARGS(port)
>   );
>   
> +DECLARE_EVENT_CLASS(ice_switch_stats_template,
> +		    TP_PROTO(struct ice_switch_info *sw_info),
> +		    TP_ARGS(sw_info),
> +		    TP_STRUCT__entry(__field(u16, rule_cnt)
> +				     __field(u8, recp_cnt)),
> +		    TP_fast_assign(__entry->rule_cnt = sw_info->rule_cnt;
> +				   __entry->recp_cnt = sw_info->recp_cnt;),
> +		    TP_printk("rules=%u recipes=%u",
> +			      __entry->rule_cnt,
> +			      __entry->recp_cnt)
> +);
> +
> +DEFINE_EVENT(ice_switch_stats_template,
> +	     ice_aq_sw_rules,
> +	     TP_PROTO(struct ice_switch_info *sw_info),
> +	     TP_ARGS(sw_info)
> +);
> +
>   /* End tracepoints */
>   
>   #endif /* _ICE_TRACE_H_ */
> diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
> index c330a436d11a..b6bc2de53b0a 100644
> --- a/drivers/net/ethernet/intel/ice/ice_type.h
> +++ b/drivers/net/ethernet/intel/ice/ice_type.h
> @@ -764,6 +764,8 @@ struct ice_switch_info {
>   	struct ice_sw_recipe *recp_list;
>   	u16 prof_res_bm_init;
>   	u16 max_used_prof_index;
> +	u16 rule_cnt;
> +	u8 recp_cnt;
>   
>   	DECLARE_BITMAP(prof_res_bm[ICE_MAX_NUM_PROFILES], ICE_MAX_FV_WORDS);
>   };


Kind regards,

Paul
Marcin Szycik June 25, 2024, 3:16 p.m. UTC | #3
On 25.06.2024 10:31, Paul Menzel wrote:
> Dear Marcin,
> 
> 
> Thank you for your patch.
> 
> Am 24.06.24 um 16:45 schrieb Marcin Szycik:
>> Track the number of rules and recipes added to switch. Add a tracepoint to
>> ice_aq_sw_rules(), which shows both rule and recipe count. This information
>> can be helpful when designing a set of rules to program to the hardware, as
>> it shows where the practical limit is. Actual limits are known (64 recipes,
>> 32k rules), but it's hard to translate these values to how many rules the
>> *user* can actually create, because of extra metadata being implicitly
>> added, and recipe/rule chaining. Chaining combines several recipes/rules to
>> create a larger recipe/rule, so one large rule added by the user might
>> actually consume multiple rules from hardware perspective.
>>
>> Rule counter is simply incremented/decremented in ice_aq_sw_rules(), since
>> all rules are added or removed via it.
>>
>> Counting recipes is harder, as recipes can't be removed (only overwritten).
>> Recipes added via ice_aq_add_recipe() could end up being unused, when
>> there is an error in later stages of rule creation. Instead, track the
>> allocation and freeing of recipes, which should reflect the actual usage of
>> recipes (if something fails after recipe(s) were created, caller should
>> free them). Also, a number of recipes are loaded from NVM by default -
>> initialize the recipe counter with the number of these recipes on switch
>> initialization.
> 
> Can you please add an example how to use the tracepoint?

Sure, will add to next version.

Example configuration:
  cd /sys/kernel/tracing
  echo function > current_tracer
  echo ice_aq_sw_rules > set_ftrace_filter
  echo ice_aq_sw_rules > set_event
  echo 1 > tracing_on
  cat trace

Sample output:
  tc-4097    [069] ...1.   787.595536: ice_aq_sw_rules <-ice_rem_adv_rule
  tc-4097    [069] .....   787.595705: ice_aq_sw_rules: rules=9 recipes=15
  tc-4098    [057] ...1.   787.652033: ice_aq_sw_rules <-ice_add_adv_rule
  tc-4098    [057] .....   787.652201: ice_aq_sw_rules: rules=10 recipes=16

Thanks,
Marcin

>> Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
>> Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>
>> ---
>>   drivers/net/ethernet/intel/ice/ice_common.c |  3 +++
>>   drivers/net/ethernet/intel/ice/ice_switch.c | 22 +++++++++++++++++++--
>>   drivers/net/ethernet/intel/ice/ice_trace.h  | 18 +++++++++++++++++
>>   drivers/net/ethernet/intel/ice/ice_type.h   |  2 ++
>>   4 files changed, 43 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
>> index 6abd1b3796ab..009716a12a26 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_common.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_common.c
>> @@ -934,6 +934,9 @@ static int ice_init_fltr_mgmt_struct(struct ice_hw *hw)
>>       INIT_LIST_HEAD(&sw->vsi_list_map_head);
>>       sw->prof_res_bm_init = 0;
>>   +    /* Initialize recipe count with default recipes read from NVM */
>> +    sw->recp_cnt = ICE_SW_LKUP_LAST;
>> +
>>       status = ice_init_def_sw_recp(hw);
>>       if (status) {
>>           devm_kfree(ice_hw_to_dev(hw), hw->switch_info);
>> diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
>> index 27828cdfe085..3caafcdc301f 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_switch.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_switch.c
>> @@ -3,6 +3,7 @@
>>     #include "ice_lib.h"
>>   #include "ice_switch.h"
>> +#include "ice_trace.h"
>>     #define ICE_ETH_DA_OFFSET        0
>>   #define ICE_ETH_ETHTYPE_OFFSET        12
>> @@ -1961,6 +1962,15 @@ ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
>>           hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
>>           status = -ENOENT;
>>   +    if (!status) {
>> +        if (opc == ice_aqc_opc_add_sw_rules)
>> +            hw->switch_info->rule_cnt += num_rules;
>> +        else if (opc == ice_aqc_opc_remove_sw_rules)
>> +            hw->switch_info->rule_cnt -= num_rules;
>> +    }
>> +
>> +    trace_ice_aq_sw_rules(hw->switch_info);
>> +
>>       return status;
>>   }
>>   @@ -2181,8 +2191,10 @@ int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
>>       sw_buf->res_type = cpu_to_le16(res_type);
>>       status = ice_aq_alloc_free_res(hw, sw_buf, buf_len,
>>                          ice_aqc_opc_alloc_res);
>> -    if (!status)
>> +    if (!status) {
>>           *rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp);
>> +        hw->switch_info->recp_cnt++;
>> +    }
>>         return status;
>>   }
>> @@ -2196,7 +2208,13 @@ int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
>>    */
>>   static int ice_free_recipe_res(struct ice_hw *hw, u16 rid)
>>   {
>> -    return ice_free_hw_res(hw, ICE_AQC_RES_TYPE_RECIPE, 1, &rid);
>> +    int status;
>> +
>> +    status = ice_free_hw_res(hw, ICE_AQC_RES_TYPE_RECIPE, 1, &rid);
>> +    if (!status)
>> +        hw->switch_info->recp_cnt--;
>> +
>> +    return status;
>>   }
>>     /**
>> diff --git a/drivers/net/ethernet/intel/ice/ice_trace.h b/drivers/net/ethernet/intel/ice/ice_trace.h
>> index 244cddd2a9ea..07aab6e130cd 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_trace.h
>> +++ b/drivers/net/ethernet/intel/ice/ice_trace.h
>> @@ -330,6 +330,24 @@ DEFINE_EVENT(ice_esw_br_port_template,
>>            TP_ARGS(port)
>>   );
>>   +DECLARE_EVENT_CLASS(ice_switch_stats_template,
>> +            TP_PROTO(struct ice_switch_info *sw_info),
>> +            TP_ARGS(sw_info),
>> +            TP_STRUCT__entry(__field(u16, rule_cnt)
>> +                     __field(u8, recp_cnt)),
>> +            TP_fast_assign(__entry->rule_cnt = sw_info->rule_cnt;
>> +                   __entry->recp_cnt = sw_info->recp_cnt;),
>> +            TP_printk("rules=%u recipes=%u",
>> +                  __entry->rule_cnt,
>> +                  __entry->recp_cnt)
>> +);
>> +
>> +DEFINE_EVENT(ice_switch_stats_template,
>> +         ice_aq_sw_rules,
>> +         TP_PROTO(struct ice_switch_info *sw_info),
>> +         TP_ARGS(sw_info)
>> +);
>> +
>>   /* End tracepoints */
>>     #endif /* _ICE_TRACE_H_ */
>> diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
>> index c330a436d11a..b6bc2de53b0a 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_type.h
>> +++ b/drivers/net/ethernet/intel/ice/ice_type.h
>> @@ -764,6 +764,8 @@ struct ice_switch_info {
>>       struct ice_sw_recipe *recp_list;
>>       u16 prof_res_bm_init;
>>       u16 max_used_prof_index;
>> +    u16 rule_cnt;
>> +    u8 recp_cnt;
>>         DECLARE_BITMAP(prof_res_bm[ICE_MAX_NUM_PROFILES], ICE_MAX_FV_WORDS);
>>   };
> 
> 
> Kind regards,
> 
> Paul
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index 6abd1b3796ab..009716a12a26 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -934,6 +934,9 @@  static int ice_init_fltr_mgmt_struct(struct ice_hw *hw)
 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
 	sw->prof_res_bm_init = 0;
 
+	/* Initialize recipe count with default recipes read from NVM */
+	sw->recp_cnt = ICE_SW_LKUP_LAST;
+
 	status = ice_init_def_sw_recp(hw);
 	if (status) {
 		devm_kfree(ice_hw_to_dev(hw), hw->switch_info);
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index 27828cdfe085..3caafcdc301f 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -3,6 +3,7 @@ 
 
 #include "ice_lib.h"
 #include "ice_switch.h"
+#include "ice_trace.h"
 
 #define ICE_ETH_DA_OFFSET		0
 #define ICE_ETH_ETHTYPE_OFFSET		12
@@ -1961,6 +1962,15 @@  ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
 	    hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
 		status = -ENOENT;
 
+	if (!status) {
+		if (opc == ice_aqc_opc_add_sw_rules)
+			hw->switch_info->rule_cnt += num_rules;
+		else if (opc == ice_aqc_opc_remove_sw_rules)
+			hw->switch_info->rule_cnt -= num_rules;
+	}
+
+	trace_ice_aq_sw_rules(hw->switch_info);
+
 	return status;
 }
 
@@ -2181,8 +2191,10 @@  int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
 	sw_buf->res_type = cpu_to_le16(res_type);
 	status = ice_aq_alloc_free_res(hw, sw_buf, buf_len,
 				       ice_aqc_opc_alloc_res);
-	if (!status)
+	if (!status) {
 		*rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp);
+		hw->switch_info->recp_cnt++;
+	}
 
 	return status;
 }
@@ -2196,7 +2208,13 @@  int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
  */
 static int ice_free_recipe_res(struct ice_hw *hw, u16 rid)
 {
-	return ice_free_hw_res(hw, ICE_AQC_RES_TYPE_RECIPE, 1, &rid);
+	int status;
+
+	status = ice_free_hw_res(hw, ICE_AQC_RES_TYPE_RECIPE, 1, &rid);
+	if (!status)
+		hw->switch_info->recp_cnt--;
+
+	return status;
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/ice/ice_trace.h b/drivers/net/ethernet/intel/ice/ice_trace.h
index 244cddd2a9ea..07aab6e130cd 100644
--- a/drivers/net/ethernet/intel/ice/ice_trace.h
+++ b/drivers/net/ethernet/intel/ice/ice_trace.h
@@ -330,6 +330,24 @@  DEFINE_EVENT(ice_esw_br_port_template,
 	     TP_ARGS(port)
 );
 
+DECLARE_EVENT_CLASS(ice_switch_stats_template,
+		    TP_PROTO(struct ice_switch_info *sw_info),
+		    TP_ARGS(sw_info),
+		    TP_STRUCT__entry(__field(u16, rule_cnt)
+				     __field(u8, recp_cnt)),
+		    TP_fast_assign(__entry->rule_cnt = sw_info->rule_cnt;
+				   __entry->recp_cnt = sw_info->recp_cnt;),
+		    TP_printk("rules=%u recipes=%u",
+			      __entry->rule_cnt,
+			      __entry->recp_cnt)
+);
+
+DEFINE_EVENT(ice_switch_stats_template,
+	     ice_aq_sw_rules,
+	     TP_PROTO(struct ice_switch_info *sw_info),
+	     TP_ARGS(sw_info)
+);
+
 /* End tracepoints */
 
 #endif /* _ICE_TRACE_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index c330a436d11a..b6bc2de53b0a 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -764,6 +764,8 @@  struct ice_switch_info {
 	struct ice_sw_recipe *recp_list;
 	u16 prof_res_bm_init;
 	u16 max_used_prof_index;
+	u16 rule_cnt;
+	u8 recp_cnt;
 
 	DECLARE_BITMAP(prof_res_bm[ICE_MAX_NUM_PROFILES], ICE_MAX_FV_WORDS);
 };