DPDK patches and discussions
 help / color / mirror / Atom feed
From: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
To: dev@dpdk.org
Cc: shahafs@mellanox.com, stable@dpdk.org
Subject: [dpdk-dev] [PATCH] net/mlx5: fix tc rule handle assignment
Date: Tue, 22 Jan 2019 12:05:46 +0000	[thread overview]
Message-ID: <1548158746-9885-1-git-send-email-viacheslavo@mellanox.com> (raw)

When tc rule is created via Netlink message application
can provide the unique rule value which can be accepted
by the kernel. Than rule is managed with this assigned
handle. It was found that kernel can reject the proposed
handle and assign its own handle value, the rule control
is lost, because application uses its initially prorosed
rule handle and knows nothing about handle been repleced.

The kernel can assign handle automatically, the application
can get the assigned handle value by specifying NLM_F_ECHO
flag in Netlink message when rule is being created. The
kernel sends back the full descriptor of rule and handle
can be retrieved from and stored by application for further
rule management.

Fixes: 57123c00c1b8 ("net/mlx5: add Linux TC flower driver for E-Switch flow")
Cc: stable@dpdk.org

Signed-off-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_tcf.c | 97 +++++++++++++++++++++++++---------------
 1 file changed, 60 insertions(+), 37 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c
index cf34742..859e99a 100644
--- a/drivers/net/mlx5/mlx5_flow_tcf.c
+++ b/drivers/net/mlx5/mlx5_flow_tcf.c
@@ -2778,27 +2778,6 @@ struct pedit_parser {
 }
 
 /**
- * Brand rtnetlink buffer with unique handle.
- *
- * This handle should be unique for a given network interface to avoid
- * collisions.
- *
- * @param nlh
- *   Pointer to Netlink message.
- * @param handle
- *   Unique 32-bit handle to use.
- */
-static void
-flow_tcf_nl_brand(struct nlmsghdr *nlh, uint32_t handle)
-{
-	struct tcmsg *tcm = mnl_nlmsg_get_payload(nlh);
-
-	tcm->tcm_handle = handle;
-	DRV_LOG(DEBUG, "Netlink msg %p is branded with handle %x",
-		(void *)nlh, handle);
-}
-
-/**
  * Prepare a flow object for Linux TC flower. It calculates the maximum size of
  * memory required, allocates the memory, initializes Netlink message headers
  * and set unique TC message handle.
@@ -2888,20 +2867,6 @@ struct pedit_parser {
 		dev_flow->tcf.tunnel->type = FLOW_TCF_TUNACT_VXLAN_DECAP;
 	else if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)
 		dev_flow->tcf.tunnel->type = FLOW_TCF_TUNACT_VXLAN_ENCAP;
-	/*
-	 * Generate a reasonably unique handle based on the address of the
-	 * target buffer.
-	 *
-	 * This is straightforward on 32-bit systems where the flow pointer can
-	 * be used directly. Otherwise, its least significant part is taken
-	 * after shifting it by the previous power of two of the pointed buffer
-	 * size.
-	 */
-	if (sizeof(dev_flow) <= 4)
-		flow_tcf_nl_brand(nlh, (uintptr_t)dev_flow);
-	else
-		flow_tcf_nl_brand(nlh, (uintptr_t)dev_flow >>
-				       rte_log2_u32(rte_align32prevpow2(size)));
 	return dev_flow;
 }
 
@@ -5593,6 +5558,7 @@ struct tcf_nlcb_query {
 	struct mlx5_flow_tcf_context *ctx = priv->tcf_context;
 	struct mlx5_flow *dev_flow;
 	struct nlmsghdr *nlh;
+	struct tcmsg *tcm;
 
 	if (!flow)
 		return;
@@ -5613,11 +5579,54 @@ struct tcf_nlcb_query {
 				dev_flow);
 			dev_flow->tcf.tunnel->vtep = NULL;
 		}
+		/* Cleanup the rule handle value. */
+		tcm = mnl_nlmsg_get_payload(nlh);
+		tcm->tcm_handle = 0;
 		dev_flow->tcf.applied = 0;
 	}
 }
 
 /**
+ * Fetch the applied rule handle. This is callback routine called by
+ * libmnl mnl_cb_run() in loop for every message in received packet.
+ * When the NLM_F_ECHO flag i sspecified the kernel sends the created
+ * rule descriptor back to the application and we can retrieve the
+ * actual rule handle from updated descriptor.
+ *
+ * @param[in] nlh
+ *   Pointer to reply header.
+ * @param[in, out] arg
+ *   Context pointer for this callback.
+ *
+ * @return
+ *   A positive, nonzero value on success (required by libmnl
+ *   to continue messages processing).
+ */
+static int
+flow_tcf_collect_apply_cb(const struct nlmsghdr *nlh, void *arg)
+{
+	struct nlmsghdr *nlhrq = arg;
+	struct tcmsg *tcmrq = mnl_nlmsg_get_payload(nlhrq);
+	struct tcmsg *tcm = mnl_nlmsg_get_payload(nlh);
+	struct nlattr *na;
+
+	if (nlh->nlmsg_type != RTM_NEWTFILTER ||
+	    nlh->nlmsg_seq != nlhrq->nlmsg_seq)
+		return 1;
+	mnl_attr_for_each(na, nlh, sizeof(*tcm)) {
+		switch (mnl_attr_get_type(na)) {
+		case TCA_KIND:
+			if (strcmp(mnl_attr_get_payload(na), "flower")) {
+				/* Not flower filter, drop entire message. */
+				return 1;
+			}
+			tcmrq->tcm_handle = tcm->tcm_handle;
+			return 1;
+		}
+	}
+	return 1;
+}
+/**
  * Apply flow to E-Switch by sending Netlink message.
  *
  * @param[in] dev
@@ -5638,6 +5647,8 @@ struct tcf_nlcb_query {
 	struct mlx5_flow_tcf_context *ctx = priv->tcf_context;
 	struct mlx5_flow *dev_flow;
 	struct nlmsghdr *nlh;
+	struct tcmsg *tcm;
+	int ret;
 
 	dev_flow = LIST_FIRST(&flow->dev_flows);
 	/* E-Switch flow can't be expanded. */
@@ -5646,7 +5657,11 @@ struct tcf_nlcb_query {
 		return 0;
 	nlh = dev_flow->tcf.nlh;
 	nlh->nlmsg_type = RTM_NEWTFILTER;
-	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
+	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE |
+			   NLM_F_EXCL | NLM_F_ECHO;
+	tcm = mnl_nlmsg_get_payload(nlh);
+	/* Allow kernel to assign handle on its own. */
+	tcm->tcm_handle = 0;
 	if (dev_flow->tcf.tunnel) {
 		/*
 		 * Replace the interface index, target for
@@ -5667,7 +5682,15 @@ struct tcf_nlcb_query {
 		*dev_flow->tcf.tunnel->ifindex_ptr =
 			dev_flow->tcf.tunnel->vtep->ifindex;
 	}
-	if (!flow_tcf_nl_ack(ctx, nlh, NULL, NULL)) {
+	ret = flow_tcf_nl_ack(ctx, nlh, flow_tcf_collect_apply_cb, nlh);
+	if (!ret) {
+		if (!tcm->tcm_handle) {
+			flow_tcf_remove(dev, flow);
+			return rte_flow_error_set
+				(error, ENOENT,
+				 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				 "netlink: rule zero handle returned");
+		}
 		dev_flow->tcf.applied = 1;
 		if (*dev_flow->tcf.ptc_flags & TCA_CLS_FLAGS_SKIP_SW)
 			return 0;
-- 
1.8.3.1

             reply	other threads:[~2019-01-22 12:06 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-22 12:05 Viacheslav Ovsiienko [this message]
2019-01-24 11:16 ` Shahaf Shuler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1548158746-9885-1-git-send-email-viacheslavo@mellanox.com \
    --to=viacheslavo@mellanox.com \
    --cc=dev@dpdk.org \
    --cc=shahafs@mellanox.com \
    --cc=stable@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).