From patchwork Thu Dec 29 15:15:21 2016 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: 18672 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id DB353F60E; Thu, 29 Dec 2016 16:16:45 +0100 (CET) Received: from mail-wm0-f54.google.com (mail-wm0-f54.google.com [74.125.82.54]) by dpdk.org (Postfix) with ESMTP id DB58B37A8 for ; Thu, 29 Dec 2016 16:15:43 +0100 (CET) Received: by mail-wm0-f54.google.com with SMTP id t79so335230143wmt.0 for ; Thu, 29 Dec 2016 07:15:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=w2/aRv8DtC4Pc+bTbP67UPIpYvgMbRCtmmYNbq64mvA=; b=Pvyoeyh/G4x7ObssbVuyIHgi7/LJeAIWnFSFn+6sfSHfQraEpBjmaLLIlLJBNiJ7ve 9fCkD0yLqmKRa1SvAg85aTUh/gHVMfG9v3dT+P5GHaSkskBvL7kbKfS+5rULv9U/0hwM XGK9mWhc6OctLVwFbwu3xh0X1/7plj3DxYgSPZJ5/DDicRcRt0yafficnlHd2pq1OdUr lvc3A0vuc0KSnEhscVhEofwiS/QESOARW5CyQNkOp3oS5mXltOn0rWv7h0cHBFXNS0mD E3bpB81s6MQHJheBQjCc35rwE0//7VE0oYpYsgJxwbuUolQHTcag7ORUEVFUEBOkZONT QeOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=w2/aRv8DtC4Pc+bTbP67UPIpYvgMbRCtmmYNbq64mvA=; b=UetLmb1D/3S904DsdiQIYGWFNgY4QW3v4GLYoCjzGqIyd/v3PEjscvs6nLNdUg5LVX 924hlRhTO+uUPHPOZ8YdOMPYBaaye1LPEJMFKds1ZKHCtfe4jDbLmUwS7ekp5731RQR2 dHljxYrED1q/nqPSSowuWE103kYCNidgxQM+NqIrySV3mc53O7yeRSeoWmPl4mqr0+8y xX/VVoOqff3fXqdVBs3uXUdS89jOeOIE+6Mrj0jLWjB93qWyMaSk3sCwFno9DBJYOb/p Jp1fQ2xmVCDbTa5TwpMfh8ZKL1QbL8YW882QYU8IPNSNkBBatol7U8vPpNvUtqCqBRex 42Bw== X-Gm-Message-State: AIkVDXK8Vau+ygzWWlY15tqlFPAXwQn6s4Ann6JThl51XxQHYroMnF2YMVr4yTSC0xaSlWyh X-Received: by 10.28.15.5 with SMTP id 5mr40939540wmp.141.1483024543435; Thu, 29 Dec 2016 07:15:43 -0800 (PST) Received: from ping.vm.6wind.com (guy78-3-82-239-227-177.fbx.proxad.net. [82.239.227.177]) by smtp.gmail.com with ESMTPSA id o3sm69289997wjx.39.2016.12.29.07.15.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 29 Dec 2016 07:15:42 -0800 (PST) From: Nelio Laranjeiro To: dev@dpdk.org, Ferruh Yigit Cc: Adrien Mazarguil Date: Thu, 29 Dec 2016 16:15:21 +0100 Message-Id: <1f211f8b421dd165165fb1c419304f1c14705169.1483022600.git.nelio.laranjeiro@6wind.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH v5 5/6] net/mlx5: support mark 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 Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 78 ++++++++++++++++++++++++++++++++++++++++++++ drivers/net/mlx5/mlx5_prm.h | 70 ++++++++++++++++++++++++++++++++++++++- drivers/net/mlx5/mlx5_rxtx.c | 12 ++++++- drivers/net/mlx5/mlx5_rxtx.h | 3 +- 4 files changed, 160 insertions(+), 3 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 093c140..0e7ea99 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -50,6 +50,7 @@ #include #include "mlx5.h" +#include "mlx5_prm.h" static int mlx5_flow_create_eth(const struct rte_flow_item *item, @@ -95,6 +96,7 @@ struct rte_flow { struct ibv_exp_wq *wq; /**< Verbs work queue. */ struct ibv_cq *cq; /**< Verbs completion queue. */ struct rxq *rxq; /**< Pointer to the queue, NULL if drop queue. */ + uint32_t mark:1; /**< Set if the flow is marked. */ }; /** Static initializer for items. */ @@ -137,6 +139,7 @@ struct mlx5_flow_items { static const enum rte_flow_action_type valid_actions[] = { RTE_FLOW_ACTION_TYPE_DROP, RTE_FLOW_ACTION_TYPE_QUEUE, + RTE_FLOW_ACTION_TYPE_MARK, RTE_FLOW_ACTION_TYPE_END, }; @@ -255,7 +258,9 @@ struct mlx5_flow { struct mlx5_flow_action { uint32_t queue:1; /**< Target is a receive queue. */ uint32_t drop:1; /**< Target is a drop queue. */ + uint32_t mark:1; /**< Mark is present in the flow. */ uint32_t queue_id; /**< Identifier of the queue. */ + uint32_t mark_id; /**< Mark identifier. */ }; /** @@ -352,6 +357,7 @@ priv_flow_validate(struct priv *priv, struct mlx5_flow_action action = { .queue = 0, .drop = 0, + .mark = 0, }; (void)priv; @@ -438,10 +444,26 @@ priv_flow_validate(struct priv *priv, if (!queue || (queue->index > (priv->rxqs_n - 1))) goto exit_action_not_supported; action.queue = 1; + } else if (actions->type == RTE_FLOW_ACTION_TYPE_MARK) { + const struct rte_flow_action_mark *mark = + (const struct rte_flow_action_mark *) + actions->conf; + + if (mark && (mark->id >= MLX5_FLOW_MARK_MAX)) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "mark must be between 0" + " and 16777199"); + return -rte_errno; + } + action.mark = 1; } else { goto exit_action_not_supported; } } + if (action.mark && !flow->ibv_attr) + flow->offset += sizeof(struct ibv_exp_flow_spec_action_tag); if (!action.queue && !action.drop) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "no valid action"); @@ -785,6 +807,30 @@ mlx5_flow_create_vxlan(const struct rte_flow_item *item, } /** + * Convert mark/flag action to Verbs specification. + * + * @param flow + * Pointer to MLX5 flow structure. + * @param mark_id + * Mark identifier. + */ +static int +mlx5_flow_create_flag_mark(struct mlx5_flow *flow, uint32_t mark_id) +{ + struct ibv_exp_flow_spec_action_tag *tag; + unsigned int size = sizeof(struct ibv_exp_flow_spec_action_tag); + + tag = (void *)((uintptr_t)flow->ibv_attr + flow->offset); + *tag = (struct ibv_exp_flow_spec_action_tag){ + .type = IBV_EXP_FLOW_SPEC_ACTION_TAG, + .size = size, + .tag_id = mlx5_flow_mark_set(mark_id), + }; + ++flow->ibv_attr->num_of_specs; + return 0; +} + +/** * Complete flow rule creation. * * @param priv @@ -840,8 +886,10 @@ priv_flow_create_action_queue(struct priv *priv, rxq = container_of((*priv->rxqs)[action->queue_id], struct rxq_ctrl, rxq); rte_flow->rxq = &rxq->rxq; + rxq->rxq.mark |= action->mark; rte_flow->wq = rxq->wq; } + rte_flow->mark = action->mark; rte_flow->ibv_attr = ibv_attr; rte_flow->ind_table = ibv_exp_create_rwq_ind_table( priv->ctx, @@ -957,6 +1005,8 @@ priv_flow_create(struct priv *priv, action = (struct mlx5_flow_action){ .queue = 0, .drop = 0, + .mark = 0, + .mark_id = MLX5_FLOW_MARK_DEFAULT, }; for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) { if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) { @@ -968,6 +1018,14 @@ priv_flow_create(struct priv *priv, actions->conf)->index; } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) { action.drop = 1; + } else if (actions->type == RTE_FLOW_ACTION_TYPE_MARK) { + const struct rte_flow_action_mark *mark = + (const struct rte_flow_action_mark *) + actions->conf; + + if (mark) + action.mark_id = mark->id; + action.mark = 1; } else { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, @@ -975,6 +1033,10 @@ priv_flow_create(struct priv *priv, goto exit; } } + if (action.mark) { + mlx5_flow_create_flag_mark(&flow, action.mark_id); + flow.offset += sizeof(struct ibv_exp_flow_spec_action_tag); + } rte_flow = priv_flow_create_action_queue(priv, flow.ibv_attr, &action, error); return rte_flow; @@ -1033,6 +1095,18 @@ priv_flow_destroy(struct priv *priv, claim_zero(ibv_exp_destroy_wq(flow->wq)); if (!flow->rxq && flow->cq) claim_zero(ibv_destroy_cq(flow->cq)); + if (flow->mark) { + struct rte_flow *tmp; + uint32_t mark_n = 0; + + for (tmp = LIST_FIRST(&priv->flows); + tmp; + tmp = LIST_NEXT(tmp, next)) { + if ((flow->rxq == tmp->rxq) && tmp->mark) + ++mark_n; + } + flow->rxq->mark = !!mark_n; + } rte_free(flow->ibv_attr); DEBUG("Flow destroyed %p", (void *)flow); rte_free(flow); @@ -1112,6 +1186,8 @@ priv_flow_stop(struct priv *priv) flow = LIST_NEXT(flow, next)) { claim_zero(ibv_exp_destroy_flow(flow->ibv_flow)); flow->ibv_flow = NULL; + if (flow->mark) + flow->rxq->mark = 0; DEBUG("Flow %p removed", (void *)flow); } } @@ -1141,6 +1217,8 @@ priv_flow_start(struct priv *priv) return rte_errno; } DEBUG("Flow %p applied", (void *)flow); + if (flow->rxq) + flow->rxq->mark |= flow->mark; } return 0; } diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h index 9cd9fdf..d9bb332 100644 --- a/drivers/net/mlx5/mlx5_prm.h +++ b/drivers/net/mlx5/mlx5_prm.h @@ -34,6 +34,8 @@ #ifndef RTE_PMD_MLX5_PRM_H_ #define RTE_PMD_MLX5_PRM_H_ +#include + /* Verbs header. */ /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ #ifdef PEDANTIC @@ -106,6 +108,15 @@ /* Outer UDP header and checksum OK. */ #define MLX5_CQE_RX_OUTER_TCP_UDP_CSUM_OK (1u << 6) +/* INVALID is used by packets matching no flow rules. */ +#define MLX5_FLOW_MARK_INVALID 0 + +/* Maximum allowed value to mark a packet. */ +#define MLX5_FLOW_MARK_MAX 0xfffff0 + +/* Default mark value used when none is provided. */ +#define MLX5_FLOW_MARK_DEFAULT 0xffffff + /* Subset of struct mlx5_wqe_eth_seg. */ struct mlx5_wqe_eth_seg_small { uint32_t rsvd0; @@ -183,10 +194,67 @@ struct mlx5_cqe { uint8_t rsvd2[12]; uint32_t byte_cnt; uint64_t timestamp; - uint8_t rsvd3[4]; + uint32_t sop_drop_qpn; uint16_t wqe_counter; uint8_t rsvd4; uint8_t op_own; }; +/** + * Convert a user mark to flow mark. + * + * @param val + * Mark value to convert. + * + * @return + * Converted mark value. + */ +static inline uint32_t +mlx5_flow_mark_set(uint32_t val) +{ + uint32_t ret; + + /* + * Add one to the user value to differentiate un-marked flows from + * marked flows. + */ + ++val; +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + /* + * Mark is 24 bits (minus reserved values) but is stored on a 32 bit + * word, byte-swapped by the kernel on little-endian systems. In this + * case, left-shifting the resulting big-endian value ensures the + * least significant 24 bits are retained when converting it back. + */ + ret = rte_cpu_to_be_32(val) >> 8; +#else + ret = val; +#endif + assert(ret <= MLX5_FLOW_MARK_MAX); + return ret; +} + +/** + * Convert a mark to user mark. + * + * @param val + * Mark value to convert. + * + * @return + * Converted mark value. + */ +static inline uint32_t +mlx5_flow_mark_get(uint32_t val) +{ + /* + * Subtract one from the retrieved value. It was added by + * mlx5_flow_mark_set() to distinguish unmarked flows. + */ +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + return (val >> 8) - 1; +#else + return val - 1; +#endif +} + #endif /* RTE_PMD_MLX5_PRM_H_ */ diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index 6f86ded..8f0b4a6 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -113,7 +113,7 @@ static inline int check_cqe_seen(volatile struct mlx5_cqe *cqe) { static const uint8_t magic[] = "seen"; - volatile uint8_t (*buf)[sizeof(cqe->rsvd3)] = &cqe->rsvd3; + volatile uint8_t (*buf)[sizeof(cqe->rsvd0)] = &cqe->rsvd0; int ret = 1; unsigned int i; @@ -1357,6 +1357,16 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) pkt->hash.rss = rss_hash_res; pkt->ol_flags = PKT_RX_RSS_HASH; } + if (rxq->mark && + ((cqe->sop_drop_qpn != + htonl(MLX5_FLOW_MARK_INVALID)) || + (cqe->sop_drop_qpn != + htonl(MLX5_FLOW_MARK_DEFAULT)))) { + pkt->hash.fdir.hi = + mlx5_flow_mark_get(cqe->sop_drop_qpn); + pkt->ol_flags &= ~PKT_RX_RSS_HASH; + pkt->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID; + } if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip | rxq->crc_present) { if (rxq->csum) { diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h index e244c48..302ca49 100644 --- a/drivers/net/mlx5/mlx5_rxtx.h +++ b/drivers/net/mlx5/mlx5_rxtx.h @@ -114,7 +114,8 @@ struct rxq { unsigned int elts_n:4; /* Log 2 of Mbufs. */ unsigned int port_id:8; unsigned int rss_hash:1; /* RSS hash result is enabled. */ - unsigned int :9; /* Remaining bits. */ + unsigned int mark:1; /* Marked flow available on the queue. */ + unsigned int :8; /* Remaining bits. */ volatile uint32_t *rq_db; volatile uint32_t *cq_db; uint16_t rq_ci;