Commit 88e96e53 authored by Vu Pham's avatar Vu Pham Committed by Saeed Mahameed

net/mlx5e: Slave representors sharing unique metadata for match

Bonded slave representors' vports must share a unique metadata
for match.

On enslaving event of slave representor to lag device, allocate
new unique "bond_metadata" for match if this is the first slave.
The subsequent enslaved representors will share the same unique
"bond_metadata".

On unslaving event of slave representor, reset the slave
representor's vport to use its own default metadata.

Replace ingress acl and rx rules of the slave representors' vports
using new vport->bond_metadata.
Signed-off-by: default avatarVu Pham <vuhuong@mellanox.com>
Reviewed-by: default avatarParav Pandit <parav@mellanox.com>
Reviewed-by: default avatarRoi Dayan <roid@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 133dcfc5
...@@ -71,6 +71,7 @@ static void mlx5e_rep_bond_metadata_release(struct mlx5e_rep_bond_metadata *mdat ...@@ -71,6 +71,7 @@ static void mlx5e_rep_bond_metadata_release(struct mlx5e_rep_bond_metadata *mdat
netdev_dbg(mdata->lag_dev, "destroy rep_bond_metadata(%d)\n", netdev_dbg(mdata->lag_dev, "destroy rep_bond_metadata(%d)\n",
mdata->metadata_reg_c_0); mdata->metadata_reg_c_0);
list_del(&mdata->list); list_del(&mdata->list);
mlx5_esw_match_metadata_free(mdata->esw, mdata->metadata_reg_c_0);
WARN_ON(!list_empty(&mdata->slaves_list)); WARN_ON(!list_empty(&mdata->slaves_list));
kfree(mdata); kfree(mdata);
} }
...@@ -82,6 +83,8 @@ int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev, ...@@ -82,6 +83,8 @@ int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev,
struct mlx5e_rep_bond_slave_entry *s_entry; struct mlx5e_rep_bond_slave_entry *s_entry;
struct mlx5e_rep_bond_metadata *mdata; struct mlx5e_rep_bond_metadata *mdata;
struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_priv *rpriv;
struct mlx5e_priv *priv;
int err;
ASSERT_RTNL(); ASSERT_RTNL();
...@@ -96,6 +99,11 @@ int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev, ...@@ -96,6 +99,11 @@ int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev,
mdata->lag_dev = lag_dev; mdata->lag_dev = lag_dev;
mdata->esw = esw; mdata->esw = esw;
INIT_LIST_HEAD(&mdata->slaves_list); INIT_LIST_HEAD(&mdata->slaves_list);
mdata->metadata_reg_c_0 = mlx5_esw_match_metadata_alloc(esw);
if (!mdata->metadata_reg_c_0) {
kfree(mdata);
return -ENOSPC;
}
list_add(&mdata->list, &rpriv->uplink_priv.bond->metadata_list); list_add(&mdata->list, &rpriv->uplink_priv.bond->metadata_list);
netdev_dbg(lag_dev, "create rep_bond_metadata(%d)\n", netdev_dbg(lag_dev, "create rep_bond_metadata(%d)\n",
...@@ -103,14 +111,33 @@ int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev, ...@@ -103,14 +111,33 @@ int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev,
} }
s_entry = kzalloc(sizeof(*s_entry), GFP_KERNEL); s_entry = kzalloc(sizeof(*s_entry), GFP_KERNEL);
if (!s_entry) if (!s_entry) {
return -ENOMEM; err = -ENOMEM;
goto entry_alloc_err;
}
s_entry->netdev = netdev; s_entry->netdev = netdev;
priv = netdev_priv(netdev);
rpriv = priv->ppriv;
err = mlx5_esw_acl_ingress_vport_bond_update(esw, rpriv->rep->vport,
mdata->metadata_reg_c_0);
if (err)
goto ingress_err;
mdata->slaves++; mdata->slaves++;
list_add_tail(&s_entry->list, &mdata->slaves_list); list_add_tail(&s_entry->list, &mdata->slaves_list);
netdev_dbg(netdev, "enslave rep vport(%d) lag_dev(%s) metadata(0x%x)\n",
rpriv->rep->vport, lag_dev->name, mdata->metadata_reg_c_0);
return 0; return 0;
ingress_err:
kfree(s_entry);
entry_alloc_err:
if (!mdata->slaves)
mlx5e_rep_bond_metadata_release(mdata);
return err;
} }
/* This must be called under rtnl_lock */ /* This must be called under rtnl_lock */
...@@ -121,6 +148,7 @@ void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw, ...@@ -121,6 +148,7 @@ void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw,
struct mlx5e_rep_bond_slave_entry *s_entry; struct mlx5e_rep_bond_slave_entry *s_entry;
struct mlx5e_rep_bond_metadata *mdata; struct mlx5e_rep_bond_metadata *mdata;
struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_priv *rpriv;
struct mlx5e_priv *priv;
ASSERT_RTNL(); ASSERT_RTNL();
...@@ -133,7 +161,16 @@ void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw, ...@@ -133,7 +161,16 @@ void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw,
if (!s_entry) if (!s_entry)
return; return;
priv = netdev_priv(netdev);
rpriv = priv->ppriv;
mlx5_esw_acl_ingress_vport_bond_update(esw, rpriv->rep->vport, 0);
mlx5e_rep_bond_update(priv, false);
list_del(&s_entry->list); list_del(&s_entry->list);
netdev_dbg(netdev, "unslave rep vport(%d) lag_dev(%s) metadata(0x%x)\n",
rpriv->rep->vport, lag_dev->name, mdata->metadata_reg_c_0);
if (--mdata->slaves == 0) if (--mdata->slaves == 0)
mlx5e_rep_bond_metadata_release(mdata); mlx5e_rep_bond_metadata_release(mdata);
kfree(s_entry); kfree(s_entry);
...@@ -163,6 +200,7 @@ static void mlx5e_rep_changelowerstate_event(struct net_device *netdev, void *pt ...@@ -163,6 +200,7 @@ static void mlx5e_rep_changelowerstate_event(struct net_device *netdev, void *pt
struct net_device *dev; struct net_device *dev;
u16 acl_vport_num; u16 acl_vport_num;
u16 fwd_vport_num; u16 fwd_vport_num;
int err;
if (!mlx5e_rep_is_lag_netdev(netdev)) if (!mlx5e_rep_is_lag_netdev(netdev))
return; return;
...@@ -187,11 +225,28 @@ static void mlx5e_rep_changelowerstate_event(struct net_device *netdev, void *pt ...@@ -187,11 +225,28 @@ static void mlx5e_rep_changelowerstate_event(struct net_device *netdev, void *pt
rpriv = priv->ppriv; rpriv = priv->ppriv;
acl_vport_num = rpriv->rep->vport; acl_vport_num = rpriv->rep->vport;
if (acl_vport_num != fwd_vport_num) { if (acl_vport_num != fwd_vport_num) {
mlx5_esw_acl_egress_vport_bond(priv->mdev->priv.eswitch, /* Only single rx_rule for unique bond_metadata should be
fwd_vport_num, * present, delete it if it's saved as passive vport's
acl_vport_num); * rx_rule with destination as passive vport's root_ft
*/
mlx5e_rep_bond_update(priv, true);
err = mlx5_esw_acl_egress_vport_bond(priv->mdev->priv.eswitch,
fwd_vport_num,
acl_vport_num);
if (err)
netdev_warn(dev,
"configure slave vport(%d) egress fwd, err(%d)",
acl_vport_num, err);
} }
} }
/* Insert new rx_rule for unique bond_metadata, save it as active vport's
* rx_rule with new destination as active vport's root_ft
*/
err = mlx5e_rep_bond_update(netdev_priv(netdev), false);
if (err)
netdev_warn(netdev, "configure active slave vport(%d) rx_rule, err(%d)",
fwd_vport_num, err);
} }
static void mlx5e_rep_changeupper_event(struct net_device *netdev, void *ptr) static void mlx5e_rep_changeupper_event(struct net_device *netdev, void *ptr)
......
...@@ -854,6 +854,24 @@ static int mlx5e_create_rep_vport_rx_rule(struct mlx5e_priv *priv) ...@@ -854,6 +854,24 @@ static int mlx5e_create_rep_vport_rx_rule(struct mlx5e_priv *priv)
return 0; return 0;
} }
static void rep_vport_rx_rule_destroy(struct mlx5e_priv *priv)
{
struct mlx5e_rep_priv *rpriv = priv->ppriv;
if (!rpriv->vport_rx_rule)
return;
mlx5_del_flow_rules(rpriv->vport_rx_rule);
rpriv->vport_rx_rule = NULL;
}
int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup)
{
rep_vport_rx_rule_destroy(priv);
return cleanup ? 0 : mlx5e_create_rep_vport_rx_rule(priv);
}
static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
{ {
struct mlx5_core_dev *mdev = priv->mdev; struct mlx5_core_dev *mdev = priv->mdev;
...@@ -918,9 +936,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) ...@@ -918,9 +936,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv) static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
{ {
struct mlx5e_rep_priv *rpriv = priv->ppriv; rep_vport_rx_rule_destroy(priv);
mlx5_del_flow_rules(rpriv->vport_rx_rule);
mlx5e_destroy_rep_root_ft(priv); mlx5e_destroy_rep_root_ft(priv);
mlx5e_destroy_ttc_table(priv, &priv->fs.ttc); mlx5e_destroy_ttc_table(priv, &priv->fs.ttc);
mlx5e_destroy_direct_tirs(priv, priv->direct_tir); mlx5e_destroy_direct_tirs(priv, priv->direct_tir);
......
...@@ -222,6 +222,7 @@ int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev, ...@@ -222,6 +222,7 @@ int mlx5e_rep_bond_enslave(struct mlx5_eswitch *esw, struct net_device *netdev,
void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw, void mlx5e_rep_bond_unslave(struct mlx5_eswitch *esw,
const struct net_device *netdev, const struct net_device *netdev,
const struct net_device *lag_dev); const struct net_device *lag_dev);
int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup);
bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv); bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv);
int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv); int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv);
......
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