@@ -3108,7 +3108,8 @@ struct mlxsw_sp_nexthop_group_info {
3108
3108
int sum_norm_weight ;
3109
3109
u8 adj_index_valid :1 ,
3110
3110
gateway :1 , /* routes using the group use a gateway */
3111
- is_resilient :1 ;
3111
+ is_resilient :1 ,
3112
+ hw_stats :1 ;
3112
3113
struct list_head list ; /* member in nh_res_grp_list */
3113
3114
struct mlxsw_sp_nexthop nexthops [] __counted_by (count );
3114
3115
};
@@ -3189,15 +3190,17 @@ mlxsw_sp_nexthop_counter_free(struct mlxsw_sp *mlxsw_sp,
3189
3190
int mlxsw_sp_nexthop_counter_enable (struct mlxsw_sp * mlxsw_sp ,
3190
3191
struct mlxsw_sp_nexthop * nh )
3191
3192
{
3193
+ const char * table_adj = MLXSW_SP_DPIPE_TABLE_NAME_ADJ ;
3192
3194
struct mlxsw_sp_nexthop_counter * nhct ;
3193
3195
struct devlink * devlink ;
3196
+ bool dpipe_stats ;
3194
3197
3195
3198
if (nh -> counter )
3196
3199
return 0 ;
3197
3200
3198
3201
devlink = priv_to_devlink (mlxsw_sp -> core );
3199
- if (! devlink_dpipe_table_counter_enabled (devlink ,
3200
- MLXSW_SP_DPIPE_TABLE_NAME_ADJ ))
3202
+ dpipe_stats = devlink_dpipe_table_counter_enabled (devlink , table_adj );
3203
+ if (!( nh -> nhgi -> hw_stats || dpipe_stats ))
3201
3204
return 0 ;
3202
3205
3203
3206
nhct = mlxsw_sp_nexthop_counter_alloc (mlxsw_sp );
@@ -3217,14 +3220,23 @@ void mlxsw_sp_nexthop_counter_disable(struct mlxsw_sp *mlxsw_sp,
3217
3220
nh -> counter = NULL ;
3218
3221
}
3219
3222
3223
+ static int mlxsw_sp_nexthop_counter_update (struct mlxsw_sp * mlxsw_sp ,
3224
+ struct mlxsw_sp_nexthop * nh )
3225
+ {
3226
+ if (nh -> nhgi -> hw_stats )
3227
+ return mlxsw_sp_nexthop_counter_enable (mlxsw_sp , nh );
3228
+ mlxsw_sp_nexthop_counter_disable (mlxsw_sp , nh );
3229
+ return 0 ;
3230
+ }
3231
+
3220
3232
int mlxsw_sp_nexthop_counter_get (struct mlxsw_sp * mlxsw_sp ,
3221
3233
struct mlxsw_sp_nexthop * nh , u64 * p_counter )
3222
3234
{
3223
3235
if (!nh -> counter )
3224
3236
return - EINVAL ;
3225
3237
3226
3238
return mlxsw_sp_flow_counter_get (mlxsw_sp , nh -> counter -> counter_index ,
3227
- false , p_counter , NULL );
3239
+ true , p_counter , NULL );
3228
3240
}
3229
3241
3230
3242
struct mlxsw_sp_nexthop * mlxsw_sp_nexthop_next (struct mlxsw_sp_router * router ,
@@ -3786,13 +3798,18 @@ mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp,
3786
3798
nh = & nhgi -> nexthops [i ];
3787
3799
3788
3800
if (!nh -> should_offload ) {
3801
+ mlxsw_sp_nexthop_counter_disable (mlxsw_sp , nh );
3789
3802
nh -> offloaded = 0 ;
3790
3803
continue ;
3791
3804
}
3792
3805
3793
3806
if (nh -> update || reallocate ) {
3794
3807
int err = 0 ;
3795
3808
3809
+ err = mlxsw_sp_nexthop_counter_update (mlxsw_sp , nh );
3810
+ if (err )
3811
+ return err ;
3812
+
3796
3813
err = mlxsw_sp_nexthop_update (mlxsw_sp , adj_index , nh ,
3797
3814
true, ratr_pl );
3798
3815
if (err )
@@ -5052,7 +5069,6 @@ mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
5052
5069
break ;
5053
5070
}
5054
5071
5055
- mlxsw_sp_nexthop_counter_enable (mlxsw_sp , nh );
5056
5072
list_add_tail (& nh -> router_list_node , & mlxsw_sp -> router -> nexthop_list );
5057
5073
nh -> ifindex = dev -> ifindex ;
5058
5074
nh -> id = nh_obj -> id ;
@@ -5077,7 +5093,6 @@ mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
5077
5093
5078
5094
err_type_init :
5079
5095
list_del (& nh -> router_list_node );
5080
- mlxsw_sp_nexthop_counter_disable (mlxsw_sp , nh );
5081
5096
return err ;
5082
5097
}
5083
5098
@@ -5100,6 +5115,7 @@ mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
5100
5115
struct mlxsw_sp_nexthop_group_info * nhgi ;
5101
5116
struct mlxsw_sp_nexthop * nh ;
5102
5117
bool is_resilient = false;
5118
+ bool hw_stats = false;
5103
5119
unsigned int nhs ;
5104
5120
int err , i ;
5105
5121
@@ -5109,9 +5125,11 @@ mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
5109
5125
break ;
5110
5126
case NH_NOTIFIER_INFO_TYPE_GRP :
5111
5127
nhs = info -> nh_grp -> num_nh ;
5128
+ hw_stats = info -> nh_grp -> hw_stats ;
5112
5129
break ;
5113
5130
case NH_NOTIFIER_INFO_TYPE_RES_TABLE :
5114
5131
nhs = info -> nh_res_table -> num_nh_buckets ;
5132
+ hw_stats = info -> nh_res_table -> hw_stats ;
5115
5133
is_resilient = true;
5116
5134
break ;
5117
5135
default :
@@ -5126,6 +5144,7 @@ mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
5126
5144
nhgi -> gateway = mlxsw_sp_nexthop_obj_is_gateway (mlxsw_sp , info );
5127
5145
nhgi -> is_resilient = is_resilient ;
5128
5146
nhgi -> count = nhs ;
5147
+ nhgi -> hw_stats = hw_stats ;
5129
5148
for (i = 0 ; i < nhgi -> count ; i ++ ) {
5130
5149
struct nh_notifier_single_info * nh_obj ;
5131
5150
int weight ;
@@ -5347,6 +5366,43 @@ mlxsw_sp_nexthop_obj_group_replace(struct mlxsw_sp *mlxsw_sp,
5347
5366
return err ;
5348
5367
}
5349
5368
5369
+ static int mlxsw_sp_nexthop_obj_res_group_pre (struct mlxsw_sp * mlxsw_sp ,
5370
+ struct nh_notifier_info * info )
5371
+ {
5372
+ struct nh_notifier_grp_info * grp_info = info -> nh_grp ;
5373
+ struct mlxsw_sp_nexthop_group_info * nhgi ;
5374
+ struct mlxsw_sp_nexthop_group * nh_grp ;
5375
+ int err ;
5376
+ int i ;
5377
+
5378
+ nh_grp = mlxsw_sp_nexthop_obj_group_lookup (mlxsw_sp , info -> id );
5379
+ if (!nh_grp )
5380
+ return 0 ;
5381
+ nhgi = nh_grp -> nhgi ;
5382
+
5383
+ if (nhgi -> hw_stats == grp_info -> hw_stats )
5384
+ return 0 ;
5385
+
5386
+ nhgi -> hw_stats = grp_info -> hw_stats ;
5387
+
5388
+ for (i = 0 ; i < nhgi -> count ; i ++ ) {
5389
+ struct mlxsw_sp_nexthop * nh = & nhgi -> nexthops [i ];
5390
+
5391
+ if (nh -> offloaded )
5392
+ nh -> update = 1 ;
5393
+ }
5394
+
5395
+ err = mlxsw_sp_nexthop_group_refresh (mlxsw_sp , nh_grp );
5396
+ if (err )
5397
+ goto err_group_refresh ;
5398
+
5399
+ return 0 ;
5400
+
5401
+ err_group_refresh :
5402
+ nhgi -> hw_stats = !grp_info -> hw_stats ;
5403
+ return err ;
5404
+ }
5405
+
5350
5406
static int mlxsw_sp_nexthop_obj_new (struct mlxsw_sp * mlxsw_sp ,
5351
5407
struct nh_notifier_info * info )
5352
5408
{
@@ -5523,6 +5579,79 @@ static int mlxsw_sp_nexthop_obj_bucket_replace(struct mlxsw_sp *mlxsw_sp,
5523
5579
return err ;
5524
5580
}
5525
5581
5582
+ static void
5583
+ mlxsw_sp_nexthop_obj_mp_hw_stats_get (struct mlxsw_sp * mlxsw_sp ,
5584
+ struct mlxsw_sp_nexthop_group_info * nhgi ,
5585
+ struct nh_notifier_grp_hw_stats_info * info )
5586
+ {
5587
+ int nhi ;
5588
+
5589
+ for (nhi = 0 ; nhi < info -> num_nh ; nhi ++ ) {
5590
+ struct mlxsw_sp_nexthop * nh = & nhgi -> nexthops [nhi ];
5591
+ u64 packets ;
5592
+ int err ;
5593
+
5594
+ err = mlxsw_sp_nexthop_counter_get (mlxsw_sp , nh , & packets );
5595
+ if (err )
5596
+ continue ;
5597
+
5598
+ nh_grp_hw_stats_report_delta (info , nhi , packets );
5599
+ }
5600
+ }
5601
+
5602
+ static void
5603
+ mlxsw_sp_nexthop_obj_res_hw_stats_get (struct mlxsw_sp * mlxsw_sp ,
5604
+ struct mlxsw_sp_nexthop_group_info * nhgi ,
5605
+ struct nh_notifier_grp_hw_stats_info * info )
5606
+ {
5607
+ int nhi = -1 ;
5608
+ int bucket ;
5609
+
5610
+ for (bucket = 0 ; bucket < nhgi -> count ; bucket ++ ) {
5611
+ struct mlxsw_sp_nexthop * nh = & nhgi -> nexthops [bucket ];
5612
+ u64 packets ;
5613
+ int err ;
5614
+
5615
+ if (nhi == -1 || info -> stats [nhi ].id != nh -> id ) {
5616
+ for (nhi = 0 ; nhi < info -> num_nh ; nhi ++ )
5617
+ if (info -> stats [nhi ].id == nh -> id )
5618
+ break ;
5619
+ if (WARN_ON_ONCE (nhi == info -> num_nh )) {
5620
+ nhi = -1 ;
5621
+ continue ;
5622
+ }
5623
+ }
5624
+
5625
+ err = mlxsw_sp_nexthop_counter_get (mlxsw_sp , nh , & packets );
5626
+ if (err )
5627
+ continue ;
5628
+
5629
+ nh_grp_hw_stats_report_delta (info , nhi , packets );
5630
+ }
5631
+ }
5632
+
5633
+ static void mlxsw_sp_nexthop_obj_hw_stats_get (struct mlxsw_sp * mlxsw_sp ,
5634
+ struct nh_notifier_info * info )
5635
+ {
5636
+ struct mlxsw_sp_nexthop_group_info * nhgi ;
5637
+ struct mlxsw_sp_nexthop_group * nh_grp ;
5638
+
5639
+ if (info -> type != NH_NOTIFIER_INFO_TYPE_GRP_HW_STATS )
5640
+ return ;
5641
+
5642
+ nh_grp = mlxsw_sp_nexthop_obj_group_lookup (mlxsw_sp , info -> id );
5643
+ if (!nh_grp )
5644
+ return ;
5645
+ nhgi = nh_grp -> nhgi ;
5646
+
5647
+ if (nhgi -> is_resilient )
5648
+ mlxsw_sp_nexthop_obj_res_hw_stats_get (mlxsw_sp , nhgi ,
5649
+ info -> nh_grp_hw_stats );
5650
+ else
5651
+ mlxsw_sp_nexthop_obj_mp_hw_stats_get (mlxsw_sp , nhgi ,
5652
+ info -> nh_grp_hw_stats );
5653
+ }
5654
+
5526
5655
static int mlxsw_sp_nexthop_obj_event (struct notifier_block * nb ,
5527
5656
unsigned long event , void * ptr )
5528
5657
{
@@ -5538,6 +5667,10 @@ static int mlxsw_sp_nexthop_obj_event(struct notifier_block *nb,
5538
5667
mutex_lock (& router -> lock );
5539
5668
5540
5669
switch (event ) {
5670
+ case NEXTHOP_EVENT_RES_TABLE_PRE_REPLACE :
5671
+ err = mlxsw_sp_nexthop_obj_res_group_pre (router -> mlxsw_sp ,
5672
+ info );
5673
+ break ;
5541
5674
case NEXTHOP_EVENT_REPLACE :
5542
5675
err = mlxsw_sp_nexthop_obj_new (router -> mlxsw_sp , info );
5543
5676
break ;
@@ -5548,6 +5681,9 @@ static int mlxsw_sp_nexthop_obj_event(struct notifier_block *nb,
5548
5681
err = mlxsw_sp_nexthop_obj_bucket_replace (router -> mlxsw_sp ,
5549
5682
info );
5550
5683
break ;
5684
+ case NEXTHOP_EVENT_HW_STATS_REPORT_DELTA :
5685
+ mlxsw_sp_nexthop_obj_hw_stats_get (router -> mlxsw_sp , info );
5686
+ break ;
5551
5687
default :
5552
5688
break ;
5553
5689
}
0 commit comments