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_RX_H_
8 #define _NFB_RX_H_
9
10 #include <nfb/nfb.h>
11 #include <nfb/ndp.h>
12
13 #include <rte_mbuf.h>
14 #include <rte_ethdev.h>
15
16 #define NFB_TIMESTAMP_FLAG (1 << 0)
17
18 extern uint64_t nfb_timestamp_rx_dynflag;
19 extern int nfb_timestamp_dynfield_offset;
20
21 static inline rte_mbuf_timestamp_t *
nfb_timestamp_dynfield(struct rte_mbuf * mbuf)22 nfb_timestamp_dynfield(struct rte_mbuf *mbuf)
23 {
24 return RTE_MBUF_DYNFIELD(mbuf,
25 nfb_timestamp_dynfield_offset, rte_mbuf_timestamp_t *);
26 }
27
28 struct ndp_rx_queue {
29 struct nfb_device *nfb; /* nfb dev structure */
30 struct ndp_queue *queue; /* rx queue */
31 uint16_t rx_queue_id; /* index */
32 uint8_t in_port; /* port */
33 uint8_t flags; /* setup flags */
34
35 struct rte_mempool *mb_pool; /* memory pool to allocate packets */
36 uint16_t buf_size; /* mbuf size */
37
38 volatile uint64_t rx_pkts; /* packets read */
39 volatile uint64_t rx_bytes; /* bytes read */
40 volatile uint64_t err_pkts; /* erroneous packets */
41 };
42
43 /**
44 * Initialize ndp_rx_queue structure
45 *
46 * @param nfb
47 * Pointer to nfb device structure.
48 * @param rx_queue_id
49 * RX queue index.
50 * @param port_id
51 * Device [external] port identifier.
52 * @param mb_pool
53 * Memory pool for buffer allocations.
54 * @param[out] rxq
55 * Pointer to ndp_rx_queue output structure
56 * @return
57 * 0 on success, a negative errno value otherwise.
58 */
59 int
60 nfb_eth_rx_queue_init(struct nfb_device *nfb,
61 uint16_t rx_queue_id,
62 uint16_t port_id,
63 struct rte_mempool *mb_pool,
64 struct ndp_rx_queue *rxq);
65
66 /**
67 * DPDK callback to setup a RX queue for use.
68 *
69 * @param dev
70 * Pointer to Ethernet device structure.
71 * @param idx
72 * RX queue index.
73 * @param desc
74 * Number of descriptors to configure in queue.
75 * @param socket
76 * NUMA socket on which memory must be allocated.
77 * @param[in] conf
78 * Thresholds parameters.
79 * @param mb_pool
80 * Memory pool for buffer allocations.
81 *
82 * @return
83 * 0 on success, a negative errno value otherwise.
84 */
85 int
86 nfb_eth_rx_queue_setup(struct rte_eth_dev *dev,
87 uint16_t rx_queue_id,
88 uint16_t nb_rx_desc __rte_unused,
89 unsigned int socket_id,
90 const struct rte_eth_rxconf *rx_conf __rte_unused,
91 struct rte_mempool *mb_pool);
92
93 /**
94 * DPDK callback to release a RX queue.
95 *
96 * @param dpdk_rxq
97 * Generic RX queue pointer.
98 */
99 void
100 nfb_eth_rx_queue_release(void *q);
101
102 /**
103 * Start traffic on Rx queue.
104 *
105 * @param dev
106 * Pointer to Ethernet device structure.
107 * @param txq_id
108 * RX queue index.
109 * @return
110 * 0 on success, a negative errno value otherwise.
111 */
112 int
113 nfb_eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rxq_id);
114
115 /**
116 * Stop traffic on Rx queue.
117 *
118 * @param dev
119 * Pointer to Ethernet device structure.
120 * @param txq_id
121 * RX queue index.
122 */
123 int
124 nfb_eth_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rxq_id);
125
126 /**
127 * DPDK callback for RX.
128 *
129 * @param dpdk_rxq
130 * Generic pointer to RX queue structure.
131 * @param[out] bufs
132 * Array to store received packets.
133 * @param nb_pkts
134 * Maximum number of packets in array.
135 *
136 * @return
137 * Number of packets successfully received (<= nb_pkts).
138 */
139 static __rte_always_inline uint16_t
nfb_eth_ndp_rx(void * queue,struct rte_mbuf ** bufs,uint16_t nb_pkts)140 nfb_eth_ndp_rx(void *queue,
141 struct rte_mbuf **bufs,
142 uint16_t nb_pkts)
143 {
144 struct ndp_rx_queue *ndp = queue;
145 uint8_t timestamping_enabled;
146 uint16_t packet_size;
147 uint64_t num_bytes = 0;
148 uint16_t num_rx;
149 unsigned int i;
150
151 const uint16_t buf_size = ndp->buf_size;
152
153 struct rte_mbuf *mbuf;
154 struct ndp_packet packets[nb_pkts];
155
156 struct rte_mbuf *mbufs[nb_pkts];
157
158 if (unlikely(ndp->queue == NULL || nb_pkts == 0)) {
159 RTE_LOG(ERR, PMD, "RX invalid arguments!\n");
160 return 0;
161 }
162
163 timestamping_enabled = ndp->flags & NFB_TIMESTAMP_FLAG;
164
165 /* returns either all or nothing */
166 i = rte_pktmbuf_alloc_bulk(ndp->mb_pool, mbufs, nb_pkts);
167 if (unlikely(i != 0))
168 return 0;
169
170 num_rx = ndp_rx_burst_get(ndp->queue, packets, nb_pkts);
171
172 if (unlikely(num_rx != nb_pkts)) {
173 for (i = num_rx; i < nb_pkts; i++)
174 rte_pktmbuf_free(mbufs[i]);
175 }
176
177 nb_pkts = num_rx;
178
179 num_rx = 0;
180 /*
181 * Reads the given number of packets from NDP queue given
182 * by queue and copies the packet data into a newly allocated mbuf
183 * to return.
184 */
185 for (i = 0; i < nb_pkts; ++i) {
186 mbuf = mbufs[i];
187
188 /* get the space available for data in the mbuf */
189 packet_size = packets[i].data_length;
190
191 if (likely(packet_size <= buf_size)) {
192 /* NDP packet will fit in one mbuf, go ahead and copy */
193 rte_memcpy(rte_pktmbuf_mtod(mbuf, void *),
194 packets[i].data, packet_size);
195
196 mbuf->data_len = (uint16_t)packet_size;
197
198 mbuf->pkt_len = packet_size;
199 mbuf->port = ndp->in_port;
200 mbuf->ol_flags = 0;
201
202 if (timestamping_enabled) {
203 rte_mbuf_timestamp_t timestamp;
204
205 /* nanoseconds */
206 timestamp =
207 rte_le_to_cpu_32(*((uint32_t *)
208 (packets[i].header + 4)));
209 timestamp <<= 32;
210 /* seconds */
211 timestamp |=
212 rte_le_to_cpu_32(*((uint32_t *)
213 (packets[i].header + 8)));
214 *nfb_timestamp_dynfield(mbuf) = timestamp;
215 mbuf->ol_flags |= nfb_timestamp_rx_dynflag;
216 }
217
218 bufs[num_rx++] = mbuf;
219 num_bytes += packet_size;
220 } else {
221 /*
222 * NDP packet will not fit in one mbuf,
223 * scattered mode is not enabled, drop packet
224 */
225 rte_pktmbuf_free(mbuf);
226 }
227 }
228
229 ndp_rx_burst_put(ndp->queue);
230
231 ndp->rx_pkts += num_rx;
232 ndp->rx_bytes += num_bytes;
233 return num_rx;
234 }
235
236 #endif /* _NFB_RX_H_ */
237