1919#include <linux/net_namespace.h>
2020#include <linux/mutex.h>
2121#include <linux/genalloc.h>
22+ #include <linux/xarray.h>
2223#include <net/netevent.h>
2324#include <net/neighbour.h>
2425#include <net/arp.h>
@@ -3111,6 +3112,7 @@ struct mlxsw_sp_nexthop_group_info {
31113112 is_resilient :1 ,
31123113 hw_stats :1 ;
31133114 struct list_head list ; /* member in nh_res_grp_list */
3115+ struct xarray nexthop_counters ;
31143116 struct mlxsw_sp_nexthop nexthops [] __counted_by (count );
31153117};
31163118
@@ -3156,6 +3158,7 @@ struct mlxsw_sp_nexthop_group {
31563158
31573159struct mlxsw_sp_nexthop_counter {
31583160 unsigned int counter_index ;
3161+ refcount_t ref_count ;
31593162};
31603163
31613164static struct mlxsw_sp_nexthop_counter *
@@ -3172,6 +3175,7 @@ mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp *mlxsw_sp)
31723175 if (err )
31733176 goto err_counter_alloc ;
31743177
3178+ refcount_set (& nhct -> ref_count , 1 );
31753179 return nhct ;
31763180
31773181err_counter_alloc :
@@ -3187,6 +3191,56 @@ mlxsw_sp_nexthop_counter_free(struct mlxsw_sp *mlxsw_sp,
31873191 kfree (nhct );
31883192}
31893193
3194+ static struct mlxsw_sp_nexthop_counter *
3195+ mlxsw_sp_nexthop_sh_counter_get (struct mlxsw_sp * mlxsw_sp ,
3196+ struct mlxsw_sp_nexthop * nh )
3197+ {
3198+ struct mlxsw_sp_nexthop_group * nh_grp = nh -> nhgi -> nh_grp ;
3199+ struct mlxsw_sp_nexthop_counter * nhct ;
3200+ void * ptr ;
3201+ int err ;
3202+
3203+ nhct = xa_load (& nh_grp -> nhgi -> nexthop_counters , nh -> id );
3204+ if (nhct ) {
3205+ refcount_inc (& nhct -> ref_count );
3206+ return nhct ;
3207+ }
3208+
3209+ nhct = mlxsw_sp_nexthop_counter_alloc (mlxsw_sp );
3210+ if (IS_ERR (nhct ))
3211+ return nhct ;
3212+
3213+ ptr = xa_store (& nh_grp -> nhgi -> nexthop_counters , nh -> id , nhct ,
3214+ GFP_KERNEL );
3215+ if (IS_ERR (ptr )) {
3216+ err = PTR_ERR (ptr );
3217+ goto err_store ;
3218+ }
3219+
3220+ return nhct ;
3221+
3222+ err_store :
3223+ mlxsw_sp_nexthop_counter_free (mlxsw_sp , nhct );
3224+ return ERR_PTR (err );
3225+ }
3226+
3227+ static void mlxsw_sp_nexthop_sh_counter_put (struct mlxsw_sp * mlxsw_sp ,
3228+ struct mlxsw_sp_nexthop * nh )
3229+ {
3230+ struct mlxsw_sp_nexthop_group * nh_grp = nh -> nhgi -> nh_grp ;
3231+ struct mlxsw_sp_nexthop_counter * nhct ;
3232+
3233+ nhct = xa_load (& nh_grp -> nhgi -> nexthop_counters , nh -> id );
3234+ if (WARN_ON (!nhct ))
3235+ return ;
3236+
3237+ if (!refcount_dec_and_test (& nhct -> ref_count ))
3238+ return ;
3239+
3240+ xa_erase (& nh_grp -> nhgi -> nexthop_counters , nh -> id );
3241+ mlxsw_sp_nexthop_counter_free (mlxsw_sp , nhct );
3242+ }
3243+
31903244int mlxsw_sp_nexthop_counter_enable (struct mlxsw_sp * mlxsw_sp ,
31913245 struct mlxsw_sp_nexthop * nh )
31923246{
@@ -3203,7 +3257,10 @@ int mlxsw_sp_nexthop_counter_enable(struct mlxsw_sp *mlxsw_sp,
32033257 if (!(nh -> nhgi -> hw_stats || dpipe_stats ))
32043258 return 0 ;
32053259
3206- nhct = mlxsw_sp_nexthop_counter_alloc (mlxsw_sp );
3260+ if (nh -> id )
3261+ nhct = mlxsw_sp_nexthop_sh_counter_get (mlxsw_sp , nh );
3262+ else
3263+ nhct = mlxsw_sp_nexthop_counter_alloc (mlxsw_sp );
32073264 if (IS_ERR (nhct ))
32083265 return PTR_ERR (nhct );
32093266
@@ -3216,7 +3273,11 @@ void mlxsw_sp_nexthop_counter_disable(struct mlxsw_sp *mlxsw_sp,
32163273{
32173274 if (!nh -> counter )
32183275 return ;
3219- mlxsw_sp_nexthop_counter_free (mlxsw_sp , nh -> counter );
3276+
3277+ if (nh -> id )
3278+ mlxsw_sp_nexthop_sh_counter_put (mlxsw_sp , nh );
3279+ else
3280+ mlxsw_sp_nexthop_counter_free (mlxsw_sp , nh -> counter );
32203281 nh -> counter = NULL ;
32213282}
32223283
@@ -5145,6 +5206,9 @@ mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
51455206 nhgi -> is_resilient = is_resilient ;
51465207 nhgi -> count = nhs ;
51475208 nhgi -> hw_stats = hw_stats ;
5209+
5210+ xa_init_flags (& nhgi -> nexthop_counters , XA_FLAGS_ALLOC1 );
5211+
51485212 for (i = 0 ; i < nhgi -> count ; i ++ ) {
51495213 struct nh_notifier_single_info * nh_obj ;
51505214 int weight ;
@@ -5227,6 +5291,8 @@ mlxsw_sp_nexthop_obj_group_info_fini(struct mlxsw_sp *mlxsw_sp,
52275291 }
52285292 mlxsw_sp_nexthop_group_refresh (mlxsw_sp , nh_grp );
52295293 WARN_ON_ONCE (nhgi -> adj_index_valid );
5294+ WARN_ON (!xa_empty (& nhgi -> nexthop_counters ));
5295+ xa_destroy (& nhgi -> nexthop_counters );
52305296 kfree (nhgi );
52315297}
52325298
0 commit comments