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