Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Currently only one EtherType can be configured for pushing in tunnels
because EtherType is configured using SPVID.et_vlan for tunnel port.

This behavior is forbidden by comparing mlxsw_sp_nve_config struct for
each new tunnel, the struct contains 'ethertype' field which means that
only one EtherType is legal at any given time. Remove 'ethertype' field to
allow creating VxLAN devices with different bridges.

To allow using several types of VxLAN bridges at the same time, the
EtherType should be determined at the egress port. This behavior is
achieved by setting SPVID to decide which EtherType to push at egress and
for each local_port which is member in 802.1ad bridge, set SPEVET.et_vlan
to ether_type1 (i.e., 0x88A8).

Use switchdev_ops->init() to set different mlxsw_sp_bridge_ops for
different ASICs in order to be able to split the behavior when port joins /
leaves an 802.1ad bridge in different ASICs.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Amit Cohen and committed by
David S. Miller
bf677bd2 0f74fa56

+53 -15
-1
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
··· 18 18 u32 ul_tb_id; 19 19 enum mlxsw_sp_l3proto ul_proto; 20 20 union mlxsw_sp_l3addr ul_sip; 21 - u16 ethertype; 22 21 }; 23 22 24 23 struct mlxsw_sp_nve {
+3 -12
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
··· 113 113 config->ul_proto = MLXSW_SP_L3_PROTO_IPV4; 114 114 config->ul_sip.addr4 = cfg->saddr.sin.sin_addr.s_addr; 115 115 config->udp_dport = cfg->dst_port; 116 - config->ethertype = params->ethertype; 117 116 } 118 117 119 118 static int __mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp, ··· 317 318 } 318 319 319 320 static int 320 - mlxsw_sp2_nve_decap_ethertype_set(struct mlxsw_sp *mlxsw_sp, u16 ethertype) 321 + mlxsw_sp2_nve_decap_ethertype_set(struct mlxsw_sp *mlxsw_sp) 321 322 { 322 323 char spvid_pl[MLXSW_REG_SPVID_LEN] = {}; 323 - u8 sver_type; 324 - int err; 325 324 326 325 mlxsw_reg_spvid_tport_set(spvid_pl, true); 327 326 mlxsw_reg_spvid_local_port_set(spvid_pl, 328 327 MLXSW_REG_TUNNEL_PORT_NVE); 329 - err = mlxsw_sp_ethtype_to_sver_type(ethertype, &sver_type); 330 - if (err) 331 - return err; 332 - 333 - mlxsw_reg_spvid_et_vlan_set(spvid_pl, sver_type); 328 + mlxsw_reg_spvid_egr_et_set_set(spvid_pl, true); 334 329 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl); 335 330 } 336 331 ··· 360 367 if (err) 361 368 goto err_spvtr_write; 362 369 363 - err = mlxsw_sp2_nve_decap_ethertype_set(mlxsw_sp, config->ethertype); 370 + err = mlxsw_sp2_nve_decap_ethertype_set(mlxsw_sp); 364 371 if (err) 365 372 goto err_decap_ethertype_set; 366 373 ··· 385 392 char spvtr_pl[MLXSW_REG_SPVTR_LEN]; 386 393 char tngcr_pl[MLXSW_REG_TNGCR_LEN]; 387 394 388 - /* Set default EtherType */ 389 - mlxsw_sp2_nve_decap_ethertype_set(mlxsw_sp, ETH_P_8021Q); 390 395 mlxsw_reg_spvtr_pack(spvtr_pl, true, MLXSW_REG_TUNNEL_PORT_NVE, 391 396 MLXSW_REG_SPVTR_IPVID_MODE_IEEE_COMPLIANT_PVID); 392 397 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvtr), spvtr_pl);
+50 -2
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
··· 2300 2300 vid, ETH_P_8021AD, extack); 2301 2301 } 2302 2302 2303 - static const struct mlxsw_sp_bridge_ops mlxsw_sp_bridge_8021ad_ops = { 2303 + static const struct mlxsw_sp_bridge_ops mlxsw_sp1_bridge_8021ad_ops = { 2304 2304 .port_join = mlxsw_sp_bridge_8021ad_port_join, 2305 2305 .port_leave = mlxsw_sp_bridge_8021ad_port_leave, 2306 + .vxlan_join = mlxsw_sp_bridge_8021ad_vxlan_join, 2307 + .fid_get = mlxsw_sp_bridge_8021q_fid_get, 2308 + .fid_lookup = mlxsw_sp_bridge_8021q_fid_lookup, 2309 + .fid_vid = mlxsw_sp_bridge_8021q_fid_vid, 2310 + }; 2311 + 2312 + static int 2313 + mlxsw_sp2_bridge_8021ad_port_join(struct mlxsw_sp_bridge_device *bridge_device, 2314 + struct mlxsw_sp_bridge_port *bridge_port, 2315 + struct mlxsw_sp_port *mlxsw_sp_port, 2316 + struct netlink_ext_ack *extack) 2317 + { 2318 + int err; 2319 + 2320 + /* The EtherType of decapsulated packets is determined at the egress 2321 + * port to allow 802.1d and 802.1ad bridges with VXLAN devices to 2322 + * co-exist. 2323 + */ 2324 + err = mlxsw_sp_port_egress_ethtype_set(mlxsw_sp_port, ETH_P_8021AD); 2325 + if (err) 2326 + return err; 2327 + 2328 + err = mlxsw_sp_bridge_8021ad_port_join(bridge_device, bridge_port, 2329 + mlxsw_sp_port, extack); 2330 + if (err) 2331 + goto err_bridge_8021ad_port_join; 2332 + 2333 + return 0; 2334 + 2335 + err_bridge_8021ad_port_join: 2336 + mlxsw_sp_port_egress_ethtype_set(mlxsw_sp_port, ETH_P_8021Q); 2337 + return err; 2338 + } 2339 + 2340 + static void 2341 + mlxsw_sp2_bridge_8021ad_port_leave(struct mlxsw_sp_bridge_device *bridge_device, 2342 + struct mlxsw_sp_bridge_port *bridge_port, 2343 + struct mlxsw_sp_port *mlxsw_sp_port) 2344 + { 2345 + mlxsw_sp_bridge_8021ad_port_leave(bridge_device, bridge_port, 2346 + mlxsw_sp_port); 2347 + mlxsw_sp_port_egress_ethtype_set(mlxsw_sp_port, ETH_P_8021Q); 2348 + } 2349 + 2350 + static const struct mlxsw_sp_bridge_ops mlxsw_sp2_bridge_8021ad_ops = { 2351 + .port_join = mlxsw_sp2_bridge_8021ad_port_join, 2352 + .port_leave = mlxsw_sp2_bridge_8021ad_port_leave, 2306 2353 .vxlan_join = mlxsw_sp_bridge_8021ad_vxlan_join, 2307 2354 .fid_get = mlxsw_sp_bridge_8021q_fid_get, 2308 2355 .fid_lookup = mlxsw_sp_bridge_8021q_fid_lookup, ··· 3588 3541 3589 3542 static void mlxsw_sp1_switchdev_init(struct mlxsw_sp *mlxsw_sp) 3590 3543 { 3544 + mlxsw_sp->bridge->bridge_8021ad_ops = &mlxsw_sp1_bridge_8021ad_ops; 3591 3545 } 3592 3546 3593 3547 const struct mlxsw_sp_switchdev_ops mlxsw_sp1_switchdev_ops = { ··· 3597 3549 3598 3550 static void mlxsw_sp2_switchdev_init(struct mlxsw_sp *mlxsw_sp) 3599 3551 { 3552 + mlxsw_sp->bridge->bridge_8021ad_ops = &mlxsw_sp2_bridge_8021ad_ops; 3600 3553 } 3601 3554 3602 3555 const struct mlxsw_sp_switchdev_ops mlxsw_sp2_switchdev_ops = { ··· 3618 3569 3619 3570 bridge->bridge_8021q_ops = &mlxsw_sp_bridge_8021q_ops; 3620 3571 bridge->bridge_8021d_ops = &mlxsw_sp_bridge_8021d_ops; 3621 - bridge->bridge_8021ad_ops = &mlxsw_sp_bridge_8021ad_ops; 3622 3572 3623 3573 mlxsw_sp->switchdev_ops->init(mlxsw_sp); 3624 3574