@@ -3108,7 +3108,8 @@ struct mlxsw_sp_nexthop_group_info {
31083108 int sum_norm_weight ;
31093109 u8 adj_index_valid :1 ,
31103110 gateway :1 , /* routes using the group use a gateway */
3111- is_resilient :1 ;
3111+ is_resilient :1 ,
3112+ hw_stats :1 ;
31123113 struct list_head list ; /* member in nh_res_grp_list */
31133114 struct mlxsw_sp_nexthop nexthops [] __counted_by (count );
31143115};
@@ -3189,15 +3190,17 @@ mlxsw_sp_nexthop_counter_free(struct mlxsw_sp *mlxsw_sp,
31893190int mlxsw_sp_nexthop_counter_enable (struct mlxsw_sp * mlxsw_sp ,
31903191 struct mlxsw_sp_nexthop * nh )
31913192{
3193+ const char * table_adj = MLXSW_SP_DPIPE_TABLE_NAME_ADJ ;
31923194 struct mlxsw_sp_nexthop_counter * nhct ;
31933195 struct devlink * devlink ;
3196+ bool dpipe_stats ;
31943197
31953198 if (nh -> counter )
31963199 return 0 ;
31973200
31983201 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 ))
32013204 return 0 ;
32023205
32033206 nhct = mlxsw_sp_nexthop_counter_alloc (mlxsw_sp );
@@ -3217,14 +3220,23 @@ void mlxsw_sp_nexthop_counter_disable(struct mlxsw_sp *mlxsw_sp,
32173220 nh -> counter = NULL ;
32183221}
32193222
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+
32203232int mlxsw_sp_nexthop_counter_get (struct mlxsw_sp * mlxsw_sp ,
32213233 struct mlxsw_sp_nexthop * nh , u64 * p_counter )
32223234{
32233235 if (!nh -> counter )
32243236 return - EINVAL ;
32253237
32263238 return mlxsw_sp_flow_counter_get (mlxsw_sp , nh -> counter -> counter_index ,
3227- false , p_counter , NULL );
3239+ true , p_counter , NULL );
32283240}
32293241
32303242struct 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,
37863798 nh = & nhgi -> nexthops [i ];
37873799
37883800 if (!nh -> should_offload ) {
3801+ mlxsw_sp_nexthop_counter_disable (mlxsw_sp , nh );
37893802 nh -> offloaded = 0 ;
37903803 continue ;
37913804 }
37923805
37933806 if (nh -> update || reallocate ) {
37943807 int err = 0 ;
37953808
3809+ err = mlxsw_sp_nexthop_counter_update (mlxsw_sp , nh );
3810+ if (err )
3811+ return err ;
3812+
37963813 err = mlxsw_sp_nexthop_update (mlxsw_sp , adj_index , nh ,
37973814 true, ratr_pl );
37983815 if (err )
@@ -5052,7 +5069,6 @@ mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
50525069 break ;
50535070 }
50545071
5055- mlxsw_sp_nexthop_counter_enable (mlxsw_sp , nh );
50565072 list_add_tail (& nh -> router_list_node , & mlxsw_sp -> router -> nexthop_list );
50575073 nh -> ifindex = dev -> ifindex ;
50585074 nh -> id = nh_obj -> id ;
@@ -5077,7 +5093,6 @@ mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
50775093
50785094err_type_init :
50795095 list_del (& nh -> router_list_node );
5080- mlxsw_sp_nexthop_counter_disable (mlxsw_sp , nh );
50815096 return err ;
50825097}
50835098
@@ -5100,6 +5115,7 @@ mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
51005115 struct mlxsw_sp_nexthop_group_info * nhgi ;
51015116 struct mlxsw_sp_nexthop * nh ;
51025117 bool is_resilient = false;
5118+ bool hw_stats = false;
51035119 unsigned int nhs ;
51045120 int err , i ;
51055121
@@ -5109,9 +5125,11 @@ mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
51095125 break ;
51105126 case NH_NOTIFIER_INFO_TYPE_GRP :
51115127 nhs = info -> nh_grp -> num_nh ;
5128+ hw_stats = info -> nh_grp -> hw_stats ;
51125129 break ;
51135130 case NH_NOTIFIER_INFO_TYPE_RES_TABLE :
51145131 nhs = info -> nh_res_table -> num_nh_buckets ;
5132+ hw_stats = info -> nh_res_table -> hw_stats ;
51155133 is_resilient = true;
51165134 break ;
51175135 default :
@@ -5126,6 +5144,7 @@ mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
51265144 nhgi -> gateway = mlxsw_sp_nexthop_obj_is_gateway (mlxsw_sp , info );
51275145 nhgi -> is_resilient = is_resilient ;
51285146 nhgi -> count = nhs ;
5147+ nhgi -> hw_stats = hw_stats ;
51295148 for (i = 0 ; i < nhgi -> count ; i ++ ) {
51305149 struct nh_notifier_single_info * nh_obj ;
51315150 int weight ;
@@ -5347,6 +5366,43 @@ mlxsw_sp_nexthop_obj_group_replace(struct mlxsw_sp *mlxsw_sp,
53475366 return err ;
53485367}
53495368
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+
53505406static int mlxsw_sp_nexthop_obj_new (struct mlxsw_sp * mlxsw_sp ,
53515407 struct nh_notifier_info * info )
53525408{
@@ -5523,6 +5579,79 @@ static int mlxsw_sp_nexthop_obj_bucket_replace(struct mlxsw_sp *mlxsw_sp,
55235579 return err ;
55245580}
55255581
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+
55265655static int mlxsw_sp_nexthop_obj_event (struct notifier_block * nb ,
55275656 unsigned long event , void * ptr )
55285657{
@@ -5538,6 +5667,10 @@ static int mlxsw_sp_nexthop_obj_event(struct notifier_block *nb,
55385667 mutex_lock (& router -> lock );
55395668
55405669 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 ;
55415674 case NEXTHOP_EVENT_REPLACE :
55425675 err = mlxsw_sp_nexthop_obj_new (router -> mlxsw_sp , info );
55435676 break ;
@@ -5548,6 +5681,9 @@ static int mlxsw_sp_nexthop_obj_event(struct notifier_block *nb,
55485681 err = mlxsw_sp_nexthop_obj_bucket_replace (router -> mlxsw_sp ,
55495682 info );
55505683 break ;
5684+ case NEXTHOP_EVENT_HW_STATS_REPORT_DELTA :
5685+ mlxsw_sp_nexthop_obj_hw_stats_get (router -> mlxsw_sp , info );
5686+ break ;
55515687 default :
55525688 break ;
55535689 }
0 commit comments