Skip to content

Commit 2d93c30

Browse files
committed
Merge branch 'mlxsw-redirection'
Petr Machata says: ==================== mlxsw: Support traffic redirection from a locked bridge port Ido Schimmel writes: It is possible to add a filter that redirects traffic from the ingress of a bridge port that is locked (i.e., performs security / SMAC lookup) and has learning enabled. For example: # ip link add name br0 type bridge # ip link set dev swp1 master br0 # bridge link set dev swp1 learning on locked on mab on # tc qdisc add dev swp1 clsact # tc filter add dev swp1 ingress pref 1 proto ip flower skip_sw src_ip 192.0.2.1 action mirred egress redirect dev swp2 In the kernel's Rx path, this filter is evaluated before the Rx handler of the bridge, which means that redirected traffic should not be affected by bridge port configuration such as learning. However, the hardware data path is a bit different and the redirect action (FORWARDING_ACTION in hardware) merely attaches a pointer to the packet, which is later used by the L2 lookup stage to understand how to forward the packet. Between both stages - ingress ACL and L2 lookup - learning and security lookup are performed, which means that redirected traffic is affected by bridge port configuration, unlike in the kernel's data path. The learning discrepancy was handled in commit 577fa14 ("mlxsw: spectrum: Do not process learned records with a dummy FID") by simply ignoring learning notifications generated by the redirected traffic. A similar solution is not possible for the security / SMAC lookup since - unlike learning - the CPU is not involved and packets that failed the lookup are dropped by the device. Instead, solve this by prepending the ignore action to the redirect action and use it to instruct the device to disable both learning and the security / SMAC lookup for redirected traffic. Patch #1 adds the ignore action. Patch #2 prepends the action to the redirect action in flower offload code. Patch #3 removes the workaround in commit 577fa14 ("mlxsw: spectrum: Do not process learned records with a dummy FID") since it is no longer needed. Patch #4 adds a test case. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 58c1e0b + 38c43a1 commit 2d93c30

File tree

8 files changed

+100
-17
lines changed

8 files changed

+100
-17
lines changed

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,46 @@ int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid,
18871887
}
18881888
EXPORT_SYMBOL(mlxsw_afa_block_append_fid_set);
18891889

1890+
/* Ignore Action
1891+
* -------------
1892+
* The ignore action is used to ignore basic switching functions such as
1893+
* learning on a per-packet basis.
1894+
*/
1895+
1896+
#define MLXSW_AFA_IGNORE_CODE 0x0F
1897+
#define MLXSW_AFA_IGNORE_SIZE 1
1898+
1899+
/* afa_ignore_disable_learning
1900+
* Disable learning on ingress.
1901+
*/
1902+
MLXSW_ITEM32(afa, ignore, disable_learning, 0x00, 29, 1);
1903+
1904+
/* afa_ignore_disable_security
1905+
* Disable security lookup on ingress.
1906+
* Reserved when Spectrum-1.
1907+
*/
1908+
MLXSW_ITEM32(afa, ignore, disable_security, 0x00, 28, 1);
1909+
1910+
static void mlxsw_afa_ignore_pack(char *payload, bool disable_learning,
1911+
bool disable_security)
1912+
{
1913+
mlxsw_afa_ignore_disable_learning_set(payload, disable_learning);
1914+
mlxsw_afa_ignore_disable_security_set(payload, disable_security);
1915+
}
1916+
1917+
int mlxsw_afa_block_append_ignore(struct mlxsw_afa_block *block,
1918+
bool disable_learning, bool disable_security)
1919+
{
1920+
char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_IGNORE_CODE,
1921+
MLXSW_AFA_IGNORE_SIZE);
1922+
1923+
if (IS_ERR(act))
1924+
return PTR_ERR(act);
1925+
mlxsw_afa_ignore_pack(act, disable_learning, disable_security);
1926+
return 0;
1927+
}
1928+
EXPORT_SYMBOL(mlxsw_afa_block_append_ignore);
1929+
18901930
/* MC Routing Action
18911931
* -----------------
18921932
* The Multicast router action. Can be used by RMFT_V2 - Router Multicast

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,
8989
struct netlink_ext_ack *extack);
9090
int mlxsw_afa_block_append_fid_set(struct mlxsw_afa_block *block, u16 fid,
9191
struct netlink_ext_ack *extack);
92+
int mlxsw_afa_block_append_ignore(struct mlxsw_afa_block *block,
93+
bool disable_learning, bool disable_security);
9294
int mlxsw_afa_block_append_mcrouter(struct mlxsw_afa_block *block,
9395
u16 expected_irif, u16 min_mtu,
9496
bool rmid_valid, u32 kvdl_index);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,9 @@ int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
10501050
int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp,
10511051
struct mlxsw_sp_acl_rule_info *rulei,
10521052
u16 fid, struct netlink_ext_ack *extack);
1053+
int mlxsw_sp_acl_rulei_act_ignore(struct mlxsw_sp *mlxsw_sp,
1054+
struct mlxsw_sp_acl_rule_info *rulei,
1055+
bool disable_learning, bool disable_security);
10531056
int mlxsw_sp_acl_rulei_act_sample(struct mlxsw_sp *mlxsw_sp,
10541057
struct mlxsw_sp_acl_rule_info *rulei,
10551058
struct mlxsw_sp_flow_block *block,
@@ -1268,7 +1271,6 @@ int mlxsw_sp_setup_tc_block_qevent_mark(struct mlxsw_sp_port *mlxsw_sp_port,
12681271
struct flow_block_offload *f);
12691272

12701273
/* spectrum_fid.c */
1271-
bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index);
12721274
struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
12731275
u16 fid_index);
12741276
int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex);

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,15 @@ int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp,
775775
return mlxsw_afa_block_append_fid_set(rulei->act_block, fid, extack);
776776
}
777777

778+
int mlxsw_sp_acl_rulei_act_ignore(struct mlxsw_sp *mlxsw_sp,
779+
struct mlxsw_sp_acl_rule_info *rulei,
780+
bool disable_learning, bool disable_security)
781+
{
782+
return mlxsw_afa_block_append_ignore(rulei->act_block,
783+
disable_learning,
784+
disable_security);
785+
}
786+
778787
int mlxsw_sp_acl_rulei_act_sample(struct mlxsw_sp *mlxsw_sp,
779788
struct mlxsw_sp_acl_rule_info *rulei,
780789
struct mlxsw_sp_flow_block *block,

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,6 @@ static const int *mlxsw_sp_packet_type_sfgc_types[] = {
137137
[MLXSW_SP_FLOOD_TYPE_MC] = mlxsw_sp_sfgc_mc_packet_types,
138138
};
139139

140-
bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
141-
{
142-
enum mlxsw_sp_fid_type fid_type = MLXSW_SP_FID_TYPE_DUMMY;
143-
struct mlxsw_sp_fid_family *fid_family;
144-
145-
fid_family = mlxsw_sp->fid_core->fid_family_arr[fid_type];
146-
147-
return fid_family->start_index == fid_index;
148-
}
149-
150140
struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
151141
u16 fid_index)
152142
{

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
160160
*/
161161
rulei->egress_bind_blocker = 1;
162162

163+
/* Ignore learning and security lookup as redirection
164+
* using ingress filters happens before the bridge.
165+
*/
166+
err = mlxsw_sp_acl_rulei_act_ignore(mlxsw_sp, rulei,
167+
true, true);
168+
if (err) {
169+
NL_SET_ERR_MSG_MOD(extack, "Cannot append ignore action");
170+
return err;
171+
}
172+
163173
fid = mlxsw_sp_acl_dummy_fid(mlxsw_sp);
164174
fid_index = mlxsw_sp_fid_index(fid);
165175
err = mlxsw_sp_acl_rulei_act_fid_set(mlxsw_sp, rulei,

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3066,9 +3066,6 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
30663066
goto just_remove;
30673067
}
30683068

3069-
if (mlxsw_sp_fid_is_dummy(mlxsw_sp, fid))
3070-
goto just_remove;
3071-
30723069
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_fid(mlxsw_sp_port, fid);
30733070
if (!mlxsw_sp_port_vlan) {
30743071
netdev_err(mlxsw_sp_port->dev, "Failed to find a matching {Port, VID} following FDB notification\n");
@@ -3136,9 +3133,6 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
31363133
goto just_remove;
31373134
}
31383135

3139-
if (mlxsw_sp_fid_is_dummy(mlxsw_sp, fid))
3140-
goto just_remove;
3141-
31423136
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_fid(mlxsw_sp_port, fid);
31433137
if (!mlxsw_sp_port_vlan) {
31443138
netdev_err(mlxsw_sp_port->dev, "Failed to find a matching {Port, VID} following FDB notification\n");

tools/testing/selftests/net/forwarding/bridge_locked_port.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ ALL_TESTS="
99
locked_port_mab_roam
1010
locked_port_mab_config
1111
locked_port_mab_flush
12+
locked_port_mab_redirect
1213
"
1314

1415
NUM_NETIFS=4
@@ -319,6 +320,41 @@ locked_port_mab_flush()
319320
log_test "Locked port MAB FDB flush"
320321
}
321322

323+
# Check that traffic can be redirected from a locked bridge port and that it
324+
# does not create locked FDB entries.
325+
locked_port_mab_redirect()
326+
{
327+
RET=0
328+
check_port_mab_support || return 0
329+
330+
bridge link set dev $swp1 learning on locked on mab on
331+
tc qdisc add dev $swp1 clsact
332+
tc filter add dev $swp1 ingress protocol all pref 1 handle 101 flower \
333+
action mirred egress redirect dev $swp2
334+
335+
ping_do $h1 192.0.2.2
336+
check_err $? "Ping did not work with redirection"
337+
338+
bridge fdb get `mac_get $h1` br br0 vlan 1 2> /dev/null | \
339+
grep "dev $swp1" | grep -q "locked"
340+
check_fail $? "Locked entry created for redirected traffic"
341+
342+
tc filter del dev $swp1 ingress protocol all pref 1 handle 101 flower
343+
344+
ping_do $h1 192.0.2.2
345+
check_fail $? "Ping worked without redirection"
346+
347+
bridge fdb get `mac_get $h1` br br0 vlan 1 2> /dev/null | \
348+
grep "dev $swp1" | grep -q "locked"
349+
check_err $? "Locked entry not created after deleting filter"
350+
351+
bridge fdb del `mac_get $h1` vlan 1 dev $swp1 master
352+
tc qdisc del dev $swp1 clsact
353+
bridge link set dev $swp1 learning off locked off mab off
354+
355+
log_test "Locked port MAB redirect"
356+
}
357+
322358
trap cleanup EXIT
323359

324360
setup_prepare

0 commit comments

Comments
 (0)