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