Skip to content

Commit b4a2332

Browse files
roidayanSaeed Mahameed
authored andcommitted
net/mlx5e: Re-attempt to offload flows on multipath port affinity events
Under multipath it's possible for us to offload the flow only through the e-switch for which proper route through the uplink exists. When the port is up and the next-hop route is set again we want to offload through it as well. We generate SW event from the FIB event handler when multipath port affinity changes. The tc offloads code gets this event, goes over the flows which were marked as of having missing route and attempts to offload them. Signed-off-by: Roi Dayan <[email protected]> Reviewed-by: Or Gerlitz <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 6997b1c commit b4a2332

File tree

4 files changed

+71
-12
lines changed

4 files changed

+71
-12
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en_rep.c

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,8 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
15731573
if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
15741574
uplink_priv = &rpriv->uplink_priv;
15751575

1576+
INIT_LIST_HEAD(&uplink_priv->unready_flows);
1577+
15761578
/* init shared tc flow table */
15771579
err = mlx5e_tc_esw_init(&uplink_priv->tc_ht);
15781580
if (err)
@@ -1632,34 +1634,48 @@ static void mlx5e_vf_rep_enable(struct mlx5e_priv *priv)
16321634
static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event, void *data)
16331635
{
16341636
struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, events_nb);
1635-
struct mlx5_eqe *eqe = data;
16361637

1637-
if (event != MLX5_EVENT_TYPE_PORT_CHANGE)
1638-
return NOTIFY_DONE;
1638+
if (event == MLX5_EVENT_TYPE_PORT_CHANGE) {
1639+
struct mlx5_eqe *eqe = data;
16391640

1640-
switch (eqe->sub_type) {
1641-
case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
1642-
case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
1643-
queue_work(priv->wq, &priv->update_carrier_work);
1644-
break;
1645-
default:
1646-
return NOTIFY_DONE;
1641+
switch (eqe->sub_type) {
1642+
case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
1643+
case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
1644+
queue_work(priv->wq, &priv->update_carrier_work);
1645+
break;
1646+
default:
1647+
return NOTIFY_DONE;
1648+
}
1649+
1650+
return NOTIFY_OK;
16471651
}
16481652

1649-
return NOTIFY_OK;
1653+
if (event == MLX5_DEV_EVENT_PORT_AFFINITY) {
1654+
struct mlx5e_rep_priv *rpriv = priv->ppriv;
1655+
1656+
queue_work(priv->wq, &rpriv->uplink_priv.reoffload_flows_work);
1657+
1658+
return NOTIFY_OK;
1659+
}
1660+
1661+
return NOTIFY_DONE;
16501662
}
16511663

16521664
static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
16531665
{
16541666
struct net_device *netdev = priv->netdev;
16551667
struct mlx5_core_dev *mdev = priv->mdev;
1668+
struct mlx5e_rep_priv *rpriv = priv->ppriv;
16561669
u16 max_mtu;
16571670

16581671
netdev->min_mtu = ETH_MIN_MTU;
16591672
mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
16601673
netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
16611674
mlx5e_set_dev_port_mtu(priv);
16621675

1676+
INIT_WORK(&rpriv->uplink_priv.reoffload_flows_work,
1677+
mlx5e_tc_reoffload_flows_work);
1678+
16631679
mlx5_lag_add(mdev, netdev);
16641680
priv->events_nb.notifier_call = uplink_rep_async_event;
16651681
mlx5_notifier_register(mdev, &priv->events_nb);
@@ -1672,11 +1688,13 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
16721688
static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
16731689
{
16741690
struct mlx5_core_dev *mdev = priv->mdev;
1691+
struct mlx5e_rep_priv *rpriv = priv->ppriv;
16751692

16761693
#ifdef CONFIG_MLX5_CORE_EN_DCB
16771694
mlx5e_dcbnl_delete_app(priv);
16781695
#endif
16791696
mlx5_notifier_unregister(mdev, &priv->events_nb);
1697+
cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work);
16801698
mlx5_lag_remove(mdev);
16811699
}
16821700

drivers/net/ethernet/mellanox/mlx5/core/en_rep.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ struct mlx5_rep_uplink_priv {
7474
struct notifier_block netdevice_nb;
7575

7676
struct mlx5_tun_entropy tun_entropy;
77+
78+
struct list_head unready_flows;
79+
struct work_struct reoffload_flows_work;
7780
};
7881

7982
struct mlx5e_rep_priv {

drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ struct mlx5e_tc_flow {
117117
struct list_head mod_hdr; /* flows sharing the same mod hdr ID */
118118
struct list_head hairpin; /* flows sharing the same hairpin */
119119
struct list_head peer; /* flows with peer flow */
120+
struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */
120121
union {
121122
struct mlx5_esw_flow_attr esw_attr[0];
122123
struct mlx5_nic_flow_attr nic_attr[0];
@@ -928,6 +929,26 @@ mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw,
928929
flow->flags &= ~MLX5E_TC_FLOW_SLOW;
929930
}
930931

932+
static void add_unready_flow(struct mlx5e_tc_flow *flow)
933+
{
934+
struct mlx5_rep_uplink_priv *uplink_priv;
935+
struct mlx5e_rep_priv *rpriv;
936+
struct mlx5_eswitch *esw;
937+
938+
esw = flow->priv->mdev->priv.eswitch;
939+
rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
940+
uplink_priv = &rpriv->uplink_priv;
941+
942+
flow->flags |= MLX5E_TC_FLOW_NOT_READY;
943+
list_add_tail(&flow->unready, &uplink_priv->unready_flows);
944+
}
945+
946+
static void remove_unready_flow(struct mlx5e_tc_flow *flow)
947+
{
948+
list_del(&flow->unready);
949+
flow->flags &= ~MLX5E_TC_FLOW_NOT_READY;
950+
}
951+
931952
static int
932953
mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
933954
struct mlx5e_tc_flow *flow,
@@ -1049,6 +1070,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
10491070
int out_index;
10501071

10511072
if (flow->flags & MLX5E_TC_FLOW_NOT_READY) {
1073+
remove_unready_flow(flow);
10521074
kvfree(attr->parse_attr);
10531075
return;
10541076
}
@@ -2810,7 +2832,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv,
28102832
if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev)))
28112833
goto err_free;
28122834

2813-
flow->flags |= MLX5E_TC_FLOW_NOT_READY;
2835+
add_unready_flow(flow);
28142836
}
28152837

28162838
return flow;
@@ -3214,3 +3236,18 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw)
32143236
list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer)
32153237
__mlx5e_tc_del_fdb_peer_flow(flow);
32163238
}
3239+
3240+
void mlx5e_tc_reoffload_flows_work(struct work_struct *work)
3241+
{
3242+
struct mlx5_rep_uplink_priv *rpriv =
3243+
container_of(work, struct mlx5_rep_uplink_priv,
3244+
reoffload_flows_work);
3245+
struct mlx5e_tc_flow *flow, *tmp;
3246+
3247+
rtnl_lock();
3248+
list_for_each_entry_safe(flow, tmp, &rpriv->unready_flows, unready) {
3249+
if (!mlx5e_tc_add_fdb_flow(flow->priv, flow, NULL))
3250+
remove_unready_flow(flow);
3251+
}
3252+
rtnl_unlock();
3253+
}

drivers/net/ethernet/mellanox/mlx5/core/en_tc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe);
7272

7373
int mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags);
7474

75+
void mlx5e_tc_reoffload_flows_work(struct work_struct *work);
7576

7677
#else /* CONFIG_MLX5_ESWITCH */
7778
static inline int mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; }

0 commit comments

Comments
 (0)