Skip to content

Commit 1520929

Browse files
committed
Merge branch 'mlxsw-Implement-sampling-using-mirroring'
Ido Schimmel says: ==================== mlxsw: Implement sampling using mirroring So far, sampling was implemented using a dedicated sampling mechanism that is available on all Spectrum ASICs. Spectrum-2 and later ASICs support sampling by mirroring packets to the CPU port with probability. This method has a couple of advantages compared to the legacy method: * Extra metadata per-packet: Egress port, egress traffic class, traffic class occupancy and end-to-end latency * Ability to sample packets on egress / per-flow as opposed to only ingress This series should not result in any user-visible changes and its aim is to convert Spectrum-2 and later ASICs to perform sampling by mirroring to the CPU port with probability. Future submissions will expose the additional metadata and enable sampling using more triggers (e.g., egress). Series overview: Patches kernel-patches#1-kernel-patches#3 extend the SPAN (mirroring) module to accept new parameters required for sampling. See individual commit messages for detailed explanation. Patch kernel-patches#4-kernel-patches#5 split sampling support between Spectrum-1 and later ASIC while still using the legacy method for all ASIC generations. Patch kernel-patches#6 converts Spectrum-2 and later ASICs to perform sampling by mirroring to the CPU port with probability. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 1bc61c9 + cf31190 commit 1520929

File tree

8 files changed

+181
-22
lines changed

8 files changed

+181
-22
lines changed

drivers/net/ethernet/mellanox/mlxsw/reg.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9925,15 +9925,28 @@ MLXSW_ITEM32(reg, mpar, enable, 0x04, 31, 1);
99259925
*/
99269926
MLXSW_ITEM32(reg, mpar, pa_id, 0x04, 0, 4);
99279927

9928+
#define MLXSW_REG_MPAR_RATE_MAX 3500000000UL
9929+
9930+
/* reg_mpar_probability_rate
9931+
* Sampling rate.
9932+
* Valid values are: 1 to 3.5*10^9
9933+
* Value of 1 means "sample all". Default is 1.
9934+
* Reserved when Spectrum-1.
9935+
* Access: RW
9936+
*/
9937+
MLXSW_ITEM32(reg, mpar, probability_rate, 0x08, 0, 32);
9938+
99289939
static inline void mlxsw_reg_mpar_pack(char *payload, u8 local_port,
99299940
enum mlxsw_reg_mpar_i_e i_e,
9930-
bool enable, u8 pa_id)
9941+
bool enable, u8 pa_id,
9942+
u32 probability_rate)
99319943
{
99329944
MLXSW_REG_ZERO(mpar, payload);
99339945
mlxsw_reg_mpar_local_port_set(payload, local_port);
99349946
mlxsw_reg_mpar_enable_set(payload, enable);
99359947
mlxsw_reg_mpar_i_e_set(payload, i_e);
99369948
mlxsw_reg_mpar_pa_id_set(payload, pa_id);
9949+
mlxsw_reg_mpar_probability_rate_set(payload, probability_rate);
99379950
}
99389951

99399952
/* MGIR - Management General Information Register
@@ -10577,6 +10590,8 @@ MLXSW_ITEM32(reg, mpagr, trigger, 0x00, 0, 4);
1057710590
*/
1057810591
MLXSW_ITEM32(reg, mpagr, pa_id, 0x04, 0, 4);
1057910592

10593+
#define MLXSW_REG_MPAGR_RATE_MAX 3500000000UL
10594+
1058010595
/* reg_mpagr_probability_rate
1058110596
* Sampling rate.
1058210597
* Valid values are: 1 to 3.5*10^9

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,6 +2804,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
28042804
mlxsw_sp->span_ops = &mlxsw_sp1_span_ops;
28052805
mlxsw_sp->policer_core_ops = &mlxsw_sp1_policer_core_ops;
28062806
mlxsw_sp->trap_ops = &mlxsw_sp1_trap_ops;
2807+
mlxsw_sp->mall_ops = &mlxsw_sp1_mall_ops;
28072808
mlxsw_sp->listeners = mlxsw_sp1_listener;
28082809
mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
28092810
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1;
@@ -2833,6 +2834,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
28332834
mlxsw_sp->span_ops = &mlxsw_sp2_span_ops;
28342835
mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops;
28352836
mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
2837+
mlxsw_sp->mall_ops = &mlxsw_sp2_mall_ops;
28362838
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2;
28372839

28382840
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
@@ -2860,6 +2862,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
28602862
mlxsw_sp->span_ops = &mlxsw_sp3_span_ops;
28612863
mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops;
28622864
mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
2865+
mlxsw_sp->mall_ops = &mlxsw_sp2_mall_ops;
28632866
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;
28642867

28652868
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ struct mlxsw_sp {
179179
const struct mlxsw_sp_span_ops *span_ops;
180180
const struct mlxsw_sp_policer_core_ops *policer_core_ops;
181181
const struct mlxsw_sp_trap_ops *trap_ops;
182+
const struct mlxsw_sp_mall_ops *mall_ops;
182183
const struct mlxsw_listener *listeners;
183184
size_t listeners_count;
184185
u32 lowest_shaper_bs;
@@ -237,6 +238,7 @@ struct mlxsw_sp_port_sample {
237238
u32 trunc_size;
238239
u32 rate;
239240
bool truncate;
241+
int span_id; /* Relevant for Spectrum-2 onwards. */
240242
};
241243

242244
struct mlxsw_sp_bridge_port;
@@ -1033,6 +1035,16 @@ extern const struct mlxsw_afk_ops mlxsw_sp1_afk_ops;
10331035
extern const struct mlxsw_afk_ops mlxsw_sp2_afk_ops;
10341036

10351037
/* spectrum_matchall.c */
1038+
struct mlxsw_sp_mall_ops {
1039+
int (*sample_add)(struct mlxsw_sp *mlxsw_sp,
1040+
struct mlxsw_sp_port *mlxsw_sp_port, u32 rate);
1041+
void (*sample_del)(struct mlxsw_sp *mlxsw_sp,
1042+
struct mlxsw_sp_port *mlxsw_sp_port);
1043+
};
1044+
1045+
extern const struct mlxsw_sp_mall_ops mlxsw_sp1_mall_ops;
1046+
extern const struct mlxsw_sp_mall_ops mlxsw_sp2_mall_ops;
1047+
10361048
enum mlxsw_sp_mall_action_type {
10371049
MLXSW_SP_MALL_ACTION_TYPE_MIRROR,
10381050
MLXSW_SP_MALL_ACTION_TYPE_SAMPLE,

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

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port,
5151
trigger = mall_entry->ingress ? MLXSW_SP_SPAN_TRIGGER_INGRESS :
5252
MLXSW_SP_SPAN_TRIGGER_EGRESS;
5353
parms.span_id = mall_entry->mirror.span_id;
54+
parms.probability_rate = 1;
5455
err = mlxsw_sp_span_agent_bind(mlxsw_sp, trigger, mlxsw_sp_port,
5556
&parms);
5657
if (err)
@@ -95,6 +96,7 @@ static int
9596
mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port,
9697
struct mlxsw_sp_mall_entry *mall_entry)
9798
{
99+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
98100
int err;
99101

100102
if (rtnl_dereference(mlxsw_sp_port->sample)) {
@@ -103,8 +105,8 @@ mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port,
103105
}
104106
rcu_assign_pointer(mlxsw_sp_port->sample, &mall_entry->sample);
105107

106-
err = mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, true,
107-
mall_entry->sample.rate);
108+
err = mlxsw_sp->mall_ops->sample_add(mlxsw_sp, mlxsw_sp_port,
109+
mall_entry->sample.rate);
108110
if (err)
109111
goto err_port_sample_set;
110112
return 0;
@@ -117,10 +119,12 @@ mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port,
117119
static void
118120
mlxsw_sp_mall_port_sample_del(struct mlxsw_sp_port *mlxsw_sp_port)
119121
{
122+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
123+
120124
if (!mlxsw_sp_port->sample)
121125
return;
122126

123-
mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, false, 1);
127+
mlxsw_sp->mall_ops->sample_del(mlxsw_sp, mlxsw_sp_port);
124128
RCU_INIT_POINTER(mlxsw_sp_port->sample, NULL);
125129
}
126130

@@ -355,3 +359,79 @@ int mlxsw_sp_mall_prio_get(struct mlxsw_sp_flow_block *block, u32 chain_index,
355359
*p_max_prio = block->mall.max_prio;
356360
return 0;
357361
}
362+
363+
static int mlxsw_sp1_mall_sample_add(struct mlxsw_sp *mlxsw_sp,
364+
struct mlxsw_sp_port *mlxsw_sp_port,
365+
u32 rate)
366+
{
367+
return mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, true, rate);
368+
}
369+
370+
static void mlxsw_sp1_mall_sample_del(struct mlxsw_sp *mlxsw_sp,
371+
struct mlxsw_sp_port *mlxsw_sp_port)
372+
{
373+
mlxsw_sp_mall_port_sample_set(mlxsw_sp_port, false, 1);
374+
}
375+
376+
const struct mlxsw_sp_mall_ops mlxsw_sp1_mall_ops = {
377+
.sample_add = mlxsw_sp1_mall_sample_add,
378+
.sample_del = mlxsw_sp1_mall_sample_del,
379+
};
380+
381+
static int mlxsw_sp2_mall_sample_add(struct mlxsw_sp *mlxsw_sp,
382+
struct mlxsw_sp_port *mlxsw_sp_port,
383+
u32 rate)
384+
{
385+
struct mlxsw_sp_span_trigger_parms trigger_parms = {};
386+
struct mlxsw_sp_span_agent_parms agent_parms = {
387+
.to_dev = NULL, /* Mirror to CPU. */
388+
.session_id = MLXSW_SP_SPAN_SESSION_ID_SAMPLING,
389+
};
390+
struct mlxsw_sp_port_sample *sample;
391+
int err;
392+
393+
sample = rtnl_dereference(mlxsw_sp_port->sample);
394+
395+
err = mlxsw_sp_span_agent_get(mlxsw_sp, &sample->span_id, &agent_parms);
396+
if (err)
397+
return err;
398+
399+
err = mlxsw_sp_span_analyzed_port_get(mlxsw_sp_port, true);
400+
if (err)
401+
goto err_analyzed_port_get;
402+
403+
trigger_parms.span_id = sample->span_id;
404+
trigger_parms.probability_rate = rate;
405+
err = mlxsw_sp_span_agent_bind(mlxsw_sp, MLXSW_SP_SPAN_TRIGGER_INGRESS,
406+
mlxsw_sp_port, &trigger_parms);
407+
if (err)
408+
goto err_agent_bind;
409+
410+
return 0;
411+
412+
err_agent_bind:
413+
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true);
414+
err_analyzed_port_get:
415+
mlxsw_sp_span_agent_put(mlxsw_sp, sample->span_id);
416+
return err;
417+
}
418+
419+
static void mlxsw_sp2_mall_sample_del(struct mlxsw_sp *mlxsw_sp,
420+
struct mlxsw_sp_port *mlxsw_sp_port)
421+
{
422+
struct mlxsw_sp_span_trigger_parms trigger_parms = {};
423+
struct mlxsw_sp_port_sample *sample;
424+
425+
sample = rtnl_dereference(mlxsw_sp_port->sample);
426+
427+
trigger_parms.span_id = sample->span_id;
428+
mlxsw_sp_span_agent_unbind(mlxsw_sp, MLXSW_SP_SPAN_TRIGGER_INGRESS,
429+
mlxsw_sp_port, &trigger_parms);
430+
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true);
431+
mlxsw_sp_span_agent_put(mlxsw_sp, sample->span_id);
432+
}
433+
434+
const struct mlxsw_sp_mall_ops mlxsw_sp2_mall_ops = {
435+
.sample_add = mlxsw_sp2_mall_sample_add,
436+
.sample_del = mlxsw_sp2_mall_sample_del,
437+
};

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,7 @@ static int mlxsw_sp_qevent_span_configure(struct mlxsw_sp *mlxsw_sp,
13411341
goto err_analyzed_port_get;
13421342

13431343
trigger_parms.span_id = span_id;
1344+
trigger_parms.probability_rate = 1;
13441345
err = mlxsw_sp_span_agent_bind(mlxsw_sp, qevent_binding->span_trigger, mlxsw_sp_port,
13451346
&trigger_parms);
13461347
if (err)
@@ -1404,7 +1405,9 @@ static int mlxsw_sp_qevent_trap_configure(struct mlxsw_sp *mlxsw_sp,
14041405
struct mlxsw_sp_mall_entry *mall_entry,
14051406
struct mlxsw_sp_qevent_binding *qevent_binding)
14061407
{
1407-
struct mlxsw_sp_span_agent_parms agent_parms = {};
1408+
struct mlxsw_sp_span_agent_parms agent_parms = {
1409+
.session_id = MLXSW_SP_SPAN_SESSION_ID_BUFFER,
1410+
};
14081411
int err;
14091412

14101413
err = mlxsw_sp_trap_group_policer_hw_id_get(mlxsw_sp,

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

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ mlxsw_sp_span_entry_phys_configure(struct mlxsw_sp_span_entry *span_entry,
186186
/* Create a new port analayzer entry for local_port. */
187187
mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
188188
MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
189+
mlxsw_reg_mpat_session_id_set(mpat_pl, sparms.session_id);
189190
mlxsw_reg_mpat_pide_set(mpat_pl, sparms.policer_enable);
190191
mlxsw_reg_mpat_pid_set(mpat_pl, sparms.policer_id);
191192

@@ -203,6 +204,7 @@ mlxsw_sp_span_entry_deconfigure_common(struct mlxsw_sp_span_entry *span_entry,
203204
int pa_id = span_entry->id;
204205

205206
mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false, span_type);
207+
mlxsw_reg_mpat_session_id_set(mpat_pl, span_entry->parms.session_id);
206208
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
207209
}
208210

@@ -938,7 +940,8 @@ mlxsw_sp_span_entry_find_by_parms(struct mlxsw_sp *mlxsw_sp,
938940

939941
if (refcount_read(&curr->ref_count) && curr->to_dev == to_dev &&
940942
curr->parms.policer_enable == sparms->policer_enable &&
941-
curr->parms.policer_id == sparms->policer_id)
943+
curr->parms.policer_id == sparms->policer_id &&
944+
curr->parms.session_id == sparms->session_id)
942945
return curr;
943946
}
944947
return NULL;
@@ -1085,6 +1088,7 @@ int mlxsw_sp_span_agent_get(struct mlxsw_sp *mlxsw_sp, int *p_span_id,
10851088

10861089
sparms.policer_id = parms->policer_id;
10871090
sparms.policer_enable = parms->policer_enable;
1091+
sparms.session_id = parms->session_id;
10881092
span_entry = mlxsw_sp_span_entry_get(mlxsw_sp, to_dev, ops, sparms);
10891093
if (!span_entry)
10901094
return -ENOBUFS;
@@ -1227,8 +1231,12 @@ __mlxsw_sp_span_trigger_port_bind(struct mlxsw_sp_span *span,
12271231
return -EINVAL;
12281232
}
12291233

1234+
if (trigger_entry->parms.probability_rate > MLXSW_REG_MPAR_RATE_MAX)
1235+
return -EINVAL;
1236+
12301237
mlxsw_reg_mpar_pack(mpar_pl, trigger_entry->local_port, i_e, enable,
1231-
trigger_entry->parms.span_id);
1238+
trigger_entry->parms.span_id,
1239+
trigger_entry->parms.probability_rate);
12321240
return mlxsw_reg_write(span->mlxsw_sp->core, MLXSW_REG(mpar), mpar_pl);
12331241
}
12341242

@@ -1362,8 +1370,11 @@ mlxsw_sp2_span_trigger_global_bind(struct mlxsw_sp_span_trigger_entry *
13621370
return -EINVAL;
13631371
}
13641372

1373+
if (trigger_entry->parms.probability_rate > MLXSW_REG_MPAGR_RATE_MAX)
1374+
return -EINVAL;
1375+
13651376
mlxsw_reg_mpagr_pack(mpagr_pl, trigger, trigger_entry->parms.span_id,
1366-
1);
1377+
trigger_entry->parms.probability_rate);
13671378
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpagr), mpagr_pl);
13681379
}
13691380

@@ -1561,7 +1572,9 @@ int mlxsw_sp_span_agent_bind(struct mlxsw_sp *mlxsw_sp,
15611572
trigger,
15621573
mlxsw_sp_port);
15631574
if (trigger_entry) {
1564-
if (trigger_entry->parms.span_id != parms->span_id)
1575+
if (trigger_entry->parms.span_id != parms->span_id ||
1576+
trigger_entry->parms.probability_rate !=
1577+
parms->probability_rate)
15651578
return -EINVAL;
15661579
refcount_inc(&trigger_entry->ref_count);
15671580
goto out;

drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@
1313
struct mlxsw_sp;
1414
struct mlxsw_sp_port;
1515

16+
/* SPAN session identifiers that correspond to MLXSW_TRAP_ID_MIRROR_SESSION<i>
17+
* trap identifiers. The session identifier is an attribute of the SPAN agent,
18+
* which determines the trap identifier of packets that are mirrored to the
19+
* CPU. Packets that are trapped to the CPU for the same logical reason (e.g.,
20+
* buffer drops) should use the same session identifier.
21+
*/
22+
enum mlxsw_sp_span_session_id {
23+
MLXSW_SP_SPAN_SESSION_ID_BUFFER,
24+
MLXSW_SP_SPAN_SESSION_ID_SAMPLING,
25+
26+
__MLXSW_SP_SPAN_SESSION_ID_MAX = 8,
27+
};
28+
1629
struct mlxsw_sp_span_parms {
1730
struct mlxsw_sp_port *dest_port; /* NULL for unoffloaded SPAN. */
1831
unsigned int ttl;
@@ -23,6 +36,7 @@ struct mlxsw_sp_span_parms {
2336
u16 vid;
2437
u16 policer_id;
2538
bool policer_enable;
39+
enum mlxsw_sp_span_session_id session_id;
2640
};
2741

2842
enum mlxsw_sp_span_trigger {
@@ -35,12 +49,14 @@ enum mlxsw_sp_span_trigger {
3549

3650
struct mlxsw_sp_span_trigger_parms {
3751
int span_id;
52+
u32 probability_rate;
3853
};
3954

4055
struct mlxsw_sp_span_agent_parms {
4156
const struct net_device *to_dev;
4257
u16 policer_id;
4358
bool policer_enable;
59+
enum mlxsw_sp_span_session_id session_id;
4460
};
4561

4662
struct mlxsw_sp_span_entry_ops;

0 commit comments

Comments
 (0)