net: lan966x: Add TC filter chaining support for IS1 and IS2 VCAPs

Allow rules to be chained between IS1 VCAP and IS2 VCAP. Chaining
between IS1 lookups or between IS2 lookups are not supported by the
hardware.

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Horatiu Vultur 2023-03-07 23:09:28 +01:00 committed by Jakub Kicinski
parent 135c2116fd
commit b3762a9db3

View file

@ -309,6 +309,75 @@ static int lan966x_tc_set_actionset(struct vcap_admin *admin,
return err;
}
static int lan966x_tc_add_rule_link_target(struct vcap_admin *admin,
struct vcap_rule *vrule,
int target_cid)
{
int link_val = target_cid % VCAP_CID_LOOKUP_SIZE;
int err;
if (!link_val)
return 0;
switch (admin->vtype) {
case VCAP_TYPE_IS1:
/* Choose IS1 specific NXT_IDX key (for chaining rules from IS1) */
err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL,
1, ~0);
if (err)
return err;
return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX,
link_val, ~0);
case VCAP_TYPE_IS2:
/* Add IS2 specific PAG key (for chaining rules from IS1) */
return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG,
link_val, ~0);
default:
break;
}
return 0;
}
static int lan966x_tc_add_rule_link(struct vcap_control *vctrl,
struct vcap_admin *admin,
struct vcap_rule *vrule,
struct flow_cls_offload *f,
int to_cid)
{
struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid);
int diff, err = 0;
if (!to_admin) {
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unknown destination chain");
return -EINVAL;
}
diff = vcap_chain_offset(vctrl, f->common.chain_index, to_cid);
if (!diff)
return 0;
/* Between IS1 and IS2 the PAG value is used */
if (admin->vtype == VCAP_TYPE_IS1 && to_admin->vtype == VCAP_TYPE_IS2) {
/* This works for IS1->IS2 */
err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff);
if (err)
return err;
err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_OVERRIDE_MASK,
0xff);
if (err)
return err;
} else {
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported chain destination");
return -EOPNOTSUPP;
}
return err;
}
static int lan966x_tc_flower_add(struct lan966x_port *port,
struct flow_cls_offload *f,
struct vcap_admin *admin,
@ -336,6 +405,11 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
if (err)
goto out;
err = lan966x_tc_add_rule_link_target(admin, vrule,
f->common.chain_index);
if (err)
goto out;
frule = flow_cls_offload_flow_rule(f);
flow_action_for_each(idx, act, &frule->action) {
@ -365,6 +439,12 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
if (err)
goto out;
err = lan966x_tc_add_rule_link(port->lan966x->vcap_ctrl,
admin, vrule,
f, act->chain_index);
if (err)
goto out;
break;
default:
NL_SET_ERR_MSG_MOD(f->common.extack,