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

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.eu


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 07caad0b
Loading
Loading
Loading
Loading
+33 −2
Original line number Diff line number Diff line
@@ -34,6 +34,10 @@ struct prestera_acl_rule_entry {
		struct {
			u8 valid:1;
		} accept, drop, trap;
		struct {
			u8 valid:1;
			struct prestera_acl_action_police i;
		} police;
		struct {
			struct prestera_acl_action_jump i;
			u8 valid:1;
@@ -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_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 */
	if (e->jump.valid) {
		act_hw[act_num].id = PRESTERA_ACL_RULE_ACTION_JUMP;
@@ -557,6 +567,9 @@ __prestera_acl_rule_entry_act_destruct(struct prestera_switch *sw,
{
	/* counter */
	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,
@@ -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_arg *arg)
{
	int err;

	/* accept */
	e->accept.valid = arg->accept.valid;
	/* drop */
@@ -588,10 +603,26 @@ __prestera_acl_rule_entry_act_construct(struct prestera_switch *sw,
	/* jump */
	e->jump.valid = arg->jump.valid;
	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 */
	if (arg->count.valid) {
		int err;

		err = prestera_counter_get(sw->counter, arg->count.client,
					   &e->counter.block,
					   &e->counter.id);
+12 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ enum prestera_acl_rule_action {
	PRESTERA_ACL_RULE_ACTION_TRAP = 2,
	PRESTERA_ACL_RULE_ACTION_JUMP = 5,
	PRESTERA_ACL_RULE_ACTION_COUNT = 7,
	PRESTERA_ACL_RULE_ACTION_POLICE = 8,

	PRESTERA_ACL_RULE_ACTION_MAX
};
@@ -74,6 +75,10 @@ struct prestera_acl_action_jump {
	u32 index;
};

struct prestera_acl_action_police {
	u32 id;
};

struct prestera_acl_action_count {
	u32 id;
};
@@ -86,6 +91,7 @@ struct prestera_acl_rule_entry_key {
struct prestera_acl_hw_action_info {
	enum prestera_acl_rule_action id;
	union {
		struct prestera_acl_action_police police;
		struct prestera_acl_action_count count;
		struct prestera_acl_action_jump jump;
	};
@@ -105,6 +111,12 @@ struct prestera_acl_rule_entry_arg {
			struct prestera_acl_action_jump i;
			u8 valid:1;
		} jump;
		struct {
			u8 valid:1;
			u64 rate;
			u64 burst;
			bool ingress;
		} police;
		struct {
			u8 valid:1;
			u32 client;
+10 −0
Original line number Diff line number Diff line
@@ -108,6 +108,16 @@ static int prestera_flower_parse_actions(struct prestera_flow_block *block,

			rule->re_arg.trap.valid = 1;
			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:
			err = prestera_flower_parse_goto_action(block, rule,
								chain_index,
+81 −0
Original line number Diff line number Diff line
@@ -74,6 +74,10 @@ enum prestera_cmd_type_t {
	PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
	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_ACK = 0x10000,
@@ -163,6 +167,10 @@ enum {
	PRESTERA_FC_SYMM_ASYMM,
};

enum {
	PRESTERA_POLICER_MODE_SR_TCM
};

enum {
	PRESTERA_HW_FDB_ENTRY_TYPE_REG_PORT = 0,
	PRESTERA_HW_FDB_ENTRY_TYPE_LAG = 1,
@@ -428,6 +436,9 @@ struct prestera_msg_acl_action {
		struct {
			__le32 index;
		} jump;
		struct {
			__le32 id;
		} police;
		struct {
			__le32 id;
		} count;
@@ -570,6 +581,26 @@ struct mvsw_msg_cpu_code_counter_ret {
	__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 {
	__le16 type;
	__le16 id;
@@ -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_vr_req) != 8);
	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 */
	BUILD_BUG_ON(sizeof(struct prestera_msg_iface) != 16);
@@ -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_rif_resp) != 12);
	BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
	BUILD_BUG_ON(sizeof(struct prestera_msg_policer_resp) != 12);

	/* check events */
	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,
	case PRESTERA_ACL_RULE_ACTION_JUMP:
		action->jump.index = __cpu_to_le32(info->jump.index);
		break;
	case PRESTERA_ACL_RULE_ACTION_POLICE:
		action->police.id = __cpu_to_le32(info->police.id);
		break;
	case PRESTERA_ACL_RULE_ACTION_COUNT:
		action->count.id = __cpu_to_le32(info->count.id);
		break;
@@ -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,
			    &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));
}
+13 −0
Original line number Diff line number Diff line
@@ -107,6 +107,11 @@ enum {
	PRESTERA_STP_FORWARD,
};

enum {
	PRESTERA_POLICER_TYPE_INGRESS,
	PRESTERA_POLICER_TYPE_EGRESS
};

enum prestera_hw_cpu_code_cnt_t {
	PRESTERA_HW_CPU_CODE_CNT_TYPE_DROP = 0,
	PRESTERA_HW_CPU_CODE_CNT_TYPE_TRAP = 1,
@@ -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,
				  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_ */