Skip to content

Commit 5a5a98e

Browse files
pmachatakuba-moo
authored andcommitted
mlxsw: spectrum_router: Support nexthop group hardware statistics
When hw_stats is set on a group, install nexthop counters on members of a group. Counter allocation request is moved from nexthop object initialization to the update code. The previous placement made sense: when the counters are enabled by dpipe, the counters are installed to all existing nexthops and all nexthops created from then on get them. For the finer-grained nexthop group statistics, this is unsuitable. The existing placement was kept for the IPv4 and IPv6 nexthops. Resilient group replacement emits a pre_replace notification, and then any bucket_replace notifications if there were any replacements at all. If the group is balanced and the nexthop composition of the replaced group didn't change, there will be no such notifiers. Therefore hook to the pre_replace notifier and mark all buckets for update, to un/install the counters. When reporting deltas for resilient groups, use the nexthop ID that we stored in a previous patch to look up to which nexthop a bucket contributes. Co-developed-by: Ido Schimmel <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: Petr Machata <[email protected]> Link: https://lore.kernel.org/r/87495a72f187df2e5d491d02729c550d235fcc85.1709901020.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 41acb55 commit 5a5a98e

File tree

1 file changed

+142
-6
lines changed

1 file changed

+142
-6
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

Lines changed: 142 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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,
31893190
int 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+
32203232
int 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

32303242
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,
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

50785094
err_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+
53505406
static 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+
55265655
static 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

Comments
 (0)