Skip to content

Commit 249ae94

Browse files
committed
Merge branch 'mlxsw-ECN-mirroring'
Ido Schimmel says: ==================== mlxsw: Add support for ECN mirroring Petr says: Patches in this set have been floating around for some time now together with trap_fwd support. That will however need more work, time for which is nowhere to be found, apparently. Instead, this patchset enables offload of only packet mirroring on RED mark qevent, enabling mirroring of ECN-marked packets. Formally it enables offload of filters added to blocks bound to the RED qevent mark if: - The switch ASIC is Spectrum-2 or above. - Only a single filter is attached at the block, at chain 0 (the default), and its classifier is matchall. - The filter has hw_stats set to disabled. - The filter has a single action, which is mirror. This differs from early_drop qevent offload, which supports mirroring and trapping. However trapping in context of ECN-marked packets is not suitable, because the HW does not drop the packet, as the trap action implies. And there is as of now no way to express only the part of trapping that transfers the packet to the SW datapath, sans the HW-datapath drop. The patchset progresses as follows: Patch #1 is an extack propagation. Mirroring of ECN-marked packets is configured in the ASIC through an ECN trigger, which is considered "egress", unlike the EARLY_DROP trigger. In patch #2, add a helper to classify triggers as ingress. As clarified above, traps cannot be offloaded on mark qevent. Similarly, given a trap_fwd action, it would not be offloadable on early_drop qevent. In patch #3, introduce support for tracking actions permissible on a given block. Patch #4 actually adds the mark qevent offload. In patch #5, fix a small style issue in one of the selftests, and in patch #6 add mark offload selftests. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents ff7f0e4 + 0cd6fa9 commit 249ae94

File tree

7 files changed

+220
-36
lines changed

7 files changed

+220
-36
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,8 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
10351035
return mlxsw_sp_setup_tc_block_clsact(mlxsw_sp_port, f, false);
10361036
case FLOW_BLOCK_BINDER_TYPE_RED_EARLY_DROP:
10371037
return mlxsw_sp_setup_tc_block_qevent_early_drop(mlxsw_sp_port, f);
1038+
case FLOW_BLOCK_BINDER_TYPE_RED_MARK:
1039+
return mlxsw_sp_setup_tc_block_qevent_mark(mlxsw_sp_port, f);
10381040
default:
10391041
return -EOPNOTSUPP;
10401042
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,8 @@ int mlxsw_sp_setup_tc_fifo(struct mlxsw_sp_port *mlxsw_sp_port,
11951195
struct tc_fifo_qopt_offload *p);
11961196
int mlxsw_sp_setup_tc_block_qevent_early_drop(struct mlxsw_sp_port *mlxsw_sp_port,
11971197
struct flow_block_offload *f);
1198+
int mlxsw_sp_setup_tc_block_qevent_mark(struct mlxsw_sp_port *mlxsw_sp_port,
1199+
struct flow_block_offload *f);
11981200

11991201
/* spectrum_fid.c */
12001202
bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index);

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

Lines changed: 77 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,7 @@ struct mlxsw_sp_qevent_binding {
14721472
u32 handle;
14731473
int tclass_num;
14741474
enum mlxsw_sp_span_trigger span_trigger;
1475+
unsigned int action_mask;
14751476
};
14761477

14771478
static LIST_HEAD(mlxsw_sp_qevent_block_cb_list);
@@ -1482,27 +1483,30 @@ static int mlxsw_sp_qevent_span_configure(struct mlxsw_sp *mlxsw_sp,
14821483
const struct mlxsw_sp_span_agent_parms *agent_parms,
14831484
int *p_span_id)
14841485
{
1486+
enum mlxsw_sp_span_trigger span_trigger = qevent_binding->span_trigger;
14851487
struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port;
14861488
struct mlxsw_sp_span_trigger_parms trigger_parms = {};
1489+
bool ingress;
14871490
int span_id;
14881491
int err;
14891492

14901493
err = mlxsw_sp_span_agent_get(mlxsw_sp, &span_id, agent_parms);
14911494
if (err)
14921495
return err;
14931496

1494-
err = mlxsw_sp_span_analyzed_port_get(mlxsw_sp_port, true);
1497+
ingress = mlxsw_sp_span_trigger_is_ingress(span_trigger);
1498+
err = mlxsw_sp_span_analyzed_port_get(mlxsw_sp_port, ingress);
14951499
if (err)
14961500
goto err_analyzed_port_get;
14971501

14981502
trigger_parms.span_id = span_id;
14991503
trigger_parms.probability_rate = 1;
1500-
err = mlxsw_sp_span_agent_bind(mlxsw_sp, qevent_binding->span_trigger, mlxsw_sp_port,
1504+
err = mlxsw_sp_span_agent_bind(mlxsw_sp, span_trigger, mlxsw_sp_port,
15011505
&trigger_parms);
15021506
if (err)
15031507
goto err_agent_bind;
15041508

1505-
err = mlxsw_sp_span_trigger_enable(mlxsw_sp_port, qevent_binding->span_trigger,
1509+
err = mlxsw_sp_span_trigger_enable(mlxsw_sp_port, span_trigger,
15061510
qevent_binding->tclass_num);
15071511
if (err)
15081512
goto err_trigger_enable;
@@ -1511,10 +1515,10 @@ static int mlxsw_sp_qevent_span_configure(struct mlxsw_sp *mlxsw_sp,
15111515
return 0;
15121516

15131517
err_trigger_enable:
1514-
mlxsw_sp_span_agent_unbind(mlxsw_sp, qevent_binding->span_trigger, mlxsw_sp_port,
1518+
mlxsw_sp_span_agent_unbind(mlxsw_sp, span_trigger, mlxsw_sp_port,
15151519
&trigger_parms);
15161520
err_agent_bind:
1517-
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true);
1521+
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, ingress);
15181522
err_analyzed_port_get:
15191523
mlxsw_sp_span_agent_put(mlxsw_sp, span_id);
15201524
return err;
@@ -1524,16 +1528,20 @@ static void mlxsw_sp_qevent_span_deconfigure(struct mlxsw_sp *mlxsw_sp,
15241528
struct mlxsw_sp_qevent_binding *qevent_binding,
15251529
int span_id)
15261530
{
1531+
enum mlxsw_sp_span_trigger span_trigger = qevent_binding->span_trigger;
15271532
struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port;
15281533
struct mlxsw_sp_span_trigger_parms trigger_parms = {
15291534
.span_id = span_id,
15301535
};
1536+
bool ingress;
15311537

1532-
mlxsw_sp_span_trigger_disable(mlxsw_sp_port, qevent_binding->span_trigger,
1538+
ingress = mlxsw_sp_span_trigger_is_ingress(span_trigger);
1539+
1540+
mlxsw_sp_span_trigger_disable(mlxsw_sp_port, span_trigger,
15331541
qevent_binding->tclass_num);
1534-
mlxsw_sp_span_agent_unbind(mlxsw_sp, qevent_binding->span_trigger, mlxsw_sp_port,
1542+
mlxsw_sp_span_agent_unbind(mlxsw_sp, span_trigger, mlxsw_sp_port,
15351543
&trigger_parms);
1536-
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true);
1544+
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, ingress);
15371545
mlxsw_sp_span_agent_put(mlxsw_sp, span_id);
15381546
}
15391547

@@ -1583,10 +1591,17 @@ static void mlxsw_sp_qevent_trap_deconfigure(struct mlxsw_sp *mlxsw_sp,
15831591
mlxsw_sp_qevent_span_deconfigure(mlxsw_sp, qevent_binding, mall_entry->trap.span_id);
15841592
}
15851593

1586-
static int mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp,
1587-
struct mlxsw_sp_mall_entry *mall_entry,
1588-
struct mlxsw_sp_qevent_binding *qevent_binding)
1594+
static int
1595+
mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp,
1596+
struct mlxsw_sp_mall_entry *mall_entry,
1597+
struct mlxsw_sp_qevent_binding *qevent_binding,
1598+
struct netlink_ext_ack *extack)
15891599
{
1600+
if (!(BIT(mall_entry->type) & qevent_binding->action_mask)) {
1601+
NL_SET_ERR_MSG(extack, "Action not supported at this qevent");
1602+
return -EOPNOTSUPP;
1603+
}
1604+
15901605
switch (mall_entry->type) {
15911606
case MLXSW_SP_MALL_ACTION_TYPE_MIRROR:
15921607
return mlxsw_sp_qevent_mirror_configure(mlxsw_sp, mall_entry, qevent_binding);
@@ -1614,15 +1629,17 @@ static void mlxsw_sp_qevent_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
16141629
}
16151630
}
16161631

1617-
static int mlxsw_sp_qevent_binding_configure(struct mlxsw_sp_qevent_block *qevent_block,
1618-
struct mlxsw_sp_qevent_binding *qevent_binding)
1632+
static int
1633+
mlxsw_sp_qevent_binding_configure(struct mlxsw_sp_qevent_block *qevent_block,
1634+
struct mlxsw_sp_qevent_binding *qevent_binding,
1635+
struct netlink_ext_ack *extack)
16191636
{
16201637
struct mlxsw_sp_mall_entry *mall_entry;
16211638
int err;
16221639

16231640
list_for_each_entry(mall_entry, &qevent_block->mall_entry_list, list) {
16241641
err = mlxsw_sp_qevent_entry_configure(qevent_block->mlxsw_sp, mall_entry,
1625-
qevent_binding);
1642+
qevent_binding, extack);
16261643
if (err)
16271644
goto err_entry_configure;
16281645
}
@@ -1646,13 +1663,17 @@ static void mlxsw_sp_qevent_binding_deconfigure(struct mlxsw_sp_qevent_block *qe
16461663
qevent_binding);
16471664
}
16481665

1649-
static int mlxsw_sp_qevent_block_configure(struct mlxsw_sp_qevent_block *qevent_block)
1666+
static int
1667+
mlxsw_sp_qevent_block_configure(struct mlxsw_sp_qevent_block *qevent_block,
1668+
struct netlink_ext_ack *extack)
16501669
{
16511670
struct mlxsw_sp_qevent_binding *qevent_binding;
16521671
int err;
16531672

16541673
list_for_each_entry(qevent_binding, &qevent_block->binding_list, list) {
1655-
err = mlxsw_sp_qevent_binding_configure(qevent_block, qevent_binding);
1674+
err = mlxsw_sp_qevent_binding_configure(qevent_block,
1675+
qevent_binding,
1676+
extack);
16561677
if (err)
16571678
goto err_binding_configure;
16581679
}
@@ -1737,7 +1758,7 @@ static int mlxsw_sp_qevent_mall_replace(struct mlxsw_sp *mlxsw_sp,
17371758

17381759
list_add_tail(&mall_entry->list, &qevent_block->mall_entry_list);
17391760

1740-
err = mlxsw_sp_qevent_block_configure(qevent_block);
1761+
err = mlxsw_sp_qevent_block_configure(qevent_block, f->common.extack);
17411762
if (err)
17421763
goto err_block_configure;
17431764

@@ -1825,7 +1846,8 @@ static void mlxsw_sp_qevent_block_release(void *cb_priv)
18251846

18261847
static struct mlxsw_sp_qevent_binding *
18271848
mlxsw_sp_qevent_binding_create(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle, int tclass_num,
1828-
enum mlxsw_sp_span_trigger span_trigger)
1849+
enum mlxsw_sp_span_trigger span_trigger,
1850+
unsigned int action_mask)
18291851
{
18301852
struct mlxsw_sp_qevent_binding *binding;
18311853

@@ -1837,6 +1859,7 @@ mlxsw_sp_qevent_binding_create(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
18371859
binding->handle = handle;
18381860
binding->tclass_num = tclass_num;
18391861
binding->span_trigger = span_trigger;
1862+
binding->action_mask = action_mask;
18401863
return binding;
18411864
}
18421865

@@ -1862,9 +1885,11 @@ mlxsw_sp_qevent_binding_lookup(struct mlxsw_sp_qevent_block *block,
18621885
return NULL;
18631886
}
18641887

1865-
static int mlxsw_sp_setup_tc_block_qevent_bind(struct mlxsw_sp_port *mlxsw_sp_port,
1866-
struct flow_block_offload *f,
1867-
enum mlxsw_sp_span_trigger span_trigger)
1888+
static int
1889+
mlxsw_sp_setup_tc_block_qevent_bind(struct mlxsw_sp_port *mlxsw_sp_port,
1890+
struct flow_block_offload *f,
1891+
enum mlxsw_sp_span_trigger span_trigger,
1892+
unsigned int action_mask)
18681893
{
18691894
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
18701895
struct mlxsw_sp_qevent_binding *qevent_binding;
@@ -1904,14 +1929,18 @@ static int mlxsw_sp_setup_tc_block_qevent_bind(struct mlxsw_sp_port *mlxsw_sp_po
19041929
goto err_binding_exists;
19051930
}
19061931

1907-
qevent_binding = mlxsw_sp_qevent_binding_create(mlxsw_sp_port, f->sch->handle,
1908-
qdisc->tclass_num, span_trigger);
1932+
qevent_binding = mlxsw_sp_qevent_binding_create(mlxsw_sp_port,
1933+
f->sch->handle,
1934+
qdisc->tclass_num,
1935+
span_trigger,
1936+
action_mask);
19091937
if (IS_ERR(qevent_binding)) {
19101938
err = PTR_ERR(qevent_binding);
19111939
goto err_binding_create;
19121940
}
19131941

1914-
err = mlxsw_sp_qevent_binding_configure(qevent_block, qevent_binding);
1942+
err = mlxsw_sp_qevent_binding_configure(qevent_block, qevent_binding,
1943+
f->extack);
19151944
if (err)
19161945
goto err_binding_configure;
19171946

@@ -1963,15 +1992,19 @@ static void mlxsw_sp_setup_tc_block_qevent_unbind(struct mlxsw_sp_port *mlxsw_sp
19631992
}
19641993
}
19651994

1966-
static int mlxsw_sp_setup_tc_block_qevent(struct mlxsw_sp_port *mlxsw_sp_port,
1967-
struct flow_block_offload *f,
1968-
enum mlxsw_sp_span_trigger span_trigger)
1995+
static int
1996+
mlxsw_sp_setup_tc_block_qevent(struct mlxsw_sp_port *mlxsw_sp_port,
1997+
struct flow_block_offload *f,
1998+
enum mlxsw_sp_span_trigger span_trigger,
1999+
unsigned int action_mask)
19692000
{
19702001
f->driver_block_list = &mlxsw_sp_qevent_block_cb_list;
19712002

19722003
switch (f->command) {
19732004
case FLOW_BLOCK_BIND:
1974-
return mlxsw_sp_setup_tc_block_qevent_bind(mlxsw_sp_port, f, span_trigger);
2005+
return mlxsw_sp_setup_tc_block_qevent_bind(mlxsw_sp_port, f,
2006+
span_trigger,
2007+
action_mask);
19752008
case FLOW_BLOCK_UNBIND:
19762009
mlxsw_sp_setup_tc_block_qevent_unbind(mlxsw_sp_port, f, span_trigger);
19772010
return 0;
@@ -1983,7 +2016,22 @@ static int mlxsw_sp_setup_tc_block_qevent(struct mlxsw_sp_port *mlxsw_sp_port,
19832016
int mlxsw_sp_setup_tc_block_qevent_early_drop(struct mlxsw_sp_port *mlxsw_sp_port,
19842017
struct flow_block_offload *f)
19852018
{
1986-
return mlxsw_sp_setup_tc_block_qevent(mlxsw_sp_port, f, MLXSW_SP_SPAN_TRIGGER_EARLY_DROP);
2019+
unsigned int action_mask = BIT(MLXSW_SP_MALL_ACTION_TYPE_MIRROR) |
2020+
BIT(MLXSW_SP_MALL_ACTION_TYPE_TRAP);
2021+
2022+
return mlxsw_sp_setup_tc_block_qevent(mlxsw_sp_port, f,
2023+
MLXSW_SP_SPAN_TRIGGER_EARLY_DROP,
2024+
action_mask);
2025+
}
2026+
2027+
int mlxsw_sp_setup_tc_block_qevent_mark(struct mlxsw_sp_port *mlxsw_sp_port,
2028+
struct flow_block_offload *f)
2029+
{
2030+
unsigned int action_mask = BIT(MLXSW_SP_MALL_ACTION_TYPE_MIRROR);
2031+
2032+
return mlxsw_sp_setup_tc_block_qevent(mlxsw_sp_port, f,
2033+
MLXSW_SP_SPAN_TRIGGER_ECN,
2034+
action_mask);
19872035
}
19882036

19892037
int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port)

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,22 @@ void mlxsw_sp_span_trigger_disable(struct mlxsw_sp_port *mlxsw_sp_port,
16501650
return trigger_entry->ops->disable(trigger_entry, mlxsw_sp_port, tc);
16511651
}
16521652

1653+
bool mlxsw_sp_span_trigger_is_ingress(enum mlxsw_sp_span_trigger trigger)
1654+
{
1655+
switch (trigger) {
1656+
case MLXSW_SP_SPAN_TRIGGER_INGRESS:
1657+
case MLXSW_SP_SPAN_TRIGGER_EARLY_DROP:
1658+
case MLXSW_SP_SPAN_TRIGGER_TAIL_DROP:
1659+
return true;
1660+
case MLXSW_SP_SPAN_TRIGGER_EGRESS:
1661+
case MLXSW_SP_SPAN_TRIGGER_ECN:
1662+
return false;
1663+
}
1664+
1665+
WARN_ON_ONCE(1);
1666+
return false;
1667+
}
1668+
16531669
static int mlxsw_sp1_span_init(struct mlxsw_sp *mlxsw_sp)
16541670
{
16551671
size_t arr_size = ARRAY_SIZE(mlxsw_sp1_span_entry_ops_arr);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ int mlxsw_sp_span_trigger_enable(struct mlxsw_sp_port *mlxsw_sp_port,
120120
enum mlxsw_sp_span_trigger trigger, u8 tc);
121121
void mlxsw_sp_span_trigger_disable(struct mlxsw_sp_port *mlxsw_sp_port,
122122
enum mlxsw_sp_span_trigger trigger, u8 tc);
123+
bool mlxsw_sp_span_trigger_is_ingress(enum mlxsw_sp_span_trigger trigger);
123124

124125
extern const struct mlxsw_sp_span_ops mlxsw_sp1_span_ops;
125126
extern const struct mlxsw_sp_span_ops mlxsw_sp2_span_ops;

0 commit comments

Comments
 (0)