Skip to content

Commit

Permalink
mlxsw: spectrum: Add support for vlan modify TC action
Browse files Browse the repository at this point in the history
Add VLAN action offloading. Invoke it from Spectrum flower handler for
"vlan modify" actions.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Petr Machata authored and David S. Miller committed Mar 10, 2017
1 parent a30aad5 commit a150201
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 0 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
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
10 changes: 10 additions & 0 deletions 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
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 a150201

Please sign in to comment.