Skip to content

Commit 139ae87

Browse files
Amit Cohenkuba-moo
Amit Cohen
authored andcommitted
mlxsw: Add VXLAN bridge ports to same hardware domain as physical bridge ports
When hardware floods packets to bridge ports, but flooding to VXLAN bridge port fails during encapsulation to one of the remote VTEPs, the packets are trapped to CPU. In such case, the packets are marked with skb->offload_fwd_mark, which means that packet was L2-forwarded in hardware. Software data path repeats flooding, but packets which are marked with skb->offload_fwd_mark will not be flooded by the bridge to bridge ports which are in the same hardware domain as the ingress port. Currently, mlxsw does not add VXLAN bridge ports to the same hardware domain as physical bridge ports despite the fact that the device is able to forward packets to and from VXLAN tunnels in hardware. In some scenarios (as mentioned above) this can result in remote VTEPs receiving duplicate packets. The packets are first flooded by hardware and after an encapsulation failure, they are flooded again to all remote VTEPs by software. Solve this by adding VXLAN bridge ports to the same hardware domain as physical bridge ports, so then nbp_switchdev_allowed_egress() will return false also for VXLAN, and packets will not be sent twice from VXLAN device. switchdev_bridge_port_offload() should get vxlan_dev not as const, so some changes are required. Call switchdev API from mlxsw_sp_bridge_vxlan_{join,leave}() which handle offload configurations. Reported-by: Vladimir Oltean <[email protected]> Closes: https://lore.kernel.org/all/20250210152246.4ajumdchwhvbarik@skbuf/ Reported-by: Vladyslav Mykhaliuk <[email protected]> Signed-off-by: Amit Cohen <[email protected]> Reviewed-by: Petr Machata <[email protected]> Reviewed-by: Ido Schimmel <[email protected]> Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Simon Horman <[email protected]> Link: https://patch.msgid.link/7279056843140fae3a72c2d204c7886b79d03899.1742224300.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 630e7e2 commit 139ae87

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -661,10 +661,10 @@ bool mlxsw_sp_bridge_device_is_offloaded(const struct mlxsw_sp *mlxsw_sp,
661661
const struct net_device *br_dev);
662662
int mlxsw_sp_bridge_vxlan_join(struct mlxsw_sp *mlxsw_sp,
663663
const struct net_device *br_dev,
664-
const struct net_device *vxlan_dev, u16 vid,
664+
struct net_device *vxlan_dev, u16 vid,
665665
struct netlink_ext_ack *extack);
666666
void mlxsw_sp_bridge_vxlan_leave(struct mlxsw_sp *mlxsw_sp,
667-
const struct net_device *vxlan_dev);
667+
struct net_device *vxlan_dev);
668668
extern struct notifier_block mlxsw_sp_switchdev_notifier;
669669

670670
/* spectrum.c */

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

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,22 +2950,42 @@ static void __mlxsw_sp_bridge_vxlan_leave(struct mlxsw_sp *mlxsw_sp,
29502950

29512951
int mlxsw_sp_bridge_vxlan_join(struct mlxsw_sp *mlxsw_sp,
29522952
const struct net_device *br_dev,
2953-
const struct net_device *vxlan_dev, u16 vid,
2953+
struct net_device *vxlan_dev, u16 vid,
29542954
struct netlink_ext_ack *extack)
29552955
{
29562956
struct mlxsw_sp_bridge_device *bridge_device;
2957+
struct mlxsw_sp_port *mlxsw_sp_port;
2958+
int err;
29572959

29582960
bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
29592961
if (WARN_ON(!bridge_device))
29602962
return -EINVAL;
29612963

2962-
return bridge_device->ops->vxlan_join(bridge_device, vxlan_dev, vid,
2963-
extack);
2964+
mlxsw_sp_port = mlxsw_sp_port_dev_lower_find(bridge_device->dev);
2965+
if (!mlxsw_sp_port)
2966+
return -EINVAL;
2967+
2968+
err = bridge_device->ops->vxlan_join(bridge_device, vxlan_dev, vid,
2969+
extack);
2970+
if (err)
2971+
return err;
2972+
2973+
err = switchdev_bridge_port_offload(vxlan_dev, mlxsw_sp_port->dev,
2974+
NULL, NULL, NULL, false, extack);
2975+
if (err)
2976+
goto err_bridge_port_offload;
2977+
2978+
return 0;
2979+
2980+
err_bridge_port_offload:
2981+
__mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, vxlan_dev);
2982+
return err;
29642983
}
29652984

29662985
void mlxsw_sp_bridge_vxlan_leave(struct mlxsw_sp *mlxsw_sp,
2967-
const struct net_device *vxlan_dev)
2986+
struct net_device *vxlan_dev)
29682987
{
2988+
switchdev_bridge_port_unoffload(vxlan_dev, NULL, NULL, NULL);
29692989
__mlxsw_sp_bridge_vxlan_leave(mlxsw_sp, vxlan_dev);
29702990
}
29712991

0 commit comments

Comments
 (0)