12e22920bSAdrien Mazarguil /*- 22e22920bSAdrien Mazarguil * BSD LICENSE 32e22920bSAdrien Mazarguil * 42e22920bSAdrien Mazarguil * Copyright 2015 6WIND S.A. 52e22920bSAdrien Mazarguil * Copyright 2015 Mellanox. 62e22920bSAdrien Mazarguil * 72e22920bSAdrien Mazarguil * Redistribution and use in source and binary forms, with or without 82e22920bSAdrien Mazarguil * modification, are permitted provided that the following conditions 92e22920bSAdrien Mazarguil * are met: 102e22920bSAdrien Mazarguil * 112e22920bSAdrien Mazarguil * * Redistributions of source code must retain the above copyright 122e22920bSAdrien Mazarguil * notice, this list of conditions and the following disclaimer. 132e22920bSAdrien Mazarguil * * Redistributions in binary form must reproduce the above copyright 142e22920bSAdrien Mazarguil * notice, this list of conditions and the following disclaimer in 152e22920bSAdrien Mazarguil * the documentation and/or other materials provided with the 162e22920bSAdrien Mazarguil * distribution. 172e22920bSAdrien Mazarguil * * Neither the name of 6WIND S.A. nor the names of its 182e22920bSAdrien Mazarguil * contributors may be used to endorse or promote products derived 192e22920bSAdrien Mazarguil * from this software without specific prior written permission. 202e22920bSAdrien Mazarguil * 212e22920bSAdrien Mazarguil * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 222e22920bSAdrien Mazarguil * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 232e22920bSAdrien Mazarguil * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 242e22920bSAdrien Mazarguil * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 252e22920bSAdrien Mazarguil * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 262e22920bSAdrien Mazarguil * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 272e22920bSAdrien Mazarguil * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 282e22920bSAdrien Mazarguil * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 292e22920bSAdrien Mazarguil * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 302e22920bSAdrien Mazarguil * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 312e22920bSAdrien Mazarguil * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 322e22920bSAdrien Mazarguil */ 332e22920bSAdrien Mazarguil 342e22920bSAdrien Mazarguil #include <assert.h> 352e22920bSAdrien Mazarguil #include <stdint.h> 362e22920bSAdrien Mazarguil #include <string.h> 372e22920bSAdrien Mazarguil #include <stdlib.h> 382e22920bSAdrien Mazarguil 392e22920bSAdrien Mazarguil /* Verbs header. */ 402e22920bSAdrien Mazarguil /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 412e22920bSAdrien Mazarguil #ifdef PEDANTIC 422e22920bSAdrien Mazarguil #pragma GCC diagnostic ignored "-pedantic" 432e22920bSAdrien Mazarguil #endif 442e22920bSAdrien Mazarguil #include <infiniband/verbs.h> 452e22920bSAdrien Mazarguil #ifdef PEDANTIC 462e22920bSAdrien Mazarguil #pragma GCC diagnostic error "-pedantic" 472e22920bSAdrien Mazarguil #endif 482e22920bSAdrien Mazarguil 492e22920bSAdrien Mazarguil /* DPDK headers don't like -pedantic. */ 502e22920bSAdrien Mazarguil #ifdef PEDANTIC 512e22920bSAdrien Mazarguil #pragma GCC diagnostic ignored "-pedantic" 522e22920bSAdrien Mazarguil #endif 532e22920bSAdrien Mazarguil #include <rte_mbuf.h> 542e22920bSAdrien Mazarguil #include <rte_mempool.h> 552e22920bSAdrien Mazarguil #include <rte_prefetch.h> 562e22920bSAdrien Mazarguil #include <rte_common.h> 572e22920bSAdrien Mazarguil #include <rte_branch_prediction.h> 580dc02ccaSAdrien Mazarguil #include <rte_memory.h> 592e22920bSAdrien Mazarguil #ifdef PEDANTIC 602e22920bSAdrien Mazarguil #pragma GCC diagnostic error "-pedantic" 612e22920bSAdrien Mazarguil #endif 622e22920bSAdrien Mazarguil 632e22920bSAdrien Mazarguil #include "mlx5.h" 642e22920bSAdrien Mazarguil #include "mlx5_utils.h" 652e22920bSAdrien Mazarguil #include "mlx5_rxtx.h" 66f3db9489SYaacov Hazan #include "mlx5_autoconf.h" 672e22920bSAdrien Mazarguil #include "mlx5_defs.h" 682e22920bSAdrien Mazarguil 692e22920bSAdrien Mazarguil /** 702e22920bSAdrien Mazarguil * Manage TX completions. 712e22920bSAdrien Mazarguil * 722e22920bSAdrien Mazarguil * When sending a burst, mlx5_tx_burst() posts several WRs. 732e22920bSAdrien Mazarguil * To improve performance, a completion event is only required once every 742e22920bSAdrien Mazarguil * MLX5_PMD_TX_PER_COMP_REQ sends. Doing so discards completion information 752e22920bSAdrien Mazarguil * for other WRs, but this information would not be used anyway. 762e22920bSAdrien Mazarguil * 772e22920bSAdrien Mazarguil * @param txq 782e22920bSAdrien Mazarguil * Pointer to TX queue structure. 792e22920bSAdrien Mazarguil * 802e22920bSAdrien Mazarguil * @return 812e22920bSAdrien Mazarguil * 0 on success, -1 on failure. 822e22920bSAdrien Mazarguil */ 832e22920bSAdrien Mazarguil static int 842e22920bSAdrien Mazarguil txq_complete(struct txq *txq) 852e22920bSAdrien Mazarguil { 862e22920bSAdrien Mazarguil unsigned int elts_comp = txq->elts_comp; 872e22920bSAdrien Mazarguil unsigned int elts_tail = txq->elts_tail; 88a859e8a9SNelio Laranjeiro unsigned int elts_free = txq->elts_tail; 892e22920bSAdrien Mazarguil const unsigned int elts_n = txq->elts_n; 902e22920bSAdrien Mazarguil int wcs_n; 912e22920bSAdrien Mazarguil 922e22920bSAdrien Mazarguil if (unlikely(elts_comp == 0)) 932e22920bSAdrien Mazarguil return 0; 942e22920bSAdrien Mazarguil #ifdef DEBUG_SEND 952e22920bSAdrien Mazarguil DEBUG("%p: processing %u work requests completions", 962e22920bSAdrien Mazarguil (void *)txq, elts_comp); 972e22920bSAdrien Mazarguil #endif 98e1682023SNelio Laranjeiro wcs_n = txq->poll_cnt(txq->cq, elts_comp); 992e22920bSAdrien Mazarguil if (unlikely(wcs_n == 0)) 1002e22920bSAdrien Mazarguil return 0; 1012e22920bSAdrien Mazarguil if (unlikely(wcs_n < 0)) { 1022e22920bSAdrien Mazarguil DEBUG("%p: ibv_poll_cq() failed (wcs_n=%d)", 1032e22920bSAdrien Mazarguil (void *)txq, wcs_n); 1042e22920bSAdrien Mazarguil return -1; 1052e22920bSAdrien Mazarguil } 1062e22920bSAdrien Mazarguil elts_comp -= wcs_n; 1072e22920bSAdrien Mazarguil assert(elts_comp <= txq->elts_comp); 1082e22920bSAdrien Mazarguil /* 1092e22920bSAdrien Mazarguil * Assume WC status is successful as nothing can be done about it 1102e22920bSAdrien Mazarguil * anyway. 1112e22920bSAdrien Mazarguil */ 1122e22920bSAdrien Mazarguil elts_tail += wcs_n * txq->elts_comp_cd_init; 1132e22920bSAdrien Mazarguil if (elts_tail >= elts_n) 1142e22920bSAdrien Mazarguil elts_tail -= elts_n; 115a859e8a9SNelio Laranjeiro 116a859e8a9SNelio Laranjeiro while (elts_free != elts_tail) { 117a859e8a9SNelio Laranjeiro struct txq_elt *elt = &(*txq->elts)[elts_free]; 118a859e8a9SNelio Laranjeiro unsigned int elts_free_next = 119a859e8a9SNelio Laranjeiro (((elts_free + 1) == elts_n) ? 0 : elts_free + 1); 120a859e8a9SNelio Laranjeiro struct rte_mbuf *tmp = elt->buf; 121a859e8a9SNelio Laranjeiro struct txq_elt *elt_next = &(*txq->elts)[elts_free_next]; 122a859e8a9SNelio Laranjeiro 123b185e63fSAdrien Mazarguil #ifndef NDEBUG 124b185e63fSAdrien Mazarguil /* Poisoning. */ 125b185e63fSAdrien Mazarguil memset(elt, 0x66, sizeof(*elt)); 126b185e63fSAdrien Mazarguil #endif 127a859e8a9SNelio Laranjeiro RTE_MBUF_PREFETCH_TO_FREE(elt_next->buf); 128a859e8a9SNelio Laranjeiro /* Faster than rte_pktmbuf_free(). */ 129a859e8a9SNelio Laranjeiro do { 130a859e8a9SNelio Laranjeiro struct rte_mbuf *next = NEXT(tmp); 131a859e8a9SNelio Laranjeiro 132a859e8a9SNelio Laranjeiro rte_pktmbuf_free_seg(tmp); 133a859e8a9SNelio Laranjeiro tmp = next; 134a859e8a9SNelio Laranjeiro } while (tmp != NULL); 135a859e8a9SNelio Laranjeiro elts_free = elts_free_next; 136a859e8a9SNelio Laranjeiro } 137a859e8a9SNelio Laranjeiro 1382e22920bSAdrien Mazarguil txq->elts_tail = elts_tail; 1392e22920bSAdrien Mazarguil txq->elts_comp = elts_comp; 1402e22920bSAdrien Mazarguil return 0; 1412e22920bSAdrien Mazarguil } 1422e22920bSAdrien Mazarguil 1432e22920bSAdrien Mazarguil /** 1448340392eSAdrien Mazarguil * Get Memory Pool (MP) from mbuf. If mbuf is indirect, the pool from which 1458340392eSAdrien Mazarguil * the cloned mbuf is allocated is returned instead. 1468340392eSAdrien Mazarguil * 1478340392eSAdrien Mazarguil * @param buf 1488340392eSAdrien Mazarguil * Pointer to mbuf. 1498340392eSAdrien Mazarguil * 1508340392eSAdrien Mazarguil * @return 1518340392eSAdrien Mazarguil * Memory pool where data is located for given mbuf. 1528340392eSAdrien Mazarguil */ 1538340392eSAdrien Mazarguil static struct rte_mempool * 1548340392eSAdrien Mazarguil txq_mb2mp(struct rte_mbuf *buf) 1558340392eSAdrien Mazarguil { 1568340392eSAdrien Mazarguil if (unlikely(RTE_MBUF_INDIRECT(buf))) 1578340392eSAdrien Mazarguil return rte_mbuf_from_indirect(buf)->pool; 1588340392eSAdrien Mazarguil return buf->pool; 1598340392eSAdrien Mazarguil } 1608340392eSAdrien Mazarguil 161491770faSNélio Laranjeiro static inline uint32_t 162491770faSNélio Laranjeiro txq_mp2mr(struct txq *txq, struct rte_mempool *mp) 163491770faSNélio Laranjeiro __attribute__((always_inline)); 164491770faSNélio Laranjeiro 1658340392eSAdrien Mazarguil /** 1662e22920bSAdrien Mazarguil * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[]. 1672e22920bSAdrien Mazarguil * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full, 1682e22920bSAdrien Mazarguil * remove an entry first. 1692e22920bSAdrien Mazarguil * 1702e22920bSAdrien Mazarguil * @param txq 1712e22920bSAdrien Mazarguil * Pointer to TX queue structure. 1722e22920bSAdrien Mazarguil * @param[in] mp 1732e22920bSAdrien Mazarguil * Memory Pool for which a Memory Region lkey must be returned. 1742e22920bSAdrien Mazarguil * 1752e22920bSAdrien Mazarguil * @return 1762e22920bSAdrien Mazarguil * mr->lkey on success, (uint32_t)-1 on failure. 1772e22920bSAdrien Mazarguil */ 178491770faSNélio Laranjeiro static inline uint32_t 179d1d914ebSOlivier Matz txq_mp2mr(struct txq *txq, struct rte_mempool *mp) 1802e22920bSAdrien Mazarguil { 1812e22920bSAdrien Mazarguil unsigned int i; 182491770faSNélio Laranjeiro uint32_t lkey = (uint32_t)-1; 1832e22920bSAdrien Mazarguil 1842e22920bSAdrien Mazarguil for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) { 1852e22920bSAdrien Mazarguil if (unlikely(txq->mp2mr[i].mp == NULL)) { 1862e22920bSAdrien Mazarguil /* Unknown MP, add a new MR for it. */ 1872e22920bSAdrien Mazarguil break; 1882e22920bSAdrien Mazarguil } 1892e22920bSAdrien Mazarguil if (txq->mp2mr[i].mp == mp) { 1902e22920bSAdrien Mazarguil assert(txq->mp2mr[i].lkey != (uint32_t)-1); 1912e22920bSAdrien Mazarguil assert(txq->mp2mr[i].mr->lkey == txq->mp2mr[i].lkey); 192491770faSNélio Laranjeiro lkey = txq->mp2mr[i].lkey; 193491770faSNélio Laranjeiro break; 1942e22920bSAdrien Mazarguil } 1952e22920bSAdrien Mazarguil } 196491770faSNélio Laranjeiro if (unlikely(lkey == (uint32_t)-1)) 197491770faSNélio Laranjeiro lkey = txq_mp2mr_reg(txq, mp, i); 198491770faSNélio Laranjeiro return lkey; 1990a3b350dSOlga Shern } 2000a3b350dSOlga Shern 201e192ef80SYaacov Hazan /** 202e192ef80SYaacov Hazan * Insert VLAN using mbuf headroom space. 203e192ef80SYaacov Hazan * 204e192ef80SYaacov Hazan * @param buf 205e192ef80SYaacov Hazan * Buffer for VLAN insertion. 206e192ef80SYaacov Hazan * 207e192ef80SYaacov Hazan * @return 208e192ef80SYaacov Hazan * 0 on success, errno value on failure. 209e192ef80SYaacov Hazan */ 210e192ef80SYaacov Hazan static inline int 211e192ef80SYaacov Hazan insert_vlan_sw(struct rte_mbuf *buf) 212e192ef80SYaacov Hazan { 213e192ef80SYaacov Hazan uintptr_t addr; 214e192ef80SYaacov Hazan uint32_t vlan; 215e192ef80SYaacov Hazan uint16_t head_room_len = rte_pktmbuf_headroom(buf); 216e192ef80SYaacov Hazan 217e192ef80SYaacov Hazan if (head_room_len < 4) 218e192ef80SYaacov Hazan return EINVAL; 219e192ef80SYaacov Hazan 220e192ef80SYaacov Hazan addr = rte_pktmbuf_mtod(buf, uintptr_t); 221e192ef80SYaacov Hazan vlan = htonl(0x81000000 | buf->vlan_tci); 222e192ef80SYaacov Hazan memmove((void *)(addr - 4), (void *)addr, 12); 223e192ef80SYaacov Hazan memcpy((void *)(addr + 8), &vlan, sizeof(vlan)); 224e192ef80SYaacov Hazan 225e192ef80SYaacov Hazan SET_DATA_OFF(buf, head_room_len - 4); 226e192ef80SYaacov Hazan DATA_LEN(buf) += 4; 227e192ef80SYaacov Hazan 228e192ef80SYaacov Hazan return 0; 229e192ef80SYaacov Hazan } 230e192ef80SYaacov Hazan 2312e22920bSAdrien Mazarguil /** 2322e22920bSAdrien Mazarguil * DPDK callback for TX. 2332e22920bSAdrien Mazarguil * 2342e22920bSAdrien Mazarguil * @param dpdk_txq 2352e22920bSAdrien Mazarguil * Generic pointer to TX queue structure. 2362e22920bSAdrien Mazarguil * @param[in] pkts 2372e22920bSAdrien Mazarguil * Packets to transmit. 2382e22920bSAdrien Mazarguil * @param pkts_n 2392e22920bSAdrien Mazarguil * Number of packets in array. 2402e22920bSAdrien Mazarguil * 2412e22920bSAdrien Mazarguil * @return 2422e22920bSAdrien Mazarguil * Number of packets successfully transmitted (<= pkts_n). 2432e22920bSAdrien Mazarguil */ 2442e22920bSAdrien Mazarguil uint16_t 2452e22920bSAdrien Mazarguil mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) 2462e22920bSAdrien Mazarguil { 2472e22920bSAdrien Mazarguil struct txq *txq = (struct txq *)dpdk_txq; 2482e22920bSAdrien Mazarguil unsigned int elts_head = txq->elts_head; 2492e22920bSAdrien Mazarguil const unsigned int elts_n = txq->elts_n; 2502e22920bSAdrien Mazarguil unsigned int elts_comp_cd = txq->elts_comp_cd; 2512e22920bSAdrien Mazarguil unsigned int elts_comp = 0; 2522e22920bSAdrien Mazarguil unsigned int i; 2532e22920bSAdrien Mazarguil unsigned int max; 2542e22920bSAdrien Mazarguil int err; 2555e1d11ecSNelio Laranjeiro struct rte_mbuf *buf = pkts[0]; 2562e22920bSAdrien Mazarguil 2572e22920bSAdrien Mazarguil assert(elts_comp_cd != 0); 2585e1d11ecSNelio Laranjeiro /* Prefetch first packet cacheline. */ 2595e1d11ecSNelio Laranjeiro rte_prefetch0(buf); 2602e22920bSAdrien Mazarguil txq_complete(txq); 2614f52bbfbSNelio Laranjeiro max = (elts_n - (elts_head - txq->elts_tail)); 2622e22920bSAdrien Mazarguil if (max > elts_n) 2632e22920bSAdrien Mazarguil max -= elts_n; 2642e22920bSAdrien Mazarguil assert(max >= 1); 2652e22920bSAdrien Mazarguil assert(max <= elts_n); 2662e22920bSAdrien Mazarguil /* Always leave one free entry in the ring. */ 2672e22920bSAdrien Mazarguil --max; 2682e22920bSAdrien Mazarguil if (max == 0) 2692e22920bSAdrien Mazarguil return 0; 2702e22920bSAdrien Mazarguil if (max > pkts_n) 2712e22920bSAdrien Mazarguil max = pkts_n; 2722e22920bSAdrien Mazarguil for (i = 0; (i != max); ++i) { 2735e1d11ecSNelio Laranjeiro struct rte_mbuf *buf_next = pkts[i + 1]; 2742e22920bSAdrien Mazarguil unsigned int elts_head_next = 2752e22920bSAdrien Mazarguil (((elts_head + 1) == elts_n) ? 0 : elts_head + 1); 2762e22920bSAdrien Mazarguil struct txq_elt *elt = &(*txq->elts)[elts_head]; 2772e22920bSAdrien Mazarguil uint32_t send_flags = 0; 278e192ef80SYaacov Hazan #ifdef HAVE_VERBS_VLAN_INSERTION 279e192ef80SYaacov Hazan int insert_vlan = 0; 280e192ef80SYaacov Hazan #endif /* HAVE_VERBS_VLAN_INSERTION */ 281573f54afSNélio Laranjeiro uintptr_t addr; 282573f54afSNélio Laranjeiro uint32_t length; 283573f54afSNélio Laranjeiro uint32_t lkey; 284573f54afSNélio Laranjeiro uintptr_t buf_next_addr; 2852e22920bSAdrien Mazarguil 2865e1d11ecSNelio Laranjeiro if (i + 1 < max) 2875e1d11ecSNelio Laranjeiro rte_prefetch0(buf_next); 2882e22920bSAdrien Mazarguil /* Request TX completion. */ 2892e22920bSAdrien Mazarguil if (unlikely(--elts_comp_cd == 0)) { 2902e22920bSAdrien Mazarguil elts_comp_cd = txq->elts_comp_cd_init; 2912e22920bSAdrien Mazarguil ++elts_comp; 2922e22920bSAdrien Mazarguil send_flags |= IBV_EXP_QP_BURST_SIGNALED; 2932e22920bSAdrien Mazarguil } 29467fa62bcSAdrien Mazarguil /* Should we enable HW CKSUM offload */ 29567fa62bcSAdrien Mazarguil if (buf->ol_flags & 29667fa62bcSAdrien Mazarguil (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) { 29767fa62bcSAdrien Mazarguil send_flags |= IBV_EXP_QP_BURST_IP_CSUM; 29867fa62bcSAdrien Mazarguil /* HW does not support checksum offloads at arbitrary 29967fa62bcSAdrien Mazarguil * offsets but automatically recognizes the packet 30067fa62bcSAdrien Mazarguil * type. For inner L3/L4 checksums, only VXLAN (UDP) 30167fa62bcSAdrien Mazarguil * tunnels are currently supported. */ 30267fa62bcSAdrien Mazarguil if (RTE_ETH_IS_TUNNEL_PKT(buf->packet_type)) 30367fa62bcSAdrien Mazarguil send_flags |= IBV_EXP_QP_BURST_TUNNEL; 30467fa62bcSAdrien Mazarguil } 305e192ef80SYaacov Hazan if (buf->ol_flags & PKT_TX_VLAN_PKT) { 306e192ef80SYaacov Hazan #ifdef HAVE_VERBS_VLAN_INSERTION 307e192ef80SYaacov Hazan if (!txq->priv->mps) 308e192ef80SYaacov Hazan insert_vlan = 1; 309e192ef80SYaacov Hazan else 310e192ef80SYaacov Hazan #endif /* HAVE_VERBS_VLAN_INSERTION */ 311e192ef80SYaacov Hazan { 312e192ef80SYaacov Hazan err = insert_vlan_sw(buf); 313e192ef80SYaacov Hazan if (unlikely(err)) 314e192ef80SYaacov Hazan goto stop; 315e192ef80SYaacov Hazan } 316e192ef80SYaacov Hazan } 3172e22920bSAdrien Mazarguil /* Retrieve buffer information. */ 3182e22920bSAdrien Mazarguil addr = rte_pktmbuf_mtod(buf, uintptr_t); 3192e22920bSAdrien Mazarguil length = DATA_LEN(buf); 3202e22920bSAdrien Mazarguil /* Update element. */ 3212e22920bSAdrien Mazarguil elt->buf = buf; 32285e347dbSNélio Laranjeiro if (txq->priv->sriov) 3232e22920bSAdrien Mazarguil rte_prefetch0((volatile void *) 3242e22920bSAdrien Mazarguil (uintptr_t)addr); 3255e1d11ecSNelio Laranjeiro /* Prefetch next buffer data. */ 3265e1d11ecSNelio Laranjeiro if (i + 1 < max) { 3275e1d11ecSNelio Laranjeiro buf_next_addr = 3285e1d11ecSNelio Laranjeiro rte_pktmbuf_mtod(buf_next, uintptr_t); 3295e1d11ecSNelio Laranjeiro rte_prefetch0((volatile void *) 3305e1d11ecSNelio Laranjeiro (uintptr_t)buf_next_addr); 3315e1d11ecSNelio Laranjeiro } 332*0431c40fSNélio Laranjeiro /* Retrieve Memory Region key for this memory pool. */ 333d970e992SNelio Laranjeiro lkey = txq_mp2mr(txq, txq_mb2mp(buf)); 334d970e992SNelio Laranjeiro if (unlikely(lkey == (uint32_t)-1)) { 335d970e992SNelio Laranjeiro /* MR does not exist. */ 336d970e992SNelio Laranjeiro DEBUG("%p: unable to get MP <-> MR" 337d970e992SNelio Laranjeiro " association", (void *)txq); 338d970e992SNelio Laranjeiro /* Clean up TX element. */ 339d970e992SNelio Laranjeiro elt->buf = NULL; 340d970e992SNelio Laranjeiro goto stop; 341d970e992SNelio Laranjeiro } 342e192ef80SYaacov Hazan #ifdef HAVE_VERBS_VLAN_INSERTION 343e192ef80SYaacov Hazan if (insert_vlan) 344e192ef80SYaacov Hazan err = txq->send_pending_vlan 345e192ef80SYaacov Hazan (txq->qp, 346e192ef80SYaacov Hazan addr, 347e192ef80SYaacov Hazan length, 348e192ef80SYaacov Hazan lkey, 349e192ef80SYaacov Hazan send_flags, 350e192ef80SYaacov Hazan &buf->vlan_tci); 351e192ef80SYaacov Hazan else 352e192ef80SYaacov Hazan #endif /* HAVE_VERBS_VLAN_INSERTION */ 353e1682023SNelio Laranjeiro err = txq->send_pending 3542e22920bSAdrien Mazarguil (txq->qp, 3552e22920bSAdrien Mazarguil addr, 3562e22920bSAdrien Mazarguil length, 3572e22920bSAdrien Mazarguil lkey, 3582e22920bSAdrien Mazarguil send_flags); 3592e22920bSAdrien Mazarguil if (unlikely(err)) 3602e22920bSAdrien Mazarguil goto stop; 36187011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 362573f54afSNélio Laranjeiro /* Increment sent bytes counter. */ 363573f54afSNélio Laranjeiro txq->stats.obytes += length; 36487011737SAdrien Mazarguil #endif 365573f54afSNélio Laranjeiro stop: 3662e22920bSAdrien Mazarguil elts_head = elts_head_next; 3675e1d11ecSNelio Laranjeiro buf = buf_next; 3682e22920bSAdrien Mazarguil } 3692e22920bSAdrien Mazarguil /* Take a shortcut if nothing must be sent. */ 3702e22920bSAdrien Mazarguil if (unlikely(i == 0)) 3712e22920bSAdrien Mazarguil return 0; 37287011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 37387011737SAdrien Mazarguil /* Increment sent packets counter. */ 37487011737SAdrien Mazarguil txq->stats.opackets += i; 37587011737SAdrien Mazarguil #endif 3762e22920bSAdrien Mazarguil /* Ring QP doorbell. */ 377e1682023SNelio Laranjeiro err = txq->send_flush(txq->qp); 3782e22920bSAdrien Mazarguil if (unlikely(err)) { 3792e22920bSAdrien Mazarguil /* A nonzero value is not supposed to be returned. 3802e22920bSAdrien Mazarguil * Nothing can be done about it. */ 3812e22920bSAdrien Mazarguil DEBUG("%p: send_flush() failed with error %d", 3822e22920bSAdrien Mazarguil (void *)txq, err); 3832e22920bSAdrien Mazarguil } 3842e22920bSAdrien Mazarguil txq->elts_head = elts_head; 3852e22920bSAdrien Mazarguil txq->elts_comp += elts_comp; 3862e22920bSAdrien Mazarguil txq->elts_comp_cd = elts_comp_cd; 3872e22920bSAdrien Mazarguil return i; 3882e22920bSAdrien Mazarguil } 3892e22920bSAdrien Mazarguil 3902e22920bSAdrien Mazarguil /** 39167fa62bcSAdrien Mazarguil * Translate RX completion flags to packet type. 39267fa62bcSAdrien Mazarguil * 39367fa62bcSAdrien Mazarguil * @param flags 39467fa62bcSAdrien Mazarguil * RX completion flags returned by poll_length_flags(). 39567fa62bcSAdrien Mazarguil * 39678a38edfSJianfeng Tan * @note: fix mlx5_dev_supported_ptypes_get() if any change here. 39778a38edfSJianfeng Tan * 39867fa62bcSAdrien Mazarguil * @return 39967fa62bcSAdrien Mazarguil * Packet type for struct rte_mbuf. 40067fa62bcSAdrien Mazarguil */ 40167fa62bcSAdrien Mazarguil static inline uint32_t 40267fa62bcSAdrien Mazarguil rxq_cq_to_pkt_type(uint32_t flags) 40367fa62bcSAdrien Mazarguil { 40467fa62bcSAdrien Mazarguil uint32_t pkt_type; 40567fa62bcSAdrien Mazarguil 40667fa62bcSAdrien Mazarguil if (flags & IBV_EXP_CQ_RX_TUNNEL_PACKET) 40767fa62bcSAdrien Mazarguil pkt_type = 40867fa62bcSAdrien Mazarguil TRANSPOSE(flags, 40967fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_OUTER_IPV4_PACKET, 41067fa62bcSAdrien Mazarguil RTE_PTYPE_L3_IPV4) | 41167fa62bcSAdrien Mazarguil TRANSPOSE(flags, 41267fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_OUTER_IPV6_PACKET, 41367fa62bcSAdrien Mazarguil RTE_PTYPE_L3_IPV6) | 41467fa62bcSAdrien Mazarguil TRANSPOSE(flags, 41567fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IPV4_PACKET, 41667fa62bcSAdrien Mazarguil RTE_PTYPE_INNER_L3_IPV4) | 41767fa62bcSAdrien Mazarguil TRANSPOSE(flags, 41867fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IPV6_PACKET, 41967fa62bcSAdrien Mazarguil RTE_PTYPE_INNER_L3_IPV6); 42067fa62bcSAdrien Mazarguil else 42167fa62bcSAdrien Mazarguil pkt_type = 42267fa62bcSAdrien Mazarguil TRANSPOSE(flags, 42367fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IPV4_PACKET, 42467fa62bcSAdrien Mazarguil RTE_PTYPE_L3_IPV4) | 42567fa62bcSAdrien Mazarguil TRANSPOSE(flags, 42667fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IPV6_PACKET, 42767fa62bcSAdrien Mazarguil RTE_PTYPE_L3_IPV6); 42867fa62bcSAdrien Mazarguil return pkt_type; 42967fa62bcSAdrien Mazarguil } 43067fa62bcSAdrien Mazarguil 43167fa62bcSAdrien Mazarguil /** 43267fa62bcSAdrien Mazarguil * Translate RX completion flags to offload flags. 43367fa62bcSAdrien Mazarguil * 43467fa62bcSAdrien Mazarguil * @param[in] rxq 43567fa62bcSAdrien Mazarguil * Pointer to RX queue structure. 43667fa62bcSAdrien Mazarguil * @param flags 43767fa62bcSAdrien Mazarguil * RX completion flags returned by poll_length_flags(). 43867fa62bcSAdrien Mazarguil * 43967fa62bcSAdrien Mazarguil * @return 44067fa62bcSAdrien Mazarguil * Offload flags (ol_flags) for struct rte_mbuf. 44167fa62bcSAdrien Mazarguil */ 44267fa62bcSAdrien Mazarguil static inline uint32_t 44367fa62bcSAdrien Mazarguil rxq_cq_to_ol_flags(const struct rxq *rxq, uint32_t flags) 44467fa62bcSAdrien Mazarguil { 44567fa62bcSAdrien Mazarguil uint32_t ol_flags = 0; 44667fa62bcSAdrien Mazarguil 447d0087d76SYaacov Hazan if (rxq->csum) { 448d0087d76SYaacov Hazan /* Set IP checksum flag only for IPv4/IPv6 packets. */ 449d0087d76SYaacov Hazan if (flags & 450d0087d76SYaacov Hazan (IBV_EXP_CQ_RX_IPV4_PACKET | IBV_EXP_CQ_RX_IPV6_PACKET)) 45167fa62bcSAdrien Mazarguil ol_flags |= 45267fa62bcSAdrien Mazarguil TRANSPOSE(~flags, 45367fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_IP_CSUM_OK, 454d0087d76SYaacov Hazan PKT_RX_IP_CKSUM_BAD); 455d0087d76SYaacov Hazan #ifdef HAVE_EXP_CQ_RX_TCP_PACKET 456d0087d76SYaacov Hazan /* Set L4 checksum flag only for TCP/UDP packets. */ 457d0087d76SYaacov Hazan if (flags & 458d0087d76SYaacov Hazan (IBV_EXP_CQ_RX_TCP_PACKET | IBV_EXP_CQ_RX_UDP_PACKET)) 459d0087d76SYaacov Hazan #endif /* HAVE_EXP_CQ_RX_TCP_PACKET */ 460d0087d76SYaacov Hazan ol_flags |= 46167fa62bcSAdrien Mazarguil TRANSPOSE(~flags, 46267fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_TCP_UDP_CSUM_OK, 46367fa62bcSAdrien Mazarguil PKT_RX_L4_CKSUM_BAD); 464d0087d76SYaacov Hazan } 46567fa62bcSAdrien Mazarguil /* 46667fa62bcSAdrien Mazarguil * PKT_RX_IP_CKSUM_BAD and PKT_RX_L4_CKSUM_BAD are used in place 46767fa62bcSAdrien Mazarguil * of PKT_RX_EIP_CKSUM_BAD because the latter is not functional 46867fa62bcSAdrien Mazarguil * (its value is 0). 46967fa62bcSAdrien Mazarguil */ 47067fa62bcSAdrien Mazarguil if ((flags & IBV_EXP_CQ_RX_TUNNEL_PACKET) && (rxq->csum_l2tun)) 47167fa62bcSAdrien Mazarguil ol_flags |= 47267fa62bcSAdrien Mazarguil TRANSPOSE(~flags, 47367fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_OUTER_IP_CSUM_OK, 47467fa62bcSAdrien Mazarguil PKT_RX_IP_CKSUM_BAD) | 47567fa62bcSAdrien Mazarguil TRANSPOSE(~flags, 47667fa62bcSAdrien Mazarguil IBV_EXP_CQ_RX_OUTER_TCP_UDP_CSUM_OK, 47767fa62bcSAdrien Mazarguil PKT_RX_L4_CKSUM_BAD); 47867fa62bcSAdrien Mazarguil return ol_flags; 47967fa62bcSAdrien Mazarguil } 48067fa62bcSAdrien Mazarguil 48167fa62bcSAdrien Mazarguil /** 4822e22920bSAdrien Mazarguil * DPDK callback for RX. 4832e22920bSAdrien Mazarguil * 4842e22920bSAdrien Mazarguil * @param dpdk_rxq 4852e22920bSAdrien Mazarguil * Generic pointer to RX queue structure. 4862e22920bSAdrien Mazarguil * @param[out] pkts 4872e22920bSAdrien Mazarguil * Array to store received packets. 4882e22920bSAdrien Mazarguil * @param pkts_n 4892e22920bSAdrien Mazarguil * Maximum number of packets in array. 4902e22920bSAdrien Mazarguil * 4912e22920bSAdrien Mazarguil * @return 4922e22920bSAdrien Mazarguil * Number of packets successfully received (<= pkts_n). 4932e22920bSAdrien Mazarguil */ 4942e22920bSAdrien Mazarguil uint16_t 4952e22920bSAdrien Mazarguil mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 4962e22920bSAdrien Mazarguil { 4972e22920bSAdrien Mazarguil struct rxq *rxq = (struct rxq *)dpdk_rxq; 4983f5ac8f2SNélio Laranjeiro struct rxq_elt (*elts)[rxq->elts_n] = rxq->elts; 4992e22920bSAdrien Mazarguil const unsigned int elts_n = rxq->elts_n; 5002e22920bSAdrien Mazarguil unsigned int elts_head = rxq->elts_head; 5012e22920bSAdrien Mazarguil struct ibv_sge sges[pkts_n]; 5022e22920bSAdrien Mazarguil unsigned int i; 5032e22920bSAdrien Mazarguil unsigned int pkts_ret = 0; 5042e22920bSAdrien Mazarguil int ret; 5052e22920bSAdrien Mazarguil 5062e22920bSAdrien Mazarguil for (i = 0; (i != pkts_n); ++i) { 5072e22920bSAdrien Mazarguil struct rxq_elt *elt = &(*elts)[elts_head]; 5082e22920bSAdrien Mazarguil unsigned int len; 509aa7f63abSAdrien Mazarguil struct rte_mbuf *seg = elt->buf; 5102e22920bSAdrien Mazarguil struct rte_mbuf *rep; 5112e22920bSAdrien Mazarguil uint32_t flags; 512f3db9489SYaacov Hazan uint16_t vlan_tci; 5132e22920bSAdrien Mazarguil 5142e22920bSAdrien Mazarguil /* Sanity checks. */ 515aa7f63abSAdrien Mazarguil assert(seg != NULL); 5162e22920bSAdrien Mazarguil assert(elts_head < rxq->elts_n); 5172e22920bSAdrien Mazarguil assert(rxq->elts_head < rxq->elts_n); 5182e22920bSAdrien Mazarguil /* 5192e22920bSAdrien Mazarguil * Fetch initial bytes of packet descriptor into a 5202e22920bSAdrien Mazarguil * cacheline while allocating rep. 5212e22920bSAdrien Mazarguil */ 522e8988095SOlivier Matz rte_mbuf_prefetch_part1(seg); 523e8988095SOlivier Matz rte_mbuf_prefetch_part2(seg); 524e1682023SNelio Laranjeiro ret = rxq->poll(rxq->cq, NULL, NULL, &flags, &vlan_tci); 5252e22920bSAdrien Mazarguil if (unlikely(ret < 0)) { 5262e22920bSAdrien Mazarguil struct ibv_wc wc; 5272e22920bSAdrien Mazarguil int wcs_n; 5282e22920bSAdrien Mazarguil 5292e22920bSAdrien Mazarguil DEBUG("rxq=%p, poll_length() failed (ret=%d)", 5302e22920bSAdrien Mazarguil (void *)rxq, ret); 5312e22920bSAdrien Mazarguil /* ibv_poll_cq() must be used in case of failure. */ 5322e22920bSAdrien Mazarguil wcs_n = ibv_poll_cq(rxq->cq, 1, &wc); 5332e22920bSAdrien Mazarguil if (unlikely(wcs_n == 0)) 5342e22920bSAdrien Mazarguil break; 5352e22920bSAdrien Mazarguil if (unlikely(wcs_n < 0)) { 5362e22920bSAdrien Mazarguil DEBUG("rxq=%p, ibv_poll_cq() failed (wcs_n=%d)", 5372e22920bSAdrien Mazarguil (void *)rxq, wcs_n); 5382e22920bSAdrien Mazarguil break; 5392e22920bSAdrien Mazarguil } 5402e22920bSAdrien Mazarguil assert(wcs_n == 1); 5412e22920bSAdrien Mazarguil if (unlikely(wc.status != IBV_WC_SUCCESS)) { 5422e22920bSAdrien Mazarguil /* Whatever, just repost the offending WR. */ 5432e22920bSAdrien Mazarguil DEBUG("rxq=%p, wr_id=%" PRIu64 ": bad work" 5442e22920bSAdrien Mazarguil " completion status (%d): %s", 5452e22920bSAdrien Mazarguil (void *)rxq, wc.wr_id, wc.status, 5462e22920bSAdrien Mazarguil ibv_wc_status_str(wc.status)); 54787011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 54887011737SAdrien Mazarguil /* Increment dropped packets counter. */ 54987011737SAdrien Mazarguil ++rxq->stats.idropped; 55087011737SAdrien Mazarguil #endif 5512e22920bSAdrien Mazarguil /* Add SGE to array for repost. */ 5522e22920bSAdrien Mazarguil sges[i] = elt->sge; 5532e22920bSAdrien Mazarguil goto repost; 5542e22920bSAdrien Mazarguil } 5552e22920bSAdrien Mazarguil ret = wc.byte_len; 5562e22920bSAdrien Mazarguil } 5572e22920bSAdrien Mazarguil if (ret == 0) 5582e22920bSAdrien Mazarguil break; 5594d326709SOlga Shern assert(ret >= (rxq->crc_present << 2)); 5604d326709SOlga Shern len = ret - (rxq->crc_present << 2); 561fbfd9955SOlivier Matz rep = rte_mbuf_raw_alloc(rxq->mp); 5622e22920bSAdrien Mazarguil if (unlikely(rep == NULL)) { 5632e22920bSAdrien Mazarguil /* 5642e22920bSAdrien Mazarguil * Unable to allocate a replacement mbuf, 5652e22920bSAdrien Mazarguil * repost WR. 5662e22920bSAdrien Mazarguil */ 567aa7f63abSAdrien Mazarguil DEBUG("rxq=%p: can't allocate a new mbuf", 568aa7f63abSAdrien Mazarguil (void *)rxq); 5692e22920bSAdrien Mazarguil /* Increment out of memory counters. */ 57087011737SAdrien Mazarguil ++rxq->stats.rx_nombuf; 5712e22920bSAdrien Mazarguil ++rxq->priv->dev->data->rx_mbuf_alloc_failed; 5722e22920bSAdrien Mazarguil goto repost; 5732e22920bSAdrien Mazarguil } 5742e22920bSAdrien Mazarguil 5752e22920bSAdrien Mazarguil /* Reconfigure sge to use rep instead of seg. */ 5762e22920bSAdrien Mazarguil elt->sge.addr = (uintptr_t)rep->buf_addr + RTE_PKTMBUF_HEADROOM; 5772e22920bSAdrien Mazarguil assert(elt->sge.lkey == rxq->mr->lkey); 578aa7f63abSAdrien Mazarguil elt->buf = rep; 5792e22920bSAdrien Mazarguil 5802e22920bSAdrien Mazarguil /* Add SGE to array for repost. */ 5812e22920bSAdrien Mazarguil sges[i] = elt->sge; 5822e22920bSAdrien Mazarguil 5832e22920bSAdrien Mazarguil /* Update seg information. */ 5842e22920bSAdrien Mazarguil SET_DATA_OFF(seg, RTE_PKTMBUF_HEADROOM); 5852e22920bSAdrien Mazarguil NB_SEGS(seg) = 1; 5862e22920bSAdrien Mazarguil PORT(seg) = rxq->port_id; 5872e22920bSAdrien Mazarguil NEXT(seg) = NULL; 5882e22920bSAdrien Mazarguil PKT_LEN(seg) = len; 5892e22920bSAdrien Mazarguil DATA_LEN(seg) = len; 590081f7eaeSNelio Laranjeiro if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip) { 59167fa62bcSAdrien Mazarguil seg->packet_type = rxq_cq_to_pkt_type(flags); 59267fa62bcSAdrien Mazarguil seg->ol_flags = rxq_cq_to_ol_flags(rxq, flags); 593f3db9489SYaacov Hazan #ifdef HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS 594f3db9489SYaacov Hazan if (flags & IBV_EXP_CQ_RX_CVLAN_STRIPPED_V1) { 595b37b528dSOlivier Matz seg->ol_flags |= PKT_RX_VLAN_PKT | 596b37b528dSOlivier Matz PKT_RX_VLAN_STRIPPED; 597f3db9489SYaacov Hazan seg->vlan_tci = vlan_tci; 598f3db9489SYaacov Hazan } 599f3db9489SYaacov Hazan #endif /* HAVE_EXP_DEVICE_ATTR_VLAN_OFFLOADS */ 600081f7eaeSNelio Laranjeiro } 6012e22920bSAdrien Mazarguil /* Return packet. */ 6022e22920bSAdrien Mazarguil *(pkts++) = seg; 6032e22920bSAdrien Mazarguil ++pkts_ret; 60487011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 60587011737SAdrien Mazarguil /* Increment bytes counter. */ 60687011737SAdrien Mazarguil rxq->stats.ibytes += len; 60787011737SAdrien Mazarguil #endif 6082e22920bSAdrien Mazarguil repost: 6092e22920bSAdrien Mazarguil if (++elts_head >= elts_n) 6102e22920bSAdrien Mazarguil elts_head = 0; 6112e22920bSAdrien Mazarguil continue; 6122e22920bSAdrien Mazarguil } 6132e22920bSAdrien Mazarguil if (unlikely(i == 0)) 6142e22920bSAdrien Mazarguil return 0; 6152e22920bSAdrien Mazarguil /* Repost WRs. */ 6162e22920bSAdrien Mazarguil #ifdef DEBUG_RECV 6172e22920bSAdrien Mazarguil DEBUG("%p: reposting %u WRs", (void *)rxq, i); 6182e22920bSAdrien Mazarguil #endif 619e1682023SNelio Laranjeiro ret = rxq->recv(rxq->wq, sges, i); 6202e22920bSAdrien Mazarguil if (unlikely(ret)) { 6212e22920bSAdrien Mazarguil /* Inability to repost WRs is fatal. */ 6222e22920bSAdrien Mazarguil DEBUG("%p: recv_burst(): failed (ret=%d)", 6232e22920bSAdrien Mazarguil (void *)rxq->priv, 6242e22920bSAdrien Mazarguil ret); 6252e22920bSAdrien Mazarguil abort(); 6262e22920bSAdrien Mazarguil } 6272e22920bSAdrien Mazarguil rxq->elts_head = elts_head; 62887011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS 62987011737SAdrien Mazarguil /* Increment packets counter. */ 63087011737SAdrien Mazarguil rxq->stats.ipackets += pkts_ret; 63187011737SAdrien Mazarguil #endif 6322e22920bSAdrien Mazarguil return pkts_ret; 6332e22920bSAdrien Mazarguil } 6342e22920bSAdrien Mazarguil 6352e22920bSAdrien Mazarguil /** 6362e22920bSAdrien Mazarguil * Dummy DPDK callback for TX. 6372e22920bSAdrien Mazarguil * 6382e22920bSAdrien Mazarguil * This function is used to temporarily replace the real callback during 6392e22920bSAdrien Mazarguil * unsafe control operations on the queue, or in case of error. 6402e22920bSAdrien Mazarguil * 6412e22920bSAdrien Mazarguil * @param dpdk_txq 6422e22920bSAdrien Mazarguil * Generic pointer to TX queue structure. 6432e22920bSAdrien Mazarguil * @param[in] pkts 6442e22920bSAdrien Mazarguil * Packets to transmit. 6452e22920bSAdrien Mazarguil * @param pkts_n 6462e22920bSAdrien Mazarguil * Number of packets in array. 6472e22920bSAdrien Mazarguil * 6482e22920bSAdrien Mazarguil * @return 6492e22920bSAdrien Mazarguil * Number of packets successfully transmitted (<= pkts_n). 6502e22920bSAdrien Mazarguil */ 6512e22920bSAdrien Mazarguil uint16_t 6522e22920bSAdrien Mazarguil removed_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) 6532e22920bSAdrien Mazarguil { 6542e22920bSAdrien Mazarguil (void)dpdk_txq; 6552e22920bSAdrien Mazarguil (void)pkts; 6562e22920bSAdrien Mazarguil (void)pkts_n; 6572e22920bSAdrien Mazarguil return 0; 6582e22920bSAdrien Mazarguil } 6592e22920bSAdrien Mazarguil 6602e22920bSAdrien Mazarguil /** 6612e22920bSAdrien Mazarguil * Dummy DPDK callback for RX. 6622e22920bSAdrien Mazarguil * 6632e22920bSAdrien Mazarguil * This function is used to temporarily replace the real callback during 6642e22920bSAdrien Mazarguil * unsafe control operations on the queue, or in case of error. 6652e22920bSAdrien Mazarguil * 6662e22920bSAdrien Mazarguil * @param dpdk_rxq 6672e22920bSAdrien Mazarguil * Generic pointer to RX queue structure. 6682e22920bSAdrien Mazarguil * @param[out] pkts 6692e22920bSAdrien Mazarguil * Array to store received packets. 6702e22920bSAdrien Mazarguil * @param pkts_n 6712e22920bSAdrien Mazarguil * Maximum number of packets in array. 6722e22920bSAdrien Mazarguil * 6732e22920bSAdrien Mazarguil * @return 6742e22920bSAdrien Mazarguil * Number of packets successfully received (<= pkts_n). 6752e22920bSAdrien Mazarguil */ 6762e22920bSAdrien Mazarguil uint16_t 6772e22920bSAdrien Mazarguil removed_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n) 6782e22920bSAdrien Mazarguil { 6792e22920bSAdrien Mazarguil (void)dpdk_rxq; 6802e22920bSAdrien Mazarguil (void)pkts; 6812e22920bSAdrien Mazarguil (void)pkts_n; 6822e22920bSAdrien Mazarguil return 0; 6832e22920bSAdrien Mazarguil } 684