Commit 87b08a8c authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-microchip-vcap-rules'



Steen Hegelund says:

====================
net: microchip: Add support for two classes of VCAP rules

This adds support for two classes of VCAP rules:

- Permanent rules (added e.g. for PTP support)
- TC user rules (added by the TC userspace tool)

For this to work the VCAP Loopups must be enabled from boot, so that the
"internal" clients like PTP can add rules that are always active.

When the TC tool add a flower filter the VCAP rule corresponding to this
filter will be disabled (kept in memory) until a TC matchall filter creates
a link from chain 0 to the chain (lookup) where the flower filter was
added.

When the flower filter is enabled it will be written to the appropriate
VCAP lookup and become active in HW.

Likewise the flower filter will be disabled if there is no link from chain
0 to the chain of the filter (lookup), and when that happens the
corresponding VCAP rule will be read from the VCAP instance and stored in
memory until it is deleted or enabled again.

Version History:
================
v4      Removed a leftover 'Fixes' tag from v2.  No functional changes.

v3      Removed the change that allowed rules to always be added in the
        LAN996x even though the lookups are not enabled (Horatiu Vultur).
        This was sent separately to net instead.

        Removed the 'Fixes' tags due to the patch sent to net by Horatiu
        Vultur.

        Added a check for validity of the chain source when enabling a
        lookup.

v2      Adding a missing goto exit in vcap_add_rule (Dan Carpenter).
        Added missing checks for error returns in vcap_enable_rule.

v1      Initial version
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ce870af3 18a15c76
Loading
Loading
Loading
Loading
+3 −7
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
#include "vcap_api_client.h"

int lan966x_goto_port_add(struct lan966x_port *port,
			  struct flow_action_entry *act,
			  int from_cid, int to_cid,
			  unsigned long goto_id,
			  struct netlink_ext_ack *extack)
{
@@ -12,7 +12,7 @@ int lan966x_goto_port_add(struct lan966x_port *port,
	int err;

	err = vcap_enable_lookups(lan966x->vcap_ctrl, port->dev,
				  act->chain_index, goto_id,
				  from_cid, to_cid, goto_id,
				  true);
	if (err == -EFAULT) {
		NL_SET_ERR_MSG_MOD(extack, "Unsupported goto chain");
@@ -29,8 +29,6 @@ int lan966x_goto_port_add(struct lan966x_port *port,
		return err;
	}

	port->tc.goto_id = goto_id;

	return 0;
}

@@ -41,14 +39,12 @@ int lan966x_goto_port_del(struct lan966x_port *port,
	struct lan966x *lan966x = port->lan966x;
	int err;

	err = vcap_enable_lookups(lan966x->vcap_ctrl, port->dev, 0,
	err = vcap_enable_lookups(lan966x->vcap_ctrl, port->dev, 0, 0,
				  goto_id, false);
	if (err) {
		NL_SET_ERR_MSG_MOD(extack, "Could not disable VCAP lookups");
		return err;
	}

	port->tc.goto_id = 0;

	return 0;
}
+1 −2
Original line number Diff line number Diff line
@@ -332,7 +332,6 @@ struct lan966x_port_tc {
	unsigned long police_id;
	unsigned long ingress_mirror_id;
	unsigned long egress_mirror_id;
	unsigned long goto_id;
	struct flow_stats police_stat;
	struct flow_stats mirror_stat;
};
@@ -607,7 +606,7 @@ int lan966x_tc_flower(struct lan966x_port *port,
		      struct flow_cls_offload *f);

int lan966x_goto_port_add(struct lan966x_port *port,
			  struct flow_action_entry *act,
			  int from_cid, int to_cid,
			  unsigned long goto_id,
			  struct netlink_ext_ack *extack);
int lan966x_goto_port_del(struct lan966x_port *port,
+16 −14
Original line number Diff line number Diff line
@@ -82,8 +82,8 @@ static int lan966x_tc_flower_use_dissectors(struct flow_cls_offload *f,
}

static int lan966x_tc_flower_action_check(struct vcap_control *vctrl,
					  struct flow_cls_offload *fco,
					  struct vcap_admin *admin)
					  struct net_device *dev,
					  struct flow_cls_offload *fco)
{
	struct flow_rule *rule = flow_cls_offload_flow_rule(fco);
	struct flow_action_entry *actent, *last_actent = NULL;
@@ -109,20 +109,22 @@ static int lan966x_tc_flower_action_check(struct vcap_control *vctrl,
		last_actent = actent; /* Save last action for later check */
	}

	/* Check that last action is a goto */
	if (last_actent->id != FLOW_ACTION_GOTO) {
		NL_SET_ERR_MSG_MOD(fco->common.extack,
				   "Last action must be 'goto'");
		return -EINVAL;
	}

	/* Check if the goto chain is in the next lookup */
	/* Check that last action is a goto
	 * The last chain/lookup does not need to have goto action
	 */
	if (last_actent->id == FLOW_ACTION_GOTO) {
		/* Check if the destination chain is in one of the VCAPs */
		if (!vcap_is_next_lookup(vctrl, fco->common.chain_index,
					 last_actent->chain_index)) {
			NL_SET_ERR_MSG_MOD(fco->common.extack,
					   "Invalid goto chain");
			return -EINVAL;
		}
	} else if (!vcap_is_last_chain(vctrl, fco->common.chain_index)) {
		NL_SET_ERR_MSG_MOD(fco->common.extack,
				   "Last action must be 'goto'");
		return -EINVAL;
	}

	/* Catch unsupported combinations of actions */
	if (action_mask & BIT(FLOW_ACTION_TRAP) &&
@@ -145,8 +147,8 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
	struct vcap_rule *vrule;
	int err, idx;

	err = lan966x_tc_flower_action_check(port->lan966x->vcap_ctrl, f,
					     admin);
	err = lan966x_tc_flower_action_check(port->lan966x->vcap_ctrl,
					     port->dev, f);
	if (err)
		return err;

+3 −13
Original line number Diff line number Diff line
@@ -24,7 +24,8 @@ static int lan966x_tc_matchall_add(struct lan966x_port *port,
		return lan966x_mirror_port_add(port, act, f->cookie,
					       ingress, f->common.extack);
	case FLOW_ACTION_GOTO:
		return lan966x_goto_port_add(port, act, f->cookie,
		return lan966x_goto_port_add(port, f->common.chain_index,
					     act->chain_index, f->cookie,
					     f->common.extack);
	default:
		NL_SET_ERR_MSG_MOD(f->common.extack,
@@ -46,13 +47,8 @@ static int lan966x_tc_matchall_del(struct lan966x_port *port,
		   f->cookie == port->tc.egress_mirror_id) {
		return lan966x_mirror_port_del(port, ingress,
					       f->common.extack);
	} else if (f->cookie == port->tc.goto_id) {
		return lan966x_goto_port_del(port, f->cookie,
					     f->common.extack);
	} else {
		NL_SET_ERR_MSG_MOD(f->common.extack,
				   "Unsupported action");
		return -EOPNOTSUPP;
		return lan966x_goto_port_del(port, f->cookie, f->common.extack);
	}

	return 0;
@@ -80,12 +76,6 @@ int lan966x_tc_matchall(struct lan966x_port *port,
			struct tc_cls_matchall_offload *f,
			bool ingress)
{
	if (!tc_cls_can_offload_and_chain0(port->dev, &f->common)) {
		NL_SET_ERR_MSG_MOD(f->common.extack,
				   "Only chain zero is supported");
		return -EOPNOTSUPP;
	}

	switch (f->command) {
	case TC_CLSMATCHALL_REPLACE:
		return lan966x_tc_matchall_add(port, f, ingress);
+6 −15
Original line number Diff line number Diff line
@@ -390,20 +390,6 @@ static int lan966x_vcap_port_info(struct net_device *dev,
	return 0;
}

static int lan966x_vcap_enable(struct net_device *dev,
			       struct vcap_admin *admin,
			       bool enable)
{
	struct lan966x_port *port = netdev_priv(dev);
	struct lan966x *lan966x = port->lan966x;

	lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(enable),
		ANA_VCAP_S2_CFG_ENA,
		lan966x, ANA_VCAP_S2_CFG(port->chip_port));

	return 0;
}

static struct vcap_operations lan966x_vcap_ops = {
	.validate_keyset = lan966x_vcap_validate_keyset,
	.add_default_fields = lan966x_vcap_add_default_fields,
@@ -414,7 +400,6 @@ static struct vcap_operations lan966x_vcap_ops = {
	.update = lan966x_vcap_update,
	.move = lan966x_vcap_move,
	.port_info = lan966x_vcap_port_info,
	.enable = lan966x_vcap_enable,
};

static void lan966x_vcap_admin_free(struct vcap_admin *admin)
@@ -521,6 +506,12 @@ int lan966x_vcap_init(struct lan966x *lan966x)
		list_add_tail(&admin->list, &ctrl->list);
	}

	for (int p = 0; p < lan966x->num_phys_ports; ++p)
		if (lan966x->ports[p])
			lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(true),
				ANA_VCAP_S2_CFG_ENA, lan966x,
				ANA_VCAP_S2_CFG(lan966x->ports[p]->chip_port));

	lan966x->vcap_ctrl = ctrl;

	return 0;
Loading