Skip to content

Commit 27484f7

Browse files
Awik84Saeed Mahameed
authored andcommitted
net/mlx5e: Offload tc rules that redirect to ovs internal port
Allow offloading rules that redirect to ovs internal port ingress and egress. To support redirect to ingress device, offloading of REDIRECT_INGRESS action is added. When a tc rule redirects to ovs internal port, the hw rule will overwrite the input vport value in reg_c0 with a new vport metadata value that is mapped for this internal port using the internal port mapping api that is introduce in previous patches. After that the hw rule will redirect the packet to the root table to continue processing with the new vport metadata value. The new vport metadata value indicates that this packet is now arriving through an internal port and therefore should be processed using rules that apply on the same internal port as the filter device. Therefore, following rules that apply on this internal port will have to match on the same vport metadata value as part of their matching keys to make sure the packet belongs to the internal port. Signed-off-by: Ariel Levkovich <lariel@nvidia.com> Reviewed-by: Vlad Buslov <vladbu@nvidia.com> Reviewed-by: Roi Dayan <roid@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
1 parent dbac71f commit 27484f7

File tree

6 files changed

+141
-4
lines changed

6 files changed

+141
-4
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,6 @@ void mlx5e_flow_put(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow);
173173

174174
struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow);
175175

176+
struct mlx5e_tc_int_port_priv *
177+
mlx5e_get_int_port_priv(struct mlx5e_priv *priv);
176178
#endif /* __MLX5_EN_TC_PRIV_H__ */

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

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,23 @@ mlx5e_tc_match_to_reg_set_and_get_id(struct mlx5_core_dev *mdev,
231231
return err;
232232
}
233233

234+
struct mlx5e_tc_int_port_priv *
235+
mlx5e_get_int_port_priv(struct mlx5e_priv *priv)
236+
{
237+
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
238+
struct mlx5_rep_uplink_priv *uplink_priv;
239+
struct mlx5e_rep_priv *uplink_rpriv;
240+
241+
if (is_mdev_switchdev_mode(priv->mdev)) {
242+
uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
243+
uplink_priv = &uplink_rpriv->uplink_priv;
244+
245+
return uplink_priv->int_port_priv;
246+
}
247+
248+
return NULL;
249+
}
250+
234251
static struct mlx5_tc_ct_priv *
235252
get_ct_priv(struct mlx5e_priv *priv)
236253
{
@@ -1573,6 +1590,9 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
15731590
if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
15741591
mlx5_fc_destroy(esw_attr->counter_dev, attr->counter);
15751592

1593+
if (esw_attr->dest_int_port)
1594+
mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->dest_int_port);
1595+
15761596
if (flow_flag_test(flow, L3_TO_L2_DECAP))
15771597
mlx5e_detach_decap(priv, flow);
15781598

@@ -3814,6 +3834,45 @@ static int verify_uplink_forwarding(struct mlx5e_priv *priv,
38143834
return 0;
38153835
}
38163836

3837+
int mlx5e_set_fwd_to_int_port_actions(struct mlx5e_priv *priv,
3838+
struct mlx5_flow_attr *attr,
3839+
int ifindex,
3840+
enum mlx5e_tc_int_port_type type,
3841+
u32 *action,
3842+
int out_index)
3843+
{
3844+
struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
3845+
struct mlx5e_tc_int_port_priv *int_port_priv;
3846+
struct mlx5e_tc_flow_parse_attr *parse_attr;
3847+
struct mlx5e_tc_int_port *dest_int_port;
3848+
int err;
3849+
3850+
parse_attr = attr->parse_attr;
3851+
int_port_priv = mlx5e_get_int_port_priv(priv);
3852+
3853+
dest_int_port = mlx5e_tc_int_port_get(int_port_priv, ifindex, type);
3854+
if (IS_ERR(dest_int_port))
3855+
return PTR_ERR(dest_int_port);
3856+
3857+
err = mlx5e_tc_match_to_reg_set(priv->mdev, &parse_attr->mod_hdr_acts,
3858+
MLX5_FLOW_NAMESPACE_FDB, VPORT_TO_REG,
3859+
mlx5e_tc_int_port_get_metadata(dest_int_port));
3860+
if (err) {
3861+
mlx5e_tc_int_port_put(int_port_priv, dest_int_port);
3862+
return err;
3863+
}
3864+
3865+
*action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
3866+
3867+
esw_attr->dest_int_port = dest_int_port;
3868+
esw_attr->dests[out_index].flags |= MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE;
3869+
3870+
/* Forward to root fdb for matching against the new source vport */
3871+
attr->dest_chain = 0;
3872+
3873+
return 0;
3874+
}
3875+
38173876
static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
38183877
struct flow_action *flow_action,
38193878
struct mlx5e_tc_flow *flow,
@@ -3833,6 +3892,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
38333892
bool encap = false, decap = false;
38343893
u32 action = attr->action;
38353894
int err, i, if_count = 0;
3895+
bool ptype_host = false;
38363896
bool mpls_push = false;
38373897

38383898
if (!flow_action_has_entries(flow_action)) {
@@ -3862,6 +3922,8 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
38623922
"skbedit ptype is only supported with type host");
38633923
return -EOPNOTSUPP;
38643924
}
3925+
3926+
ptype_host = true;
38653927
break;
38663928
case FLOW_ACTION_DROP:
38673929
action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
@@ -3926,6 +3988,50 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
39263988
break;
39273989

39283990
return -EOPNOTSUPP;
3991+
case FLOW_ACTION_REDIRECT_INGRESS: {
3992+
struct net_device *out_dev;
3993+
3994+
out_dev = act->dev;
3995+
if (!out_dev)
3996+
return -EOPNOTSUPP;
3997+
3998+
if (!netif_is_ovs_master(out_dev)) {
3999+
NL_SET_ERR_MSG_MOD(extack,
4000+
"redirect to ingress is supported only for OVS internal ports");
4001+
return -EOPNOTSUPP;
4002+
}
4003+
4004+
if (netif_is_ovs_master(parse_attr->filter_dev)) {
4005+
NL_SET_ERR_MSG_MOD(extack,
4006+
"redirect to ingress is not supported from internal port");
4007+
return -EOPNOTSUPP;
4008+
}
4009+
4010+
if (!ptype_host) {
4011+
NL_SET_ERR_MSG_MOD(extack,
4012+
"redirect to int port ingress requires ptype=host action");
4013+
return -EOPNOTSUPP;
4014+
}
4015+
4016+
if (esw_attr->out_count) {
4017+
NL_SET_ERR_MSG_MOD(extack,
4018+
"redirect to int port ingress is supported only as single destination");
4019+
return -EOPNOTSUPP;
4020+
}
4021+
4022+
action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
4023+
MLX5_FLOW_CONTEXT_ACTION_COUNT;
4024+
4025+
err = mlx5e_set_fwd_to_int_port_actions(priv, attr, out_dev->ifindex,
4026+
MLX5E_TC_INT_PORT_INGRESS,
4027+
&action, esw_attr->out_count);
4028+
if (err)
4029+
return err;
4030+
4031+
esw_attr->out_count++;
4032+
4033+
break;
4034+
}
39294035
case FLOW_ACTION_REDIRECT:
39304036
case FLOW_ACTION_MIRRED: {
39314037
struct mlx5e_priv *out_priv;
@@ -4035,6 +4141,16 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
40354141
rpriv = out_priv->ppriv;
40364142
esw_attr->dests[esw_attr->out_count].rep = rpriv->rep;
40374143
esw_attr->dests[esw_attr->out_count].mdev = out_priv->mdev;
4144+
esw_attr->out_count++;
4145+
} else if (netif_is_ovs_master(out_dev)) {
4146+
err = mlx5e_set_fwd_to_int_port_actions(priv, attr,
4147+
out_dev->ifindex,
4148+
MLX5E_TC_INT_PORT_EGRESS,
4149+
&action,
4150+
esw_attr->out_count);
4151+
if (err)
4152+
return err;
4153+
40384154
esw_attr->out_count++;
40394155
} else if (parse_attr->filter_dev != priv->netdev) {
40404156
/* All mlx5 devices are called to configure
@@ -4136,6 +4252,13 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
41364252
}
41374253
}
41384254

4255+
/* If we forward to internal port we can only have 1 dest */
4256+
if (esw_attr->dest_int_port && esw_attr->out_count > 1) {
4257+
NL_SET_ERR_MSG_MOD(extack,
4258+
"Redirect to internal port should be the only destination");
4259+
return -EOPNOTSUPP;
4260+
}
4261+
41394262
/* always set IP version for indirect table handling */
41404263
attr->ip_version = mlx5e_tc_get_ip_version(&parse_attr->spec, true);
41414264

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ bool mlx5e_tc_is_vf_tunnel(struct net_device *out_dev, struct net_device *route_
286286
int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *route_dev,
287287
u16 *vport);
288288

289+
int mlx5e_set_fwd_to_int_port_actions(struct mlx5e_priv *priv,
290+
struct mlx5_flow_attr *attr,
291+
int ifindex,
292+
enum mlx5e_tc_int_port_type type,
293+
u32 *action,
294+
int out_index);
289295
#else /* CONFIG_MLX5_CLS_ACT */
290296
static inline int mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; }
291297
static inline void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) {}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ struct mlx5_esw_flow_attr {
467467
struct mlx5_eswitch_rep *in_rep;
468468
struct mlx5_core_dev *in_mdev;
469469
struct mlx5_core_dev *counter_dev;
470+
struct mlx5e_tc_int_port *dest_int_port;
470471

471472
int split_count;
472473
int out_count;

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,11 @@ esw_setup_chain_src_port_rewrite(struct mlx5_flow_destination *dest,
290290
err = esw_setup_chain_dest(dest, flow_act, chains, attr->dest_chain, 1, 0, *i);
291291
if (err)
292292
goto err_setup_chain;
293-
flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
294-
flow_act->pkt_reformat = esw_attr->dests[j].pkt_reformat;
293+
294+
if (esw_attr->dests[j].pkt_reformat) {
295+
flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
296+
flow_act->pkt_reformat = esw_attr->dests[j].pkt_reformat;
297+
}
295298
}
296299
return 0;
297300

@@ -315,7 +318,8 @@ esw_is_indir_table(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr)
315318
int i;
316319

317320
for (i = esw_attr->split_count; i < esw_attr->out_count; i++)
318-
if (mlx5_esw_indir_table_needed(esw, attr, esw_attr->dests[i].rep->vport,
321+
if (esw_attr->dests[i].rep &&
322+
mlx5_esw_indir_table_needed(esw, attr, esw_attr->dests[i].rep->vport,
319323
esw_attr->dests[i].mdev))
320324
return true;
321325
return false;

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ mlx5_eswitch_termtbl_required(struct mlx5_eswitch *esw,
229229

230230
/* hairpin */
231231
for (i = esw_attr->split_count; i < esw_attr->out_count; i++)
232-
if (esw_attr->dests[i].rep->vport == MLX5_VPORT_UPLINK)
232+
if (esw_attr->dests[i].rep &&
233+
esw_attr->dests[i].rep->vport == MLX5_VPORT_UPLINK)
233234
return true;
234235

235236
return false;

0 commit comments

Comments
 (0)