Commit c358ea17 authored by Vlad Buslov's avatar Vlad Buslov Committed by Saeed Mahameed

net/mlx5: Bridge, allow merged eswitch connectivity

Allow connectivity between representors of different eswitch instances that
are attached to same bridge when merged_eswitch capability is enabled. Add
ports of peer eswitch to bridge instance and mark them with
MLX5_ESW_BRIDGE_PORT_FLAG_PEER. Mark FDBs offloaded on peer ports with
MLX5_ESW_BRIDGE_FLAG_PEER flag. Such FDBs can only be aged out on their
local eswitch instance, which then sends SWITCHDEV_FDB_DEL_TO_BRIDGE event.
Listen to the event on mlx5 bridge implementation and delete peer FDBs in
event handler.
Signed-off-by: default avatarVlad Buslov <vladbu@nvidia.com>
Reviewed-by: default avatarRoi Dayan <roid@nvidia.com>
Reviewed-by: default avatarMark Bloch <mbloch@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent bf3d56d8
...@@ -15,6 +15,7 @@ struct mlx5_bridge_switchdev_fdb_work { ...@@ -15,6 +15,7 @@ struct mlx5_bridge_switchdev_fdb_work {
struct work_struct work; struct work_struct work;
struct switchdev_notifier_fdb_info fdb_info; struct switchdev_notifier_fdb_info fdb_info;
struct net_device *dev; struct net_device *dev;
struct mlx5_esw_bridge_offloads *br_offloads;
bool add; bool add;
}; };
...@@ -25,13 +26,28 @@ static bool mlx5_esw_bridge_dev_same_esw(struct net_device *dev, struct mlx5_esw ...@@ -25,13 +26,28 @@ static bool mlx5_esw_bridge_dev_same_esw(struct net_device *dev, struct mlx5_esw
return esw == priv->mdev->priv.eswitch; return esw == priv->mdev->priv.eswitch;
} }
static bool mlx5_esw_bridge_dev_same_hw(struct net_device *dev, struct mlx5_eswitch *esw)
{
struct mlx5e_priv *priv = netdev_priv(dev);
struct mlx5_core_dev *mdev, *esw_mdev;
u64 system_guid, esw_system_guid;
mdev = priv->mdev;
esw_mdev = esw->dev;
system_guid = mlx5_query_nic_system_image_guid(mdev);
esw_system_guid = mlx5_query_nic_system_image_guid(esw_mdev);
return system_guid == esw_system_guid;
}
static int mlx5_esw_bridge_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_eswitch *esw, static int mlx5_esw_bridge_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_eswitch *esw,
u16 *vport_num, u16 *esw_owner_vhca_id) u16 *vport_num, u16 *esw_owner_vhca_id)
{ {
struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_priv *rpriv;
struct mlx5e_priv *priv; struct mlx5e_priv *priv;
if (!mlx5e_eswitch_rep(dev) || !mlx5_esw_bridge_dev_same_esw(dev, esw)) if (!mlx5e_eswitch_rep(dev) || !mlx5_esw_bridge_dev_same_hw(dev, esw))
return -ENODEV; return -ENODEV;
priv = netdev_priv(dev); priv = netdev_priv(dev);
...@@ -48,7 +64,7 @@ mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(struct net_device *dev, struct m ...@@ -48,7 +64,7 @@ mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(struct net_device *dev, struct m
struct net_device *lower_dev; struct net_device *lower_dev;
struct list_head *iter; struct list_head *iter;
if (mlx5e_eswitch_rep(dev) && mlx5_esw_bridge_dev_same_esw(dev, esw)) if (mlx5e_eswitch_rep(dev))
return mlx5_esw_bridge_vport_num_vhca_id_get(dev, esw, vport_num, return mlx5_esw_bridge_vport_num_vhca_id_get(dev, esw, vport_num,
esw_owner_vhca_id); esw_owner_vhca_id);
...@@ -74,6 +90,7 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr ...@@ -74,6 +90,7 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
netdev_nb); netdev_nb);
struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct netdev_notifier_changeupper_info *info = ptr; struct netdev_notifier_changeupper_info *info = ptr;
struct mlx5_eswitch *esw = br_offloads->esw;
struct net_device *upper = info->upper_dev; struct net_device *upper = info->upper_dev;
u16 vport_num, esw_owner_vhca_id; u16 vport_num, esw_owner_vhca_id;
struct netlink_ext_ack *extack; struct netlink_ext_ack *extack;
...@@ -90,11 +107,20 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr ...@@ -90,11 +107,20 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
extack = netdev_notifier_info_to_extack(&info->info); extack = netdev_notifier_info_to_extack(&info->info);
return info->linking ? if (mlx5_esw_bridge_dev_same_esw(dev, esw))
mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id, br_offloads, err = info->linking ?
extack) : mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id,
mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads, br_offloads, extack) :
extack); mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id,
br_offloads, extack);
else if (mlx5_esw_bridge_dev_same_hw(dev, esw))
err = info->linking ?
mlx5_esw_bridge_vport_peer_link(ifindex, vport_num, esw_owner_vhca_id,
br_offloads, extack) :
mlx5_esw_bridge_vport_peer_unlink(ifindex, vport_num, esw_owner_vhca_id,
br_offloads, extack);
return err;
} }
static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb, static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb,
...@@ -253,16 +279,14 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work) ...@@ -253,16 +279,14 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work)
container_of(work, struct mlx5_bridge_switchdev_fdb_work, work); container_of(work, struct mlx5_bridge_switchdev_fdb_work, work);
struct switchdev_notifier_fdb_info *fdb_info = struct switchdev_notifier_fdb_info *fdb_info =
&fdb_work->fdb_info; &fdb_work->fdb_info;
struct mlx5_esw_bridge_offloads *br_offloads; struct mlx5_esw_bridge_offloads *br_offloads =
fdb_work->br_offloads;
struct net_device *dev = fdb_work->dev; struct net_device *dev = fdb_work->dev;
u16 vport_num, esw_owner_vhca_id; u16 vport_num, esw_owner_vhca_id;
struct mlx5e_priv *priv;
int err; int err;
rtnl_lock(); rtnl_lock();
priv = netdev_priv(dev);
br_offloads = priv->mdev->priv.eswitch->br_offloads;
err = mlx5_esw_bridge_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num, err = mlx5_esw_bridge_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
&esw_owner_vhca_id); &esw_owner_vhca_id);
if (err) if (err)
...@@ -282,7 +306,8 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work) ...@@ -282,7 +306,8 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work)
static struct mlx5_bridge_switchdev_fdb_work * static struct mlx5_bridge_switchdev_fdb_work *
mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add, mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add,
struct switchdev_notifier_fdb_info *fdb_info) struct switchdev_notifier_fdb_info *fdb_info,
struct mlx5_esw_bridge_offloads *br_offloads)
{ {
struct mlx5_bridge_switchdev_fdb_work *work; struct mlx5_bridge_switchdev_fdb_work *work;
u8 *addr; u8 *addr;
...@@ -304,6 +329,7 @@ mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add, ...@@ -304,6 +329,7 @@ mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add,
dev_hold(dev); dev_hold(dev);
work->dev = dev; work->dev = dev;
work->br_offloads = br_offloads;
work->add = add; work->add = add;
return work; return work;
} }
...@@ -334,10 +360,13 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb, ...@@ -334,10 +360,13 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
if (!mlx5e_eswitch_rep(dev)) if (!mlx5e_eswitch_rep(dev))
return NOTIFY_DONE; return NOTIFY_DONE;
if (!mlx5_esw_bridge_dev_same_esw(dev, br_offloads->esw))
return NOTIFY_DONE;
switch (event) { switch (event) {
case SWITCHDEV_FDB_DEL_TO_BRIDGE:
/* only handle the event when source is on another eswitch */
if (mlx5_esw_bridge_dev_same_esw(dev, br_offloads->esw))
break;
fallthrough;
case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_ADD_TO_DEVICE:
case SWITCHDEV_FDB_DEL_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE:
fdb_info = container_of(info, fdb_info = container_of(info,
...@@ -346,7 +375,8 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb, ...@@ -346,7 +375,8 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
work = mlx5_esw_bridge_init_switchdev_fdb_work(dev, work = mlx5_esw_bridge_init_switchdev_fdb_work(dev,
event == SWITCHDEV_FDB_ADD_TO_DEVICE, event == SWITCHDEV_FDB_ADD_TO_DEVICE,
fdb_info); fdb_info,
br_offloads);
if (IS_ERR(work)) { if (IS_ERR(work)) {
WARN_ONCE(1, "Failed to init switchdev work, err=%ld", WARN_ONCE(1, "Failed to init switchdev work, err=%ld",
PTR_ERR(work)); PTR_ERR(work));
......
...@@ -79,7 +79,7 @@ mlx5_esw_bridge_fdb_offload_notify(struct net_device *dev, const unsigned char * ...@@ -79,7 +79,7 @@ mlx5_esw_bridge_fdb_offload_notify(struct net_device *dev, const unsigned char *
static void static void
mlx5_esw_bridge_fdb_del_notify(struct mlx5_esw_bridge_fdb_entry *entry) mlx5_esw_bridge_fdb_del_notify(struct mlx5_esw_bridge_fdb_entry *entry)
{ {
if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER)) if (!(entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER | MLX5_ESW_BRIDGE_FLAG_PEER)))
mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr, mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
entry->key.vid, entry->key.vid,
SWITCHDEV_FDB_DEL_TO_BRIDGE); SWITCHDEV_FDB_DEL_TO_BRIDGE);
...@@ -513,7 +513,7 @@ mlx5_esw_bridge_ingress_filter_flow_create(u16 vport_num, const unsigned char *a ...@@ -513,7 +513,7 @@ mlx5_esw_bridge_ingress_filter_flow_create(u16 vport_num, const unsigned char *a
} }
static struct mlx5_flow_handle * static struct mlx5_flow_handle *
mlx5_esw_bridge_egress_flow_create(u16 vport_num, const unsigned char *addr, mlx5_esw_bridge_egress_flow_create(u16 vport_num, u16 esw_owner_vhca_id, const unsigned char *addr,
struct mlx5_esw_bridge_vlan *vlan, struct mlx5_esw_bridge_vlan *vlan,
struct mlx5_esw_bridge *bridge) struct mlx5_esw_bridge *bridge)
{ {
...@@ -558,6 +558,10 @@ mlx5_esw_bridge_egress_flow_create(u16 vport_num, const unsigned char *addr, ...@@ -558,6 +558,10 @@ mlx5_esw_bridge_egress_flow_create(u16 vport_num, const unsigned char *addr,
vlan->vid); vlan->vid);
} }
if (MLX5_CAP_ESW(bridge->br_offloads->esw->dev, merged_eswitch)) {
dest.vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID;
dest.vport.vhca_id = esw_owner_vhca_id;
}
handle = mlx5_add_flow_rules(bridge->egress_ft, rule_spec, &flow_act, &dest, 1); handle = mlx5_add_flow_rules(bridge->egress_ft, rule_spec, &flow_act, &dest, 1);
kvfree(rule_spec); kvfree(rule_spec);
...@@ -917,7 +921,7 @@ mlx5_esw_bridge_port_vlan_lookup(u16 vid, u16 vport_num, u16 esw_owner_vhca_id, ...@@ -917,7 +921,7 @@ mlx5_esw_bridge_port_vlan_lookup(u16 vid, u16 vport_num, u16 esw_owner_vhca_id,
static struct mlx5_esw_bridge_fdb_entry * static struct mlx5_esw_bridge_fdb_entry *
mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
const unsigned char *addr, u16 vid, bool added_by_user, const unsigned char *addr, u16 vid, bool added_by_user, bool peer,
struct mlx5_eswitch *esw, struct mlx5_esw_bridge *bridge) struct mlx5_eswitch *esw, struct mlx5_esw_bridge *bridge)
{ {
struct mlx5_esw_bridge_vlan *vlan = NULL; struct mlx5_esw_bridge_vlan *vlan = NULL;
...@@ -945,6 +949,8 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow ...@@ -945,6 +949,8 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow
entry->lastuse = jiffies; entry->lastuse = jiffies;
if (added_by_user) if (added_by_user)
entry->flags |= MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER; entry->flags |= MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER;
if (peer)
entry->flags |= MLX5_ESW_BRIDGE_FLAG_PEER;
counter = mlx5_fc_create(esw->dev, true); counter = mlx5_fc_create(esw->dev, true);
if (IS_ERR(counter)) { if (IS_ERR(counter)) {
...@@ -974,7 +980,8 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow ...@@ -974,7 +980,8 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow
entry->filter_handle = handle; entry->filter_handle = handle;
} }
handle = mlx5_esw_bridge_egress_flow_create(vport_num, addr, vlan, bridge); handle = mlx5_esw_bridge_egress_flow_create(vport_num, esw_owner_vhca_id, addr, vlan,
bridge);
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
err = PTR_ERR(handle); err = PTR_ERR(handle);
esw_warn(esw->dev, "Failed to create egress flow(vport=%u,err=%d)\n", esw_warn(esw->dev, "Failed to create egress flow(vport=%u,err=%d)\n",
...@@ -1050,7 +1057,7 @@ int mlx5_esw_bridge_vlan_filtering_set(u16 vport_num, u16 esw_owner_vhca_id, boo ...@@ -1050,7 +1057,7 @@ int mlx5_esw_bridge_vlan_filtering_set(u16 vport_num, u16 esw_owner_vhca_id, boo
return 0; return 0;
} }
static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id, static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id, u16 flags,
struct mlx5_esw_bridge_offloads *br_offloads, struct mlx5_esw_bridge_offloads *br_offloads,
struct mlx5_esw_bridge *bridge) struct mlx5_esw_bridge *bridge)
{ {
...@@ -1065,6 +1072,7 @@ static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id, ...@@ -1065,6 +1072,7 @@ static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id,
port->vport_num = vport_num; port->vport_num = vport_num;
port->esw_owner_vhca_id = esw_owner_vhca_id; port->esw_owner_vhca_id = esw_owner_vhca_id;
port->bridge = bridge; port->bridge = bridge;
port->flags |= flags;
xa_init(&port->vlans); xa_init(&port->vlans);
err = mlx5_esw_bridge_port_insert(port, br_offloads); err = mlx5_esw_bridge_port_insert(port, br_offloads);
if (err) { if (err) {
...@@ -1101,9 +1109,10 @@ static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_off ...@@ -1101,9 +1109,10 @@ static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_off
return 0; return 0;
} }
int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, static int mlx5_esw_bridge_vport_link_with_flags(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads, u16 flags,
struct netlink_ext_ack *extack) struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{ {
struct mlx5_esw_bridge *bridge; struct mlx5_esw_bridge *bridge;
int err; int err;
...@@ -1114,7 +1123,7 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id ...@@ -1114,7 +1123,7 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id
return PTR_ERR(bridge); return PTR_ERR(bridge);
} }
err = mlx5_esw_bridge_vport_init(vport_num, esw_owner_vhca_id, br_offloads, bridge); err = mlx5_esw_bridge_vport_init(vport_num, esw_owner_vhca_id, flags, br_offloads, bridge);
if (err) { if (err) {
NL_SET_ERR_MSG_MOD(extack, "Error initializing port"); NL_SET_ERR_MSG_MOD(extack, "Error initializing port");
goto err_vport; goto err_vport;
...@@ -1126,6 +1135,14 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id ...@@ -1126,6 +1135,14 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id
return err; return err;
} }
int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id, 0,
br_offloads, extack);
}
int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads, struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
...@@ -1149,6 +1166,26 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_ ...@@ -1149,6 +1166,26 @@ int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_
return err; return err;
} }
int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
if (!MLX5_CAP_ESW(br_offloads->esw->dev, merged_eswitch))
return 0;
return mlx5_esw_bridge_vport_link_with_flags(ifindex, vport_num, esw_owner_vhca_id,
MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
br_offloads, extack);
}
int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack)
{
return mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
extack);
}
int mlx5_esw_bridge_port_vlan_add(u16 vport_num, u16 esw_owner_vhca_id, u16 vid, u16 flags, int mlx5_esw_bridge_port_vlan_add(u16 vport_num, u16 esw_owner_vhca_id, u16 vid, u16 flags,
struct mlx5_esw_bridge_offloads *br_offloads, struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
...@@ -1206,6 +1243,7 @@ void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_o ...@@ -1206,6 +1243,7 @@ void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_o
bridge = port->bridge; bridge = port->bridge;
entry = mlx5_esw_bridge_fdb_entry_init(dev, vport_num, esw_owner_vhca_id, fdb_info->addr, entry = mlx5_esw_bridge_fdb_entry_init(dev, vport_num, esw_owner_vhca_id, fdb_info->addr,
fdb_info->vid, fdb_info->added_by_user, fdb_info->vid, fdb_info->added_by_user,
port->flags & MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
br_offloads->esw, bridge); br_offloads->esw, bridge);
if (IS_ERR(entry)) if (IS_ERR(entry))
return; return;
...@@ -1213,7 +1251,7 @@ void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_o ...@@ -1213,7 +1251,7 @@ void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_o
if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER) if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER)
mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid, mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid,
SWITCHDEV_FDB_OFFLOADED); SWITCHDEV_FDB_OFFLOADED);
else else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER))
/* Take over dynamic entries to prevent kernel bridge from aging them out. */ /* Take over dynamic entries to prevent kernel bridge from aging them out. */
mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid, mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid,
SWITCHDEV_FDB_ADD_TO_BRIDGE); SWITCHDEV_FDB_ADD_TO_BRIDGE);
...@@ -1263,7 +1301,8 @@ void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads) ...@@ -1263,7 +1301,8 @@ void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads)
if (time_after(lastuse, entry->lastuse)) { if (time_after(lastuse, entry->lastuse)) {
mlx5_esw_bridge_fdb_entry_refresh(lastuse, entry); mlx5_esw_bridge_fdb_entry_refresh(lastuse, entry);
} else if (time_is_before_jiffies(entry->lastuse + bridge->ageing_time)) { } else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER) &&
time_is_before_jiffies(entry->lastuse + bridge->ageing_time)) {
mlx5_esw_bridge_fdb_del_notify(entry); mlx5_esw_bridge_fdb_del_notify(entry);
mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge); mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge);
} }
......
...@@ -40,6 +40,12 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id ...@@ -40,6 +40,12 @@ int mlx5_esw_bridge_vport_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id
int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id, int mlx5_esw_bridge_vport_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads, struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int mlx5_esw_bridge_vport_peer_link(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
int mlx5_esw_bridge_vport_peer_unlink(int ifindex, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads,
struct netlink_ext_ack *extack);
void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id, void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
struct mlx5_esw_bridge_offloads *br_offloads, struct mlx5_esw_bridge_offloads *br_offloads,
struct switchdev_notifier_fdb_info *fdb_info); struct switchdev_notifier_fdb_info *fdb_info);
......
...@@ -19,6 +19,11 @@ struct mlx5_esw_bridge_fdb_key { ...@@ -19,6 +19,11 @@ struct mlx5_esw_bridge_fdb_key {
enum { enum {
MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER = BIT(0), MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER = BIT(0),
MLX5_ESW_BRIDGE_FLAG_PEER = BIT(1),
};
enum {
MLX5_ESW_BRIDGE_PORT_FLAG_PEER = BIT(0),
}; };
struct mlx5_esw_bridge_fdb_entry { struct mlx5_esw_bridge_fdb_entry {
...@@ -49,6 +54,7 @@ struct mlx5_esw_bridge_vlan { ...@@ -49,6 +54,7 @@ struct mlx5_esw_bridge_vlan {
struct mlx5_esw_bridge_port { struct mlx5_esw_bridge_port {
u16 vport_num; u16 vport_num;
u16 esw_owner_vhca_id; u16 esw_owner_vhca_id;
u16 flags;
struct mlx5_esw_bridge *bridge; struct mlx5_esw_bridge *bridge;
struct xarray vlans; struct xarray vlans;
}; };
......
...@@ -86,14 +86,17 @@ DECLARE_EVENT_CLASS(mlx5_esw_bridge_port_template, ...@@ -86,14 +86,17 @@ DECLARE_EVENT_CLASS(mlx5_esw_bridge_port_template,
TP_STRUCT__entry( TP_STRUCT__entry(
__field(u16, vport_num) __field(u16, vport_num)
__field(u16, esw_owner_vhca_id) __field(u16, esw_owner_vhca_id)
__field(u16, flags)
), ),
TP_fast_assign( TP_fast_assign(
__entry->vport_num = port->vport_num; __entry->vport_num = port->vport_num;
__entry->esw_owner_vhca_id = port->esw_owner_vhca_id; __entry->esw_owner_vhca_id = port->esw_owner_vhca_id;
__entry->flags = port->flags;
), ),
TP_printk("vport_num=%hu esw_owner_vhca_id=%hu", TP_printk("vport_num=%hu esw_owner_vhca_id=%hu flags=%hx",
__entry->vport_num, __entry->vport_num,
__entry->esw_owner_vhca_id) __entry->esw_owner_vhca_id,
__entry->flags)
); );
DEFINE_EVENT(mlx5_esw_bridge_port_template, DEFINE_EVENT(mlx5_esw_bridge_port_template,
......
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