Skip to content

Commit

Permalink
Merge branch 'mlxsw-VLAN-offload-cls_flower'
Browse files Browse the repository at this point in the history
Jiri Pirko says:

====================
mlxsw: spectrum: Add support for VLAN offload for cls_flower

This patchset adds support to offload VLAN modify TC action and adds support
to offload cls_flower rules that include VID and PCP matching.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 10, 2017
2 parents a30aad5 + 9caab08 commit 1015d74
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 2 deletions.
83 changes: 83 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,89 @@ static char *mlxsw_afa_block_append_action(struct mlxsw_afa_block *block,
return oneact + MLXSW_AFA_PAYLOAD_OFFSET;
}

/* VLAN Action
* -----------
* VLAN action is used for manipulating VLANs. It can be used to implement QinQ,
* VLAN translation, change of PCP bits of the VLAN tag, push, pop as swap VLANs
* and more.
*/

#define MLXSW_AFA_VLAN_CODE 0x02
#define MLXSW_AFA_VLAN_SIZE 1

enum mlxsw_afa_vlan_vlan_tag_cmd {
MLXSW_AFA_VLAN_VLAN_TAG_CMD_NOP,
MLXSW_AFA_VLAN_VLAN_TAG_CMD_PUSH_TAG,
MLXSW_AFA_VLAN_VLAN_TAG_CMD_POP_TAG,
};

enum mlxsw_afa_vlan_cmd {
MLXSW_AFA_VLAN_CMD_NOP,
MLXSW_AFA_VLAN_CMD_SET_OUTER,
MLXSW_AFA_VLAN_CMD_SET_INNER,
MLXSW_AFA_VLAN_CMD_COPY_OUTER_TO_INNER,
MLXSW_AFA_VLAN_CMD_COPY_INNER_TO_OUTER,
MLXSW_AFA_VLAN_CMD_SWAP,
};

/* afa_vlan_vlan_tag_cmd
* Tag command: push, pop, nop VLAN header.
*/
MLXSW_ITEM32(afa, vlan, vlan_tag_cmd, 0x00, 29, 3);

/* afa_vlan_vid_cmd */
MLXSW_ITEM32(afa, vlan, vid_cmd, 0x04, 29, 3);

/* afa_vlan_vid */
MLXSW_ITEM32(afa, vlan, vid, 0x04, 0, 12);

/* afa_vlan_ethertype_cmd */
MLXSW_ITEM32(afa, vlan, ethertype_cmd, 0x08, 29, 3);

/* afa_vlan_ethertype
* Index to EtherTypes in Switch VLAN EtherType Register (SVER).
*/
MLXSW_ITEM32(afa, vlan, ethertype, 0x08, 24, 3);

/* afa_vlan_pcp_cmd */
MLXSW_ITEM32(afa, vlan, pcp_cmd, 0x08, 13, 3);

/* afa_vlan_pcp */
MLXSW_ITEM32(afa, vlan, pcp, 0x08, 8, 3);

static inline void
mlxsw_afa_vlan_pack(char *payload,
enum mlxsw_afa_vlan_vlan_tag_cmd vlan_tag_cmd,
enum mlxsw_afa_vlan_cmd vid_cmd, u16 vid,
enum mlxsw_afa_vlan_cmd pcp_cmd, u8 pcp,
enum mlxsw_afa_vlan_cmd ethertype_cmd, u8 ethertype)
{
mlxsw_afa_vlan_vlan_tag_cmd_set(payload, vlan_tag_cmd);
mlxsw_afa_vlan_vid_cmd_set(payload, vid_cmd);
mlxsw_afa_vlan_vid_set(payload, vid);
mlxsw_afa_vlan_pcp_cmd_set(payload, pcp_cmd);
mlxsw_afa_vlan_pcp_set(payload, pcp);
mlxsw_afa_vlan_ethertype_cmd_set(payload, ethertype_cmd);
mlxsw_afa_vlan_ethertype_set(payload, ethertype);
}

int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
u16 vid, u8 pcp, u8 et)
{
char *act = mlxsw_afa_block_append_action(block,
MLXSW_AFA_VLAN_CODE,
MLXSW_AFA_VLAN_SIZE);

if (!act)
return -ENOBUFS;
mlxsw_afa_vlan_pack(act, MLXSW_AFA_VLAN_VLAN_TAG_CMD_NOP,
MLXSW_AFA_VLAN_CMD_SET_OUTER, vid,
MLXSW_AFA_VLAN_CMD_SET_OUTER, pcp,
MLXSW_AFA_VLAN_CMD_SET_OUTER, et);
return 0;
}
EXPORT_SYMBOL(mlxsw_afa_block_append_vlan_modify);

/* Trap / Discard Action
* ---------------------
* The Trap / Discard action enables trapping / mirroring packets to the CPU
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,7 @@ void mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id);
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block);
int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
u8 local_port, bool in_port);
int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
u16 vid, u8 pcp, u8 et);

#endif
6 changes: 5 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ enum mlxsw_afk_element {
MLXSW_AFK_ELEMENT_DST_IP6_LO,
MLXSW_AFK_ELEMENT_DST_L4_PORT,
MLXSW_AFK_ELEMENT_SRC_L4_PORT,
MLXSW_AFK_ELEMENT_VID,
MLXSW_AFK_ELEMENT_PCP,
MLXSW_AFK_ELEMENT_MAX,
};

Expand Down Expand Up @@ -88,7 +90,7 @@ struct mlxsw_afk_element_info {
MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF, \
_element, _offset, 0, _size)

/* For the purpose of the driver, define a internal storage scratchpad
/* For the purpose of the driver, define an internal storage scratchpad
* that will be used to store key/mask values. For each defined element type
* define an internal storage geometry.
*/
Expand All @@ -98,6 +100,8 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = {
MLXSW_AFK_ELEMENT_INFO_BUF(SMAC, 0x0A, 6),
MLXSW_AFK_ELEMENT_INFO_U32(ETHERTYPE, 0x00, 0, 16),
MLXSW_AFK_ELEMENT_INFO_U32(IP_PROTO, 0x10, 0, 8),
MLXSW_AFK_ELEMENT_INFO_U32(VID, 0x10, 8, 12),
MLXSW_AFK_ELEMENT_INFO_U32(PCP, 0x10, 20, 3),
MLXSW_AFK_ELEMENT_INFO_U32(SRC_IP4, 0x18, 0, 32),
MLXSW_AFK_ELEMENT_INFO_U32(DST_IP4, 0x1C, 0, 32),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_HI, 0x18, 8),
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,9 @@ int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei);
int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
struct net_device *out_dev);
int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
u32 action, u16 vid, u16 proto, u8 prio);

struct mlxsw_sp_acl_rule;

Expand Down
29 changes: 29 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <linux/string.h>
#include <linux/rhashtable.h>
#include <linux/netdevice.h>
#include <net/tc_act/tc_vlan.h>

#include "reg.h"
#include "core.h"
Expand Down Expand Up @@ -335,6 +336,34 @@ int mlxsw_sp_acl_rulei_act_fwd(struct mlxsw_sp *mlxsw_sp,
local_port, in_port);
}

int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
u32 action, u16 vid, u16 proto, u8 prio)
{
u8 ethertype;

if (action == TCA_VLAN_ACT_MODIFY) {
switch (proto) {
case ETH_P_8021Q:
ethertype = 0;
break;
case ETH_P_8021AD:
ethertype = 1;
break;
default:
dev_err(mlxsw_sp->bus_info->dev, "Unsupported VLAN protocol %#04x\n",
proto);
return -EINVAL;
}

return mlxsw_afa_block_append_vlan_modify(rulei->act_block,
vid, prio, ethertype);
} else {
dev_err(mlxsw_sp->bus_info->dev, "Unsupported VLAN action\n");
return -EINVAL;
}
}

struct mlxsw_sp_acl_rule *
mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_ruleset *ruleset,
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,15 @@

static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
MLXSW_AFK_ELEMENT_INST_BUF(DMAC, 0x00, 6),
MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12),
MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
};

static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
MLXSW_AFK_ELEMENT_INST_BUF(SMAC, 0x00, 6),
MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12),
MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
};

Expand All @@ -65,6 +69,8 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
};

static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
MLXSW_AFK_ELEMENT_INST_U32(VID, 0x00, 0, 12),
MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 29, 3),
MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x08, 0, 16),
MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x0C, 0, 16),
};
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,8 @@ static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = {
MLXSW_AFK_ELEMENT_DST_IP4,
MLXSW_AFK_ELEMENT_DST_L4_PORT,
MLXSW_AFK_ELEMENT_SRC_L4_PORT,
MLXSW_AFK_ELEMENT_VID,
MLXSW_AFK_ELEMENT_PCP,
};

static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv6[] = {
Expand Down
34 changes: 33 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <net/pkt_cls.h>
#include <net/tc_act/tc_gact.h>
#include <net/tc_act/tc_mirred.h>
#include <net/tc_act/tc_vlan.h>

#include "spectrum.h"
#include "core_acl_flex_keys.h"
Expand Down Expand Up @@ -73,6 +74,15 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
out_dev);
if (err)
return err;
} else if (is_tcf_vlan(a)) {
u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
u32 action = tcf_vlan_action(a);
u8 prio = tcf_vlan_push_prio(a);
u16 vid = tcf_vlan_push_vid(a);

return mlxsw_sp_acl_rulei_act_vlan(mlxsw_sp, rulei,
action, vid,
proto, prio);
} else {
dev_err(mlxsw_sp->bus_info->dev, "Unsupported action\n");
return -EOPNOTSUPP;
Expand Down Expand Up @@ -173,7 +183,8 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_PORTS))) {
BIT(FLOW_DISSECTOR_KEY_PORTS) |
BIT(FLOW_DISSECTOR_KEY_VLAN))) {
dev_err(mlxsw_sp->bus_info->dev, "Unsupported key\n");
return -EOPNOTSUPP;
}
Expand Down Expand Up @@ -234,6 +245,27 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
sizeof(key->src));
}

if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
struct flow_dissector_key_vlan *key =
skb_flow_dissector_target(f->dissector,
FLOW_DISSECTOR_KEY_VLAN,
f->key);
struct flow_dissector_key_vlan *mask =
skb_flow_dissector_target(f->dissector,
FLOW_DISSECTOR_KEY_VLAN,
f->mask);
if (mask->vlan_id != 0)
mlxsw_sp_acl_rulei_keymask_u32(rulei,
MLXSW_AFK_ELEMENT_VID,
key->vlan_id,
mask->vlan_id);
if (mask->vlan_priority != 0)
mlxsw_sp_acl_rulei_keymask_u32(rulei,
MLXSW_AFK_ELEMENT_PCP,
key->vlan_priority,
mask->vlan_priority);
}

if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS)
mlxsw_sp_flower_parse_ipv4(rulei, f);

Expand Down
5 changes: 5 additions & 0 deletions include/net/tc_act/tc_vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@ static inline __be16 tcf_vlan_push_proto(const struct tc_action *a)
return to_vlan(a)->tcfv_push_proto;
}

static inline u8 tcf_vlan_push_prio(const struct tc_action *a)
{
return to_vlan(a)->tcfv_push_prio;
}

#endif /* __NET_TC_VLAN_H */

0 comments on commit 1015d74

Please sign in to comment.