From patchwork Wed Jun 27 15:07:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?N=C3=A9lio_Laranjeiro?= X-Patchwork-Id: 41686 X-Patchwork-Delegate: shahafs@mellanox.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 330531BFF1; Wed, 27 Jun 2018 17:08:01 +0200 (CEST) Received: from mail-wr0-f194.google.com (mail-wr0-f194.google.com [209.85.128.194]) by dpdk.org (Postfix) with ESMTP id 9DC6D1BFBF for ; Wed, 27 Jun 2018 17:07:45 +0200 (CEST) Received: by mail-wr0-f194.google.com with SMTP id k16-v6so2412324wro.0 for ; Wed, 27 Jun 2018 08:07:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references; bh=PqKDnXhwtZPMfywHazvZ9gKvn+hH1CQYQA5s61neoXs=; b=Zb9rcoZb+AqLkaGcgEcFK2Xg3WslnLZ+eSXDCk1APzOg+P1Rx6xwLRwyTBRZmQvjlx lkv55rSpmCbc3qMGSqbmQTNBYaMir1QH7IswtVDplqlqbTmw7EyQXIqN1/suQxrwnoTH 0wvp5Brr0LAbyucQb48ml44icMMV6ohBH74sOydli0u+uLdAim3f9WWZPCtmqNjXlLtG sCk6s2r7NSRvd0sVqqnSBxYY6V35OhPOoyFVhJchUxGCU3CwYzwpvhMxXSf8V7oXtvFc RgU/A0KNq7E+3JHHCjtovJhnnW7XOWs1DBEAEimQBC9VGCgWFZOxPjgp1EjHO/AKg7gd lxMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=PqKDnXhwtZPMfywHazvZ9gKvn+hH1CQYQA5s61neoXs=; b=AEF6eZUFbJePeBE0og/qyRuSFt96MGbXoIAk5eJH35Z0vYurMVkqKEy4nVKIqkqCx2 pABfCXEAmdAGd575MboZgkxA+cEkieNzg5QnTG4koxlWoSdXCDQ18jLPg0yew3oeEXgK TaIIxaHFi21xOuXCc2FKn8LvRm5KbETiTjBuD5+JEHhBZXZ/goguplTHnacGB90EML1g z/RYzUtHI7IwT8VSIZRIV0bWhS2y0SVs/Jwj4NrCJhzbAuQZPR9Lzwa2MrubPMnfL3d+ jJyq+dt7JDApjXLkzG358XV4oi+05L3RBikvK1PA4qxSeepsAEOfRcBZpAQKifI0YP1X V2DQ== X-Gm-Message-State: APt69E1HBnQvvVEfZZR3Ce9Ab1iwLm6KmbpJXDTcC7N3jNuntcFunyFj Xt9w9oU1MmmlL2zP4neBX9fxFTkRqg== X-Google-Smtp-Source: AAOMgpf1BiNv3ImEA1G2AGjC1muDBR5jzJHvp+3XrB7HEb3Oc9NB2jpTSxBhbsllNarVTCPdBwXqlA== X-Received: by 2002:adf:99ea:: with SMTP id y97-v6mr5414013wrb.215.1530112065047; Wed, 27 Jun 2018 08:07:45 -0700 (PDT) Received: from laranjeiro-vm.dev.6wind.com (host.78.145.23.62.rev.coltfrance.com. [62.23.145.78]) by smtp.gmail.com with ESMTPSA id k17-v6sm4872513wrp.19.2018.06.27.08.07.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Jun 2018 08:07:44 -0700 (PDT) From: Nelio Laranjeiro To: dev@dpdk.org, Adrien Mazarguil , Yongseok Koh Date: Wed, 27 Jun 2018 17:07:44 +0200 Message-Id: <90a73b5f33e147ffa3a668f5d19410de17f96045.1530111623.git.nelio.laranjeiro@6wind.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: References: Subject: [dpdk-dev] [PATCH v2 12/20] net/mlx5: add mark/flag flow action X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 209 +++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 57f072c03..a39157533 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -52,6 +52,10 @@ extern const struct eth_dev_ops mlx5_dev_ops_isolate; #define MLX5_FLOW_FATE_DROP (1u << 0) #define MLX5_FLOW_FATE_QUEUE (1u << 1) +/* Modify a packet. */ +#define MLX5_FLOW_MOD_FLAG (1u << 0) +#define MLX5_FLOW_MOD_MARK (1u << 1) + /** Handles information leading to a drop fate. */ struct mlx5_flow_verbs { unsigned int size; /**< Size of the attribute. */ @@ -70,6 +74,8 @@ struct rte_flow { struct rte_flow_attr attributes; /**< User flow attribute. */ uint32_t layers; /**< Bit-fields of present layers see MLX5_FLOW_ITEMS_*. */ + uint32_t modifier; + /**< Bit-fields of present modifier see MLX5_FLOW_MOD_*. */ uint32_t fate; /**< Bit-fields of present fate see MLX5_FLOW_FATE_*. */ struct mlx5_flow_verbs verbs; /* Verbs flow. */ @@ -954,6 +960,12 @@ mlx5_flow_action_drop(const struct rte_flow_action *actions, actions, "multiple fate actions are not" " supported"); + if (flow->modifier & (MLX5_FLOW_MOD_FLAG | MLX5_FLOW_MOD_MARK)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "drop is not compatible with" + " flag/mark action"); if (size < flow_size) mlx5_flow_spec_verbs_add(flow, &drop, size); flow->fate |= MLX5_FLOW_FATE_DROP; @@ -1007,6 +1019,144 @@ mlx5_flow_action_queue(struct rte_eth_dev *dev, return 0; } +/** + * Validate action flag provided by the user. + * + * @param actions + * Pointer to flow actions array. + * @param flow + * Pointer to the rte_flow structure. + * @param flow_size + * Size in bytes of the available space for to store the flow information. + * @param error + * Pointer to error structure. + * + * @return + * size in bytes necessary for the conversion, a negative errno value + * otherwise and rte_errno is set. + */ +static int +mlx5_flow_action_flag(const struct rte_flow_action *actions, + struct rte_flow *flow, const size_t flow_size, + struct rte_flow_error *error) +{ + unsigned int size = sizeof(struct ibv_flow_spec_action_tag); + struct ibv_flow_spec_action_tag tag = { + .type = IBV_FLOW_SPEC_ACTION_TAG, + .size = size, + .tag_id = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT), + }; + + if (flow->modifier & MLX5_FLOW_MOD_FLAG) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "flag action already present"); + if (flow->fate & MLX5_FLOW_FATE_DROP) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "flag is not compatible with drop" + " action"); + if (flow->modifier & MLX5_FLOW_MOD_MARK) + return 0; + flow->modifier |= MLX5_FLOW_MOD_FLAG; + if (size <= flow_size) + mlx5_flow_spec_verbs_add(flow, &tag, size); + return size; +} + +/** + * Update verbs specification to modify the flag to mark. + * + * @param flow + * Pointer to the rte_flow structure. + * @param mark_id + * Mark identifier to replace the flag. + */ +static void +mlx5_flow_verbs_mark_update(struct rte_flow *flow, uint32_t mark_id) +{ + struct ibv_spec_header *hdr; + int i; + + /* Update Verbs specification. */ + hdr = (struct ibv_spec_header *)flow->verbs.specs; + for (i = 0; i != flow->verbs.attr->num_of_specs; ++i) { + if (hdr->type == IBV_FLOW_SPEC_ACTION_TAG) { + struct ibv_flow_spec_action_tag *t = + (struct ibv_flow_spec_action_tag *)hdr; + + t->tag_id = mlx5_flow_mark_set(mark_id); + } + hdr = (struct ibv_spec_header *)((uintptr_t)hdr + hdr->size); + } +} + +/** + * Validate action mark provided by the user. + * + * @param actions + * Pointer to flow actions array. + * @param flow + * Pointer to the rte_flow structure. + * @param flow_size[in] + * Size in bytes of the available space for to store the flow information. + * @param error + * Pointer to error structure. + * + * @return + * size in bytes necessary for the conversion, a negative errno value + * otherwise and rte_errno is set. + */ +static int +mlx5_flow_action_mark(const struct rte_flow_action *actions, + struct rte_flow *flow, const size_t flow_size, + struct rte_flow_error *error) +{ + const struct rte_flow_action_mark *mark = actions->conf; + unsigned int size = sizeof(struct ibv_flow_spec_action_tag); + struct ibv_flow_spec_action_tag tag = { + .type = IBV_FLOW_SPEC_ACTION_TAG, + .size = size, + }; + + if (!mark) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "configuration cannot be null"); + if (mark->id >= MLX5_FLOW_MARK_MAX) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, + &mark->id, + "mark must be between 0 and" + " 16777199"); + if (flow->modifier & MLX5_FLOW_MOD_MARK) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "mark action already present"); + if (flow->fate & MLX5_FLOW_FATE_DROP) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "mark is not compatible with drop" + " action"); + if (flow->modifier & MLX5_FLOW_MOD_FLAG) { + mlx5_flow_verbs_mark_update(flow, mark->id); + size = 0; /**< Only an update is done in the specification. */ + } else { + tag.tag_id = mlx5_flow_mark_set(mark->id); + if (size <= flow_size) { + tag.tag_id = mlx5_flow_mark_set(mark->id); + mlx5_flow_spec_verbs_add(flow, &tag, size); + } + } + flow->modifier |= MLX5_FLOW_MOD_MARK; + return size; +} + /** * Validate actions provided by the user. * @@ -1039,6 +1189,14 @@ mlx5_flow_actions(struct rte_eth_dev *dev, switch (actions->type) { case RTE_FLOW_ACTION_TYPE_VOID: break; + case RTE_FLOW_ACTION_TYPE_FLAG: + ret = mlx5_flow_action_flag(actions, flow, remain, + error); + break; + case RTE_FLOW_ACTION_TYPE_MARK: + ret = mlx5_flow_action_mark(actions, flow, remain, + error); + break; case RTE_FLOW_ACTION_TYPE_DROP: ret = mlx5_flow_action_drop(actions, flow, remain, error); @@ -1122,6 +1280,23 @@ mlx5_flow_merge(struct rte_eth_dev *dev, struct rte_flow *flow, return size; } +/** + * Mark the Rx queues mark flag if the flow has a mark or flag modifier. + * + * @param dev + * Pointer to Ethernet device. + * @param flow + * Pointer to flow structure. + */ +static void +mlx5_flow_rxq_mark(struct rte_eth_dev *dev, struct rte_flow *flow) +{ + struct priv *priv = dev->data->dev_private; + + (*priv->rxqs)[flow->queue]->mark |= + flow->modifier & (MLX5_FLOW_MOD_FLAG | MLX5_FLOW_MOD_MARK); +} + /** * Validate a flow supported by the NIC. * @@ -1281,6 +1456,7 @@ mlx5_flow_list_create(struct rte_eth_dev *dev, if (ret < 0) goto error; } + mlx5_flow_rxq_mark(dev, flow); TAILQ_INSERT_TAIL(list, flow, next); return flow; error: @@ -1323,8 +1499,31 @@ static void mlx5_flow_list_destroy(struct rte_eth_dev *dev, struct mlx5_flows *list, struct rte_flow *flow) { + struct priv *priv = dev->data->dev_private; + struct rte_flow *rflow; + const uint32_t mask = MLX5_FLOW_MOD_FLAG & MLX5_FLOW_MOD_MARK; + int mark = 0; + mlx5_flow_fate_remove(dev, flow); TAILQ_REMOVE(list, flow, next); + if (!(flow->modifier & mask)) { + rte_free(flow); + return; + } + /* + * When a flow is removed and this flow has a flag/mark modifier, all + * flows needs to be parse to verify if the Rx queue use by the flow + * still need to track the flag/mark request. + */ + TAILQ_FOREACH(rflow, &priv->flows, next) { + if (!(rflow->modifier & mask)) + continue; + if (flow->queue == rflow->queue) { + mark = 1; + break; + } + } + (*priv->rxqs)[flow->queue]->mark = !!mark; rte_free(flow); } @@ -1358,10 +1557,19 @@ mlx5_flow_list_flush(struct rte_eth_dev *dev, struct mlx5_flows *list) void mlx5_flow_stop(struct rte_eth_dev *dev, struct mlx5_flows *list) { + struct priv *priv = dev->data->dev_private; struct rte_flow *flow; + unsigned int i; + unsigned int idx; TAILQ_FOREACH_REVERSE(flow, list, mlx5_flows, next) mlx5_flow_fate_remove(dev, flow); + for (idx = 0, i = 0; idx != priv->rxqs_n; ++i) { + if (!(*priv->rxqs)[idx]) + continue; + (*priv->rxqs)[idx]->mark = 0; + ++idx; + } } /** @@ -1386,6 +1594,7 @@ mlx5_flow_start(struct rte_eth_dev *dev, struct mlx5_flows *list) ret = mlx5_flow_fate_apply(dev, flow, &error); if (ret < 0) goto error; + mlx5_flow_rxq_mark(dev, flow); } return 0; error: