Skip to content

Commit

Permalink
Merge branch 'prestera-matchall'
Browse files Browse the repository at this point in the history
Maksym Glubokiy says:

====================
net: prestera: matchall features

This patch series extracts matchall rules management out of SPAN API
implementation and adds 2 features on top of that:
  - support for egress traffic (mirred egress action)
  - proper rule priorities management between matchall and flower
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 26, 2022
2 parents 6661918 + 44af957 commit 5b3b51a
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 78 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/prestera/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ 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_span.o prestera_counter.o \
prestera_router.o prestera_router_hw.o
prestera_router.o prestera_router_hw.o prestera_matchall.o

obj-$(CONFIG_PRESTERA_PCI) += prestera_pci.o
43 changes: 43 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ struct prestera_acl_ruleset {
struct prestera_acl_ruleset_ht_key ht_key;
struct rhashtable rule_ht;
struct prestera_acl *acl;
struct {
u32 min;
u32 max;
} prio;
unsigned long rule_count;
refcount_t refcount;
void *keymask;
Expand Down Expand Up @@ -162,6 +166,9 @@ prestera_acl_ruleset_create(struct prestera_acl *acl,
ruleset->pcl_id = PRESTERA_ACL_PCL_ID_MAKE((u8)uid, chain_index);
ruleset->index = uid;

ruleset->prio.min = UINT_MAX;
ruleset->prio.max = 0;

err = rhashtable_insert_fast(&acl->ruleset_ht, &ruleset->ht_node,
prestera_acl_ruleset_ht_params);
if (err)
Expand Down Expand Up @@ -365,6 +372,26 @@ prestera_acl_ruleset_block_unbind(struct prestera_acl_ruleset *ruleset,
block->ruleset_zero = NULL;
}

static void
prestera_acl_ruleset_prio_refresh(struct prestera_acl *acl,
struct prestera_acl_ruleset *ruleset)
{
struct prestera_acl_rule *rule;

ruleset->prio.min = UINT_MAX;
ruleset->prio.max = 0;

list_for_each_entry(rule, &acl->rules, list) {
if (ruleset->ingress != rule->ruleset->ingress)
continue;
if (ruleset->ht_key.chain_index != rule->chain_index)
continue;

ruleset->prio.min = min(ruleset->prio.min, rule->priority);
ruleset->prio.max = max(ruleset->prio.max, rule->priority);
}
}

void
prestera_acl_rule_keymask_pcl_id_set(struct prestera_acl_rule *rule, u16 pcl_id)
{
Expand All @@ -389,6 +416,13 @@ u32 prestera_acl_ruleset_index_get(const struct prestera_acl_ruleset *ruleset)
return ruleset->index;
}

void prestera_acl_ruleset_prio_get(struct prestera_acl_ruleset *ruleset,
u32 *prio_min, u32 *prio_max)
{
*prio_min = ruleset->prio.min;
*prio_max = ruleset->prio.max;
}

bool prestera_acl_ruleset_is_offload(struct prestera_acl_ruleset *ruleset)
{
return ruleset->offload;
Expand Down Expand Up @@ -429,6 +463,13 @@ void prestera_acl_rule_destroy(struct prestera_acl_rule *rule)
kfree(rule);
}

static void prestera_acl_ruleset_prio_update(struct prestera_acl_ruleset *ruleset,
u32 prio)
{
ruleset->prio.min = min(ruleset->prio.min, prio);
ruleset->prio.max = max(ruleset->prio.max, prio);
}

int prestera_acl_rule_add(struct prestera_switch *sw,
struct prestera_acl_rule *rule)
{
Expand Down Expand Up @@ -468,6 +509,7 @@ int prestera_acl_rule_add(struct prestera_switch *sw,

list_add_tail(&rule->list, &sw->acl->rules);
ruleset->rule_count++;
prestera_acl_ruleset_prio_update(ruleset, rule->priority);
return 0;

err_acl_block_bind:
Expand All @@ -492,6 +534,7 @@ void prestera_acl_rule_del(struct prestera_switch *sw,
list_del(&rule->list);

prestera_acl_rule_entry_destroy(sw->acl, rule->re);
prestera_acl_ruleset_prio_refresh(sw->acl, ruleset);

/* unbind block (all ports) */
if (!ruleset->ht_key.chain_index && !ruleset->rule_count)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ int prestera_acl_ruleset_bind(struct prestera_acl_ruleset *ruleset,
int prestera_acl_ruleset_unbind(struct prestera_acl_ruleset *ruleset,
struct prestera_port *port);
u32 prestera_acl_ruleset_index_get(const struct prestera_acl_ruleset *ruleset);
void prestera_acl_ruleset_prio_get(struct prestera_acl_ruleset *ruleset,
u32 *prio_min, u32 *prio_max);
void
prestera_acl_rule_keymask_pcl_id_set(struct prestera_acl_rule *rule,
u16 pcl_id);
Expand Down
12 changes: 8 additions & 4 deletions drivers/net/ethernet/marvell/prestera/prestera_flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
#include "prestera.h"
#include "prestera_acl.h"
#include "prestera_flow.h"
#include "prestera_span.h"
#include "prestera_flower.h"
#include "prestera_matchall.h"
#include "prestera_span.h"

static LIST_HEAD(prestera_block_cb_list);

Expand All @@ -17,9 +18,9 @@ static int prestera_flow_block_mall_cb(struct prestera_flow_block *block,
{
switch (f->command) {
case TC_CLSMATCHALL_REPLACE:
return prestera_span_replace(block, f);
return prestera_mall_replace(block, f);
case TC_CLSMATCHALL_DESTROY:
prestera_span_destroy(block);
prestera_mall_destroy(block);
return 0;
default:
return -EOPNOTSUPP;
Expand Down Expand Up @@ -89,6 +90,9 @@ prestera_flow_block_create(struct prestera_switch *sw,
INIT_LIST_HEAD(&block->template_list);
block->net = net;
block->sw = sw;
block->mall.prio_min = UINT_MAX;
block->mall.prio_max = 0;
block->mall.bound = false;
block->ingress = ingress;

return block;
Expand Down Expand Up @@ -263,7 +267,7 @@ static void prestera_setup_flow_block_unbind(struct prestera_port *port,

block = flow_block_cb_priv(block_cb);

prestera_span_destroy(block);
prestera_mall_destroy(block);

err = prestera_flow_block_unbind(block, port);
if (err)
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ struct prestera_flow_block {
struct prestera_acl_ruleset *ruleset_zero;
struct flow_block_cb *block_cb;
struct list_head template_list;
struct {
u32 prio_min;
u32 prio_max;
bool bound;
} mall;
unsigned int rule_count;
bool ingress;
};
Expand Down
48 changes: 48 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "prestera_acl.h"
#include "prestera_flow.h"
#include "prestera_flower.h"
#include "prestera_matchall.h"

struct prestera_flower_template {
struct prestera_acl_ruleset *ruleset;
Expand Down Expand Up @@ -360,6 +361,49 @@ static int prestera_flower_parse(struct prestera_flow_block *block,
f->common.extack);
}

static int prestera_flower_prio_check(struct prestera_flow_block *block,
struct flow_cls_offload *f)
{
u32 mall_prio_min;
u32 mall_prio_max;
int err;

err = prestera_mall_prio_get(block, &mall_prio_min, &mall_prio_max);
if (err == -ENOENT)
/* No matchall filters installed on this chain. */
return 0;

if (err) {
NL_SET_ERR_MSG(f->common.extack, "Failed to get matchall priorities");
return err;
}

if (f->common.prio <= mall_prio_max && block->ingress) {
NL_SET_ERR_MSG(f->common.extack,
"Failed to add in front of existing matchall rules");
return -EOPNOTSUPP;
}
if (f->common.prio >= mall_prio_min && !block->ingress) {
NL_SET_ERR_MSG(f->common.extack, "Failed to add behind of existing matchall rules");
return -EOPNOTSUPP;
}

return 0;
}

int prestera_flower_prio_get(struct prestera_flow_block *block, u32 chain_index,
u32 *prio_min, u32 *prio_max)
{
struct prestera_acl_ruleset *ruleset;

ruleset = prestera_acl_ruleset_lookup(block->sw->acl, block, chain_index);
if (IS_ERR(ruleset))
return PTR_ERR(ruleset);

prestera_acl_ruleset_prio_get(ruleset, prio_min, prio_max);
return 0;
}

int prestera_flower_replace(struct prestera_flow_block *block,
struct flow_cls_offload *f)
{
Expand All @@ -368,6 +412,10 @@ int prestera_flower_replace(struct prestera_flow_block *block,
struct prestera_acl_rule *rule;
int err;

err = prestera_flower_prio_check(block, f);
if (err)
return err;

ruleset = prestera_acl_ruleset_get(acl, block, f->common.chain_index);
if (IS_ERR(ruleset))
return PTR_ERR(ruleset);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/marvell/prestera/prestera_flower.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@ int prestera_flower_tmplt_create(struct prestera_flow_block *block,
void prestera_flower_tmplt_destroy(struct prestera_flow_block *block,
struct flow_cls_offload *f);
void prestera_flower_template_cleanup(struct prestera_flow_block *block);
int prestera_flower_prio_get(struct prestera_flow_block *block, u32 chain_index,
u32 *prio_min, u32 *prio_max);

#endif /* _PRESTERA_FLOWER_H_ */
30 changes: 22 additions & 8 deletions drivers/net/ethernet/marvell/prestera/prestera_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,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_INGRESS_BIND = 0x1101,
PRESTERA_CMD_TYPE_SPAN_INGRESS_UNBIND = 0x1102,
PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
PRESTERA_CMD_TYPE_SPAN_EGRESS_BIND = 0x1104,
PRESTERA_CMD_TYPE_SPAN_EGRESS_UNBIND = 0x1105,

PRESTERA_CMD_TYPE_POLICER_CREATE = 0x1500,
PRESTERA_CMD_TYPE_POLICER_RELEASE = 0x1501,
Expand Down Expand Up @@ -1434,27 +1436,39 @@ int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
return 0;
}

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

if (ingress)
cmd_type = PRESTERA_CMD_TYPE_SPAN_INGRESS_BIND;
else
cmd_type = PRESTERA_CMD_TYPE_SPAN_EGRESS_BIND;

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

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

int prestera_hw_span_unbind(const struct prestera_port *port)
int prestera_hw_span_unbind(const struct prestera_port *port, bool ingress)
{
struct prestera_msg_span_req req = {
.port = __cpu_to_le32(port->hw_id),
.dev = __cpu_to_le32(port->dev_id),
};
enum prestera_cmd_type_t cmd_type;

return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
&req.cmd, sizeof(req));
if (ingress)
cmd_type = PRESTERA_CMD_TYPE_SPAN_INGRESS_UNBIND;
else
cmd_type = PRESTERA_CMD_TYPE_SPAN_EGRESS_UNBIND;

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

int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ethernet/marvell/prestera/prestera_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,9 @@ int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_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_bind(const struct prestera_port *port, u8 span_id,
bool ingress);
int prestera_hw_span_unbind(const struct prestera_port *port, bool ingress);
int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id);

/* Router API */
Expand Down
Loading

0 comments on commit 5b3b51a

Please sign in to comment.