Skip to content

Commit ae91331

Browse files
committed
Merge branch 'net-lan966x-add-support-for-is1-vcap'
Horatiu Vultur says: ==================== net: lan966x: Add support for IS1 VCAP Provide the Ingress Stage 1 (IS1) VCAP (Versatile Content-Aware Processor) support for the Lan966x platform. The IS1 VCAP has 3 lookups and they are accessible with a TC chain id: - chain 1000000: IS1 Lookup 0 - chain 1100000: IS1 Lookup 1 - chain 1200000: IS1 Lookup 2 The IS1 is capable of different actions like rewrite VLAN tags, change priority of the frames, police the traffic, etc. These features will be added at a later point. The IS1 currently implements the action that allows setting the value of a PAG (Policy Association Group) key field in the frame metadata and this can be used for matching in an IS2 VCAP rule. In this way a rule in IS0 VCAP can be linked to rules in the IS2 VCAP. The linking is exposed by using the TC "goto chain" action with an offset from the IS2 chain ids. For example "goto chain 8000001" will use a PAG value of 1 to chain to a rule in IS2 lookup 0. ==================== Link: https://lore.kernel.org/r/20230307220929.834219-1-horatiu.vultur@microchip.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents cc4342f + 44d706f commit ae91331

File tree

8 files changed

+2156
-87
lines changed

8 files changed

+2156
-87
lines changed

drivers/net/ethernet/microchip/lan966x/lan966x_main.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@
9292
#define SE_IDX_QUEUE 0 /* 0-79 : Queue scheduler elements */
9393
#define SE_IDX_PORT 80 /* 80-89 : Port schedular elements */
9494

95+
#define LAN966X_VCAP_CID_IS1_L0 VCAP_CID_INGRESS_L0 /* IS1 lookup 0 */
96+
#define LAN966X_VCAP_CID_IS1_L1 VCAP_CID_INGRESS_L1 /* IS1 lookup 1 */
97+
#define LAN966X_VCAP_CID_IS1_L2 VCAP_CID_INGRESS_L2 /* IS1 lookup 2 */
98+
#define LAN966X_VCAP_CID_IS1_MAX (VCAP_CID_INGRESS_L3 - 1) /* IS1 Max */
99+
95100
#define LAN966X_VCAP_CID_IS2_L0 VCAP_CID_INGRESS_STAGE2_L0 /* IS2 lookup 0 */
96101
#define LAN966X_VCAP_CID_IS2_L1 VCAP_CID_INGRESS_STAGE2_L1 /* IS2 lookup 1 */
97102
#define LAN966X_VCAP_CID_IS2_MAX (VCAP_CID_INGRESS_STAGE2_L2 - 1) /* IS2 Max */
@@ -139,6 +144,39 @@ enum vcap_is2_port_sel_ipv6 {
139144
VCAP_IS2_PS_IPV6_MAC_ETYPE,
140145
};
141146

147+
enum vcap_is1_port_sel_other {
148+
VCAP_IS1_PS_OTHER_NORMAL,
149+
VCAP_IS1_PS_OTHER_7TUPLE,
150+
VCAP_IS1_PS_OTHER_DBL_VID,
151+
VCAP_IS1_PS_OTHER_DMAC_VID,
152+
};
153+
154+
enum vcap_is1_port_sel_ipv4 {
155+
VCAP_IS1_PS_IPV4_NORMAL,
156+
VCAP_IS1_PS_IPV4_7TUPLE,
157+
VCAP_IS1_PS_IPV4_5TUPLE_IP4,
158+
VCAP_IS1_PS_IPV4_DBL_VID,
159+
VCAP_IS1_PS_IPV4_DMAC_VID,
160+
};
161+
162+
enum vcap_is1_port_sel_ipv6 {
163+
VCAP_IS1_PS_IPV6_NORMAL,
164+
VCAP_IS1_PS_IPV6_7TUPLE,
165+
VCAP_IS1_PS_IPV6_5TUPLE_IP4,
166+
VCAP_IS1_PS_IPV6_NORMAL_IP6,
167+
VCAP_IS1_PS_IPV6_5TUPLE_IP6,
168+
VCAP_IS1_PS_IPV6_DBL_VID,
169+
VCAP_IS1_PS_IPV6_DMAC_VID,
170+
};
171+
172+
enum vcap_is1_port_sel_rt {
173+
VCAP_IS1_PS_RT_NORMAL,
174+
VCAP_IS1_PS_RT_7TUPLE,
175+
VCAP_IS1_PS_RT_DBL_VID,
176+
VCAP_IS1_PS_RT_DMAC_VID,
177+
VCAP_IS1_PS_RT_FOLLOW_OTHER = 7,
178+
};
179+
142180
struct lan966x_port;
143181

144182
struct lan966x_db {

drivers/net/ethernet/microchip/lan966x/lan966x_regs.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,42 @@ enum lan966x_target {
316316
#define ANA_DROP_CFG_DROP_MC_SMAC_ENA_GET(x)\
317317
FIELD_GET(ANA_DROP_CFG_DROP_MC_SMAC_ENA, x)
318318

319+
/* ANA:PORT:VCAP_CFG */
320+
#define ANA_VCAP_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 12, 0, 1, 4)
321+
322+
#define ANA_VCAP_CFG_S1_ENA BIT(14)
323+
#define ANA_VCAP_CFG_S1_ENA_SET(x)\
324+
FIELD_PREP(ANA_VCAP_CFG_S1_ENA, x)
325+
#define ANA_VCAP_CFG_S1_ENA_GET(x)\
326+
FIELD_GET(ANA_VCAP_CFG_S1_ENA, x)
327+
328+
/* ANA:PORT:VCAP_S1_KEY_CFG */
329+
#define ANA_VCAP_S1_CFG(g, r) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 16, r, 3, 4)
330+
331+
#define ANA_VCAP_S1_CFG_KEY_RT_CFG GENMASK(11, 9)
332+
#define ANA_VCAP_S1_CFG_KEY_RT_CFG_SET(x)\
333+
FIELD_PREP(ANA_VCAP_S1_CFG_KEY_RT_CFG, x)
334+
#define ANA_VCAP_S1_CFG_KEY_RT_CFG_GET(x)\
335+
FIELD_GET(ANA_VCAP_S1_CFG_KEY_RT_CFG, x)
336+
337+
#define ANA_VCAP_S1_CFG_KEY_IP6_CFG GENMASK(8, 6)
338+
#define ANA_VCAP_S1_CFG_KEY_IP6_CFG_SET(x)\
339+
FIELD_PREP(ANA_VCAP_S1_CFG_KEY_IP6_CFG, x)
340+
#define ANA_VCAP_S1_CFG_KEY_IP6_CFG_GET(x)\
341+
FIELD_GET(ANA_VCAP_S1_CFG_KEY_IP6_CFG, x)
342+
343+
#define ANA_VCAP_S1_CFG_KEY_IP4_CFG GENMASK(5, 3)
344+
#define ANA_VCAP_S1_CFG_KEY_IP4_CFG_SET(x)\
345+
FIELD_PREP(ANA_VCAP_S1_CFG_KEY_IP4_CFG, x)
346+
#define ANA_VCAP_S1_CFG_KEY_IP4_CFG_GET(x)\
347+
FIELD_GET(ANA_VCAP_S1_CFG_KEY_IP4_CFG, x)
348+
349+
#define ANA_VCAP_S1_CFG_KEY_OTHER_CFG GENMASK(2, 0)
350+
#define ANA_VCAP_S1_CFG_KEY_OTHER_CFG_SET(x)\
351+
FIELD_PREP(ANA_VCAP_S1_CFG_KEY_OTHER_CFG, x)
352+
#define ANA_VCAP_S1_CFG_KEY_OTHER_CFG_GET(x)\
353+
FIELD_GET(ANA_VCAP_S1_CFG_KEY_OTHER_CFG, x)
354+
319355
/* ANA:PORT:VCAP_S2_CFG */
320356
#define ANA_VCAP_S2_CFG(g) __REG(TARGET_ANA, 0, 1, 28672, g, 9, 128, 28, 0, 1, 4)
321357

drivers/net/ethernet/microchip/lan966x/lan966x_tc_flower.c

Lines changed: 210 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,34 @@
55
#include "vcap_api_client.h"
66
#include "vcap_tc.h"
77

8-
static bool lan966x_tc_is_known_etype(u16 etype)
8+
static bool lan966x_tc_is_known_etype(struct vcap_tc_flower_parse_usage *st,
9+
u16 etype)
910
{
10-
switch (etype) {
11-
case ETH_P_ALL:
12-
case ETH_P_ARP:
13-
case ETH_P_IP:
14-
case ETH_P_IPV6:
15-
return true;
11+
switch (st->admin->vtype) {
12+
case VCAP_TYPE_IS1:
13+
switch (etype) {
14+
case ETH_P_ALL:
15+
case ETH_P_ARP:
16+
case ETH_P_IP:
17+
case ETH_P_IPV6:
18+
return true;
19+
}
20+
break;
21+
case VCAP_TYPE_IS2:
22+
switch (etype) {
23+
case ETH_P_ALL:
24+
case ETH_P_ARP:
25+
case ETH_P_IP:
26+
case ETH_P_IPV6:
27+
case ETH_P_SNAP:
28+
case ETH_P_802_2:
29+
return true;
30+
}
31+
break;
32+
default:
33+
NL_SET_ERR_MSG_MOD(st->fco->common.extack,
34+
"VCAP type not supported");
35+
return false;
1636
}
1737

1838
return false;
@@ -69,7 +89,7 @@ lan966x_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)
6989
flow_rule_match_basic(st->frule, &match);
7090
if (match.mask->n_proto) {
7191
st->l3_proto = be16_to_cpu(match.key->n_proto);
72-
if (!lan966x_tc_is_known_etype(st->l3_proto)) {
92+
if (!lan966x_tc_is_known_etype(st, st->l3_proto)) {
7393
err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
7494
st->l3_proto, ~0);
7595
if (err)
@@ -79,18 +99,61 @@ lan966x_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)
7999
VCAP_BIT_1);
80100
if (err)
81101
goto out;
102+
} else if (st->l3_proto == ETH_P_IPV6 &&
103+
st->admin->vtype == VCAP_TYPE_IS1) {
104+
/* Don't set any keys in this case */
105+
} else if (st->l3_proto == ETH_P_SNAP &&
106+
st->admin->vtype == VCAP_TYPE_IS1) {
107+
err = vcap_rule_add_key_bit(st->vrule,
108+
VCAP_KF_ETYPE_LEN_IS,
109+
VCAP_BIT_0);
110+
if (err)
111+
goto out;
112+
113+
err = vcap_rule_add_key_bit(st->vrule,
114+
VCAP_KF_IP_SNAP_IS,
115+
VCAP_BIT_1);
116+
if (err)
117+
goto out;
118+
} else if (st->admin->vtype == VCAP_TYPE_IS1) {
119+
err = vcap_rule_add_key_bit(st->vrule,
120+
VCAP_KF_ETYPE_LEN_IS,
121+
VCAP_BIT_1);
122+
if (err)
123+
goto out;
124+
125+
err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
126+
st->l3_proto, ~0);
127+
if (err)
128+
goto out;
82129
}
83130
}
84131
if (match.mask->ip_proto) {
85132
st->l4_proto = match.key->ip_proto;
86133

87134
if (st->l4_proto == IPPROTO_TCP) {
135+
if (st->admin->vtype == VCAP_TYPE_IS1) {
136+
err = vcap_rule_add_key_bit(st->vrule,
137+
VCAP_KF_TCP_UDP_IS,
138+
VCAP_BIT_1);
139+
if (err)
140+
goto out;
141+
}
142+
88143
err = vcap_rule_add_key_bit(st->vrule,
89144
VCAP_KF_TCP_IS,
90145
VCAP_BIT_1);
91146
if (err)
92147
goto out;
93148
} else if (st->l4_proto == IPPROTO_UDP) {
149+
if (st->admin->vtype == VCAP_TYPE_IS1) {
150+
err = vcap_rule_add_key_bit(st->vrule,
151+
VCAP_KF_TCP_UDP_IS,
152+
VCAP_BIT_1);
153+
if (err)
154+
goto out;
155+
}
156+
94157
err = vcap_rule_add_key_bit(st->vrule,
95158
VCAP_KF_TCP_IS,
96159
VCAP_BIT_0);
@@ -112,12 +175,30 @@ lan966x_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)
112175
return err;
113176
}
114177

178+
static int
179+
lan966x_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st)
180+
{
181+
if (st->admin->vtype != VCAP_TYPE_IS1) {
182+
NL_SET_ERR_MSG_MOD(st->fco->common.extack,
183+
"cvlan not supported in this VCAP");
184+
return -EINVAL;
185+
}
186+
187+
return vcap_tc_flower_handler_cvlan_usage(st);
188+
}
189+
115190
static int
116191
lan966x_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st)
117192
{
118-
return vcap_tc_flower_handler_vlan_usage(st,
119-
VCAP_KF_8021Q_VID_CLS,
120-
VCAP_KF_8021Q_PCP_CLS);
193+
enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS;
194+
enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS;
195+
196+
if (st->admin->vtype == VCAP_TYPE_IS1) {
197+
vid_key = VCAP_KF_8021Q_VID0;
198+
pcp_key = VCAP_KF_8021Q_PCP0;
199+
}
200+
201+
return vcap_tc_flower_handler_vlan_usage(st, vid_key, pcp_key);
121202
}
122203

123204
static int
@@ -128,6 +209,7 @@ static int
128209
[FLOW_DISSECTOR_KEY_CONTROL] = lan966x_tc_flower_handler_control_usage,
129210
[FLOW_DISSECTOR_KEY_PORTS] = vcap_tc_flower_handler_portnum_usage,
130211
[FLOW_DISSECTOR_KEY_BASIC] = lan966x_tc_flower_handler_basic_usage,
212+
[FLOW_DISSECTOR_KEY_CVLAN] = lan966x_tc_flower_handler_cvlan_usage,
131213
[FLOW_DISSECTOR_KEY_VLAN] = lan966x_tc_flower_handler_vlan_usage,
132214
[FLOW_DISSECTOR_KEY_TCP] = vcap_tc_flower_handler_tcp_usage,
133215
[FLOW_DISSECTOR_KEY_ARP] = vcap_tc_flower_handler_arp_usage,
@@ -143,6 +225,7 @@ static int lan966x_tc_flower_use_dissectors(struct flow_cls_offload *f,
143225
.fco = f,
144226
.vrule = vrule,
145227
.l3_proto = ETH_P_ALL,
228+
.admin = admin,
146229
};
147230
int err = 0;
148231

@@ -221,6 +304,100 @@ static int lan966x_tc_flower_action_check(struct vcap_control *vctrl,
221304
return 0;
222305
}
223306

307+
/* Add the actionset that is the default for the VCAP type */
308+
static int lan966x_tc_set_actionset(struct vcap_admin *admin,
309+
struct vcap_rule *vrule)
310+
{
311+
enum vcap_actionfield_set aset;
312+
int err = 0;
313+
314+
switch (admin->vtype) {
315+
case VCAP_TYPE_IS1:
316+
aset = VCAP_AFS_S1;
317+
break;
318+
case VCAP_TYPE_IS2:
319+
aset = VCAP_AFS_BASE_TYPE;
320+
break;
321+
default:
322+
return -EINVAL;
323+
}
324+
325+
/* Do not overwrite any current actionset */
326+
if (vrule->actionset == VCAP_AFS_NO_VALUE)
327+
err = vcap_set_rule_set_actionset(vrule, aset);
328+
329+
return err;
330+
}
331+
332+
static int lan966x_tc_add_rule_link_target(struct vcap_admin *admin,
333+
struct vcap_rule *vrule,
334+
int target_cid)
335+
{
336+
int link_val = target_cid % VCAP_CID_LOOKUP_SIZE;
337+
int err;
338+
339+
if (!link_val)
340+
return 0;
341+
342+
switch (admin->vtype) {
343+
case VCAP_TYPE_IS1:
344+
/* Choose IS1 specific NXT_IDX key (for chaining rules from IS1) */
345+
err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL,
346+
1, ~0);
347+
if (err)
348+
return err;
349+
350+
return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX,
351+
link_val, ~0);
352+
case VCAP_TYPE_IS2:
353+
/* Add IS2 specific PAG key (for chaining rules from IS1) */
354+
return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG,
355+
link_val, ~0);
356+
default:
357+
break;
358+
}
359+
return 0;
360+
}
361+
362+
static int lan966x_tc_add_rule_link(struct vcap_control *vctrl,
363+
struct vcap_admin *admin,
364+
struct vcap_rule *vrule,
365+
struct flow_cls_offload *f,
366+
int to_cid)
367+
{
368+
struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid);
369+
int diff, err = 0;
370+
371+
if (!to_admin) {
372+
NL_SET_ERR_MSG_MOD(f->common.extack,
373+
"Unknown destination chain");
374+
return -EINVAL;
375+
}
376+
377+
diff = vcap_chain_offset(vctrl, f->common.chain_index, to_cid);
378+
if (!diff)
379+
return 0;
380+
381+
/* Between IS1 and IS2 the PAG value is used */
382+
if (admin->vtype == VCAP_TYPE_IS1 && to_admin->vtype == VCAP_TYPE_IS2) {
383+
/* This works for IS1->IS2 */
384+
err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff);
385+
if (err)
386+
return err;
387+
388+
err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_OVERRIDE_MASK,
389+
0xff);
390+
if (err)
391+
return err;
392+
} else {
393+
NL_SET_ERR_MSG_MOD(f->common.extack,
394+
"Unsupported chain destination");
395+
return -EOPNOTSUPP;
396+
}
397+
398+
return err;
399+
}
400+
224401
static int lan966x_tc_flower_add(struct lan966x_port *port,
225402
struct flow_cls_offload *f,
226403
struct vcap_admin *admin,
@@ -248,11 +425,23 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
248425
if (err)
249426
goto out;
250427

428+
err = lan966x_tc_add_rule_link_target(admin, vrule,
429+
f->common.chain_index);
430+
if (err)
431+
goto out;
432+
251433
frule = flow_cls_offload_flow_rule(f);
252434

253435
flow_action_for_each(idx, act, &frule->action) {
254436
switch (act->id) {
255437
case FLOW_ACTION_TRAP:
438+
if (admin->vtype != VCAP_TYPE_IS2) {
439+
NL_SET_ERR_MSG_MOD(f->common.extack,
440+
"Trap action not supported in this VCAP");
441+
err = -EOPNOTSUPP;
442+
goto out;
443+
}
444+
256445
err = vcap_rule_add_action_bit(vrule,
257446
VCAP_AF_CPU_COPY_ENA,
258447
VCAP_BIT_1);
@@ -266,6 +455,16 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
266455

267456
break;
268457
case FLOW_ACTION_GOTO:
458+
err = lan966x_tc_set_actionset(admin, vrule);
459+
if (err)
460+
goto out;
461+
462+
err = lan966x_tc_add_rule_link(port->lan966x->vcap_ctrl,
463+
admin, vrule,
464+
f, act->chain_index);
465+
if (err)
466+
goto out;
467+
269468
break;
270469
default:
271470
NL_SET_ERR_MSG_MOD(f->common.extack,

0 commit comments

Comments
 (0)