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+
115190static int
116191lan966x_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
123204static 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+
224401static 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