@@ -309,6 +309,75 @@ static int lan966x_tc_set_actionset(struct vcap_admin *admin,
309309 return err ;
310310}
311311
312+ static int lan966x_tc_add_rule_link_target (struct vcap_admin * admin ,
313+ struct vcap_rule * vrule ,
314+ int target_cid )
315+ {
316+ int link_val = target_cid % VCAP_CID_LOOKUP_SIZE ;
317+ int err ;
318+
319+ if (!link_val )
320+ return 0 ;
321+
322+ switch (admin -> vtype ) {
323+ case VCAP_TYPE_IS1 :
324+ /* Choose IS1 specific NXT_IDX key (for chaining rules from IS1) */
325+ err = vcap_rule_add_key_u32 (vrule , VCAP_KF_LOOKUP_GEN_IDX_SEL ,
326+ 1 , ~0 );
327+ if (err )
328+ return err ;
329+
330+ return vcap_rule_add_key_u32 (vrule , VCAP_KF_LOOKUP_GEN_IDX ,
331+ link_val , ~0 );
332+ case VCAP_TYPE_IS2 :
333+ /* Add IS2 specific PAG key (for chaining rules from IS1) */
334+ return vcap_rule_add_key_u32 (vrule , VCAP_KF_LOOKUP_PAG ,
335+ link_val , ~0 );
336+ default :
337+ break ;
338+ }
339+ return 0 ;
340+ }
341+
342+ static int lan966x_tc_add_rule_link (struct vcap_control * vctrl ,
343+ struct vcap_admin * admin ,
344+ struct vcap_rule * vrule ,
345+ struct flow_cls_offload * f ,
346+ int to_cid )
347+ {
348+ struct vcap_admin * to_admin = vcap_find_admin (vctrl , to_cid );
349+ int diff , err = 0 ;
350+
351+ if (!to_admin ) {
352+ NL_SET_ERR_MSG_MOD (f -> common .extack ,
353+ "Unknown destination chain" );
354+ return - EINVAL ;
355+ }
356+
357+ diff = vcap_chain_offset (vctrl , f -> common .chain_index , to_cid );
358+ if (!diff )
359+ return 0 ;
360+
361+ /* Between IS1 and IS2 the PAG value is used */
362+ if (admin -> vtype == VCAP_TYPE_IS1 && to_admin -> vtype == VCAP_TYPE_IS2 ) {
363+ /* This works for IS1->IS2 */
364+ err = vcap_rule_add_action_u32 (vrule , VCAP_AF_PAG_VAL , diff );
365+ if (err )
366+ return err ;
367+
368+ err = vcap_rule_add_action_u32 (vrule , VCAP_AF_PAG_OVERRIDE_MASK ,
369+ 0xff );
370+ if (err )
371+ return err ;
372+ } else {
373+ NL_SET_ERR_MSG_MOD (f -> common .extack ,
374+ "Unsupported chain destination" );
375+ return - EOPNOTSUPP ;
376+ }
377+
378+ return err ;
379+ }
380+
312381static int lan966x_tc_flower_add (struct lan966x_port * port ,
313382 struct flow_cls_offload * f ,
314383 struct vcap_admin * admin ,
@@ -336,6 +405,11 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
336405 if (err )
337406 goto out ;
338407
408+ err = lan966x_tc_add_rule_link_target (admin , vrule ,
409+ f -> common .chain_index );
410+ if (err )
411+ goto out ;
412+
339413 frule = flow_cls_offload_flow_rule (f );
340414
341415 flow_action_for_each (idx , act , & frule -> action ) {
@@ -365,6 +439,12 @@ static int lan966x_tc_flower_add(struct lan966x_port *port,
365439 if (err )
366440 goto out ;
367441
442+ err = lan966x_tc_add_rule_link (port -> lan966x -> vcap_ctrl ,
443+ admin , vrule ,
444+ f , act -> chain_index );
445+ if (err )
446+ goto out ;
447+
368448 break ;
369449 default :
370450 NL_SET_ERR_MSG_MOD (f -> common .extack ,
0 commit comments