Commit 8c448c2b authored by Serhiy Boiko's avatar Serhiy Boiko Committed by David S. Miller
Browse files

net: prestera: add support for egress traffic mirroring



This enables adding matchall rules for egress:

  tc filter add .. egress .. matchall skip_sw \
    action mirred egress mirror dev ..

Signed-off-by: default avatarSerhiy Boiko <serhiy.boiko@plvision.eu>
Signed-off-by: default avatarMaksym Glubokiy <maksym.glubokiy@plvision.eu>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8afd552d
Loading
Loading
Loading
Loading
+22 −8
Original line number Diff line number Diff line
@@ -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,
@@ -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)
+3 −2
Original line number Diff line number Diff line
@@ -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 */
+4 −3
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ int prestera_mall_replace(struct prestera_flow_block *block,
	port = netdev_priv(act->dev);

	list_for_each_entry(binding, &block->binding_list, list) {
		err = prestera_span_rule_add(binding, port);
		err = prestera_span_rule_add(binding, port, block->ingress);
		if (err)
			goto rollback;
	}
@@ -53,7 +53,7 @@ int prestera_mall_replace(struct prestera_flow_block *block,
rollback:
	list_for_each_entry_continue_reverse(binding,
					     &block->binding_list, list)
		prestera_span_rule_del(binding);
		prestera_span_rule_del(binding, block->ingress);
	return err;
}

@@ -62,5 +62,6 @@ void prestera_mall_destroy(struct prestera_flow_block *block)
	struct prestera_flow_block_binding *binding;

	list_for_each_entry(binding, &block->binding_list, list)
		prestera_span_rule_del(binding);
		prestera_span_rule_del(binding, block->ingress);

}
+6 −4
Original line number Diff line number Diff line
@@ -121,7 +121,8 @@ static int prestera_span_put(struct prestera_switch *sw, u8 span_id)
}

int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
			   struct prestera_port *to_port)
			   struct prestera_port *to_port,
			   bool ingress)
{
	struct prestera_switch *sw = binding->port->sw;
	u8 span_id;
@@ -135,7 +136,7 @@ int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
	if (err)
		return err;

	err = prestera_hw_span_bind(binding->port, span_id);
	err = prestera_hw_span_bind(binding->port, span_id, ingress);
	if (err) {
		prestera_span_put(sw, span_id);
		return err;
@@ -145,11 +146,12 @@ int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
	return 0;
}

int prestera_span_rule_del(struct prestera_flow_block_binding *binding)
int prestera_span_rule_del(struct prestera_flow_block_binding *binding,
			   bool ingress)
{
	int err;

	err = prestera_hw_span_unbind(binding->port);
	err = prestera_hw_span_unbind(binding->port, ingress);
	if (err)
		return err;

+4 −2
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@ int prestera_span_init(struct prestera_switch *sw);
void prestera_span_fini(struct prestera_switch *sw);

int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
			   struct prestera_port *to_port);
int prestera_span_rule_del(struct prestera_flow_block_binding *binding);
			   struct prestera_port *to_port,
			   bool ingress);
int prestera_span_rule_del(struct prestera_flow_block_binding *binding,
			   bool ingress);

#endif /* _PRESTERA_SPAN_H_ */