Skip to content

Commit

Permalink
net/mlx5: Bridge, identify port by vport_num+esw_owner_vhca_id pair
Browse files Browse the repository at this point in the history
Following patches in series allow traffic between vports of different
eswitch instances, which requires addressing bridge port by
vport_num+esw_owner_vhca_id pair since vport_num is only unique
per-eswitch. As a preparation, extend struct mlx5_esw_bridge_port with
'esw_owner_vhca_id' field and use it as part of key for
mlx5_esw_bridge->vports xarray.

With this change we can't rely on switchdev_handle_port_obj_add() helper to
get mlx5 representor from stacked device because we need specifically
representor from parent eswitch that registered the callback to obtain
correct esw_owner_vhca_id. The helper doesn't allow passing additional
parameters to predicate function and doesn't provide access to the notifier
block to obtain eswitch through br_offloads. Implement custom helpers to
obtain mlx5 representor and use them in
mlx5_esw_bridge_port_obj_{add|del|attr_set}() implementations.

Remove direct pointer to parent bridge from struct mlx5_vport as it is no
longer needed.

Signed-off-by: Vlad Buslov <vladbu@nvidia.com>
Reviewed-by: Roi Dayan <roid@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
  • Loading branch information
w1ldptr authored and Saeed Mahameed committed Aug 16, 2021
1 parent a514d17 commit 3ee6233
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 208 deletions.
238 changes: 133 additions & 105 deletions drivers/net/ethernet/mellanox/mlx5/core/en/rep/bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,83 @@ struct mlx5_bridge_switchdev_fdb_work {
bool add;
};

static bool mlx5_esw_bridge_dev_same_esw(struct net_device *dev, struct mlx5_eswitch *esw)
{
struct mlx5e_priv *priv = netdev_priv(dev);

return esw == priv->mdev->priv.eswitch;
}

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)
{
struct mlx5e_rep_priv *rpriv;
struct mlx5e_priv *priv;

if (!mlx5e_eswitch_rep(dev) || !mlx5_esw_bridge_dev_same_esw(dev, esw))
return -ENODEV;

priv = netdev_priv(dev);
rpriv = priv->ppriv;
*vport_num = rpriv->rep->vport;
*esw_owner_vhca_id = MLX5_CAP_GEN(priv->mdev, vhca_id);
return 0;
}

static int
mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_eswitch *esw,
u16 *vport_num, u16 *esw_owner_vhca_id)
{
struct net_device *lower_dev;
struct list_head *iter;

if (mlx5e_eswitch_rep(dev) && mlx5_esw_bridge_dev_same_esw(dev, esw))
return mlx5_esw_bridge_vport_num_vhca_id_get(dev, esw, vport_num,
esw_owner_vhca_id);

netdev_for_each_lower_dev(dev, lower_dev, iter) {
int err;

if (netif_is_bridge_master(lower_dev))
continue;

err = mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(lower_dev, esw, vport_num,
esw_owner_vhca_id);
if (!err)
return 0;
}

return -ENODEV;
}

static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr)
{
struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb,
struct mlx5_esw_bridge_offloads,
netdev_nb);
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct netdev_notifier_changeupper_info *info = ptr;
struct net_device *upper = info->upper_dev;
u16 vport_num, esw_owner_vhca_id;
struct netlink_ext_ack *extack;
struct mlx5e_rep_priv *rpriv;
struct mlx5_eswitch *esw;
struct mlx5_vport *vport;
struct net_device *upper;
struct mlx5e_priv *priv;
u16 vport_num;

if (!mlx5e_eswitch_rep(dev))
return 0;
int ifindex = upper->ifindex;
int err;

upper = info->upper_dev;
if (!netif_is_bridge_master(upper))
return 0;

esw = br_offloads->esw;
priv = netdev_priv(dev);
if (esw != priv->mdev->priv.eswitch)
err = mlx5_esw_bridge_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
&esw_owner_vhca_id);
if (err)
return 0;

rpriv = priv->ppriv;
vport_num = rpriv->rep->vport;
vport = mlx5_eswitch_get_vport(esw, vport_num);
if (IS_ERR(vport))
return PTR_ERR(vport);

extack = netdev_notifier_info_to_extack(&info->info);

return info->linking ?
mlx5_esw_bridge_vport_link(upper->ifindex, br_offloads, vport, extack) :
mlx5_esw_bridge_vport_unlink(upper->ifindex, br_offloads, vport, extack);
mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
extack) :
mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id, br_offloads,
extack);
}

static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb,
Expand All @@ -75,87 +114,80 @@ static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb,
return notifier_from_errno(err);
}

static int mlx5_esw_bridge_port_obj_add(struct net_device *dev,
const void *ctx,
const struct switchdev_obj *obj,
struct netlink_ext_ack *extack)
static int
mlx5_esw_bridge_port_obj_add(struct net_device *dev,
struct switchdev_notifier_port_obj_info *port_obj_info,
struct mlx5_esw_bridge_offloads *br_offloads)
{
struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_obj_info->info);
const struct switchdev_obj *obj = port_obj_info->obj;
const struct switchdev_obj_port_vlan *vlan;
struct mlx5e_rep_priv *rpriv;
struct mlx5_eswitch *esw;
struct mlx5_vport *vport;
struct mlx5e_priv *priv;
u16 vport_num;
int err = 0;
u16 vport_num, esw_owner_vhca_id;
int err;

priv = netdev_priv(dev);
rpriv = priv->ppriv;
vport_num = rpriv->rep->vport;
esw = priv->mdev->priv.eswitch;
vport = mlx5_eswitch_get_vport(esw, vport_num);
if (IS_ERR(vport))
return PTR_ERR(vport);
err = mlx5_esw_bridge_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
&esw_owner_vhca_id);
if (err)
return 0;

port_obj_info->handled = true;

switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_VLAN:
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
err = mlx5_esw_bridge_port_vlan_add(vlan->vid, vlan->flags, esw, vport, extack);
err = mlx5_esw_bridge_port_vlan_add(vport_num, esw_owner_vhca_id, vlan->vid,
vlan->flags, br_offloads, extack);
break;
default:
return -EOPNOTSUPP;
}
return err;
}

static int mlx5_esw_bridge_port_obj_del(struct net_device *dev,
const void *ctx,
const struct switchdev_obj *obj)
static int
mlx5_esw_bridge_port_obj_del(struct net_device *dev,
struct switchdev_notifier_port_obj_info *port_obj_info,
struct mlx5_esw_bridge_offloads *br_offloads)
{
const struct switchdev_obj *obj = port_obj_info->obj;
const struct switchdev_obj_port_vlan *vlan;
struct mlx5e_rep_priv *rpriv;
struct mlx5_eswitch *esw;
struct mlx5_vport *vport;
struct mlx5e_priv *priv;
u16 vport_num;
u16 vport_num, esw_owner_vhca_id;
int err;

priv = netdev_priv(dev);
rpriv = priv->ppriv;
vport_num = rpriv->rep->vport;
esw = priv->mdev->priv.eswitch;
vport = mlx5_eswitch_get_vport(esw, vport_num);
if (IS_ERR(vport))
return PTR_ERR(vport);
err = mlx5_esw_bridge_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
&esw_owner_vhca_id);
if (err)
return 0;

port_obj_info->handled = true;

switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_VLAN:
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
mlx5_esw_bridge_port_vlan_del(vlan->vid, esw, vport);
mlx5_esw_bridge_port_vlan_del(vport_num, esw_owner_vhca_id, vlan->vid, br_offloads);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}

static int mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
const void *ctx,
const struct switchdev_attr *attr,
struct netlink_ext_ack *extack)
static int
mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
struct switchdev_notifier_port_attr_info *port_attr_info,
struct mlx5_esw_bridge_offloads *br_offloads)
{
struct mlx5e_rep_priv *rpriv;
struct mlx5_eswitch *esw;
struct mlx5_vport *vport;
struct mlx5e_priv *priv;
u16 vport_num;
int err = 0;
struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_attr_info->info);
const struct switchdev_attr *attr = port_attr_info->attr;
u16 vport_num, esw_owner_vhca_id;
int err;

priv = netdev_priv(dev);
rpriv = priv->ppriv;
vport_num = rpriv->rep->vport;
esw = priv->mdev->priv.eswitch;
vport = mlx5_eswitch_get_vport(esw, vport_num);
if (IS_ERR(vport))
return PTR_ERR(vport);
err = mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
&esw_owner_vhca_id);
if (err)
return 0;

port_attr_info->handled = true;

switch (attr->id) {
case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
Expand All @@ -167,10 +199,12 @@ static int mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
break;
case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
err = mlx5_esw_bridge_ageing_time_set(attr->u.ageing_time, esw, vport);
err = mlx5_esw_bridge_ageing_time_set(vport_num, esw_owner_vhca_id,
attr->u.ageing_time, br_offloads);
break;
case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
err = mlx5_esw_bridge_vlan_filtering_set(attr->u.vlan_filtering, esw, vport);
err = mlx5_esw_bridge_vlan_filtering_set(vport_num, esw_owner_vhca_id,
attr->u.vlan_filtering, br_offloads);
break;
default:
err = -EOPNOTSUPP;
Expand All @@ -179,27 +213,24 @@ static int mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
return err;
}

static int mlx5_esw_bridge_event_blocking(struct notifier_block *unused,
static int mlx5_esw_bridge_event_blocking(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb,
struct mlx5_esw_bridge_offloads,
nb_blk);
struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
int err;

switch (event) {
case SWITCHDEV_PORT_OBJ_ADD:
err = switchdev_handle_port_obj_add(dev, ptr,
mlx5e_eswitch_rep,
mlx5_esw_bridge_port_obj_add);
err = mlx5_esw_bridge_port_obj_add(dev, ptr, br_offloads);
break;
case SWITCHDEV_PORT_OBJ_DEL:
err = switchdev_handle_port_obj_del(dev, ptr,
mlx5e_eswitch_rep,
mlx5_esw_bridge_port_obj_del);
err = mlx5_esw_bridge_port_obj_del(dev, ptr, br_offloads);
break;
case SWITCHDEV_PORT_ATTR_SET:
err = switchdev_handle_port_attr_set(dev, ptr,
mlx5e_eswitch_rep,
mlx5_esw_bridge_port_obj_attr_set);
err = mlx5_esw_bridge_port_obj_attr_set(dev, ptr, br_offloads);
break;
default:
err = 0;
Expand All @@ -222,27 +253,27 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work)
container_of(work, struct mlx5_bridge_switchdev_fdb_work, work);
struct switchdev_notifier_fdb_info *fdb_info =
&fdb_work->fdb_info;
struct mlx5_esw_bridge_offloads *br_offloads;
struct net_device *dev = fdb_work->dev;
struct mlx5e_rep_priv *rpriv;
struct mlx5_eswitch *esw;
struct mlx5_vport *vport;
u16 vport_num, esw_owner_vhca_id;
struct mlx5e_priv *priv;
u16 vport_num;
int err;

rtnl_lock();

priv = netdev_priv(dev);
rpriv = priv->ppriv;
vport_num = rpriv->rep->vport;
esw = priv->mdev->priv.eswitch;
vport = mlx5_eswitch_get_vport(esw, vport_num);
if (IS_ERR(vport))
br_offloads = priv->mdev->priv.eswitch->br_offloads;
err = mlx5_esw_bridge_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
&esw_owner_vhca_id);
if (err)
goto out;

if (fdb_work->add)
mlx5_esw_bridge_fdb_create(dev, esw, vport, fdb_info);
mlx5_esw_bridge_fdb_create(dev, vport_num, esw_owner_vhca_id, br_offloads,
fdb_info);
else
mlx5_esw_bridge_fdb_remove(dev, esw, vport, fdb_info);
mlx5_esw_bridge_fdb_remove(dev, vport_num, esw_owner_vhca_id, br_offloads,
fdb_info);

out:
rtnl_unlock();
Expand Down Expand Up @@ -288,18 +319,10 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
struct mlx5_bridge_switchdev_fdb_work *work;
struct switchdev_notifier_info *info = ptr;
struct net_device *upper;
struct mlx5e_priv *priv;

if (!mlx5e_eswitch_rep(dev))
return NOTIFY_DONE;
priv = netdev_priv(dev);
if (priv->mdev->priv.eswitch != br_offloads->esw)
return NOTIFY_DONE;

if (event == SWITCHDEV_PORT_ATTR_SET) {
int err = switchdev_handle_port_attr_set(dev, ptr,
mlx5e_eswitch_rep,
mlx5_esw_bridge_port_obj_attr_set);
int err = mlx5_esw_bridge_port_obj_attr_set(dev, ptr, br_offloads);

return notifier_from_errno(err);
}

Expand All @@ -309,6 +332,11 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
if (!netif_is_bridge_master(upper))
return NOTIFY_DONE;

if (!mlx5e_eswitch_rep(dev))
return NOTIFY_DONE;
if (!mlx5_esw_bridge_dev_same_esw(dev, br_offloads->esw))
return NOTIFY_DONE;

switch (event) {
case SWITCHDEV_FDB_ADD_TO_DEVICE:
case SWITCHDEV_FDB_DEL_TO_DEVICE:
Expand Down

0 comments on commit 3ee6233

Please sign in to comment.