Skip to content

Commit aa6ce2e

Browse files
jahurleydavem330
authored andcommitted
nfp: flower: support stats update for merge flows
With the merging of 2 sub flows, a new 'merge' flow will be created and written to FW. The TC layer is unaware that the merge flow exists and will request stats from the sub flows. Conversely, the FW treats a merge rule the same as any other rule and sends stats updates to the NFP driver. Add links between merge flows and their sub flows. Use these links to pass merge flow stats updates from FW to the underlying sub flows, ensuring TC stats requests are handled correctly. The updating of sub flow stats is done on (the less time critcal) TC stats requests rather than on FW stats update. Signed-off-by: John Hurley <[email protected]> Signed-off-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1c6952c commit aa6ce2e

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,24 @@ struct nfp_fl_payload {
252252
char *unmasked_data;
253253
char *mask_data;
254254
char *action_data;
255+
struct list_head linked_flows;
256+
};
257+
258+
struct nfp_fl_payload_link {
259+
/* A link contains a pointer to a merge flow and an associated sub_flow.
260+
* Each merge flow will feature in 2 links to its underlying sub_flows.
261+
* A sub_flow will have at least 1 link to a merge flow or more if it
262+
* has been used to create multiple merge flows.
263+
*
264+
* For a merge flow, 'linked_flows' in its nfp_fl_payload struct lists
265+
* all links to sub_flows (sub_flow.flow) via merge.list.
266+
* For a sub_flow, 'linked_flows' gives all links to merge flows it has
267+
* formed (merge_flow.flow) via sub_flow.list.
268+
*/
269+
struct {
270+
struct list_head list;
271+
struct nfp_fl_payload *flow;
272+
} merge_flow, sub_flow;
255273
};
256274

257275
extern const struct rhashtable_params nfp_flower_table_params;

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

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
398398

399399
flow_pay->nfp_tun_ipv4_addr = 0;
400400
flow_pay->meta.flags = 0;
401+
INIT_LIST_HEAD(&flow_pay->linked_flows);
401402

402403
return flow_pay;
403404

@@ -716,6 +717,43 @@ nfp_flower_merge_action(struct nfp_fl_payload *sub_flow1,
716717
return 0;
717718
}
718719

720+
/* Flow link code should only be accessed under RTNL. */
721+
static void nfp_flower_unlink_flow(struct nfp_fl_payload_link *link)
722+
{
723+
list_del(&link->merge_flow.list);
724+
list_del(&link->sub_flow.list);
725+
kfree(link);
726+
}
727+
728+
static void nfp_flower_unlink_flows(struct nfp_fl_payload *merge_flow,
729+
struct nfp_fl_payload *sub_flow)
730+
{
731+
struct nfp_fl_payload_link *link;
732+
733+
list_for_each_entry(link, &merge_flow->linked_flows, merge_flow.list)
734+
if (link->sub_flow.flow == sub_flow) {
735+
nfp_flower_unlink_flow(link);
736+
return;
737+
}
738+
}
739+
740+
static int nfp_flower_link_flows(struct nfp_fl_payload *merge_flow,
741+
struct nfp_fl_payload *sub_flow)
742+
{
743+
struct nfp_fl_payload_link *link;
744+
745+
link = kmalloc(sizeof(*link), GFP_KERNEL);
746+
if (!link)
747+
return -ENOMEM;
748+
749+
link->merge_flow.flow = merge_flow;
750+
list_add_tail(&link->merge_flow.list, &merge_flow->linked_flows);
751+
link->sub_flow.flow = sub_flow;
752+
list_add_tail(&link->sub_flow.list, &sub_flow->linked_flows);
753+
754+
return 0;
755+
}
756+
719757
/**
720758
* nfp_flower_merge_offloaded_flows() - Merge 2 existing flows to single flow.
721759
* @app: Pointer to the APP handle
@@ -764,8 +802,19 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app,
764802
if (err)
765803
goto err_destroy_merge_flow;
766804

805+
err = nfp_flower_link_flows(merge_flow, sub_flow1);
806+
if (err)
807+
goto err_destroy_merge_flow;
808+
809+
err = nfp_flower_link_flows(merge_flow, sub_flow2);
810+
if (err)
811+
goto err_unlink_sub_flow1;
812+
767813
err = -EOPNOTSUPP;
768814

815+
nfp_flower_unlink_flows(merge_flow, sub_flow2);
816+
err_unlink_sub_flow1:
817+
nfp_flower_unlink_flows(merge_flow, sub_flow1);
769818
err_destroy_merge_flow:
770819
kfree(merge_flow->action_data);
771820
kfree(merge_flow->mask_data);
@@ -913,6 +962,52 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
913962
return err;
914963
}
915964

965+
static void
966+
__nfp_flower_update_merge_stats(struct nfp_app *app,
967+
struct nfp_fl_payload *merge_flow)
968+
{
969+
struct nfp_flower_priv *priv = app->priv;
970+
struct nfp_fl_payload_link *link;
971+
struct nfp_fl_payload *sub_flow;
972+
u64 pkts, bytes, used;
973+
u32 ctx_id;
974+
975+
ctx_id = be32_to_cpu(merge_flow->meta.host_ctx_id);
976+
pkts = priv->stats[ctx_id].pkts;
977+
/* Do not cycle subflows if no stats to distribute. */
978+
if (!pkts)
979+
return;
980+
bytes = priv->stats[ctx_id].bytes;
981+
used = priv->stats[ctx_id].used;
982+
983+
/* Reset stats for the merge flow. */
984+
priv->stats[ctx_id].pkts = 0;
985+
priv->stats[ctx_id].bytes = 0;
986+
987+
/* The merge flow has received stats updates from firmware.
988+
* Distribute these stats to all subflows that form the merge.
989+
* The stats will collected from TC via the subflows.
990+
*/
991+
list_for_each_entry(link, &merge_flow->linked_flows, merge_flow.list) {
992+
sub_flow = link->sub_flow.flow;
993+
ctx_id = be32_to_cpu(sub_flow->meta.host_ctx_id);
994+
priv->stats[ctx_id].pkts += pkts;
995+
priv->stats[ctx_id].bytes += bytes;
996+
max_t(u64, priv->stats[ctx_id].used, used);
997+
}
998+
}
999+
1000+
static void
1001+
nfp_flower_update_merge_stats(struct nfp_app *app,
1002+
struct nfp_fl_payload *sub_flow)
1003+
{
1004+
struct nfp_fl_payload_link *link;
1005+
1006+
/* Get merge flows that the subflow forms to distribute their stats. */
1007+
list_for_each_entry(link, &sub_flow->linked_flows, sub_flow.list)
1008+
__nfp_flower_update_merge_stats(app, link->merge_flow.flow);
1009+
}
1010+
9161011
/**
9171012
* nfp_flower_get_stats() - Populates flow stats obtained from hardware.
9181013
* @app: Pointer to the APP handle
@@ -939,6 +1034,10 @@ nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev,
9391034
ctx_id = be32_to_cpu(nfp_flow->meta.host_ctx_id);
9401035

9411036
spin_lock_bh(&priv->stats_lock);
1037+
/* If request is for a sub_flow, update stats from merged flows. */
1038+
if (!list_empty(&nfp_flow->linked_flows))
1039+
nfp_flower_update_merge_stats(app, nfp_flow);
1040+
9421041
flow_stats_update(&flow->stats, priv->stats[ctx_id].bytes,
9431042
priv->stats[ctx_id].pkts, priv->stats[ctx_id].used);
9441043

0 commit comments

Comments
 (0)