Skip to content

Commit

Permalink
net: microchip: vcap api: Use src and dst chain id to chain VCAP lookups
Browse files Browse the repository at this point in the history
This adds both the source and destination chain id to the information kept
for enabled port lookups.
This allows enabling and disabling a chain of lookups by walking the chain
information for a port.

This changes the way that VCAP lookups are enabled from userspace: instead
of one matchall rule that enables all the 4 Sparx5 IS2 lookups, you need a
matchall rule per lookup.

In practice that is done by adding one matchall rule in chain 0 to goto IS2
Lookup 0, and then for each lookup you add a rule per lookup (low priority)
that does a goto to the next lookup chain.

Examples:

If you want IS2 Lookup 0 to be enabled you add the same matchall filter as
before:

tc filter add dev eth12 ingress chain 0 prio 1000 handle 1000 matchall \
       skip_sw action goto chain 8000000

If you also want to enable lookup 1 to 3 in IS2 and chain them you need
to add the following matchall filters:

tc filter add dev eth12 ingress chain 8000000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8100000

tc filter add dev eth12 ingress chain 8100000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8200000

tc filter add dev eth12 ingress chain 8200000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8300000

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Steen Hegelund authored and David S. Miller committed Jan 16, 2023
1 parent 33e3a27 commit cfd9e7b
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 84 deletions.
10 changes: 3 additions & 7 deletions drivers/net/ethernet/microchip/lan966x/lan966x_goto.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
#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)
{
struct lan966x *lan966x = port->lan966x;
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");
Expand All @@ -29,8 +29,6 @@ int lan966x_goto_port_add(struct lan966x_port *port,
return err;
}

port->tc.goto_id = goto_id;

return 0;
}

Expand All @@ -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;
}
3 changes: 1 addition & 2 deletions drivers/net/ethernet/microchip/lan966x/lan966x_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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,
Expand Down
16 changes: 3 additions & 13 deletions drivers/net/ethernet/microchip/lan966x/lan966x_tc_matchall.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
16 changes: 8 additions & 8 deletions drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static int sparx5_tc_matchall_replace(struct net_device *ndev,
switch (action->id) {
case FLOW_ACTION_GOTO:
err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
tmo->common.chain_index,
action->chain_index, tmo->cookie,
true);
if (err == -EFAULT) {
Expand All @@ -43,6 +44,11 @@ static int sparx5_tc_matchall_replace(struct net_device *ndev,
"VCAP already enabled");
return -EOPNOTSUPP;
}
if (err == -EADDRNOTAVAIL) {
NL_SET_ERR_MSG_MOD(tmo->common.extack,
"Already matching this chain");
return -EOPNOTSUPP;
}
if (err) {
NL_SET_ERR_MSG_MOD(tmo->common.extack,
"Could not enable VCAP lookups");
Expand All @@ -66,8 +72,8 @@ static int sparx5_tc_matchall_destroy(struct net_device *ndev,

sparx5 = port->sparx5;
if (!tmo->rule && tmo->cookie) {
err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev, 0,
tmo->cookie, false);
err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
0, 0, tmo->cookie, false);
if (err)
return err;
return 0;
Expand All @@ -80,12 +86,6 @@ int sparx5_tc_matchall(struct net_device *ndev,
struct tc_cls_matchall_offload *tmo,
bool ingress)
{
if (!tc_cls_can_offload_and_chain0(ndev, &tmo->common)) {
NL_SET_ERR_MSG_MOD(tmo->common.extack,
"Only chain zero is supported");
return -EOPNOTSUPP;
}

switch (tmo->command) {
case TC_CLSMATCHALL_REPLACE:
return sparx5_tc_matchall_replace(ndev, tmo, ingress);
Expand Down
126 changes: 74 additions & 52 deletions drivers/net/ethernet/microchip/vcap/vcap_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ struct vcap_rule_move {
int count; /* blocksize of addresses to move */
};

/* Stores the filter cookie that enabled the port */
/* Stores the filter cookie and chain id that enabled the port */
struct vcap_enabled_port {
struct list_head list; /* for insertion in enabled ports list */
struct net_device *ndev; /* the enabled port */
unsigned long cookie; /* filter that enabled the port */
int src_cid; /* source chain id */
int dst_cid; /* destination chain id */
};

void vcap_iter_set(struct vcap_stream_iter *itr, int sw_width,
Expand Down Expand Up @@ -1930,6 +1932,21 @@ static void vcap_move_rules(struct vcap_rule_internal *ri,
move->offset, move->count);
}

/* Check if the chain is already used to enable a VCAP lookup for this port */
static bool vcap_is_chain_used(struct vcap_control *vctrl,
struct net_device *ndev, int src_cid)
{
struct vcap_enabled_port *eport;
struct vcap_admin *admin;

list_for_each_entry(admin, &vctrl->list, list)
list_for_each_entry(eport, &admin->enabled, list)
if (eport->src_cid == src_cid && eport->ndev == ndev)
return true;

return false;
}

/* Encode and write a validated rule to the VCAP */
int vcap_add_rule(struct vcap_rule *rule)
{
Expand Down Expand Up @@ -2595,72 +2612,83 @@ void vcap_set_tc_exterr(struct flow_cls_offload *fco, struct vcap_rule *vrule)
EXPORT_SYMBOL_GPL(vcap_set_tc_exterr);

/* Check if this port is already enabled for this VCAP instance */
static bool vcap_is_enabled(struct vcap_admin *admin, struct net_device *ndev,
unsigned long cookie)
static bool vcap_is_enabled(struct vcap_control *vctrl, struct net_device *ndev,
int dst_cid)
{
struct vcap_enabled_port *eport;
struct vcap_admin *admin;

list_for_each_entry(eport, &admin->enabled, list)
if (eport->cookie == cookie || eport->ndev == ndev)
return true;
list_for_each_entry(admin, &vctrl->list, list)
list_for_each_entry(eport, &admin->enabled, list)
if (eport->dst_cid == dst_cid && eport->ndev == ndev)
return true;

return false;
}

/* Enable this port for this VCAP instance */
static int vcap_enable(struct vcap_admin *admin, struct net_device *ndev,
unsigned long cookie)
/* Enable this port and chain id in a VCAP instance */
static int vcap_enable(struct vcap_control *vctrl, struct net_device *ndev,
unsigned long cookie, int src_cid, int dst_cid)
{
struct vcap_enabled_port *eport;
struct vcap_admin *admin;

if (src_cid >= dst_cid)
return -EFAULT;

admin = vcap_find_admin(vctrl, dst_cid);
if (!admin)
return -ENOENT;

eport = kzalloc(sizeof(*eport), GFP_KERNEL);
if (!eport)
return -ENOMEM;

eport->ndev = ndev;
eport->cookie = cookie;
eport->src_cid = src_cid;
eport->dst_cid = dst_cid;
mutex_lock(&admin->lock);
list_add_tail(&eport->list, &admin->enabled);
mutex_unlock(&admin->lock);

return 0;
}

/* Disable this port for this VCAP instance */
static int vcap_disable(struct vcap_admin *admin, struct net_device *ndev,
/* Disable this port and chain id for a VCAP instance */
static int vcap_disable(struct vcap_control *vctrl, struct net_device *ndev,
unsigned long cookie)
{
struct vcap_enabled_port *eport;
struct vcap_enabled_port *elem, *eport = NULL;
struct vcap_admin *found = NULL, *admin;

list_for_each_entry(eport, &admin->enabled, list) {
if (eport->cookie == cookie && eport->ndev == ndev) {
list_del(&eport->list);
kfree(eport);
return 0;
list_for_each_entry(admin, &vctrl->list, list) {
list_for_each_entry(elem, &admin->enabled, list) {
if (elem->cookie == cookie && elem->ndev == ndev) {
eport = elem;
found = admin;
break;
}
}
if (eport)
break;
}

return -ENOENT;
}

/* Find the VCAP instance that enabled the port using a specific filter */
static struct vcap_admin *vcap_find_admin_by_cookie(struct vcap_control *vctrl,
unsigned long cookie)
{
struct vcap_enabled_port *eport;
struct vcap_admin *admin;

list_for_each_entry(admin, &vctrl->list, list)
list_for_each_entry(eport, &admin->enabled, list)
if (eport->cookie == cookie)
return admin;
if (!eport)
return -ENOENT;

return NULL;
mutex_lock(&found->lock);
list_del(&eport->list);
mutex_unlock(&found->lock);
kfree(eport);
return 0;
}

/* Enable/Disable the VCAP instance lookups. Chain id 0 means disable */
/* Enable/Disable the VCAP instance lookups */
int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
int chain_id, unsigned long cookie, bool enable)
int src_cid, int dst_cid, unsigned long cookie,
bool enable)
{
struct vcap_admin *admin;
int err;

err = vcap_api_check(vctrl);
Expand All @@ -2670,29 +2698,23 @@ int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
if (!ndev)
return -ENODEV;

if (chain_id)
admin = vcap_find_admin(vctrl, chain_id);
else
admin = vcap_find_admin_by_cookie(vctrl, cookie);
if (!admin)
return -ENOENT;

/* first instance and first chain */
if (admin->vinst || chain_id > admin->first_cid)
/* Source and destination must be the first chain in a lookup */
if (src_cid % VCAP_CID_LOOKUP_SIZE)
return -EFAULT;
if (dst_cid % VCAP_CID_LOOKUP_SIZE)
return -EFAULT;

if (chain_id) {
if (vcap_is_enabled(admin, ndev, cookie))
if (enable) {
if (vcap_is_enabled(vctrl, ndev, dst_cid))
return -EADDRINUSE;
mutex_lock(&admin->lock);
vcap_enable(admin, ndev, cookie);
if (vcap_is_chain_used(vctrl, ndev, src_cid))
return -EADDRNOTAVAIL;
err = vcap_enable(vctrl, ndev, cookie, src_cid, dst_cid);
} else {
mutex_lock(&admin->lock);
vcap_disable(admin, ndev, cookie);
err = vcap_disable(vctrl, ndev, cookie);
}
mutex_unlock(&admin->lock);

return 0;
return err;
}
EXPORT_SYMBOL_GPL(vcap_enable_lookups);

Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ethernet/microchip/vcap/vcap_api_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@ struct vcap_counter {
bool sticky;
};

/* Enable/Disable the VCAP instance lookups. Chain id 0 means disable */
/* Enable/Disable the VCAP instance lookups */
int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
int chain_id, unsigned long cookie, bool enable);
int from_cid, int to_cid, unsigned long cookie,
bool enable);

/* VCAP rule operations */
/* Allocate a rule and fill in the basic information */
Expand Down

0 comments on commit cfd9e7b

Please sign in to comment.