1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019 Cesnet 3 * Copyright(c) 2019 Netcope Technologies, a.s. <[email protected]> 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 dev 74 * Pointer to Ethernet device structure. 75 * @param qid 76 * Receive queue index. 77 */ 78 void 79 nfb_eth_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid); 80 81 /** 82 * Start traffic on Tx queue. 83 * 84 * @param dev 85 * Pointer to Ethernet device structure. 86 * @param txq_id 87 * TX queue index. 88 * 89 * @return 90 * 0 on success, a negative errno value otherwise. 91 */ 92 int 93 nfb_eth_tx_queue_start(struct rte_eth_dev *dev, uint16_t txq_id); 94 95 /** 96 * Stop traffic on Tx queue. 97 * 98 * @param dev 99 * Pointer to Ethernet device structure. 100 * @param txq_id 101 * TX queue index. 102 * 103 * @return 104 * 0 on success, a negative errno value otherwise. 105 */ 106 int 107 nfb_eth_tx_queue_stop(struct rte_eth_dev *dev, uint16_t txq_id); 108 109 /** 110 * DPDK callback for TX. 111 * 112 * @param dpdk_txq 113 * Generic pointer to TX queue structure. 114 * @param bufs 115 * Packets to transmit. 116 * @param nb_pkts 117 * Number of packets in array. 118 * 119 * @return 120 * Number of packets successfully transmitted (<= nb_pkts). 121 */ 122 static __rte_always_inline uint16_t 123 nfb_eth_ndp_tx(void *queue, 124 struct rte_mbuf **bufs, 125 uint16_t nb_pkts) 126 { 127 int i; 128 struct rte_mbuf *mbuf; 129 struct ndp_tx_queue *ndp = queue; 130 uint16_t num_tx = 0; 131 uint64_t num_bytes = 0; 132 133 void *dst; 134 uint32_t pkt_len; 135 uint8_t mbuf_segs; 136 137 struct ndp_packet packets[nb_pkts]; 138 139 if (unlikely(nb_pkts == 0)) 140 return 0; 141 142 if (unlikely(ndp->queue == NULL)) { 143 RTE_LOG(ERR, PMD, "TX invalid arguments!\n"); 144 return 0; 145 } 146 147 for (i = 0; i < nb_pkts; i++) { 148 packets[i].data_length = bufs[i]->pkt_len; 149 packets[i].header_length = 0; 150 } 151 152 num_tx = ndp_tx_burst_get(ndp->queue, packets, nb_pkts); 153 154 if (unlikely(num_tx != nb_pkts)) 155 return 0; 156 157 for (i = 0; i < nb_pkts; ++i) { 158 mbuf = bufs[i]; 159 160 pkt_len = mbuf->pkt_len; 161 mbuf_segs = mbuf->nb_segs; 162 163 num_bytes += pkt_len; 164 if (mbuf_segs == 1) { 165 /* 166 * non-scattered packet, 167 * transmit from one mbuf 168 */ 169 rte_memcpy(packets[i].data, 170 rte_pktmbuf_mtod(mbuf, const void *), 171 pkt_len); 172 } else { 173 /* scattered packet, transmit from more mbufs */ 174 struct rte_mbuf *m = mbuf; 175 while (m) { 176 dst = packets[i].data; 177 178 rte_memcpy(dst, 179 rte_pktmbuf_mtod(m, 180 const void *), 181 m->data_len); 182 dst = ((uint8_t *)(dst)) + 183 m->data_len; 184 m = m->next; 185 } 186 } 187 188 rte_pktmbuf_free(mbuf); 189 } 190 191 ndp_tx_burst_flush(ndp->queue); 192 193 ndp->tx_pkts += num_tx; 194 ndp->err_pkts += nb_pkts - num_tx; 195 ndp->tx_bytes += num_bytes; 196 return num_tx; 197 } 198 199 #endif /* _NFB_TX_H_ */ 200