Commit 930a3a62 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-vlan-=vxlan'

mlxsw: Allow 802.1d and .1ad VxLAN bridges to coexist on Spectrum>=2
Ido Schimmel says:

====================
This patchset allows user space to simultaneously configure both 802.1d
and 802.1ad VxLAN bridges on Spectrum-2 and later ASICs. 802.1ad VxLAN
bridges are still forbidden on Spectrum-1.

The reason for the current limitation is that up until now the EtherType
that was pushed to decapsulated VxLAN packets was a property of the
tunnel port, of which there is only one. This meant that a 802.1ad VxLAN
bridge could not be configured if the tunnel port was already configured
to push a 802.1q tag.

This patchset improves the situation by making two changes. First,
decapsulated packets are marked as having their EtherType decided by the
egress port. Second, local ports member in the bridge (e.g., swp1) are
configured to set the correct egress EtherType.

Patchset overview:

Patch #1 adds a register required for the first change

Patches #2-#3 add the register required for the second change and a
corresponding API

Patch #4 prepares the driver for the split in behavior between
Spectrum-1 and later ASICs

Patch #5 performs the two above mentioned changes to allow the driver to
support simultaneous 802.1ad and 802.1d VxLAN bridges on Spectrum-2 and
later ASICs

Patch #6 adds a selftest

Patch #7 removes a selftest that verified the limitation that was lifted
by this patchset
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 07bcf685 1724c97d
...@@ -842,6 +842,14 @@ MLXSW_ITEM32(reg, spvid, local_port, 0x00, 16, 8); ...@@ -842,6 +842,14 @@ MLXSW_ITEM32(reg, spvid, local_port, 0x00, 16, 8);
*/ */
MLXSW_ITEM32(reg, spvid, sub_port, 0x00, 8, 8); MLXSW_ITEM32(reg, spvid, sub_port, 0x00, 8, 8);
/* reg_spvid_egr_et_set
* When VLAN is pushed at ingress (for untagged packets or for
* QinQ push mode) then the EtherType is decided at the egress port.
* Reserved when Spectrum-1.
* Access: RW
*/
MLXSW_ITEM32(reg, spvid, egr_et_set, 0x04, 24, 1);
/* reg_spvid_et_vlan /* reg_spvid_et_vlan
* EtherType used for when VLAN is pushed at ingress (for untagged * EtherType used for when VLAN is pushed at ingress (for untagged
* packets or for QinQ push mode). * packets or for QinQ push mode).
...@@ -849,6 +857,7 @@ MLXSW_ITEM32(reg, spvid, sub_port, 0x00, 8, 8); ...@@ -849,6 +857,7 @@ MLXSW_ITEM32(reg, spvid, sub_port, 0x00, 8, 8);
* 1: ether_type1 * 1: ether_type1
* 2: ether_type2 - Reserved when Spectrum-1, supported by Spectrum-2 * 2: ether_type2 - Reserved when Spectrum-1, supported by Spectrum-2
* Ethertype IDs are configured by SVER. * Ethertype IDs are configured by SVER.
* Reserved when egr_et_set = 1.
* Access: RW * Access: RW
*/ */
MLXSW_ITEM32(reg, spvid, et_vlan, 0x04, 16, 2); MLXSW_ITEM32(reg, spvid, et_vlan, 0x04, 16, 2);
...@@ -2079,6 +2088,41 @@ static inline void mlxsw_reg_spvc_pack(char *payload, u8 local_port, bool et1, ...@@ -2079,6 +2088,41 @@ static inline void mlxsw_reg_spvc_pack(char *payload, u8 local_port, bool et1,
mlxsw_reg_spvc_et0_set(payload, et0); mlxsw_reg_spvc_et0_set(payload, et0);
} }
/* SPEVET - Switch Port Egress VLAN EtherType
* ------------------------------------------
* The switch port egress VLAN EtherType configures which EtherType to push at
* egress for packets incoming through a local port for which 'SPVID.egr_et_set'
* is set.
*/
#define MLXSW_REG_SPEVET_ID 0x202A
#define MLXSW_REG_SPEVET_LEN 0x08
MLXSW_REG_DEFINE(spevet, MLXSW_REG_SPEVET_ID, MLXSW_REG_SPEVET_LEN);
/* reg_spevet_local_port
* Egress Local port number.
* Not supported to CPU port.
* Access: Index
*/
MLXSW_ITEM32(reg, spevet, local_port, 0x00, 16, 8);
/* reg_spevet_et_vlan
* Egress EtherType VLAN to push when SPVID.egr_et_set field set for the packet:
* 0: ether_type0 - (default)
* 1: ether_type1
* 2: ether_type2
* Access: RW
*/
MLXSW_ITEM32(reg, spevet, et_vlan, 0x04, 16, 2);
static inline void mlxsw_reg_spevet_pack(char *payload, u8 local_port,
u8 et_vlan)
{
MLXSW_REG_ZERO(spevet, payload);
mlxsw_reg_spevet_local_port_set(payload, local_port);
mlxsw_reg_spevet_et_vlan_set(payload, et_vlan);
}
/* CWTP - Congetion WRED ECN TClass Profile /* CWTP - Congetion WRED ECN TClass Profile
* ---------------------------------------- * ----------------------------------------
* Configures the profiles for queues of egress port and traffic class * Configures the profiles for queues of egress port and traffic class
...@@ -12017,6 +12061,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { ...@@ -12017,6 +12061,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(sfmr), MLXSW_REG(sfmr),
MLXSW_REG(spvmlr), MLXSW_REG(spvmlr),
MLXSW_REG(spvc), MLXSW_REG(spvc),
MLXSW_REG(spevet),
MLXSW_REG(cwtp), MLXSW_REG(cwtp),
MLXSW_REG(cwtpm), MLXSW_REG(cwtpm),
MLXSW_REG(pgcr), MLXSW_REG(pgcr),
......
...@@ -402,6 +402,22 @@ int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type) ...@@ -402,6 +402,22 @@ int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type)
return 0; return 0;
} }
int mlxsw_sp_port_egress_ethtype_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 ethtype)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char spevet_pl[MLXSW_REG_SPEVET_LEN];
u8 sver_type;
int err;
err = mlxsw_sp_ethtype_to_sver_type(ethtype, &sver_type);
if (err)
return err;
mlxsw_reg_spevet_pack(spevet_pl, mlxsw_sp_port->local_port, sver_type);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spevet), spevet_pl);
}
static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 vid, u16 ethtype) u16 vid, u16 ethtype)
{ {
...@@ -2909,6 +2925,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core, ...@@ -2909,6 +2925,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
mlxsw_sp->switchdev_ops = &mlxsw_sp1_switchdev_ops;
mlxsw_sp->kvdl_ops = &mlxsw_sp1_kvdl_ops; mlxsw_sp->kvdl_ops = &mlxsw_sp1_kvdl_ops;
mlxsw_sp->afa_ops = &mlxsw_sp1_act_afa_ops; mlxsw_sp->afa_ops = &mlxsw_sp1_act_afa_ops;
mlxsw_sp->afk_ops = &mlxsw_sp1_afk_ops; mlxsw_sp->afk_ops = &mlxsw_sp1_afk_ops;
...@@ -2939,6 +2956,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, ...@@ -2939,6 +2956,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
mlxsw_sp->switchdev_ops = &mlxsw_sp2_switchdev_ops;
mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops; mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops; mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops; mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
...@@ -2967,6 +2985,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core, ...@@ -2967,6 +2985,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
mlxsw_sp->switchdev_ops = &mlxsw_sp2_switchdev_ops;
mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops; mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops; mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops; mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
......
...@@ -92,6 +92,11 @@ struct mlxsw_sp_rif_ops; ...@@ -92,6 +92,11 @@ struct mlxsw_sp_rif_ops;
extern const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[]; extern const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[];
extern const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[]; extern const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[];
struct mlxsw_sp_switchdev_ops;
extern const struct mlxsw_sp_switchdev_ops mlxsw_sp1_switchdev_ops;
extern const struct mlxsw_sp_switchdev_ops mlxsw_sp2_switchdev_ops;
enum mlxsw_sp_fid_type { enum mlxsw_sp_fid_type {
MLXSW_SP_FID_TYPE_8021Q, MLXSW_SP_FID_TYPE_8021Q,
MLXSW_SP_FID_TYPE_8021D, MLXSW_SP_FID_TYPE_8021D,
...@@ -167,6 +172,7 @@ struct mlxsw_sp { ...@@ -167,6 +172,7 @@ struct mlxsw_sp {
struct mlxsw_sp_counter_pool *counter_pool; struct mlxsw_sp_counter_pool *counter_pool;
struct mlxsw_sp_span *span; struct mlxsw_sp_span *span;
struct mlxsw_sp_trap *trap; struct mlxsw_sp_trap *trap;
const struct mlxsw_sp_switchdev_ops *switchdev_ops;
const struct mlxsw_sp_kvdl_ops *kvdl_ops; const struct mlxsw_sp_kvdl_ops *kvdl_ops;
const struct mlxsw_afa_ops *afa_ops; const struct mlxsw_afa_ops *afa_ops;
const struct mlxsw_afk_ops *afk_ops; const struct mlxsw_afk_ops *afk_ops;
...@@ -609,6 +615,8 @@ int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable); ...@@ -609,6 +615,8 @@ int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable);
int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
bool learn_enable); bool learn_enable);
int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type); int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type);
int mlxsw_sp_port_egress_ethtype_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 ethtype);
int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
u16 ethtype); u16 ethtype);
struct mlxsw_sp_port_vlan * struct mlxsw_sp_port_vlan *
......
...@@ -18,7 +18,6 @@ struct mlxsw_sp_nve_config { ...@@ -18,7 +18,6 @@ struct mlxsw_sp_nve_config {
u32 ul_tb_id; u32 ul_tb_id;
enum mlxsw_sp_l3proto ul_proto; enum mlxsw_sp_l3proto ul_proto;
union mlxsw_sp_l3addr ul_sip; union mlxsw_sp_l3addr ul_sip;
u16 ethertype;
}; };
struct mlxsw_sp_nve { struct mlxsw_sp_nve {
......
...@@ -113,7 +113,6 @@ static void mlxsw_sp_nve_vxlan_config(const struct mlxsw_sp_nve *nve, ...@@ -113,7 +113,6 @@ static void mlxsw_sp_nve_vxlan_config(const struct mlxsw_sp_nve *nve,
config->ul_proto = MLXSW_SP_L3_PROTO_IPV4; config->ul_proto = MLXSW_SP_L3_PROTO_IPV4;
config->ul_sip.addr4 = cfg->saddr.sin.sin_addr.s_addr; config->ul_sip.addr4 = cfg->saddr.sin.sin_addr.s_addr;
config->udp_dport = cfg->dst_port; config->udp_dport = cfg->dst_port;
config->ethertype = params->ethertype;
} }
static int __mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp, static int __mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
...@@ -318,20 +317,14 @@ static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp, ...@@ -318,20 +317,14 @@ static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp,
} }
static int static int
mlxsw_sp2_nve_decap_ethertype_set(struct mlxsw_sp *mlxsw_sp, u16 ethertype) mlxsw_sp2_nve_decap_ethertype_set(struct mlxsw_sp *mlxsw_sp)
{ {
char spvid_pl[MLXSW_REG_SPVID_LEN] = {}; char spvid_pl[MLXSW_REG_SPVID_LEN] = {};
u8 sver_type;
int err;
mlxsw_reg_spvid_tport_set(spvid_pl, true); mlxsw_reg_spvid_tport_set(spvid_pl, true);
mlxsw_reg_spvid_local_port_set(spvid_pl, mlxsw_reg_spvid_local_port_set(spvid_pl,
MLXSW_REG_TUNNEL_PORT_NVE); MLXSW_REG_TUNNEL_PORT_NVE);
err = mlxsw_sp_ethtype_to_sver_type(ethertype, &sver_type); mlxsw_reg_spvid_egr_et_set_set(spvid_pl, true);
if (err)
return err;
mlxsw_reg_spvid_et_vlan_set(spvid_pl, sver_type);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl);
} }
...@@ -367,7 +360,7 @@ mlxsw_sp2_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp, ...@@ -367,7 +360,7 @@ mlxsw_sp2_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp,
if (err) if (err)
goto err_spvtr_write; goto err_spvtr_write;
err = mlxsw_sp2_nve_decap_ethertype_set(mlxsw_sp, config->ethertype); err = mlxsw_sp2_nve_decap_ethertype_set(mlxsw_sp);
if (err) if (err)
goto err_decap_ethertype_set; goto err_decap_ethertype_set;
...@@ -392,8 +385,6 @@ static void mlxsw_sp2_nve_vxlan_config_clear(struct mlxsw_sp *mlxsw_sp) ...@@ -392,8 +385,6 @@ static void mlxsw_sp2_nve_vxlan_config_clear(struct mlxsw_sp *mlxsw_sp)
char spvtr_pl[MLXSW_REG_SPVTR_LEN]; char spvtr_pl[MLXSW_REG_SPVTR_LEN];
char tngcr_pl[MLXSW_REG_TNGCR_LEN]; char tngcr_pl[MLXSW_REG_TNGCR_LEN];
/* Set default EtherType */
mlxsw_sp2_nve_decap_ethertype_set(mlxsw_sp, ETH_P_8021Q);
mlxsw_reg_spvtr_pack(spvtr_pl, true, MLXSW_REG_TUNNEL_PORT_NVE, mlxsw_reg_spvtr_pack(spvtr_pl, true, MLXSW_REG_TUNNEL_PORT_NVE,
MLXSW_REG_SPVTR_IPVID_MODE_IEEE_COMPLIANT_PVID); MLXSW_REG_SPVTR_IPVID_MODE_IEEE_COMPLIANT_PVID);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvtr), spvtr_pl); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvtr), spvtr_pl);
......
...@@ -98,6 +98,10 @@ struct mlxsw_sp_bridge_ops { ...@@ -98,6 +98,10 @@ struct mlxsw_sp_bridge_ops {
const struct mlxsw_sp_fid *fid); const struct mlxsw_sp_fid *fid);
}; };
struct mlxsw_sp_switchdev_ops {
void (*init)(struct mlxsw_sp *mlxsw_sp);
};
static int static int
mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_bridge_port *bridge_port, struct mlxsw_sp_bridge_port *bridge_port,
...@@ -2296,7 +2300,7 @@ mlxsw_sp_bridge_8021ad_vxlan_join(struct mlxsw_sp_bridge_device *bridge_device, ...@@ -2296,7 +2300,7 @@ mlxsw_sp_bridge_8021ad_vxlan_join(struct mlxsw_sp_bridge_device *bridge_device,
vid, ETH_P_8021AD, extack); vid, ETH_P_8021AD, extack);
} }
static const struct mlxsw_sp_bridge_ops mlxsw_sp_bridge_8021ad_ops = { static const struct mlxsw_sp_bridge_ops mlxsw_sp1_bridge_8021ad_ops = {
.port_join = mlxsw_sp_bridge_8021ad_port_join, .port_join = mlxsw_sp_bridge_8021ad_port_join,
.port_leave = mlxsw_sp_bridge_8021ad_port_leave, .port_leave = mlxsw_sp_bridge_8021ad_port_leave,
.vxlan_join = mlxsw_sp_bridge_8021ad_vxlan_join, .vxlan_join = mlxsw_sp_bridge_8021ad_vxlan_join,
...@@ -2305,6 +2309,53 @@ static const struct mlxsw_sp_bridge_ops mlxsw_sp_bridge_8021ad_ops = { ...@@ -2305,6 +2309,53 @@ static const struct mlxsw_sp_bridge_ops mlxsw_sp_bridge_8021ad_ops = {
.fid_vid = mlxsw_sp_bridge_8021q_fid_vid, .fid_vid = mlxsw_sp_bridge_8021q_fid_vid,
}; };
static int
mlxsw_sp2_bridge_8021ad_port_join(struct mlxsw_sp_bridge_device *bridge_device,
struct mlxsw_sp_bridge_port *bridge_port,
struct mlxsw_sp_port *mlxsw_sp_port,
struct netlink_ext_ack *extack)
{
int err;
/* The EtherType of decapsulated packets is determined at the egress
* port to allow 802.1d and 802.1ad bridges with VXLAN devices to
* co-exist.
*/
err = mlxsw_sp_port_egress_ethtype_set(mlxsw_sp_port, ETH_P_8021AD);
if (err)
return err;
err = mlxsw_sp_bridge_8021ad_port_join(bridge_device, bridge_port,
mlxsw_sp_port, extack);
if (err)
goto err_bridge_8021ad_port_join;
return 0;
err_bridge_8021ad_port_join:
mlxsw_sp_port_egress_ethtype_set(mlxsw_sp_port, ETH_P_8021Q);
return err;
}
static void
mlxsw_sp2_bridge_8021ad_port_leave(struct mlxsw_sp_bridge_device *bridge_device,
struct mlxsw_sp_bridge_port *bridge_port,
struct mlxsw_sp_port *mlxsw_sp_port)
{
mlxsw_sp_bridge_8021ad_port_leave(bridge_device, bridge_port,
mlxsw_sp_port);
mlxsw_sp_port_egress_ethtype_set(mlxsw_sp_port, ETH_P_8021Q);
}
static const struct mlxsw_sp_bridge_ops mlxsw_sp2_bridge_8021ad_ops = {
.port_join = mlxsw_sp2_bridge_8021ad_port_join,
.port_leave = mlxsw_sp2_bridge_8021ad_port_leave,
.vxlan_join = mlxsw_sp_bridge_8021ad_vxlan_join,
.fid_get = mlxsw_sp_bridge_8021q_fid_get,
.fid_lookup = mlxsw_sp_bridge_8021q_fid_lookup,
.fid_vid = mlxsw_sp_bridge_8021q_fid_vid,
};
int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port, int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *brport_dev, struct net_device *brport_dev,
struct net_device *br_dev, struct net_device *br_dev,
...@@ -3535,6 +3586,24 @@ static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp) ...@@ -3535,6 +3586,24 @@ static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier); unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
} }
static void mlxsw_sp1_switchdev_init(struct mlxsw_sp *mlxsw_sp)
{
mlxsw_sp->bridge->bridge_8021ad_ops = &mlxsw_sp1_bridge_8021ad_ops;
}
const struct mlxsw_sp_switchdev_ops mlxsw_sp1_switchdev_ops = {
.init = mlxsw_sp1_switchdev_init,
};
static void mlxsw_sp2_switchdev_init(struct mlxsw_sp *mlxsw_sp)
{
mlxsw_sp->bridge->bridge_8021ad_ops = &mlxsw_sp2_bridge_8021ad_ops;
}
const struct mlxsw_sp_switchdev_ops mlxsw_sp2_switchdev_ops = {
.init = mlxsw_sp2_switchdev_init,
};
int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp) int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
{ {
struct mlxsw_sp_bridge *bridge; struct mlxsw_sp_bridge *bridge;
...@@ -3549,7 +3618,8 @@ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp) ...@@ -3549,7 +3618,8 @@ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
bridge->bridge_8021q_ops = &mlxsw_sp_bridge_8021q_ops; bridge->bridge_8021q_ops = &mlxsw_sp_bridge_8021q_ops;
bridge->bridge_8021d_ops = &mlxsw_sp_bridge_8021d_ops; bridge->bridge_8021d_ops = &mlxsw_sp_bridge_8021d_ops;
bridge->bridge_8021ad_ops = &mlxsw_sp_bridge_8021ad_ops;
mlxsw_sp->switchdev_ops->init(mlxsw_sp);
return mlxsw_sp_fdb_init(mlxsw_sp); return mlxsw_sp_fdb_init(mlxsw_sp);
} }
......
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
lib_dir=$(dirname $0)/../../../../net/forwarding
VXPORT=4789
ALL_TESTS="
create_dot1d_and_dot1ad_vxlans
"
NUM_NETIFS=2
source $lib_dir/lib.sh
setup_prepare()
{
swp1=${NETIFS[p1]}
swp2=${NETIFS[p2]}
ip link set dev $swp1 up
ip link set dev $swp2 up
}
cleanup()
{
pre_cleanup
ip link set dev $swp2 down
ip link set dev $swp1 down
}
create_dot1d_and_dot1ad_vxlans()
{
RET=0
ip link add dev br0 type bridge vlan_filtering 1 vlan_protocol 802.1ad \
vlan_default_pvid 0 mcast_snooping 0
ip link set dev br0 up
ip link add name vx100 type vxlan id 1000 local 192.0.2.17 dstport \
"$VXPORT" nolearning noudpcsum tos inherit ttl 100
ip link set dev vx100 up
ip link set dev $swp1 master br0
ip link set dev vx100 master br0
bridge vlan add vid 100 dev vx100 pvid untagged
ip link add dev br1 type bridge vlan_filtering 0 mcast_snooping 0
ip link set dev br1 up
ip link add name vx200 type vxlan id 2000 local 192.0.2.17 dstport \
"$VXPORT" nolearning noudpcsum tos inherit ttl 100
ip link set dev vx200 up
ip link set dev $swp2 master br1
ip link set dev vx200 master br1 2>/dev/null
check_fail $? "802.1d and 802.1ad VxLANs at the same time not rejected"
ip link set dev vx200 master br1 2>&1 >/dev/null \
| grep -q mlxsw_spectrum
check_err $? "802.1d and 802.1ad VxLANs at the same time rejected without extack"
log_test "create 802.1d and 802.1ad VxLANs"
ip link del dev vx200
ip link del dev br1
ip link del dev vx100
ip link del dev br0
}
trap cleanup EXIT
setup_prepare
setup_wait
tests_run
exit $EXIT_STATUS
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment