Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) IGEL Co.,Ltd.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <stdlib.h>
7 : :
8 : : #include <rte_mbuf.h>
9 : : #include <ethdev_driver.h>
10 : : #include <ethdev_vdev.h>
11 : : #include <rte_malloc.h>
12 : : #include <rte_memcpy.h>
13 : : #include <bus_vdev_driver.h>
14 : : #include <rte_kvargs.h>
15 : : #include <rte_spinlock.h>
16 : :
17 : : #define ETH_NULL_PACKET_SIZE_ARG "size"
18 : : #define ETH_NULL_PACKET_COPY_ARG "copy"
19 : : #define ETH_NULL_PACKET_NO_RX_ARG "no-rx"
20 : :
21 : : static unsigned int default_packet_size = 64;
22 : : static unsigned int default_packet_copy;
23 : : static unsigned int default_no_rx;
24 : :
25 : : static const char *valid_arguments[] = {
26 : : ETH_NULL_PACKET_SIZE_ARG,
27 : : ETH_NULL_PACKET_COPY_ARG,
28 : : ETH_NULL_PACKET_NO_RX_ARG,
29 : : NULL
30 : : };
31 : :
32 : : struct pmd_internals;
33 : :
34 : : struct null_queue {
35 : : struct pmd_internals *internals;
36 : :
37 : : /**
38 : : * For RX queue:
39 : : * Mempool to allocate mbufs from.
40 : : *
41 : : * For TX queue:
42 : : * Mempool to free mbufs to, if fast release of mbufs is enabled.
43 : : * UINTPTR_MAX if the mempool for fast release of mbufs has not yet been detected.
44 : : * NULL if fast release of mbufs is not enabled.
45 : : *
46 : : * @see RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
47 : : */
48 : : struct rte_mempool *mb_pool;
49 : : void *dummy_packet;
50 : :
51 : : uint64_t rx_pkts;
52 : : uint64_t rx_bytes;
53 : :
54 : : RTE_ATOMIC(uint64_t) tx_pkts;
55 : : RTE_ATOMIC(uint64_t) tx_bytes;
56 : : };
57 : :
58 : : struct pmd_options {
59 : : unsigned int packet_copy;
60 : : unsigned int packet_size;
61 : : unsigned int no_rx;
62 : : };
63 : :
64 : : struct pmd_internals {
65 : : unsigned int packet_size;
66 : : unsigned int packet_copy;
67 : : unsigned int no_rx;
68 : : uint16_t port_id;
69 : :
70 : : struct null_queue rx_null_queues[RTE_MAX_QUEUES_PER_PORT];
71 : : struct null_queue tx_null_queues[RTE_MAX_QUEUES_PER_PORT];
72 : :
73 : : struct rte_ether_addr eth_addr;
74 : : /** Bit mask of RSS offloads, the bit offset also means flow type */
75 : : uint64_t flow_type_rss_offloads;
76 : :
77 : : rte_spinlock_t rss_lock;
78 : :
79 : : uint16_t reta_size;
80 : : struct rte_eth_rss_reta_entry64 reta_conf[RTE_ETH_RSS_RETA_SIZE_128 /
81 : : RTE_ETH_RETA_GROUP_SIZE];
82 : :
83 : : uint8_t rss_key[40]; /**< 40-byte hash key. */
84 : : };
85 : : static struct rte_eth_link pmd_link = {
86 : : .link_speed = RTE_ETH_SPEED_NUM_10G,
87 : : .link_duplex = RTE_ETH_LINK_FULL_DUPLEX,
88 : : .link_status = RTE_ETH_LINK_DOWN,
89 : : .link_autoneg = RTE_ETH_LINK_FIXED,
90 : : };
91 : :
92 [ - + ]: 253 : RTE_LOG_REGISTER_DEFAULT(eth_null_logtype, NOTICE);
93 : : #define RTE_LOGTYPE_ETH_NULL eth_null_logtype
94 : :
95 : : #define PMD_LOG(level, ...) \
96 : : RTE_LOG_LINE_PREFIX(level, ETH_NULL, "%s(): ", __func__, __VA_ARGS__)
97 : :
98 : : static uint16_t
99 : 0 : eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
100 : : {
101 : : unsigned int i;
102 : : struct null_queue *h = q;
103 : : unsigned int packet_size;
104 : : uint64_t bytes = 0;
105 : :
106 : 0 : packet_size = h->internals->packet_size;
107 [ # # ]: 0 : if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0)
108 : : return 0;
109 : :
110 [ # # ]: 0 : for (i = 0; i < nb_bufs; i++) {
111 : 0 : bufs[i]->data_len = (uint16_t)packet_size;
112 : 0 : bufs[i]->pkt_len = packet_size;
113 : 0 : bytes += packet_size;
114 : 0 : bufs[i]->port = h->internals->port_id;
115 : : }
116 : :
117 : 0 : h->rx_pkts += nb_bufs;
118 : 0 : h->rx_bytes += bytes;
119 : 0 : return nb_bufs;
120 : : }
121 : :
122 : : static uint16_t
123 : 0 : eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
124 : : {
125 : : unsigned int i;
126 : : struct null_queue *h = q;
127 : : unsigned int packet_size;
128 : : uint64_t bytes = 0;
129 : :
130 : 0 : packet_size = h->internals->packet_size;
131 [ # # ]: 0 : if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0)
132 : : return 0;
133 : :
134 [ # # ]: 0 : for (i = 0; i < nb_bufs; i++) {
135 [ # # ]: 0 : rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
136 : : packet_size);
137 : 0 : bufs[i]->data_len = (uint16_t)packet_size;
138 : 0 : bufs[i]->pkt_len = packet_size;
139 : 0 : bytes += packet_size;
140 : 0 : bufs[i]->port = h->internals->port_id;
141 : : }
142 : :
143 : 0 : h->rx_pkts += nb_bufs;
144 : 0 : h->rx_bytes += bytes;
145 : 0 : return nb_bufs;
146 : : }
147 : :
148 : : static uint16_t
149 : 0 : eth_null_no_rx(void *q __rte_unused, struct rte_mbuf **bufs __rte_unused,
150 : : uint16_t nb_bufs __rte_unused)
151 : : {
152 : 0 : return 0;
153 : : }
154 : :
155 : : enum eth_tx_free_mode {
156 : : ETH_TX_FREE_MODE_NO_MBUF_FAST_FREE, /* MBUF_FAST_FREE not possible. */
157 : : ETH_TX_FREE_MODE_MBUF_FAST_FREE, /* MBUF_FAST_FREE enabled for the device. */
158 : : ETH_TX_FREE_MODE_PER_QUEUE, /* Varies per TX queue. */
159 : : };
160 : :
161 : : static __rte_always_inline uint16_t
162 : : eth_null_tx_common(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs,
163 : : enum eth_tx_free_mode mode)
164 : : {
165 : : struct null_queue *h = q;
166 : : unsigned int i;
167 : : uint64_t bytes = 0;
168 : :
169 [ # # # # : 0 : for (i = 0; i < nb_bufs; i++)
# # ]
170 : 0 : bytes += rte_pktmbuf_pkt_len(bufs[i]);
171 : :
172 : : if (mode == ETH_TX_FREE_MODE_MBUF_FAST_FREE ||
173 [ # # ]: 0 : (mode == ETH_TX_FREE_MODE_PER_QUEUE && h->mb_pool != NULL)) {
174 : : /* RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE */
175 [ # # # # ]: 0 : if (unlikely(h->mb_pool == (void *)UINTPTR_MAX)) {
176 [ # # # # ]: 0 : if (unlikely(nb_bufs == 0))
177 : : return 0; /* Do not dereference uninitialized bufs[0]. */
178 : 0 : h->mb_pool = bufs[0]->pool;
179 : : }
180 [ # # # # ]: 0 : rte_mbuf_raw_free_bulk(h->mb_pool, bufs, nb_bufs);
181 : : } else {
182 : 0 : rte_pktmbuf_free_bulk(bufs, nb_bufs);
183 : : }
184 : 0 : rte_atomic_fetch_add_explicit(&h->tx_pkts, nb_bufs, rte_memory_order_relaxed);
185 : 0 : rte_atomic_fetch_add_explicit(&h->tx_bytes, bytes, rte_memory_order_relaxed);
186 : :
187 : 0 : return nb_bufs;
188 : : }
189 : :
190 : : static uint16_t
191 : 0 : eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
192 : : {
193 : 0 : return eth_null_tx_common(q, bufs, nb_bufs, ETH_TX_FREE_MODE_PER_QUEUE);
194 : : }
195 : :
196 : : static uint16_t
197 : 0 : eth_null_tx_no_mbuf_fast_free(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
198 : : {
199 : 0 : return eth_null_tx_common(q, bufs, nb_bufs, ETH_TX_FREE_MODE_NO_MBUF_FAST_FREE);
200 : : }
201 : :
202 : : static uint16_t
203 : 0 : eth_null_tx_mbuf_fast_free(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
204 : : {
205 : 0 : return eth_null_tx_common(q, bufs, nb_bufs, ETH_TX_FREE_MODE_MBUF_FAST_FREE);
206 : : }
207 : :
208 : : static uint16_t
209 : 0 : eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
210 : : {
211 : : struct null_queue *h = q;
212 : : unsigned int i;
213 : : uint64_t bytes = 0;
214 : :
215 [ # # ]: 0 : for (i = 0; i < nb_bufs; i++) {
216 : 0 : struct rte_mbuf *m = bufs[i];
217 : 0 : size_t len = RTE_MIN(h->internals->packet_size, m->data_len);
218 : :
219 [ # # ]: 0 : rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(m, void *), len);
220 : 0 : bytes += m->pkt_len;
221 : : }
222 : :
223 : 0 : rte_atomic_fetch_add_explicit(&h->tx_pkts, nb_bufs, rte_memory_order_relaxed);
224 : 0 : rte_atomic_fetch_add_explicit(&h->tx_bytes, bytes, rte_memory_order_relaxed);
225 : 0 : return nb_bufs;
226 : : }
227 : :
228 : : static void
229 : 8 : eth_dev_assign_rxtx_ops(struct rte_eth_dev *dev)
230 : : {
231 : 8 : struct pmd_internals *internals = dev->data->dev_private;
232 : :
233 [ - + ]: 8 : if (internals->packet_copy) {
234 : 0 : dev->rx_pkt_burst = eth_null_copy_rx;
235 : 0 : dev->tx_pkt_burst = eth_null_copy_tx;
236 : : } else {
237 [ - + ]: 8 : if (internals->no_rx)
238 : 0 : dev->rx_pkt_burst = eth_null_no_rx;
239 : : else
240 : 8 : dev->rx_pkt_burst = eth_null_rx;
241 : :
242 : 8 : dev->tx_pkt_burst = eth_null_tx;
243 [ - + ]: 8 : if (dev->data->dev_conf.txmode.offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS)
244 : 0 : dev->tx_pkt_burst = eth_null_tx_no_mbuf_fast_free;
245 [ - + ]: 8 : if (dev->data->dev_conf.txmode.offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
246 : 0 : dev->tx_pkt_burst = eth_null_tx_mbuf_fast_free;
247 : : }
248 : 8 : }
249 : :
250 : : static int
251 : 2 : eth_dev_configure(struct rte_eth_dev *dev)
252 : : {
253 : 2 : struct pmd_internals *internals = dev->data->dev_private;
254 : :
255 [ - + ]: 2 : if ((dev->data->dev_conf.txmode.offloads &
256 : : (RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE | RTE_ETH_TX_OFFLOAD_MULTI_SEGS)) ==
257 : : (RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE | RTE_ETH_TX_OFFLOAD_MULTI_SEGS)) {
258 : 0 : PMD_LOG(ERR,
259 : : "TX offloads MBUF_FAST_FREE and MULTI_SEGS are mutually exclusive");
260 : 0 : return -EINVAL;
261 : : }
262 [ - + ]: 2 : if (dev->data->dev_conf.txmode.offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE &&
263 [ # # ]: 0 : internals->packet_copy) {
264 : 0 : PMD_LOG(INFO,
265 : : "TX offload MBUF_FAST_FREE is ignored with %s argument",
266 : : ETH_NULL_PACKET_COPY_ARG);
267 : : }
268 : : /* Assign RX/TX ops depending on device TX offloads. */
269 : 2 : eth_dev_assign_rxtx_ops(dev);
270 : 2 : return 0;
271 : : }
272 : :
273 : : static int
274 : 0 : eth_dev_start(struct rte_eth_dev *dev)
275 : : {
276 : : uint16_t i;
277 : :
278 [ # # ]: 0 : if (dev == NULL)
279 : : return -EINVAL;
280 : :
281 : 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
282 : :
283 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
284 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
285 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
286 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
287 : :
288 : : return 0;
289 : : }
290 : :
291 : : static int
292 : 0 : eth_dev_stop(struct rte_eth_dev *dev)
293 : : {
294 : : uint16_t i;
295 : :
296 [ # # ]: 0 : if (dev == NULL)
297 : : return 0;
298 : :
299 : 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
300 : :
301 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
302 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
303 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
304 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
305 : :
306 : : return 0;
307 : : }
308 : :
309 : : static int
310 : 0 : eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
311 : : uint16_t nb_rx_desc __rte_unused,
312 : : unsigned int socket_id __rte_unused,
313 : : const struct rte_eth_rxconf *rx_conf __rte_unused,
314 : : struct rte_mempool *mb_pool)
315 : : {
316 : : struct rte_mbuf *dummy_packet;
317 : : struct pmd_internals *internals;
318 : : unsigned int packet_size;
319 : :
320 [ # # ]: 0 : if ((dev == NULL) || (mb_pool == NULL))
321 : : return -EINVAL;
322 : :
323 : 0 : internals = dev->data->dev_private;
324 : :
325 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
326 : : return -ENODEV;
327 : :
328 : 0 : packet_size = internals->packet_size;
329 : :
330 : 0 : internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
331 : 0 : dev->data->rx_queues[rx_queue_id] =
332 : 0 : &internals->rx_null_queues[rx_queue_id];
333 : 0 : dummy_packet = rte_zmalloc_socket(NULL,
334 : 0 : packet_size, 0, dev->data->numa_node);
335 [ # # ]: 0 : if (dummy_packet == NULL)
336 : : return -ENOMEM;
337 : :
338 : 0 : internals->rx_null_queues[rx_queue_id].internals = internals;
339 : 0 : internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
340 : :
341 : 0 : return 0;
342 : : }
343 : :
344 : : static int
345 : 0 : eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
346 : : uint16_t nb_tx_desc __rte_unused,
347 : : unsigned int socket_id __rte_unused,
348 : : const struct rte_eth_txconf *tx_conf)
349 : : {
350 : : struct rte_mbuf *dummy_packet;
351 : : struct pmd_internals *internals;
352 : : unsigned int packet_size;
353 : :
354 [ # # ]: 0 : if (dev == NULL)
355 : : return -EINVAL;
356 : :
357 : 0 : internals = dev->data->dev_private;
358 : :
359 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
360 : : return -ENODEV;
361 : :
362 [ # # ]: 0 : if (((dev->data->dev_conf.txmode.offloads | tx_conf->offloads) &
363 : : (RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE | RTE_ETH_TX_OFFLOAD_MULTI_SEGS)) ==
364 : : (RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE | RTE_ETH_TX_OFFLOAD_MULTI_SEGS)) {
365 : 0 : PMD_LOG(ERR,
366 : : "TX offloads MBUF_FAST_FREE and MULTI_SEGS are mutually exclusive");
367 : 0 : return -EINVAL;
368 : : }
369 [ # # ]: 0 : if (tx_conf->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE &&
370 [ # # ]: 0 : internals->packet_copy) {
371 : 0 : PMD_LOG(INFO,
372 : : "TX offload MBUF_FAST_FREE is ignored with %s argument",
373 : : ETH_NULL_PACKET_COPY_ARG);
374 : : }
375 : :
376 : 0 : packet_size = internals->packet_size;
377 : :
378 : 0 : dev->data->tx_queues[tx_queue_id] =
379 : 0 : &internals->tx_null_queues[tx_queue_id];
380 : 0 : dummy_packet = rte_zmalloc_socket(NULL,
381 : 0 : packet_size, 0, dev->data->numa_node);
382 [ # # ]: 0 : if (dummy_packet == NULL)
383 : : return -ENOMEM;
384 : :
385 : 0 : internals->tx_null_queues[tx_queue_id].internals = internals;
386 : 0 : internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
387 : 0 : internals->tx_null_queues[tx_queue_id].mb_pool =
388 : 0 : (dev->data->dev_conf.txmode.offloads | tx_conf->offloads) &
389 : : RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE ?
390 [ # # ]: 0 : (void *)UINTPTR_MAX : NULL;
391 : :
392 : 0 : return 0;
393 : : }
394 : :
395 : : static int
396 : 0 : eth_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused)
397 : : {
398 : 0 : return 0;
399 : : }
400 : :
401 : : static int
402 : 9 : eth_dev_info(struct rte_eth_dev *dev,
403 : : struct rte_eth_dev_info *dev_info)
404 : : {
405 : : struct pmd_internals *internals;
406 : :
407 [ + - ]: 9 : if ((dev == NULL) || (dev_info == NULL))
408 : : return -EINVAL;
409 : :
410 : 9 : internals = dev->data->dev_private;
411 : 9 : dev_info->max_mac_addrs = 1;
412 : 9 : dev_info->max_rx_pktlen = (uint32_t)-1;
413 : 9 : dev_info->max_rx_queues = RTE_DIM(internals->rx_null_queues);
414 : 9 : dev_info->max_tx_queues = RTE_DIM(internals->tx_null_queues);
415 : 9 : dev_info->min_rx_bufsize = 0;
416 : 9 : dev_info->tx_queue_offload_capa = RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
417 : : RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
418 : 9 : dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_MT_LOCKFREE |
419 : : dev_info->tx_queue_offload_capa;
420 : :
421 : 9 : dev_info->reta_size = internals->reta_size;
422 : 9 : dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
423 : 9 : dev_info->hash_key_size = sizeof(internals->rss_key);
424 : :
425 : 9 : return 0;
426 : : }
427 : :
428 : : static int
429 : 2 : eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
430 : : {
431 : 2 : const struct pmd_internals *internal = dev->data->dev_private;
432 : : unsigned int i;
433 : :
434 [ + + ]: 4 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
435 : 2 : uint64_t pkts = internal->rx_null_queues[i].rx_pkts;
436 : 2 : uint64_t bytes = internal->rx_null_queues[i].rx_bytes;
437 : :
438 : 2 : stats->ipackets += pkts;
439 : 2 : stats->ibytes += bytes;
440 : :
441 [ + - ]: 2 : if (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
442 : 2 : stats->q_ipackets[i] = pkts;
443 : 2 : stats->q_ibytes[i] = bytes;
444 : : }
445 : : }
446 : :
447 [ + + ]: 4 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
448 : : const struct null_queue *q = &internal->tx_null_queues[i];
449 : : uint64_t pkts, bytes;
450 : :
451 : 2 : pkts = rte_atomic_load_explicit(&q->tx_pkts, rte_memory_order_relaxed);
452 : 2 : bytes = rte_atomic_load_explicit(&q->tx_bytes, rte_memory_order_relaxed);
453 : :
454 : 2 : stats->opackets = pkts;
455 : 2 : stats->obytes = bytes;
456 : :
457 [ + - ]: 2 : if (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
458 : 2 : stats->q_opackets[i] = pkts;
459 : 2 : stats->q_obytes[i] = bytes;
460 : : }
461 : : }
462 : :
463 : 2 : return 0;
464 : : }
465 : :
466 : : static int
467 : 0 : eth_stats_reset(struct rte_eth_dev *dev)
468 : : {
469 : 0 : struct pmd_internals *internal = dev->data->dev_private;
470 : : unsigned int i;
471 : :
472 [ # # ]: 0 : for (i = 0; i < RTE_DIM(internal->rx_null_queues); i++) {
473 : 0 : internal->rx_null_queues[i].rx_pkts = 0;
474 : 0 : internal->rx_null_queues[i].rx_bytes = 0;
475 : : }
476 : :
477 [ # # ]: 0 : for (i = 0; i < RTE_DIM(internal->tx_null_queues); i++) {
478 : : struct null_queue *q = &internal->tx_null_queues[i];
479 : :
480 : 0 : rte_atomic_store_explicit(&q->tx_pkts, 0, rte_memory_order_relaxed);
481 : 0 : rte_atomic_store_explicit(&q->tx_bytes, 0, rte_memory_order_relaxed);
482 : : }
483 : :
484 : 0 : return 0;
485 : : }
486 : :
487 : : static void
488 : 0 : eth_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
489 : : {
490 : 0 : struct null_queue *nq = dev->data->rx_queues[qid];
491 : :
492 [ # # ]: 0 : if (nq == NULL)
493 : : return;
494 : :
495 : 0 : rte_free(nq->dummy_packet);
496 : : }
497 : :
498 : : static void
499 : 0 : eth_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
500 : : {
501 : 0 : struct null_queue *nq = dev->data->tx_queues[qid];
502 : :
503 [ # # ]: 0 : if (nq == NULL)
504 : : return;
505 : :
506 : 0 : rte_free(nq->dummy_packet);
507 : : }
508 : :
509 : : static int
510 : 5 : eth_link_update(struct rte_eth_dev *dev __rte_unused,
511 : 5 : int wait_to_complete __rte_unused) { return 0; }
512 : :
513 : : static int
514 : 0 : eth_rss_reta_update(struct rte_eth_dev *dev,
515 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
516 : : {
517 : : int i, j;
518 : 0 : struct pmd_internals *internal = dev->data->dev_private;
519 : :
520 [ # # ]: 0 : if (reta_size != internal->reta_size)
521 : : return -EINVAL;
522 : :
523 : 0 : rte_spinlock_lock(&internal->rss_lock);
524 : :
525 : : /* Copy RETA table */
526 [ # # ]: 0 : for (i = 0; i < (internal->reta_size / RTE_ETH_RETA_GROUP_SIZE); i++) {
527 : 0 : internal->reta_conf[i].mask = reta_conf[i].mask;
528 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++)
529 [ # # ]: 0 : if ((reta_conf[i].mask >> j) & 0x01)
530 : 0 : internal->reta_conf[i].reta[j] = reta_conf[i].reta[j];
531 : : }
532 : :
533 : : rte_spinlock_unlock(&internal->rss_lock);
534 : :
535 : 0 : return 0;
536 : : }
537 : :
538 : : static int
539 : 0 : eth_rss_reta_query(struct rte_eth_dev *dev,
540 : : struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
541 : : {
542 : : int i, j;
543 : 0 : struct pmd_internals *internal = dev->data->dev_private;
544 : :
545 [ # # ]: 0 : if (reta_size != internal->reta_size)
546 : : return -EINVAL;
547 : :
548 : 0 : rte_spinlock_lock(&internal->rss_lock);
549 : :
550 : : /* Copy RETA table */
551 [ # # ]: 0 : for (i = 0; i < (internal->reta_size / RTE_ETH_RETA_GROUP_SIZE); i++) {
552 [ # # ]: 0 : for (j = 0; j < RTE_ETH_RETA_GROUP_SIZE; j++)
553 [ # # ]: 0 : if ((reta_conf[i].mask >> j) & 0x01)
554 : 0 : reta_conf[i].reta[j] = internal->reta_conf[i].reta[j];
555 : : }
556 : :
557 : : rte_spinlock_unlock(&internal->rss_lock);
558 : :
559 : 0 : return 0;
560 : : }
561 : :
562 : : static int
563 : 0 : eth_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf)
564 : : {
565 : 0 : struct pmd_internals *internal = dev->data->dev_private;
566 : :
567 : 0 : rte_spinlock_lock(&internal->rss_lock);
568 : :
569 [ # # ]: 0 : if ((rss_conf->rss_hf & internal->flow_type_rss_offloads) != 0)
570 : 0 : dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf =
571 : : rss_conf->rss_hf & internal->flow_type_rss_offloads;
572 : :
573 [ # # ]: 0 : if (rss_conf->rss_key)
574 [ # # ]: 0 : rte_memcpy(internal->rss_key, rss_conf->rss_key, 40);
575 : :
576 : : rte_spinlock_unlock(&internal->rss_lock);
577 : :
578 : 0 : return 0;
579 : : }
580 : :
581 : : static int
582 : 1 : eth_rss_hash_conf_get(struct rte_eth_dev *dev,
583 : : struct rte_eth_rss_conf *rss_conf)
584 : : {
585 : 1 : struct pmd_internals *internal = dev->data->dev_private;
586 : :
587 : 1 : rte_spinlock_lock(&internal->rss_lock);
588 : :
589 : 1 : rss_conf->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
590 [ + - ]: 1 : if (rss_conf->rss_key)
591 [ - + ]: 1 : rte_memcpy(rss_conf->rss_key, internal->rss_key, 40);
592 : :
593 : : rte_spinlock_unlock(&internal->rss_lock);
594 : :
595 : 1 : return 0;
596 : : }
597 : :
598 : : static int
599 : 0 : eth_mac_address_set(__rte_unused struct rte_eth_dev *dev,
600 : : __rte_unused struct rte_ether_addr *addr)
601 : : {
602 : 0 : return 0;
603 : : }
604 : :
605 : : static int
606 : 6 : eth_dev_close(struct rte_eth_dev *dev)
607 : : {
608 : 6 : PMD_LOG(INFO, "Closing null ethdev on NUMA socket %u",
609 : : rte_socket_id());
610 : :
611 [ + - ]: 6 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
612 : : return 0;
613 : :
614 : : /* mac_addrs must not be freed alone because part of dev_private */
615 : 6 : dev->data->mac_addrs = NULL;
616 : :
617 : 6 : return 0;
618 : : }
619 : :
620 : : static const struct eth_dev_ops ops = {
621 : : .dev_close = eth_dev_close,
622 : : .dev_start = eth_dev_start,
623 : : .dev_stop = eth_dev_stop,
624 : : .dev_configure = eth_dev_configure,
625 : : .dev_infos_get = eth_dev_info,
626 : : .rx_queue_setup = eth_rx_queue_setup,
627 : : .tx_queue_setup = eth_tx_queue_setup,
628 : : .rx_queue_release = eth_rx_queue_release,
629 : : .tx_queue_release = eth_tx_queue_release,
630 : : .mtu_set = eth_mtu_set,
631 : : .link_update = eth_link_update,
632 : : .mac_addr_set = eth_mac_address_set,
633 : : .stats_get = eth_stats_get,
634 : : .stats_reset = eth_stats_reset,
635 : : .reta_update = eth_rss_reta_update,
636 : : .reta_query = eth_rss_reta_query,
637 : : .rss_hash_update = eth_rss_hash_update,
638 : : .rss_hash_conf_get = eth_rss_hash_conf_get
639 : : };
640 : :
641 : : static int
642 : 6 : eth_dev_null_create(struct rte_vdev_device *dev, struct pmd_options *args)
643 : : {
644 : : const unsigned int nb_rx_queues = 1;
645 : : const unsigned int nb_tx_queues = 1;
646 : : struct rte_eth_dev_data *data;
647 : : struct pmd_internals *internals = NULL;
648 : : struct rte_eth_dev *eth_dev = NULL;
649 : :
650 : : static const uint8_t default_rss_key[40] = {
651 : : 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D,
652 : : 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
653 : : 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B,
654 : : 0xBE, 0xAC, 0x01, 0xFA
655 : : };
656 : :
657 [ + - ]: 6 : if (dev->device.numa_node == SOCKET_ID_ANY)
658 : 6 : dev->device.numa_node = rte_socket_id();
659 : :
660 : 6 : PMD_LOG(INFO, "Creating null ethdev on numa socket %u",
661 : : dev->device.numa_node);
662 : :
663 : 6 : eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internals));
664 [ + - ]: 6 : if (!eth_dev)
665 : : return -ENOMEM;
666 : :
667 : : /* now put it all together
668 : : * - store queue data in internals,
669 : : * - store numa_node info in ethdev data
670 : : * - point eth_dev_data to internals
671 : : * - and point eth_dev structure to new eth_dev_data structure
672 : : */
673 : : /* NOTE: we'll replace the data element, of originally allocated eth_dev
674 : : * so the nulls are local per-process */
675 : :
676 : 6 : internals = eth_dev->data->dev_private;
677 : 6 : internals->packet_size = args->packet_size;
678 : 6 : internals->packet_copy = args->packet_copy;
679 : 6 : internals->no_rx = args->no_rx;
680 : 6 : internals->port_id = eth_dev->data->port_id;
681 : 6 : rte_eth_random_addr(internals->eth_addr.addr_bytes);
682 : :
683 : 6 : internals->flow_type_rss_offloads = RTE_ETH_RSS_PROTO_MASK;
684 : 6 : internals->reta_size = RTE_DIM(internals->reta_conf) * RTE_ETH_RETA_GROUP_SIZE;
685 : :
686 [ - + ]: 6 : rte_memcpy(internals->rss_key, default_rss_key, 40);
687 : :
688 : 6 : data = eth_dev->data;
689 : 6 : data->nb_rx_queues = (uint16_t)nb_rx_queues;
690 : 6 : data->nb_tx_queues = (uint16_t)nb_tx_queues;
691 : 6 : data->dev_link = pmd_link;
692 : 6 : data->mac_addrs = &internals->eth_addr;
693 : 6 : data->promiscuous = 1;
694 : 6 : data->all_multicast = 1;
695 : 6 : data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
696 : :
697 : 6 : eth_dev->dev_ops = &ops;
698 : :
699 : : /* finally assign rx and tx ops */
700 : 6 : eth_dev_assign_rxtx_ops(eth_dev);
701 : :
702 : 6 : rte_eth_dev_probing_finish(eth_dev);
703 : 6 : return 0;
704 : : }
705 : :
706 : : static inline int
707 : 0 : get_packet_size_arg(const char *key __rte_unused,
708 : : const char *value, void *extra_args)
709 : : {
710 : : const char *a = value;
711 : : unsigned int *packet_size = extra_args;
712 : :
713 [ # # ]: 0 : if ((value == NULL) || (extra_args == NULL))
714 : : return -EINVAL;
715 : :
716 : 0 : *packet_size = (unsigned int)strtoul(a, NULL, 0);
717 [ # # ]: 0 : if (*packet_size == UINT_MAX)
718 : 0 : return -1;
719 : :
720 : : return 0;
721 : : }
722 : :
723 : : static inline int
724 : 0 : get_packet_copy_arg(const char *key __rte_unused,
725 : : const char *value, void *extra_args)
726 : : {
727 : : const char *a = value;
728 : : unsigned int *packet_copy = extra_args;
729 : :
730 [ # # ]: 0 : if ((value == NULL) || (extra_args == NULL))
731 : : return -EINVAL;
732 : :
733 : 0 : *packet_copy = (unsigned int)strtoul(a, NULL, 0);
734 [ # # ]: 0 : if (*packet_copy == UINT_MAX)
735 : 0 : return -1;
736 : :
737 : : return 0;
738 : : }
739 : :
740 : : static int
741 : 0 : get_packet_no_rx_arg(const char *key __rte_unused,
742 : : const char *value, void *extra_args)
743 : : {
744 : : const char *a = value;
745 : : unsigned int no_rx;
746 : :
747 [ # # ]: 0 : if (value == NULL || extra_args == NULL)
748 : : return -EINVAL;
749 : :
750 : 0 : no_rx = (unsigned int)strtoul(a, NULL, 0);
751 [ # # ]: 0 : if (no_rx != 0 && no_rx != 1)
752 : : return -1;
753 : :
754 : 0 : *(unsigned int *)extra_args = no_rx;
755 : 0 : return 0;
756 : : }
757 : :
758 : : static int
759 : 6 : rte_pmd_null_probe(struct rte_vdev_device *dev)
760 : : {
761 : : const char *name, *params;
762 : 6 : struct pmd_options args = {
763 : : .packet_copy = default_packet_copy,
764 : : .packet_size = default_packet_size,
765 : : .no_rx = default_no_rx,
766 : : };
767 : : struct rte_kvargs *kvlist = NULL;
768 : : struct rte_eth_dev *eth_dev;
769 : : int ret;
770 : :
771 [ + - ]: 6 : if (!dev)
772 : : return -EINVAL;
773 : :
774 : : name = rte_vdev_device_name(dev);
775 : : params = rte_vdev_device_args(dev);
776 : 6 : PMD_LOG(INFO, "Initializing pmd_null for %s", name);
777 : :
778 [ - + ]: 6 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
779 : 0 : eth_dev = rte_eth_dev_attach_secondary(name);
780 [ # # ]: 0 : if (!eth_dev) {
781 : 0 : PMD_LOG(ERR, "Failed to probe %s", name);
782 : 0 : return -1;
783 : : }
784 : : /* TODO: request info from primary to set up Rx and Tx */
785 : 0 : eth_dev->dev_ops = &ops;
786 : 0 : eth_dev->device = &dev->device;
787 : 0 : eth_dev_assign_rxtx_ops(eth_dev);
788 : 0 : rte_eth_dev_probing_finish(eth_dev);
789 : 0 : return 0;
790 : : }
791 : :
792 [ + - ]: 6 : if (params != NULL) {
793 : 6 : kvlist = rte_kvargs_parse(params, valid_arguments);
794 [ + - ]: 6 : if (kvlist == NULL)
795 : : return -1;
796 : :
797 : 6 : ret = rte_kvargs_process(kvlist,
798 : : ETH_NULL_PACKET_SIZE_ARG,
799 : : &get_packet_size_arg, &args.packet_size);
800 [ - + ]: 6 : if (ret < 0)
801 : 0 : goto free_kvlist;
802 : :
803 : :
804 : 6 : ret = rte_kvargs_process(kvlist,
805 : : ETH_NULL_PACKET_COPY_ARG,
806 : : &get_packet_copy_arg, &args.packet_copy);
807 [ - + ]: 6 : if (ret < 0)
808 : 0 : goto free_kvlist;
809 : :
810 : 6 : ret = rte_kvargs_process(kvlist,
811 : : ETH_NULL_PACKET_NO_RX_ARG,
812 : : &get_packet_no_rx_arg, &args.no_rx);
813 [ - + ]: 6 : if (ret < 0)
814 : 0 : goto free_kvlist;
815 : :
816 [ - + - - ]: 6 : if (args.no_rx && args.packet_copy) {
817 : 0 : PMD_LOG(ERR,
818 : : "Both %s and %s arguments at the same time not supported",
819 : : ETH_NULL_PACKET_COPY_ARG,
820 : : ETH_NULL_PACKET_NO_RX_ARG);
821 : 0 : goto free_kvlist;
822 : : }
823 : : }
824 : :
825 [ + - ]: 12 : PMD_LOG(INFO, "Configure pmd_null: packet size is %d, "
826 : : "packet copy is %s", args.packet_size,
827 : : args.packet_copy ? "enabled" : "disabled");
828 : :
829 : 6 : ret = eth_dev_null_create(dev, &args);
830 : :
831 : 6 : free_kvlist:
832 : 6 : rte_kvargs_free(kvlist);
833 : 6 : return ret;
834 : : }
835 : :
836 : : static int
837 : 6 : rte_pmd_null_remove(struct rte_vdev_device *dev)
838 : : {
839 : : struct rte_eth_dev *eth_dev = NULL;
840 : :
841 [ + - ]: 6 : if (!dev)
842 : : return -EINVAL;
843 : :
844 : : /* find the ethdev entry */
845 : 6 : eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev));
846 [ + - ]: 6 : if (eth_dev == NULL)
847 : : return 0; /* port already released */
848 : :
849 : 6 : eth_dev_close(eth_dev);
850 : 6 : rte_eth_dev_release_port(eth_dev);
851 : :
852 : 6 : return 0;
853 : : }
854 : :
855 : : static struct rte_vdev_driver pmd_null_drv = {
856 : : .probe = rte_pmd_null_probe,
857 : : .remove = rte_pmd_null_remove,
858 : : };
859 : :
860 : 253 : RTE_PMD_REGISTER_VDEV(net_null, pmd_null_drv);
861 : : RTE_PMD_REGISTER_ALIAS(net_null, eth_null);
862 : : RTE_PMD_REGISTER_PARAM_STRING(net_null,
863 : : "size=<int> "
864 : : "copy=<int> "
865 : : ETH_NULL_PACKET_NO_RX_ARG "=0|1");
|