net/mlx5e: Add pedit to tc action infra
Add parsing support by implementing struct mlx5e_tc_act for this action. Signed-off-by: Roi Dayan <roid@nvidia.com> Reviewed-by: Oz Shlomo <ozsh@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
parent
9ca1bb2cf6
commit
e36db1ee7a
@ -49,7 +49,7 @@ mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en_tc.o en/rep/tc.o en/rep/neigh.o \
|
|||||||
|
|
||||||
mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en/tc/act/act.o en/tc/act/drop.o en/tc/act/trap.o \
|
mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en/tc/act/act.o en/tc/act/drop.o en/tc/act/trap.o \
|
||||||
en/tc/act/accept.o en/tc/act/mark.o en/tc/act/goto.o \
|
en/tc/act/accept.o en/tc/act/mark.o en/tc/act/goto.o \
|
||||||
en/tc/act/tun.o en/tc/act/csum.o
|
en/tc/act/tun.o en/tc/act/csum.o en/tc/act/pedit.o
|
||||||
|
|
||||||
mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o
|
mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o
|
||||||
mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += en/tc/sample.o
|
mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += en/tc/sample.o
|
||||||
|
@ -20,8 +20,8 @@ static struct mlx5e_tc_act *tc_acts_fdb[NUM_FLOW_ACTIONS] = {
|
|||||||
NULL, /* FLOW_ACTION_VLAN_MANGLE, */
|
NULL, /* FLOW_ACTION_VLAN_MANGLE, */
|
||||||
&mlx5e_tc_act_tun_encap,
|
&mlx5e_tc_act_tun_encap,
|
||||||
&mlx5e_tc_act_tun_decap,
|
&mlx5e_tc_act_tun_decap,
|
||||||
NULL, /* FLOW_ACTION_MANGLE, */
|
&mlx5e_tc_act_pedit,
|
||||||
NULL, /* FLOW_ACTION_ADD, */
|
&mlx5e_tc_act_pedit,
|
||||||
&mlx5e_tc_act_csum,
|
&mlx5e_tc_act_csum,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,8 +40,8 @@ static struct mlx5e_tc_act *tc_acts_nic[NUM_FLOW_ACTIONS] = {
|
|||||||
NULL, /* FLOW_ACTION_VLAN_MANGLE, */
|
NULL, /* FLOW_ACTION_VLAN_MANGLE, */
|
||||||
NULL, /* FLOW_ACTION_TUNNEL_ENCAP, */
|
NULL, /* FLOW_ACTION_TUNNEL_ENCAP, */
|
||||||
NULL, /* FLOW_ACTION_TUNNEL_DECAP, */
|
NULL, /* FLOW_ACTION_TUNNEL_DECAP, */
|
||||||
NULL, /* FLOW_ACTION_MANGLE, */
|
&mlx5e_tc_act_pedit,
|
||||||
NULL, /* FLOW_ACTION_ADD, */
|
&mlx5e_tc_act_pedit,
|
||||||
&mlx5e_tc_act_csum,
|
&mlx5e_tc_act_csum,
|
||||||
&mlx5e_tc_act_mark,
|
&mlx5e_tc_act_mark,
|
||||||
};
|
};
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
#ifndef __MLX5_EN_TC_ACT_H__
|
#ifndef __MLX5_EN_TC_ACT_H__
|
||||||
#define __MLX5_EN_TC_ACT_H__
|
#define __MLX5_EN_TC_ACT_H__
|
||||||
|
|
||||||
|
#include <net/tc_act/tc_pedit.h>
|
||||||
#include <net/flow_offload.h>
|
#include <net/flow_offload.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include "eswitch.h"
|
#include "eswitch.h"
|
||||||
|
#include "pedit.h"
|
||||||
|
|
||||||
struct mlx5_flow_attr;
|
struct mlx5_flow_attr;
|
||||||
|
|
||||||
@ -17,6 +19,7 @@ struct mlx5e_tc_act_parse_state {
|
|||||||
bool encap;
|
bool encap;
|
||||||
bool decap;
|
bool decap;
|
||||||
const struct ip_tunnel_info *tun_info;
|
const struct ip_tunnel_info *tun_info;
|
||||||
|
struct pedit_headers_action hdrs[__PEDIT_CMD_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlx5e_tc_act {
|
struct mlx5e_tc_act {
|
||||||
@ -38,6 +41,7 @@ extern struct mlx5e_tc_act mlx5e_tc_act_goto;
|
|||||||
extern struct mlx5e_tc_act mlx5e_tc_act_tun_encap;
|
extern struct mlx5e_tc_act mlx5e_tc_act_tun_encap;
|
||||||
extern struct mlx5e_tc_act mlx5e_tc_act_tun_decap;
|
extern struct mlx5e_tc_act mlx5e_tc_act_tun_decap;
|
||||||
extern struct mlx5e_tc_act mlx5e_tc_act_csum;
|
extern struct mlx5e_tc_act mlx5e_tc_act_csum;
|
||||||
|
extern struct mlx5e_tc_act mlx5e_tc_act_pedit;
|
||||||
|
|
||||||
struct mlx5e_tc_act *
|
struct mlx5e_tc_act *
|
||||||
mlx5e_tc_act_get(enum flow_action_id act_id,
|
mlx5e_tc_act_get(enum flow_action_id act_id,
|
||||||
|
165
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c
Normal file
165
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.c
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||||
|
// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
#include "act.h"
|
||||||
|
#include "pedit.h"
|
||||||
|
#include "en/tc_priv.h"
|
||||||
|
#include "en/mod_hdr.h"
|
||||||
|
|
||||||
|
static int pedit_header_offsets[] = {
|
||||||
|
[FLOW_ACT_MANGLE_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth),
|
||||||
|
[FLOW_ACT_MANGLE_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4),
|
||||||
|
[FLOW_ACT_MANGLE_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6),
|
||||||
|
[FLOW_ACT_MANGLE_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp),
|
||||||
|
[FLOW_ACT_MANGLE_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp),
|
||||||
|
};
|
||||||
|
|
||||||
|
#define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype])
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
|
||||||
|
struct pedit_headers_action *hdrs,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
u32 *curr_pmask, *curr_pval;
|
||||||
|
|
||||||
|
curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset);
|
||||||
|
curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset);
|
||||||
|
|
||||||
|
if (*curr_pmask & mask) { /* disallow acting twice on the same location */
|
||||||
|
NL_SET_ERR_MSG_MOD(extack,
|
||||||
|
"curr_pmask and new mask same. Acting twice on same location");
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*curr_pmask |= mask;
|
||||||
|
*curr_pval |= (val & mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_pedit_to_modify_hdr(struct mlx5e_priv *priv,
|
||||||
|
const struct flow_action_entry *act, int namespace,
|
||||||
|
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||||
|
struct pedit_headers_action *hdrs,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1;
|
||||||
|
u8 htype = act->mangle.htype;
|
||||||
|
int err = -EOPNOTSUPP;
|
||||||
|
u32 mask, val, offset;
|
||||||
|
|
||||||
|
if (htype == FLOW_ACT_MANGLE_UNSPEC) {
|
||||||
|
NL_SET_ERR_MSG_MOD(extack, "legacy pedit isn't offloaded");
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mlx5e_mod_hdr_max_actions(priv->mdev, namespace)) {
|
||||||
|
NL_SET_ERR_MSG_MOD(extack, "The pedit offload action is not supported");
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
mask = act->mangle.mask;
|
||||||
|
val = act->mangle.val;
|
||||||
|
offset = act->mangle.offset;
|
||||||
|
|
||||||
|
err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd], extack);
|
||||||
|
if (err)
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
hdrs[cmd].pedits++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out_err:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_pedit_to_reformat(const struct flow_action_entry *act,
|
||||||
|
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
u32 mask, val, offset;
|
||||||
|
u32 *p;
|
||||||
|
|
||||||
|
if (act->id != FLOW_ACTION_MANGLE) {
|
||||||
|
NL_SET_ERR_MSG_MOD(extack, "Unsupported action id");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (act->mangle.htype != FLOW_ACT_MANGLE_HDR_TYPE_ETH) {
|
||||||
|
NL_SET_ERR_MSG_MOD(extack, "Only Ethernet modification is supported");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
mask = ~act->mangle.mask;
|
||||||
|
val = act->mangle.val;
|
||||||
|
offset = act->mangle.offset;
|
||||||
|
p = (u32 *)&parse_attr->eth;
|
||||||
|
*(p + (offset >> 2)) |= (val & mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mlx5e_tc_act_pedit_parse_action(struct mlx5e_priv *priv,
|
||||||
|
const struct flow_action_entry *act, int namespace,
|
||||||
|
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||||
|
struct pedit_headers_action *hdrs,
|
||||||
|
struct mlx5e_tc_flow *flow,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
if (flow && flow_flag_test(flow, L3_TO_L2_DECAP))
|
||||||
|
return parse_pedit_to_reformat(act, parse_attr, extack);
|
||||||
|
|
||||||
|
return parse_pedit_to_modify_hdr(priv, act, namespace, parse_attr, hdrs, extack);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
tc_act_can_offload_pedit(struct mlx5e_tc_act_parse_state *parse_state,
|
||||||
|
const struct flow_action_entry *act,
|
||||||
|
int act_index)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
tc_act_parse_pedit(struct mlx5e_tc_act_parse_state *parse_state,
|
||||||
|
const struct flow_action_entry *act,
|
||||||
|
struct mlx5e_priv *priv,
|
||||||
|
struct mlx5_flow_attr *attr)
|
||||||
|
{
|
||||||
|
struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
|
||||||
|
struct mlx5e_tc_flow *flow = parse_state->flow;
|
||||||
|
enum mlx5_flow_namespace_type ns_type;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
ns_type = mlx5e_get_flow_namespace(flow);
|
||||||
|
|
||||||
|
err = mlx5e_tc_act_pedit_parse_action(flow->priv, act, ns_type,
|
||||||
|
attr->parse_attr, parse_state->hdrs,
|
||||||
|
flow, parse_state->extack);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (flow_flag_test(flow, L3_TO_L2_DECAP))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||||
|
|
||||||
|
if (ns_type == MLX5_FLOW_NAMESPACE_FDB)
|
||||||
|
esw_attr->split_count = esw_attr->out_count;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mlx5e_tc_act mlx5e_tc_act_pedit = {
|
||||||
|
.can_offload = tc_act_can_offload_pedit,
|
||||||
|
.parse_action = tc_act_parse_pedit,
|
||||||
|
};
|
32
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.h
Normal file
32
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/pedit.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||||
|
/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
|
||||||
|
|
||||||
|
#ifndef __MLX5_EN_TC_ACT_PEDIT_H__
|
||||||
|
#define __MLX5_EN_TC_ACT_PEDIT_H__
|
||||||
|
|
||||||
|
#include "en_tc.h"
|
||||||
|
|
||||||
|
struct pedit_headers {
|
||||||
|
struct ethhdr eth;
|
||||||
|
struct vlan_hdr vlan;
|
||||||
|
struct iphdr ip4;
|
||||||
|
struct ipv6hdr ip6;
|
||||||
|
struct tcphdr tcp;
|
||||||
|
struct udphdr udp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pedit_headers_action {
|
||||||
|
struct pedit_headers vals;
|
||||||
|
struct pedit_headers masks;
|
||||||
|
u32 pedits;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
mlx5e_tc_act_pedit_parse_action(struct mlx5e_priv *priv,
|
||||||
|
const struct flow_action_entry *act, int namespace,
|
||||||
|
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||||
|
struct pedit_headers_action *hdrs,
|
||||||
|
struct mlx5e_tc_flow *flow,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
|
|
||||||
|
#endif /* __MLX5_EN_TC_ACT_PEDIT_H__ */
|
@ -122,6 +122,7 @@ mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw,
|
|||||||
bool mlx5e_is_eswitch_flow(struct mlx5e_tc_flow *flow);
|
bool mlx5e_is_eswitch_flow(struct mlx5e_tc_flow *flow);
|
||||||
bool mlx5e_is_ft_flow(struct mlx5e_tc_flow *flow);
|
bool mlx5e_is_ft_flow(struct mlx5e_tc_flow *flow);
|
||||||
bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow);
|
bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow);
|
||||||
|
int mlx5e_get_flow_namespace(struct mlx5e_tc_flow *flow);
|
||||||
|
|
||||||
static inline void __flow_flag_set(struct mlx5e_tc_flow *flow, unsigned long flag)
|
static inline void __flow_flag_set(struct mlx5e_tc_flow *flow, unsigned long flag)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
#include <linux/refcount.h>
|
#include <linux/refcount.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/if_macvlan.h>
|
#include <linux/if_macvlan.h>
|
||||||
#include <net/tc_act/tc_pedit.h>
|
|
||||||
#include <net/psample.h>
|
#include <net/psample.h>
|
||||||
#include <net/arp.h>
|
#include <net/arp.h>
|
||||||
#include <net/ipv6_stubs.h>
|
#include <net/ipv6_stubs.h>
|
||||||
@ -62,6 +61,7 @@
|
|||||||
#include "en/tc_tun_encap.h"
|
#include "en/tc_tun_encap.h"
|
||||||
#include "en/tc/sample.h"
|
#include "en/tc/sample.h"
|
||||||
#include "en/tc/act/act.h"
|
#include "en/tc/act/act.h"
|
||||||
|
#include "en/tc/act/pedit.h"
|
||||||
#include "lib/devcom.h"
|
#include "lib/devcom.h"
|
||||||
#include "lib/geneve.h"
|
#include "lib/geneve.h"
|
||||||
#include "lib/fs_chains.h"
|
#include "lib/fs_chains.h"
|
||||||
@ -407,7 +407,7 @@ bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow)
|
|||||||
return flow_flag_test(flow, OFFLOADED);
|
return flow_flag_test(flow, OFFLOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_flow_name_space(struct mlx5e_tc_flow *flow)
|
int mlx5e_get_flow_namespace(struct mlx5e_tc_flow *flow)
|
||||||
{
|
{
|
||||||
return mlx5e_is_eswitch_flow(flow) ?
|
return mlx5e_is_eswitch_flow(flow) ?
|
||||||
MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL;
|
MLX5_FLOW_NAMESPACE_FDB : MLX5_FLOW_NAMESPACE_KERNEL;
|
||||||
@ -418,7 +418,7 @@ get_mod_hdr_table(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow)
|
|||||||
{
|
{
|
||||||
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
||||||
|
|
||||||
return get_flow_name_space(flow) == MLX5_FLOW_NAMESPACE_FDB ?
|
return mlx5e_get_flow_namespace(flow) == MLX5_FLOW_NAMESPACE_FDB ?
|
||||||
&esw->offloads.mod_hdr :
|
&esw->offloads.mod_hdr :
|
||||||
&priv->fs.tc.mod_hdr;
|
&priv->fs.tc.mod_hdr;
|
||||||
}
|
}
|
||||||
@ -431,7 +431,7 @@ static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
|
|||||||
struct mlx5e_mod_hdr_handle *mh;
|
struct mlx5e_mod_hdr_handle *mh;
|
||||||
|
|
||||||
mh = mlx5e_mod_hdr_attach(priv->mdev, get_mod_hdr_table(priv, flow),
|
mh = mlx5e_mod_hdr_attach(priv->mdev, get_mod_hdr_table(priv, flow),
|
||||||
get_flow_name_space(flow),
|
mlx5e_get_flow_namespace(flow),
|
||||||
&parse_attr->mod_hdr_acts);
|
&parse_attr->mod_hdr_acts);
|
||||||
if (IS_ERR(mh))
|
if (IS_ERR(mh))
|
||||||
return PTR_ERR(mh);
|
return PTR_ERR(mh);
|
||||||
@ -1365,7 +1365,7 @@ int mlx5e_tc_add_flow_mod_hdr(struct mlx5e_priv *priv,
|
|||||||
struct mlx5_modify_hdr *mod_hdr;
|
struct mlx5_modify_hdr *mod_hdr;
|
||||||
|
|
||||||
mod_hdr = mlx5_modify_header_alloc(priv->mdev,
|
mod_hdr = mlx5_modify_header_alloc(priv->mdev,
|
||||||
get_flow_name_space(flow),
|
mlx5e_get_flow_namespace(flow),
|
||||||
mod_hdr_acts->num_actions,
|
mod_hdr_acts->num_actions,
|
||||||
mod_hdr_acts->actions);
|
mod_hdr_acts->actions);
|
||||||
if (IS_ERR(mod_hdr))
|
if (IS_ERR(mod_hdr))
|
||||||
@ -2605,55 +2605,6 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pedit_headers {
|
|
||||||
struct ethhdr eth;
|
|
||||||
struct vlan_hdr vlan;
|
|
||||||
struct iphdr ip4;
|
|
||||||
struct ipv6hdr ip6;
|
|
||||||
struct tcphdr tcp;
|
|
||||||
struct udphdr udp;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pedit_headers_action {
|
|
||||||
struct pedit_headers vals;
|
|
||||||
struct pedit_headers masks;
|
|
||||||
u32 pedits;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int pedit_header_offsets[] = {
|
|
||||||
[FLOW_ACT_MANGLE_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth),
|
|
||||||
[FLOW_ACT_MANGLE_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4),
|
|
||||||
[FLOW_ACT_MANGLE_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6),
|
|
||||||
[FLOW_ACT_MANGLE_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp),
|
|
||||||
[FLOW_ACT_MANGLE_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp),
|
|
||||||
};
|
|
||||||
|
|
||||||
#define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype])
|
|
||||||
|
|
||||||
static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset,
|
|
||||||
struct pedit_headers_action *hdrs,
|
|
||||||
struct netlink_ext_ack *extack)
|
|
||||||
{
|
|
||||||
u32 *curr_pmask, *curr_pval;
|
|
||||||
|
|
||||||
curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset);
|
|
||||||
curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset);
|
|
||||||
|
|
||||||
if (*curr_pmask & mask) { /* disallow acting twice on the same location */
|
|
||||||
NL_SET_ERR_MSG_MOD(extack,
|
|
||||||
"curr_pmask and new mask same. Acting twice on same location");
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
*curr_pmask |= mask;
|
|
||||||
*curr_pval |= (val & mask);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_err:
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mlx5_fields {
|
struct mlx5_fields {
|
||||||
u8 field;
|
u8 field;
|
||||||
u8 field_bsize;
|
u8 field_bsize;
|
||||||
@ -2890,88 +2841,6 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
|
|||||||
|
|
||||||
static const struct pedit_headers zero_masks = {};
|
static const struct pedit_headers zero_masks = {};
|
||||||
|
|
||||||
static int
|
|
||||||
parse_pedit_to_modify_hdr(struct mlx5e_priv *priv,
|
|
||||||
const struct flow_action_entry *act, int namespace,
|
|
||||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
|
||||||
struct pedit_headers_action *hdrs,
|
|
||||||
struct netlink_ext_ack *extack)
|
|
||||||
{
|
|
||||||
u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1;
|
|
||||||
int err = -EOPNOTSUPP;
|
|
||||||
u32 mask, val, offset;
|
|
||||||
u8 htype;
|
|
||||||
|
|
||||||
htype = act->mangle.htype;
|
|
||||||
err = -EOPNOTSUPP; /* can't be all optimistic */
|
|
||||||
|
|
||||||
if (htype == FLOW_ACT_MANGLE_UNSPEC) {
|
|
||||||
NL_SET_ERR_MSG_MOD(extack, "legacy pedit isn't offloaded");
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mlx5e_mod_hdr_max_actions(priv->mdev, namespace)) {
|
|
||||||
NL_SET_ERR_MSG_MOD(extack,
|
|
||||||
"The pedit offload action is not supported");
|
|
||||||
goto out_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
mask = act->mangle.mask;
|
|
||||||
val = act->mangle.val;
|
|
||||||
offset = act->mangle.offset;
|
|
||||||
|
|
||||||
err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd], extack);
|
|
||||||
if (err)
|
|
||||||
goto out_err;
|
|
||||||
|
|
||||||
hdrs[cmd].pedits++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
out_err:
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
parse_pedit_to_reformat(const struct flow_action_entry *act,
|
|
||||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
|
||||||
struct netlink_ext_ack *extack)
|
|
||||||
{
|
|
||||||
u32 mask, val, offset;
|
|
||||||
u32 *p;
|
|
||||||
|
|
||||||
if (act->id != FLOW_ACTION_MANGLE) {
|
|
||||||
NL_SET_ERR_MSG_MOD(extack, "Unsupported action id");
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (act->mangle.htype != FLOW_ACT_MANGLE_HDR_TYPE_ETH) {
|
|
||||||
NL_SET_ERR_MSG_MOD(extack, "Only Ethernet modification is supported");
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
mask = ~act->mangle.mask;
|
|
||||||
val = act->mangle.val;
|
|
||||||
offset = act->mangle.offset;
|
|
||||||
p = (u32 *)&parse_attr->eth;
|
|
||||||
*(p + (offset >> 2)) |= (val & mask);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_tc_pedit_action(struct mlx5e_priv *priv,
|
|
||||||
const struct flow_action_entry *act, int namespace,
|
|
||||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
|
||||||
struct pedit_headers_action *hdrs,
|
|
||||||
struct mlx5e_tc_flow *flow,
|
|
||||||
struct netlink_ext_ack *extack)
|
|
||||||
{
|
|
||||||
if (flow && flow_flag_test(flow, L3_TO_L2_DECAP))
|
|
||||||
return parse_pedit_to_reformat(act, parse_attr, extack);
|
|
||||||
|
|
||||||
return parse_pedit_to_modify_hdr(priv, act, namespace,
|
|
||||||
parse_attr, hdrs, extack);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace,
|
static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace,
|
||||||
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
struct mlx5e_tc_flow_parse_attr *parse_attr,
|
||||||
struct pedit_headers_action *hdrs,
|
struct pedit_headers_action *hdrs,
|
||||||
@ -3295,7 +3164,8 @@ static int add_vlan_rewrite_action(struct mlx5e_priv *priv, int namespace,
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = parse_tc_pedit_action(priv, &pedit_act, namespace, parse_attr, hdrs, NULL, extack);
|
err = mlx5e_tc_act_pedit_parse_action(priv, &pedit_act, namespace, parse_attr, hdrs,
|
||||||
|
NULL, extack);
|
||||||
*action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
*action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@ -3340,7 +3210,7 @@ actions_prepare_mod_hdr_actions(struct mlx5e_priv *priv,
|
|||||||
!hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits)
|
!hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ns_type = get_flow_name_space(flow);
|
ns_type = mlx5e_get_flow_namespace(flow);
|
||||||
|
|
||||||
err = alloc_tc_pedit_action(priv, ns_type, parse_attr, hdrs,
|
err = alloc_tc_pedit_action(priv, ns_type, parse_attr, hdrs,
|
||||||
&attr->action, extack);
|
&attr->action, extack);
|
||||||
@ -3391,9 +3261,9 @@ parse_tc_nic_actions(struct mlx5e_priv *priv,
|
|||||||
struct mlx5e_tc_act_parse_state *parse_state;
|
struct mlx5e_tc_act_parse_state *parse_state;
|
||||||
struct mlx5e_tc_flow_parse_attr *parse_attr;
|
struct mlx5e_tc_flow_parse_attr *parse_attr;
|
||||||
struct mlx5_flow_attr *attr = flow->attr;
|
struct mlx5_flow_attr *attr = flow->attr;
|
||||||
struct pedit_headers_action hdrs[2] = {};
|
|
||||||
enum mlx5_flow_namespace_type ns_type;
|
enum mlx5_flow_namespace_type ns_type;
|
||||||
const struct flow_action_entry *act;
|
const struct flow_action_entry *act;
|
||||||
|
struct pedit_headers_action *hdrs;
|
||||||
struct mlx5e_tc_act *tc_act;
|
struct mlx5e_tc_act *tc_act;
|
||||||
int err, i;
|
int err, i;
|
||||||
|
|
||||||
@ -3405,19 +3275,11 @@ parse_tc_nic_actions(struct mlx5e_priv *priv,
|
|||||||
parse_attr = attr->parse_attr;
|
parse_attr = attr->parse_attr;
|
||||||
parse_state = &parse_attr->parse_state;
|
parse_state = &parse_attr->parse_state;
|
||||||
mlx5e_tc_act_init_parse_state(parse_state, flow, flow_action, extack);
|
mlx5e_tc_act_init_parse_state(parse_state, flow, flow_action, extack);
|
||||||
ns_type = get_flow_name_space(flow);
|
ns_type = mlx5e_get_flow_namespace(flow);
|
||||||
|
hdrs = parse_state->hdrs;
|
||||||
|
|
||||||
flow_action_for_each(i, act, flow_action) {
|
flow_action_for_each(i, act, flow_action) {
|
||||||
switch (act->id) {
|
switch (act->id) {
|
||||||
case FLOW_ACTION_MANGLE:
|
|
||||||
case FLOW_ACTION_ADD:
|
|
||||||
err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_KERNEL,
|
|
||||||
parse_attr, hdrs, NULL, extack);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
|
||||||
break;
|
|
||||||
case FLOW_ACTION_VLAN_MANGLE:
|
case FLOW_ACTION_VLAN_MANGLE:
|
||||||
err = add_vlan_rewrite_action(priv,
|
err = add_vlan_rewrite_action(priv,
|
||||||
MLX5_FLOW_NAMESPACE_KERNEL,
|
MLX5_FLOW_NAMESPACE_KERNEL,
|
||||||
@ -3776,7 +3638,6 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
|||||||
struct mlx5e_tc_flow *flow,
|
struct mlx5e_tc_flow *flow,
|
||||||
struct netlink_ext_ack *extack)
|
struct netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
struct pedit_headers_action hdrs[2] = {};
|
|
||||||
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
||||||
struct mlx5e_tc_act_parse_state *parse_state;
|
struct mlx5e_tc_act_parse_state *parse_state;
|
||||||
struct mlx5e_tc_flow_parse_attr *parse_attr;
|
struct mlx5e_tc_flow_parse_attr *parse_attr;
|
||||||
@ -3788,6 +3649,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
|||||||
enum mlx5_flow_namespace_type ns_type;
|
enum mlx5_flow_namespace_type ns_type;
|
||||||
const struct flow_action_entry *act;
|
const struct flow_action_entry *act;
|
||||||
struct mlx5_esw_flow_attr *esw_attr;
|
struct mlx5_esw_flow_attr *esw_attr;
|
||||||
|
struct pedit_headers_action *hdrs;
|
||||||
struct mlx5e_tc_act *tc_act;
|
struct mlx5e_tc_act *tc_act;
|
||||||
int err, i, if_count = 0;
|
int err, i, if_count = 0;
|
||||||
bool ptype_host = false;
|
bool ptype_host = false;
|
||||||
@ -3801,7 +3663,8 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
|||||||
parse_attr = attr->parse_attr;
|
parse_attr = attr->parse_attr;
|
||||||
parse_state = &parse_attr->parse_state;
|
parse_state = &parse_attr->parse_state;
|
||||||
mlx5e_tc_act_init_parse_state(parse_state, flow, flow_action, extack);
|
mlx5e_tc_act_init_parse_state(parse_state, flow, flow_action, extack);
|
||||||
ns_type = get_flow_name_space(flow);
|
ns_type = mlx5e_get_flow_namespace(flow);
|
||||||
|
hdrs = parse_state->hdrs;
|
||||||
|
|
||||||
flow_action_for_each(i, act, flow_action) {
|
flow_action_for_each(i, act, flow_action) {
|
||||||
switch (act->id) {
|
switch (act->id) {
|
||||||
@ -3845,18 +3708,6 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
|
|||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
|
attr->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
|
||||||
flow_flag_set(flow, L3_TO_L2_DECAP);
|
flow_flag_set(flow, L3_TO_L2_DECAP);
|
||||||
break;
|
break;
|
||||||
case FLOW_ACTION_MANGLE:
|
|
||||||
case FLOW_ACTION_ADD:
|
|
||||||
err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_FDB,
|
|
||||||
parse_attr, hdrs, flow, extack);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (!flow_flag_test(flow, L3_TO_L2_DECAP)) {
|
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
|
||||||
esw_attr->split_count = esw_attr->out_count;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FLOW_ACTION_REDIRECT_INGRESS: {
|
case FLOW_ACTION_REDIRECT_INGRESS: {
|
||||||
struct net_device *out_dev;
|
struct net_device *out_dev;
|
||||||
|
|
||||||
@ -4255,7 +4106,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size,
|
|||||||
flow->cookie = f->cookie;
|
flow->cookie = f->cookie;
|
||||||
flow->priv = priv;
|
flow->priv = priv;
|
||||||
|
|
||||||
attr = mlx5_alloc_flow_attr(get_flow_name_space(flow));
|
attr = mlx5_alloc_flow_attr(mlx5e_get_flow_namespace(flow));
|
||||||
if (!attr)
|
if (!attr)
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user