[dpdk-dev] [PATCH] net/mlx5: fix 32bits compilation issue
Fixes: 02bb06aca20f ("net/mlx5: use vector types to speed up processing") Reported-by: Thomas Monjalon Signed-off-by: Nelio Laranjeiro --- Please squash it in the original patch if possible. --- drivers/net/mlx5/mlx5_rxtx.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index 8cf68c5..0177428 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -390,6 +390,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) uint32_t length; unsigned int ds = 0; uintptr_t addr; + uint64_t naddr; uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE; uint8_t ehdr[2]; uint8_t cs_flags = 0; @@ -515,12 +516,12 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) ds = 3; use_dseg: /* Add the remaining packet as a simple ds. */ - addr = htonll(addr); + naddr = htonll(addr); *dseg = (rte_v128u32_t){ htonl(length), txq_mp2mr(txq, txq_mb2mp(buf)), - addr, - addr >> 32, + naddr, + naddr >> 32, }; ++ds; if (!segs_n) @@ -554,12 +555,12 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) total_length += length; #endif /* Store segment information. */ - addr = htonll(rte_pktmbuf_mtod(buf, uintptr_t)); + naddr = htonll(rte_pktmbuf_mtod(buf, uintptr_t)); *dseg = (rte_v128u32_t){ htonl(length), txq_mp2mr(txq, txq_mb2mp(buf)), - addr, - addr >> 32, + naddr, + naddr >> 32, }; (*txq->elts)[elts_head] = buf; elts_head = (elts_head + 1) & (elts_n - 1); -- 2.1.4
[dpdk-dev] [PATCH 2/2] net/mlx5: fix Rx packet validation and type
Rx checksum validation and packet type offloads are read from the wrong location. Fixes: 501505c5608a ("net/mlx: fix IPv4 and IPv6 packet type") Fixes: 350f4c482e46 ("net/mlx5: fix Rx checksum macros") Fixes: 6218063b39a6 ("net/mlx5: refactor Rx data path") Cc: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_prm.h | 47 + drivers/net/mlx5/mlx5_rxtx.c | 50 +++- 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h index d9bb332..755b5d7 100644 --- a/drivers/net/mlx5/mlx5_prm.h +++ b/drivers/net/mlx5/mlx5_prm.h @@ -64,9 +64,6 @@ /* Invalidate a CQE. */ #define MLX5_CQE_INVALIDATE (MLX5_CQE_INVALID << 4) -/* CQE value to inform that VLAN is stripped. */ -#define MLX5_CQE_VLAN_STRIPPED 0x1 - /* Maximum number of packets a multi-packet WQE can handle. */ #define MLX5_MPW_DSEG_MAX 5 @@ -87,26 +84,41 @@ #define MLX5_OPCODE_TSO MLX5_OPCODE_LSO_MPW /* Compat with OFED 3.3. */ #endif -/* IPv4 packet. */ -#define MLX5_CQE_RX_IPV4_PACKET (1u << 2) +/* CQE value to inform that VLAN is stripped. */ +#define MLX5_CQE_VLAN_STRIPPED (1u << 0) + +/* IPv4 options. */ +#define MLX5_CQE_RX_IP_EXT_OPTS_PACKET (1u << 1) /* IPv6 packet. */ -#define MLX5_CQE_RX_IPV6_PACKET (1u << 3) +#define MLX5_CQE_RX_IPV6_PACKET (1u << 2) + +/* IPv4 packet. */ +#define MLX5_CQE_RX_IPV4_PACKET (1u << 3) -/* Outer IPv4 packet. */ -#define MLX5_CQE_RX_OUTER_IPV4_PACKET (1u << 7) +/* TCP packet. */ +#define MLX5_CQE_RX_TCP_PACKET (1u << 4) -/* Outer IPv6 packet. */ -#define MLX5_CQE_RX_OUTER_IPV6_PACKET (1u << 8) +/* UDP packet. */ +#define MLX5_CQE_RX_UDP_PACKET (1u << 5) -/* Tunnel packet bit in the CQE. */ -#define MLX5_CQE_RX_TUNNEL_PACKET (1u << 4) +/* IP is fragmented. */ +#define MLX5_CQE_RX_IP_FRAG_PACKET (1u << 7) + +/* L2 header is valid. */ +#define MLX5_CQE_RX_L2_HDR_VALID (1u << 8) -/* Outer IP checksum OK. */ -#define MLX5_CQE_RX_OUTER_IP_CSUM_OK (1u << 5) +/* L3 header is valid. */ +#define MLX5_CQE_RX_L3_HDR_VALID (1u << 9) -/* Outer UDP header and checksum OK. */ -#define MLX5_CQE_RX_OUTER_TCP_UDP_CSUM_OK (1u << 6) +/* L4 header is valid. */ +#define MLX5_CQE_RX_L4_HDR_VALID (1u << 10) + +/* Outer packet, 0 IPv4, 1 IPv6. */ +#define MLX5_CQE_RX_OUTER_PACKET (1u << 1) + +/* Tunnel packet bit in the CQE. */ +#define MLX5_CQE_RX_TUNNEL_PACKET (1u << 0) /* INVALID is used by packets matching no flow rules. */ #define MLX5_FLOW_MARK_INVALID 0 @@ -188,8 +200,7 @@ struct mlx5_cqe { uint32_t rx_hash_res; uint8_t rx_hash_type; uint8_t rsvd1[11]; - uint8_t hds_ip_ext; - uint8_t l4_hdr_type_etc; + uint16_t hdr_type_etc; uint16_t vlan_info; uint8_t rsvd2[12]; uint32_t byte_cnt; diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index 56c7f78..f88b3eb 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -1107,23 +1107,20 @@ static inline uint32_t rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe) { uint32_t pkt_type; - uint8_t flags = cqe->l4_hdr_type_etc; + uint16_t flags = ntohs(cqe->hdr_type_etc); - if (cqe->pkt_info & MLX5_CQE_RX_TUNNEL_PACKET) + if (cqe->pkt_info & MLX5_CQE_RX_TUNNEL_PACKET) { pkt_type = TRANSPOSE(flags, - MLX5_CQE_RX_OUTER_IPV4_PACKET, - RTE_PTYPE_L3_IPV4_EXT_UNKNOWN) | - TRANSPOSE(flags, - MLX5_CQE_RX_OUTER_IPV6_PACKET, - RTE_PTYPE_L3_IPV6_EXT_UNKNOWN) | - TRANSPOSE(flags, MLX5_CQE_RX_IPV4_PACKET, RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN) | TRANSPOSE(flags, MLX5_CQE_RX_IPV6_PACKET, RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN); - else + pkt_type |= ((cqe->pkt_info & MLX5_CQE_RX_OUTER_PACKET) ? +RTE_PTYPE_L3_IPV6_EXT_UNKNOWN : +RTE_PTYPE_L3_IPV4_EXT_UNKNOWN); + } else { pkt_type = TRANSPOSE(flags, MLX5_CQE_L3_HDR_TYPE_IPV6, @@ -1131,6 +1128,7 @@ rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe) TRANSPOSE(flags, MLX5_CQE_L3_HDR_TYPE_IPV4, RTE_PTYPE_L3_IPV4_EXT_UNKNOWN); + } return pkt_type; } @@ -1248,28 +1246,22 @@ static inline uint32_t rxq_cq_to_ol_flags(struct rxq
[dpdk-dev] [PATCH 1/2] net/mlx5: fix flow API mark combined with drop
Fixes: ea3bc3b1df94 ("net/mlx5: support mark flow action") Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index d7ed686..7b97a61 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -480,7 +480,7 @@ priv_flow_validate(struct priv *priv, goto exit_action_not_supported; } } - if (action.mark && !flow->ibv_attr) + if (action.mark && !flow->ibv_attr && !action.drop) 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, @@ -1042,6 +1042,7 @@ priv_flow_create(struct priv *priv, actions->conf)->index; } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) { action.drop = 1; + action.mark = 0; } else if (actions->type == RTE_FLOW_ACTION_TYPE_MARK) { const struct rte_flow_action_mark *mark = (const struct rte_flow_action_mark *) @@ -1049,7 +1050,7 @@ priv_flow_create(struct priv *priv, if (mark) action.mark_id = mark->id; - action.mark = 1; + action.mark = !action.drop; } else { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, -- 2.1.4
[dpdk-dev] [PATCH 1/2] net/mlx5: fix VLAN validation
TCI field is read from the wrong place due to an invalid cast. Moreover there is no need to limit matching to VID since PCP and DEI bits can be matched as well. Fixes: 12475fb203ad ("net/mlx5: support VLAN flow item") Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 11 --- 1 file changed, 11 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 7b97a61..d805c0a 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -410,17 +410,6 @@ priv_flow_validate(struct priv *priv, if (items->type == RTE_FLOW_ITEM_TYPE_VOID) continue; - /* Handle special situation for VLAN. */ - if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) { - if (((const struct rte_flow_item_vlan *)items)->tci > - ETHER_MAX_VLAN_ID) { - rte_flow_error_set(error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ITEM, - items, - "wrong VLAN id value"); - return -rte_errno; - } - } for (i = 0; cur_item->items && cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END; -- 2.1.4
[dpdk-dev] [PATCH 2/2] net/mlx5: fix validation
Size of the mask is wrongly computed and make the validation process only verify the first 4 bytes of the layer. Fixes: 2097d0d1e2cc ("net/mlx5: support basic flow items and actions") Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index d805c0a..42a12e8 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -424,7 +424,7 @@ priv_flow_validate(struct priv *priv, cur_item = token; err = mlx5_flow_item_validate(items, (const uint8_t *)cur_item->mask, - sizeof(cur_item->mask_sz)); + cur_item->mask_sz); if (err) goto exit_item_not_supported; if (flow->ibv_attr && cur_item->convert) { -- 2.1.4
[dpdk-dev] [PATCH 1/3] net/mlx5: use flow API default masks
Default masks were introduced in the API after its implementation in this PMD. Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 42a12e8..4917f79 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -164,6 +164,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", }, + .default_mask = &rte_flow_item_eth_mask, .mask_sz = sizeof(struct rte_flow_item_eth), .convert = mlx5_flow_create_eth, .dst_sz = sizeof(struct ibv_exp_flow_spec_eth), @@ -175,6 +176,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .mask = &(const struct rte_flow_item_vlan){ .tci = -1, }, + .default_mask = &rte_flow_item_vlan_mask, .mask_sz = sizeof(struct rte_flow_item_vlan), .convert = mlx5_flow_create_vlan, .dst_sz = 0, @@ -191,12 +193,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .next_proto_id = -1, }, }, - .default_mask = &(const struct rte_flow_item_ipv4){ - .hdr = { - .src_addr = -1, - .dst_addr = -1, - }, - }, + .default_mask = &rte_flow_item_ipv4_mask, .mask_sz = sizeof(struct rte_flow_item_ipv4), .convert = mlx5_flow_create_ipv4, .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv4_ext), @@ -221,6 +218,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { }, }, }, + .default_mask = &rte_flow_item_ipv6_mask, .mask_sz = sizeof(struct rte_flow_item_ipv6), .convert = mlx5_flow_create_ipv6, .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6), @@ -234,6 +232,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .dst_port = -1, }, }, + .default_mask = &rte_flow_item_udp_mask, .mask_sz = sizeof(struct rte_flow_item_udp), .convert = mlx5_flow_create_udp, .dst_sz = sizeof(struct ibv_exp_flow_spec_tcp_udp), @@ -246,6 +245,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .dst_port = -1, }, }, + .default_mask = &rte_flow_item_tcp_mask, .mask_sz = sizeof(struct rte_flow_item_tcp), .convert = mlx5_flow_create_tcp, .dst_sz = sizeof(struct ibv_exp_flow_spec_tcp_udp), @@ -256,6 +256,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .mask = &(const struct rte_flow_item_vxlan){ .vni = "\xff\xff\xff", }, + .default_mask = &rte_flow_item_vxlan_mask, .mask_sz = sizeof(struct rte_flow_item_vxlan), .convert = mlx5_flow_create_vxlan, .dst_sz = sizeof(struct ibv_exp_flow_spec_tunnel), -- 2.1.4
[dpdk-dev] [PATCH 3/3] net/mlx5: fix flow rule creation if ports are stopped
Adding a flow when the port is stopped ends in an inconsistent situation where the queue can receive traffic when it should not. Record new rules and apply them as soon as the port is started. Fixes: 2097d0d1e2cc ("net/mlx5: support basic flow items and actions") Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 34ac5d3..23c1b5e 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -948,6 +948,8 @@ priv_flow_create_action_queue(struct priv *priv, NULL, "cannot allocate QP"); goto error; } + if (!priv->started) + return rte_flow; rte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp, rte_flow->ibv_attr); if (!rte_flow->ibv_flow) { -- 2.1.4
[dpdk-dev] [PATCH 2/3] net/mlx5: fix verification of mark action
A configuration structure for the MARK action must always be specified. Fixes: ea3bc3b1df94 ("net/mlx5: support mark flow action") Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 4917f79..34ac5d3 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -457,7 +457,13 @@ priv_flow_validate(struct priv *priv, (const struct rte_flow_action_mark *) actions->conf; - if (mark && (mark->id >= MLX5_FLOW_MARK_MAX)) { + if (!mark) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "mark must be defined"); + return -rte_errno; + } else if (mark->id >= MLX5_FLOW_MARK_MAX) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions, -- 2.1.4
[dpdk-dev] [PATCH 1/3] net/mlx5: fix Ethernet header re-writing
First two bytes of the Ethernet header was written twice at the same place. Fixes: b8fe952ec5b6 ("net/mlx5: prepare Tx vectorization") Signed-off-by: Yongseok Koh Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_rxtx.c | 36 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index 94fe747..ffca21c 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -386,7 +386,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) unsigned int ds = 0; uintptr_t addr; uint64_t naddr; - uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE; + uint16_t pkt_inline_sz = MLX5_WQE_DWORD_SIZE + 2; uint16_t ehdr; uint8_t cs_flags = 0; #ifdef MLX5_PMD_SOFT_COUNTERS @@ -436,23 +436,27 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) cs_flags = MLX5_ETH_WQE_L3_CSUM | MLX5_ETH_WQE_L4_CSUM; } raw = ((uint8_t *)(uintptr_t)wqe) + 2 * MLX5_WQE_DWORD_SIZE; - /* -* Start by copying the Ethernet header minus the first two -* bytes which will be appended at the end of the Ethernet -* segment. -*/ - memcpy((uint8_t *)raw, ((uint8_t *)addr) + 2, 16); - length -= MLX5_WQE_DWORD_SIZE; - addr += MLX5_WQE_DWORD_SIZE; /* Replace the Ethernet type by the VLAN if necessary. */ if (buf->ol_flags & PKT_TX_VLAN_PKT) { uint32_t vlan = htonl(0x8100 | buf->vlan_tci); - - memcpy((uint8_t *)(raw + MLX5_WQE_DWORD_SIZE - 2 - - sizeof(vlan)), - &vlan, sizeof(vlan)); - addr -= sizeof(vlan); - length += sizeof(vlan); + unsigned int len = 2 * ETHER_ADDR_LEN - 2; + + addr += 2; + length -= 2; + /* Copy Destination and source mac address. */ + memcpy((uint8_t *)raw, ((uint8_t *)addr), len); + /* Copy VLAN. */ + memcpy((uint8_t *)raw + len, &vlan, sizeof(vlan)); + /* Copy missing two bytes to end the DSeg. */ + memcpy((uint8_t *)raw + len + sizeof(vlan), + ((uint8_t *)addr) + len, 2); + addr += len + 2; + length -= (len + 2); + } else { + memcpy((uint8_t *)raw, ((uint8_t *)addr) + 2, + MLX5_WQE_DWORD_SIZE); + length -= pkt_inline_sz; + addr += pkt_inline_sz; } /* Inline if enough room. */ if (txq->max_inline != 0) { @@ -467,7 +471,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) * raw starts two bytes before the boundary to * continue the above copy of packet data. */ - raw += MLX5_WQE_DWORD_SIZE - 2; + raw += MLX5_WQE_DWORD_SIZE; room = end - (uintptr_t)raw; if (room > max_inline) { uintptr_t addr_end = (addr + max_inline) & -- 2.1.4
[dpdk-dev] [PATCH 2/3] net/mlx5: fix Tx WQE corruption caused by starvation
Fixes an issue which may occurs with the inline feature activated and a packet greater than the max_inline requested. In such situation, more work request elements can be consumed and in the worst case override some still handled by the NIC, this can result in sending garbage on the network or putting the work queue in error. Fixes: 2a66cf378954 ("net/mlx5: support inline send") Cc: sta...@dpdk.org Reported-by: Elad Persiko Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_rxtx.c | 91 +--- drivers/net/mlx5/mlx5_rxtx.h | 1 + 2 files changed, 78 insertions(+), 14 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index ffca21c..a0e15ac 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -238,8 +238,9 @@ txq_complete(struct txq *txq) } while (1); if (unlikely(cqe == NULL)) return; + txq->wqe_pi = ntohs(cqe->wqe_counter); ctrl = (volatile struct mlx5_wqe_ctrl *) - tx_mlx5_wqe(txq, ntohs(cqe->wqe_counter)); + tx_mlx5_wqe(txq, txq->wqe_pi); elts_tail = ctrl->ctrl3; assert(elts_tail < (1 << txq->wqe_n)); /* Free buffers. */ @@ -365,6 +366,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) unsigned int i = 0; unsigned int j = 0; unsigned int max; + uint16_t max_wqe; unsigned int comp; volatile struct mlx5_wqe_v *wqe = NULL; unsigned int segs_n = 0; @@ -380,6 +382,9 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) max = (elts_n - (elts_head - txq->elts_tail)); if (max > elts_n) max -= elts_n; + max_wqe = (1u << txq->wqe_n) - (txq->wqe_ci - txq->wqe_pi); + if (unlikely(!max_wqe)) + return 0; do { volatile rte_v128u32_t *dseg = NULL; uint32_t length; @@ -407,6 +412,8 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) --segs_n; if (!segs_n) --pkts_n; + if (unlikely(--max_wqe == 0)) + break; wqe = (volatile struct mlx5_wqe_v *) tx_mlx5_wqe(txq, txq->wqe_ci); rte_prefetch0(tx_mlx5_wqe(txq, txq->wqe_ci + 1)); @@ -476,10 +483,19 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) if (room > max_inline) { uintptr_t addr_end = (addr + max_inline) & ~(RTE_CACHE_LINE_SIZE - 1); - uint16_t copy_b = ((addr_end - addr) > length) ? - length : - (addr_end - addr); + unsigned int copy_b = + RTE_MIN((addr_end - addr), length); + uint16_t n; + /* +* One Dseg remains in the current WQE. To +* keep the computation positive, it is +* removed after the bytes to Dseg conversion. +*/ + n = (MLX5_WQE_DS(copy_b) - 1 + 3) / 4; + if (unlikely(max_wqe < n)) + break; + max_wqe -= n; rte_memcpy((void *)raw, (void *)addr, copy_b); addr += copy_b; length -= copy_b; @@ -493,12 +509,18 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) */ ds = 2 + MLX5_WQE_DS(pkt_inline_sz - 2); if (length > 0) { - dseg = (volatile rte_v128u32_t *) - ((uintptr_t)wqe + -(ds * MLX5_WQE_DWORD_SIZE)); - if ((uintptr_t)dseg >= end) + if (ds % (MLX5_WQE_SIZE / + MLX5_WQE_DWORD_SIZE) == 0) { + if (unlikely(--max_wqe == 0)) + break; + dseg = (volatile rte_v128u32_t *) + tx_mlx5_wqe(txq, txq->wqe_ci + + ds / 4); + } else { dseg
[dpdk-dev] [PATCH 3/3] net/mlx5: fix inline WQE consumption
For some sizes of packets, the number of bytes copied in the work queue element could be greater than the available size of the inline. In such situation it could consumed one more work queue element where it should not. Fixes: 0e8679fcddc4 ("net/mlx5: fix inline logic") Cc: sta...@dpdk.org Reported-by: Elad Persiko Signed-off-by: Yongseok Koh Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_rxtx.c | 31 --- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index a0e15ac..40f2c47 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -466,33 +466,28 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) addr += pkt_inline_sz; } /* Inline if enough room. */ - if (txq->max_inline != 0) { + if (txq->max_inline) { uintptr_t end = (uintptr_t) (((uintptr_t)txq->wqes) + (1 << txq->wqe_n) * MLX5_WQE_SIZE); - uint16_t max_inline = - txq->max_inline * RTE_CACHE_LINE_SIZE; - uint16_t room; + unsigned int max_inline = txq->max_inline * + RTE_CACHE_LINE_SIZE - + MLX5_WQE_DWORD_SIZE; + uintptr_t addr_end = (addr + max_inline) & +~(RTE_CACHE_LINE_SIZE - 1); + unsigned int copy_b = (addr_end > addr) ? + RTE_MIN((addr_end - addr), length) : + 0; - /* -* raw starts two bytes before the boundary to -* continue the above copy of packet data. -*/ raw += MLX5_WQE_DWORD_SIZE; - room = end - (uintptr_t)raw; - if (room > max_inline) { - uintptr_t addr_end = (addr + max_inline) & - ~(RTE_CACHE_LINE_SIZE - 1); - unsigned int copy_b = - RTE_MIN((addr_end - addr), length); - uint16_t n; - + if (copy_b && ((end - (uintptr_t)raw) > copy_b)) { /* * One Dseg remains in the current WQE. To * keep the computation positive, it is * removed after the bytes to Dseg conversion. */ - n = (MLX5_WQE_DS(copy_b) - 1 + 3) / 4; + uint16_t n = (MLX5_WQE_DS(copy_b) - 1 + 3) / 4; + if (unlikely(max_wqe < n)) break; max_wqe -= n; @@ -500,8 +495,6 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) addr += copy_b; length -= copy_b; pkt_inline_sz += copy_b; - /* Sanity check. */ - assert(addr <= addr_end); } /* * 2 DWORDs consumed by the WQE header + ETH segment + -- 2.1.4
[dpdk-dev] [PATCH] doc: add flow API to features list
Signed-off-by: Nelio Laranjeiro --- doc/guides/nics/features/default.ini | 1 + doc/guides/nics/features/mlx5.ini| 1 + doc/guides/nics/mlx5.rst | 1 + 3 files changed, 3 insertions(+) diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini index 6e4a043..9e363ff 100644 --- a/doc/guides/nics/features/default.ini +++ b/doc/guides/nics/features/default.ini @@ -36,6 +36,7 @@ Flexible filter = Hash filter = Flow director= Flow control = +Flow API = Rate limitation = Traffic mirroring= CRC offload = diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini index f811e3f..f20d214 100644 --- a/doc/guides/nics/features/mlx5.ini +++ b/doc/guides/nics/features/mlx5.ini @@ -21,6 +21,7 @@ RSS reta update = Y SR-IOV = Y VLAN filter = Y Flow director= Y +Flow API = Y CRC offload = Y VLAN offload = Y L3 checksum offload = Y diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index a41c432..571a926 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -86,6 +86,7 @@ Features - Hardware checksum offloads. - Flow director (RTE_FDIR_MODE_PERFECT, RTE_FDIR_MODE_PERFECT_MAC_VLAN and RTE_ETH_FDIR_REJECT). +- Flow API. - Secondary process TX is supported. - KVM and VMware ESX SR-IOV modes are supported. - RSS hash result is supported. -- 2.1.4
[dpdk-dev] [PATCH 0/3] doc: update release notes
Biggest change is in the first patch to provide a better visibility for users on which NIC has been tested on which platform. Others two are just updates for Mellanox PMDs. Nelio Laranjeiro (3): doc: merge release notes sections doc: update release notes for mlx4 doc: update release notes for mlx5 doc/guides/nics/mlx4.rst | 9 +- doc/guides/nics/mlx5.rst | 37 - doc/guides/rel_notes/release_17_02.rst | 295 + 3 files changed, 301 insertions(+), 40 deletions(-) -- 2.1.4
[dpdk-dev] [PATCH 1/3] doc: merge release notes sections
These sections do not provide the exact tests that were done nor whether specific NICs are supported by all platforms. Signed-off-by: Nelio Laranjeiro --- doc/guides/rel_notes/release_17_02.rst | 60 +- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 83519dc..f662b50 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -373,52 +373,52 @@ The libraries prepended with a plus sign were incremented in this version. Tested Platforms -.. This section should contain a list of platforms that were tested with this release. +.. This section should contain a list of systems (properties, NIC, OS) that were tested with this release. The format is: - #. Platform name. + #. (Intel, IBM, ARM,...) platform with NICs. * Platform details. - * Platform details. - This section is a comment. do not overwrite or remove it. - Also, make sure to start the actual text at the margin. - = +* Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz +* Intel(R) Xeon(R) CPU E5-2697 v3 @ 2.70GHz +* Intel(R) Xeon(R) CPU E5-2699 v3 @ 2.30GHz + * Intel(R) Server board S2600WTT + * BIOS: SE5C610.86B.01.01.0005.101720141054 -Tested NICs +* ... -.. This section should contain a list of NICs that were tested with this release. +* OS - The format is: + * CentOS 7.0 + * Fedora 23 + * Fedora 24 + * FreeBSD 10.3 + * Red Hat Enterprise Linux 7.2 + * SUSE Enterprise Linux 12 + * Ubuntu 15.10 + * Ubuntu 16.04 LTS + * Wind River Linux 8 + * ... - #. NIC name. + * List of NICs - * NIC details. - * NIC details. +* Intel(R) Ethernet Controller X540-AT2 - This section is a comment. do not overwrite or remove it. - Also, make sure to start the actual text at the margin. - = + * Firmware version: 0x8389 + * Device id (pf): 8086:1528 + * Driver version: 3.23.2 (ixgbe) + * ... +* Intel(R) 82599ES 10 Gigabit Ethernet Controller -Tested OSes + * Firmware version: 0x61bf0001 + * Device id (pf/vf): 8086:10fb / 8086:10ed + * Driver version: 4.0.1-k (ixgbe) -.. This section should contain a list of OSes that were tested with this release. - The format is as follows, in alphabetical order: - - * CentOS 7.0 - * Fedora 23 - * Fedora 24 - * FreeBSD 10.3 - * Red Hat Enterprise Linux 7.2 - * SUSE Enterprise Linux 12 - * Ubuntu 15.10 - * Ubuntu 16.04 LTS - * Wind River Linux 8 +* ... This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. -- 2.1.4
[dpdk-dev] [PATCH 2/3] doc: update release notes for mlx4
Signed-off-by: Nelio Laranjeiro --- doc/guides/nics/mlx4.rst | 9 +++-- doc/guides/rel_notes/release_17_02.rst | 35 ++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/mlx4.rst b/doc/guides/nics/mlx4.rst index 49f4626..9a2e973 100644 --- a/doc/guides/nics/mlx4.rst +++ b/doc/guides/nics/mlx4.rst @@ -238,8 +238,8 @@ DPDK and must be installed separately: Currently supported by DPDK: -- Mellanox OFED **3.1**. -- Firmware version **2.35.5100** and higher. +- Mellanox OFED **4.0-1.0.1.0**. +- Firmware version **2.40.5030**. - Supported architectures: **x86_64** and **POWER8**. Getting Mellanox OFED @@ -262,6 +262,11 @@ required from that distribution. this DPDK release was developed and tested against is strongly recommended. Please check the `prerequisites`_. +Supported NICs +-- + +* Mellanox(R) ConnectX(R)-3 Pro 40G MCX354A-FCC_Ax (2*40G) + Usage example - diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index f662b50..d69dc4f 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -122,6 +122,10 @@ New Features A new network PMD which supports Solarflare SFN7xxx and SFN8xxx family of 10/40 Gbps adapters has been added. +* **Updated the mlx4 driver.** + + * Addressed a few bugs. + * **Added support for Mellanox ConnectX-5 adapters (mlx5).** Support for Mellanox ConnectX-5 family of 10/25/40/50/100 Gbps adapters @@ -423,3 +427,34 @@ Tested Platforms This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. = + +#. Intel(R) platforms with Mellanox(R) NICs. + + * Platform details. + + * Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz + * Intel(R) Xeon(R) CPU E5-2680 v2 @ 2.80GHz + * Intel(R) Xeon(R) CPU E5-2697 v3 @ 2.60GHz + + * OS: + + * CentOS 7.0 + * Fedora 23 + * Fedora 24 + * FreeBSD 10.3 + * Red Hat Enterprise Linux 7.2 + * SUSE Enterprise Linux 12 + * Ubuntu 14.04 LTS + * Ubuntu 15.10 + * Ubuntu 16.04 LTS + * Wind River Linux 8 + + * MLNX_OFED: 4.0-1.0.1.0 + + * NICs: + + * Mellanox(R) ConnectX(R)-3 Pro 40G MCX354A-FCC_Ax (2x40G) + + * Host interface: PCI Express 3.0 x8 + * Device ID: 15b3:1007 + * Firmware version: 2.40.5030 -- 2.1.4
[dpdk-dev] [PATCH 3/3] doc: update release notes for mlx5
Signed-off-by: Nelio Laranjeiro --- doc/guides/nics/mlx5.rst | 37 -- doc/guides/rel_notes/release_17_02.rst | 202 + 2 files changed, 230 insertions(+), 9 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index 571a926..09922a0 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -243,17 +243,13 @@ DPDK and must be installed separately: Currently supported by DPDK: -- Mellanox OFED version: - - - ConnectX-4: **3.4-1.0.0.0** - - ConnectX-4 Lx: **3.4-1.0.0.0** - - ConnectX-5: **4.0-0.0.8.1** - +- Mellanox OFED version: **4.0-1.0.1.0** - firmware version: - - ConnectX-4: **12.17.1010** - - ConnectX-4 Lx: **14.17.1010** - - ConnectX-5: **16.18.0296** + - ConnectX-4: **12.18.1000** + - ConnectX-4 Lx: **14.18.1000** + - ConnectX-5: **16.18.1000** + - ConnectX-5 Ex: **16.18.1000** Getting Mellanox OFED ~ @@ -275,6 +271,29 @@ required from that distribution. this DPDK release was developed and tested against is strongly recommended. Please check the `prerequisites`_. +Supported NICs +-- + +* Mellanox(R) ConnectX(R)-4 10G MCX4111A-XCAT (1x10G) +* Mellanox(R) ConnectX(R)-4 10G MCX4121A-XCAT (2x10G) +* Mellanox(R) ConnectX(R)-4 25G MCX4111A-ACAT (1x25G) +* Mellanox(R) ConnectX(R)-4 25G MCX4121A-ACAT (2x25G) +* Mellanox(R) ConnectX(R)-4 40G MCX4131A-BCAT (1x40G) +* Mellanox(R) ConnectX(R)-4 40G MCX413A-BCAT (1x40G) +* Mellanox(R) ConnectX(R)-4 40G MCX415A-BCAT (1x40G) +* Mellanox(R) ConnectX(R)-4 50G MCX4131A-GCAT (1x50G) +* Mellanox(R) ConnectX(R)-4 50G MCX413A-GCAT (1x50G) +* Mellanox(R) ConnectX(R)-4 50G MCX414A-BCAT (2x50G) +* Mellanox(R) ConnectX(R)-4 50G MCX415A-GCAT (2x50G) +* Mellanox(R) ConnectX(R)-4 50G MCX416A-BCAT (2x50G) +* Mellanox(R) ConnectX(R)-4 50G MCX416A-GCAT (2x50G) +* Mellanox(R) ConnectX(R)-4 50G MCX415A-CCAT (1x100G) +* Mellanox(R) ConnectX(R)-4 100G MCX416A-CCAT (2x100G) +* Mellanox(R) ConnectX(R)-4 Lx 10G MCX4121A-XCAT (2x10G) +* Mellanox(R) ConnectX(R)-4 Lx 25G MCX4121A-ACAT (2x25G) +* Mellanox(R) ConnectX(R)-5 100G MCX556A-ECAT (2x100G) +* Mellanox(R) ConnectX(R)-5 Ex EN 100G MCX516A-CDAT (2x100G) + Notes for testpmd - diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index d69dc4f..a17a3b6 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -131,6 +131,17 @@ New Features Support for Mellanox ConnectX-5 family of 10/25/40/50/100 Gbps adapters has been added to the existing mlx5 PMD. +* **Updated the mlx5 driver.** + + * Improve Tx performance by using vector logic. + * Improve RSS balancing when number of queues is not a power of two. + * Generic flow API support for Ethernet, IPv4, IPv4, UDP, TCP, VLAN and +VXLAN pattern items with DROP and QUEUE actions. + * Support for extended statistics. + * Addressed several data path bugs. + * As of MLNX_OFED 4.0-1.0.1.0, the Toeplitz RSS hash function is not +symmetric anymore for consistency with other PMDs. + * **virtio-user with vhost-kernel as another exceptional path.** Previously, we upstreamed a virtual device, virtio-user with vhost-user @@ -458,3 +469,194 @@ Tested Platforms * Host interface: PCI Express 3.0 x8 * Device ID: 15b3:1007 * Firmware version: 2.40.5030 + + * Mellanox(R) ConnectX(R)-4 10G MCX4111A-XCAT (1x10G) + + * Host interface: PCI Express 3.0 x8 + * Device ID: 15b3:1013 + * Firmware version: 12.18.1000 + + * Mellanox(R) ConnectX(R)-4 10G MCX4121A-XCAT (2x10G) + + * Host interface: PCI Express 3.0 x8 + * Device ID: 15b3:1013 + * Firmware version: 12.18.1000 + + * Mellanox(R) ConnectX(R)-4 25G MCX4111A-ACAT (1x25G) + + * Host interface: PCI Express 3.0 x8 + * Device ID: 15b3:1013 + * Firmware version: 12.18.1000 + + * Mellanox(R) ConnectX(R)-4 25G MCX4121A-ACAT (2x25G) + + * Host interface: PCI Express 3.0 x8 + * Device ID: 15b3:1013 + * Firmware version: 12.18.1000 + + * Mellanox(R) ConnectX(R)-4 40G MCX4131A-BCAT/MCX413A-BCAT (1x40G) + + * Host interface: PCI Express 3.0 x8 + * Device ID: 15b3:1013 + * Firmware version: 12.18.1000 + + * Mellanox(R) ConnectX(R)-4 40G MCX415A-BCAT (1x40G) + + * Host interface: PCI Express 3.0 x16 + * Device ID: 15b3:1013 + * Firmware version: 12.18.1000 + + * Mellanox(R) ConnectX(R)-4 50G MCX4131A-GCAT/MCX413A-GCAT (1x50G) + + * Host interface: PCI Express 3.0 x8 + * Device ID: 15b3:1013 + * Firmware version: 12.18.1000 + + * Mellanox(R) ConnectX(R)-4 50G MCX414A-BCAT (2x50G) + + * Host interface: PCI Express 3.0 x8 + * Device ID: 15b3:1013 + * Firmware version: 12.18.1000 + + * Mellanox(R) ConnectX(R)-4 50G MCX415A-GCAT/MCX416A-BCAT/MCX416A-GCAT (2x50G) + + * Host interface: PCI
[dpdk-dev] [PATCH v2] doc: add flow API to features list
Signed-off-by: Nelio Laranjeiro --- Changes in v2: - add ixgbe and i40e. --- doc/guides/nics/features/default.ini | 1 + doc/guides/nics/features/i40e.ini| 1 + doc/guides/nics/features/ixgbe.ini | 1 + doc/guides/nics/features/mlx5.ini| 1 + doc/guides/nics/mlx5.rst | 1 + 5 files changed, 5 insertions(+) diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini index 6e4a043..9e363ff 100644 --- a/doc/guides/nics/features/default.ini +++ b/doc/guides/nics/features/default.ini @@ -36,6 +36,7 @@ Flexible filter = Hash filter = Flow director= Flow control = +Flow API = Rate limitation = Traffic mirroring= CRC offload = diff --git a/doc/guides/nics/features/i40e.ini b/doc/guides/nics/features/i40e.ini index 0dbc3c3..6d11cce 100644 --- a/doc/guides/nics/features/i40e.ini +++ b/doc/guides/nics/features/i40e.ini @@ -27,6 +27,7 @@ Tunnel filter= Y Hash filter = Y Flow director= Y Flow control = Y +Flow API = Y Traffic mirroring= Y CRC offload = Y VLAN offload = Y diff --git a/doc/guides/nics/features/ixgbe.ini b/doc/guides/nics/features/ixgbe.ini index 9eb68ac..e65bbb8 100644 --- a/doc/guides/nics/features/ixgbe.ini +++ b/doc/guides/nics/features/ixgbe.ini @@ -29,6 +29,7 @@ SYN filter = Y Tunnel filter= Y Flow director= Y Flow control = Y +Flow API = Y Rate limitation = Y Traffic mirroring= Y CRC offload = Y diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini index f811e3f..f20d214 100644 --- a/doc/guides/nics/features/mlx5.ini +++ b/doc/guides/nics/features/mlx5.ini @@ -21,6 +21,7 @@ RSS reta update = Y SR-IOV = Y VLAN filter = Y Flow director= Y +Flow API = Y CRC offload = Y VLAN offload = Y L3 checksum offload = Y diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index a41c432..571a926 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -86,6 +86,7 @@ Features - Hardware checksum offloads. - Flow director (RTE_FDIR_MODE_PERFECT, RTE_FDIR_MODE_PERFECT_MAC_VLAN and RTE_ETH_FDIR_REJECT). +- Flow API. - Secondary process TX is supported. - KVM and VMware ESX SR-IOV modes are supported. - RSS hash result is supported. -- 2.1.4
[dpdk-dev] [PATCH] net/mlx5: fix Tx doorbell
Too much data is uselessly written to the Tx doorbell. Fixes: 1d88ba171942 ("net/mlx5: refactor Tx data path") Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- This patch should be applied on top of [1] or [2]. [1] http://dpdk.org/ml/archives/dev/2016-November/050716.html [2] http://dpdk.org/dev/patchwork/patch/17254/ --- drivers/net/mlx5/mlx5_rxtx.c | 26 -- drivers/net/mlx5/mlx5_rxtx.h | 2 -- drivers/net/mlx5/mlx5_txq.c | 2 -- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index 22b22ac..029d872 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -82,7 +82,8 @@ txq_mp2mr(struct txq *txq, struct rte_mempool *mp) __attribute__((always_inline)); static inline void -mlx5_tx_dbrec(struct txq *txq) __attribute__((always_inline)); +mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe) + __attribute__((always_inline)); static inline uint32_t rxq_cq_to_pkt_type(volatile struct mlx5_cqe *cqe) @@ -326,23 +327,20 @@ txq_mp2mr(struct txq *txq, struct rte_mempool *mp) * * @param txq * Pointer to TX queue structure. + * @param wqe + * Pointer to the last WQE posted in the NIC. */ static inline void -mlx5_tx_dbrec(struct txq *txq) +mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe) { - uint8_t *dst = (uint8_t *)((uintptr_t)txq->bf_reg + txq->bf_offset); - uint32_t data[4] = { - htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND), - htonl(txq->qp_num_8s), - 0, - 0, - }; + uint64_t *dst = (uint64_t *)((uintptr_t)txq->bf_reg); + volatile uint64_t *src = ((volatile uint64_t *)wqe); + rte_wmb(); *txq->qp_db = htonl(txq->wqe_ci); /* Ensure ordering between DB record and BF copy. */ rte_wmb(); - memcpy(dst, (uint8_t *)data, 16); - txq->bf_offset ^= (1 << txq->bf_buf_size); + *dst = *src; } /** @@ -609,7 +607,7 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) txq->stats.opackets += i; #endif /* Ring QP doorbell. */ - mlx5_tx_dbrec(txq); + mlx5_tx_dbrec(txq, (volatile struct mlx5_wqe *)wqe); txq->elts_head = elts_head; return i; } @@ -816,7 +814,7 @@ mlx5_tx_burst_mpw(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) /* Ring QP doorbell. */ if (mpw.state == MLX5_MPW_STATE_OPENED) mlx5_mpw_close(txq, &mpw); - mlx5_tx_dbrec(txq); + mlx5_tx_dbrec(txq, mpw.wqe); txq->elts_head = elts_head; return i; } @@ -1084,7 +1082,7 @@ mlx5_tx_burst_mpw_inline(void *dpdk_txq, struct rte_mbuf **pkts, mlx5_mpw_inline_close(txq, &mpw); else if (mpw.state == MLX5_MPW_STATE_OPENED) mlx5_mpw_close(txq, &mpw); - mlx5_tx_dbrec(txq); + mlx5_tx_dbrec(txq, mpw.wqe); txq->elts_head = elts_head; return i; } diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h index 6dcd35d..e244c48 100644 --- a/drivers/net/mlx5/mlx5_rxtx.h +++ b/drivers/net/mlx5/mlx5_rxtx.h @@ -251,8 +251,6 @@ struct txq { uint16_t elts_n:4; /* (*elts)[] length (in log2). */ uint16_t cqe_n:4; /* Number of CQ elements (in log2). */ uint16_t wqe_n:4; /* Number of of WQ elements (in log2). */ - uint16_t bf_buf_size:4; /* Log2 Blueflame size. */ - uint16_t bf_offset; /* Blueflame offset. */ uint16_t max_inline; /* Multiple of RTE_CACHE_LINE_SIZE to inline. */ uint32_t qp_num_8s; /* QP number shifted by 8. */ volatile struct mlx5_cqe (*cqes)[]; /* Completion queue. */ diff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c index f4c6682..ad39ddc 100644 --- a/drivers/net/mlx5/mlx5_txq.c +++ b/drivers/net/mlx5/mlx5_txq.c @@ -220,8 +220,6 @@ txq_setup(struct txq_ctrl *tmpl, struct txq_ctrl *txq_ctrl) tmpl->txq.wqe_n = log2above(qp->sq.wqe_cnt); tmpl->txq.qp_db = &qp->gen_data.db[MLX5_SND_DBR]; tmpl->txq.bf_reg = qp->gen_data.bf->reg; - tmpl->txq.bf_offset = qp->gen_data.bf->offset; - tmpl->txq.bf_buf_size = log2above(qp->gen_data.bf->buf_size); tmpl->txq.cq_db = cq->dbrec; tmpl->txq.cqes = (volatile struct mlx5_cqe (*)[]) -- 2.1.4
[dpdk-dev] [PATCH v2 1/4] net/mlx5: add preliminary support for rte_flow
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/Makefile| 1 + drivers/net/mlx5/mlx5.h | 16 ++ drivers/net/mlx5/mlx5_fdir.c | 15 ++ drivers/net/mlx5/mlx5_flow.c | 122 +++ 4 files changed, 154 insertions(+) create mode 100644 drivers/net/mlx5/mlx5_flow.c diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index cf87f0b..6d1338a 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -48,6 +48,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_stats.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rss.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_fdir.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mr.c +SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow.c # Dependencies. DEPDIRS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += lib/librte_ether diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 79b7a60..04f4eaa 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -59,6 +59,7 @@ #include #include #include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -268,4 +269,19 @@ void priv_fdir_enable(struct priv *); int mlx5_dev_filter_ctrl(struct rte_eth_dev *, enum rte_filter_type, enum rte_filter_op, void *); +/* mlx5_flow.c */ + +int mlx5_flow_validate(struct rte_eth_dev *, const struct rte_flow_attr *, + const struct rte_flow_item [], + const struct rte_flow_action [], + struct rte_flow_error *); +struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, + const struct rte_flow_attr *, + const struct rte_flow_item [], + const struct rte_flow_action [], + struct rte_flow_error *); +int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, + struct rte_flow_error *); +int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); + #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_fdir.c b/drivers/net/mlx5/mlx5_fdir.c index 1acf682..f80c58b 100644 --- a/drivers/net/mlx5/mlx5_fdir.c +++ b/drivers/net/mlx5/mlx5_fdir.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -1042,6 +1044,14 @@ priv_fdir_ctrl_func(struct priv *priv, enum rte_filter_op filter_op, void *arg) return ret; } +static const struct rte_flow_ops mlx5_flow_ops = { + .validate = mlx5_flow_validate, + .create = mlx5_flow_create, + .destroy = mlx5_flow_destroy, + .flush = mlx5_flow_flush, + .query = NULL, +}; + /** * Manage filter operations. * @@ -1067,6 +1077,11 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev, struct priv *priv = dev->data->dev_private; switch (filter_type) { + case RTE_ETH_FILTER_GENERIC: + if (filter_op != RTE_ETH_FILTER_GET) + return -EINVAL; + *(const void **)arg = &mlx5_flow_ops; + return 0; case RTE_ETH_FILTER_FDIR: priv_lock(priv); ret = priv_fdir_ctrl_func(priv, filter_op, arg); diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c new file mode 100644 index 000..a514dff --- /dev/null +++ b/drivers/net/mlx5/mlx5_flow.c @@ -0,0 +1,122 @@ +/*- + * BSD LICENSE + * + * Copyright 2016 6WIND S.A. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, ST
[dpdk-dev] [PATCH v2 2/4] net/mlx5: add software support for rte_flow
Introduce initial software validation for rte_flow rules. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 2 + drivers/net/mlx5/mlx5_flow.c| 202 ++-- drivers/net/mlx5/mlx5_trigger.c | 2 + 3 files changed, 177 insertions(+), 29 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 04f4eaa..ac995a0 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -136,6 +136,7 @@ struct priv { unsigned int reta_idx_n; /* RETA index size. */ struct fdir_filter_list *fdir_filter_list; /* Flow director rules. */ struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */ + LIST_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ uint32_t link_speed_capa; /* Link speed capabilities. */ rte_spinlock_t lock; /* Lock for control functions. */ }; @@ -283,5 +284,6 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, struct rte_flow_error *); int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); +void priv_flow_flush(struct priv *); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index a514dff..3e5098a 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -30,11 +30,119 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include + #include #include #include +#include + #include "mlx5.h" +struct rte_flow { + LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure. */ +}; + +/** + * Validate a flow supported by the NIC. + * + * @param priv + * Pointer to private structure. + * @param[in] attr + * Flow rule attributes. + * @param[in] pattern + * Pattern specification (list terminated by the END pattern item). + * @param[in] actions + * Associated actions (list terminated by the END action). + * @param[out] error + * Perform verbose error reporting if not NULL. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +static int +priv_flow_validate(struct priv *priv, + const struct rte_flow_attr *attr, + const struct rte_flow_item items[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + (void)priv; + const struct rte_flow_item *ilast = NULL; + + if (attr->group) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_GROUP, + NULL, + "groups are not supported"); + return -rte_errno; + } + if (attr->priority) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, + NULL, + "priorities are not supported"); + return -rte_errno; + } + if (attr->egress) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, + NULL, + "egress is not supported"); + return -rte_errno; + } + if (!attr->ingress) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, + NULL, + "only ingress is supported"); + return -rte_errno; + } + for (; items->type != RTE_FLOW_ITEM_TYPE_END; ++items) { + if (items->type == RTE_FLOW_ITEM_TYPE_VOID) { + continue; + } else if (items->type == RTE_FLOW_ITEM_TYPE_ETH) { + if (ilast) + goto exit_item_not_supported; + ilast = items; + } else if ((items->type == RTE_FLOW_ITEM_TYPE_IPV4) || + (items->type == RTE_FLOW_ITEM_TYPE_IPV6)) { + if (!ilast) + goto exit_item_not_supported; + else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH) + goto exit_item_not_supported; + ilast = items; + } else if ((items->type == RTE_FLOW_ITEM_TYPE_UDP) || + (items->type == RTE_FLOW_ITEM_TYPE_TCP)) { + if (!ilast) + goto exit_item_not_supported; + else if ((ilast->type != RTE_FLOW_ITEM_TYPE_IPV4) && +(ilast->type != RTE_FLOW_ITEM_TYP
[dpdk-dev] [PATCH v2 3/4] net/mlx5: add rte_flow rule creation
Convert Ethernet, IPv4, IPv6, TCP, UDP layers into ibv_flow and create those rules when after validation (i.e. NIC supports the rule). VLAN is still not supported in this commit. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 3 +- drivers/net/mlx5/mlx5_flow.c| 737 +++- drivers/net/mlx5/mlx5_trigger.c | 6 +- 3 files changed, 729 insertions(+), 17 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index ac995a0..ca7e84c 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -284,6 +284,7 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, struct rte_flow_error *); int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); -void priv_flow_flush(struct priv *); +int priv_flow_apply(struct priv *); +void priv_flow_remove(struct priv *); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 3e5098a..44e2fb8 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -31,6 +31,17 @@ */ #include +#include + +/* Verbs header. */ +/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif #include #include @@ -39,11 +50,82 @@ #include "mlx5.h" +/** Define a value to use as index for the drop queue. */ +#define MLX5_FLOW_DROP_QUEUE ((uint32_t)-1) + struct rte_flow { LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure. */ + struct ibv_exp_flow_attr *ibv_attr; /* Pointer to Verbs attributes. */ + struct ibv_exp_rwq_ind_table *ind_table; /* Indirection table. */ + struct ibv_qp *qp; /* Verbs Queue pair. */ + struct ibv_exp_flow *ibv_flow; /* Verbs flow. */ + struct ibv_exp_wq *wq; /* Verbs work queue. */ + struct ibv_cq *cq; /* Verbs completion queue. */ + uint8_t drop; /* 1 if this flow is associated to a drop queue. */ }; /** + * Check support for a given item. + * + * @param item[in] + * Item specification. + * @param mask[in] + * Bit-mask covering supported fields to compare with spec, last and mask in + * \item. + * @param size + * Bit-Mask size in bytes. + * + * @return + * 0 on success. + */ +static int +mlx5_flow_item_validate(const struct rte_flow_item *item, + const uint8_t *mask, unsigned int size) +{ + int ret = 0; + + if (item->spec && !item->mask) { + unsigned int i; + const uint8_t *spec = item->spec; + + for (i = 0; i < size; ++i) + if ((spec[i] | mask[i]) != mask[i]) + return -1; + } + if (item->last && !item->mask) { + unsigned int i; + const uint8_t *spec = item->last; + + for (i = 0; i < size; ++i) + if ((spec[i] | mask[i]) != mask[i]) + return -1; + } + if (item->mask) { + unsigned int i; + const uint8_t *spec = item->mask; + + for (i = 0; i < size; ++i) + if ((spec[i] | mask[i]) != mask[i]) + return -1; + } + if (item->spec && item->last) { + uint8_t spec[size]; + uint8_t last[size]; + const uint8_t *apply = mask; + unsigned int i; + + if (item->mask) + apply = item->mask; + for (i = 0; i < size; ++i) { + spec[i] = ((const uint8_t *)item->spec)[i] & apply[i]; + last[i] = ((const uint8_t *)item->last)[i] & apply[i]; + } + ret = memcmp(spec, last, size); + } + return ret; +} + +/** * Validate a flow supported by the NIC. * * @param priv @@ -67,8 +149,42 @@ priv_flow_validate(struct priv *priv, const struct rte_flow_action actions[], struct rte_flow_error *error) { - (void)priv; const struct rte_flow_item *ilast = NULL; + const struct rte_flow_item_eth eth_mask = { + .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + .type = -1, + }; + const struct rte_flow_item_ipv4 ipv4_mask = { + .hdr = { + .src_addr = -1, + .dst_addr = -1, + }, + }; + const struct rte_flow_item_ipv6 ipv6_mask = { + .hdr
[dpdk-dev] [PATCH v2 0/4] net/mlx5: support flow_rte
This series requires rte_flow [1]. It brings rte_flow support to the same level as flow director (FDIR) in mlx5. [1] http://dpdk.org/ml/archives/dev/2016-December/052802.html Changes in v2: - Fix several issues. - Support VLAN filtering. Nelio Laranjeiro (4): net/mlx5: add preliminary support for rte_flow net/mlx5: add software support for rte_flow net/mlx5: add rte_flow rule creation net/mlx5: add VLAN filter support in rte_flow drivers/net/mlx5/Makefile |1 + drivers/net/mlx5/mlx5.h | 19 + drivers/net/mlx5/mlx5_fdir.c| 15 + drivers/net/mlx5/mlx5_flow.c| 1030 +++ drivers/net/mlx5/mlx5_trigger.c |4 + 5 files changed, 1069 insertions(+) create mode 100644 drivers/net/mlx5/mlx5_flow.c -- 2.1.4
[dpdk-dev] [PATCH v2 4/4] net/mlx5: add VLAN filter support in rte_flow
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 59 ++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 44e2fb8..fec1950 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -185,6 +185,9 @@ priv_flow_validate(struct priv *priv, .dst_port = -1, }, }; + const struct rte_flow_item_vlan vlan_mask = { + .tci = -1, + }; if (attr->group) { rte_flow_error_set(error, ENOTSUP, @@ -229,11 +232,32 @@ priv_flow_validate(struct priv *priv, sizeof(eth_mask)); if (err) goto exit_item_not_supported; - } else if (items->type == RTE_FLOW_ITEM_TYPE_IPV4) { + } else if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) { if (!ilast) goto exit_item_not_supported; else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH) goto exit_item_not_supported; + if (((const struct rte_flow_item_vlan *)items)->tci > + ETHER_MAX_VLAN_ID) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + items, + "wrong VLAN tci value"); + goto exit; + } + ilast = items; + err = mlx5_flow_item_validate( + items, + (const uint8_t *)&vlan_mask, + sizeof(vlan_mask)); + if (err) + goto exit_item_not_supported; + } else if (items->type == RTE_FLOW_ITEM_TYPE_IPV4) { + if (!ilast) + goto exit_item_not_supported; + else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH && +ilast->type != RTE_FLOW_ITEM_TYPE_VLAN) + goto exit_item_not_supported; ilast = items; err = mlx5_flow_item_validate( items, @@ -244,7 +268,8 @@ priv_flow_validate(struct priv *priv, } else if (items->type == RTE_FLOW_ITEM_TYPE_IPV6) { if (!ilast) goto exit_item_not_supported; - else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH) + else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH && +ilast->type != RTE_FLOW_ITEM_TYPE_VLAN) goto exit_item_not_supported; ilast = items; err = mlx5_flow_item_validate( @@ -376,6 +401,28 @@ mlx5_flow_create_eth(const struct rte_flow_item *item, } /** + * Convert VLAN item to Verbs specification. + * + * @param item[in] + * Item specification. + * @param eth[in, out] + * Verbs Ethernet specification structure. + */ +static void +mlx5_flow_create_vlan(const struct rte_flow_item *item, + struct ibv_exp_flow_spec_eth *eth) +{ + const struct rte_flow_item_vlan *spec = item->spec; + const struct rte_flow_item_vlan *mask = item->mask; + + if (spec) + eth->val.vlan_tag = spec->tci; + if (mask) + eth->mask.vlan_tag = mask->tci; + eth->val.vlan_tag &= eth->mask.vlan_tag; +} + +/** * Convert IPv4 item to Verbs specification. * * @param item[in] @@ -704,6 +751,14 @@ priv_flow_create(struct priv *priv, flow_size += eth_size; ++ibv_attr->num_of_specs; ibv_attr->priority = 2; + } else if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) { + struct ibv_exp_flow_spec_eth *eth; + unsigned int eth_size = + sizeof(struct ibv_exp_flow_spec_eth); + + eth = (void *)((uintptr_t)ibv_attr + flow_size - + eth_size); + mlx5_flow_create_vlan(items, eth); } else if (items->type == RTE_FLOW_ITEM_TYPE_IPV4) { struct ibv_exp_flow_spec_ipv4 *ipv4; unsigned int ipv4_size = -- 2.1.4
[dpdk-dev] [PATCH v3 0/4] net/mlx5: support flow_rte
This series requires rte_flow [1]. It brings rte_flow support to the same level as flow director (FDIR) in mlx5. [1] http://dpdk.org/ml/archives/dev/2016-December/052950.html Changes in v3: - Fix Ethernet ether type issue. Changes in v2: - Fix several issues. - Support VLAN filtering. Nelio Laranjeiro (4): net/mlx5: add preliminary support for rte_flow net/mlx5: add software support for rte_flow net/mlx5: add rte_flow rule creation net/mlx5: add VLAN filter support in rte_flow drivers/net/mlx5/Makefile |1 + drivers/net/mlx5/mlx5.h | 19 + drivers/net/mlx5/mlx5_fdir.c| 15 + drivers/net/mlx5/mlx5_flow.c| 1026 +++ drivers/net/mlx5/mlx5_trigger.c |4 + 5 files changed, 1065 insertions(+) create mode 100644 drivers/net/mlx5/mlx5_flow.c -- 2.1.4
[dpdk-dev] [PATCH v3 1/4] net/mlx5: add preliminary support for rte_flow
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/Makefile| 1 + drivers/net/mlx5/mlx5.h | 16 ++ drivers/net/mlx5/mlx5_fdir.c | 15 ++ drivers/net/mlx5/mlx5_flow.c | 122 +++ 4 files changed, 154 insertions(+) create mode 100644 drivers/net/mlx5/mlx5_flow.c diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index cf87f0b..6d1338a 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -48,6 +48,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_stats.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rss.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_fdir.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mr.c +SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow.c # Dependencies. DEPDIRS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += lib/librte_ether diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 79b7a60..04f4eaa 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -59,6 +59,7 @@ #include #include #include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -268,4 +269,19 @@ void priv_fdir_enable(struct priv *); int mlx5_dev_filter_ctrl(struct rte_eth_dev *, enum rte_filter_type, enum rte_filter_op, void *); +/* mlx5_flow.c */ + +int mlx5_flow_validate(struct rte_eth_dev *, const struct rte_flow_attr *, + const struct rte_flow_item [], + const struct rte_flow_action [], + struct rte_flow_error *); +struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, + const struct rte_flow_attr *, + const struct rte_flow_item [], + const struct rte_flow_action [], + struct rte_flow_error *); +int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, + struct rte_flow_error *); +int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); + #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_fdir.c b/drivers/net/mlx5/mlx5_fdir.c index 1acf682..f80c58b 100644 --- a/drivers/net/mlx5/mlx5_fdir.c +++ b/drivers/net/mlx5/mlx5_fdir.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -1042,6 +1044,14 @@ priv_fdir_ctrl_func(struct priv *priv, enum rte_filter_op filter_op, void *arg) return ret; } +static const struct rte_flow_ops mlx5_flow_ops = { + .validate = mlx5_flow_validate, + .create = mlx5_flow_create, + .destroy = mlx5_flow_destroy, + .flush = mlx5_flow_flush, + .query = NULL, +}; + /** * Manage filter operations. * @@ -1067,6 +1077,11 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev, struct priv *priv = dev->data->dev_private; switch (filter_type) { + case RTE_ETH_FILTER_GENERIC: + if (filter_op != RTE_ETH_FILTER_GET) + return -EINVAL; + *(const void **)arg = &mlx5_flow_ops; + return 0; case RTE_ETH_FILTER_FDIR: priv_lock(priv); ret = priv_fdir_ctrl_func(priv, filter_op, arg); diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c new file mode 100644 index 000..a514dff --- /dev/null +++ b/drivers/net/mlx5/mlx5_flow.c @@ -0,0 +1,122 @@ +/*- + * BSD LICENSE + * + * Copyright 2016 6WIND S.A. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, ST
[dpdk-dev] [PATCH v3 3/4] net/mlx5: add rte_flow rule creation
Convert Ethernet, IPv4, IPv6, TCP, UDP layers into ibv_flow and create those rules when after validation (i.e. NIC supports the rule). VLAN is still not supported in this commit. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 3 +- drivers/net/mlx5/mlx5_flow.c| 733 +++- drivers/net/mlx5/mlx5_trigger.c | 6 +- 3 files changed, 725 insertions(+), 17 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index ac995a0..ca7e84c 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -284,6 +284,7 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, struct rte_flow_error *); int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); -void priv_flow_flush(struct priv *); +int priv_flow_apply(struct priv *); +void priv_flow_remove(struct priv *); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 3e5098a..a33c568 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -31,6 +31,17 @@ */ #include +#include + +/* Verbs header. */ +/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif #include #include @@ -39,11 +50,82 @@ #include "mlx5.h" +/** Define a value to use as index for the drop queue. */ +#define MLX5_FLOW_DROP_QUEUE ((uint32_t)-1) + struct rte_flow { LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure. */ + struct ibv_exp_flow_attr *ibv_attr; /* Pointer to Verbs attributes. */ + struct ibv_exp_rwq_ind_table *ind_table; /* Indirection table. */ + struct ibv_qp *qp; /* Verbs Queue pair. */ + struct ibv_exp_flow *ibv_flow; /* Verbs flow. */ + struct ibv_exp_wq *wq; /* Verbs work queue. */ + struct ibv_cq *cq; /* Verbs completion queue. */ + uint8_t drop; /* 1 if this flow is associated to a drop queue. */ }; /** + * Check support for a given item. + * + * @param item[in] + * Item specification. + * @param mask[in] + * Bit-mask covering supported fields to compare with spec, last and mask in + * \item. + * @param size + * Bit-Mask size in bytes. + * + * @return + * 0 on success. + */ +static int +mlx5_flow_item_validate(const struct rte_flow_item *item, + const uint8_t *mask, unsigned int size) +{ + int ret = 0; + + if (item->spec && !item->mask) { + unsigned int i; + const uint8_t *spec = item->spec; + + for (i = 0; i < size; ++i) + if ((spec[i] | mask[i]) != mask[i]) + return -1; + } + if (item->last && !item->mask) { + unsigned int i; + const uint8_t *spec = item->last; + + for (i = 0; i < size; ++i) + if ((spec[i] | mask[i]) != mask[i]) + return -1; + } + if (item->mask) { + unsigned int i; + const uint8_t *spec = item->mask; + + for (i = 0; i < size; ++i) + if ((spec[i] | mask[i]) != mask[i]) + return -1; + } + if (item->spec && item->last) { + uint8_t spec[size]; + uint8_t last[size]; + const uint8_t *apply = mask; + unsigned int i; + + if (item->mask) + apply = item->mask; + for (i = 0; i < size; ++i) { + spec[i] = ((const uint8_t *)item->spec)[i] & apply[i]; + last[i] = ((const uint8_t *)item->last)[i] & apply[i]; + } + ret = memcmp(spec, last, size); + } + return ret; +} + +/** * Validate a flow supported by the NIC. * * @param priv @@ -67,8 +149,41 @@ priv_flow_validate(struct priv *priv, const struct rte_flow_action actions[], struct rte_flow_error *error) { - (void)priv; const struct rte_flow_item *ilast = NULL; + const struct rte_flow_item_eth eth_mask = { + .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + }; + const struct rte_flow_item_ipv4 ipv4_mask = { + .hdr = { + .src_addr = -1, + .dst_addr = -1, + }, + }; + const struct rte_flow_item_ipv6 ipv6_mask = { + .hdr = { + .src_addr = { +
[dpdk-dev] [PATCH v3 2/4] net/mlx5: add software support for rte_flow
Introduce initial software validation for rte_flow rules. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 2 + drivers/net/mlx5/mlx5_flow.c| 202 ++-- drivers/net/mlx5/mlx5_trigger.c | 2 + 3 files changed, 177 insertions(+), 29 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 04f4eaa..ac995a0 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -136,6 +136,7 @@ struct priv { unsigned int reta_idx_n; /* RETA index size. */ struct fdir_filter_list *fdir_filter_list; /* Flow director rules. */ struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */ + LIST_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ uint32_t link_speed_capa; /* Link speed capabilities. */ rte_spinlock_t lock; /* Lock for control functions. */ }; @@ -283,5 +284,6 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, struct rte_flow_error *); int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); +void priv_flow_flush(struct priv *); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index a514dff..3e5098a 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -30,11 +30,119 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include + #include #include #include +#include + #include "mlx5.h" +struct rte_flow { + LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure. */ +}; + +/** + * Validate a flow supported by the NIC. + * + * @param priv + * Pointer to private structure. + * @param[in] attr + * Flow rule attributes. + * @param[in] pattern + * Pattern specification (list terminated by the END pattern item). + * @param[in] actions + * Associated actions (list terminated by the END action). + * @param[out] error + * Perform verbose error reporting if not NULL. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +static int +priv_flow_validate(struct priv *priv, + const struct rte_flow_attr *attr, + const struct rte_flow_item items[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + (void)priv; + const struct rte_flow_item *ilast = NULL; + + if (attr->group) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_GROUP, + NULL, + "groups are not supported"); + return -rte_errno; + } + if (attr->priority) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, + NULL, + "priorities are not supported"); + return -rte_errno; + } + if (attr->egress) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, + NULL, + "egress is not supported"); + return -rte_errno; + } + if (!attr->ingress) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, + NULL, + "only ingress is supported"); + return -rte_errno; + } + for (; items->type != RTE_FLOW_ITEM_TYPE_END; ++items) { + if (items->type == RTE_FLOW_ITEM_TYPE_VOID) { + continue; + } else if (items->type == RTE_FLOW_ITEM_TYPE_ETH) { + if (ilast) + goto exit_item_not_supported; + ilast = items; + } else if ((items->type == RTE_FLOW_ITEM_TYPE_IPV4) || + (items->type == RTE_FLOW_ITEM_TYPE_IPV6)) { + if (!ilast) + goto exit_item_not_supported; + else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH) + goto exit_item_not_supported; + ilast = items; + } else if ((items->type == RTE_FLOW_ITEM_TYPE_UDP) || + (items->type == RTE_FLOW_ITEM_TYPE_TCP)) { + if (!ilast) + goto exit_item_not_supported; + else if ((ilast->type != RTE_FLOW_ITEM_TYPE_IPV4) && +(ilast->type != RTE_FLOW_ITEM_TYP
[dpdk-dev] [PATCH v3 4/4] net/mlx5: add VLAN filter support in rte_flow
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 59 ++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index a33c568..2478fb6 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -184,6 +184,9 @@ priv_flow_validate(struct priv *priv, .dst_port = -1, }, }; + const struct rte_flow_item_vlan vlan_mask = { + .tci = -1, + }; if (attr->group) { rte_flow_error_set(error, ENOTSUP, @@ -228,11 +231,32 @@ priv_flow_validate(struct priv *priv, sizeof(eth_mask)); if (err) goto exit_item_not_supported; - } else if (items->type == RTE_FLOW_ITEM_TYPE_IPV4) { + } else if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) { if (!ilast) goto exit_item_not_supported; else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH) goto exit_item_not_supported; + if (((const struct rte_flow_item_vlan *)items)->tci > + ETHER_MAX_VLAN_ID) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + items, + "wrong VLAN tci value"); + goto exit; + } + ilast = items; + err = mlx5_flow_item_validate( + items, + (const uint8_t *)&vlan_mask, + sizeof(vlan_mask)); + if (err) + goto exit_item_not_supported; + } else if (items->type == RTE_FLOW_ITEM_TYPE_IPV4) { + if (!ilast) + goto exit_item_not_supported; + else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH && +ilast->type != RTE_FLOW_ITEM_TYPE_VLAN) + goto exit_item_not_supported; ilast = items; err = mlx5_flow_item_validate( items, @@ -243,7 +267,8 @@ priv_flow_validate(struct priv *priv, } else if (items->type == RTE_FLOW_ITEM_TYPE_IPV6) { if (!ilast) goto exit_item_not_supported; - else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH) + else if (ilast->type != RTE_FLOW_ITEM_TYPE_ETH && +ilast->type != RTE_FLOW_ITEM_TYPE_VLAN) goto exit_item_not_supported; ilast = items; err = mlx5_flow_item_validate( @@ -372,6 +397,28 @@ mlx5_flow_create_eth(const struct rte_flow_item *item, } /** + * Convert VLAN item to Verbs specification. + * + * @param item[in] + * Item specification. + * @param eth[in, out] + * Verbs Ethernet specification structure. + */ +static void +mlx5_flow_create_vlan(const struct rte_flow_item *item, + struct ibv_exp_flow_spec_eth *eth) +{ + const struct rte_flow_item_vlan *spec = item->spec; + const struct rte_flow_item_vlan *mask = item->mask; + + if (spec) + eth->val.vlan_tag = spec->tci; + if (mask) + eth->mask.vlan_tag = mask->tci; + eth->val.vlan_tag &= eth->mask.vlan_tag; +} + +/** * Convert IPv4 item to Verbs specification. * * @param item[in] @@ -700,6 +747,14 @@ priv_flow_create(struct priv *priv, flow_size += eth_size; ++ibv_attr->num_of_specs; ibv_attr->priority = 2; + } else if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) { + struct ibv_exp_flow_spec_eth *eth; + unsigned int eth_size = + sizeof(struct ibv_exp_flow_spec_eth); + + eth = (void *)((uintptr_t)ibv_attr + flow_size - + eth_size); + mlx5_flow_create_vlan(items, eth); } else if (items->type == RTE_FLOW_ITEM_TYPE_IPV4) { struct ibv_exp_flow_spec_ipv4 *ipv4; unsigned int ipv4_size = -- 2.1.4
[dpdk-dev] [PATCH] net/mlx5: fix RSS hash result for flows
Flows redirected to a specific queue do not have a valid RSS hash result and the related mbuf flag must not be set. Fixes: ecf60761fc2a ("net/mlx5: return RSS hash result in mbuf") CC: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_rxtx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index a37e433..6f86ded 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -1353,7 +1353,7 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) /* Update packet information. */ pkt->packet_type = 0; pkt->ol_flags = 0; - if (rxq->rss_hash) { + if (rss_hash_res && rxq->rss_hash) { pkt->hash.rss = rss_hash_res; pkt->ol_flags = PKT_RX_RSS_HASH; } -- 2.1.4
[dpdk-dev] [PATCH v4 3/6] net/mlx5: support VLAN flow item
Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 54 +++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index ebae2b5..549da6c 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -55,6 +55,9 @@ static int mlx5_flow_create_eth(const struct rte_flow_item *item, void *data); static int +mlx5_flow_create_vlan(const struct rte_flow_item *item, void *data); + +static int mlx5_flow_create_ipv4(const struct rte_flow_item *item, void *data); static int @@ -131,7 +134,8 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .dst_sz = sizeof(struct ibv_exp_flow_spec_eth), }, [RTE_FLOW_ITEM_TYPE_ETH] = { - .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4, + .items = ITEMS(RTE_FLOW_ITEM_TYPE_VLAN, + RTE_FLOW_ITEM_TYPE_IPV4, RTE_FLOW_ITEM_TYPE_IPV6), .actions = valid_actions, .mask = &(const struct rte_flow_item_eth){ @@ -142,6 +146,17 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .convert = mlx5_flow_create_eth, .dst_sz = sizeof(struct ibv_exp_flow_spec_eth), }, + [RTE_FLOW_ITEM_TYPE_VLAN] = { + .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_IPV6), + .actions = valid_actions, + .mask = &(const struct rte_flow_item_vlan){ + .tci = -1, + }, + .mask_sz = sizeof(struct rte_flow_item_vlan), + .convert = mlx5_flow_create_vlan, + .dst_sz = 0, + }, [RTE_FLOW_ITEM_TYPE_IPV4] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_TCP), @@ -348,6 +363,17 @@ priv_flow_validate(struct priv *priv, if (items->type == RTE_FLOW_ITEM_TYPE_VOID) continue; + /* Handle special situation for VLAN. */ + if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) { + if (((const struct rte_flow_item_vlan *)items)->tci > + ETHER_MAX_VLAN_ID) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + items, + "wrong VLAN id value"); + return -rte_errno; + } + } for (i = 0; cur_item->items && cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END; @@ -471,6 +497,32 @@ mlx5_flow_create_eth(const struct rte_flow_item *item, void *data) } /** + * Convert VLAN item to Verbs specification. + * + * @param item[in] + * Item specification. + * @param data[in, out] + * User structure. + */ +static int +mlx5_flow_create_vlan(const struct rte_flow_item *item, void *data) +{ + const struct rte_flow_item_vlan *spec = item->spec; + const struct rte_flow_item_vlan *mask = item->mask; + struct mlx5_flow *flow = (struct mlx5_flow *)data; + struct ibv_exp_flow_spec_eth *eth; + const unsigned int eth_size = sizeof(struct ibv_exp_flow_spec_eth); + + eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset - eth_size); + if (spec) + eth->val.vlan_tag = spec->tci; + if (mask) + eth->mask.vlan_tag = mask->tci; + eth->val.vlan_tag &= eth->mask.vlan_tag; + return 0; +} + +/** * Convert IPv4 item to Verbs specification. * * @param item[in] -- 2.1.4
[dpdk-dev] [PATCH v4 2/6] net/mlx5: support basic flow items and actions
Introduce initial software for rte_flow rules. VLAN, VXLAN are still not supported. Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5.h | 3 + drivers/net/mlx5/mlx5_flow.c| 928 ++-- drivers/net/mlx5/mlx5_trigger.c | 2 + 3 files changed, 904 insertions(+), 29 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 04f4eaa..c415ce3 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -136,6 +136,7 @@ struct priv { unsigned int reta_idx_n; /* RETA index size. */ struct fdir_filter_list *fdir_filter_list; /* Flow director rules. */ struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */ + LIST_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ uint32_t link_speed_capa; /* Link speed capabilities. */ rte_spinlock_t lock; /* Lock for control functions. */ }; @@ -283,5 +284,7 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, struct rte_flow_error *); int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); +int priv_flow_start(struct priv *); +void priv_flow_stop(struct priv *); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 4fdefa0..ebae2b5 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -31,12 +31,380 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include + +/* Verbs header. */ +/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + #include #include #include +#include #include "mlx5.h" +static int +mlx5_flow_create_eth(const struct rte_flow_item *item, void *data); + +static int +mlx5_flow_create_ipv4(const struct rte_flow_item *item, void *data); + +static int +mlx5_flow_create_ipv6(const struct rte_flow_item *item, void *data); + +static int +mlx5_flow_create_udp(const struct rte_flow_item *item, void *data); + +static int +mlx5_flow_create_tcp(const struct rte_flow_item *item, void *data); + +struct rte_flow { + LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ + struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ + struct ibv_exp_rwq_ind_table *ind_table; /**< Indirection table. */ + struct ibv_qp *qp; /**< Verbs queue pair. */ + struct ibv_exp_flow *ibv_flow; /**< Verbs 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. */ +}; + +/** Static initializer for items. */ +#define ITEMS(...) \ + (const enum rte_flow_item_type []){ \ + __VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \ + } + +/** Structure to generate a simple graph of layers supported by the NIC. */ +struct mlx5_flow_items { + /** List of possible following items. */ + const enum rte_flow_item_type *const items; + /** List of possible actions for these items. */ + const enum rte_flow_action_type *const actions; + /** Bit-masks corresponding to the possibilities for the item. */ + const void *mask; + /** Bit-masks size in bytes. */ + const unsigned int mask_sz; + /** +* Conversion function from rte_flow to NIC specific flow. +* +* @param item +* rte_flow item to convert. +* @param data +* Internal structure to store the conversion. +* +* @return +* 0 on success, negative value otherwise. +*/ + int (*convert)(const struct rte_flow_item *item, void *data); + /** Size in bytes of the destination structure. */ + const unsigned int dst_sz; +}; + +/** Valid action for this PMD. */ +static const enum rte_flow_action_type valid_actions[] = { + RTE_FLOW_ACTION_TYPE_DROP, + RTE_FLOW_ACTION_TYPE_QUEUE, + RTE_FLOW_ACTION_TYPE_END, +}; + +/** Graph of supported items and associated actions. */ +static const struct mlx5_flow_items mlx5_flow_items[] = { + [RTE_FLOW_ITEM_TYPE_VOID] = { + .items = ITEMS(RTE_FLOW_ITEM_TYPE_VOID, + RTE_FLOW_ITEM_TYPE_ETH), + .actions = valid_actions, + .mask = &(const struct rte_flow_item_eth){ + .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", + .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", + }, + .mask_sz = sizeof(struct rte_flow_item_eth), + .convert =
[dpdk-dev] [PATCH v4 1/6] net/mlx5: add preliminary flow API support
Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/Makefile| 1 + drivers/net/mlx5/mlx5.h | 16 ++ drivers/net/mlx5/mlx5_fdir.c | 15 ++ drivers/net/mlx5/mlx5_flow.c | 124 +++ 4 files changed, 156 insertions(+) create mode 100644 drivers/net/mlx5/mlx5_flow.c diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index cf87f0b..6d1338a 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -48,6 +48,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_stats.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rss.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_fdir.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mr.c +SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow.c # Dependencies. DEPDIRS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += lib/librte_ether diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 79b7a60..04f4eaa 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -59,6 +59,7 @@ #include #include #include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -268,4 +269,19 @@ void priv_fdir_enable(struct priv *); int mlx5_dev_filter_ctrl(struct rte_eth_dev *, enum rte_filter_type, enum rte_filter_op, void *); +/* mlx5_flow.c */ + +int mlx5_flow_validate(struct rte_eth_dev *, const struct rte_flow_attr *, + const struct rte_flow_item [], + const struct rte_flow_action [], + struct rte_flow_error *); +struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, + const struct rte_flow_attr *, + const struct rte_flow_item [], + const struct rte_flow_action [], + struct rte_flow_error *); +int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, + struct rte_flow_error *); +int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); + #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_fdir.c b/drivers/net/mlx5/mlx5_fdir.c index 1acf682..f80c58b 100644 --- a/drivers/net/mlx5/mlx5_fdir.c +++ b/drivers/net/mlx5/mlx5_fdir.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -1042,6 +1044,14 @@ priv_fdir_ctrl_func(struct priv *priv, enum rte_filter_op filter_op, void *arg) return ret; } +static const struct rte_flow_ops mlx5_flow_ops = { + .validate = mlx5_flow_validate, + .create = mlx5_flow_create, + .destroy = mlx5_flow_destroy, + .flush = mlx5_flow_flush, + .query = NULL, +}; + /** * Manage filter operations. * @@ -1067,6 +1077,11 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev, struct priv *priv = dev->data->dev_private; switch (filter_type) { + case RTE_ETH_FILTER_GENERIC: + if (filter_op != RTE_ETH_FILTER_GET) + return -EINVAL; + *(const void **)arg = &mlx5_flow_ops; + return 0; case RTE_ETH_FILTER_FDIR: priv_lock(priv); ret = priv_fdir_ctrl_func(priv, filter_op, arg); diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c new file mode 100644 index 000..4fdefa0 --- /dev/null +++ b/drivers/net/mlx5/mlx5_flow.c @@ -0,0 +1,124 @@ +/*- + * BSD LICENSE + * + * Copyright 2016 6WIND S.A. + * Copyright 2016 Mellanox. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON A
[dpdk-dev] [PATCH v4 0/6] net/mlx5: support flow API
Changes in v4: - Simplify flow parsing by using a graph. - Add VXLAN flow item. - Add mark flow action. - Extend IPv4 filter item (Type of service, Next Protocol ID). Changes in v3: - Fix Ethernet ether type issue. Changes in v2: - Fix several issues. - Support VLAN filtering. Nelio Laranjeiro (6): net/mlx5: add preliminary flow API support net/mlx5: support basic flow items and actions net/mlx5: support VLAN flow item net/mlx5: support VXLAN flow item net/mlx5: support mark flow action net/mlx5: extend IPv4 flow item drivers/net/mlx5/Makefile |1 + drivers/net/mlx5/mlx5.h | 19 + drivers/net/mlx5/mlx5_fdir.c| 15 + drivers/net/mlx5/mlx5_flow.c| 1192 +++ drivers/net/mlx5/mlx5_prm.h | 70 ++- drivers/net/mlx5/mlx5_rxtx.c| 12 +- drivers/net/mlx5/mlx5_rxtx.h|3 +- drivers/net/mlx5/mlx5_trigger.c |2 + 8 files changed, 1311 insertions(+), 3 deletions(-) create mode 100644 drivers/net/mlx5/mlx5_flow.c -- 2.1.4
[dpdk-dev] [PATCH v4 4/6] net/mlx5: support VXLAN flow item
Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 72 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 549da6c..1ec0ef5 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -69,6 +69,9 @@ mlx5_flow_create_udp(const struct rte_flow_item *item, void *data); static int mlx5_flow_create_tcp(const struct rte_flow_item *item, void *data); +static int +mlx5_flow_create_vxlan(const struct rte_flow_item *item, void *data); + struct rte_flow { LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ @@ -123,7 +126,8 @@ static const enum rte_flow_action_type valid_actions[] = { static const struct mlx5_flow_items mlx5_flow_items[] = { [RTE_FLOW_ITEM_TYPE_VOID] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_VOID, - RTE_FLOW_ITEM_TYPE_ETH), + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_VXLAN), .actions = valid_actions, .mask = &(const struct rte_flow_item_eth){ .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", @@ -196,6 +200,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6), }, [RTE_FLOW_ITEM_TYPE_UDP] = { + .items = ITEMS(RTE_FLOW_ITEM_TYPE_VXLAN), .actions = valid_actions, .mask = &(const struct rte_flow_item_udp){ .hdr = { @@ -219,12 +224,23 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .convert = mlx5_flow_create_tcp, .dst_sz = sizeof(struct ibv_exp_flow_spec_tcp_udp), }, + [RTE_FLOW_ITEM_TYPE_VXLAN] = { + .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH), + .actions = valid_actions, + .mask = &(const struct rte_flow_item_vxlan){ + .vni = "\xff\xff\xff", + }, + .mask_sz = sizeof(struct rte_flow_item_vxlan), + .convert = mlx5_flow_create_vxlan, + .dst_sz = sizeof(struct ibv_exp_flow_spec_tunnel), + }, }; /** Structure to pass to the conversion function. */ struct mlx5_flow { struct ibv_exp_flow_attr *ibv_attr; /**< Verbs attribute. */ unsigned int offset; /**< Offset in bytes in the ibv_attr buffer. */ + uint32_t inner; /**< Set once VXLAN is encountered. */ }; struct mlx5_flow_action { @@ -474,7 +490,7 @@ mlx5_flow_create_eth(const struct rte_flow_item *item, void *data) eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *eth = (struct ibv_exp_flow_spec_eth) { - .type = IBV_EXP_FLOW_SPEC_ETH, + .type = flow->inner | IBV_EXP_FLOW_SPEC_ETH, .size = eth_size, }; if (spec) { @@ -541,7 +557,7 @@ mlx5_flow_create_ipv4(const struct rte_flow_item *item, void *data) ipv4 = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *ipv4 = (struct ibv_exp_flow_spec_ipv4) { - .type = IBV_EXP_FLOW_SPEC_IPV4, + .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV4, .size = ipv4_size, }; if (spec) { @@ -584,7 +600,7 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item, void *data) ipv6 = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *ipv6 = (struct ibv_exp_flow_spec_ipv6) { - .type = IBV_EXP_FLOW_SPEC_IPV6, + .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6, .size = ipv6_size, }; if (spec) { @@ -628,7 +644,7 @@ mlx5_flow_create_udp(const struct rte_flow_item *item, void *data) udp = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *udp = (struct ibv_exp_flow_spec_tcp_udp) { - .type = IBV_EXP_FLOW_SPEC_UDP, + .type = flow->inner | IBV_EXP_FLOW_SPEC_UDP, .size = udp_size, }; if (spec) { @@ -666,7 +682,7 @@ mlx5_flow_create_tcp(const struct rte_flow_item *item, void *data) tcp = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *tcp = (struct ibv_exp_flow_spec_tcp_udp) { - .type = IBV_EXP_FLOW_SPEC_TCP, + .type = flow->inner | IBV_EXP_FLOW_SPEC_TCP, .size = tcp_size, }; if (spec) { @@ -686,6 +702,49 @@ mlx5_flow_create_tcp(const struct rte_flow_item *item, void *data) } /** + * Convert VXLAN item to Verbs specification. + * + * @param item[in] + * Item specification. + * @param data[in, out] + * User structure. + */ +stati
[dpdk-dev] [PATCH v4 6/6] net/mlx5: extend IPv4 flow item
This commits adds: - Type of service - Next protocol ID Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 22 +++--- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 01f7a77..77021b5 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -172,11 +172,13 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .hdr = { .src_addr = -1, .dst_addr = -1, + .type_of_service = -1, + .next_proto_id = -1, }, }, .mask_sz = sizeof(struct rte_flow_item_ipv4), .convert = mlx5_flow_create_ipv4, - .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv4), + .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv4_ext), }, [RTE_FLOW_ITEM_TYPE_IPV6] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP, @@ -574,29 +576,35 @@ mlx5_flow_create_ipv4(const struct rte_flow_item *item, void *data) const struct rte_flow_item_ipv4 *spec = item->spec; const struct rte_flow_item_ipv4 *mask = item->mask; struct mlx5_flow *flow = (struct mlx5_flow *)data; - struct ibv_exp_flow_spec_ipv4 *ipv4; - unsigned int ipv4_size = sizeof(struct ibv_exp_flow_spec_ipv4); + struct ibv_exp_flow_spec_ipv4_ext *ipv4; + unsigned int ipv4_size = sizeof(struct ibv_exp_flow_spec_ipv4_ext); ipv4 = (void *)((uintptr_t)flow->ibv_attr + flow->offset); - *ipv4 = (struct ibv_exp_flow_spec_ipv4) { - .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV4, + *ipv4 = (struct ibv_exp_flow_spec_ipv4_ext) { + .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV4_EXT, .size = ipv4_size, }; if (spec) { - ipv4->val = (struct ibv_exp_flow_ipv4_filter){ + ipv4->val = (struct ibv_exp_flow_ipv4_ext_filter){ .src_ip = spec->hdr.src_addr, .dst_ip = spec->hdr.dst_addr, + .proto = spec->hdr.next_proto_id, + .tos = spec->hdr.type_of_service, }; } if (mask) { - ipv4->mask = (struct ibv_exp_flow_ipv4_filter){ + ipv4->mask = (struct ibv_exp_flow_ipv4_ext_filter){ .src_ip = mask->hdr.src_addr, .dst_ip = mask->hdr.dst_addr, + .proto = mask->hdr.next_proto_id, + .tos = mask->hdr.type_of_service, }; } /* Remove unwanted bits from values. */ ipv4->val.src_ip &= ipv4->mask.src_ip; ipv4->val.dst_ip &= ipv4->mask.dst_ip; + ipv4->val.proto &= ipv4->mask.proto; + ipv4->val.tos &= ipv4->mask.tos; ++flow->ibv_attr->num_of_specs; flow->ibv_attr->priority = 1; return 0; -- 2.1.4
[dpdk-dev] [PATCH v4 5/6] net/mlx5: support mark flow action
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 1ec0ef5..01f7a77 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, void *data); @@ -81,6 +82,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. */ @@ -119,6 +121,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, }; @@ -246,7 +249,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. */ }; /** @@ -341,6 +346,7 @@ priv_flow_validate(struct priv *priv, struct mlx5_flow_action action = { .queue = 0, .drop = 0, + .mark = 0, }; (void)priv; @@ -427,10 +433,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"); @@ -745,6 +767,30 @@ mlx5_flow_create_vxlan(const struct rte_flow_item *item, void *data) } /** + * 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 @@ -800,8 +846,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, @@ -917,6 +965,8 @@ priv_flow_create(struct priv *priv, action = (struct mlx5_flow_action){ .queue = 0, .drop
[dpdk-dev] [PATCH v5 0/6] net/mlx5: support flow API
Changes in v5: - Fix masking when only spec is present in item structure. - Fix first element of flow items array. Changes in v4: - Simplify flow parsing by using a graph. - Add VXLAN flow item. - Add mark flow action. - Extend IPv4 filter item (Type of service, Next Protocol ID). Changes in v3: - Fix Ethernet ether type issue. Changes in v2: - Fix several issues. - Support VLAN filtering. Nelio Laranjeiro (6): net/mlx5: add preliminary flow API support net/mlx5: support basic flow items and actions net/mlx5: support VLAN flow item net/mlx5: support VXLAN flow item net/mlx5: support mark flow action net/mlx5: extend IPv4 flow item drivers/net/mlx5/Makefile |1 + drivers/net/mlx5/mlx5.h | 19 + drivers/net/mlx5/mlx5_fdir.c| 15 + drivers/net/mlx5/mlx5_flow.c| 1248 +++ drivers/net/mlx5/mlx5_prm.h | 70 ++- drivers/net/mlx5/mlx5_rxtx.c| 12 +- drivers/net/mlx5/mlx5_rxtx.h|3 +- drivers/net/mlx5/mlx5_trigger.c |2 + 8 files changed, 1367 insertions(+), 3 deletions(-) create mode 100644 drivers/net/mlx5/mlx5_flow.c -- 2.1.4
[dpdk-dev] [PATCH v5 1/6] net/mlx5: add preliminary flow API support
Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/Makefile| 1 + drivers/net/mlx5/mlx5.h | 16 ++ drivers/net/mlx5/mlx5_fdir.c | 15 ++ drivers/net/mlx5/mlx5_flow.c | 124 +++ 4 files changed, 156 insertions(+) create mode 100644 drivers/net/mlx5/mlx5_flow.c diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index cf87f0b..6d1338a 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -48,6 +48,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_stats.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rss.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_fdir.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mr.c +SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow.c # Dependencies. DEPDIRS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += lib/librte_ether diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 79b7a60..04f4eaa 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -59,6 +59,7 @@ #include #include #include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -268,4 +269,19 @@ void priv_fdir_enable(struct priv *); int mlx5_dev_filter_ctrl(struct rte_eth_dev *, enum rte_filter_type, enum rte_filter_op, void *); +/* mlx5_flow.c */ + +int mlx5_flow_validate(struct rte_eth_dev *, const struct rte_flow_attr *, + const struct rte_flow_item [], + const struct rte_flow_action [], + struct rte_flow_error *); +struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, + const struct rte_flow_attr *, + const struct rte_flow_item [], + const struct rte_flow_action [], + struct rte_flow_error *); +int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, + struct rte_flow_error *); +int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); + #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_fdir.c b/drivers/net/mlx5/mlx5_fdir.c index 1acf682..f80c58b 100644 --- a/drivers/net/mlx5/mlx5_fdir.c +++ b/drivers/net/mlx5/mlx5_fdir.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include #ifdef PEDANTIC #pragma GCC diagnostic error "-Wpedantic" #endif @@ -1042,6 +1044,14 @@ priv_fdir_ctrl_func(struct priv *priv, enum rte_filter_op filter_op, void *arg) return ret; } +static const struct rte_flow_ops mlx5_flow_ops = { + .validate = mlx5_flow_validate, + .create = mlx5_flow_create, + .destroy = mlx5_flow_destroy, + .flush = mlx5_flow_flush, + .query = NULL, +}; + /** * Manage filter operations. * @@ -1067,6 +1077,11 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev, struct priv *priv = dev->data->dev_private; switch (filter_type) { + case RTE_ETH_FILTER_GENERIC: + if (filter_op != RTE_ETH_FILTER_GET) + return -EINVAL; + *(const void **)arg = &mlx5_flow_ops; + return 0; case RTE_ETH_FILTER_FDIR: priv_lock(priv); ret = priv_fdir_ctrl_func(priv, filter_op, arg); diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c new file mode 100644 index 000..4fdefa0 --- /dev/null +++ b/drivers/net/mlx5/mlx5_flow.c @@ -0,0 +1,124 @@ +/*- + * BSD LICENSE + * + * Copyright 2016 6WIND S.A. + * Copyright 2016 Mellanox. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON A
[dpdk-dev] [PATCH v5 2/6] net/mlx5: support basic flow items and actions
Introduce initial software for rte_flow rules. VLAN, VXLAN are still not supported. Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5.h | 3 + drivers/net/mlx5/mlx5_flow.c| 954 ++-- drivers/net/mlx5/mlx5_trigger.c | 2 + 3 files changed, 930 insertions(+), 29 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 04f4eaa..c415ce3 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -136,6 +136,7 @@ struct priv { unsigned int reta_idx_n; /* RETA index size. */ struct fdir_filter_list *fdir_filter_list; /* Flow director rules. */ struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */ + LIST_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ uint32_t link_speed_capa; /* Link speed capabilities. */ rte_spinlock_t lock; /* Lock for control functions. */ }; @@ -283,5 +284,7 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, struct rte_flow_error *); int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); +int priv_flow_start(struct priv *); +void priv_flow_stop(struct priv *); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 4fdefa0..4f6696e 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -31,12 +31,387 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include +#include + +/* Verbs header. */ +/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ +#ifdef PEDANTIC +#pragma GCC diagnostic ignored "-Wpedantic" +#endif +#include +#ifdef PEDANTIC +#pragma GCC diagnostic error "-Wpedantic" +#endif + #include #include #include +#include #include "mlx5.h" +static int +mlx5_flow_create_eth(const struct rte_flow_item *item, +const void *default_mask, +void *data); + +static int +mlx5_flow_create_ipv4(const struct rte_flow_item *item, + const void *default_mask, + void *data); + +static int +mlx5_flow_create_ipv6(const struct rte_flow_item *item, + const void *default_mask, + void *data); + +static int +mlx5_flow_create_udp(const struct rte_flow_item *item, +const void *default_mask, +void *data); + +static int +mlx5_flow_create_tcp(const struct rte_flow_item *item, +const void *default_mask, +void *data); + +struct rte_flow { + LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ + struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ + struct ibv_exp_rwq_ind_table *ind_table; /**< Indirection table. */ + struct ibv_qp *qp; /**< Verbs queue pair. */ + struct ibv_exp_flow *ibv_flow; /**< Verbs 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. */ +}; + +/** Static initializer for items. */ +#define ITEMS(...) \ + (const enum rte_flow_item_type []){ \ + __VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \ + } + +/** Structure to generate a simple graph of layers supported by the NIC. */ +struct mlx5_flow_items { + /** List of possible actions for these items. */ + const enum rte_flow_action_type *const actions; + /** Bit-masks corresponding to the possibilities for the item. */ + const void *mask; + /** Bit-masks size in bytes. */ + const unsigned int mask_sz; + /** +* Conversion function from rte_flow to NIC specific flow. +* +* @param item +* rte_flow item to convert. +* @param default_mask +* Default bit-masks to use when item->mask is not provided. +* @param data +* Internal structure to store the conversion. +* +* @return +* 0 on success, negative value otherwise. +*/ + int (*convert)(const struct rte_flow_item *item, + const void *default_mask, + void *data); + /** Size in bytes of the destination structure. */ + const unsigned int dst_sz; + /** List of possible following items. */ + const enum rte_flow_item_type *const items; +}; + +/** Valid action for this PMD. */ +static const enum rte_flow_action_type valid_actions[] = { + RTE_FLOW_ACTION_TYPE_DROP, + RTE_FLOW_ACTION_TYPE_QUEUE, + RTE_FLOW_ACTION_TYPE_END, +}; + +/** Graph of supported items and associated actions. */ +static const struct mlx5_flow_items mlx5_flow_items[] = { +
[dpdk-dev] [PATCH v5 3/6] net/mlx5: support VLAN flow item
Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 62 +++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 4f6696e..8f2f4d5 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -57,6 +57,11 @@ mlx5_flow_create_eth(const struct rte_flow_item *item, void *data); static int +mlx5_flow_create_vlan(const struct rte_flow_item *item, + const void *default_mask, + void *data); + +static int mlx5_flow_create_ipv4(const struct rte_flow_item *item, const void *default_mask, void *data); @@ -136,7 +141,8 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH), }, [RTE_FLOW_ITEM_TYPE_ETH] = { - .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4, + .items = ITEMS(RTE_FLOW_ITEM_TYPE_VLAN, + RTE_FLOW_ITEM_TYPE_IPV4, RTE_FLOW_ITEM_TYPE_IPV6), .actions = valid_actions, .mask = &(const struct rte_flow_item_eth){ @@ -147,6 +153,17 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .convert = mlx5_flow_create_eth, .dst_sz = sizeof(struct ibv_exp_flow_spec_eth), }, + [RTE_FLOW_ITEM_TYPE_VLAN] = { + .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_IPV6), + .actions = valid_actions, + .mask = &(const struct rte_flow_item_vlan){ + .tci = -1, + }, + .mask_sz = sizeof(struct rte_flow_item_vlan), + .convert = mlx5_flow_create_vlan, + .dst_sz = 0, + }, [RTE_FLOW_ITEM_TYPE_IPV4] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_TCP), @@ -355,6 +372,17 @@ priv_flow_validate(struct priv *priv, if (items->type == RTE_FLOW_ITEM_TYPE_VOID) continue; + /* Handle special situation for VLAN. */ + if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) { + if (((const struct rte_flow_item_vlan *)items)->tci > + ETHER_MAX_VLAN_ID) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + items, + "wrong VLAN id value"); + return -rte_errno; + } + } for (i = 0; cur_item->items && cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END; @@ -481,6 +509,38 @@ mlx5_flow_create_eth(const struct rte_flow_item *item, } /** + * Convert VLAN item to Verbs specification. + * + * @param item[in] + * Item specification. + * @param default_mask[in] + * Default bit-masks to use when item->mask is not provided. + * @param data[in, out] + * User structure. + */ +static int +mlx5_flow_create_vlan(const struct rte_flow_item *item, + const void *default_mask, + void *data) +{ + const struct rte_flow_item_vlan *spec = item->spec; + const struct rte_flow_item_vlan *mask = item->mask; + struct mlx5_flow *flow = (struct mlx5_flow *)data; + struct ibv_exp_flow_spec_eth *eth; + const unsigned int eth_size = sizeof(struct ibv_exp_flow_spec_eth); + + eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset - eth_size); + if (!spec) + return 0; + if (!mask) + mask = default_mask; + eth->val.vlan_tag = spec->tci; + eth->mask.vlan_tag = mask->tci; + eth->val.vlan_tag &= eth->mask.vlan_tag; + return 0; +} + +/** * Convert IPv4 item to Verbs specification. * * @param item[in] -- 2.1.4
[dpdk-dev] [PATCH v5 5/6] net/mlx5: support mark flow action
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, +
[dpdk-dev] [PATCH v5 6/6] net/mlx5: extend IPv4 flow item
This commits adds: - Type of service - Next protocol ID Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 40 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 0e7ea99..d7ed686 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -111,6 +111,12 @@ struct mlx5_flow_items { const enum rte_flow_action_type *const actions; /** Bit-masks corresponding to the possibilities for the item. */ const void *mask; + /** +* Default bit-masks to use when item->mask is not provided. When +* \default_mask is also NULL, the full supported bit-mask (\mask) is +* used instead. +*/ + const void *default_mask; /** Bit-masks size in bytes. */ const unsigned int mask_sz; /** @@ -181,11 +187,19 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .hdr = { .src_addr = -1, .dst_addr = -1, + .type_of_service = -1, + .next_proto_id = -1, + }, + }, + .default_mask = &(const struct rte_flow_item_ipv4){ + .hdr = { + .src_addr = -1, + .dst_addr = -1, }, }, .mask_sz = sizeof(struct rte_flow_item_ipv4), .convert = mlx5_flow_create_ipv4, - .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv4), + .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv4_ext), }, [RTE_FLOW_ITEM_TYPE_IPV6] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP, @@ -425,7 +439,11 @@ priv_flow_validate(struct priv *priv, if (err) goto exit_item_not_supported; if (flow->ibv_attr && cur_item->convert) { - err = cur_item->convert(items, cur_item->mask, flow); + err = cur_item->convert(items, + (cur_item->default_mask ? +cur_item->default_mask : +cur_item->mask), + flow); if (err) goto exit_item_not_supported; } @@ -598,31 +616,37 @@ mlx5_flow_create_ipv4(const struct rte_flow_item *item, const struct rte_flow_item_ipv4 *spec = item->spec; const struct rte_flow_item_ipv4 *mask = item->mask; struct mlx5_flow *flow = (struct mlx5_flow *)data; - struct ibv_exp_flow_spec_ipv4 *ipv4; - unsigned int ipv4_size = sizeof(struct ibv_exp_flow_spec_ipv4); + struct ibv_exp_flow_spec_ipv4_ext *ipv4; + unsigned int ipv4_size = sizeof(struct ibv_exp_flow_spec_ipv4_ext); ++flow->ibv_attr->num_of_specs; flow->ibv_attr->priority = 1; ipv4 = (void *)((uintptr_t)flow->ibv_attr + flow->offset); - *ipv4 = (struct ibv_exp_flow_spec_ipv4) { - .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV4, + *ipv4 = (struct ibv_exp_flow_spec_ipv4_ext) { + .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV4_EXT, .size = ipv4_size, }; if (!spec) return 0; if (!mask) mask = default_mask; - ipv4->val = (struct ibv_exp_flow_ipv4_filter){ + ipv4->val = (struct ibv_exp_flow_ipv4_ext_filter){ .src_ip = spec->hdr.src_addr, .dst_ip = spec->hdr.dst_addr, + .proto = spec->hdr.next_proto_id, + .tos = spec->hdr.type_of_service, }; - ipv4->mask = (struct ibv_exp_flow_ipv4_filter){ + ipv4->mask = (struct ibv_exp_flow_ipv4_ext_filter){ .src_ip = mask->hdr.src_addr, .dst_ip = mask->hdr.dst_addr, + .proto = mask->hdr.next_proto_id, + .tos = mask->hdr.type_of_service, }; /* Remove unwanted bits from values. */ ipv4->val.src_ip &= ipv4->mask.src_ip; ipv4->val.dst_ip &= ipv4->mask.dst_ip; + ipv4->val.proto &= ipv4->mask.proto; + ipv4->val.tos &= ipv4->mask.tos; return 0; } -- 2.1.4
[dpdk-dev] [PATCH v5 4/6] net/mlx5: support VXLAN flow item
Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 78 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 8f2f4d5..093c140 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -81,6 +81,11 @@ mlx5_flow_create_tcp(const struct rte_flow_item *item, const void *default_mask, void *data); +static int +mlx5_flow_create_vxlan(const struct rte_flow_item *item, + const void *default_mask, + void *data); + struct rte_flow { LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ @@ -138,7 +143,8 @@ static const enum rte_flow_action_type valid_actions[] = { /** Graph of supported items and associated actions. */ static const struct mlx5_flow_items mlx5_flow_items[] = { [RTE_FLOW_ITEM_TYPE_END] = { - .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH), + .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_VXLAN), }, [RTE_FLOW_ITEM_TYPE_ETH] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_VLAN, @@ -203,6 +209,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6), }, [RTE_FLOW_ITEM_TYPE_UDP] = { + .items = ITEMS(RTE_FLOW_ITEM_TYPE_VXLAN), .actions = valid_actions, .mask = &(const struct rte_flow_item_udp){ .hdr = { @@ -226,12 +233,23 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .convert = mlx5_flow_create_tcp, .dst_sz = sizeof(struct ibv_exp_flow_spec_tcp_udp), }, + [RTE_FLOW_ITEM_TYPE_VXLAN] = { + .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH), + .actions = valid_actions, + .mask = &(const struct rte_flow_item_vxlan){ + .vni = "\xff\xff\xff", + }, + .mask_sz = sizeof(struct rte_flow_item_vxlan), + .convert = mlx5_flow_create_vxlan, + .dst_sz = sizeof(struct ibv_exp_flow_spec_tunnel), + }, }; /** Structure to pass to the conversion function. */ struct mlx5_flow { struct ibv_exp_flow_attr *ibv_attr; /**< Verbs attribute. */ unsigned int offset; /**< Offset in bytes in the ibv_attr buffer. */ + uint32_t inner; /**< Set once VXLAN is encountered. */ }; struct mlx5_flow_action { @@ -489,7 +507,7 @@ mlx5_flow_create_eth(const struct rte_flow_item *item, flow->ibv_attr->priority = 2; eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *eth = (struct ibv_exp_flow_spec_eth) { - .type = IBV_EXP_FLOW_SPEC_ETH, + .type = flow->inner | IBV_EXP_FLOW_SPEC_ETH, .size = eth_size, }; if (!spec) @@ -565,7 +583,7 @@ mlx5_flow_create_ipv4(const struct rte_flow_item *item, flow->ibv_attr->priority = 1; ipv4 = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *ipv4 = (struct ibv_exp_flow_spec_ipv4) { - .type = IBV_EXP_FLOW_SPEC_IPV4, + .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV4, .size = ipv4_size, }; if (!spec) @@ -612,7 +630,7 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item, flow->ibv_attr->priority = 1; ipv6 = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *ipv6 = (struct ibv_exp_flow_spec_ipv6) { - .type = IBV_EXP_FLOW_SPEC_IPV6, + .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6, .size = ipv6_size, }; if (!spec) @@ -660,7 +678,7 @@ mlx5_flow_create_udp(const struct rte_flow_item *item, flow->ibv_attr->priority = 0; udp = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *udp = (struct ibv_exp_flow_spec_tcp_udp) { - .type = IBV_EXP_FLOW_SPEC_UDP, + .type = flow->inner | IBV_EXP_FLOW_SPEC_UDP, .size = udp_size, }; if (!spec) @@ -702,7 +720,7 @@ mlx5_flow_create_tcp(const struct rte_flow_item *item, flow->ibv_attr->priority = 0; tcp = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *tcp = (struct ibv_exp_flow_spec_tcp_udp) { - .type = IBV_EXP_FLOW_SPEC_TCP, + .type = flow->inner | IBV_EXP_FLOW_SPEC_TCP, .size = tcp_size, }; if (!spec) @@ -720,6 +738,53 @@ mlx5_flow_create_tcp(const struct rte_flow_item *item, } /** + * Convert VXLAN item to Verbs specification.
[dpdk-dev] [PATCH] net/mlx5: fix MTU update
Changing the MTU is not related to changing the number of segments, activating or not the multi-segment support should be handled by the application. Fixes: 9964b965ad69 ("net/mlx5: re-add Rx scatter support") Cc: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_ethdev.c | 127 ++--- drivers/net/mlx5/mlx5_rxq.c| 67 -- drivers/net/mlx5/mlx5_rxtx.h | 1 - 3 files changed, 16 insertions(+), 179 deletions(-) diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index 08cc814..b0eb3cd 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -924,12 +924,6 @@ mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete) /** * DPDK callback to change the MTU. * - * Setting the MTU affects hardware MRU (packets larger than the MTU cannot be - * received). Use this as a hint to enable/disable scattered packets support - * and improve performance when not needed. - * Since failure is not an option, reconfiguring queues on the fly is not - * recommended. - * * @param dev * Pointer to Ethernet device structure. * @param in_mtu @@ -942,122 +936,33 @@ int mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) { struct priv *priv = dev->data->dev_private; + uint16_t kern_mtu; int ret = 0; - unsigned int i; - unsigned int max_frame_len; - int rehash; - int restart = priv->started; if (mlx5_is_secondary()) return -E_RTE_SECONDARY; priv_lock(priv); + ret = priv_get_mtu(priv, &kern_mtu); + if (ret) + goto out; /* Set kernel interface MTU first. */ - if (priv_set_mtu(priv, mtu)) { - ret = errno; - WARN("cannot set port %u MTU to %u: %s", priv->port, mtu, -strerror(ret)); + ret = priv_set_mtu(priv, mtu); + if (ret) goto out; - } else + ret = priv_get_mtu(priv, &kern_mtu); + if (ret) + goto out; + if (kern_mtu == mtu) { + priv->mtu = mtu; DEBUG("adapter port %u MTU set to %u", priv->port, mtu); - /* Temporarily replace RX handler with a fake one, assuming it has not -* been copied elsewhere. */ - dev->rx_pkt_burst = removed_rx_burst; - /* Make sure everyone has left dev->rx_pkt_burst() and uses -* removed_rx_burst() instead. */ - rte_wmb(); - usleep(1000); - /* MTU does not include header and CRC. */ - max_frame_len = ETHER_HDR_LEN + mtu + ETHER_CRC_LEN; - /* Check if at least one queue is going to need a SGE update. */ - for (i = 0; i != priv->rxqs_n; ++i) { - struct rxq *rxq = (*priv->rxqs)[i]; - unsigned int mb_len; - unsigned int size = RTE_PKTMBUF_HEADROOM + max_frame_len; - unsigned int sges_n; - - if (rxq == NULL) - continue; - mb_len = rte_pktmbuf_data_room_size(rxq->mp); - assert(mb_len >= RTE_PKTMBUF_HEADROOM); - /* -* Determine the number of SGEs needed for a full packet -* and round it to the next power of two. -*/ - sges_n = log2above((size / mb_len) + !!(size % mb_len)); - if (sges_n != rxq->sges_n) - break; } - /* -* If all queues have the right number of SGEs, a simple rehash -* of their buffers is enough, otherwise SGE information can only -* be updated in a queue by recreating it. All resources that depend -* on queues (flows, indirection tables) must be recreated as well in -* that case. -*/ - rehash = (i == priv->rxqs_n); - if (!rehash) { - /* Clean up everything as with mlx5_dev_stop(). */ - priv_special_flow_disable_all(priv); - priv_mac_addrs_disable(priv); - priv_destroy_hash_rxqs(priv); - priv_fdir_disable(priv); - priv_dev_interrupt_handler_uninstall(priv, dev); - } -recover: - /* Reconfigure each RX queue. */ - for (i = 0; (i != priv->rxqs_n); ++i) { - struct rxq *rxq = (*priv->rxqs)[i]; - struct rxq_ctrl *rxq_ctrl = - container_of(rxq, struct rxq_ctrl, rxq); - unsigned int mb_len; - unsigned int tmp; - - if (rxq == NULL) - continue; - mb_len = rte_pktmbuf_data_room_size(rxq->mp); - assert(mb_len >= RTE_PKTMBUF_HEADROOM); - /* Provide new values to rxq_setup(). */ - dev->data->dev_conf.rxmode.jumbo_frame = -
[dpdk-dev] [PATCH 1/5] net/mlx5: warn which Tx/Rx burst function is selected
Warning the user helps to understand way the performances does not match the expected values. Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_ethdev.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index b0eb3cd..a233a73 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -1516,17 +1516,17 @@ priv_select_tx_function(struct priv *priv) priv->dev->tx_pkt_burst = mlx5_tx_burst_raw_vec; else priv->dev->tx_pkt_burst = mlx5_tx_burst_vec; - DEBUG("selected Enhanced MPW TX vectorized function"); + INFO("selected Enhanced MPW TX vectorized function"); } else { priv->dev->tx_pkt_burst = mlx5_tx_burst_empw; - DEBUG("selected Enhanced MPW TX function"); + INFO("selected Enhanced MPW TX function"); } } else if (priv->mps && priv->txq_inline) { priv->dev->tx_pkt_burst = mlx5_tx_burst_mpw_inline; - DEBUG("selected MPW inline TX function"); + INFO("selected MPW inline TX function"); } else if (priv->mps) { priv->dev->tx_pkt_burst = mlx5_tx_burst_mpw; - DEBUG("selected MPW TX function"); + INFO("selected MPW TX function"); } } @@ -1542,7 +1542,7 @@ priv_select_rx_function(struct priv *priv) if (priv_check_vec_rx_support(priv) > 0) { priv_prep_vec_rx_function(priv); priv->dev->rx_pkt_burst = mlx5_rx_burst_vec; - DEBUG("selected RX vectorized function"); + INFO("selected RX vectorized function"); } else { priv->dev->rx_pkt_burst = mlx5_rx_burst; } -- 2.1.4
[dpdk-dev] [PATCH 3/5] net/mlx5: avoid reusing old queue's mbuf on reconfigure
This patch prepare the merge of fake mbuf allocation needed by the vector code with rxq_alloc_elts() where all mbuf of the queues should be allocated. Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_rxq.c | 21 - 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index 118a2d9..b54d7b0 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -675,16 +675,12 @@ rxq_trim_elts(struct rxq *rxq) * Pointer to RX queue structure. * @param elts_n * Number of elements to allocate. - * @param[in] pool - * If not NULL, fetch buffers from this array instead of allocating them - * with rte_pktmbuf_alloc(). * * @return * 0 on success, errno value on failure. */ static int -rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n, - struct rte_mbuf *(*pool)[]) +rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n) { const unsigned int sges_n = 1 << rxq_ctrl->rxq.sges_n; unsigned int i; @@ -696,15 +692,8 @@ rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n, volatile struct mlx5_wqe_data_seg *scat = &(*rxq_ctrl->rxq.wqes)[i]; - if (pool != NULL) { - buf = (*pool)[i]; - assert(buf != NULL); - rte_pktmbuf_reset(buf); - rte_pktmbuf_refcnt_update(buf, 1); - } else - buf = rte_pktmbuf_alloc(rxq_ctrl->rxq.mp); + buf = rte_pktmbuf_alloc(rxq_ctrl->rxq.mp); if (buf == NULL) { - assert(pool == NULL); ERROR("%p: empty mbuf pool", (void *)rxq_ctrl); ret = ENOMEM; goto error; @@ -736,7 +725,6 @@ rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n, assert(ret == 0); return 0; error: - assert(pool == NULL); elts_n = i; for (i = 0; (i != elts_n); ++i) { if ((*rxq_ctrl->rxq.elts)[i] != NULL) @@ -1074,15 +1062,14 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl, (void *)dev, strerror(ret)); goto error; } - /* Reuse buffers from original queue if possible. */ if (rxq_ctrl->rxq.elts_n) { assert(1 << rxq_ctrl->rxq.elts_n == desc); assert(rxq_ctrl->rxq.elts != tmpl.rxq.elts); ret = rxq_trim_elts(&rxq_ctrl->rxq); if (!ret) - ret = rxq_alloc_elts(&tmpl, desc, rxq_ctrl->rxq.elts); + ret = rxq_alloc_elts(&tmpl, desc); } else - ret = rxq_alloc_elts(&tmpl, desc, NULL); + ret = rxq_alloc_elts(&tmpl, desc); if (ret) { ERROR("%p: RXQ allocation failed: %s", (void *)dev, strerror(ret)); -- 2.1.4
[dpdk-dev] [PATCH 0/5] net/mlx5: enable/disable vPMD and some cleanups
This series add more information and flexibility to the user to use or not the vPMD. An information will be printed to inform the user which Tx/Rx function have been automatically selected in addition, new device parameters are added to disable Tx/Rx vector (see device documentation for more details). Nelio Laranjeiro (5): net/mlx5: warn which Tx/Rx burst function is selected net/mlx5: add parameters to enable/disable vector code net/mlx5: avoid reusing old queue's mbuf on reconfigure net/mlx5: prepare vector Rx ring at setup time net/mlx5: cleanup Rx ring in free functions doc/guides/nics/mlx5.rst | 14 drivers/net/mlx5/mlx5.c | 23 +++ drivers/net/mlx5/mlx5.h | 2 + drivers/net/mlx5/mlx5_ethdev.c | 11 ++- drivers/net/mlx5/mlx5_rxq.c | 129 +++ drivers/net/mlx5/mlx5_rxtx.c | 6 -- drivers/net/mlx5/mlx5_rxtx.h | 4 +- drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 47 ++--- 8 files changed, 107 insertions(+), 129 deletions(-) -- 2.1.4
[dpdk-dev] [PATCH 2/5] net/mlx5: add parameters to enable/disable vector code
Helps to deactivate the vector function without re-compiling the code. Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- doc/guides/nics/mlx5.rst | 14 ++ drivers/net/mlx5/mlx5.c | 23 +++ drivers/net/mlx5/mlx5.h | 2 ++ drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 9 +++-- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index a68b7ad..fca2132 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -225,6 +225,20 @@ Run-time configuration Disabled by default. +- ``tx_vec_en`` parameter [int] + + A nonzero value enables Tx vector on ConnectX-5 only NIC if the number of + global Tx queues on the port is lesser than MLX5_VPMD_MIN_TXQS. + + Enabled by default on ConnectX-5. + +- ``rx_vec_en`` parameter [int] + + A nonzero value enables Rx vector if the port is not configured in + multi-segment otherwise this parameter is ignored. + + Enabled by default. + Prerequisites - diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 757c910..b7e5046 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -94,6 +94,12 @@ /* Device parameter to enable hardware TSO offload. */ #define MLX5_TSO "tso" +/* Device parameter to enable hardware Tx vector. */ +#define MLX5_TX_VEC_EN "tx_vec_en" + +/* Device parameter to enable hardware Rx vector. */ +#define MLX5_RX_VEC_EN "rx_vec_en" + /* Default PMD specific parameter value. */ #define MLX5_ARG_UNSET (-1) @@ -105,6 +111,8 @@ struct mlx5_args { int mpw_hdr_dseg; int inline_max_packet_sz; int tso; + int tx_vec_en; + int rx_vec_en; }; /** * Retrieve integer value from environment variable. @@ -324,6 +332,10 @@ mlx5_args_check(const char *key, const char *val, void *opaque) args->inline_max_packet_sz = tmp; } else if (strcmp(MLX5_TSO, key) == 0) { args->tso = !!tmp; + } else if (strcmp(MLX5_TX_VEC_EN, key) == 0) { + args->tx_vec_en = !!tmp; + } else if (strcmp(MLX5_RX_VEC_EN, key) == 0) { + args->rx_vec_en = !!tmp; } else { WARN("%s: unknown parameter", key); return -EINVAL; @@ -353,6 +365,8 @@ mlx5_args(struct mlx5_args *args, struct rte_devargs *devargs) MLX5_TXQ_MPW_HDR_DSEG_EN, MLX5_TXQ_MAX_INLINE_LEN, MLX5_TSO, + MLX5_TX_VEC_EN, + MLX5_RX_VEC_EN, NULL, }; struct rte_kvargs *kvlist; @@ -408,6 +422,10 @@ mlx5_args_assign(struct priv *priv, struct mlx5_args *args) priv->inline_max_packet_sz = args->inline_max_packet_sz; if (args->tso != MLX5_ARG_UNSET) priv->tso = args->tso; + if (args->tx_vec_en != MLX5_ARG_UNSET) + priv->tx_vec_en = args->tx_vec_en; + if (args->rx_vec_en != MLX5_ARG_UNSET) + priv->rx_vec_en = args->rx_vec_en; } /** @@ -553,6 +571,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) .mpw_hdr_dseg = MLX5_ARG_UNSET, .inline_max_packet_sz = MLX5_ARG_UNSET, .tso = MLX5_ARG_UNSET, + .tx_vec_en = MLX5_ARG_UNSET, + .rx_vec_en = MLX5_ARG_UNSET, }; exp_device_attr.comp_mask = @@ -615,6 +635,9 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->mps = mps; /* Enable MPW by default if supported. */ priv->cqe_comp = 1; /* Enable compression by default. */ priv->tunnel_en = tunnel_en; + /* Enable vector by default if supported. */ + priv->tx_vec_en = 1; + priv->rx_vec_en = 1; err = mlx5_args(&args, pci_dev->device.devargs); if (err) { ERROR("failed to process device arguments: %s", diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index f16f778..43c5384 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -131,6 +131,8 @@ struct priv { unsigned int tso:1; /* Whether TSO is supported. */ unsigned int tunnel_en:1; unsigned int isolated:1; /* Whether isolated mode is enabled. */ + unsigned int tx_vec_en:1; /* Whether Tx vector is enabled. */ + unsigned int rx_vec_en:1; /* Whether Rx vector is enabled. */ /* Whether Tx offloads for tunneled packets are supported. */ unsigned int max_tso_payload_sz; /* Maximum TCP payload for TSO. */ unsigned int txq_inline; /* Maximum packet size for inlining. */ diff --git a/drivers/net/mlx5/mlx5_rxtx_vec_s
[dpdk-dev] [PATCH 4/5] net/mlx5: prepare vector Rx ring at setup time
To use the vector, it needs to add to the PMD Rx mbuf ring four extra mbuf to avoid memory corruption. This additional mbuf are added on dev_start() whereas all other mbuf are allocated on queue setup. This patch brings this allocation back to the same place as other mbuf allocation. Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_ethdev.c | 1 - drivers/net/mlx5/mlx5_rxq.c | 43 drivers/net/mlx5/mlx5_rxtx.c | 6 - drivers/net/mlx5/mlx5_rxtx.h | 1 - drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 38 --- 5 files changed, 34 insertions(+), 55 deletions(-) diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index a233a73..ad5b28a 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -1540,7 +1540,6 @@ void priv_select_rx_function(struct priv *priv) { if (priv_check_vec_rx_support(priv) > 0) { - priv_prep_vec_rx_function(priv); priv->dev->rx_pkt_burst = mlx5_rx_burst_vec; INFO("selected RX vectorized function"); } else { diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index b54d7b0..c90ec81 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -720,6 +720,27 @@ rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n) }; (*rxq_ctrl->rxq.elts)[i] = buf; } + if (rxq_check_vec_support(&rxq_ctrl->rxq) > 0) { + struct rxq *rxq = &rxq_ctrl->rxq; + struct rte_mbuf *mbuf_init = &rxq->fake_mbuf; + + assert(rxq->elts_n == rxq->cqe_n); + /* Initialize default rearm_data for vPMD. */ + mbuf_init->data_off = RTE_PKTMBUF_HEADROOM; + rte_mbuf_refcnt_set(mbuf_init, 1); + mbuf_init->nb_segs = 1; + mbuf_init->port = rxq->port_id; + /* +* prevent compiler reordering: +* rearm_data covers previous fields. +*/ + rte_compiler_barrier(); + rxq->mbuf_initializer = *(uint64_t *)&mbuf_init->rearm_data; + /* Padding with a fake mbuf for vectorized Rx. */ + for (i = 0; i < MLX5_VPMD_DESCS_PER_LOOP; ++i) + (*rxq->elts)[elts_n + i] = &rxq->fake_mbuf; + rxq->trim_elts = 1; + } DEBUG("%p: allocated and configured %u segments (max %u packets)", (void *)rxq_ctrl, elts_n, elts_n / (1 << rxq_ctrl->rxq.sges_n)); assert(ret == 0); @@ -799,9 +820,11 @@ rxq_setup(struct rxq_ctrl *tmpl) struct ibv_cq *ibcq = tmpl->cq; struct ibv_mlx5_cq_info cq_info; struct mlx5_rwq *rwq = container_of(tmpl->wq, struct mlx5_rwq, wq); - struct rte_mbuf *(*elts)[1 << tmpl->rxq.elts_n] = + const uint16_t desc_n = + (1 << tmpl->rxq.elts_n) + tmpl->priv->rx_vec_en * + MLX5_VPMD_DESCS_PER_LOOP; + struct rte_mbuf *(*elts)[desc_n] = rte_calloc_socket("RXQ", 1, sizeof(*elts), 0, tmpl->socket); - if (ibv_mlx5_exp_get_cq_info(ibcq, &cq_info)) { ERROR("Unable to query CQ info. check your OFED."); return ENOTSUP; @@ -871,7 +894,9 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl, } attr; unsigned int mb_len = rte_pktmbuf_data_room_size(mp); unsigned int cqe_n = desc - 1; - struct rte_mbuf *(*elts)[desc] = NULL; + const uint16_t desc_n = + desc + priv->rx_vec_en * MLX5_VPMD_DESCS_PER_LOOP; + struct rte_mbuf *(*elts)[desc_n] = NULL; int ret = 0; (void)conf; /* Thresholds configuration (ignored). */ @@ -1129,7 +1154,8 @@ mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, struct priv *priv = dev->data->dev_private; struct rxq *rxq = (*priv->rxqs)[idx]; struct rxq_ctrl *rxq_ctrl = container_of(rxq, struct rxq_ctrl, rxq); - const uint16_t desc_pad = MLX5_VPMD_DESCS_PER_LOOP; /* For vPMD. */ + const uint16_t desc_n = + desc + priv->rx_vec_en * MLX5_VPMD_DESCS_PER_LOOP; int ret; if (mlx5_is_secondary()) @@ -1162,9 +1188,8 @@ mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, /* Resize if rxq size is changed. */ if (rxq_ctrl->rxq.elts_n != log2above(desc)) { rxq_ctrl = rte_realloc(rxq_ctrl, - sizeof(*rxq_ctrl) + - (desc + desc_pad) * -
[dpdk-dev] [PATCH 5/5] net/mlx5: cleanup Rx ring in free functions
Vector PMD returns buffers to the application without setting the pointers in the Rx queue to null nor allocating them. When the PMD cleanup the ring it needs to take a special care to those pointers to not free the mbufs before the application have used them nor if the application have already freed them. Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_rxq.c | 71 +--- drivers/net/mlx5/mlx5_rxtx.h | 3 +- 2 files changed, 21 insertions(+), 53 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index c90ec81..68dce04 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -634,41 +634,6 @@ priv_rehash_flows(struct priv *priv) } /** - * Unlike regular Rx function, vPMD Rx doesn't replace mbufs immediately when - * receiving packets. Instead it replaces later in bulk. In rxq->elts[], entries - * from rq_pi to rq_ci are owned by device but the rest is already delivered to - * application. In order not to reuse those mbufs by rxq_alloc_elts(), this - * function must be called to replace used mbufs. - * - * @param rxq - * Pointer to RX queue structure. - * - * @return - * 0 on success, errno value on failure. - */ -static int -rxq_trim_elts(struct rxq *rxq) -{ - const uint16_t q_n = (1 << rxq->elts_n); - const uint16_t q_mask = q_n - 1; - uint16_t used = q_n - (rxq->rq_ci - rxq->rq_pi); - uint16_t i; - - if (!rxq->trim_elts) - return 0; - for (i = 0; i < used; ++i) { - struct rte_mbuf *buf; - buf = rte_pktmbuf_alloc(rxq->mp); - if (!buf) - return ENOMEM; - (*rxq->elts)[(rxq->rq_ci + i) & q_mask] = buf; - } - rxq->rq_pi = rxq->rq_ci; - rxq->trim_elts = 0; - return 0; -} - -/** * Allocate RX queue elements. * * @param rxq_ctrl @@ -739,7 +704,6 @@ rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n) /* Padding with a fake mbuf for vectorized Rx. */ for (i = 0; i < MLX5_VPMD_DESCS_PER_LOOP; ++i) (*rxq->elts)[elts_n + i] = &rxq->fake_mbuf; - rxq->trim_elts = 1; } DEBUG("%p: allocated and configured %u segments (max %u packets)", (void *)rxq_ctrl, elts_n, elts_n / (1 << rxq_ctrl->rxq.sges_n)); @@ -766,16 +730,28 @@ rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n) static void rxq_free_elts(struct rxq_ctrl *rxq_ctrl) { - unsigned int i; + struct rxq *rxq = &rxq_ctrl->rxq; + const uint16_t q_n = (1 << rxq->elts_n); + const uint16_t q_mask = q_n - 1; + uint16_t used = q_n - (rxq->rq_ci - rxq->rq_pi); + uint16_t i; DEBUG("%p: freeing WRs", (void *)rxq_ctrl); - if (rxq_ctrl->rxq.elts == NULL) + if (rxq->elts == NULL) return; - - for (i = 0; (i != (1u << rxq_ctrl->rxq.elts_n)); ++i) { - if ((*rxq_ctrl->rxq.elts)[i] != NULL) - rte_pktmbuf_free_seg((*rxq_ctrl->rxq.elts)[i]); - (*rxq_ctrl->rxq.elts)[i] = NULL; + /** +* Some mbuf in the Ring belongs to the application. They cannot be +* freed. +*/ + if (rxq_check_vec_support(rxq) > 0) { + for (i = 0; i < used; ++i) + (*rxq->elts)[(rxq->rq_ci + i) & q_mask] = NULL; + rxq->rq_pi = rxq->rq_ci; + } + for (i = 0; (i != (1u << rxq->elts_n)); ++i) { + if ((*rxq->elts)[i] != NULL) + rte_pktmbuf_free_seg((*rxq->elts)[i]); + (*rxq->elts)[i] = NULL; } } @@ -1087,14 +1063,7 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl, (void *)dev, strerror(ret)); goto error; } - if (rxq_ctrl->rxq.elts_n) { - assert(1 << rxq_ctrl->rxq.elts_n == desc); - assert(rxq_ctrl->rxq.elts != tmpl.rxq.elts); - ret = rxq_trim_elts(&rxq_ctrl->rxq); - if (!ret) - ret = rxq_alloc_elts(&tmpl, desc); - } else - ret = rxq_alloc_elts(&tmpl, desc); + ret = rxq_alloc_elts(&tmpl, desc); if (ret) { ERROR("%p: RXQ allocation failed: %s", (void *)dev, strerror(ret)); diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h index 690b308..300d097 100644 --- a/drivers/net/mlx5/mlx5_rxtx.h +++ b/drivers/net/mlx5/mlx5_rxtx.h @@ -116,8 +116,7 @@ struct rxq { unsigned int rss_hash:1; /* RSS hash result is enabled. */ unsigned int mark:1;
[dpdk-dev] [PATCH 1/5] net/mlx5: remove flow drop useless if branches
Those two if statements are useless as there is a verification on the drop field of the flow to jump to the end of the function just above. Signed-off-by: Nelio Laranjeiro Acked-by: Shahaf Shuler --- drivers/net/mlx5/mlx5_flow.c | 4 1 file changed, 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 86be929..d62ccff 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -1279,10 +1279,6 @@ priv_flow_destroy(struct priv *priv, claim_zero(ibv_destroy_qp(flow->qp)); if (flow->ind_table) claim_zero(ibv_exp_destroy_rwq_ind_table(flow->ind_table)); - if (flow->drop && flow->wq) - claim_zero(ibv_exp_destroy_wq(flow->wq)); - if (flow->drop && flow->cq) - claim_zero(ibv_destroy_cq(flow->cq)); if (flow->mark) { struct rte_flow *tmp; struct rxq *rxq; -- 2.1.4
[dpdk-dev] [PATCH 0/5] net/mlx5: cleanups
This Series make some cleanup in mlx5 PMD by removing useless code or non working code. This series apply on top of: [PATCH 0/5] net/mlx5: enable/disable vPMD and some cleanups Specifically on patch: net/mlx5: cleanup Rx ring in free functions http://dpdk.org/dev/patchwork/patch/27303/ Nelio Laranjeiro (5): net/mlx5: remove flow drop useless if branches net/mlx5: remove pdentic pragma net/mlx5: fix non working secondary process by removing it net/mlx5: remove multiple drop RSS queues net/mlx5: remove old MLNX_OFED 3.3 verification drivers/net/mlx5/Makefile| 5 - drivers/net/mlx5/mlx5.c | 40 +--- drivers/net/mlx5/mlx5.h | 21 - drivers/net/mlx5/mlx5_ethdev.c | 173 +-- drivers/net/mlx5/mlx5_fdir.c | 7 -- drivers/net/mlx5/mlx5_flow.c | 59 drivers/net/mlx5/mlx5_mac.c | 7 -- drivers/net/mlx5/mlx5_mr.c | 7 -- drivers/net/mlx5/mlx5_rss.c | 7 -- drivers/net/mlx5/mlx5_rxmode.c | 7 -- drivers/net/mlx5/mlx5_rxq.c | 48 -- drivers/net/mlx5/mlx5_rxtx.c | 7 -- drivers/net/mlx5/mlx5_rxtx.h | 9 -- drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 7 -- drivers/net/mlx5/mlx5_stats.c| 7 -- drivers/net/mlx5/mlx5_trigger.c | 7 -- drivers/net/mlx5/mlx5_txq.c | 48 -- drivers/net/mlx5/mlx5_vlan.c | 7 -- 18 files changed, 21 insertions(+), 452 deletions(-) -- 2.1.4
[dpdk-dev] [PATCH 3/5] net/mlx5: fix non working secondary process by removing it
Secondary process is a copy/paste of the mlx4 drivers, it was never tested and it even segfault at the secondary process start in the mlx5_pci_probe(). This makes more sense to wipe this non working feature to re-write a working and functional version. Fixes: a48deada651b ("mlx5: allow operation in secondary processes") Signed-off-by: Nelio Laranjeiro Acked-by: Shahaf Shuler --- drivers/net/mlx5/mlx5.c| 33 +--- drivers/net/mlx5/mlx5.h| 9 --- drivers/net/mlx5/mlx5_ethdev.c | 166 + drivers/net/mlx5/mlx5_rxq.c| 41 -- drivers/net/mlx5/mlx5_rxtx.h | 2 - drivers/net/mlx5/mlx5_txq.c| 41 -- 6 files changed, 4 insertions(+), 288 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index bfcff70..bd66a7c 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -771,37 +771,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) err = ENOMEM; goto port_error; } - - /* Secondary processes have to use local storage for their -* private data as well as a copy of eth_dev->data, but this -* pointer must not be modified before burst functions are -* actually called. */ - if (mlx5_is_secondary()) { - struct mlx5_secondary_data *sd = - &mlx5_secondary_data[eth_dev->data->port_id]; - sd->primary_priv = eth_dev->data->dev_private; - if (sd->primary_priv == NULL) { - ERROR("no private data for port %u", - eth_dev->data->port_id); - err = EINVAL; - goto port_error; - } - sd->shared_dev_data = eth_dev->data; - rte_spinlock_init(&sd->lock); - memcpy(sd->data.name, sd->shared_dev_data->name, - sizeof(sd->data.name)); - sd->data.dev_private = priv; - sd->data.rx_mbuf_alloc_failed = 0; - sd->data.mtu = ETHER_MTU; - sd->data.port_id = sd->shared_dev_data->port_id; - sd->data.mac_addrs = priv->mac; - eth_dev->tx_pkt_burst = mlx5_tx_burst_secondary_setup; - eth_dev->rx_pkt_burst = mlx5_rx_burst_secondary_setup; - } else { - eth_dev->data->dev_private = priv; - eth_dev->data->mac_addrs = priv->mac; - } - + eth_dev->data->dev_private = priv; + eth_dev->data->mac_addrs = priv->mac; eth_dev->device = &pci_dev->device; rte_eth_copy_pci_info(eth_dev, pci_dev); eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE; diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 31d0c49..2392be5 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -158,14 +158,6 @@ struct priv { rte_spinlock_t lock; /* Lock for control functions. */ }; -/* Local storage for secondary process data. */ -struct mlx5_secondary_data { - struct rte_eth_dev_data data; /* Local device data. */ - struct priv *primary_priv; /* Private structure from primary. */ - struct rte_eth_dev_data *shared_dev_data; /* Shared device data. */ - rte_spinlock_t lock; /* Port configuration lock. */ -} mlx5_secondary_data[RTE_MAX_ETHPORTS]; - /** * Lock private structure to protect it from concurrent access in the * control path. @@ -221,7 +213,6 @@ void priv_dev_interrupt_handler_uninstall(struct priv *, struct rte_eth_dev *); void priv_dev_interrupt_handler_install(struct priv *, struct rte_eth_dev *); int mlx5_set_link_down(struct rte_eth_dev *dev); int mlx5_set_link_up(struct rte_eth_dev *dev); -struct priv *mlx5_secondary_data_setup(struct priv *priv); void priv_select_tx_function(struct priv *); void priv_select_rx_function(struct priv *); diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index 36872b5..0e0a99e 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -126,12 +126,7 @@ struct ethtool_link_settings { struct priv * mlx5_get_priv(struct rte_eth_dev *dev) { - struct mlx5_secondary_data *sd; - - if (!mlx5_is_secondary()) - return dev->data->dev_private; - sd = &mlx5_secondary_data[dev->data->port_id]; - return sd->data.dev_private; + return dev->data->dev_private; }
[dpdk-dev] [PATCH 4/5] net/mlx5: remove multiple drop RSS queues
Since MLNX_OFED 4.1 this code is no more useful. Signed-off-by: Nelio Laranjeiro Acked-by: Shahaf Shuler --- drivers/net/mlx5/Makefile| 5 drivers/net/mlx5/mlx5_flow.c | 55 ++-- 2 files changed, 17 insertions(+), 43 deletions(-) diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index 8736de5..14b739a 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -104,11 +104,6 @@ mlx5_autoconf.h.new: FORCE mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh $Q $(RM) -f -- '$@' $Q sh -- '$<' '$@' \ - HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP \ - infiniband/verbs_exp.h \ - enum IBV_EXP_FLOW_SPEC_ACTION_DROP \ - $(AUTOCONF_OUTPUT) - $Q sh -- '$<' '$@' \ HAVE_VERBS_IBV_EXP_CQ_COMPRESSED_CQE \ infiniband/verbs_exp.h \ enum IBV_EXP_CQ_COMPRESSED_CQE \ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index d62ccff..7dd3ebb 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -52,13 +52,6 @@ #include "mlx5.h" #include "mlx5_prm.h" -/* Number of Work Queue necessary for the DROP queue. */ -#ifndef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP -#define MLX5_DROP_WQ_N 4 -#else -#define MLX5_DROP_WQ_N 1 -#endif - static int mlx5_flow_create_eth(const struct rte_flow_item *item, const void *default_mask, @@ -290,7 +283,7 @@ struct mlx5_flow { struct rte_flow_drop { struct ibv_exp_rwq_ind_table *ind_table; /**< Indirection table. */ struct ibv_qp *qp; /**< Verbs queue pair. */ - struct ibv_exp_wq *wqs[MLX5_DROP_WQ_N]; /**< Verbs work queue. */ + struct ibv_exp_wq *wq; /**< Verbs work queue. */ struct ibv_cq *cq; /**< Verbs completion queue. */ }; @@ -580,10 +573,8 @@ priv_flow_validate(struct priv *priv, } if (action->mark && !flow->ibv_attr && !action->drop) flow->offset += sizeof(struct ibv_exp_flow_spec_action_tag); -#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP if (!flow->ibv_attr && action->drop) flow->offset += sizeof(struct ibv_exp_flow_spec_action_drop); -#endif if (!action->queue && !action->drop) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "no valid action"); @@ -1001,10 +992,8 @@ priv_flow_create_action_queue_drop(struct priv *priv, struct rte_flow_error *error) { struct rte_flow *rte_flow; -#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP struct ibv_exp_flow_spec_action_drop *drop; unsigned int size = sizeof(struct ibv_exp_flow_spec_action_drop); -#endif assert(priv->pd); assert(priv->ctx); @@ -1015,7 +1004,6 @@ priv_flow_create_action_queue_drop(struct priv *priv, return NULL; } rte_flow->drop = 1; -#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_DROP drop = (void *)((uintptr_t)flow->ibv_attr + flow->offset); *drop = (struct ibv_exp_flow_spec_action_drop){ .type = IBV_EXP_FLOW_SPEC_ACTION_DROP, @@ -1023,7 +1011,6 @@ priv_flow_create_action_queue_drop(struct priv *priv, }; ++flow->ibv_attr->num_of_specs; flow->offset += sizeof(struct ibv_exp_flow_spec_action_drop); -#endif rte_flow->ibv_attr = flow->ibv_attr; if (!priv->started) return rte_flow; @@ -1386,7 +1373,6 @@ static int priv_flow_create_drop_queue(struct priv *priv) { struct rte_flow_drop *fdq = NULL; - unsigned int i; assert(priv->pd); assert(priv->ctx); @@ -1403,25 +1389,23 @@ priv_flow_create_drop_queue(struct priv *priv) WARN("cannot allocate CQ for drop queue"); goto error; } - for (i = 0; i != MLX5_DROP_WQ_N; ++i) { - fdq->wqs[i] = ibv_exp_create_wq(priv->ctx, - &(struct ibv_exp_wq_init_attr){ - .wq_type = IBV_EXP_WQT_RQ, - .max_recv_wr = 1, - .max_recv_sge = 1, - .pd = priv->pd, - .cq = fdq->cq, - }); - if (!fdq->wqs[i]) { - WARN("cannot allocate WQ for drop queue"); - goto error; - } + fdq->wq = ibv_exp_create_wq(priv->ctx, + &(struct ibv_exp_wq_init_attr){ + .wq_type = IBV_EXP_WQT_RQ, +
[dpdk-dev] [PATCH 2/5] net/mlx5: remove pdentic pragma
Those are useless since DPDK headers have been cleaned up. Signed-off-by: Nelio Laranjeiro Acked-by: Shahaf Shuler --- drivers/net/mlx5/mlx5.c | 7 --- drivers/net/mlx5/mlx5.h | 7 --- drivers/net/mlx5/mlx5_ethdev.c | 7 --- drivers/net/mlx5/mlx5_fdir.c | 7 --- drivers/net/mlx5/mlx5_mac.c | 7 --- drivers/net/mlx5/mlx5_mr.c | 7 --- drivers/net/mlx5/mlx5_rss.c | 7 --- drivers/net/mlx5/mlx5_rxmode.c | 7 --- drivers/net/mlx5/mlx5_rxq.c | 7 --- drivers/net/mlx5/mlx5_rxtx.c | 7 --- drivers/net/mlx5/mlx5_rxtx.h | 7 --- drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 7 --- drivers/net/mlx5/mlx5_stats.c| 7 --- drivers/net/mlx5/mlx5_trigger.c | 7 --- drivers/net/mlx5/mlx5_txq.c | 7 --- drivers/net/mlx5/mlx5_vlan.c | 7 --- 16 files changed, 112 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index b7e5046..bfcff70 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -50,19 +50,12 @@ #pragma GCC diagnostic error "-Wpedantic" #endif -/* DPDK headers don't like -pedantic. */ -#ifdef PEDANTIC -#pragma GCC diagnostic ignored "-Wpedantic" -#endif #include #include #include #include #include #include -#ifdef PEDANTIC -#pragma GCC diagnostic error "-Wpedantic" -#endif #include "mlx5.h" #include "mlx5_utils.h" diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 43c5384..31d0c49 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -50,10 +50,6 @@ #pragma GCC diagnostic error "-Wpedantic" #endif -/* DPDK headers don't like -pedantic. */ -#ifdef PEDANTIC -#pragma GCC diagnostic ignored "-Wpedantic" -#endif #include #include #include @@ -61,9 +57,6 @@ #include #include #include -#ifdef PEDANTIC -#pragma GCC diagnostic error "-Wpedantic" -#endif #include "mlx5_utils.h" #include "mlx5_rxtx.h" diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index ad5b28a..36872b5 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -50,10 +50,6 @@ #include #include -/* DPDK headers don't like -pedantic. */ -#ifdef PEDANTIC -#pragma GCC diagnostic ignored "-Wpedantic" -#endif #include #include #include @@ -61,9 +57,6 @@ #include #include #include -#ifdef PEDANTIC -#pragma GCC diagnostic error "-Wpedantic" -#endif #include "mlx5.h" #include "mlx5_rxtx.h" diff --git a/drivers/net/mlx5/mlx5_fdir.c b/drivers/net/mlx5/mlx5_fdir.c index 34a7e69..ad256e4 100644 --- a/drivers/net/mlx5/mlx5_fdir.c +++ b/drivers/net/mlx5/mlx5_fdir.c @@ -47,19 +47,12 @@ #pragma GCC diagnostic error "-Wpedantic" #endif -/* DPDK headers don't like -pedantic. */ -#ifdef PEDANTIC -#pragma GCC diagnostic ignored "-Wpedantic" -#endif #include #include #include #include #include #include -#ifdef PEDANTIC -#pragma GCC diagnostic error "-Wpedantic" -#endif #include "mlx5.h" #include "mlx5_rxtx.h" diff --git a/drivers/net/mlx5/mlx5_mac.c b/drivers/net/mlx5/mlx5_mac.c index 8489ea6..45d23e4 100644 --- a/drivers/net/mlx5/mlx5_mac.c +++ b/drivers/net/mlx5/mlx5_mac.c @@ -51,16 +51,9 @@ #pragma GCC diagnostic error "-Wpedantic" #endif -/* DPDK headers don't like -pedantic. */ -#ifdef PEDANTIC -#pragma GCC diagnostic ignored "-Wpedantic" -#endif #include #include #include -#ifdef PEDANTIC -#pragma GCC diagnostic error "-Wpedantic" -#endif #include "mlx5.h" #include "mlx5_utils.h" diff --git a/drivers/net/mlx5/mlx5_mr.c b/drivers/net/mlx5/mlx5_mr.c index 2873351..9593830 100644 --- a/drivers/net/mlx5/mlx5_mr.c +++ b/drivers/net/mlx5/mlx5_mr.c @@ -41,14 +41,7 @@ #pragma GCC diagnostic error "-Wpedantic" #endif -/* DPDK headers don't like -pedantic. */ -#ifdef PEDANTIC -#pragma GCC diagnostic ignored "-Wpedantic" -#endif #include -#ifdef PEDANTIC -#pragma GCC diagnostic error "-Wpedantic" -#endif #include "mlx5.h" #include "mlx5_rxtx.h" diff --git a/drivers/net/mlx5/mlx5_rss.c b/drivers/net/mlx5/mlx5_rss.c index a2dd7d1..1249943 100644 --- a/drivers/net/mlx5/mlx5_rss.c +++ b/drivers/net/mlx5/mlx5_rss.c @@ -47,15 +47,8 @@ #pragma GCC diagnostic error "-Wpedantic" #endif -/* DPDK headers don't like -pedantic. */ -#ifdef PEDANTIC -#pragma GCC diagnostic ignored "-Wpedantic" -#endif #include #include -#ifdef PEDANTIC -#pragma GCC diagnostic error "-Wpedantic" -#endif #include "mlx5.h" #include "mlx5_rxtx.h" diff --git a/drivers/net/mlx5/mlx5_rxmode.c b/drivers/net/mlx5/mlx5_
[dpdk-dev] [PATCH 5/5] net/mlx5: remove old MLNX_OFED 3.3 verification
This version of MLNX_OFED is no more supported. Signed-off-by: Nelio Laranjeiro Acked-by: Shahaf Shuler --- drivers/net/mlx5/mlx5.h | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 2392be5..e89aba8 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -63,11 +63,6 @@ #include "mlx5_autoconf.h" #include "mlx5_defs.h" -#if !defined(HAVE_VERBS_IBV_EXP_CQ_COMPRESSED_CQE) || \ - !defined(HAVE_VERBS_MLX5_ETH_VLAN_INLINE_HEADER_SIZE) -#error Mellanox OFED >= 3.3 is required, please refer to the documentation. -#endif - enum { PCI_VENDOR_ID_MELLANOX = 0x15b3, }; -- 2.1.4
[dpdk-dev] [PATCH v1 00/21] net/mlx5: cleanup for isolated mode
This series cleanups the control plane part and the way it uses the different kind of objects (DPDK queues, Verbs Queues, ...). It has three goals: 1. Reduce the memory usage by sharing all possible objects. 2. Leave the configuration to the control plane and the creation/destruction of queues to the dev_start/dev_stop() to have a better control on object and easily apply the configuration. 3. Create all flows through the generic flow API, it will also help to implement a detection collision algorithm as all flows are using the same service and thus the same kind of object. Nelio Laranjeiro (21): net/mlx5: merge action and flow parser structure net/mlx5: remove flow director support net/mlx5: prefix Rx queue control structures net/mlx5: prefix Tx control queue structures net/mlx5: remove redundant started flag net/mlx5: verify all flows are been removed on close net/mlx5: add reference counter on memory region net/mlx5: separate DPDK from Verbs Rx queue objects net/mlx5: separate DPDK from Verbs Tx queue objects net/mlx5: add reference counter on DPDK Tx queues net/mlx5: add reference counter on DPDK Rx queues net/mlx5: remove queue drop support net/mlx5: make indirection tables sharable net/mlx5: add Hash Rx queue object net/mlx5: disable priority protection in flows net/mlx5: use flow to enable promiscuous mode net/mlx5: use flow to enable all multi mode net/mlx5: use flow to enable unicast traffic net/mlx5: handle a single RSS hash key for all protocols net/mlx5: remove hash Rx queues support net/mlx5: support RSS hash configuration in generic flow action doc/guides/nics/features/mlx5.ini|1 - doc/guides/nics/mlx5.rst |2 - drivers/net/mlx5/Makefile|1 - drivers/net/mlx5/mlx5.c | 91 +- drivers/net/mlx5/mlx5.h | 85 +- drivers/net/mlx5/mlx5_defs.h |3 - drivers/net/mlx5/mlx5_ethdev.c | 16 +- drivers/net/mlx5/mlx5_fdir.c | 1094 --- drivers/net/mlx5/mlx5_flow.c | 1009 ++ drivers/net/mlx5/mlx5_mac.c | 403 +-- drivers/net/mlx5/mlx5_mr.c | 229 ++-- drivers/net/mlx5/mlx5_rss.c | 127 +-- drivers/net/mlx5/mlx5_rxmode.c | 376 +-- drivers/net/mlx5/mlx5_rxq.c | 1929 -- drivers/net/mlx5/mlx5_rxtx.c | 39 +- drivers/net/mlx5/mlx5_rxtx.h | 285 +++-- drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 35 +- drivers/net/mlx5/mlx5_stats.c|4 +- drivers/net/mlx5/mlx5_trigger.c | 301 +- drivers/net/mlx5/mlx5_txq.c | 711 - drivers/net/mlx5/mlx5_utils.h|2 + drivers/net/mlx5/mlx5_vlan.c | 61 +- 22 files changed, 2695 insertions(+), 4109 deletions(-) delete mode 100644 drivers/net/mlx5/mlx5_fdir.c -- 2.1.4
[dpdk-dev] [PATCH v1] net/mlx5: support RSS hash configuration in generic flow action
This also bring back the RSS support on all flows created by default from the control plane. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 437 ++- 1 file changed, 346 insertions(+), 91 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 8316255..fe21dac 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -87,12 +87,89 @@ mlx5_flow_create_vxlan(const struct rte_flow_item *item, const void *default_mask, void *data); +/* Hash RX queue types. */ +enum hash_rxq_type { + HASH_RXQ_TCPV4, + HASH_RXQ_UDPV4, + HASH_RXQ_IPV4, + HASH_RXQ_TCPV6, + HASH_RXQ_UDPV6, + HASH_RXQ_IPV6, + HASH_RXQ_ETH, +}; + +/* Initialization data for hash RX queue. */ +struct hash_rxq_init { + uint64_t hash_fields; /* Fields that participate in the hash. */ + uint64_t dpdk_rss_hf; /* Matching DPDK RSS hash fields. */ + unsigned int flow_priority; /* Flow priority to use. */ +}; + +/* Initialization data for hash RX queues. */ +const struct hash_rxq_init hash_rxq_init[] = { + [HASH_RXQ_TCPV4] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | + IBV_EXP_RX_HASH_DST_IPV4 | + IBV_EXP_RX_HASH_SRC_PORT_TCP | + IBV_EXP_RX_HASH_DST_PORT_TCP), + .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV4_TCP, + .flow_priority = 4, + }, + [HASH_RXQ_UDPV4] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | + IBV_EXP_RX_HASH_DST_IPV4 | + IBV_EXP_RX_HASH_SRC_PORT_UDP | + IBV_EXP_RX_HASH_DST_PORT_UDP), + .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV4_UDP, + .flow_priority = 4, + }, + [HASH_RXQ_IPV4] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | + IBV_EXP_RX_HASH_DST_IPV4), + .dpdk_rss_hf = (ETH_RSS_IPV4 | + ETH_RSS_FRAG_IPV4), + .flow_priority = 5, + }, + [HASH_RXQ_TCPV6] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 | + IBV_EXP_RX_HASH_DST_IPV6 | + IBV_EXP_RX_HASH_SRC_PORT_TCP | + IBV_EXP_RX_HASH_DST_PORT_TCP), + .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_TCP, + .flow_priority = 4, + }, + [HASH_RXQ_UDPV6] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 | + IBV_EXP_RX_HASH_DST_IPV6 | + IBV_EXP_RX_HASH_SRC_PORT_UDP | + IBV_EXP_RX_HASH_DST_PORT_UDP), + .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_UDP, + .flow_priority = 4, + }, + [HASH_RXQ_IPV6] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 | + IBV_EXP_RX_HASH_DST_IPV6), + .dpdk_rss_hf = (ETH_RSS_IPV6 | + ETH_RSS_FRAG_IPV6), + .flow_priority = 5, + }, + [HASH_RXQ_ETH] = { + .hash_fields = 0, + .dpdk_rss_hf = 0, + .flow_priority = 6, + }, +}; + +/* Number of entries in hash_rxq_init[]. */ +const unsigned int hash_rxq_init_n = RTE_DIM(hash_rxq_init); + struct rte_flow { TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ - struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ - struct ibv_exp_flow *ibv_flow; /**< Verbs flow. */ - struct mlx5_hrxq *hrxq; /**< Hash Rx queue. */ uint32_t mark:1; /**< Set if the flow is marked. */ + struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ + struct mlx5_hrxq *hrxqs[RTE_DIM(hash_rxq_init)]; /**< Hash Rx queues. */ + struct ibv_exp_flow *ibv_flows[RTE_DIM(hash_rxq_init)]; + /**< Verbs flows. */ }; /** Static initializer for items. */ @@ -271,6 +348,7 @@ struct mlx5_flow_action { uint32_t mark_id; /**< Mark identifier. */ uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */ uint16_t queues_n; /**< Number of entries in queue[]. */ + const struct rte_eth_rss_conf *rss_conf; /**< User RSS configuration. */ }; /** Structure to pass to the conversion function. */ @@ -278,7 +356,6 @@ struct mlx5_flow_parse { struct ibv_exp_flow_attr *ibv_attr; /**< Verbs attribute. */ unsigned int offset; /**< Offset in bytes in the ibv_attr buffer. */ uint32_t inner; /**< Set once VXLAN is encountered. */ - uint64_t hash_fields; /**< Fields that participate in the hash. */ struct mlx
[dpdk-dev] [PATCH v1 01/21] net/mlx5: merge action and flow parser structure
mlx5_flow_create() and mlx5_flow_validate() are making common checks. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 151 +-- 1 file changed, 72 insertions(+), 79 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 7dd3ebb..00355f4 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -271,12 +271,23 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { }, }; +/* Structure to parse actions. */ +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 mark_id; /**< Mark identifier. */ + uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */ + uint16_t queues_n; /**< Number of entries in queue[]. */ +}; + /** Structure to pass to the conversion function. */ -struct mlx5_flow { +struct mlx5_flow_parse { struct ibv_exp_flow_attr *ibv_attr; /**< Verbs attribute. */ unsigned int offset; /**< Offset in bytes in the ibv_attr buffer. */ uint32_t inner; /**< Set once VXLAN is encountered. */ uint64_t hash_fields; /**< Fields that participate in the hash. */ + struct mlx5_flow_action actions; /**< Parsed action result. */ }; /** Structure for Drop queue. */ @@ -287,15 +298,6 @@ struct rte_flow_drop { struct ibv_cq *cq; /**< Verbs completion queue. */ }; -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 mark_id; /**< Mark identifier. */ - uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */ - uint16_t queues_n; /**< Number of entries in queue[]. */ -}; - /** * Check support for a given item. * @@ -374,8 +376,6 @@ mlx5_flow_item_validate(const struct rte_flow_item *item, * Perform verbose error reporting if not NULL. * @param[in, out] flow * Flow structure to update. - * @param[in, out] action - * Action structure to update. * * @return * 0 on success, a negative errno value otherwise and rte_errno is set. @@ -386,8 +386,7 @@ priv_flow_validate(struct priv *priv, const struct rte_flow_item items[], const struct rte_flow_action actions[], struct rte_flow_error *error, - struct mlx5_flow *flow, - struct mlx5_flow_action *action) + struct mlx5_flow_parse *flow) { const struct mlx5_flow_items *cur_item = mlx5_flow_items; @@ -469,7 +468,7 @@ priv_flow_validate(struct priv *priv, if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) { continue; } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) { - action->drop = 1; + flow->actions.drop = 1; } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) { const struct rte_flow_action_queue *queue = (const struct rte_flow_action_queue *) @@ -479,13 +478,13 @@ priv_flow_validate(struct priv *priv, if (!queue || (queue->index > (priv->rxqs_n - 1))) goto exit_action_not_supported; - for (n = 0; n < action->queues_n; ++n) { - if (action->queues[n] == queue->index) { + for (n = 0; n < flow->actions.queues_n; ++n) { + if (flow->actions.queues[n] == queue->index) { found = 1; break; } } - if (action->queues_n > 1 && !found) { + if (flow->actions.queues_n > 1 && !found) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions, @@ -493,9 +492,9 @@ priv_flow_validate(struct priv *priv, return -rte_errno; } if (!found) { - action->queue = 1; - action->queues_n = 1; - action->queues[0] = queue->index; + flow->actions.queue = 1; + flow->actions.queues_n = 1; + flow->actions.queues[0] = queue->index;
[dpdk-dev] [PATCH v1 02/21] net/mlx5: remove flow director support
Generic flow API should be use for flow steering as is provides a better and easier way to configure flows. Signed-off-by: Nelio Laranjeiro --- doc/guides/nics/features/mlx5.ini |1 - doc/guides/nics/mlx5.rst |2 - drivers/net/mlx5/Makefile |1 - drivers/net/mlx5/mlx5.c |8 - drivers/net/mlx5/mlx5.h | 12 +- drivers/net/mlx5/mlx5_fdir.c | 1094 - drivers/net/mlx5/mlx5_flow.c | 44 ++ drivers/net/mlx5/mlx5_rxq.c |2 - drivers/net/mlx5/mlx5_rxtx.h |9 - drivers/net/mlx5/mlx5_trigger.c |3 - 10 files changed, 45 insertions(+), 1131 deletions(-) delete mode 100644 drivers/net/mlx5/mlx5_fdir.c diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini index 2913591..327a450 100644 --- a/doc/guides/nics/features/mlx5.ini +++ b/doc/guides/nics/features/mlx5.ini @@ -22,7 +22,6 @@ RSS key update = Y RSS reta update = Y SR-IOV = Y VLAN filter = Y -Flow director= Y Flow API = Y CRC offload = Y VLAN offload = Y diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index f4cb18b..c56f6f0 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -89,8 +89,6 @@ Features - Promiscuous mode. - Multicast promiscuous mode. - Hardware checksum offloads. -- Flow director (RTE_FDIR_MODE_PERFECT, RTE_FDIR_MODE_PERFECT_MAC_VLAN and - RTE_ETH_FDIR_REJECT). - Flow API. - Secondary process TX is supported. - KVM and VMware ESX SR-IOV modes are supported. diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index 14b739a..099e4f0 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -49,7 +49,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rxmode.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_vlan.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_stats.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rss.c -SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_fdir.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mr.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow.c diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index bd66a7c..ef10a22 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -150,10 +150,6 @@ mlx5_dev_close(struct rte_eth_dev *dev) priv_mac_addrs_disable(priv); priv_destroy_hash_rxqs(priv); - /* Remove flow director elements. */ - priv_fdir_disable(priv); - priv_fdir_delete_filters_list(priv); - /* Prevent crashes when queues are still in use. */ dev->rx_pkt_burst = removed_rx_burst; dev->tx_pkt_burst = removed_tx_burst; @@ -739,10 +735,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) claim_zero(priv_mac_addr_add(priv, 0, (const uint8_t (*)[ETHER_ADDR_LEN]) mac.addr_bytes)); - /* Initialize FD filters list. */ - err = fdir_init_filters_list(priv); - if (err) - goto port_error; #ifndef NDEBUG { char ifname[IF_NAMESIZE]; diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index e89aba8..c7194de 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -144,8 +144,6 @@ struct priv { struct rte_intr_handle intr_handle; /* Interrupt handler. */ unsigned int (*reta_idx)[]; /* RETA index table. */ unsigned int reta_idx_n; /* RETA index size. */ - struct fdir_filter_list *fdir_filter_list; /* Flow director rules. */ - struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */ struct rte_flow_drop *flow_drop_queue; /* Flow drop queue. */ TAILQ_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ uint32_t link_speed_capa; /* Link speed capabilities. */ @@ -270,18 +268,10 @@ void mlx5_vlan_strip_queue_set(struct rte_eth_dev *, uint16_t, int); int mlx5_dev_start(struct rte_eth_dev *); void mlx5_dev_stop(struct rte_eth_dev *); -/* mlx5_fdir.c */ +/* mlx5_flow.c */ -void priv_fdir_queue_destroy(struct priv *, struct fdir_queue *); -int fdir_init_filters_list(struct priv *); -void priv_fdir_delete_filters_list(struct priv *); -void priv_fdir_disable(struct priv *); -void priv_fdir_enable(struct priv *); int mlx5_dev_filter_ctrl(struct rte_eth_dev *, enum rte_filter_type, enum rte_filter_op, void *); - -/* mlx5_flow.c */ - int mlx5_flow_validate(struct rte_eth_dev *, const struct rte_flow_attr *, const struct rte_flow_item [], const struct rte_flow_action [], diff --git a/drivers/net/mlx5/mlx5_fdir.c b/drivers/net/mlx5/mlx5_fdir.c deleted file mode 100644 index ad256e4..000 --- a/drivers/net/mlx5/mlx5_fdir.c +++ /dev/null @@ -1,109
[dpdk-dev] [PATCH v1 05/21] net/mlx5: remove redundant started flag
This flag is already present in the Ethernet device. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 1 - drivers/net/mlx5/mlx5_flow.c| 6 +++--- drivers/net/mlx5/mlx5_rxq.c | 2 +- drivers/net/mlx5/mlx5_trigger.c | 12 drivers/net/mlx5/mlx5_txq.c | 2 +- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 155dd76..40c3475 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -103,7 +103,6 @@ struct priv { /* Device properties. */ uint16_t mtu; /* Configured MTU. */ uint8_t port; /* Physical port number. */ - unsigned int started:1; /* Device started, flows enabled. */ unsigned int promisc_req:1; /* Promiscuous mode requested. */ unsigned int allmulti_req:1; /* All multicast mode requested. */ unsigned int hw_csum:1; /* Checksum offload is supported. */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 77b85a6..996fe31 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -1053,7 +1053,7 @@ priv_flow_create_action_queue_drop(struct priv *priv, ++flow->ibv_attr->num_of_specs; flow->offset += sizeof(struct ibv_exp_flow_spec_action_drop); rte_flow->ibv_attr = flow->ibv_attr; - if (!priv->started) + if (!priv->dev->data->dev_started) return rte_flow; rte_flow->qp = priv->flow_drop_queue->qp; rte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp, @@ -1161,7 +1161,7 @@ priv_flow_create_action_queue(struct priv *priv, NULL, "cannot allocate QP"); goto error; } - if (!priv->started) + if (!priv->dev->data->dev_started) return rte_flow; rte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp, rte_flow->ibv_attr); @@ -1627,7 +1627,7 @@ mlx5_flow_isolate(struct rte_eth_dev *dev, struct priv *priv = dev->data->dev_private; priv_lock(priv); - if (priv->started) { + if (dev->data->dev_started) { rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index c09a554..88a024c 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -1140,7 +1140,7 @@ mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc, if (rxq != NULL) { DEBUG("%p: reusing already allocated queue index %u (%p)", (void *)dev, idx, (void *)rxq); - if (priv->started) { + if (dev->data->dev_started) { priv_unlock(priv); return -EEXIST; } diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c index 3b17678..a4a0acd 100644 --- a/drivers/net/mlx5/mlx5_trigger.c +++ b/drivers/net/mlx5/mlx5_trigger.c @@ -61,10 +61,6 @@ mlx5_dev_start(struct rte_eth_dev *dev) return -E_RTE_SECONDARY; priv_lock(priv); - if (priv->started) { - priv_unlock(priv); - return 0; - } /* Update Rx/Tx callback. */ priv_select_tx_function(priv); priv_select_rx_function(priv); @@ -72,8 +68,6 @@ mlx5_dev_start(struct rte_eth_dev *dev) err = priv_create_hash_rxqs(priv); if (!err) err = priv_rehash_flows(priv); - if (!err) - priv->started = 1; else { ERROR("%p: an error occurred while configuring hash RX queues:" " %s", @@ -82,7 +76,6 @@ mlx5_dev_start(struct rte_eth_dev *dev) } err = priv_flow_start(priv); if (err) { - priv->started = 0; ERROR("%p: an error occurred while configuring flows:" " %s", (void *)priv, strerror(err)); @@ -125,10 +118,6 @@ mlx5_dev_stop(struct rte_eth_dev *dev) return; priv_lock(priv); - if (!priv->started) { - priv_unlock(priv); - return; - } DEBUG("%p: cleaning up and destroying hash RX queues", (void *)dev); priv_special_flow_disable_all(priv); priv_mac_addrs_disable(priv); @@ -136,6 +125,5 @@ mlx5_dev_stop(struct rte_eth_dev *dev) priv_flow_stop(priv); priv_rx_intr_vec_disable(priv); priv_dev_interrupt_handler_uninstall(priv, dev); - priv->started = 0; priv_unlock(priv); } diff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c
[dpdk-dev] [PATCH v1 03/21] net/mlx5: prefix Rx queue control structures
Prefix struct rxq_ctrl with mlx5. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 8 ++--- drivers/net/mlx5/mlx5.h | 4 +-- drivers/net/mlx5/mlx5_flow.c | 12 +++ drivers/net/mlx5/mlx5_rxq.c | 61 +++- drivers/net/mlx5/mlx5_rxtx.c | 14 - drivers/net/mlx5/mlx5_rxtx.h | 17 +- drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 21 +++-- drivers/net/mlx5/mlx5_stats.c| 2 +- drivers/net/mlx5/mlx5_vlan.c | 5 +-- 9 files changed, 75 insertions(+), 69 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index ef10a22..d2fa8b1 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -157,14 +157,14 @@ mlx5_dev_close(struct rte_eth_dev *dev) /* XXX race condition if mlx5_rx_burst() is still running. */ usleep(1000); for (i = 0; (i != priv->rxqs_n); ++i) { - struct rxq *rxq = (*priv->rxqs)[i]; - struct rxq_ctrl *rxq_ctrl; + struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; + struct mlx5_rxq_ctrl *rxq_ctrl; if (rxq == NULL) continue; - rxq_ctrl = container_of(rxq, struct rxq_ctrl, rxq); + rxq_ctrl = container_of(rxq, struct mlx5_rxq_ctrl, rxq); (*priv->rxqs)[i] = NULL; - rxq_cleanup(rxq_ctrl); + mlx5_rxq_cleanup(rxq_ctrl); rte_free(rxq_ctrl); } priv->rxqs_n = 0; diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index c7194de..55cea6f 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -129,7 +129,7 @@ struct priv { /* RX/TX queues. */ unsigned int rxqs_n; /* RX queues array size. */ unsigned int txqs_n; /* TX queues array size. */ - struct rxq *(*rxqs)[]; /* RX queues. */ + struct mlx5_rxq_data *(*rxqs)[]; /* RX queues. */ struct txq *(*txqs)[]; /* TX queues. */ /* Indirection tables referencing all RX WQs. */ struct ibv_exp_rwq_ind_table *(*ind_tables)[]; @@ -287,6 +287,6 @@ int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); int mlx5_flow_isolate(struct rte_eth_dev *, int, struct rte_flow_error *); int priv_flow_start(struct priv *); void priv_flow_stop(struct priv *); -int priv_flow_rxq_in_use(struct priv *, struct rxq *); +int priv_flow_rxq_in_use(struct priv *, struct mlx5_rxq_data *); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 545bc8f..77b85a6 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -99,7 +99,7 @@ struct rte_flow { uint32_t mark:1; /**< Set if the flow is marked. */ uint32_t drop:1; /**< Drop queue. */ uint64_t hash_fields; /**< Fields that participate in the hash. */ - struct rxq *rxqs[]; /**< Pointer to the queues array. */ + struct mlx5_rxq_data *rxqs[]; /**< Pointer to the queues array. */ }; /** Static initializer for items. */ @@ -1106,10 +1106,10 @@ priv_flow_create_action_queue(struct priv *priv, return NULL; } for (i = 0; i < flow->actions.queues_n; ++i) { - struct rxq_ctrl *rxq; + struct mlx5_rxq_ctrl *rxq; rxq = container_of((*priv->rxqs)[flow->actions.queues[i]], - struct rxq_ctrl, rxq); + struct mlx5_rxq_ctrl, rxq); wqs[i] = rxq->wq; rte_flow->rxqs[i] = &rxq->rxq; ++rte_flow->rxqs_n; @@ -1305,7 +1305,7 @@ priv_flow_destroy(struct priv *priv, claim_zero(ibv_exp_destroy_rwq_ind_table(flow->ind_table)); if (flow->mark) { struct rte_flow *tmp; - struct rxq *rxq; + struct mlx5_rxq_data *rxq; uint32_t mark_n = 0; uint32_t queue_n; @@ -1325,7 +1325,7 @@ priv_flow_destroy(struct priv *priv, for (tqueue_n = 0; tqueue_n < tmp->rxqs_n; ++tqueue_n) { - struct rxq *trxq; + struct mlx5_rxq_data *trxq; trxq = tmp->rxqs[tqueue_n]; if (rxq == trxq) @@ -1594,7 +1594,7 @@ priv_flow_start(struct priv *priv) * Nonzero if the queue is used by a flow. */ int -priv_flow_rxq_in_use(struct priv *priv, struct rxq *rxq) +priv_flow_rxq_in_use(struct priv *priv, struct mlx5_rxq_data *rxq) { struct rte_
[dpdk-dev] [PATCH v1 04/21] net/mlx5: prefix Tx control queue structures
Prefix struct txq_ctrl with mlx5. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 8 drivers/net/mlx5/mlx5.h | 2 +- drivers/net/mlx5/mlx5_mr.c | 20 +- drivers/net/mlx5/mlx5_rxtx.c | 25 --- drivers/net/mlx5/mlx5_rxtx.h | 29 ++- drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 14 ++--- drivers/net/mlx5/mlx5_stats.c| 2 +- drivers/net/mlx5/mlx5_txq.c | 39 ++-- 8 files changed, 72 insertions(+), 67 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index d2fa8b1..c7bc65f 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -174,14 +174,14 @@ mlx5_dev_close(struct rte_eth_dev *dev) /* XXX race condition if mlx5_tx_burst() is still running. */ usleep(1000); for (i = 0; (i != priv->txqs_n); ++i) { - struct txq *txq = (*priv->txqs)[i]; - struct txq_ctrl *txq_ctrl; + struct mlx5_txq_data *txq = (*priv->txqs)[i]; + struct mlx5_txq_ctrl *txq_ctrl; if (txq == NULL) continue; - txq_ctrl = container_of(txq, struct txq_ctrl, txq); + txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq); (*priv->txqs)[i] = NULL; - txq_cleanup(txq_ctrl); + mlx5_txq_cleanup(txq_ctrl); rte_free(txq_ctrl); } priv->txqs_n = 0; diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 55cea6f..155dd76 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -130,7 +130,7 @@ struct priv { unsigned int rxqs_n; /* RX queues array size. */ unsigned int txqs_n; /* TX queues array size. */ struct mlx5_rxq_data *(*rxqs)[]; /* RX queues. */ - struct txq *(*txqs)[]; /* TX queues. */ + struct mlx5_txq_data *(*txqs)[]; /* TX queues. */ /* Indirection tables referencing all RX WQs. */ struct ibv_exp_rwq_ind_table *(*ind_tables)[]; unsigned int ind_tables_n; /* Number of indirection tables. */ diff --git a/drivers/net/mlx5/mlx5_mr.c b/drivers/net/mlx5/mlx5_mr.c index 9593830..e8adde5 100644 --- a/drivers/net/mlx5/mlx5_mr.c +++ b/drivers/net/mlx5/mlx5_mr.c @@ -175,9 +175,11 @@ mlx5_mp2mr(struct ibv_pd *pd, struct rte_mempool *mp) * mr->lkey on success, (uint32_t)-1 on failure. */ uint32_t -txq_mp2mr_reg(struct txq *txq, struct rte_mempool *mp, unsigned int idx) +mlx5_txq_mp2mr_reg(struct mlx5_txq_data *txq, struct rte_mempool *mp, + unsigned int idx) { - struct txq_ctrl *txq_ctrl = container_of(txq, struct txq_ctrl, txq); + struct mlx5_txq_ctrl *txq_ctrl = + container_of(txq, struct mlx5_txq_ctrl, txq); struct ibv_mr *mr; /* Add a new entry, register MR first. */ @@ -229,8 +231,8 @@ struct txq_mp2mr_mbuf_check_data { * Object index, unused. */ static void -txq_mp2mr_mbuf_check(struct rte_mempool *mp, void *arg, void *obj, - uint32_t index __rte_unused) +mlx5_txq_mp2mr_mbuf_check(struct rte_mempool *mp, void *arg, void *obj, + uint32_t index __rte_unused) { struct txq_mp2mr_mbuf_check_data *data = arg; struct rte_mbuf *buf = obj; @@ -253,9 +255,9 @@ txq_mp2mr_mbuf_check(struct rte_mempool *mp, void *arg, void *obj, * Pointer to TX queue structure. */ void -txq_mp2mr_iter(struct rte_mempool *mp, void *arg) +mlx5_txq_mp2mr_iter(struct rte_mempool *mp, void *arg) { - struct txq_ctrl *txq_ctrl = arg; + struct mlx5_txq_ctrl *txq_ctrl = arg; struct txq_mp2mr_mbuf_check_data data = { .ret = 0, }; @@ -264,8 +266,8 @@ txq_mp2mr_iter(struct rte_mempool *mp, void *arg) unsigned int i; /* Register mempool only if the first element looks like a mbuf. */ - if (rte_mempool_obj_iter(mp, txq_mp2mr_mbuf_check, &data) == 0 || - data.ret == -1) + if (rte_mempool_obj_iter(mp, mlx5_txq_mp2mr_mbuf_check, &data) == 0 || + data.ret == -1) return; if (mlx5_check_mempool(mp, &start, &end) != 0) { ERROR("mempool %p: not virtually contiguous", @@ -283,5 +285,5 @@ txq_mp2mr_iter(struct rte_mempool *mp, void *arg) end <= (uintptr_t)mr->addr + mr->length) return; } - txq_mp2mr_reg(&txq_ctrl->txq, mp, i); + mlx5_txq_mp2mr_reg(&txq_ctrl->txq, mp, i); } diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index cd5182c..986e238 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_
[dpdk-dev] [PATCH v1 06/21] net/mlx5: verify all flows are been removed on close
Debug tools to verify all flows are be un-register from the NIC. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 3 +++ drivers/net/mlx5/mlx5.h | 1 + drivers/net/mlx5/mlx5_flow.c | 22 ++ 3 files changed, 26 insertions(+) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index c7bc65f..0d8ca52 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -200,6 +200,9 @@ mlx5_dev_close(struct rte_eth_dev *dev) } if (priv->reta_idx != NULL) rte_free(priv->reta_idx); + i = priv_flow_verify(priv); + if (i) + WARN("%p: some flows still remain", (void*)priv); priv_unlock(priv); memset(priv, 0, sizeof(*priv)); } diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 40c3475..a5e9aa1 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -287,5 +287,6 @@ int mlx5_flow_isolate(struct rte_eth_dev *, int, struct rte_flow_error *); int priv_flow_start(struct priv *); void priv_flow_stop(struct priv *); int priv_flow_rxq_in_use(struct priv *, struct mlx5_rxq_data *); +int priv_flow_verify(struct priv *); #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 996fe31..bcbb984 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -1639,3 +1639,25 @@ mlx5_flow_isolate(struct rte_eth_dev *dev, priv_unlock(priv); return 0; } + +/** + * Verify the flow list is empty + * + * @param priv + * Pointer to private structure. + * + * @return the number of object not released. + */ +int +priv_flow_verify(struct priv *priv) +{ + struct rte_flow *flow; + int ret = 0; + + TAILQ_FOREACH(flow, &priv->flows, next) { + DEBUG("%p: flow %p still referenced", (void*)priv, + (void*)flow); + ++ret; + } + return ret; +} -- 2.1.4
[dpdk-dev] [PATCH v1 07/21] net/mlx5: add reference counter on memory region
Memory regions becomes shared by the same time, the control plane as it own reference in addition of the Tx/Rx queues. This should also avoid to un-register a memory region when the Tx queue evicts it from its local cache. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 8 ++ drivers/net/mlx5/mlx5_mr.c | 202 ++- drivers/net/mlx5/mlx5_rxq.c | 17 ++-- drivers/net/mlx5/mlx5_rxtx.h | 42 + drivers/net/mlx5/mlx5_txq.c | 8 +- 5 files changed, 186 insertions(+), 91 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index a5e9aa1..1ae5f59 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -145,6 +145,7 @@ struct priv { unsigned int reta_idx_n; /* RETA index size. */ struct rte_flow_drop *flow_drop_queue; /* Flow drop queue. */ TAILQ_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ + LIST_HEAD(mr, mlx5_mr) mr; /* Memory region. */ uint32_t link_speed_capa; /* Link speed capabilities. */ struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */ rte_spinlock_t lock; /* Lock for control functions. */ @@ -289,4 +290,11 @@ void priv_flow_stop(struct priv *); int priv_flow_rxq_in_use(struct priv *, struct mlx5_rxq_data *); int priv_flow_verify(struct priv *); +/* mlx5_mr.c */ + +struct mlx5_mr* priv_mr_new(struct priv *, struct rte_mempool *); +struct mlx5_mr* priv_mr_get(struct priv *, struct rte_mempool *); +int priv_mr_release(struct priv *, struct mlx5_mr *); +int priv_mr_verify(struct priv *); + #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_mr.c b/drivers/net/mlx5/mlx5_mr.c index e8adde5..b5e9500 100644 --- a/drivers/net/mlx5/mlx5_mr.c +++ b/drivers/net/mlx5/mlx5_mr.c @@ -42,6 +42,7 @@ #endif #include +#include #include "mlx5.h" #include "mlx5_rxtx.h" @@ -111,54 +112,6 @@ static int mlx5_check_mempool(struct rte_mempool *mp, uintptr_t *start, } /** - * Register mempool as a memory region. - * - * @param pd - * Pointer to protection domain. - * @param mp - * Pointer to memory pool. - * - * @return - * Memory region pointer, NULL in case of error. - */ -struct ibv_mr * -mlx5_mp2mr(struct ibv_pd *pd, struct rte_mempool *mp) -{ - const struct rte_memseg *ms = rte_eal_get_physmem_layout(); - uintptr_t start; - uintptr_t end; - unsigned int i; - - if (mlx5_check_mempool(mp, &start, &end) != 0) { - ERROR("mempool %p: not virtually contiguous", - (void *)mp); - return NULL; - } - - DEBUG("mempool %p area start=%p end=%p size=%zu", - (void *)mp, (void *)start, (void *)end, - (size_t)(end - start)); - /* Round start and end to page boundary if found in memory segments. */ - for (i = 0; (i < RTE_MAX_MEMSEG) && (ms[i].addr != NULL); ++i) { - uintptr_t addr = (uintptr_t)ms[i].addr; - size_t len = ms[i].len; - unsigned int align = ms[i].hugepage_sz; - - if ((start > addr) && (start < addr + len)) - start = RTE_ALIGN_FLOOR(start, align); - if ((end > addr) && (end < addr + len)) - end = RTE_ALIGN_CEIL(end, align); - } - DEBUG("mempool %p using start=%p end=%p size=%zu for MR", - (void *)mp, (void *)start, (void *)end, - (size_t)(end - start)); - return ibv_reg_mr(pd, - (void *)start, - end - start, - IBV_ACCESS_LOCAL_WRITE); -} - -/** * Register a Memory Region (MR) <-> Memory Pool (MP) association in * txq->mp2mr[]. If mp2mr[] is full, remove an entry first. * @@ -180,12 +133,14 @@ mlx5_txq_mp2mr_reg(struct mlx5_txq_data *txq, struct rte_mempool *mp, { struct mlx5_txq_ctrl *txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq); - struct ibv_mr *mr; + struct mlx5_mr *mr; /* Add a new entry, register MR first. */ DEBUG("%p: discovered new memory pool \"%s\" (%p)", (void *)txq_ctrl, mp->name, (void *)mp); - mr = mlx5_mp2mr(txq_ctrl->priv->pd, mp); + mr = priv_mr_get(txq_ctrl->priv, mp); + if (mr == NULL) + mr = priv_mr_new(txq_ctrl->priv, mp); if (unlikely(mr == NULL)) { DEBUG("%p: unable to configure MR, ibv_reg_mr() failed.", (void *)txq_ctrl); @@ -196,20 +151,17 @@ mlx5_txq_mp2mr_reg(struct mlx5_txq_data *txq, struct rte_mempool *mp, DEBUG("%p: MR <-> MP table full, dropping oldest entry.", (void *)txq_ctrl); --idx; - claim_zero(ibv_dereg_mr(txq_ct
[dpdk-dev] [PATCH v1 09/21] net/mlx5: separate DPDK from Verbs Tx queue objects
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 3 + drivers/net/mlx5/mlx5.h | 1 + drivers/net/mlx5/mlx5_rxtx.h | 18 +- drivers/net/mlx5/mlx5_txq.c | 437 ++- 4 files changed, 284 insertions(+), 175 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index c158d8e..23068ae 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -203,6 +203,9 @@ mlx5_dev_close(struct rte_eth_dev *dev) i = mlx5_priv_rxq_ibv_verify(priv); if (i) WARN("%p: some Verbs Rx queue still remain", (void*)priv); + i = mlx5_priv_txq_ibv_verify(priv); + if (i) + WARN("%p: some Verbs Tx queue still remain", (void*)priv); i = priv_flow_verify(priv); if (i) WARN("%p: some flows still remain", (void*)priv); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 228fd34..25711ef 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -147,6 +147,7 @@ struct priv { TAILQ_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ LIST_HEAD(mr, mlx5_mr) mr; /* Memory region. */ LIST_HEAD(rxqibv, mlx5_rxq_ibv) rxqsibv; /* Verbs Rx queues. */ + LIST_HEAD(txqibv, mlx5_txq_ibv) txqsibv; /* Verbs Tx queues. */ uint32_t link_speed_capa; /* Link speed capabilities. */ struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */ rte_spinlock_t lock; /* Lock for control functions. */ diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h index abdbf6a..f78aa38 100644 --- a/drivers/net/mlx5/mlx5_rxtx.h +++ b/drivers/net/mlx5/mlx5_rxtx.h @@ -283,12 +283,21 @@ struct mlx5_txq_data { struct mlx5_txq_stats stats; /* TX queue counters. */ } __rte_cache_aligned; +/* Verbs Rx queue elements. */ +struct mlx5_txq_ibv { + LIST_ENTRY(mlx5_txq_ibv) next; /* Pointer to the next element. */ + rte_atomic32_t refcnt; /* Reference counter. */ + struct ibv_cq *cq; /* Completion Queue. */ + struct ibv_qp *qp; /* Queue Pair. */ +}; + /* TX queue control descriptor. */ struct mlx5_txq_ctrl { struct priv *priv; /* Back pointer to private data. */ - struct ibv_cq *cq; /* Completion Queue. */ - struct ibv_qp *qp; /* Queue Pair. */ unsigned int socket; /* CPU socket ID for allocations. */ + unsigned int max_inline_data; /* Max inline data. */ + unsigned int max_tso_header; /* Max TSO header size. */ + struct mlx5_txq_ibv *ibv; /* Verbs queue object. */ struct mlx5_txq_data txq; /* Data path structure. */ }; @@ -333,6 +342,11 @@ int mlx5_txq_ctrl_setup(struct rte_eth_dev *, struct mlx5_txq_ctrl *, uint16_t, int mlx5_tx_queue_setup(struct rte_eth_dev *, uint16_t, uint16_t, unsigned int, const struct rte_eth_txconf *); void mlx5_tx_queue_release(void *); +struct mlx5_txq_ibv* mlx5_priv_txq_ibv_new(struct priv *priv, uint16_t idx); +struct mlx5_txq_ibv* mlx5_priv_txq_ibv_get(struct priv *priv, uint16_t idx); +int mlx5_priv_txq_ibv_release(struct priv *priv, struct mlx5_txq_ibv *txq); +int mlx5_priv_txq_ibv_releasable(struct priv *priv, struct mlx5_txq_ibv *txq); +int mlx5_priv_txq_ibv_verify(struct priv *priv); /* mlx5_rxtx.c */ diff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c index ce826dd..570eb67 100644 --- a/drivers/net/mlx5/mlx5_txq.c +++ b/drivers/net/mlx5/mlx5_txq.c @@ -73,13 +73,6 @@ txq_alloc_elts(struct mlx5_txq_ctrl *txq_ctrl, unsigned int elts_n) for (i = 0; (i != elts_n); ++i) (*txq_ctrl->txq.elts)[i] = NULL; - for (i = 0; (i != (1u << txq_ctrl->txq.wqe_n)); ++i) { - volatile struct mlx5_wqe64 *wqe = - (volatile struct mlx5_wqe64 *) - txq_ctrl->txq.wqes + i; - - memset((void *)(uintptr_t)wqe, 0x0, sizeof(*wqe)); - } DEBUG("%p: allocated and configured %u WRs", (void *)txq_ctrl, elts_n); txq_ctrl->txq.elts_head = 0; txq_ctrl->txq.elts_tail = 0; @@ -136,60 +129,15 @@ mlx5_txq_cleanup(struct mlx5_txq_ctrl *txq_ctrl) DEBUG("cleaning up %p", (void *)txq_ctrl); txq_free_elts(txq_ctrl); - if (txq_ctrl->qp != NULL) - claim_zero(ibv_destroy_qp(txq_ctrl->qp)); - if (txq_ctrl->cq != NULL) - claim_zero(ibv_destroy_cq(txq_ctrl->cq)); for (i = 0; (i != RTE_DIM(txq_ctrl->txq.mp2mr)); ++i) if (txq_ctrl->txq.mp2mr[i]) priv_mr_release(txq_ctrl->priv, txq_ctrl->txq.mp2mr[i]); + if (txq_ctrl->ibv) + mlx5_priv_txq_ibv_release(txq_ctrl->priv, txq_ctrl->ibv); memset(txq_ctrl, 0, sizeof(*txq_ctrl)); } /** - * Initialize TX queue. - * - * @param tmpl - * Pointer to TX q
[dpdk-dev] [PATCH v1 08/21] net/mlx5: separate DPDK from Verbs Rx queue objects
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 3 + drivers/net/mlx5/mlx5.h | 2 +- drivers/net/mlx5/mlx5_flow.c | 97 +++- drivers/net/mlx5/mlx5_rxq.c | 564 ++- drivers/net/mlx5/mlx5_rxtx.h | 26 +- drivers/net/mlx5/mlx5_vlan.c | 2 +- 6 files changed, 401 insertions(+), 293 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 0d8ca52..c158d8e 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -200,6 +200,9 @@ mlx5_dev_close(struct rte_eth_dev *dev) } if (priv->reta_idx != NULL) rte_free(priv->reta_idx); + i = mlx5_priv_rxq_ibv_verify(priv); + if (i) + WARN("%p: some Verbs Rx queue still remain", (void*)priv); i = priv_flow_verify(priv); if (i) WARN("%p: some flows still remain", (void*)priv); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 1ae5f59..228fd34 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -146,6 +146,7 @@ struct priv { struct rte_flow_drop *flow_drop_queue; /* Flow drop queue. */ TAILQ_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ LIST_HEAD(mr, mlx5_mr) mr; /* Memory region. */ + LIST_HEAD(rxqibv, mlx5_rxq_ibv) rxqsibv; /* Verbs Rx queues. */ uint32_t link_speed_capa; /* Link speed capabilities. */ struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */ rte_spinlock_t lock; /* Lock for control functions. */ @@ -287,7 +288,6 @@ int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); int mlx5_flow_isolate(struct rte_eth_dev *, int, struct rte_flow_error *); int priv_flow_start(struct priv *); void priv_flow_stop(struct priv *); -int priv_flow_rxq_in_use(struct priv *, struct mlx5_rxq_data *); int priv_flow_verify(struct priv *); /* mlx5_mr.c */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index bcbb984..9ed8d05 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -95,11 +95,11 @@ struct rte_flow { struct ibv_exp_flow *ibv_flow; /**< Verbs flow. */ struct ibv_exp_wq *wq; /**< Verbs work queue. */ struct ibv_cq *cq; /**< Verbs completion queue. */ - uint16_t rxqs_n; /**< Number of queues in this flow, 0 if drop queue. */ uint32_t mark:1; /**< Set if the flow is marked. */ uint32_t drop:1; /**< Drop queue. */ uint64_t hash_fields; /**< Fields that participate in the hash. */ - struct mlx5_rxq_data *rxqs[]; /**< Pointer to the queues array. */ + uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< List of queues. */ + uint16_t queues_n; /**< Number of queues in the list. */ }; /** Static initializer for items. */ @@ -1097,23 +1097,21 @@ priv_flow_create_action_queue(struct priv *priv, assert(priv->pd); assert(priv->ctx); assert(!flow->actions.drop); - rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow) + - sizeof(*rte_flow->rxqs) * flow->actions.queues_n, - 0); + rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0); if (!rte_flow) { rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "cannot allocate flow memory"); return NULL; } for (i = 0; i < flow->actions.queues_n; ++i) { - struct mlx5_rxq_ctrl *rxq; + struct mlx5_rxq_ibv *rxq = + mlx5_priv_rxq_ibv_get(priv, flow->actions.queues[i]); - rxq = container_of((*priv->rxqs)[flow->actions.queues[i]], - struct mlx5_rxq_ctrl, rxq); wqs[i] = rxq->wq; - rte_flow->rxqs[i] = &rxq->rxq; - ++rte_flow->rxqs_n; - rxq->rxq.mark |= flow->actions.mark; + rte_flow->queues[i] = flow->actions.queues[i]; + ++rte_flow->queues_n; + (*priv->rxqs)[flow->actions.queues[i]]->mark |= + flow->actions.mark; } /* finalise indirection table. */ for (j = 0; i < wqs_n; ++i, ++j) { @@ -1294,6 +1292,8 @@ static void priv_flow_destroy(struct priv *priv, struct rte_flow *flow) { + unsigned int i; + TAILQ_REMOVE(&priv->flows, flow, next); if (flow->ibv_flow) claim_zero(ibv_exp_destroy_flow(flow->ibv_flow)); @@ -1303,37 +1303,33 @@ priv_flow_destroy(struct priv *priv, claim_zero(ibv_destroy_qp(flow->qp)); if (flow->ind_table) claim_zero(ibv_exp_destroy_rwq_ind_table(flow->ind_table)); - if (flow->mark)
[dpdk-dev] [PATCH v1 10/21] net/mlx5: add reference counter on DPDK Tx queues
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 16 +- drivers/net/mlx5/mlx5.h | 1 + drivers/net/mlx5/mlx5_mr.c | 37 ++-- drivers/net/mlx5/mlx5_rxtx.h| 13 +- drivers/net/mlx5/mlx5_trigger.c | 56 ++ drivers/net/mlx5/mlx5_txq.c | 383 6 files changed, 317 insertions(+), 189 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 23068ae..c8be196 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -173,17 +173,8 @@ mlx5_dev_close(struct rte_eth_dev *dev) if (priv->txqs != NULL) { /* XXX race condition if mlx5_tx_burst() is still running. */ usleep(1000); - for (i = 0; (i != priv->txqs_n); ++i) { - struct mlx5_txq_data *txq = (*priv->txqs)[i]; - struct mlx5_txq_ctrl *txq_ctrl; - - if (txq == NULL) - continue; - txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq); - (*priv->txqs)[i] = NULL; - mlx5_txq_cleanup(txq_ctrl); - rte_free(txq_ctrl); - } + for (i = 0; (i != priv->txqs_n); ++i) + mlx5_priv_txq_release(priv, i); priv->txqs_n = 0; priv->txqs = NULL; } @@ -206,6 +197,9 @@ mlx5_dev_close(struct rte_eth_dev *dev) i = mlx5_priv_txq_ibv_verify(priv); if (i) WARN("%p: some Verbs Tx queue still remain", (void*)priv); + i = mlx5_priv_txq_verify(priv); + if (i) + WARN("%p: some Tx Queues still remain", (void*)priv); i = priv_flow_verify(priv); if (i) WARN("%p: some flows still remain", (void*)priv); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 25711ef..4dd432b 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -147,6 +147,7 @@ struct priv { TAILQ_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ LIST_HEAD(mr, mlx5_mr) mr; /* Memory region. */ LIST_HEAD(rxqibv, mlx5_rxq_ibv) rxqsibv; /* Verbs Rx queues. */ + LIST_HEAD(txq, mlx5_txq_ctrl) txqsctrl; /* DPDK Tx queues. */ LIST_HEAD(txqibv, mlx5_txq_ibv) txqsibv; /* Verbs Tx queues. */ uint32_t link_speed_capa; /* Link speed capabilities. */ struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */ diff --git a/drivers/net/mlx5/mlx5_mr.c b/drivers/net/mlx5/mlx5_mr.c index b5e9500..58e3b3f 100644 --- a/drivers/net/mlx5/mlx5_mr.c +++ b/drivers/net/mlx5/mlx5_mr.c @@ -164,7 +164,7 @@ mlx5_txq_mp2mr_reg(struct mlx5_txq_data *txq, struct rte_mempool *mp, return txq_ctrl->txq.mp2mr[idx]->lkey; } -struct txq_mp2mr_mbuf_check_data { +struct mlx5_mp2mr_mbuf_check_data { int ret; }; @@ -183,10 +183,10 @@ struct txq_mp2mr_mbuf_check_data { * Object index, unused. */ static void -mlx5_txq_mp2mr_mbuf_check(struct rte_mempool *mp, void *arg, void *obj, - uint32_t index __rte_unused) +mlx5_mp2mr_mbuf_check(struct rte_mempool *mp, void *arg, void *obj, + uint32_t index __rte_unused) { - struct txq_mp2mr_mbuf_check_data *data = arg; + struct mlx5_mp2mr_mbuf_check_data *data = arg; struct rte_mbuf *buf = obj; /* @@ -207,35 +207,24 @@ mlx5_txq_mp2mr_mbuf_check(struct rte_mempool *mp, void *arg, void *obj, * Pointer to TX queue structure. */ void -mlx5_txq_mp2mr_iter(struct rte_mempool *mp, void *arg) +mlx5_mp2mr_iter(struct rte_mempool *mp, void *arg) { - struct mlx5_txq_ctrl *txq_ctrl = arg; - struct txq_mp2mr_mbuf_check_data data = { + struct priv *priv = (struct priv *)arg; + struct mlx5_mp2mr_mbuf_check_data data = { .ret = 0, }; - uintptr_t start; - uintptr_t end; - unsigned int i; + struct mlx5_mr *mr; /* Register mempool only if the first element looks like a mbuf. */ - if (rte_mempool_obj_iter(mp, mlx5_txq_mp2mr_mbuf_check, &data) == 0 || + if (rte_mempool_obj_iter(mp, mlx5_mp2mr_mbuf_check, &data) == 0 || data.ret == -1) return; - if (mlx5_check_mempool(mp, &start, &end) != 0) { - ERROR("mempool %p: not virtually contiguous", - (void *)mp); + mr = priv_mr_get(priv, mp); + if (mr) { + priv_mr_release(priv, mr); return; } - for (i = 0; (i != RTE_DIM(txq_ctrl->txq.mp2mr)); ++i) { - if (unlikely(txq_ctrl->txq.mp2mr[i] == NULL)) { - /* Unknown MP, add a new MR for it. */ - break; - } - if (start >= (uintptr_t)txq_ct
[dpdk-dev] [PATCH v1 12/21] net/mlx5: remove queue drop support
In prevision of the huge rework on Rx hash queues and the fact this feature will be totally different, the drop flow is removed from now and will be re-introduced later. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 1 - drivers/net/mlx5/mlx5_flow.c | 228 +++ 2 files changed, 15 insertions(+), 214 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 448995e..a0266d4 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -143,7 +143,6 @@ struct priv { struct rte_intr_handle intr_handle; /* Interrupt handler. */ unsigned int (*reta_idx)[]; /* RETA index table. */ unsigned int reta_idx_n; /* RETA index size. */ - struct rte_flow_drop *flow_drop_queue; /* Flow drop queue. */ TAILQ_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ LIST_HEAD(mr, mlx5_mr) mr; /* Memory region. */ LIST_HEAD(rxq, mlx5_rxq_ctrl) rxqsctrl; /* DPDK Rx queues. */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 9ed8d05..151854a 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -96,7 +96,6 @@ struct rte_flow { struct ibv_exp_wq *wq; /**< Verbs work queue. */ struct ibv_cq *cq; /**< Verbs completion queue. */ uint32_t mark:1; /**< Set if the flow is marked. */ - uint32_t drop:1; /**< Drop queue. */ uint64_t hash_fields; /**< Fields that participate in the hash. */ uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< List of queues. */ uint16_t queues_n; /**< Number of queues in the list. */ @@ -274,7 +273,6 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { /* Structure to parse actions. */ 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 mark_id; /**< Mark identifier. */ uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */ @@ -290,14 +288,6 @@ struct mlx5_flow_parse { struct mlx5_flow_action actions; /**< Parsed action result. */ }; -/** Structure for Drop queue. */ -struct rte_flow_drop { - struct ibv_exp_rwq_ind_table *ind_table; /**< Indirection table. */ - struct ibv_qp *qp; /**< Verbs queue pair. */ - struct ibv_exp_wq *wq; /**< Verbs work queue. */ - struct ibv_cq *cq; /**< Verbs completion queue. */ -}; - static const struct rte_flow_ops mlx5_flow_ops = { .validate = mlx5_flow_validate, .create = mlx5_flow_create, @@ -512,7 +502,11 @@ priv_flow_validate(struct priv *priv, if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) { continue; } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) { - flow->actions.drop = 1; + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "Drop queue not supported"); + return -rte_errno; } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) { const struct rte_flow_action_queue *queue = (const struct rte_flow_action_queue *) @@ -614,11 +608,9 @@ priv_flow_validate(struct priv *priv, goto exit_action_not_supported; } } - if (flow->actions.mark && !flow->ibv_attr && !flow->actions.drop) + if (flow->actions.mark && !flow->ibv_attr) flow->offset += sizeof(struct ibv_exp_flow_spec_action_tag); - if (!flow->ibv_attr && flow->actions.drop) - flow->offset += sizeof(struct ibv_exp_flow_spec_action_drop); - if (!flow->actions.queue && !flow->actions.drop) { + if (!flow->actions.queue) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "no valid action"); return -rte_errno; @@ -1015,62 +1007,6 @@ mlx5_flow_create_flag_mark(struct mlx5_flow_parse *flow, uint32_t mark_id) } /** - * Complete flow rule creation with a drop queue. - * - * @param priv - * Pointer to private structure. - * @param flow - * MLX5 flow attributes (filled by mlx5_flow_validate()). - * @param[out] error - * Perform verbose error reporting if not NULL. - * - * @return - * A flow if the rule could be created. - */ -static struct rte_flow * -priv_flow_create_action_queue_drop(struct priv *priv, - struct mlx5_flow_parse *flow, - struct rte_flow_error *error) -{
[dpdk-dev] [PATCH v1 13/21] net/mlx5: make indirection tables sharable
Avoid to have for each Hash Rx queue it dedicated indirection table. On verbs side, the indirection table only points to the Work Queue, two hash Rx queues using the same set of WQ can use the same indirection table. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 3 + drivers/net/mlx5/mlx5.h | 2 + drivers/net/mlx5/mlx5_flow.c | 79 ++ drivers/net/mlx5/mlx5_rxq.c | 149 ++ drivers/net/mlx5/mlx5_rxtx.h | 18 + drivers/net/mlx5/mlx5_utils.h | 2 + 6 files changed, 207 insertions(+), 46 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index b37292c..d5cb6e4 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -182,6 +182,9 @@ mlx5_dev_close(struct rte_eth_dev *dev) } if (priv->reta_idx != NULL) rte_free(priv->reta_idx); + i = mlx5_priv_ind_table_ibv_verify(priv); + if (i) + WARN("%p: some Indirection table still remain", (void*)priv); i = mlx5_priv_rxq_ibv_verify(priv); if (i) WARN("%p: some Verbs Rx queue still remain", (void*)priv); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index a0266d4..081c2c6 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -149,6 +149,8 @@ struct priv { LIST_HEAD(rxqibv, mlx5_rxq_ibv) rxqsibv; /* Verbs Rx queues. */ LIST_HEAD(txq, mlx5_txq_ctrl) txqsctrl; /* DPDK Tx queues. */ LIST_HEAD(txqibv, mlx5_txq_ibv) txqsibv; /* Verbs Tx queues. */ + /* Verbs Indirection tables. */ + LIST_HEAD(ind_tables, mlx5_ind_table_ibv) ind_tbls; uint32_t link_speed_capa; /* Link speed capabilities. */ struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */ rte_spinlock_t lock; /* Lock for control functions. */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 151854a..049a8e2 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -90,15 +90,13 @@ mlx5_flow_create_vxlan(const struct rte_flow_item *item, struct rte_flow { TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ - struct ibv_exp_rwq_ind_table *ind_table; /**< Indirection table. */ + struct mlx5_ind_table_ibv *ind_table; /**< Indirection table. */ struct ibv_qp *qp; /**< Verbs queue pair. */ struct ibv_exp_flow *ibv_flow; /**< Verbs flow. */ struct ibv_exp_wq *wq; /**< Verbs work queue. */ struct ibv_cq *cq; /**< Verbs completion queue. */ uint32_t mark:1; /**< Set if the flow is marked. */ uint64_t hash_fields; /**< Fields that participate in the hash. */ - uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< List of queues. */ - uint16_t queues_n; /**< Number of queues in the list. */ }; /** Static initializer for items. */ @@ -1026,50 +1024,37 @@ priv_flow_create_action_queue(struct priv *priv, { struct rte_flow *rte_flow; unsigned int i; - unsigned int j; - const unsigned int wqs_n = 1 << log2above(flow->actions.queues_n); - struct ibv_exp_wq *wqs[wqs_n]; assert(priv->pd); assert(priv->ctx); - assert(!flow->actions.drop); rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0); if (!rte_flow) { rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "cannot allocate flow memory"); return NULL; } - for (i = 0; i < flow->actions.queues_n; ++i) { - struct mlx5_rxq_ibv *rxq = - mlx5_priv_rxq_ibv_get(priv, flow->actions.queues[i]); - - wqs[i] = rxq->wq; - rte_flow->queues[i] = flow->actions.queues[i]; - ++rte_flow->queues_n; - (*priv->rxqs)[flow->actions.queues[i]]->mark |= - flow->actions.mark; - } - /* finalise indirection table. */ - for (j = 0; i < wqs_n; ++i, ++j) { - wqs[i] = wqs[j]; - if (j == flow->actions.queues_n) - j = 0; + for (i = 0; i != flow->actions.queues_n; ++i) { + struct mlx5_rxq_data *q = (*priv->rxqs)[flow->actions.queues[i]]; + + q->mark |= flow->actions.mark; } rte_flow->mark = flow->actions.mark; rte_flow->ibv_attr = flow->ibv_attr; rte_flow->hash_fields = flow->hash_fields; - rte_flow->ind_table = ibv_exp_create_rwq_ind_table( - priv->ctx, - &(struct ibv_exp_rwq_ind_table_init_attr){ - .
[dpdk-dev] [PATCH v1 11/21] net/mlx5: add reference counter on DPDK Rx queues
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 16 +- drivers/net/mlx5/mlx5.h | 1 + drivers/net/mlx5/mlx5_rxq.c | 492 +--- drivers/net/mlx5/mlx5_rxtx.h| 10 + drivers/net/mlx5/mlx5_trigger.c | 45 5 files changed, 321 insertions(+), 243 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index c8be196..b37292c 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -156,17 +156,8 @@ mlx5_dev_close(struct rte_eth_dev *dev) if (priv->rxqs != NULL) { /* XXX race condition if mlx5_rx_burst() is still running. */ usleep(1000); - for (i = 0; (i != priv->rxqs_n); ++i) { - struct mlx5_rxq_data *rxq = (*priv->rxqs)[i]; - struct mlx5_rxq_ctrl *rxq_ctrl; - - if (rxq == NULL) - continue; - rxq_ctrl = container_of(rxq, struct mlx5_rxq_ctrl, rxq); - (*priv->rxqs)[i] = NULL; - mlx5_rxq_cleanup(rxq_ctrl); - rte_free(rxq_ctrl); - } + for (i = 0; (i != priv->rxqs_n); ++i) + mlx5_priv_rxq_release(priv, i); priv->rxqs_n = 0; priv->rxqs = NULL; } @@ -194,6 +185,9 @@ mlx5_dev_close(struct rte_eth_dev *dev) i = mlx5_priv_rxq_ibv_verify(priv); if (i) WARN("%p: some Verbs Rx queue still remain", (void*)priv); + i = mlx5_priv_rxq_verify(priv); + if (i) + WARN("%p: some Rx Queues still remain", (void*)priv); i = mlx5_priv_txq_ibv_verify(priv); if (i) WARN("%p: some Verbs Tx queue still remain", (void*)priv); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 4dd432b..448995e 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -146,6 +146,7 @@ struct priv { struct rte_flow_drop *flow_drop_queue; /* Flow drop queue. */ TAILQ_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ LIST_HEAD(mr, mlx5_mr) mr; /* Memory region. */ + LIST_HEAD(rxq, mlx5_rxq_ctrl) rxqsctrl; /* DPDK Rx queues. */ LIST_HEAD(rxqibv, mlx5_rxq_ibv) rxqsibv; /* Verbs Rx queues. */ LIST_HEAD(txq, mlx5_txq_ctrl) txqsctrl; /* DPDK Tx queues. */ LIST_HEAD(txqibv, mlx5_txq_ibv) txqsibv; /* Verbs Tx queues. */ diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index 1663734..3b75a7e 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -37,6 +37,7 @@ #include #include #include +#include /* Verbs header. */ /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ @@ -631,16 +632,15 @@ priv_rehash_flows(struct priv *priv) * * @param rxq_ctrl * Pointer to RX queue structure. - * @param elts_n - * Number of elements to allocate. * * @return * 0 on success, errno value on failure. */ -static int -rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl, unsigned int elts_n) +int +rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl) { const unsigned int sges_n = 1 << rxq_ctrl->rxq.sges_n; + unsigned int elts_n = 1 << rxq_ctrl->rxq.elts_n; unsigned int i; int ret = 0; @@ -669,9 +669,11 @@ rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl, unsigned int elts_n) NB_SEGS(buf) = 1; (*rxq_ctrl->rxq.elts)[i] = buf; } + /* If Rx vector is activated. */ if (rxq_check_vec_support(&rxq_ctrl->rxq) > 0) { struct mlx5_rxq_data *rxq = &rxq_ctrl->rxq; struct rte_mbuf *mbuf_init = &rxq->fake_mbuf; + int j; assert(rxq->elts_n == rxq->cqe_n); /* Initialize default rearm_data for vPMD. */ @@ -684,10 +686,12 @@ rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl, unsigned int elts_n) * rearm_data covers previous fields. */ rte_compiler_barrier(); - rxq->mbuf_initializer = *(uint64_t *)&mbuf_init->rearm_data; + rxq->mbuf_initializer = + *(uint64_t *)&mbuf_init->rearm_data; /* Padding with a fake mbuf for vectorized Rx. */ - for (i = 0; i < MLX5_VPMD_DESCS_PER_LOOP; ++i) - (*rxq->elts)[elts_n + i] = &rxq->fake_mbuf; + for (j = 0; j < MLX5_VPMD_DESCS_PER_LOOP; ++j) + (*rxq->elts)[elts_n + j] = &rxq->fake_mbuf; + /* Mark that it need to be cleaned up for rxq_alloc_elts(). */ } DEBUG("%p: allocated and configured %u segments (max %u packets)", (vo
[dpdk-dev] [PATCH v1 14/21] net/mlx5: add Hash Rx queue object
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 3 + drivers/net/mlx5/mlx5.h | 1 + drivers/net/mlx5/mlx5_flow.c | 137 +++- drivers/net/mlx5/mlx5_rxq.c | 161 +++ drivers/net/mlx5/mlx5_rxtx.h | 19 + 5 files changed, 239 insertions(+), 82 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index d5cb6e4..52cbb20 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -182,6 +182,9 @@ mlx5_dev_close(struct rte_eth_dev *dev) } if (priv->reta_idx != NULL) rte_free(priv->reta_idx); + i = mlx5_priv_hrxq_ibv_verify(priv); + if (i) + WARN("%p: some Hash Rx queue still remain", (void*)priv); i = mlx5_priv_ind_table_ibv_verify(priv); if (i) WARN("%p: some Indirection table still remain", (void*)priv); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 081c2c6..3c2e719 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -147,6 +147,7 @@ struct priv { LIST_HEAD(mr, mlx5_mr) mr; /* Memory region. */ LIST_HEAD(rxq, mlx5_rxq_ctrl) rxqsctrl; /* DPDK Rx queues. */ LIST_HEAD(rxqibv, mlx5_rxq_ibv) rxqsibv; /* Verbs Rx queues. */ + LIST_HEAD(hrxq, mlx5_hrxq) hrxqs; /* Verbs Hash Rx queues. */ LIST_HEAD(txq, mlx5_txq_ctrl) txqsctrl; /* DPDK Tx queues. */ LIST_HEAD(txqibv, mlx5_txq_ibv) txqsibv; /* Verbs Tx queues. */ /* Verbs Indirection tables. */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 049a8e2..f258567 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -90,13 +90,9 @@ mlx5_flow_create_vxlan(const struct rte_flow_item *item, struct rte_flow { TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ - struct mlx5_ind_table_ibv *ind_table; /**< Indirection table. */ - struct ibv_qp *qp; /**< Verbs queue pair. */ struct ibv_exp_flow *ibv_flow; /**< Verbs flow. */ - struct ibv_exp_wq *wq; /**< Verbs work queue. */ - struct ibv_cq *cq; /**< Verbs completion queue. */ + struct mlx5_hrxq *hrxq; /**< Hash Rx queue. */ uint32_t mark:1; /**< Set if the flow is marked. */ - uint64_t hash_fields; /**< Fields that participate in the hash. */ }; /** Static initializer for items. */ @@ -1033,56 +1029,36 @@ priv_flow_create_action_queue(struct priv *priv, NULL, "cannot allocate flow memory"); return NULL; } - for (i = 0; i != flow->actions.queues_n; ++i) { - struct mlx5_rxq_data *q = (*priv->rxqs)[flow->actions.queues[i]]; - - q->mark |= flow->actions.mark; - } rte_flow->mark = flow->actions.mark; rte_flow->ibv_attr = flow->ibv_attr; - rte_flow->hash_fields = flow->hash_fields; - rte_flow->ind_table = - mlx5_priv_ind_table_ibv_get(priv, flow->actions.queues, + rte_flow->hrxq = mlx5_priv_hrxq_get(priv, rss_hash_default_key, + rss_hash_default_key_len, + flow->hash_fields, + flow->actions.queues, flow->actions.queues_n); - if (!rte_flow->ind_table) { - rte_flow->ind_table = - mlx5_priv_ind_table_ibv_new(priv, flow->actions.queues, - flow->actions.queues_n); - if (!rte_flow->ind_table) { - rte_flow_error_set(error, ENOMEM, - RTE_FLOW_ERROR_TYPE_HANDLE, - NULL, - "cannot allocate indirection table"); - goto error; - } + if (rte_flow->hrxq) { + rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, + NULL, "duplicated flow"); + goto error; } - rte_flow->qp = ibv_exp_create_qp( - priv->ctx, - &(struct ibv_exp_qp_init_attr){ - .qp_type = IBV_QPT_RAW_PACKET, - .comp_mask = - IBV_EXP_QP_INIT_ATTR_PD | - IBV_EXP_QP_INIT_ATTR_PORT | - IBV_EXP_QP_INIT_ATTR_RX_HASH, - .pd = priv->pd, - .rx_hash_conf = &(struct ibv_exp_rx_hash_conf){
[dpdk-dev] [PATCH v1 15/21] net/mlx5: disable priority protection in flows
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 7 --- 1 file changed, 7 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index f258567..90deb30 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -426,13 +426,6 @@ priv_flow_validate(struct priv *priv, "groups are not supported"); return -rte_errno; } - if (attr->priority) { - rte_flow_error_set(error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, - NULL, - "priorities are not supported"); - return -rte_errno; - } if (attr->egress) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, -- 2.1.4
[dpdk-dev] [PATCH v1 16/21] net/mlx5: use flow to enable promiscuous mode
RSS hash configuration is currently ignored by the PMD, this commits removes the RSS feature on promiscuous mode. This functionality will be added in a later commit. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 1 + drivers/net/mlx5/mlx5.h | 15 +++-- drivers/net/mlx5/mlx5_flow.c| 127 drivers/net/mlx5/mlx5_rxmode.c | 52 +--- drivers/net/mlx5/mlx5_rxq.c | 8 +-- drivers/net/mlx5/mlx5_rxtx.h| 3 - drivers/net/mlx5/mlx5_trigger.c | 20 +-- 7 files changed, 158 insertions(+), 68 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 52cbb20..f000404 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -775,6 +775,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->dev = eth_dev; eth_dev->dev_ops = &mlx5_dev_ops; TAILQ_INIT(&priv->flows); + TAILQ_INIT(&priv->ctrl_flows); /* Bring Ethernet device up. */ DEBUG("forcing Ethernet interface up"); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 3c2e719..cbf8849 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -39,6 +39,7 @@ #include #include #include +#include /* Verbs header. */ /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ @@ -86,6 +87,9 @@ struct mlx5_xstats_ctrl { uint64_t base[MLX5_MAX_XSTATS]; }; +/* Flow list . */ +TAILQ_HEAD(mlx5_flows, rte_flow); + struct priv { struct rte_eth_dev *dev; /* Ethernet device. */ struct ibv_context *ctx; /* Verbs context. */ @@ -103,7 +107,6 @@ struct priv { /* Device properties. */ uint16_t mtu; /* Configured MTU. */ uint8_t port; /* Physical port number. */ - unsigned int promisc_req:1; /* Promiscuous mode requested. */ unsigned int allmulti_req:1; /* All multicast mode requested. */ unsigned int hw_csum:1; /* Checksum offload is supported. */ unsigned int hw_csum_l2tun:1; /* Same for L2 tunnels. */ @@ -143,7 +146,8 @@ struct priv { struct rte_intr_handle intr_handle; /* Interrupt handler. */ unsigned int (*reta_idx)[]; /* RETA index table. */ unsigned int reta_idx_n; /* RETA index size. */ - TAILQ_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */ + struct mlx5_flows flows; /* RTE Flow rules. */ + struct mlx5_flows ctrl_flows; /* Control flow rules. */ LIST_HEAD(mr, mlx5_mr) mr; /* Memory region. */ LIST_HEAD(rxq, mlx5_rxq_ctrl) rxqsctrl; /* DPDK Rx queues. */ LIST_HEAD(rxqibv, mlx5_rxq_ibv) rxqsibv; /* Verbs Rx queues. */ @@ -289,11 +293,14 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *, struct rte_flow_error *); int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *, struct rte_flow_error *); +void priv_flow_flush(struct priv *, struct mlx5_flows *); int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *); int mlx5_flow_isolate(struct rte_eth_dev *, int, struct rte_flow_error *); -int priv_flow_start(struct priv *); -void priv_flow_stop(struct priv *); +int priv_flow_start(struct priv *, struct mlx5_flows *); +void priv_flow_stop(struct priv *, struct mlx5_flows *); int priv_flow_verify(struct priv *); +int mlx5_flow_ctrl(struct rte_eth_dev *, struct rte_flow_item_eth *, + struct rte_flow_item_eth *, unsigned int, unsigned int); /* mlx5_mr.c */ diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 90deb30..39a49af 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -1169,11 +1169,14 @@ mlx5_flow_create(struct rte_eth_dev *dev, * * @param priv * Pointer to private structure. + * @param list + * Pointer to a TAILQ flow list. * @param[in] flow * Flow to destroy. */ static void priv_flow_destroy(struct priv *priv, + struct mlx5_flows *list, struct rte_flow *flow) { unsigned int i; @@ -1193,7 +1196,7 @@ priv_flow_destroy(struct priv *priv, * To remove the mark from the queue, the queue must not be * present in any other marked flow (RSS or not). */ - TAILQ_FOREACH(tmp, &priv->flows, next) { + TAILQ_FOREACH(tmp, list, next) { unsigned int j; if (!tmp->mark) @@ -1208,7 +1211,7 @@ priv_flow_destroy(struct priv *priv, rxq->mark = mark; } out: - TAILQ_REMOVE(&priv->flows, flow, next); + TAILQ_REMOVE(list, flow, next); if (flow->ibv_flow) claim_zero(ibv_exp_destroy_flow(flow->ibv_flow)); mlx5_priv_hrxq_release(priv, flow->hr
[dpdk-dev] [PATCH v1 17/21] net/mlx5: use flow to enable all multi mode
RSS hash configuration is currently ignored by the PMD, this commits removes the RSS feature on promiscuous mode. This functionality will be added in a later commit. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.h | 1 - drivers/net/mlx5/mlx5_rxmode.c | 52 ++--- drivers/net/mlx5/mlx5_rxq.c | 9 +++ drivers/net/mlx5/mlx5_rxtx.h| 3 --- drivers/net/mlx5/mlx5_trigger.c | 2 ++ 5 files changed, 23 insertions(+), 44 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index cbf8849..ba461a3 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -107,7 +107,6 @@ struct priv { /* Device properties. */ uint16_t mtu; /* Configured MTU. */ uint8_t port; /* Physical port number. */ - unsigned int allmulti_req:1; /* All multicast mode requested. */ unsigned int hw_csum:1; /* Checksum offload is supported. */ unsigned int hw_csum_l2tun:1; /* Same for L2 tunnels. */ unsigned int hw_vlan_strip:1; /* VLAN stripping is supported. */ diff --git a/drivers/net/mlx5/mlx5_rxmode.c b/drivers/net/mlx5/mlx5_rxmode.c index d6ca907..3fcfec7 100644 --- a/drivers/net/mlx5/mlx5_rxmode.c +++ b/drivers/net/mlx5/mlx5_rxmode.c @@ -53,18 +53,6 @@ /* Initialization data for special flows. */ static const struct special_flow_init special_flow_init[] = { - [HASH_RXQ_FLOW_TYPE_ALLMULTI] = { - .dst_mac_val = "\x01\x00\x00\x00\x00\x00", - .dst_mac_mask = "\x01\x00\x00\x00\x00\x00", - .hash_types = - 1 << HASH_RXQ_UDPV4 | - 1 << HASH_RXQ_IPV4 | - 1 << HASH_RXQ_UDPV6 | - 1 << HASH_RXQ_IPV6 | - 1 << HASH_RXQ_ETH | - 0, - .per_vlan = 0, - }, [HASH_RXQ_FLOW_TYPE_BROADCAST] = { .dst_mac_val = "\xff\xff\xff\xff\xff\xff", .dst_mac_mask = "\xff\xff\xff\xff\xff\xff", @@ -328,7 +316,7 @@ priv_special_flow_enable_all(struct priv *priv) if (priv->isolated) return 0; - for (flow_type = HASH_RXQ_FLOW_TYPE_ALLMULTI; + for (flow_type = HASH_RXQ_FLOW_TYPE_BROADCAST; flow_type != HASH_RXQ_FLOW_TYPE_MAC; ++flow_type) { int ret; @@ -355,7 +343,7 @@ priv_special_flow_disable_all(struct priv *priv) { enum hash_rxq_flow_type flow_type; - for (flow_type = HASH_RXQ_FLOW_TYPE_ALLMULTI; + for (flow_type = HASH_RXQ_FLOW_TYPE_BROADCAST; flow_type != HASH_RXQ_FLOW_TYPE_MAC; ++flow_type) priv_special_flow_disable(priv, flow_type); @@ -412,19 +400,17 @@ mlx5_promiscuous_disable(struct rte_eth_dev *dev) void mlx5_allmulticast_enable(struct rte_eth_dev *dev) { - struct priv *priv = dev->data->dev_private; - int ret; + struct rte_flow_item_eth eth = { + .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00", + .src.addr_bytes = "\x01\x00\x00\x00\x00\x00", + .type = 0, + }; if (mlx5_is_secondary()) return; - - priv_lock(priv); - priv->allmulti_req = 1; - ret = priv_rehash_flows(priv); - if (ret) - ERROR("error while enabling allmulticast mode: %s", - strerror(ret)); - priv_unlock(priv); + dev->data->all_multicast = 1; + if (dev->data->dev_started) + claim_zero(mlx5_flow_ctrl(dev, ð, ð, 3, 1)); } /** @@ -436,17 +422,15 @@ mlx5_allmulticast_enable(struct rte_eth_dev *dev) void mlx5_allmulticast_disable(struct rte_eth_dev *dev) { - struct priv *priv = dev->data->dev_private; - int ret; + struct rte_flow_item_eth eth = { + .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00", + .src.addr_bytes = "\x01\x00\x00\x00\x00\x00", + .type = 0, + }; if (mlx5_is_secondary()) return; - - priv_lock(priv); - priv->allmulti_req = 0; - ret = priv_rehash_flows(priv); - if (ret) - ERROR("error while disabling allmulticast mode: %s", - strerror(ret)); - priv_unlock(priv); + dev->data->all_multicast = 0; + if (dev->data->dev_started) + claim_zero(mlx5_flow_ctrl(dev, ð, ð, 3, 0)); } diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index 5f9e84a..e5ec57f 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -573,16 +573,13 @@ priv_destroy_hash_rxqs(struct priv *priv) int priv_allow_flow_type(struct priv *priv, enum hash_rxq_flow_type type)
[dpdk-dev] [PATCH v1 19/21] net/mlx5: handle a single RSS hash key for all protocols
Since RSS configuration can also be used by flow API, there is no more necessity to keep a list of RSS configurable for all protocols. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c| 24 +--- drivers/net/mlx5/mlx5.h| 6 +- drivers/net/mlx5/mlx5_ethdev.c | 16 -- drivers/net/mlx5/mlx5_rss.c| 127 + drivers/net/mlx5/mlx5_rxq.c| 5 +- 5 files changed, 45 insertions(+), 133 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index af3f7c8..bf6c66b 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -174,11 +174,8 @@ mlx5_dev_close(struct rte_eth_dev *dev) claim_zero(ibv_close_device(priv->ctx)); } else assert(priv->ctx == NULL); - if (priv->rss_conf != NULL) { - for (i = 0; (i != hash_rxq_init_n); ++i) - rte_free((*priv->rss_conf)[i]); - rte_free(priv->rss_conf); - } + if (priv->rss_conf.rss_key != NULL) + rte_free(priv->rss_conf.rss_key); if (priv->reta_idx != NULL) rte_free(priv->reta_idx); i = mlx5_priv_hrxq_ibv_verify(priv); @@ -709,19 +706,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->txq_inline = MLX5_WQE_SIZE_MAX - MLX5_WQE_SIZE; } - /* Allocate and register default RSS hash keys. */ - priv->rss_conf = rte_calloc(__func__, hash_rxq_init_n, - sizeof((*priv->rss_conf)[0]), 0); - if (priv->rss_conf == NULL) { - err = ENOMEM; - goto port_error; - } - err = rss_hash_rss_conf_new_key(priv, - rss_hash_default_key, - rss_hash_default_key_len, - ETH_RSS_PROTO_MASK); - if (err) - goto port_error; /* Configure the first MAC address by default. */ if (priv_get_mac(priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx5_en loaded?" @@ -781,10 +765,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) continue; port_error: - if (priv) { - rte_free(priv->rss_conf); + if (priv) rte_free(priv); - } if (pd) claim_zero(ibv_dealloc_pd(pd)); if (ctx) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index ee0de3c..5058bcd 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -133,9 +133,7 @@ struct priv { /* Hash RX QPs feeding the indirection table. */ struct hash_rxq (*hash_rxqs)[]; unsigned int hash_rxqs_n; /* Hash RX QPs array size. */ - /* RSS configuration array indexed by hash RX queue type. */ - struct rte_eth_rss_conf *(*rss_conf)[]; - uint64_t rss_hf; /* RSS DPDK bit field of active RSS. */ + struct rte_eth_rss_conf rss_conf; /* RSS configuration. */ struct rte_intr_handle intr_handle; /* Interrupt handler. */ unsigned int (*reta_idx)[]; /* RETA index table. */ unsigned int reta_idx_n; /* RETA index size. */ @@ -222,8 +220,6 @@ void mlx5_mac_addr_set(struct rte_eth_dev *, struct ether_addr *); /* mlx5_rss.c */ -int rss_hash_rss_conf_new_key(struct priv *, const uint8_t *, unsigned int, - uint64_t); int mlx5_rss_hash_update(struct rte_eth_dev *, struct rte_eth_rss_conf *); int mlx5_rss_hash_conf_get(struct rte_eth_dev *, struct rte_eth_rss_conf *); int priv_rss_reta_index_resize(struct priv *, unsigned int); diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index 0e0a99e..1817fdb 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -574,7 +574,17 @@ dev_configure(struct rte_eth_dev *dev) unsigned int j; unsigned int reta_idx_n; - priv->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; + priv->rss_conf.rss_key = + rte_realloc(priv->rss_conf.rss_key, + rss_hash_default_key_len, 0); + if (!priv->rss_conf.rss_key) { + ERROR("cannot allocate RSS hash key memory (%u)", rxqs_n); + return ENOMEM; + } + memcpy(priv->rss_conf.rss_key, rss_hash_default_key, + rss_hash_default_key_len); + priv->rss_conf.rss_key_len = rss_hash_default_key_len; + priv->rss_conf.rss_hf = dev->data->de
[dpdk-dev] [PATCH v1 18/21] net/mlx5: use flow to enable unicast traffic
RSS hash configuration is currently ignored by the PMD, this commits removes the RSS feature. This functionality will be added in a later commit. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 9 +- drivers/net/mlx5/mlx5.h | 22 +-- drivers/net/mlx5/mlx5_defs.h| 3 - drivers/net/mlx5/mlx5_flow.c| 26 ++- drivers/net/mlx5/mlx5_mac.c | 403 +++- drivers/net/mlx5/mlx5_rxmode.c | 332 + drivers/net/mlx5/mlx5_rxq.c | 65 --- drivers/net/mlx5/mlx5_rxtx.h| 26 --- drivers/net/mlx5/mlx5_trigger.c | 181 -- drivers/net/mlx5/mlx5_vlan.c| 54 ++ 10 files changed, 231 insertions(+), 890 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index f000404..af3f7c8 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -146,13 +146,12 @@ mlx5_dev_close(struct rte_eth_dev *dev) ((priv->ctx != NULL) ? priv->ctx->device->name : "")); /* In case mlx5_dev_stop() has not been called. */ priv_dev_interrupt_handler_uninstall(priv, dev); - priv_special_flow_disable_all(priv); - priv_mac_addrs_disable(priv); priv_destroy_hash_rxqs(priv); /* Prevent crashes when queues are still in use. */ dev->rx_pkt_burst = removed_rx_burst; dev->tx_pkt_burst = removed_tx_burst; + priv_dev_traffic_disable(priv, dev); if (priv->rxqs != NULL) { /* XXX race condition if mlx5_rx_burst() is still running. */ usleep(1000); @@ -734,10 +733,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) mac.addr_bytes[0], mac.addr_bytes[1], mac.addr_bytes[2], mac.addr_bytes[3], mac.addr_bytes[4], mac.addr_bytes[5]); - /* Register MAC address. */ - claim_zero(priv_mac_addr_add(priv, 0, -(const uint8_t (*)[ETHER_ADDR_LEN]) -mac.addr_bytes)); #ifndef NDEBUG { char ifname[IF_NAMESIZE]; @@ -774,6 +769,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) eth_dev->device->driver = &mlx5_driver.driver; priv->dev = eth_dev; eth_dev->dev_ops = &mlx5_dev_ops; + /* Register MAC address. */ + claim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0)); TAILQ_INIT(&priv->flows); TAILQ_INIT(&priv->ctrl_flows); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index ba461a3..ee0de3c 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -95,13 +95,7 @@ struct priv { struct ibv_context *ctx; /* Verbs context. */ struct ibv_device_attr device_attr; /* Device properties. */ struct ibv_pd *pd; /* Protection Domain. */ - /* -* MAC addresses array and configuration bit-field. -* An extra entry that cannot be modified by the DPDK is reserved -* for broadcast frames (destination MAC address ff:ff:ff:ff:ff:ff). -*/ - struct ether_addr mac[MLX5_MAX_MAC_ADDRESSES]; - BITFIELD_DECLARE(mac_configured, uint32_t, MLX5_MAX_MAC_ADDRESSES); + struct ether_addr mac[MLX5_MAX_MAC_ADDRESSES]; /* MAC addresses. */ uint16_t vlan_filter[MLX5_MAX_VLAN_IDS]; /* VLAN filters table. */ unsigned int vlan_filter_n; /* Number of configured VLAN filters. */ /* Device properties. */ @@ -221,13 +215,7 @@ void priv_select_rx_function(struct priv *); /* mlx5_mac.c */ int priv_get_mac(struct priv *, uint8_t (*)[ETHER_ADDR_LEN]); -void hash_rxq_mac_addrs_del(struct hash_rxq *); -void priv_mac_addrs_disable(struct priv *); void mlx5_mac_addr_remove(struct rte_eth_dev *, uint32_t); -int hash_rxq_mac_addrs_add(struct hash_rxq *); -int priv_mac_addr_add(struct priv *, unsigned int, - const uint8_t (*)[ETHER_ADDR_LEN]); -int priv_mac_addrs_enable(struct priv *); int mlx5_mac_addr_add(struct rte_eth_dev *, struct ether_addr *, uint32_t, uint32_t); void mlx5_mac_addr_set(struct rte_eth_dev *, struct ether_addr *); @@ -246,10 +234,6 @@ int mlx5_dev_rss_reta_update(struct rte_eth_dev *, /* mlx5_rxmode.c */ -int priv_special_flow_enable(struct priv *, enum hash_rxq_flow_type); -void priv_special_flow_disable(struct priv *, enum hash_rxq_flow_type); -int priv_special_flow_enable_all(struct priv *); -void priv_special_flow_disable_all(struct priv *); void mlx5_promiscuous_enable(struct rte_eth_dev *); void mlx5_promiscuous_disable(struct rte_eth_dev *); void mlx5_allmulticast_enable(struct rte_eth_dev *); @@ -276,6 +260,10 @@ void mlx5_vlan_strip_queue_set(struct rte_eth_dev *
[dpdk-dev] [PATCH v1 20/21] net/mlx5: remove hash Rx queues support
>From this commit the RSS support becomes un-available until it is replaced by the generic flow implementation. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5.c | 2 - drivers/net/mlx5/mlx5.h | 6 - drivers/net/mlx5/mlx5_rxq.c | 470 drivers/net/mlx5/mlx5_rxtx.h| 76 --- drivers/net/mlx5/mlx5_trigger.c | 12 +- 5 files changed, 7 insertions(+), 559 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index bf6c66b..7f6c774 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -146,8 +146,6 @@ mlx5_dev_close(struct rte_eth_dev *dev) ((priv->ctx != NULL) ? priv->ctx->device->name : "")); /* In case mlx5_dev_stop() has not been called. */ priv_dev_interrupt_handler_uninstall(priv, dev); - priv_destroy_hash_rxqs(priv); - /* Prevent crashes when queues are still in use. */ dev->rx_pkt_burst = removed_rx_burst; dev->tx_pkt_burst = removed_tx_burst; diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 5058bcd..7058256 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -126,13 +126,7 @@ struct priv { unsigned int txqs_n; /* TX queues array size. */ struct mlx5_rxq_data *(*rxqs)[]; /* RX queues. */ struct mlx5_txq_data *(*txqs)[]; /* TX queues. */ - /* Indirection tables referencing all RX WQs. */ - struct ibv_exp_rwq_ind_table *(*ind_tables)[]; - unsigned int ind_tables_n; /* Number of indirection tables. */ unsigned int ind_table_max_size; /* Maximum indirection table size. */ - /* Hash RX QPs feeding the indirection table. */ - struct hash_rxq (*hash_rxqs)[]; - unsigned int hash_rxqs_n; /* Hash RX QPs array size. */ struct rte_eth_rss_conf rss_conf; /* RSS configuration. */ struct rte_intr_handle intr_handle; /* Interrupt handler. */ unsigned int (*reta_idx)[]; /* RETA index table. */ diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index d5dc928..762288b 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -64,121 +64,6 @@ #include "mlx5_autoconf.h" #include "mlx5_defs.h" -/* Initialization data for hash RX queues. */ -const struct hash_rxq_init hash_rxq_init[] = { - [HASH_RXQ_TCPV4] = { - .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | - IBV_EXP_RX_HASH_DST_IPV4 | - IBV_EXP_RX_HASH_SRC_PORT_TCP | - IBV_EXP_RX_HASH_DST_PORT_TCP), - .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV4_TCP, - .flow_priority = 0, - .flow_spec.tcp_udp = { - .type = IBV_EXP_FLOW_SPEC_TCP, - .size = sizeof(hash_rxq_init[0].flow_spec.tcp_udp), - }, - .underlayer = &hash_rxq_init[HASH_RXQ_IPV4], - }, - [HASH_RXQ_UDPV4] = { - .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | - IBV_EXP_RX_HASH_DST_IPV4 | - IBV_EXP_RX_HASH_SRC_PORT_UDP | - IBV_EXP_RX_HASH_DST_PORT_UDP), - .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV4_UDP, - .flow_priority = 0, - .flow_spec.tcp_udp = { - .type = IBV_EXP_FLOW_SPEC_UDP, - .size = sizeof(hash_rxq_init[0].flow_spec.tcp_udp), - }, - .underlayer = &hash_rxq_init[HASH_RXQ_IPV4], - }, - [HASH_RXQ_IPV4] = { - .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | - IBV_EXP_RX_HASH_DST_IPV4), - .dpdk_rss_hf = (ETH_RSS_IPV4 | - ETH_RSS_FRAG_IPV4), - .flow_priority = 1, - .flow_spec.ipv4 = { - .type = IBV_EXP_FLOW_SPEC_IPV4, - .size = sizeof(hash_rxq_init[0].flow_spec.ipv4), - }, - .underlayer = &hash_rxq_init[HASH_RXQ_ETH], - }, - [HASH_RXQ_TCPV6] = { - .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 | - IBV_EXP_RX_HASH_DST_IPV6 | - IBV_EXP_RX_HASH_SRC_PORT_TCP | - IBV_EXP_RX_HASH_DST_PORT_TCP), - .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_TCP, - .flow_priority = 0, - .flow_spec.tcp_udp = { - .type = IBV_EXP_FLOW_SPEC_TCP, - .size = sizeof(hash_rxq_init[0].flow_spec.tcp_udp), - }, - .underlayer = &hash_rxq_init[HASH_RXQ_IPV6], - }, - [HASH_RXQ_UDPV6] = { - .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 | - IBV_EXP_RX_HASH_DST_
[dpdk-dev] [PATCH v1 21/21] net/mlx5: support RSS hash configuration in generic flow action
This also bring back the RSS support on all flows created by default from the control plane. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 437 ++- 1 file changed, 346 insertions(+), 91 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 8316255..fe21dac 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -87,12 +87,89 @@ mlx5_flow_create_vxlan(const struct rte_flow_item *item, const void *default_mask, void *data); +/* Hash RX queue types. */ +enum hash_rxq_type { + HASH_RXQ_TCPV4, + HASH_RXQ_UDPV4, + HASH_RXQ_IPV4, + HASH_RXQ_TCPV6, + HASH_RXQ_UDPV6, + HASH_RXQ_IPV6, + HASH_RXQ_ETH, +}; + +/* Initialization data for hash RX queue. */ +struct hash_rxq_init { + uint64_t hash_fields; /* Fields that participate in the hash. */ + uint64_t dpdk_rss_hf; /* Matching DPDK RSS hash fields. */ + unsigned int flow_priority; /* Flow priority to use. */ +}; + +/* Initialization data for hash RX queues. */ +const struct hash_rxq_init hash_rxq_init[] = { + [HASH_RXQ_TCPV4] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | + IBV_EXP_RX_HASH_DST_IPV4 | + IBV_EXP_RX_HASH_SRC_PORT_TCP | + IBV_EXP_RX_HASH_DST_PORT_TCP), + .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV4_TCP, + .flow_priority = 4, + }, + [HASH_RXQ_UDPV4] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | + IBV_EXP_RX_HASH_DST_IPV4 | + IBV_EXP_RX_HASH_SRC_PORT_UDP | + IBV_EXP_RX_HASH_DST_PORT_UDP), + .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV4_UDP, + .flow_priority = 4, + }, + [HASH_RXQ_IPV4] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 | + IBV_EXP_RX_HASH_DST_IPV4), + .dpdk_rss_hf = (ETH_RSS_IPV4 | + ETH_RSS_FRAG_IPV4), + .flow_priority = 5, + }, + [HASH_RXQ_TCPV6] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 | + IBV_EXP_RX_HASH_DST_IPV6 | + IBV_EXP_RX_HASH_SRC_PORT_TCP | + IBV_EXP_RX_HASH_DST_PORT_TCP), + .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_TCP, + .flow_priority = 4, + }, + [HASH_RXQ_UDPV6] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 | + IBV_EXP_RX_HASH_DST_IPV6 | + IBV_EXP_RX_HASH_SRC_PORT_UDP | + IBV_EXP_RX_HASH_DST_PORT_UDP), + .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_UDP, + .flow_priority = 4, + }, + [HASH_RXQ_IPV6] = { + .hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 | + IBV_EXP_RX_HASH_DST_IPV6), + .dpdk_rss_hf = (ETH_RSS_IPV6 | + ETH_RSS_FRAG_IPV6), + .flow_priority = 5, + }, + [HASH_RXQ_ETH] = { + .hash_fields = 0, + .dpdk_rss_hf = 0, + .flow_priority = 6, + }, +}; + +/* Number of entries in hash_rxq_init[]. */ +const unsigned int hash_rxq_init_n = RTE_DIM(hash_rxq_init); + struct rte_flow { TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ - struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ - struct ibv_exp_flow *ibv_flow; /**< Verbs flow. */ - struct mlx5_hrxq *hrxq; /**< Hash Rx queue. */ uint32_t mark:1; /**< Set if the flow is marked. */ + struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */ + struct mlx5_hrxq *hrxqs[RTE_DIM(hash_rxq_init)]; /**< Hash Rx queues. */ + struct ibv_exp_flow *ibv_flows[RTE_DIM(hash_rxq_init)]; + /**< Verbs flows. */ }; /** Static initializer for items. */ @@ -271,6 +348,7 @@ struct mlx5_flow_action { uint32_t mark_id; /**< Mark identifier. */ uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */ uint16_t queues_n; /**< Number of entries in queue[]. */ + const struct rte_eth_rss_conf *rss_conf; /**< User RSS configuration. */ }; /** Structure to pass to the conversion function. */ @@ -278,7 +356,6 @@ struct mlx5_flow_parse { struct ibv_exp_flow_attr *ibv_attr; /**< Verbs attribute. */ unsigned int offset; /**< Offset in bytes in the ibv_attr buffer. */ uint32_t inner; /**< Set once VXLAN is encountered. */ - uint64_t hash_fields; /**< Fields that participate in the hash. */ struct mlx
[dpdk-dev] [PATCH v2] net/mlx5: enable/disable vPMD and some cleanups
This series add more information and flexibility to the user to use or not the vPMD. An information will be printed to inform the user which Tx/Rx function have been automatically selected in addition, new device parameters are added to disable Tx/Rx vector (see device documentation for more details). Changes in v2: Remove other patches to only leave the most important one, the capability for the user to deactivate the Tx/Rx vector code at runtime. It can be very useful to blame this young code in cases of issues without having to tweak and recompile the code to reach the same goal. Other patches will be differed for the next release has they are less important. Nelio Laranjeiro (1): net/mlx5: add parameters to enable/disable vector code doc/guides/nics/mlx5.rst | 14 ++ drivers/net/mlx5/mlx5.c | 23 +++ drivers/net/mlx5/mlx5.h | 2 ++ drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 9 +++-- 4 files changed, 46 insertions(+), 2 deletions(-) -- 2.1.4
[dpdk-dev] [PATCH v2] net/mlx5: add parameters to enable/disable vector code
Vector code is very young and can present some issues for users, to avoid them to modify the selections function by commenting the code and recompile the PMD, new devices parameters are added to deactivate the Tx and/or Rx vector code. By using such device parameters, the user will be able to fall back to regular burst functions. Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- doc/guides/nics/mlx5.rst | 14 ++ drivers/net/mlx5/mlx5.c | 23 +++ drivers/net/mlx5/mlx5.h | 2 ++ drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 9 +++-- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index db15118..f4cb18b 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -254,6 +254,20 @@ Run-time configuration When hardware TSO is enabled, packets marked with TCP segmentation offload will be divided into segments by the hardware. Disabled by default. +- ``tx_vec_en`` parameter [int] + + A nonzero value enables Tx vector on ConnectX-5 only NIC if the number of + global Tx queues on the port is lesser than MLX5_VPMD_MIN_TXQS. + + Enabled by default on ConnectX-5. + +- ``rx_vec_en`` parameter [int] + + A nonzero value enables Rx vector if the port is not configured in + multi-segment otherwise this parameter is ignored. + + Enabled by default. + Prerequisites - diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 757c910..b7e5046 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -94,6 +94,12 @@ /* Device parameter to enable hardware TSO offload. */ #define MLX5_TSO "tso" +/* Device parameter to enable hardware Tx vector. */ +#define MLX5_TX_VEC_EN "tx_vec_en" + +/* Device parameter to enable hardware Rx vector. */ +#define MLX5_RX_VEC_EN "rx_vec_en" + /* Default PMD specific parameter value. */ #define MLX5_ARG_UNSET (-1) @@ -105,6 +111,8 @@ struct mlx5_args { int mpw_hdr_dseg; int inline_max_packet_sz; int tso; + int tx_vec_en; + int rx_vec_en; }; /** * Retrieve integer value from environment variable. @@ -324,6 +332,10 @@ mlx5_args_check(const char *key, const char *val, void *opaque) args->inline_max_packet_sz = tmp; } else if (strcmp(MLX5_TSO, key) == 0) { args->tso = !!tmp; + } else if (strcmp(MLX5_TX_VEC_EN, key) == 0) { + args->tx_vec_en = !!tmp; + } else if (strcmp(MLX5_RX_VEC_EN, key) == 0) { + args->rx_vec_en = !!tmp; } else { WARN("%s: unknown parameter", key); return -EINVAL; @@ -353,6 +365,8 @@ mlx5_args(struct mlx5_args *args, struct rte_devargs *devargs) MLX5_TXQ_MPW_HDR_DSEG_EN, MLX5_TXQ_MAX_INLINE_LEN, MLX5_TSO, + MLX5_TX_VEC_EN, + MLX5_RX_VEC_EN, NULL, }; struct rte_kvargs *kvlist; @@ -408,6 +422,10 @@ mlx5_args_assign(struct priv *priv, struct mlx5_args *args) priv->inline_max_packet_sz = args->inline_max_packet_sz; if (args->tso != MLX5_ARG_UNSET) priv->tso = args->tso; + if (args->tx_vec_en != MLX5_ARG_UNSET) + priv->tx_vec_en = args->tx_vec_en; + if (args->rx_vec_en != MLX5_ARG_UNSET) + priv->rx_vec_en = args->rx_vec_en; } /** @@ -553,6 +571,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) .mpw_hdr_dseg = MLX5_ARG_UNSET, .inline_max_packet_sz = MLX5_ARG_UNSET, .tso = MLX5_ARG_UNSET, + .tx_vec_en = MLX5_ARG_UNSET, + .rx_vec_en = MLX5_ARG_UNSET, }; exp_device_attr.comp_mask = @@ -615,6 +635,9 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) priv->mps = mps; /* Enable MPW by default if supported. */ priv->cqe_comp = 1; /* Enable compression by default. */ priv->tunnel_en = tunnel_en; + /* Enable vector by default if supported. */ + priv->tx_vec_en = 1; + priv->rx_vec_en = 1; err = mlx5_args(&args, pci_dev->device.devargs); if (err) { ERROR("failed to process device arguments: %s", diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index f16f778..43c5384 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -131,6 +131,8 @@ struct priv { unsigned int tso:1; /* Whether TSO is supported. */ unsigned int tunnel_en:1; unsigned int isolated:1; /* Whether isolated mode is enabled. */ + unsigned i
[dpdk-dev] [PATCH v2] net/mlx5: fix MTU update
Changing the MTU is not related to changing the number of segments, activating or not the multi-segment support should be handled by the application. Fixes: 9964b965ad69 ("net/mlx5: re-add Rx scatter support") Cc: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro Acked-by: Yongseok Koh --- Changes in v2: change rxq_ctrl_setup() to be static. --- drivers/net/mlx5/mlx5_ethdev.c | 127 ++--- drivers/net/mlx5/mlx5_rxq.c| 69 +- drivers/net/mlx5/mlx5_rxtx.h | 4 -- 3 files changed, 17 insertions(+), 183 deletions(-) diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index 08cc814..b0eb3cd 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -924,12 +924,6 @@ mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete) /** * DPDK callback to change the MTU. * - * Setting the MTU affects hardware MRU (packets larger than the MTU cannot be - * received). Use this as a hint to enable/disable scattered packets support - * and improve performance when not needed. - * Since failure is not an option, reconfiguring queues on the fly is not - * recommended. - * * @param dev * Pointer to Ethernet device structure. * @param in_mtu @@ -942,122 +936,33 @@ int mlx5_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) { struct priv *priv = dev->data->dev_private; + uint16_t kern_mtu; int ret = 0; - unsigned int i; - unsigned int max_frame_len; - int rehash; - int restart = priv->started; if (mlx5_is_secondary()) return -E_RTE_SECONDARY; priv_lock(priv); + ret = priv_get_mtu(priv, &kern_mtu); + if (ret) + goto out; /* Set kernel interface MTU first. */ - if (priv_set_mtu(priv, mtu)) { - ret = errno; - WARN("cannot set port %u MTU to %u: %s", priv->port, mtu, -strerror(ret)); + ret = priv_set_mtu(priv, mtu); + if (ret) goto out; - } else + ret = priv_get_mtu(priv, &kern_mtu); + if (ret) + goto out; + if (kern_mtu == mtu) { + priv->mtu = mtu; DEBUG("adapter port %u MTU set to %u", priv->port, mtu); - /* Temporarily replace RX handler with a fake one, assuming it has not -* been copied elsewhere. */ - dev->rx_pkt_burst = removed_rx_burst; - /* Make sure everyone has left dev->rx_pkt_burst() and uses -* removed_rx_burst() instead. */ - rte_wmb(); - usleep(1000); - /* MTU does not include header and CRC. */ - max_frame_len = ETHER_HDR_LEN + mtu + ETHER_CRC_LEN; - /* Check if at least one queue is going to need a SGE update. */ - for (i = 0; i != priv->rxqs_n; ++i) { - struct rxq *rxq = (*priv->rxqs)[i]; - unsigned int mb_len; - unsigned int size = RTE_PKTMBUF_HEADROOM + max_frame_len; - unsigned int sges_n; - - if (rxq == NULL) - continue; - mb_len = rte_pktmbuf_data_room_size(rxq->mp); - assert(mb_len >= RTE_PKTMBUF_HEADROOM); - /* -* Determine the number of SGEs needed for a full packet -* and round it to the next power of two. -*/ - sges_n = log2above((size / mb_len) + !!(size % mb_len)); - if (sges_n != rxq->sges_n) - break; } - /* -* If all queues have the right number of SGEs, a simple rehash -* of their buffers is enough, otherwise SGE information can only -* be updated in a queue by recreating it. All resources that depend -* on queues (flows, indirection tables) must be recreated as well in -* that case. -*/ - rehash = (i == priv->rxqs_n); - if (!rehash) { - /* Clean up everything as with mlx5_dev_stop(). */ - priv_special_flow_disable_all(priv); - priv_mac_addrs_disable(priv); - priv_destroy_hash_rxqs(priv); - priv_fdir_disable(priv); - priv_dev_interrupt_handler_uninstall(priv, dev); - } -recover: - /* Reconfigure each RX queue. */ - for (i = 0; (i != priv->rxqs_n); ++i) { - struct rxq *rxq = (*priv->rxqs)[i]; - struct rxq_ctrl *rxq_ctrl = - container_of(rxq, struct rxq_ctrl, rxq); - unsigned int mb_len; - unsigned int tmp; - - if (rxq == NULL) - continue; - mb_len = rte_pktmbuf_data_room_size(rxq->mp); - assert(mb_len >= RTE_PKTMBUF_HEADROOM); - /* Provide new values to rxq_setup(). */ -
[dpdk-dev] [PATCH] net/mlx5: fix Tx when first segment size is too short
First segment size must be 18 bytes, packets not respecting this are silently not sent by the NIC but counted as sent by the PMD. The only way to figure out is compiling the PMD in debug mode. Cc: sta...@dpdk.org Fixes: 6579c27c11a5 ("net/mlx5: remove gather loop on segments") Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_rxtx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index 823aac8..e2e8a22 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -485,7 +485,8 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) #ifdef MLX5_PMD_SOFT_COUNTERS total_length = length; #endif - assert(length >= MLX5_WQE_DWORD_SIZE); + if (length < (MLX5_WQE_DWORD_SIZE + 2)) + break; /* Update element. */ (*txq->elts)[elts_head] = buf; elts_head = (elts_head + 1) & (elts_n - 1); -- 2.1.4
[dpdk-dev] [PATCH] net/mlx5: fix Tx when first segment size is too short
First segment size must be at least 18 bytes, packets not respecting this are silently not sent by the NIC but counted as sent by the PMD. The only way to figure out is compiling the PMD in debug mode. Cc: sta...@dpdk.org Fixes: 6579c27c11a5 ("net/mlx5: remove gather loop on segments") Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil Acked-by: Yongseok Koh --- v2: fix the commit log. --- drivers/net/mlx5/mlx5_rxtx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index 823aac8..e2e8a22 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -485,7 +485,8 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) #ifdef MLX5_PMD_SOFT_COUNTERS total_length = length; #endif - assert(length >= MLX5_WQE_DWORD_SIZE); + if (length < (MLX5_WQE_DWORD_SIZE + 2)) + break; /* Update element. */ (*txq->elts)[elts_head] = buf; elts_head = (elts_head + 1) & (elts_n - 1); -- 2.1.4
[dpdk-dev] [PATCH 2/2] net/mlx5: fix RSS flow rule with non existing queues
RSS flow rule validation accepts any queue even non existing ones which causes a segmentation fault at creation time. Fixes: fb4db56ea074 ("net/mlx5: support RSS action flow rule") Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_flow.c | 20 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index b34be55..3691e95 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -488,16 +488,18 @@ priv_flow_validate(struct priv *priv, break; } } - if (action->queues_n && !found) { + if (action->queues_n > 1 && !found) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions, "queue action not in RSS queues"); return -rte_errno; } - action->queue = 1; - action->queues_n = 1; - action->queues[0] = queue->index; + if (!found) { + action->queue = 1; + action->queues_n = 1; + action->queues[0] = queue->index; + } } else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) { const struct rte_flow_action_rss *rss = (const struct rte_flow_action_rss *) @@ -524,6 +526,16 @@ priv_flow_validate(struct priv *priv, return -rte_errno; } } + for (n = 0; n < rss->num; ++n) { + if (rss->queue[n] >= priv->rxqs_n) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "queue id > number of" + " queues"); + return -rte_errno; + } + } action->queue = 1; for (n = 0; n < rss->num; ++n) action->queues[n] = rss->queue[n]; -- 2.1.4
[dpdk-dev] [PATCH 1/2] net/mlx5: remove duplicated process
Flow validation already processes the final actions to verify if a rule can be applied or not and the same is done during creation. As the creation function relies on validation to generate and apply a rule, this job can be fully handled by the validation function. Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_flow.c | 115 --- 1 file changed, 43 insertions(+), 72 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 5468642..b34be55 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -377,6 +377,8 @@ mlx5_flow_item_validate(const struct rte_flow_item *item, * Perform verbose error reporting if not NULL. * @param[in, out] flow * Flow structure to update. + * @param[in, out] action + * Action structure to update. * * @return * 0 on success, a negative errno value otherwise and rte_errno is set. @@ -387,14 +389,10 @@ priv_flow_validate(struct priv *priv, const struct rte_flow_item items[], const struct rte_flow_action actions[], struct rte_flow_error *error, - struct mlx5_flow *flow) + struct mlx5_flow *flow, + struct mlx5_flow_action *action) { const struct mlx5_flow_items *cur_item = mlx5_flow_items; - struct mlx5_flow_action action = { - .queue = 0, - .drop = 0, - .mark = 0, - }; (void)priv; if (attr->group) { @@ -474,7 +472,7 @@ priv_flow_validate(struct priv *priv, if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) { continue; } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) { - action.drop = 1; + action->drop = 1; } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) { const struct rte_flow_action_queue *queue = (const struct rte_flow_action_queue *) @@ -484,34 +482,35 @@ priv_flow_validate(struct priv *priv, if (!queue || (queue->index > (priv->rxqs_n - 1))) goto exit_action_not_supported; - for (n = 0; n < action.queues_n; ++n) { - if (action.queues[n] == queue->index) { + for (n = 0; n < action->queues_n; ++n) { + if (action->queues[n] == queue->index) { found = 1; break; } } - if (action.queues_n && !found) { + if (action->queues_n && !found) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions, "queue action not in RSS queues"); return -rte_errno; } - action.queue = 1; - action.queues_n = 1; - action.queues[0] = queue->index; + action->queue = 1; + action->queues_n = 1; + action->queues[0] = queue->index; } else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) { const struct rte_flow_action_rss *rss = (const struct rte_flow_action_rss *) actions->conf; uint16_t n; - if (action.queues_n == 1) { + if (action->queues_n == 1) { uint16_t found = 0; - assert(action.queues_n); + assert(action->queues_n); for (n = 0; n < rss->num; ++n) { - if (action.queues[0] == rss->queue[n]) { + if (action->queues[0] == + rss->queue[n]) { found = 1; break; } @@ -525,10 +524,10 @@ priv_flow_validate(struct priv *priv, return -rte_errno; } } - action.queue = 1; + action->queue = 1; for (n = 0; n < rss->num; ++n) - ac
[dpdk-dev] [PATCH] net/mlx5: fix mark id retrieval
Mark ID in the completion queue entry is 24 bits, the remaining 8 bits are reserved and may be nonzero. Do not take them into account when looking for marked packets. CC: sta...@dpdk.org Fixes: ea3bc3b1df94 ("net/mlx5: support mark flow action") Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_prm.h | 7 +++ drivers/net/mlx5/mlx5_rxtx.c | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h index 155bdba..608072f 100644 --- a/drivers/net/mlx5/mlx5_prm.h +++ b/drivers/net/mlx5/mlx5_prm.h @@ -138,6 +138,13 @@ /* Inner L4 checksum offload (Tunneled packets only). */ #define MLX5_ETH_WQE_L4_INNER_CSUM (1u << 5) +/* Is flow mark valid. */ +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN +#define MLX5_FLOW_MARK_IS_VALID(val) ((val) & 0xff00) +#else +#define MLX5_FLOW_MARK_IS_VALID(val) ((val) & 0xff) +#endif + /* INVALID is used by packets matching no flow rules. */ #define MLX5_FLOW_MARK_INVALID 0 diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index a1dd84a..1c5311c 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -1953,8 +1953,8 @@ 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))) { + if (rxq->mark && + MLX5_FLOW_MARK_IS_VALID(cqe->sop_drop_qpn)) { pkt->ol_flags |= PKT_RX_FDIR; if (cqe->sop_drop_qpn != htonl(MLX5_FLOW_MARK_DEFAULT)) { -- 2.1.4
[dpdk-dev] [PATCH] net/mlx5: remove duplicated process
Flow validation already processes the final actions to verify if a rule can be applied or not and the same is done during creation. As the creation function relies on validation to generate and apply a rule, this job can be fully handled by the validation function. Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil Acked-by: Yongseok Koh --- drivers/net/mlx5/mlx5_flow.c | 115 --- 1 file changed, 43 insertions(+), 72 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 5468642..b34be55 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -377,6 +377,8 @@ mlx5_flow_item_validate(const struct rte_flow_item *item, * Perform verbose error reporting if not NULL. * @param[in, out] flow * Flow structure to update. + * @param[in, out] action + * Action structure to update. * * @return * 0 on success, a negative errno value otherwise and rte_errno is set. @@ -387,14 +389,10 @@ priv_flow_validate(struct priv *priv, const struct rte_flow_item items[], const struct rte_flow_action actions[], struct rte_flow_error *error, - struct mlx5_flow *flow) + struct mlx5_flow *flow, + struct mlx5_flow_action *action) { const struct mlx5_flow_items *cur_item = mlx5_flow_items; - struct mlx5_flow_action action = { - .queue = 0, - .drop = 0, - .mark = 0, - }; (void)priv; if (attr->group) { @@ -474,7 +472,7 @@ priv_flow_validate(struct priv *priv, if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) { continue; } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) { - action.drop = 1; + action->drop = 1; } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) { const struct rte_flow_action_queue *queue = (const struct rte_flow_action_queue *) @@ -484,34 +482,35 @@ priv_flow_validate(struct priv *priv, if (!queue || (queue->index > (priv->rxqs_n - 1))) goto exit_action_not_supported; - for (n = 0; n < action.queues_n; ++n) { - if (action.queues[n] == queue->index) { + for (n = 0; n < action->queues_n; ++n) { + if (action->queues[n] == queue->index) { found = 1; break; } } - if (action.queues_n && !found) { + if (action->queues_n && !found) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions, "queue action not in RSS queues"); return -rte_errno; } - action.queue = 1; - action.queues_n = 1; - action.queues[0] = queue->index; + action->queue = 1; + action->queues_n = 1; + action->queues[0] = queue->index; } else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) { const struct rte_flow_action_rss *rss = (const struct rte_flow_action_rss *) actions->conf; uint16_t n; - if (action.queues_n == 1) { + if (action->queues_n == 1) { uint16_t found = 0; - assert(action.queues_n); + assert(action->queues_n); for (n = 0; n < rss->num; ++n) { - if (action.queues[0] == rss->queue[n]) { + if (action->queues[0] == + rss->queue[n]) { found = 1; break; } @@ -525,10 +524,10 @@ priv_flow_validate(struct priv *priv, return -rte_errno; } } - action.queue = 1; + action->queue = 1; for (n = 0; n < rss->num; ++n) - ac
[dpdk-dev] [PATCH] net/mlx5: fix RSS flow rule with non existing queues
RSS flow rule validation accepts any queue even non existing ones which causes a segmentation fault at creation time. Fixes: fb4db56ea074 ("net/mlx5: support RSS action flow rule") Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil Acked-by: Yongseok Koh --- To be integrated after DPDK 17.05-rc1 v2: split the patch-set in two distinct patches. --- drivers/net/mlx5/mlx5_flow.c | 20 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index b34be55..3691e95 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -488,16 +488,18 @@ priv_flow_validate(struct priv *priv, break; } } - if (action->queues_n && !found) { + if (action->queues_n > 1 && !found) { rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions, "queue action not in RSS queues"); return -rte_errno; } - action->queue = 1; - action->queues_n = 1; - action->queues[0] = queue->index; + if (!found) { + action->queue = 1; + action->queues_n = 1; + action->queues[0] = queue->index; + } } else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) { const struct rte_flow_action_rss *rss = (const struct rte_flow_action_rss *) @@ -524,6 +526,16 @@ priv_flow_validate(struct priv *priv, return -rte_errno; } } + for (n = 0; n < rss->num; ++n) { + if (rss->queue[n] >= priv->rxqs_n) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + actions, + "queue id > number of" + " queues"); + return -rte_errno; + } + } action->queue = 1; for (n = 0; n < rss->num; ++n) action->queues[n] = rss->queue[n]; -- 2.1.4
[dpdk-dev] [PATCH] net/mlx5: fix startup when flow cannot be applied
When flows cannot be re-applied due to configuration modifications, the start function should rollback the configuration done. Fixes: 2097d0d1e2cc ("net/mlx5: support basic flow items and actions") Cc: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_trigger.c | 21 - 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c index 30addd2..683b57c 100644 --- a/drivers/net/mlx5/mlx5_trigger.c +++ b/drivers/net/mlx5/mlx5_trigger.c @@ -82,17 +82,28 @@ mlx5_dev_start(struct rte_eth_dev *dev) ERROR("%p: an error occurred while configuring hash RX queues:" " %s", (void *)priv, strerror(err)); - /* Rollback. */ - priv_special_flow_disable_all(priv); - priv_mac_addrs_disable(priv); - priv_destroy_hash_rxqs(priv); + goto error; } if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_NONE) priv_fdir_enable(priv); - priv_dev_interrupt_handler_install(priv, dev); err = priv_flow_start(priv); + if (!err) { + priv->started = 0; + ERROR("%p: an error occurred while configuring flows:" + " %s", + (void *)priv, strerror(err)); + goto error; + } + priv_dev_interrupt_handler_install(priv, dev); priv_xstats_init(priv); priv_unlock(priv); + return 0; +error: + /* Rollback. */ + priv_special_flow_disable_all(priv); + priv_mac_addrs_disable(priv); + priv_destroy_hash_rxqs(priv); + priv_flow_stop(priv); return -err; } -- 2.1.4
[dpdk-dev] [PATCH] net/mlx5: fix supported packets types
Fixes: 0603df73a077 ("net/mlx5: fix Rx packet validation and type") Cc: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_ethdev.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index 2145965..f6396f5 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -667,10 +667,10 @@ mlx5_dev_supported_ptypes_get(struct rte_eth_dev *dev) { static const uint32_t ptypes[] = { /* refers to rxq_cq_to_pkt_type() */ - RTE_PTYPE_L3_IPV4, - RTE_PTYPE_L3_IPV6, - RTE_PTYPE_INNER_L3_IPV4, - RTE_PTYPE_INNER_L3_IPV6, + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, + RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, + RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN, + RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN, RTE_PTYPE_UNKNOWN }; -- 2.1.4
[dpdk-dev] [PATCH] net/mlx5: fix a wrong error handler
The returned error code was wrongly handled causing the PMD to refuse to start. Fixes: 91572d2a0b1a ("net/mlx5: fix startup when flow cannot be applied") CC: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c index 683b57c..0acbf28 100644 --- a/drivers/net/mlx5/mlx5_trigger.c +++ b/drivers/net/mlx5/mlx5_trigger.c @@ -87,7 +87,7 @@ mlx5_dev_start(struct rte_eth_dev *dev) if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_NONE) priv_fdir_enable(priv); err = priv_flow_start(priv); - if (!err) { + if (err) { priv->started = 0; ERROR("%p: an error occurred while configuring flows:" " %s", -- 2.1.4
[dpdk-dev] [PATCH] net/mlx5: fix flow mark action handling
Mark value is always reported even when not requested or invalid. Fixes: ea3bc3b1df94 ("net/mlx5: support mark flow action") CC: sta...@dpdk.org Reported-by: Mark Bloch Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_rxtx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index b2b7223..e152776 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -1431,7 +1431,7 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) } if (rxq->mark && ((cqe->sop_drop_qpn != - htonl(MLX5_FLOW_MARK_INVALID)) || + htonl(MLX5_FLOW_MARK_INVALID)) && (cqe->sop_drop_qpn != htonl(MLX5_FLOW_MARK_DEFAULT { pkt->hash.fdir.hi = -- 2.1.4
[dpdk-dev] [PATCH v2 0/9] net/mlx5: enhance flow API
Changes in v2: - Send series to dev@dpdk.org This series brings: - fixes: - handle error on Queue Pair creation. - Move a free to the right function. - Uses a single RSS drop queue for dropping flows. - Enhance IPv6 filtering by adding extra fields. - support rss hash result in combination of mark id. - support flag action. - support RSS action. Nelio Laranjeiro (9): net/mlx5: fix drop queue creation error net/mlx5: fix resources free in the right function net/mlx5: support ether type support in flow item net/mlx5: add RSS hash result with mark id net/mlx5: extend IPv6 flow item net/mlx5: support flag flow action net/mlx5: prepare support for RSS action rule net/mlx5: support RSS action flow rule net/mlx5: use an RSS drop queue drivers/net/mlx5/mlx5.h | 1 + drivers/net/mlx5/mlx5_flow.c | 439 --- drivers/net/mlx5/mlx5_prm.h | 7 +- drivers/net/mlx5/mlx5_rxtx.c | 20 +- 4 files changed, 386 insertions(+), 81 deletions(-) -- 2.1.4
[dpdk-dev] [PATCH v2 2/9] net/mlx5: fix resources free in the right function
ibv_attr should be freed in the function which allocates the memory. Fixes: 2097d0d1e2cc ("net/mlx5: support basic flow items and actions") CC: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 6765a77..0712926 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -974,7 +974,6 @@ priv_flow_create_action_queue(struct priv *priv, ibv_exp_destroy_wq(rte_flow->wq); if (!rte_flow->rxq && rte_flow->cq) ibv_destroy_cq(rte_flow->cq); - rte_free(rte_flow->ibv_attr); rte_free(rte_flow); return NULL; } @@ -1068,6 +1067,8 @@ priv_flow_create(struct priv *priv, } rte_flow = priv_flow_create_action_queue(priv, flow.ibv_attr, &action, error); + if (!rte_flow) + goto exit; return rte_flow; exit: rte_free(flow.ibv_attr); -- 2.1.4
[dpdk-dev] [PATCH v2 3/9] net/mlx5: support ether type support in flow item
Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 0712926..d3c0661 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -163,6 +163,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { .mask = &(const struct rte_flow_item_eth){ .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", + .type = -1, }, .default_mask = &rte_flow_item_eth_mask, .mask_sz = sizeof(struct rte_flow_item_eth), @@ -552,13 +553,16 @@ mlx5_flow_create_eth(const struct rte_flow_item *item, mask = default_mask; memcpy(eth->val.dst_mac, spec->dst.addr_bytes, ETHER_ADDR_LEN); memcpy(eth->val.src_mac, spec->src.addr_bytes, ETHER_ADDR_LEN); + eth->val.ether_type = spec->type; memcpy(eth->mask.dst_mac, mask->dst.addr_bytes, ETHER_ADDR_LEN); memcpy(eth->mask.src_mac, mask->src.addr_bytes, ETHER_ADDR_LEN); + eth->mask.ether_type = mask->type; /* Remove unwanted bits from values. */ for (i = 0; i < ETHER_ADDR_LEN; ++i) { eth->val.dst_mac[i] &= eth->mask.dst_mac[i]; eth->val.src_mac[i] &= eth->mask.src_mac[i]; } + eth->val.ether_type &= eth->mask.ether_type; return 0; } -- 2.1.4
[dpdk-dev] [PATCH v2 1/9] net/mlx5: fix drop queue creation error
Creating a drop queue in mlx5 ends by creating a non polled queue, but if the associated work queue could not be created the error was not handled ending in a undefined situation. Fixes: 2097d0d1e2cc ("net/mlx5: support basic flow items and actions") CC: sta...@dpdk.org Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 23c1b5e..6765a77 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -902,6 +902,12 @@ priv_flow_create_action_queue(struct priv *priv, .pd = priv->pd, .cq = rte_flow->cq, }); + if (!rte_flow->wq) { + rte_flow_error_set(error, ENOMEM, + RTE_FLOW_ERROR_TYPE_HANDLE, + NULL, "cannot allocate WQ"); + goto error; + } } else { rxq = container_of((*priv->rxqs)[action->queue_id], struct rxq_ctrl, rxq); -- 2.1.4
[dpdk-dev] [PATCH v2 4/9] net/mlx5: add RSS hash result with mark id
RSS hash and mark ID can now coexists. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c index 8f16f2f..122847d 100644 --- a/drivers/net/mlx5/mlx5_rxtx.c +++ b/drivers/net/mlx5/mlx5_rxtx.c @@ -1545,7 +1545,6 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 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 | -- 2.1.4
[dpdk-dev] [PATCH v2 5/9] net/mlx5: extend IPv6 flow item
This commit adds: - Vtc flow, - Protocol, - Hop limits Needs MLNX_OFED-4.0-0.0.7.0 or higher. Signed-off-by: Nelio Laranjeiro Acked-by: Adrien Mazarguil --- drivers/net/mlx5/mlx5_flow.c | 25 ++--- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index d3c0661..a885f6e 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -217,12 +217,15 @@ static const struct mlx5_flow_items mlx5_flow_items[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, + .vtc_flow = -1, + .proto = -1, + .hop_limits = -1, }, }, .default_mask = &rte_flow_item_ipv6_mask, .mask_sz = sizeof(struct rte_flow_item_ipv6), .convert = mlx5_flow_create_ipv6, - .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6), + .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6_ext), }, [RTE_FLOW_ITEM_TYPE_UDP] = { .items = ITEMS(RTE_FLOW_ITEM_TYPE_VXLAN), @@ -668,15 +671,14 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item, const struct rte_flow_item_ipv6 *spec = item->spec; const struct rte_flow_item_ipv6 *mask = item->mask; struct mlx5_flow *flow = (struct mlx5_flow *)data; - struct ibv_exp_flow_spec_ipv6 *ipv6; - unsigned int ipv6_size = sizeof(struct ibv_exp_flow_spec_ipv6); - unsigned int i; + struct ibv_exp_flow_spec_ipv6_ext *ipv6; + unsigned int ipv6_size = sizeof(struct ibv_exp_flow_spec_ipv6_ext); ++flow->ibv_attr->num_of_specs; flow->ibv_attr->priority = 1; ipv6 = (void *)((uintptr_t)flow->ibv_attr + flow->offset); - *ipv6 = (struct ibv_exp_flow_spec_ipv6) { - .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6, + *ipv6 = (struct ibv_exp_flow_spec_ipv6_ext) { + .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6_EXT, .size = ipv6_size, }; if (!spec) @@ -691,11 +693,12 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item, RTE_DIM(ipv6->mask.src_ip)); memcpy(ipv6->mask.dst_ip, mask->hdr.dst_addr, RTE_DIM(ipv6->mask.dst_ip)); - /* Remove unwanted bits from values. */ - for (i = 0; i < RTE_DIM(ipv6->val.src_ip); ++i) { - ipv6->val.src_ip[i] &= ipv6->mask.src_ip[i]; - ipv6->val.dst_ip[i] &= ipv6->mask.dst_ip[i]; - } + ipv6->mask.flow_label = mask->hdr.vtc_flow; + ipv6->mask.next_hdr = mask->hdr.proto; + ipv6->mask.hop_limit = mask->hdr.hop_limits; + ipv6->val.flow_label &= ipv6->mask.flow_label; + ipv6->val.next_hdr &= ipv6->mask.next_hdr; + ipv6->val.hop_limit &= ipv6->mask.hop_limit; return 0; } -- 2.1.4
[dpdk-dev] [PATCH v2 7/9] net/mlx5: prepare support for RSS action rule
In mlx5 PMD handling a single queue of several destination queues ends in creating the same Verbs attribute, the main difference resides in the indirection table and the RSS hash key. This helps to prepare the supports to the RSS queues by first handling the queue action has being an RSS queue with a single queue. No RSS hash key will be provided to the Verbs flow. Signed-off-by: Nelio Laranjeiro --- drivers/net/mlx5/mlx5_flow.c | 249 +-- 1 file changed, 190 insertions(+), 59 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 39a96ea..a188aa3 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -95,8 +95,10 @@ struct rte_flow { struct ibv_exp_flow *ibv_flow; /**< Verbs 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. */ + struct rxq *(*rxqs)[]; /**< Pointer to the queues array. */ + uint16_t rxqs_n; /**< Number of queues in this flow, 0 if drop queue. */ uint32_t mark:1; /**< Set if the flow is marked. */ + uint32_t drop:1; /**< Drop queue. */ }; /** Static initializer for items. */ @@ -279,8 +281,9 @@ 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. */ + uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */ + uint16_t queues_n; /**< Number of entries in queue[]. */ }; /** @@ -861,12 +864,128 @@ mlx5_flow_create_flag_mark(struct mlx5_flow *flow, uint32_t mark_id) } /** + * Complete flow rule creation with a drop queue. + * + * @param priv + * Pointer to private structure. + * @param flow + * MLX5 flow attributes (filled by mlx5_flow_validate()). + * @param[out] error + * Perform verbose error reporting if not NULL. + * + * @return + * A flow if the rule could be created. + */ +static struct rte_flow * +priv_flow_create_action_queue_drop(struct priv *priv, + struct mlx5_flow *flow, + struct rte_flow_error *error) +{ + struct rte_flow *rte_flow; + + assert(priv->pd); + assert(priv->ctx); + rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0); + if (!rte_flow) { + rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, + NULL, "cannot allocate flow memory"); + return NULL; + } + rte_flow->cq = + ibv_exp_create_cq(priv->ctx, 1, NULL, NULL, 0, + &(struct ibv_exp_cq_init_attr){ + .comp_mask = 0, + }); + if (!rte_flow->cq) { + rte_flow_error_set(error, ENOMEM, + RTE_FLOW_ERROR_TYPE_HANDLE, + NULL, "cannot allocate CQ"); + goto error; + } + rte_flow->wq = ibv_exp_create_wq(priv->ctx, +&(struct ibv_exp_wq_init_attr){ +.wq_type = IBV_EXP_WQT_RQ, +.max_recv_wr = 1, +.max_recv_sge = 1, +.pd = priv->pd, +.cq = rte_flow->cq, +}); + if (!rte_flow->wq) { + rte_flow_error_set(error, ENOMEM, + RTE_FLOW_ERROR_TYPE_HANDLE, + NULL, "cannot allocate WQ"); + goto error; + } + rte_flow->drop = 1; + rte_flow->ibv_attr = flow->ibv_attr; + rte_flow->ind_table = ibv_exp_create_rwq_ind_table( + priv->ctx, + &(struct ibv_exp_rwq_ind_table_init_attr){ + .pd = priv->pd, + .log_ind_tbl_size = 0, + .ind_tbl = &rte_flow->wq, + .comp_mask = 0, + }); + if (!rte_flow->ind_table) { + rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, + NULL, "cannot allocate indirection table"); + goto error; + } + rte_flow->qp = ibv_exp_create_qp( + priv->ctx, + &(struct ibv_exp_qp_init_attr){ + .qp_type = IBV_QPT