Commit e7e3f514 authored by Steen Hegelund's avatar Steen Hegelund Committed by David S. Miller

net: microchip: sparx5: Add ingress information to VCAP instance

This allows the check of the goto action to be specific to the ingress and
egress VCAP instances.

The debugfs support is also updated to show this information.
Signed-off-by: default avatarSteen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b95d9e2c
...@@ -603,7 +603,8 @@ int lan966x_vcap_init(struct lan966x *lan966x); ...@@ -603,7 +603,8 @@ int lan966x_vcap_init(struct lan966x *lan966x);
void lan966x_vcap_deinit(struct lan966x *lan966x); void lan966x_vcap_deinit(struct lan966x *lan966x);
int lan966x_tc_flower(struct lan966x_port *port, int lan966x_tc_flower(struct lan966x_port *port,
struct flow_cls_offload *f); struct flow_cls_offload *f,
bool ingress);
int lan966x_goto_port_add(struct lan966x_port *port, int lan966x_goto_port_add(struct lan966x_port *port,
int from_cid, int to_cid, int from_cid, int to_cid,
......
...@@ -70,7 +70,7 @@ static int lan966x_tc_block_cb(enum tc_setup_type type, void *type_data, ...@@ -70,7 +70,7 @@ static int lan966x_tc_block_cb(enum tc_setup_type type, void *type_data,
case TC_SETUP_CLSMATCHALL: case TC_SETUP_CLSMATCHALL:
return lan966x_tc_matchall(port, type_data, ingress); return lan966x_tc_matchall(port, type_data, ingress);
case TC_SETUP_CLSFLOWER: case TC_SETUP_CLSFLOWER:
return lan966x_tc_flower(port, type_data); return lan966x_tc_flower(port, type_data, ingress);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -83,7 +83,8 @@ static int lan966x_tc_flower_use_dissectors(struct flow_cls_offload *f, ...@@ -83,7 +83,8 @@ static int lan966x_tc_flower_use_dissectors(struct flow_cls_offload *f,
static int lan966x_tc_flower_action_check(struct vcap_control *vctrl, static int lan966x_tc_flower_action_check(struct vcap_control *vctrl,
struct net_device *dev, struct net_device *dev,
struct flow_cls_offload *fco) struct flow_cls_offload *fco,
bool ingress)
{ {
struct flow_rule *rule = flow_cls_offload_flow_rule(fco); struct flow_rule *rule = flow_cls_offload_flow_rule(fco);
struct flow_action_entry *actent, *last_actent = NULL; struct flow_action_entry *actent, *last_actent = NULL;
...@@ -120,7 +121,8 @@ static int lan966x_tc_flower_action_check(struct vcap_control *vctrl, ...@@ -120,7 +121,8 @@ static int lan966x_tc_flower_action_check(struct vcap_control *vctrl,
"Invalid goto chain"); "Invalid goto chain");
return -EINVAL; return -EINVAL;
} }
} else if (!vcap_is_last_chain(vctrl, fco->common.chain_index)) { } else if (!vcap_is_last_chain(vctrl, fco->common.chain_index,
ingress)) {
NL_SET_ERR_MSG_MOD(fco->common.extack, NL_SET_ERR_MSG_MOD(fco->common.extack,
"Last action must be 'goto'"); "Last action must be 'goto'");
return -EINVAL; return -EINVAL;
...@@ -139,7 +141,8 @@ static int lan966x_tc_flower_action_check(struct vcap_control *vctrl, ...@@ -139,7 +141,8 @@ static int lan966x_tc_flower_action_check(struct vcap_control *vctrl,
static int lan966x_tc_flower_add(struct lan966x_port *port, static int lan966x_tc_flower_add(struct lan966x_port *port,
struct flow_cls_offload *f, struct flow_cls_offload *f,
struct vcap_admin *admin) struct vcap_admin *admin,
bool ingress)
{ {
struct flow_action_entry *act; struct flow_action_entry *act;
u16 l3_proto = ETH_P_ALL; u16 l3_proto = ETH_P_ALL;
...@@ -148,7 +151,7 @@ static int lan966x_tc_flower_add(struct lan966x_port *port, ...@@ -148,7 +151,7 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
int err, idx; int err, idx;
err = lan966x_tc_flower_action_check(port->lan966x->vcap_ctrl, err = lan966x_tc_flower_action_check(port->lan966x->vcap_ctrl,
port->dev, f); port->dev, f, ingress);
if (err) if (err)
return err; return err;
...@@ -232,7 +235,8 @@ static int lan966x_tc_flower_del(struct lan966x_port *port, ...@@ -232,7 +235,8 @@ static int lan966x_tc_flower_del(struct lan966x_port *port,
} }
int lan966x_tc_flower(struct lan966x_port *port, int lan966x_tc_flower(struct lan966x_port *port,
struct flow_cls_offload *f) struct flow_cls_offload *f,
bool ingress)
{ {
struct vcap_admin *admin; struct vcap_admin *admin;
...@@ -245,7 +249,7 @@ int lan966x_tc_flower(struct lan966x_port *port, ...@@ -245,7 +249,7 @@ int lan966x_tc_flower(struct lan966x_port *port,
switch (f->command) { switch (f->command) {
case FLOW_CLS_REPLACE: case FLOW_CLS_REPLACE:
return lan966x_tc_flower_add(port, f, admin); return lan966x_tc_flower_add(port, f, admin, ingress);
case FLOW_CLS_DESTROY: case FLOW_CLS_DESTROY:
return lan966x_tc_flower_del(port, f, admin); return lan966x_tc_flower_del(port, f, admin);
default: default:
......
...@@ -23,6 +23,7 @@ static struct lan966x_vcap_inst { ...@@ -23,6 +23,7 @@ static struct lan966x_vcap_inst {
int first_cid; /* first chain id in this vcap */ int first_cid; /* first chain id in this vcap */
int last_cid; /* last chain id in this vcap */ int last_cid; /* last chain id in this vcap */
int count; /* number of available addresses */ int count; /* number of available addresses */
bool ingress; /* is vcap in the ingress path */
} lan966x_vcap_inst_cfg[] = { } lan966x_vcap_inst_cfg[] = {
{ {
.vtype = VCAP_TYPE_IS2, /* IS2-0 */ .vtype = VCAP_TYPE_IS2, /* IS2-0 */
...@@ -31,6 +32,7 @@ static struct lan966x_vcap_inst { ...@@ -31,6 +32,7 @@ static struct lan966x_vcap_inst {
.first_cid = LAN966X_VCAP_CID_IS2_L0, .first_cid = LAN966X_VCAP_CID_IS2_L0,
.last_cid = LAN966X_VCAP_CID_IS2_MAX, .last_cid = LAN966X_VCAP_CID_IS2_MAX,
.count = 256, .count = 256,
.ingress = true,
}, },
}; };
...@@ -431,6 +433,7 @@ lan966x_vcap_admin_alloc(struct lan966x *lan966x, struct vcap_control *ctrl, ...@@ -431,6 +433,7 @@ lan966x_vcap_admin_alloc(struct lan966x *lan966x, struct vcap_control *ctrl,
admin->vtype = cfg->vtype; admin->vtype = cfg->vtype;
admin->vinst = 0; admin->vinst = 0;
admin->ingress = cfg->ingress;
admin->w32be = true; admin->w32be = true;
admin->tgt_inst = cfg->tgt_inst; admin->tgt_inst = cfg->tgt_inst;
......
...@@ -618,7 +618,8 @@ static int sparx5_tc_use_dissectors(struct flow_cls_offload *fco, ...@@ -618,7 +618,8 @@ static int sparx5_tc_use_dissectors(struct flow_cls_offload *fco,
static int sparx5_tc_flower_action_check(struct vcap_control *vctrl, static int sparx5_tc_flower_action_check(struct vcap_control *vctrl,
struct net_device *ndev, struct net_device *ndev,
struct flow_cls_offload *fco) struct flow_cls_offload *fco,
bool ingress)
{ {
struct flow_rule *rule = flow_cls_offload_flow_rule(fco); struct flow_rule *rule = flow_cls_offload_flow_rule(fco);
struct flow_action_entry *actent, *last_actent = NULL; struct flow_action_entry *actent, *last_actent = NULL;
...@@ -655,7 +656,8 @@ static int sparx5_tc_flower_action_check(struct vcap_control *vctrl, ...@@ -655,7 +656,8 @@ static int sparx5_tc_flower_action_check(struct vcap_control *vctrl,
"Invalid goto chain"); "Invalid goto chain");
return -EINVAL; return -EINVAL;
} }
} else if (!vcap_is_last_chain(vctrl, fco->common.chain_index)) { } else if (!vcap_is_last_chain(vctrl, fco->common.chain_index,
ingress)) {
NL_SET_ERR_MSG_MOD(fco->common.extack, NL_SET_ERR_MSG_MOD(fco->common.extack,
"Last action must be 'goto'"); "Last action must be 'goto'");
return -EINVAL; return -EINVAL;
...@@ -970,7 +972,8 @@ static int sparx5_tc_add_rule_link(struct vcap_control *vctrl, ...@@ -970,7 +972,8 @@ static int sparx5_tc_add_rule_link(struct vcap_control *vctrl,
static int sparx5_tc_flower_replace(struct net_device *ndev, static int sparx5_tc_flower_replace(struct net_device *ndev,
struct flow_cls_offload *fco, struct flow_cls_offload *fco,
struct vcap_admin *admin) struct vcap_admin *admin,
bool ingress)
{ {
struct sparx5_port *port = netdev_priv(ndev); struct sparx5_port *port = netdev_priv(ndev);
struct sparx5_multiple_rules multi = {}; struct sparx5_multiple_rules multi = {};
...@@ -983,7 +986,7 @@ static int sparx5_tc_flower_replace(struct net_device *ndev, ...@@ -983,7 +986,7 @@ static int sparx5_tc_flower_replace(struct net_device *ndev,
vctrl = port->sparx5->vcap_ctrl; vctrl = port->sparx5->vcap_ctrl;
err = sparx5_tc_flower_action_check(vctrl, ndev, fco); err = sparx5_tc_flower_action_check(vctrl, ndev, fco, ingress);
if (err) if (err)
return err; return err;
...@@ -1141,7 +1144,7 @@ int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco, ...@@ -1141,7 +1144,7 @@ int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,
switch (fco->command) { switch (fco->command) {
case FLOW_CLS_REPLACE: case FLOW_CLS_REPLACE:
return sparx5_tc_flower_replace(ndev, fco, admin); return sparx5_tc_flower_replace(ndev, fco, admin, ingress);
case FLOW_CLS_DESTROY: case FLOW_CLS_DESTROY:
return sparx5_tc_flower_destroy(ndev, fco, admin); return sparx5_tc_flower_destroy(ndev, fco, admin);
case FLOW_CLS_STATS: case FLOW_CLS_STATS:
......
...@@ -55,6 +55,7 @@ static struct sparx5_vcap_inst { ...@@ -55,6 +55,7 @@ static struct sparx5_vcap_inst {
int map_id; /* id in the super vcap block mapping (if applicable) */ int map_id; /* id in the super vcap block mapping (if applicable) */
int blockno; /* starting block in super vcap (if applicable) */ int blockno; /* starting block in super vcap (if applicable) */
int blocks; /* number of blocks in super vcap (if applicable) */ int blocks; /* number of blocks in super vcap (if applicable) */
bool ingress; /* is vcap in the ingress path */
} sparx5_vcap_inst_cfg[] = { } sparx5_vcap_inst_cfg[] = {
{ {
.vtype = VCAP_TYPE_IS0, /* CLM-0 */ .vtype = VCAP_TYPE_IS0, /* CLM-0 */
...@@ -66,6 +67,7 @@ static struct sparx5_vcap_inst { ...@@ -66,6 +67,7 @@ static struct sparx5_vcap_inst {
.last_cid = SPARX5_VCAP_CID_IS0_L2 - 1, .last_cid = SPARX5_VCAP_CID_IS0_L2 - 1,
.blockno = 8, /* Maps block 8-9 */ .blockno = 8, /* Maps block 8-9 */
.blocks = 2, .blocks = 2,
.ingress = true,
}, },
{ {
.vtype = VCAP_TYPE_IS0, /* CLM-1 */ .vtype = VCAP_TYPE_IS0, /* CLM-1 */
...@@ -77,6 +79,7 @@ static struct sparx5_vcap_inst { ...@@ -77,6 +79,7 @@ static struct sparx5_vcap_inst {
.last_cid = SPARX5_VCAP_CID_IS0_L4 - 1, .last_cid = SPARX5_VCAP_CID_IS0_L4 - 1,
.blockno = 6, /* Maps block 6-7 */ .blockno = 6, /* Maps block 6-7 */
.blocks = 2, .blocks = 2,
.ingress = true,
}, },
{ {
.vtype = VCAP_TYPE_IS0, /* CLM-2 */ .vtype = VCAP_TYPE_IS0, /* CLM-2 */
...@@ -88,6 +91,7 @@ static struct sparx5_vcap_inst { ...@@ -88,6 +91,7 @@ static struct sparx5_vcap_inst {
.last_cid = SPARX5_VCAP_CID_IS0_MAX, .last_cid = SPARX5_VCAP_CID_IS0_MAX,
.blockno = 4, /* Maps block 4-5 */ .blockno = 4, /* Maps block 4-5 */
.blocks = 2, .blocks = 2,
.ingress = true,
}, },
{ {
.vtype = VCAP_TYPE_IS2, /* IS2-0 */ .vtype = VCAP_TYPE_IS2, /* IS2-0 */
...@@ -99,6 +103,7 @@ static struct sparx5_vcap_inst { ...@@ -99,6 +103,7 @@ static struct sparx5_vcap_inst {
.last_cid = SPARX5_VCAP_CID_IS2_L2 - 1, .last_cid = SPARX5_VCAP_CID_IS2_L2 - 1,
.blockno = 0, /* Maps block 0-1 */ .blockno = 0, /* Maps block 0-1 */
.blocks = 2, .blocks = 2,
.ingress = true,
}, },
{ {
.vtype = VCAP_TYPE_IS2, /* IS2-1 */ .vtype = VCAP_TYPE_IS2, /* IS2-1 */
...@@ -110,6 +115,7 @@ static struct sparx5_vcap_inst { ...@@ -110,6 +115,7 @@ static struct sparx5_vcap_inst {
.last_cid = SPARX5_VCAP_CID_IS2_MAX, .last_cid = SPARX5_VCAP_CID_IS2_MAX,
.blockno = 2, /* Maps block 2-3 */ .blockno = 2, /* Maps block 2-3 */
.blocks = 2, .blocks = 2,
.ingress = true,
}, },
{ {
.vtype = VCAP_TYPE_ES2, .vtype = VCAP_TYPE_ES2,
...@@ -118,6 +124,7 @@ static struct sparx5_vcap_inst { ...@@ -118,6 +124,7 @@ static struct sparx5_vcap_inst {
.first_cid = SPARX5_VCAP_CID_ES2_L0, .first_cid = SPARX5_VCAP_CID_ES2_L0,
.last_cid = SPARX5_VCAP_CID_ES2_MAX, .last_cid = SPARX5_VCAP_CID_ES2_MAX,
.count = 12288, /* Addresses according to datasheet */ .count = 12288, /* Addresses according to datasheet */
.ingress = false,
}, },
}; };
...@@ -1413,6 +1420,7 @@ sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl, ...@@ -1413,6 +1420,7 @@ sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl,
mutex_init(&admin->lock); mutex_init(&admin->lock);
admin->vtype = cfg->vtype; admin->vtype = cfg->vtype;
admin->vinst = cfg->vinst; admin->vinst = cfg->vinst;
admin->ingress = cfg->ingress;
admin->lookups = cfg->lookups; admin->lookups = cfg->lookups;
admin->lookups_per_instance = cfg->lookups_per_instance; admin->lookups_per_instance = cfg->lookups_per_instance;
admin->first_cid = cfg->first_cid; admin->first_cid = cfg->first_cid;
......
...@@ -1601,15 +1601,17 @@ struct vcap_admin *vcap_find_admin(struct vcap_control *vctrl, int cid) ...@@ -1601,15 +1601,17 @@ struct vcap_admin *vcap_find_admin(struct vcap_control *vctrl, int cid)
} }
EXPORT_SYMBOL_GPL(vcap_find_admin); EXPORT_SYMBOL_GPL(vcap_find_admin);
/* Is this the last admin instance ordered by chain id */ /* Is this the last admin instance ordered by chain id and direction */
static bool vcap_admin_is_last(struct vcap_control *vctrl, static bool vcap_admin_is_last(struct vcap_control *vctrl,
struct vcap_admin *admin) struct vcap_admin *admin,
bool ingress)
{ {
struct vcap_admin *iter, *last = NULL; struct vcap_admin *iter, *last = NULL;
int max_cid = 0; int max_cid = 0;
list_for_each_entry(iter, &vctrl->list, list) { list_for_each_entry(iter, &vctrl->list, list) {
if (iter->first_cid > max_cid) { if (iter->first_cid > max_cid &&
iter->ingress == ingress) {
last = iter; last = iter;
max_cid = iter->first_cid; max_cid = iter->first_cid;
} }
...@@ -3177,7 +3179,7 @@ int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev, ...@@ -3177,7 +3179,7 @@ int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
EXPORT_SYMBOL_GPL(vcap_enable_lookups); EXPORT_SYMBOL_GPL(vcap_enable_lookups);
/* Is this chain id the last lookup of all VCAPs */ /* Is this chain id the last lookup of all VCAPs */
bool vcap_is_last_chain(struct vcap_control *vctrl, int cid) bool vcap_is_last_chain(struct vcap_control *vctrl, int cid, bool ingress)
{ {
struct vcap_admin *admin; struct vcap_admin *admin;
int lookup; int lookup;
...@@ -3189,7 +3191,7 @@ bool vcap_is_last_chain(struct vcap_control *vctrl, int cid) ...@@ -3189,7 +3191,7 @@ bool vcap_is_last_chain(struct vcap_control *vctrl, int cid)
if (!admin) if (!admin)
return false; return false;
if (!vcap_admin_is_last(vctrl, admin)) if (!vcap_admin_is_last(vctrl, admin, ingress))
return false; return false;
/* This must be the last lookup in this VCAP type */ /* This must be the last lookup in this VCAP type */
......
...@@ -176,6 +176,7 @@ struct vcap_admin { ...@@ -176,6 +176,7 @@ struct vcap_admin {
int first_valid_addr; /* bottom of address range to be used */ int first_valid_addr; /* bottom of address range to be used */
int last_used_addr; /* address of lowest added rule */ int last_used_addr; /* address of lowest added rule */
bool w32be; /* vcap uses "32bit-word big-endian" encoding */ bool w32be; /* vcap uses "32bit-word big-endian" encoding */
bool ingress; /* chain traffic direction */
struct vcap_cache_data cache; /* encoded rule data */ struct vcap_cache_data cache; /* encoded rule data */
}; };
......
...@@ -222,7 +222,7 @@ int vcap_chain_offset(struct vcap_control *vctrl, int from_cid, int to_cid); ...@@ -222,7 +222,7 @@ int vcap_chain_offset(struct vcap_control *vctrl, int from_cid, int to_cid);
/* Is the next chain id in the following lookup, possible in another VCAP */ /* Is the next chain id in the following lookup, possible in another VCAP */
bool vcap_is_next_lookup(struct vcap_control *vctrl, int cur_cid, int next_cid); bool vcap_is_next_lookup(struct vcap_control *vctrl, int cur_cid, int next_cid);
/* Is this chain id the last lookup of all VCAPs */ /* Is this chain id the last lookup of all VCAPs */
bool vcap_is_last_chain(struct vcap_control *vctrl, int cid); bool vcap_is_last_chain(struct vcap_control *vctrl, int cid, bool ingress);
/* Provide all rules via a callback interface */ /* Provide all rules via a callback interface */
int vcap_rule_iter(struct vcap_control *vctrl, int vcap_rule_iter(struct vcap_control *vctrl,
int (*callback)(void *, struct vcap_rule *), void *arg); int (*callback)(void *, struct vcap_rule *), void *arg);
......
...@@ -280,6 +280,7 @@ static void vcap_show_admin_info(struct vcap_control *vctrl, ...@@ -280,6 +280,7 @@ static void vcap_show_admin_info(struct vcap_control *vctrl,
out->prf(out->dst, "version: %d\n", vcap->version); out->prf(out->dst, "version: %d\n", vcap->version);
out->prf(out->dst, "vtype: %d\n", admin->vtype); out->prf(out->dst, "vtype: %d\n", admin->vtype);
out->prf(out->dst, "vinst: %d\n", admin->vinst); out->prf(out->dst, "vinst: %d\n", admin->vinst);
out->prf(out->dst, "ingress: %d\n", admin->ingress);
out->prf(out->dst, "first_cid: %d\n", admin->first_cid); out->prf(out->dst, "first_cid: %d\n", admin->first_cid);
out->prf(out->dst, "last_cid: %d\n", admin->last_cid); out->prf(out->dst, "last_cid: %d\n", admin->last_cid);
out->prf(out->dst, "lookups: %d\n", admin->lookups); out->prf(out->dst, "lookups: %d\n", admin->lookups);
......
...@@ -389,6 +389,7 @@ static const char * const test_admin_info_expect[] = { ...@@ -389,6 +389,7 @@ static const char * const test_admin_info_expect[] = {
"version: 1\n", "version: 1\n",
"vtype: 2\n", "vtype: 2\n",
"vinst: 0\n", "vinst: 0\n",
"ingress: 1\n",
"first_cid: 10000\n", "first_cid: 10000\n",
"last_cid: 19999\n", "last_cid: 19999\n",
"lookups: 4\n", "lookups: 4\n",
...@@ -407,6 +408,7 @@ static void vcap_api_show_admin_test(struct kunit *test) ...@@ -407,6 +408,7 @@ static void vcap_api_show_admin_test(struct kunit *test)
.last_valid_addr = 3071, .last_valid_addr = 3071,
.first_valid_addr = 0, .first_valid_addr = 0,
.last_used_addr = 794, .last_used_addr = 794,
.ingress = true,
}; };
struct vcap_output_print out = { struct vcap_output_print out = {
.prf = (void *)test_prf, .prf = (void *)test_prf,
...@@ -435,6 +437,7 @@ static const char * const test_admin_expect[] = { ...@@ -435,6 +437,7 @@ static const char * const test_admin_expect[] = {
"version: 1\n", "version: 1\n",
"vtype: 2\n", "vtype: 2\n",
"vinst: 0\n", "vinst: 0\n",
"ingress: 1\n",
"first_cid: 8000000\n", "first_cid: 8000000\n",
"last_cid: 8199999\n", "last_cid: 8199999\n",
"lookups: 4\n", "lookups: 4\n",
...@@ -496,6 +499,7 @@ static void vcap_api_show_admin_rule_test(struct kunit *test) ...@@ -496,6 +499,7 @@ static void vcap_api_show_admin_rule_test(struct kunit *test)
.last_valid_addr = 3071, .last_valid_addr = 3071,
.first_valid_addr = 0, .first_valid_addr = 0,
.last_used_addr = 794, .last_used_addr = 794,
.ingress = true,
.cache = { .cache = {
.keystream = keydata, .keystream = keydata,
.maskstream = mskdata, .maskstream = mskdata,
......
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