From mboxrd@z Thu Jan 1 00:00:00 1970 From: Slava Ovsiienko Subject: [PATCH 4/4] net/mlx5: add E-switch rule hardware offload flag check Date: Mon, 12 Nov 2018 20:01:42 +0000 Message-ID: <1542052877-41512-5-git-send-email-viacheslavo@mellanox.com> References: <1541225876-8817-2-git-send-email-viacheslavo@mellanox.com> <1542052877-41512-1-git-send-email-viacheslavo@mellanox.com> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Cc: "dev@dpdk.org" , Slava Ovsiienko To: Shahaf Shuler , Yongseok Koh Return-path: Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-eopbgr80050.outbound.protection.outlook.com [40.107.8.50]) by dpdk.org (Postfix) with ESMTP id 66D0C4CAD for ; Mon, 12 Nov 2018 21:01:43 +0100 (CET) In-Reply-To: <1542052877-41512-1-git-send-email-viacheslavo@mellanox.com> Content-Language: en-US List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds the in_hw flag check for tc flower filter rules. If rule is applied without skip_sw flag set driver should check whether the in_hw flag is set after rule applying. If no in_hw flag set found it means the rule is not hardware offloaded and error should be returned to application. Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_tcf.c | 142 +++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 142 insertions(+) diff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_= tcf.c index 5bfb2d8..91deb88 100644 --- a/drivers/net/mlx5/mlx5_flow_tcf.c +++ b/drivers/net/mlx5/mlx5_flow_tcf.c @@ -5082,6 +5082,134 @@ struct tcf_nlcb_context { pthread_mutex_unlock(&vtep_list_mutex); } =20 +struct tcf_nlcb_query { + uint32_t handle; + uint32_t tc_flags; + uint32_t flags_valid:1; +}; + +/** + * Collect queried rule attributes. This is callback routine called by + * libmnl mnl_cb_run() in loop for every message in received packet. + * Current implementation collects the flower flags only. + * + * @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_query_cb(const struct nlmsghdr *nlh, void *arg) +{ + struct tcf_nlcb_query *query =3D arg; + struct tcmsg *tcm =3D mnl_nlmsg_get_payload(nlh); + struct nlattr *na, *na_opt; + bool flower =3D false; + + if (nlh->nlmsg_type !=3D RTM_NEWTFILTER || + tcm->tcm_handle !=3D query->handle) + 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; + } + flower =3D true; + break; + case TCA_OPTIONS: + if (!flower) { + /* Not flower options, drop entire message. */ + return 1; + } + /* Check nested flower options. */ + mnl_attr_for_each_nested(na_opt, na) { + switch (mnl_attr_get_type(na_opt)) { + case TCA_FLOWER_FLAGS: + query->flags_valid =3D 1; + query->tc_flags =3D + mnl_attr_get_u32(na_opt); + break; + } + } + break; + } + } + return 1; +} + +/** + * Query a TC flower rule flags via netlink. + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] dev_flow + * Pointer to the flow. + * @param[out] pflags + * pointer to the data retrieved by the query. + * + * @return + * 0 on success, a negative errno value otherwise. + */ +static int +flow_tcf_query_flags(struct mlx5_flow_tcf_context *tcf, + struct mlx5_flow *dev_flow, + uint32_t *pflags) +{ + struct nlmsghdr *nlh; + struct tcmsg *tcm; + struct tcf_nlcb_query query =3D { + .handle =3D dev_flow->tcf.tcm->tcm_handle, + }; + + nlh =3D mnl_nlmsg_put_header(tcf->buf); + nlh->nlmsg_type =3D RTM_GETTFILTER; + nlh->nlmsg_flags =3D NLM_F_REQUEST; + tcm =3D mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm)); + memcpy(tcm, dev_flow->tcf.tcm, sizeof(*tcm)); + /* + * Ignore Netlink error for filter query operations. + * The reply length is sent by kernel as errno. + * Just check we got the flags option. + */ + flow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_query_cb, &query); + if (!query.flags_valid) { + *pflags =3D 0; + return -ENOENT; + } + *pflags =3D query.tc_flags; + return 0; +} + +/** + * Query and check the in_hw set for specified rule. + * + * @param[in] tcf + * Context object initialized by mlx5_flow_tcf_context_create(). + * @param[in] dev_flow + * Pointer to the flow to check. + * + * @return + * 0 on success, a negative errno value otherwise. + */ +static int +flow_tcf_check_inhw(struct mlx5_flow_tcf_context *tcf, + struct mlx5_flow *dev_flow) +{ + uint32_t flags; + int ret; + + ret =3D flow_tcf_query_flags(tcf, dev_flow, &flags); + if (ret) + return ret; + return (flags & TCA_CLS_FLAGS_IN_HW) ? 0 : -ENOENT; +} + /** * Remove flow from E-Switch by sending Netlink message. * @@ -5173,6 +5301,20 @@ struct tcf_nlcb_context { } if (!flow_tcf_nl_ack(ctx, nlh, NULL, NULL)) { dev_flow->tcf.applied =3D 1; + if (*dev_flow->tcf.ptc_flags & TCA_CLS_FLAGS_SKIP_SW) + return 0; + /* + * Rule was applied without skip_sw flag set. + * We should check whether the rule was acctually + * accepted by hardware (have look at in_hw flag). + */ + if (flow_tcf_check_inhw(ctx, dev_flow)) { + flow_tcf_remove(dev, flow); + return rte_flow_error_set + (error, ENOENT, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "netlink: rule has no in_hw flag set"); + } return 0; } if (dev_flow->tcf.tunnel) { --=20 1.8.3.1