Commit dde2daa0 authored by Volodymyr Mytnyk's avatar Volodymyr Mytnyk Committed by Jakub Kicinski

net: prestera: add police action support

- Add HW api to configure policer:
  - SR TCM policer mode is only supported for now.
  - Policer ingress/egress direction support.
- Add police action support into flower
Signed-off-by: default avatarVolodymyr Mytnyk <volodymyr.mytnyk@plvision.eu>
Link: https://lore.kernel.org/r/1651061148-21321-1-git-send-email-volodymyr.mytnyk@plvision.euSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 07caad0b
...@@ -34,6 +34,10 @@ struct prestera_acl_rule_entry { ...@@ -34,6 +34,10 @@ struct prestera_acl_rule_entry {
struct { struct {
u8 valid:1; u8 valid:1;
} accept, drop, trap; } accept, drop, trap;
struct {
u8 valid:1;
struct prestera_acl_action_police i;
} police;
struct { struct {
struct prestera_acl_action_jump i; struct prestera_acl_action_jump i;
u8 valid:1; u8 valid:1;
...@@ -533,6 +537,12 @@ static int __prestera_acl_rule_entry2hw_add(struct prestera_switch *sw, ...@@ -533,6 +537,12 @@ static int __prestera_acl_rule_entry2hw_add(struct prestera_switch *sw,
act_hw[act_num].id = PRESTERA_ACL_RULE_ACTION_TRAP; act_hw[act_num].id = PRESTERA_ACL_RULE_ACTION_TRAP;
act_num++; act_num++;
} }
/* police */
if (e->police.valid) {
act_hw[act_num].id = PRESTERA_ACL_RULE_ACTION_POLICE;
act_hw[act_num].police = e->police.i;
act_num++;
}
/* jump */ /* jump */
if (e->jump.valid) { if (e->jump.valid) {
act_hw[act_num].id = PRESTERA_ACL_RULE_ACTION_JUMP; act_hw[act_num].id = PRESTERA_ACL_RULE_ACTION_JUMP;
...@@ -557,6 +567,9 @@ __prestera_acl_rule_entry_act_destruct(struct prestera_switch *sw, ...@@ -557,6 +567,9 @@ __prestera_acl_rule_entry_act_destruct(struct prestera_switch *sw,
{ {
/* counter */ /* counter */
prestera_counter_put(sw->counter, e->counter.block, e->counter.id); prestera_counter_put(sw->counter, e->counter.block, e->counter.id);
/* police */
if (e->police.valid)
prestera_hw_policer_release(sw, e->police.i.id);
} }
void prestera_acl_rule_entry_destroy(struct prestera_acl *acl, void prestera_acl_rule_entry_destroy(struct prestera_acl *acl,
...@@ -579,6 +592,8 @@ __prestera_acl_rule_entry_act_construct(struct prestera_switch *sw, ...@@ -579,6 +592,8 @@ __prestera_acl_rule_entry_act_construct(struct prestera_switch *sw,
struct prestera_acl_rule_entry *e, struct prestera_acl_rule_entry *e,
struct prestera_acl_rule_entry_arg *arg) struct prestera_acl_rule_entry_arg *arg)
{ {
int err;
/* accept */ /* accept */
e->accept.valid = arg->accept.valid; e->accept.valid = arg->accept.valid;
/* drop */ /* drop */
...@@ -588,10 +603,26 @@ __prestera_acl_rule_entry_act_construct(struct prestera_switch *sw, ...@@ -588,10 +603,26 @@ __prestera_acl_rule_entry_act_construct(struct prestera_switch *sw,
/* jump */ /* jump */
e->jump.valid = arg->jump.valid; e->jump.valid = arg->jump.valid;
e->jump.i = arg->jump.i; e->jump.i = arg->jump.i;
/* police */
if (arg->police.valid) {
u8 type = arg->police.ingress ? PRESTERA_POLICER_TYPE_INGRESS :
PRESTERA_POLICER_TYPE_EGRESS;
err = prestera_hw_policer_create(sw, type, &e->police.i.id);
if (err)
goto err_out;
err = prestera_hw_policer_sr_tcm_set(sw, e->police.i.id,
arg->police.rate,
arg->police.burst);
if (err) {
prestera_hw_policer_release(sw, e->police.i.id);
goto err_out;
}
e->police.valid = arg->police.valid;
}
/* counter */ /* counter */
if (arg->count.valid) { if (arg->count.valid) {
int err;
err = prestera_counter_get(sw->counter, arg->count.client, err = prestera_counter_get(sw->counter, arg->count.client,
&e->counter.block, &e->counter.block,
&e->counter.id); &e->counter.id);
......
...@@ -56,6 +56,7 @@ enum prestera_acl_rule_action { ...@@ -56,6 +56,7 @@ enum prestera_acl_rule_action {
PRESTERA_ACL_RULE_ACTION_TRAP = 2, PRESTERA_ACL_RULE_ACTION_TRAP = 2,
PRESTERA_ACL_RULE_ACTION_JUMP = 5, PRESTERA_ACL_RULE_ACTION_JUMP = 5,
PRESTERA_ACL_RULE_ACTION_COUNT = 7, PRESTERA_ACL_RULE_ACTION_COUNT = 7,
PRESTERA_ACL_RULE_ACTION_POLICE = 8,
PRESTERA_ACL_RULE_ACTION_MAX PRESTERA_ACL_RULE_ACTION_MAX
}; };
...@@ -74,6 +75,10 @@ struct prestera_acl_action_jump { ...@@ -74,6 +75,10 @@ struct prestera_acl_action_jump {
u32 index; u32 index;
}; };
struct prestera_acl_action_police {
u32 id;
};
struct prestera_acl_action_count { struct prestera_acl_action_count {
u32 id; u32 id;
}; };
...@@ -86,6 +91,7 @@ struct prestera_acl_rule_entry_key { ...@@ -86,6 +91,7 @@ struct prestera_acl_rule_entry_key {
struct prestera_acl_hw_action_info { struct prestera_acl_hw_action_info {
enum prestera_acl_rule_action id; enum prestera_acl_rule_action id;
union { union {
struct prestera_acl_action_police police;
struct prestera_acl_action_count count; struct prestera_acl_action_count count;
struct prestera_acl_action_jump jump; struct prestera_acl_action_jump jump;
}; };
...@@ -105,6 +111,12 @@ struct prestera_acl_rule_entry_arg { ...@@ -105,6 +111,12 @@ struct prestera_acl_rule_entry_arg {
struct prestera_acl_action_jump i; struct prestera_acl_action_jump i;
u8 valid:1; u8 valid:1;
} jump; } jump;
struct {
u8 valid:1;
u64 rate;
u64 burst;
bool ingress;
} police;
struct { struct {
u8 valid:1; u8 valid:1;
u32 client; u32 client;
......
...@@ -108,6 +108,16 @@ static int prestera_flower_parse_actions(struct prestera_flow_block *block, ...@@ -108,6 +108,16 @@ static int prestera_flower_parse_actions(struct prestera_flow_block *block,
rule->re_arg.trap.valid = 1; rule->re_arg.trap.valid = 1;
break; break;
case FLOW_ACTION_POLICE:
if (rule->re_arg.police.valid)
return -EEXIST;
rule->re_arg.police.valid = 1;
rule->re_arg.police.rate =
act->police.rate_bytes_ps;
rule->re_arg.police.burst = act->police.burst;
rule->re_arg.police.ingress = true;
break;
case FLOW_ACTION_GOTO: case FLOW_ACTION_GOTO:
err = prestera_flower_parse_goto_action(block, rule, err = prestera_flower_parse_goto_action(block, rule,
chain_index, chain_index,
......
...@@ -74,6 +74,10 @@ enum prestera_cmd_type_t { ...@@ -74,6 +74,10 @@ enum prestera_cmd_type_t {
PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102, PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103, PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
PRESTERA_CMD_TYPE_POLICER_CREATE = 0x1500,
PRESTERA_CMD_TYPE_POLICER_RELEASE = 0x1501,
PRESTERA_CMD_TYPE_POLICER_SET = 0x1502,
PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000, PRESTERA_CMD_TYPE_CPU_CODE_COUNTERS_GET = 0x2000,
PRESTERA_CMD_TYPE_ACK = 0x10000, PRESTERA_CMD_TYPE_ACK = 0x10000,
...@@ -163,6 +167,10 @@ enum { ...@@ -163,6 +167,10 @@ enum {
PRESTERA_FC_SYMM_ASYMM, PRESTERA_FC_SYMM_ASYMM,
}; };
enum {
PRESTERA_POLICER_MODE_SR_TCM
};
enum { enum {
PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0, PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1, PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
...@@ -428,6 +436,9 @@ struct prestera_msg_acl_action { ...@@ -428,6 +436,9 @@ struct prestera_msg_acl_action {
struct { struct {
__le32 index; __le32 index;
} jump; } jump;
struct {
__le32 id;
} police;
struct { struct {
__le32 id; __le32 id;
} count; } count;
...@@ -570,6 +581,26 @@ struct mvsw_msg_cpu_code_counter_ret { ...@@ -570,6 +581,26 @@ struct mvsw_msg_cpu_code_counter_ret {
__le64 packet_count; __le64 packet_count;
}; };
struct prestera_msg_policer_req {
struct prestera_msg_cmd cmd;
__le32 id;
union {
struct {
__le64 cir;
__le32 cbs;
} __packed sr_tcm; /* make sure always 12 bytes size */
__le32 reserved[6];
};
u8 mode;
u8 type;
u8 pad[2];
};
struct prestera_msg_policer_resp {
struct prestera_msg_ret ret;
__le32 id;
};
struct prestera_msg_event { struct prestera_msg_event {
__le16 type; __le16 type;
__le16 id; __le16 id;
...@@ -622,6 +653,7 @@ static void prestera_hw_build_tests(void) ...@@ -622,6 +653,7 @@ static void prestera_hw_build_tests(void)
BUILD_BUG_ON(sizeof(struct prestera_msg_rif_req) != 36); BUILD_BUG_ON(sizeof(struct prestera_msg_rif_req) != 36);
BUILD_BUG_ON(sizeof(struct prestera_msg_vr_req) != 8); BUILD_BUG_ON(sizeof(struct prestera_msg_vr_req) != 8);
BUILD_BUG_ON(sizeof(struct prestera_msg_lpm_req) != 36); BUILD_BUG_ON(sizeof(struct prestera_msg_lpm_req) != 36);
BUILD_BUG_ON(sizeof(struct prestera_msg_policer_req) != 36);
/* structure that are part of req/resp fw messages */ /* structure that are part of req/resp fw messages */
BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16); BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16);
...@@ -640,6 +672,7 @@ static void prestera_hw_build_tests(void) ...@@ -640,6 +672,7 @@ static void prestera_hw_build_tests(void)
BUILD_BUG_ON(sizeof(struct prestera_msg_counter_resp) != 24); BUILD_BUG_ON(sizeof(struct prestera_msg_counter_resp) != 24);
BUILD_BUG_ON(sizeof(struct prestera_msg_rif_resp) != 12); BUILD_BUG_ON(sizeof(struct prestera_msg_rif_resp) != 12);
BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12); BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
BUILD_BUG_ON(sizeof(struct prestera_msg_policer_resp) != 12);
/* check events */ /* check events */
BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20); BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
...@@ -1192,6 +1225,9 @@ prestera_acl_rule_add_put_action(struct prestera_msg_acl_action *action, ...@@ -1192,6 +1225,9 @@ prestera_acl_rule_add_put_action(struct prestera_msg_acl_action *action,
case PRESTERA_ACL_RULE_ACTION_JUMP: case PRESTERA_ACL_RULE_ACTION_JUMP:
action->jump.index = __cpu_to_le32(info->jump.index); action->jump.index = __cpu_to_le32(info->jump.index);
break; break;
case PRESTERA_ACL_RULE_ACTION_POLICE:
action->police.id = __cpu_to_le32(info->police.id);
break;
case PRESTERA_ACL_RULE_ACTION_COUNT: case PRESTERA_ACL_RULE_ACTION_COUNT:
action->count.id = __cpu_to_le32(info->count.id); action->count.id = __cpu_to_le32(info->count.id);
break; break;
...@@ -2163,3 +2199,48 @@ int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id, ...@@ -2163,3 +2199,48 @@ int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id,
return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_CLEAR, return prestera_cmd(sw, PRESTERA_CMD_TYPE_COUNTER_CLEAR,
&req.cmd, sizeof(req)); &req.cmd, sizeof(req));
} }
int prestera_hw_policer_create(struct prestera_switch *sw, u8 type,
u32 *policer_id)
{
struct prestera_msg_policer_resp resp;
struct prestera_msg_policer_req req = {
.type = type
};
int err;
err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_POLICER_CREATE,
&req.cmd, sizeof(req), &resp.ret, sizeof(resp));
if (err)
return err;
*policer_id = __le32_to_cpu(resp.id);
return 0;
}
int prestera_hw_policer_release(struct prestera_switch *sw,
u32 policer_id)
{
struct prestera_msg_policer_req req = {
.id = __cpu_to_le32(policer_id)
};
return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_RELEASE,
&req.cmd, sizeof(req));
}
int prestera_hw_policer_sr_tcm_set(struct prestera_switch *sw,
u32 policer_id, u64 cir, u32 cbs)
{
struct prestera_msg_policer_req req = {
.mode = PRESTERA_POLICER_MODE_SR_TCM,
.id = __cpu_to_le32(policer_id),
.sr_tcm = {
.cir = __cpu_to_le64(cir),
.cbs = __cpu_to_le32(cbs)
}
};
return prestera_cmd(sw, PRESTERA_CMD_TYPE_POLICER_SET,
&req.cmd, sizeof(req));
}
...@@ -107,6 +107,11 @@ enum { ...@@ -107,6 +107,11 @@ enum {
PRESTERA_STP_FORWARD, PRESTERA_STP_FORWARD,
}; };
enum {
PRESTERA_POLICER_TYPE_INGRESS,
PRESTERA_POLICER_TYPE_EGRESS
};
enum prestera_hw_cpu_code_cnt_t { enum prestera_hw_cpu_code_cnt_t {
PRESTERA_HW_CPU_CODE_CNT_TYPE_DROP = 0, PRESTERA_HW_CPU_CODE_CNT_TYPE_DROP = 0,
PRESTERA_HW_CPU_CODE_CNT_TYPE_TRAP = 1, PRESTERA_HW_CPU_CODE_CNT_TYPE_TRAP = 1,
...@@ -288,4 +293,12 @@ prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code, ...@@ -288,4 +293,12 @@ prestera_hw_cpu_code_counters_get(struct prestera_switch *sw, u8 code,
enum prestera_hw_cpu_code_cnt_t counter_type, enum prestera_hw_cpu_code_cnt_t counter_type,
u64 *packet_count); u64 *packet_count);
/* Policer API */
int prestera_hw_policer_create(struct prestera_switch *sw, u8 type,
u32 *policer_id);
int prestera_hw_policer_release(struct prestera_switch *sw,
u32 policer_id);
int prestera_hw_policer_sr_tcm_set(struct prestera_switch *sw,
u32 policer_id, u64 cir, u32 cbs);
#endif /* _PRESTERA_HW_H_ */ #endif /* _PRESTERA_HW_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment