Skip to content

Commit 8231bee

Browse files
committed
Merge branch 'mlxsw-SPAN-Support-routes-pointing-at-bridges'
Ido Schimmel says: ==================== mlxsw: SPAN: Support routes pointing at bridges Petr says: When mirroring to a gretap or ip6gretap netdevice, the route that directs the encapsulated packets can reference a bridge. In that case, in the software model, the packet is switched. Thus when offloading mirroring like that, take into consideration FDB, STP, PVID configured at the bridge, and whether that VLAN ID should be tagged on egress. Patch #1 introduces functions to get bridge PVID, VLAN flags and to look up an FDB entry. Patches #2 and #3 refactor some existing code and introduce a new accessor function. With patches #4 and #5 mlxsw calls mlxsw_sp_span_respin() on switchdev events as well. There is no impact yet, because bridge as an underlay device is still not allowed. That is implemented in patch #6, which uses the new interfaces to figure out on which one port the mirroring should be configured, and whether the mirrored packets should be VLAN-tagged and how. Changes from v2 to v3: - Rename the suite of bridge accessor function to br_vlan_get_pvid(), br_vlan_get_info() and br_fdb_find_port(). The _get bit is to avoid clashing with an existing static function. Changes from v1 to v2: - Change the suite of bridge accessor functions to br_vlan_pvid_rtnl(), br_vlan_info_rtnl(), br_fdb_find_port_rtnl(). ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 6df9346 + 946a11e commit 8231bee

File tree

10 files changed

+326
-36
lines changed

10 files changed

+326
-36
lines changed

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

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -441,29 +441,29 @@ static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
441441
mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
442442
}
443443

444-
int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
445-
u8 state)
444+
enum mlxsw_reg_spms_state mlxsw_sp_stp_spms_state(u8 state)
446445
{
447-
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
448-
enum mlxsw_reg_spms_state spms_state;
449-
char *spms_pl;
450-
int err;
451-
452446
switch (state) {
453447
case BR_STATE_FORWARDING:
454-
spms_state = MLXSW_REG_SPMS_STATE_FORWARDING;
455-
break;
448+
return MLXSW_REG_SPMS_STATE_FORWARDING;
456449
case BR_STATE_LEARNING:
457-
spms_state = MLXSW_REG_SPMS_STATE_LEARNING;
458-
break;
450+
return MLXSW_REG_SPMS_STATE_LEARNING;
459451
case BR_STATE_LISTENING: /* fall-through */
460452
case BR_STATE_DISABLED: /* fall-through */
461453
case BR_STATE_BLOCKING:
462-
spms_state = MLXSW_REG_SPMS_STATE_DISCARDING;
463-
break;
454+
return MLXSW_REG_SPMS_STATE_DISCARDING;
464455
default:
465456
BUG();
466457
}
458+
}
459+
460+
int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
461+
u8 state)
462+
{
463+
enum mlxsw_reg_spms_state spms_state = mlxsw_sp_stp_spms_state(state);
464+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
465+
char *spms_pl;
466+
int err;
467467

468468
spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL);
469469
if (!spms_pl)
@@ -3666,6 +3666,15 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
36663666
goto err_lag_init;
36673667
}
36683668

3669+
/* Initialize SPAN before router and switchdev, so that those components
3670+
* can call mlxsw_sp_span_respin().
3671+
*/
3672+
err = mlxsw_sp_span_init(mlxsw_sp);
3673+
if (err) {
3674+
dev_err(mlxsw_sp->bus_info->dev, "Failed to init span system\n");
3675+
goto err_span_init;
3676+
}
3677+
36693678
err = mlxsw_sp_switchdev_init(mlxsw_sp);
36703679
if (err) {
36713680
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n");
@@ -3684,15 +3693,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
36843693
goto err_afa_init;
36853694
}
36863695

3687-
err = mlxsw_sp_span_init(mlxsw_sp);
3688-
if (err) {
3689-
dev_err(mlxsw_sp->bus_info->dev, "Failed to init span system\n");
3690-
goto err_span_init;
3691-
}
3692-
3693-
/* Initialize router after SPAN is initialized, so that the FIB and
3694-
* neighbor event handlers can issue SPAN respin.
3695-
*/
36963696
err = mlxsw_sp_router_init(mlxsw_sp);
36973697
if (err) {
36983698
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize router\n");
@@ -3739,14 +3739,14 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
37393739
err_netdev_notifier:
37403740
mlxsw_sp_router_fini(mlxsw_sp);
37413741
err_router_init:
3742-
mlxsw_sp_span_fini(mlxsw_sp);
3743-
err_span_init:
37443742
mlxsw_sp_afa_fini(mlxsw_sp);
37453743
err_afa_init:
37463744
mlxsw_sp_counter_pool_fini(mlxsw_sp);
37473745
err_counter_pool_init:
37483746
mlxsw_sp_switchdev_fini(mlxsw_sp);
37493747
err_switchdev_init:
3748+
mlxsw_sp_span_fini(mlxsw_sp);
3749+
err_span_init:
37503750
mlxsw_sp_lag_fini(mlxsw_sp);
37513751
err_lag_init:
37523752
mlxsw_sp_buffers_fini(mlxsw_sp);
@@ -3768,10 +3768,10 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
37683768
mlxsw_sp_acl_fini(mlxsw_sp);
37693769
unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
37703770
mlxsw_sp_router_fini(mlxsw_sp);
3771-
mlxsw_sp_span_fini(mlxsw_sp);
37723771
mlxsw_sp_afa_fini(mlxsw_sp);
37733772
mlxsw_sp_counter_pool_fini(mlxsw_sp);
37743773
mlxsw_sp_switchdev_fini(mlxsw_sp);
3774+
mlxsw_sp_span_fini(mlxsw_sp);
37753775
mlxsw_sp_lag_fini(mlxsw_sp);
37763776
mlxsw_sp_buffers_fini(mlxsw_sp);
37773777
mlxsw_sp_traps_fini(mlxsw_sp);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
364364
int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port,
365365
enum mlxsw_reg_qeec_hr hr, u8 index,
366366
u8 next_index, u32 maxrate);
367+
enum mlxsw_reg_spms_state mlxsw_sp_stp_spms_state(u8 stp_state);
367368
int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
368369
u8 state);
369370
int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable);

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

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,17 @@
3232
* POSSIBILITY OF SUCH DAMAGE.
3333
*/
3434

35+
#include <linux/if_bridge.h>
3536
#include <linux/list.h>
3637
#include <net/arp.h>
3738
#include <net/gre.h>
3839
#include <net/ndisc.h>
3940
#include <net/ip6_tunnel.h>
4041

4142
#include "spectrum.h"
42-
#include "spectrum_span.h"
4343
#include "spectrum_ipip.h"
44+
#include "spectrum_span.h"
45+
#include "spectrum_switchdev.h"
4446

4547
int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
4648
{
@@ -167,6 +169,72 @@ mlxsw_sp_span_entry_unoffloadable(struct mlxsw_sp_span_parms *sparmsp)
167169
return 0;
168170
}
169171

172+
static struct net_device *
173+
mlxsw_sp_span_entry_bridge_8021q(const struct net_device *br_dev,
174+
unsigned char *dmac,
175+
u16 *p_vid)
176+
{
177+
struct bridge_vlan_info vinfo;
178+
struct net_device *edev;
179+
u16 pvid;
180+
181+
if (WARN_ON(br_vlan_get_pvid(br_dev, &pvid)))
182+
return NULL;
183+
if (!pvid)
184+
return NULL;
185+
186+
edev = br_fdb_find_port(br_dev, dmac, pvid);
187+
if (!edev)
188+
return NULL;
189+
190+
if (br_vlan_get_info(edev, pvid, &vinfo))
191+
return NULL;
192+
if (!(vinfo.flags & BRIDGE_VLAN_INFO_UNTAGGED))
193+
*p_vid = pvid;
194+
return edev;
195+
}
196+
197+
static struct net_device *
198+
mlxsw_sp_span_entry_bridge_8021d(const struct net_device *br_dev,
199+
unsigned char *dmac)
200+
{
201+
return br_fdb_find_port(br_dev, dmac, 0);
202+
}
203+
204+
static struct net_device *
205+
mlxsw_sp_span_entry_bridge(const struct net_device *br_dev,
206+
unsigned char dmac[ETH_ALEN],
207+
u16 *p_vid)
208+
{
209+
struct mlxsw_sp_bridge_port *bridge_port;
210+
enum mlxsw_reg_spms_state spms_state;
211+
struct mlxsw_sp_port *port;
212+
struct net_device *dev;
213+
u8 stp_state;
214+
215+
if (br_vlan_enabled(br_dev))
216+
dev = mlxsw_sp_span_entry_bridge_8021q(br_dev, dmac, p_vid);
217+
else
218+
dev = mlxsw_sp_span_entry_bridge_8021d(br_dev, dmac);
219+
if (!dev)
220+
return NULL;
221+
222+
port = mlxsw_sp_port_dev_lower_find(dev);
223+
if (!port)
224+
return NULL;
225+
226+
bridge_port = mlxsw_sp_bridge_port_find(port->mlxsw_sp->bridge, dev);
227+
if (!bridge_port)
228+
return NULL;
229+
230+
stp_state = mlxsw_sp_bridge_port_stp_state(bridge_port);
231+
spms_state = mlxsw_sp_stp_spms_state(stp_state);
232+
if (spms_state != MLXSW_REG_SPMS_STATE_FORWARDING)
233+
return NULL;
234+
235+
return dev;
236+
}
237+
170238
static __maybe_unused int
171239
mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *l3edev,
172240
union mlxsw_sp_l3addr saddr,
@@ -177,21 +245,34 @@ mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *l3edev,
177245
struct mlxsw_sp_span_parms *sparmsp)
178246
{
179247
unsigned char dmac[ETH_ALEN];
248+
u16 vid = 0;
180249

181250
if (mlxsw_sp_l3addr_is_zero(gw))
182251
gw = daddr;
183252

184-
if (!l3edev || !mlxsw_sp_port_dev_check(l3edev) ||
185-
mlxsw_sp_span_dmac(tbl, &gw, l3edev, dmac))
186-
return mlxsw_sp_span_entry_unoffloadable(sparmsp);
253+
if (!l3edev || mlxsw_sp_span_dmac(tbl, &gw, l3edev, dmac))
254+
goto unoffloadable;
255+
256+
if (netif_is_bridge_master(l3edev)) {
257+
l3edev = mlxsw_sp_span_entry_bridge(l3edev, dmac, &vid);
258+
if (!l3edev)
259+
goto unoffloadable;
260+
}
261+
262+
if (!mlxsw_sp_port_dev_check(l3edev))
263+
goto unoffloadable;
187264

188265
sparmsp->dest_port = netdev_priv(l3edev);
189266
sparmsp->ttl = ttl;
190267
memcpy(sparmsp->dmac, dmac, ETH_ALEN);
191268
memcpy(sparmsp->smac, l3edev->dev_addr, ETH_ALEN);
192269
sparmsp->saddr = saddr;
193270
sparmsp->daddr = daddr;
271+
sparmsp->vid = vid;
194272
return 0;
273+
274+
unoffloadable:
275+
return mlxsw_sp_span_entry_unoffloadable(sparmsp);
195276
}
196277

197278
#if IS_ENABLED(CONFIG_NET_IPGRE)
@@ -268,9 +349,10 @@ mlxsw_sp_span_entry_gretap4_configure(struct mlxsw_sp_span_entry *span_entry,
268349
/* Create a new port analayzer entry for local_port. */
269350
mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
270351
MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
352+
mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
271353
mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
272354
MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
273-
sparms.dmac, false);
355+
sparms.dmac, !!sparms.vid);
274356
mlxsw_reg_mpat_eth_rspan_l3_ipv4_pack(mpat_pl,
275357
sparms.ttl, sparms.smac,
276358
be32_to_cpu(sparms.saddr.addr4),
@@ -368,9 +450,10 @@ mlxsw_sp_span_entry_gretap6_configure(struct mlxsw_sp_span_entry *span_entry,
368450
/* Create a new port analayzer entry for local_port. */
369451
mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
370452
MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
453+
mlxsw_reg_mpat_eth_rspan_pack(mpat_pl, sparms.vid);
371454
mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
372455
MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
373-
sparms.dmac, false);
456+
sparms.dmac, !!sparms.vid);
374457
mlxsw_reg_mpat_eth_rspan_l3_ipv6_pack(mpat_pl, sparms.ttl, sparms.smac,
375458
sparms.saddr.addr6,
376459
sparms.daddr.addr6);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct mlxsw_sp_span_parms {
6363
unsigned char smac[ETH_ALEN];
6464
union mlxsw_sp_l3addr daddr;
6565
union mlxsw_sp_l3addr saddr;
66+
u16 vid;
6667
};
6768

6869
struct mlxsw_sp_span_entry_ops;

0 commit comments

Comments
 (0)