ethdev: promote sibling iterators to stable
[dpdk.git] / drivers / net / nfb / nfb_rx.h
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_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 dpdk_rxq
98  *   Generic RX queue pointer.
99  */
100 void
101 nfb_eth_rx_queue_release(void *q);
102
103 /**
104  * Start traffic on Rx queue.
105  *
106  * @param dev
107  *   Pointer to Ethernet device structure.
108  * @param txq_id
109  *   RX queue index.
110  * @return
111  *   0 on success, a negative errno value otherwise.
112  */
113 int
114 nfb_eth_rx_queue_start(struct rte_eth_dev *dev, uint16_t rxq_id);
115
116 /**
117  * Stop traffic on Rx queue.
118  *
119  * @param dev
120  *   Pointer to Ethernet device structure.
121  * @param txq_id
122  *   RX queue index.
123  */
124 int
125 nfb_eth_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rxq_id);
126
127 /**
128  * DPDK callback for RX.
129  *
130  * @param dpdk_rxq
131  *   Generic pointer to RX queue structure.
132  * @param[out] bufs
133  *   Array to store received packets.
134  * @param nb_pkts
135  *   Maximum number of packets in array.
136  *
137  * @return
138  *   Number of packets successfully received (<= nb_pkts).
139  */
140 static __rte_always_inline uint16_t
141 nfb_eth_ndp_rx(void *queue,
142         struct rte_mbuf **bufs,
143         uint16_t nb_pkts)
144 {
145         struct ndp_rx_queue *ndp = queue;
146         uint8_t timestamping_enabled;
147         uint16_t packet_size;
148         uint64_t num_bytes = 0;
149         uint16_t num_rx;
150         unsigned int i;
151
152         const uint16_t buf_size = ndp->buf_size;
153
154         struct rte_mbuf *mbuf;
155         struct ndp_packet packets[nb_pkts];
156
157         struct rte_mbuf *mbufs[nb_pkts];
158
159         if (unlikely(ndp->queue == NULL || nb_pkts == 0)) {
160                 RTE_LOG(ERR, PMD, "RX invalid arguments!\n");
161                 return 0;
162         }
163
164         timestamping_enabled = ndp->flags & NFB_TIMESTAMP_FLAG;
165
166         /* returns either all or nothing */
167         i = rte_pktmbuf_alloc_bulk(ndp->mb_pool, mbufs, nb_pkts);
168         if (unlikely(i != 0))
169                 return 0;
170
171         num_rx = ndp_rx_burst_get(ndp->queue, packets, nb_pkts);
172
173         if (unlikely(num_rx != nb_pkts)) {
174                 for (i = num_rx; i < nb_pkts; i++)
175                         rte_pktmbuf_free(mbufs[i]);
176         }
177
178         nb_pkts = num_rx;
179
180         num_rx = 0;
181         /*
182          * Reads the given number of packets from NDP queue given
183          * by queue and copies the packet data into a newly allocated mbuf
184          * to return.
185          */
186         for (i = 0; i < nb_pkts; ++i) {
187                 mbuf = mbufs[i];
188
189                 /* get the space available for data in the mbuf */
190                 packet_size = packets[i].data_length;
191
192                 if (likely(packet_size <= buf_size)) {
193                         /* NDP packet will fit in one mbuf, go ahead and copy */
194                         rte_memcpy(rte_pktmbuf_mtod(mbuf, void *),
195                                 packets[i].data, packet_size);
196
197                         mbuf->data_len = (uint16_t)packet_size;
198
199                         mbuf->pkt_len = packet_size;
200                         mbuf->port = ndp->in_port;
201                         mbuf->ol_flags = 0;
202
203                         if (timestamping_enabled) {
204                                 rte_mbuf_timestamp_t timestamp;
205
206                                 /* nanoseconds */
207                                 timestamp =
208                                         rte_le_to_cpu_32(*((uint32_t *)
209                                         (packets[i].header + 4)));
210                                 timestamp <<= 32;
211                                 /* seconds */
212                                 timestamp |=
213                                         rte_le_to_cpu_32(*((uint32_t *)
214                                         (packets[i].header + 8)));
215                                 *nfb_timestamp_dynfield(mbuf) = timestamp;
216                                 mbuf->ol_flags |= nfb_timestamp_rx_dynflag;
217                         }
218
219                         bufs[num_rx++] = mbuf;
220                         num_bytes += packet_size;
221                 } else {
222                         /*
223                          * NDP packet will not fit in one mbuf,
224                          * scattered mode is not enabled, drop packet
225                          */
226                         rte_pktmbuf_free(mbuf);
227                 }
228         }
229
230         ndp_rx_burst_put(ndp->queue);
231
232         ndp->rx_pkts += num_rx;
233         ndp->rx_bytes += num_bytes;
234         return num_rx;
235 }
236
237 #endif /* _NFB_RX_H_ */