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 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
nfb_eth_ndp_tx(void * queue,struct rte_mbuf ** bufs,uint16_t nb_pkts)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 NFB_LOG(ERR, "TX invalid arguments");
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