Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dbc2d68e authored by John Hurley's avatar John Hurley Committed by David S. Miller
Browse files

nfp: flower: handle merge hint messages



If a merge hint is received containing 2 flows that are matched via an
implicit recirculation (sending to and matching on an internal port), fw
reports that the flows (called sub_flows) may be able to be combined to a
single flow.

Add infastructure to accept and process merge hint messages. The actual
merging of the flows is left as a stub call.

Signed-off-by: default avatarJohn Hurley <john.hurley@netronome.com>
Signed-off-by: default avatarSimon Horman <simon.horman@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cf4172d5
Loading
Loading
Loading
Loading
+47 −1
Original line number Diff line number Diff line
@@ -204,6 +204,50 @@ nfp_flower_cmsg_portreify_rx(struct nfp_app *app, struct sk_buff *skb)
	wake_up(&priv->reify_wait_queue);
}

static void
nfp_flower_cmsg_merge_hint_rx(struct nfp_app *app, struct sk_buff *skb)
{
	unsigned int msg_len = nfp_flower_cmsg_get_data_len(skb);
	struct nfp_flower_cmsg_merge_hint *msg;
	struct nfp_fl_payload *sub_flows[2];
	int err, i, flow_cnt;

	msg = nfp_flower_cmsg_get_data(skb);
	/* msg->count starts at 0 and always assumes at least 1 entry. */
	flow_cnt = msg->count + 1;

	if (msg_len < struct_size(msg, flow, flow_cnt)) {
		nfp_flower_cmsg_warn(app, "Merge hint ctrl msg too short - %d bytes but expect %ld\n",
				     msg_len, struct_size(msg, flow, flow_cnt));
		return;
	}

	if (flow_cnt != 2) {
		nfp_flower_cmsg_warn(app, "Merge hint contains %d flows - two are expected\n",
				     flow_cnt);
		return;
	}

	rtnl_lock();
	for (i = 0; i < flow_cnt; i++) {
		u32 ctx = be32_to_cpu(msg->flow[i].host_ctx);

		sub_flows[i] = nfp_flower_get_fl_payload_from_ctx(app, ctx);
		if (!sub_flows[i]) {
			nfp_flower_cmsg_warn(app, "Invalid flow in merge hint\n");
			goto err_rtnl_unlock;
		}
	}

	err = nfp_flower_merge_offloaded_flows(app, sub_flows[0], sub_flows[1]);
	/* Only warn on memory fail. Hint veto will not break functionality. */
	if (err == -ENOMEM)
		nfp_flower_cmsg_warn(app, "Flow merge memory fail.\n");

err_rtnl_unlock:
	rtnl_unlock();
}

static void
nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
{
@@ -223,8 +267,10 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)
		nfp_flower_cmsg_portmod_rx(app, skb);
		break;
	case NFP_FLOWER_CMSG_TYPE_MERGE_HINT:
		if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MERGE)
		if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MERGE) {
			nfp_flower_cmsg_merge_hint_rx(app, skb);
			break;
		}
		goto err_default;
	case NFP_FLOWER_CMSG_TYPE_NO_NEIGH:
		nfp_tunnel_request_route(app, skb);
+10 −0
Original line number Diff line number Diff line
@@ -452,6 +452,16 @@ struct nfp_flower_cmsg_portreify {

#define NFP_FLOWER_CMSG_PORTREIFY_INFO_EXIST	BIT(0)

/* NFP_FLOWER_CMSG_TYPE_FLOW_MERGE_HINT */
struct nfp_flower_cmsg_merge_hint {
	u8 reserved[3];
	u8 count;
	struct {
		__be32 host_ctx;
		__be64 host_cookie;
	} __packed flow[0];
};

enum nfp_flower_cmsg_port_type {
	NFP_FLOWER_CMSG_PORT_TYPE_UNSPEC =	0x0,
	NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT =	0x1,
+3 −0
Original line number Diff line number Diff line
@@ -285,6 +285,9 @@ void nfp_flower_metadata_cleanup(struct nfp_app *app);

int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
			enum tc_setup_type type, void *type_data);
int nfp_flower_merge_offloaded_flows(struct nfp_app *app,
				     struct nfp_fl_payload *sub_flow1,
				     struct nfp_fl_payload *sub_flow2);
int nfp_flower_compile_flow_match(struct nfp_app *app,
				  struct tc_cls_flower_offload *flow,
				  struct nfp_fl_key_ls *key_ls,
+18 −0
Original line number Diff line number Diff line
@@ -388,6 +388,24 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
	return NULL;
}

/**
 * nfp_flower_merge_offloaded_flows() - Merge 2 existing flows to single flow.
 * @app:	Pointer to the APP handle
 * @sub_flow1:	Initial flow matched to produce merge hint
 * @sub_flow2:	Post recirculation flow matched in merge hint
 *
 * Combines 2 flows (if valid) to a single flow, removing the initial from hw
 * and offloading the new, merged flow.
 *
 * Return: negative value on error, 0 in success.
 */
int nfp_flower_merge_offloaded_flows(struct nfp_app *app,
				     struct nfp_fl_payload *sub_flow1,
				     struct nfp_fl_payload *sub_flow2)
{
	return -EOPNOTSUPP;
}

/**
 * nfp_flower_add_offload() - Adds a new flow to hardware.
 * @app:	Pointer to the APP handle