Skip to content

Commit 1c6952c

Browse files
jahurleydavem330
authored andcommitted
nfp: flower: generate merge flow rule
When combining 2 sub_flows to a single 'merge flow' (assuming the merge is valid), the merge flow should contain the same match fields as sub_flow 1 with actions derived from a combination of sub_flows 1 and 2. This action list should have all actions from sub_flow 1 with the exception of the output action that triggered the 'implicit recirculation' by sending to an internal port, followed by all actions of sub_flow 2. Any pre-actions in either sub_flow should feature at the start of the action list. Add code to generate a new merge flow and populate the match and actions fields based on the sub_flows. The offloading of the flow is left to future patches. Signed-off-by: John Hurley <[email protected]> Signed-off-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 107e37b commit 1c6952c

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed

drivers/net/ethernet/netronome/nfp/flower/main.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,15 @@ nfp_flower_internal_port_can_offload(struct nfp_app *app,
279279
return false;
280280
}
281281

282+
/* The address of the merged flow acts as its cookie.
283+
* Cookies supplied to us by TC flower are also addresses to allocated
284+
* memory and thus this scheme should not generate any collisions.
285+
*/
286+
static inline bool nfp_flower_is_merge_flow(struct nfp_fl_payload *flow_pay)
287+
{
288+
return flow_pay->tc_flower_cookie == (unsigned long)flow_pay;
289+
}
290+
282291
int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
283292
unsigned int host_ctx_split);
284293
void nfp_flower_metadata_cleanup(struct nfp_app *app);

drivers/net/ethernet/netronome/nfp/flower/offload.c

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,112 @@ nfp_flower_can_merge(struct nfp_fl_payload *sub_flow1,
610610
return 0;
611611
}
612612

613+
static unsigned int
614+
nfp_flower_copy_pre_actions(char *act_dst, char *act_src, int len,
615+
bool *tunnel_act)
616+
{
617+
unsigned int act_off = 0, act_len;
618+
struct nfp_fl_act_head *a;
619+
u8 act_id = 0;
620+
621+
while (act_off < len) {
622+
a = (struct nfp_fl_act_head *)&act_src[act_off];
623+
act_len = a->len_lw << NFP_FL_LW_SIZ;
624+
act_id = a->jump_id;
625+
626+
switch (act_id) {
627+
case NFP_FL_ACTION_OPCODE_PRE_TUNNEL:
628+
if (tunnel_act)
629+
*tunnel_act = true;
630+
case NFP_FL_ACTION_OPCODE_PRE_LAG:
631+
memcpy(act_dst + act_off, act_src + act_off, act_len);
632+
break;
633+
default:
634+
return act_off;
635+
}
636+
637+
act_off += act_len;
638+
}
639+
640+
return act_off;
641+
}
642+
643+
static int nfp_fl_verify_post_tun_acts(char *acts, int len)
644+
{
645+
struct nfp_fl_act_head *a;
646+
unsigned int act_off = 0;
647+
648+
while (act_off < len) {
649+
a = (struct nfp_fl_act_head *)&acts[act_off];
650+
if (a->jump_id != NFP_FL_ACTION_OPCODE_OUTPUT)
651+
return -EOPNOTSUPP;
652+
653+
act_off += a->len_lw << NFP_FL_LW_SIZ;
654+
}
655+
656+
return 0;
657+
}
658+
659+
static int
660+
nfp_flower_merge_action(struct nfp_fl_payload *sub_flow1,
661+
struct nfp_fl_payload *sub_flow2,
662+
struct nfp_fl_payload *merge_flow)
663+
{
664+
unsigned int sub1_act_len, sub2_act_len, pre_off1, pre_off2;
665+
bool tunnel_act = false;
666+
char *merge_act;
667+
int err;
668+
669+
/* The last action of sub_flow1 must be output - do not merge this. */
670+
sub1_act_len = sub_flow1->meta.act_len - sizeof(struct nfp_fl_output);
671+
sub2_act_len = sub_flow2->meta.act_len;
672+
673+
if (!sub2_act_len)
674+
return -EINVAL;
675+
676+
if (sub1_act_len + sub2_act_len > NFP_FL_MAX_A_SIZ)
677+
return -EINVAL;
678+
679+
/* A shortcut can only be applied if there is a single action. */
680+
if (sub1_act_len)
681+
merge_flow->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL);
682+
else
683+
merge_flow->meta.shortcut = sub_flow2->meta.shortcut;
684+
685+
merge_flow->meta.act_len = sub1_act_len + sub2_act_len;
686+
merge_act = merge_flow->action_data;
687+
688+
/* Copy any pre-actions to the start of merge flow action list. */
689+
pre_off1 = nfp_flower_copy_pre_actions(merge_act,
690+
sub_flow1->action_data,
691+
sub1_act_len, &tunnel_act);
692+
merge_act += pre_off1;
693+
sub1_act_len -= pre_off1;
694+
pre_off2 = nfp_flower_copy_pre_actions(merge_act,
695+
sub_flow2->action_data,
696+
sub2_act_len, NULL);
697+
merge_act += pre_off2;
698+
sub2_act_len -= pre_off2;
699+
700+
/* FW does a tunnel push when egressing, therefore, if sub_flow 1 pushes
701+
* a tunnel, sub_flow 2 can only have output actions for a valid merge.
702+
*/
703+
if (tunnel_act) {
704+
char *post_tun_acts = &sub_flow2->action_data[pre_off2];
705+
706+
err = nfp_fl_verify_post_tun_acts(post_tun_acts, sub2_act_len);
707+
if (err)
708+
return err;
709+
}
710+
711+
/* Copy remaining actions from sub_flows 1 and 2. */
712+
memcpy(merge_act, sub_flow1->action_data + pre_off1, sub1_act_len);
713+
merge_act += sub1_act_len;
714+
memcpy(merge_act, sub_flow2->action_data + pre_off2, sub2_act_len);
715+
716+
return 0;
717+
}
718+
613719
/**
614720
* nfp_flower_merge_offloaded_flows() - Merge 2 existing flows to single flow.
615721
* @app: Pointer to the APP handle
@@ -625,13 +731,47 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app,
625731
struct nfp_fl_payload *sub_flow1,
626732
struct nfp_fl_payload *sub_flow2)
627733
{
734+
struct nfp_fl_payload *merge_flow;
735+
struct nfp_fl_key_ls merge_key_ls;
628736
int err;
629737

738+
ASSERT_RTNL();
739+
740+
if (sub_flow1 == sub_flow2 ||
741+
nfp_flower_is_merge_flow(sub_flow1) ||
742+
nfp_flower_is_merge_flow(sub_flow2))
743+
return -EINVAL;
744+
630745
err = nfp_flower_can_merge(sub_flow1, sub_flow2);
631746
if (err)
632747
return err;
633748

634-
return -EOPNOTSUPP;
749+
merge_key_ls.key_size = sub_flow1->meta.key_len;
750+
751+
merge_flow = nfp_flower_allocate_new(&merge_key_ls);
752+
if (!merge_flow)
753+
return -ENOMEM;
754+
755+
merge_flow->tc_flower_cookie = (unsigned long)merge_flow;
756+
merge_flow->ingress_dev = sub_flow1->ingress_dev;
757+
758+
memcpy(merge_flow->unmasked_data, sub_flow1->unmasked_data,
759+
sub_flow1->meta.key_len);
760+
memcpy(merge_flow->mask_data, sub_flow1->mask_data,
761+
sub_flow1->meta.mask_len);
762+
763+
err = nfp_flower_merge_action(sub_flow1, sub_flow2, merge_flow);
764+
if (err)
765+
goto err_destroy_merge_flow;
766+
767+
err = -EOPNOTSUPP;
768+
769+
err_destroy_merge_flow:
770+
kfree(merge_flow->action_data);
771+
kfree(merge_flow->mask_data);
772+
kfree(merge_flow->unmasked_data);
773+
kfree(merge_flow);
774+
return err;
635775
}
636776

637777
/**

0 commit comments

Comments
 (0)