1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019 Cesnet 3 * Copyright(c) 2019 Netcope Technologies, a.s. <info@netcope.com> 4 * All rights reserved. 5 */ 6 7 #ifndef _NFB_TX_H_ 8 #define _NFB_TX_H_ 9 10 #include <nfb/nfb.h> 11 #include <nfb/ndp.h> 12 13 #include <ethdev_driver.h> 14 #include <rte_ethdev.h> 15 #include <rte_malloc.h> 16 17 struct ndp_tx_queue { 18 struct nfb_device *nfb; /* nfb dev structure */ 19 struct ndp_queue *queue; /* tx queue */ 20 uint16_t tx_queue_id; /* index */ 21 volatile uint64_t tx_pkts; /* packets transmitted */ 22 volatile uint64_t tx_bytes; /* bytes transmitted */ 23 volatile uint64_t err_pkts; /* erroneous packets */ 24 }; 25 26 /** 27 * DPDK callback to setup a TX queue for use. 28 * 29 * @param dev 30 * Pointer to Ethernet device structure. 31 * @param idx 32 * RX queue index. 33 * @param desc 34 * Number of descriptors to configure in queue. 35 * @param socket 36 * NUMA socket on which memory must be allocated. 37 * @param[in] conf 38 * Thresholds parameters. 39 * @param mp 40 * Memory pool for buffer allocations. 41 * 42 * @return 43 * 0 on success, a negative errno value otherwise. 44 */ 45 int 46 nfb_eth_tx_queue_setup(struct rte_eth_dev *dev, 47 uint16_t tx_queue_id, 48 uint16_t nb_tx_desc __rte_unused, 49 unsigned int socket_id, 50 const struct rte_eth_txconf *tx_conf __rte_unused); 51 52 /** 53 * Initialize ndp_tx_queue structure 54 * 55 * @param nfb 56 * Pointer to nfb device structure. 57 * @param tx_queue_id 58 * TX queue index. 59 * @param[out] txq 60 * Pointer to ndp_tx_queue output structure 61 * 62 * @return 63 * 0 on success, a negative errno value otherwise. 64 */ 65 int 66 nfb_eth_tx_queue_init(struct nfb_device *nfb, 67 uint16_t tx_queue_id, 68 struct ndp_tx_queue *txq); 69 70 /** 71 * DPDK callback to release a RX queue. 72 * 73 * @param dpdk_rxq 74 * Generic RX queue pointer. 75 */ 76 void 77 nfb_eth_tx_queue_release(void *q); 78 79 /** 80 * Start traffic on Tx queue. 81 * 82 * @param dev 83 * Pointer to Ethernet device structure. 84 * @param txq_id 85 * TX queue index. 86 * 87 * @return 88 * 0 on success, a negative errno value otherwise. 89 */ 90 int 91 nfb_eth_tx_queue_start(struct rte_eth_dev *dev, uint16_t txq_id); 92 93 /** 94 * Stop traffic on Tx queue. 95 * 96 * @param dev 97 * Pointer to Ethernet device structure. 98 * @param txq_id 99 * TX queue index. 100 * 101 * @return 102 * 0 on success, a negative errno value otherwise. 103 */ 104 int 105 nfb_eth_tx_queue_stop(struct rte_eth_dev *dev, uint16_t txq_id); 106 107 /** 108 * DPDK callback for TX. 109 * 110 * @param dpdk_txq 111 * Generic pointer to TX queue structure. 112 * @param bufs 113 * Packets to transmit. 114 * @param nb_pkts 115 * Number of packets in array. 116 * 117 * @return 118 * Number of packets successfully transmitted (<= nb_pkts). 119 */ 120 static __rte_always_inline uint16_t 121 nfb_eth_ndp_tx(void *queue, 122 struct rte_mbuf **bufs, 123 uint16_t nb_pkts) 124 { 125 int i; 126 struct rte_mbuf *mbuf; 127 struct ndp_tx_queue *ndp = queue; 128 uint16_t num_tx = 0; 129 uint64_t num_bytes = 0; 130 131 void *dst; 132 uint32_t pkt_len; 133 uint8_t mbuf_segs; 134 135 struct ndp_packet packets[nb_pkts]; 136 137 if (unlikely(ndp->queue == NULL || nb_pkts == 0)) { 138 RTE_LOG(ERR, PMD, "TX invalid arguments!\n"); 139 return 0; 140 } 141 142 for (i = 0; i < nb_pkts; i++) { 143 packets[i].data_length = bufs[i]->pkt_len; 144 packets[i].header_length = 0; 145 } 146 147 num_tx = ndp_tx_burst_get(ndp->queue, packets, nb_pkts); 148 149 if (unlikely(num_tx != nb_pkts)) 150 return 0; 151 152 for (i = 0; i < nb_pkts; ++i) { 153 mbuf = bufs[i]; 154 155 pkt_len = mbuf->pkt_len; 156 mbuf_segs = mbuf->nb_segs; 157 158 num_bytes += pkt_len; 159 if (mbuf_segs == 1) { 160 /* 161 * non-scattered packet, 162 * transmit from one mbuf 163 */ 164 rte_memcpy(packets[i].data, 165 rte_pktmbuf_mtod(mbuf, const void *), 166 pkt_len); 167 } else { 168 /* scattered packet, transmit from more mbufs */ 169 struct rte_mbuf *m = mbuf; 170 while (m) { 171 dst = packets[i].data; 172 173 rte_memcpy(dst, 174 rte_pktmbuf_mtod(m, 175 const void *), 176 m->data_len); 177 dst = ((uint8_t *)(dst)) + 178 m->data_len; 179 m = m->next; 180 } 181 } 182 183 rte_pktmbuf_free(mbuf); 184 } 185 186 ndp_tx_burst_flush(ndp->queue); 187 188 ndp->tx_pkts += num_tx; 189 ndp->err_pkts += nb_pkts - num_tx; 190 ndp->tx_bytes += num_bytes; 191 return num_tx; 192 } 193 194 #endif /* _NFB_TX_H_ */ 195