Skip to content

Commit

Permalink
net: marvell: prestera: Add matchall support
Browse files Browse the repository at this point in the history
- Introduce matchall filter support
- Add SPAN API to configure port mirroring.
- Add tc mirror action.

At this moment, only mirror (egress) action is supported.

Example:
    tc filter ... action mirred egress mirror dev DEV

Co-developed-by: Volodymyr Mytnyk <vmytnyk@marvell.com>
Signed-off-by: Volodymyr Mytnyk <vmytnyk@marvell.com>
Signed-off-by: Serhiy Boiko <serhiy.boiko@plvision.eu>
Signed-off-by: Vadym Kochan <vkochan@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Serhiy Boiko authored and David S. Miller committed Jun 16, 2021
1 parent 8b474a9 commit 13defa2
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 1 deletion.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/prestera/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ obj-$(CONFIG_PRESTERA) += prestera.o
prestera-objs := prestera_main.o prestera_hw.o prestera_dsa.o \
prestera_rxtx.o prestera_devlink.o prestera_ethtool.o \
prestera_switchdev.o prestera_acl.o prestera_flow.o \
prestera_flower.o
prestera_flower.o prestera_span.o

obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
2 changes: 2 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ struct prestera_event {
};

struct prestera_switchdev;
struct prestera_span;
struct prestera_rxtx;
struct prestera_trap_data;
struct prestera_acl;
Expand All @@ -181,6 +182,7 @@ struct prestera_switch {
struct prestera_switchdev *swdev;
struct prestera_rxtx *rxtx;
struct prestera_acl *acl;
struct prestera_span *span;
struct list_head event_handlers;
struct notifier_block netdev_nb;
struct prestera_trap_data *trap_data;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "prestera.h"
#include "prestera_hw.h"
#include "prestera_acl.h"
#include "prestera_span.h"

struct prestera_acl {
struct prestera_switch *sw;
Expand Down Expand Up @@ -127,6 +128,7 @@ int prestera_acl_block_bind(struct prestera_flow_block *block,
binding = kzalloc(sizeof(*binding), GFP_KERNEL);
if (!binding)
return -ENOMEM;
binding->span_id = PRESTERA_SPAN_INVALID_ID;
binding->port = port;

err = prestera_hw_acl_port_bind(port, block->ruleset->id);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct prestera_acl_ruleset;
struct prestera_flow_block_binding {
struct list_head list;
struct prestera_port *port;
int span_id;
};

struct prestera_flow_block {
Expand Down
19 changes: 19 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,25 @@
#include "prestera.h"
#include "prestera_acl.h"
#include "prestera_flow.h"
#include "prestera_span.h"
#include "prestera_flower.h"

static LIST_HEAD(prestera_block_cb_list);

static int prestera_flow_block_mall_cb(struct prestera_flow_block *block,
struct tc_cls_matchall_offload *f)
{
switch (f->command) {
case TC_CLSMATCHALL_REPLACE:
return prestera_span_replace(block, f);
case TC_CLSMATCHALL_DESTROY:
prestera_span_destroy(block);
return 0;
default:
return -EOPNOTSUPP;
}
}

static int prestera_flow_block_flower_cb(struct prestera_flow_block *block,
struct flow_cls_offload *f)
{
Expand Down Expand Up @@ -38,6 +53,8 @@ static int prestera_flow_block_cb(enum tc_setup_type type,
switch (type) {
case TC_SETUP_CLSFLOWER:
return prestera_flow_block_flower_cb(block, type_data);
case TC_SETUP_CLSMATCHALL:
return prestera_flow_block_mall_cb(block, type_data);
default:
return -EOPNOTSUPP;
}
Expand Down Expand Up @@ -143,6 +160,8 @@ static void prestera_setup_flow_block_unbind(struct prestera_port *port,

block = flow_block_cb_priv(block_cb);

prestera_span_destroy(block);

err = prestera_acl_block_unbind(block, port);
if (err)
goto error;
Expand Down
69 changes: 69 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ enum prestera_cmd_type_t {

PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,

PRESTERA_CMD_TYPE_SPAN_GET = 0x1100,
PRESTERA_CMD_TYPE_SPAN_BIND = 0x1101,
PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,

PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,

PRESTERA_CMD_TYPE_ACK = 0x10000,
Expand Down Expand Up @@ -377,6 +382,18 @@ struct prestera_msg_acl_ruleset_resp {
u16 id;
};

struct prestera_msg_span_req {
struct prestera_msg_cmd cmd;
u32 port;
u32 dev;
u8 id;
} __packed __aligned(4);

struct prestera_msg_span_resp {
struct prestera_msg_ret ret;
u8 id;
} __packed __aligned(4);

struct prestera_msg_stp_req {
struct prestera_msg_cmd cmd;
u32 port;
Expand Down Expand Up @@ -1055,6 +1072,58 @@ int prestera_hw_acl_port_unbind(const struct prestera_port *port,
&req.cmd, sizeof(req));
}

int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
{
struct prestera_msg_span_resp resp;
struct prestera_msg_span_req req = {
.port = port->hw_id,
.dev = port->dev_id,
};
int err;

err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_SPAN_GET,
&req.cmd, sizeof(req), &resp.ret, sizeof(resp));
if (err)
return err;

*span_id = resp.id;

return 0;
}

int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id)
{
struct prestera_msg_span_req req = {
.port = port->hw_id,
.dev = port->dev_id,
.id = span_id,
};

return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_BIND,
&req.cmd, sizeof(req));
}

int prestera_hw_span_unbind(const struct prestera_port *port)
{
struct prestera_msg_span_req req = {
.port = port->hw_id,
.dev = port->dev_id,
};

return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
&req.cmd, sizeof(req));
}

int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
{
struct prestera_msg_span_req req = {
.id = span_id
};

return prestera_cmd(sw, PRESTERA_CMD_TYPE_SPAN_RELEASE,
&req.cmd, sizeof(req));
}

int prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
{
struct prestera_msg_port_attr_req req = {
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ int prestera_hw_acl_port_bind(const struct prestera_port *port,
int prestera_hw_acl_port_unbind(const struct prestera_port *port,
u16 ruleset_id);

/* SPAN API */
int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id);
int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id);
int prestera_hw_span_unbind(const struct prestera_port *port);
int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id);

/* Event handlers */
int prestera_hw_event_handler_register(struct prestera_switch *sw,
enum prestera_event_type type,
Expand Down
8 changes: 8 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "prestera_hw.h"
#include "prestera_acl.h"
#include "prestera_flow.h"
#include "prestera_span.h"
#include "prestera_rxtx.h"
#include "prestera_devlink.h"
#include "prestera_ethtool.h"
Expand Down Expand Up @@ -845,6 +846,10 @@ static int prestera_switch_init(struct prestera_switch *sw)
if (err)
goto err_acl_init;

err = prestera_span_init(sw);
if (err)
goto err_span_init;

err = prestera_devlink_register(sw);
if (err)
goto err_dl_register;
Expand All @@ -864,6 +869,8 @@ static int prestera_switch_init(struct prestera_switch *sw)
err_lag_init:
prestera_devlink_unregister(sw);
err_dl_register:
prestera_span_fini(sw);
err_span_init:
prestera_acl_fini(sw);
err_acl_init:
prestera_event_handlers_unregister(sw);
Expand All @@ -883,6 +890,7 @@ static void prestera_switch_fini(struct prestera_switch *sw)
prestera_destroy_ports(sw);
prestera_lag_fini(sw);
prestera_devlink_unregister(sw);
prestera_span_fini(sw);
prestera_acl_fini(sw);
prestera_event_handlers_unregister(sw);
prestera_rxtx_switch_fini(sw);
Expand Down
Loading

0 comments on commit 13defa2

Please sign in to comment.