b2c92ab72aec1964cd1fd9f95b64da1ebe80259f
[dpdk.git] / drivers / net / null / rte_eth_null.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (C) IGEL Co.,Ltd.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of IGEL Co.,Ltd. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <rte_mbuf.h>
35 #include <rte_ethdev_driver.h>
36 #include <rte_ethdev_vdev.h>
37 #include <rte_malloc.h>
38 #include <rte_memcpy.h>
39 #include <rte_bus_vdev.h>
40 #include <rte_kvargs.h>
41 #include <rte_spinlock.h>
42
43 #define ETH_NULL_PACKET_SIZE_ARG        "size"
44 #define ETH_NULL_PACKET_COPY_ARG        "copy"
45
46 static unsigned default_packet_size = 64;
47 static unsigned default_packet_copy;
48
49 static const char *valid_arguments[] = {
50         ETH_NULL_PACKET_SIZE_ARG,
51         ETH_NULL_PACKET_COPY_ARG,
52         NULL
53 };
54
55 struct pmd_internals;
56
57 struct null_queue {
58         struct pmd_internals *internals;
59
60         struct rte_mempool *mb_pool;
61         struct rte_mbuf *dummy_packet;
62
63         rte_atomic64_t rx_pkts;
64         rte_atomic64_t tx_pkts;
65 };
66
67 struct pmd_internals {
68         unsigned packet_size;
69         unsigned packet_copy;
70         uint16_t port_id;
71
72         struct null_queue rx_null_queues[RTE_MAX_QUEUES_PER_PORT];
73         struct null_queue tx_null_queues[RTE_MAX_QUEUES_PER_PORT];
74
75         struct rte_ether_addr eth_addr;
76         /** Bit mask of RSS offloads, the bit offset also means flow type */
77         uint64_t flow_type_rss_offloads;
78
79         rte_spinlock_t rss_lock;
80
81         uint16_t reta_size;
82         struct rte_eth_rss_reta_entry64 reta_conf[ETH_RSS_RETA_SIZE_128 /
83                         RTE_RETA_GROUP_SIZE];
84
85         uint8_t rss_key[40];                /**< 40-byte hash key. */
86 };
87 static struct rte_eth_link pmd_link = {
88         .link_speed = ETH_SPEED_NUM_10G,
89         .link_duplex = ETH_LINK_FULL_DUPLEX,
90         .link_status = ETH_LINK_DOWN,
91         .link_autoneg = ETH_LINK_FIXED,
92 };
93
94 static int eth_null_logtype;
95
96 #define PMD_LOG(level, fmt, args...) \
97         rte_log(RTE_LOG_ ## level, eth_null_logtype, \
98                 "%s(): " fmt "\n", __func__, ##args)
99
100 static uint16_t
101 eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
102 {
103         int i;
104         struct null_queue *h = q;
105         unsigned packet_size;
106
107         if ((q == NULL) || (bufs == NULL))
108                 return 0;
109
110         packet_size = h->internals->packet_size;
111         if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0)
112                 return 0;
113
114         for (i = 0; i < nb_bufs; i++) {
115                 bufs[i]->data_len = (uint16_t)packet_size;
116                 bufs[i]->pkt_len = packet_size;
117                 bufs[i]->port = h->internals->port_id;
118         }
119
120         rte_atomic64_add(&(h->rx_pkts), i);
121
122         return i;
123 }
124
125 static uint16_t
126 eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
127 {
128         int i;
129         struct null_queue *h = q;
130         unsigned packet_size;
131
132         if ((q == NULL) || (bufs == NULL))
133                 return 0;
134
135         packet_size = h->internals->packet_size;
136         if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0)
137                 return 0;
138
139         for (i = 0; i < nb_bufs; i++) {
140                 rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
141                                         packet_size);
142                 bufs[i]->data_len = (uint16_t)packet_size;
143                 bufs[i]->pkt_len = packet_size;
144                 bufs[i]->port = h->internals->port_id;
145         }
146
147         rte_atomic64_add(&(h->rx_pkts), i);
148
149         return i;
150 }
151
152 static uint16_t
153 eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
154 {
155         int i;
156         struct null_queue *h = q;
157
158         if ((q == NULL) || (bufs == NULL))
159                 return 0;
160
161         for (i = 0; i < nb_bufs; i++)
162                 rte_pktmbuf_free(bufs[i]);
163
164         rte_atomic64_add(&(h->tx_pkts), i);
165
166         return i;
167 }
168
169 static uint16_t
170 eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
171 {
172         int i;
173         struct null_queue *h = q;
174         unsigned packet_size;
175
176         if ((q == NULL) || (bufs == NULL))
177                 return 0;
178
179         packet_size = h->internals->packet_size;
180         for (i = 0; i < nb_bufs; i++) {
181                 rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *),
182                                         packet_size);
183                 rte_pktmbuf_free(bufs[i]);
184         }
185
186         rte_atomic64_add(&(h->tx_pkts), i);
187
188         return i;
189 }
190
191 static int
192 eth_dev_configure(struct rte_eth_dev *dev __rte_unused)
193 {
194         return 0;
195 }
196
197 static int
198 eth_dev_start(struct rte_eth_dev *dev)
199 {
200         if (dev == NULL)
201                 return -EINVAL;
202
203         dev->data->dev_link.link_status = ETH_LINK_UP;
204         return 0;
205 }
206
207 static void
208 eth_dev_stop(struct rte_eth_dev *dev)
209 {
210         if (dev == NULL)
211                 return;
212
213         dev->data->dev_link.link_status = ETH_LINK_DOWN;
214 }
215
216 static int
217 eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
218                 uint16_t nb_rx_desc __rte_unused,
219                 unsigned int socket_id __rte_unused,
220                 const struct rte_eth_rxconf *rx_conf __rte_unused,
221                 struct rte_mempool *mb_pool)
222 {
223         struct rte_mbuf *dummy_packet;
224         struct pmd_internals *internals;
225         unsigned packet_size;
226
227         if ((dev == NULL) || (mb_pool == NULL))
228                 return -EINVAL;
229
230         internals = dev->data->dev_private;
231
232         if (rx_queue_id >= dev->data->nb_rx_queues)
233                 return -ENODEV;
234
235         packet_size = internals->packet_size;
236
237         internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
238         dev->data->rx_queues[rx_queue_id] =
239                 &internals->rx_null_queues[rx_queue_id];
240         dummy_packet = rte_zmalloc_socket(NULL,
241                         packet_size, 0, dev->data->numa_node);
242         if (dummy_packet == NULL)
243                 return -ENOMEM;
244
245         internals->rx_null_queues[rx_queue_id].internals = internals;
246         internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
247
248         return 0;
249 }
250
251 static int
252 eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
253                 uint16_t nb_tx_desc __rte_unused,
254                 unsigned int socket_id __rte_unused,
255                 const struct rte_eth_txconf *tx_conf __rte_unused)
256 {
257         struct rte_mbuf *dummy_packet;
258         struct pmd_internals *internals;
259         unsigned packet_size;
260
261         if (dev == NULL)
262                 return -EINVAL;
263
264         internals = dev->data->dev_private;
265
266         if (tx_queue_id >= dev->data->nb_tx_queues)
267                 return -ENODEV;
268
269         packet_size = internals->packet_size;
270
271         dev->data->tx_queues[tx_queue_id] =
272                 &internals->tx_null_queues[tx_queue_id];
273         dummy_packet = rte_zmalloc_socket(NULL,
274                         packet_size, 0, dev->data->numa_node);
275         if (dummy_packet == NULL)
276                 return -ENOMEM;
277
278         internals->tx_null_queues[tx_queue_id].internals = internals;
279         internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
280
281         return 0;
282 }
283
284 static int
285 eth_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused)
286 {
287         return 0;
288 }
289
290 static void
291 eth_dev_info(struct rte_eth_dev *dev,
292                 struct rte_eth_dev_info *dev_info)
293 {
294         struct pmd_internals *internals;
295
296         if ((dev == NULL) || (dev_info == NULL))
297                 return;
298
299         internals = dev->data->dev_private;
300         dev_info->max_mac_addrs = 1;
301         dev_info->max_rx_pktlen = (uint32_t)-1;
302         dev_info->max_rx_queues = RTE_DIM(internals->rx_null_queues);
303         dev_info->max_tx_queues = RTE_DIM(internals->tx_null_queues);
304         dev_info->min_rx_bufsize = 0;
305         dev_info->reta_size = internals->reta_size;
306         dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
307 }
308
309 static int
310 eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
311 {
312         unsigned i, num_stats;
313         unsigned long rx_total = 0, tx_total = 0;
314         const struct pmd_internals *internal;
315
316         if ((dev == NULL) || (igb_stats == NULL))
317                 return -EINVAL;
318
319         internal = dev->data->dev_private;
320         num_stats = RTE_MIN((unsigned)RTE_ETHDEV_QUEUE_STAT_CNTRS,
321                         RTE_MIN(dev->data->nb_rx_queues,
322                                 RTE_DIM(internal->rx_null_queues)));
323         for (i = 0; i < num_stats; i++) {
324                 igb_stats->q_ipackets[i] =
325                         internal->rx_null_queues[i].rx_pkts.cnt;
326                 rx_total += igb_stats->q_ipackets[i];
327         }
328
329         num_stats = RTE_MIN((unsigned)RTE_ETHDEV_QUEUE_STAT_CNTRS,
330                         RTE_MIN(dev->data->nb_tx_queues,
331                                 RTE_DIM(internal->tx_null_queues)));
332         for (i = 0; i < num_stats; i++) {
333                 igb_stats->q_opackets[i] =
334                         internal->tx_null_queues[i].tx_pkts.cnt;
335                 tx_total += igb_stats->q_opackets[i];
336         }
337
338         igb_stats->ipackets = rx_total;
339         igb_stats->opackets = tx_total;
340
341         return 0;
342 }
343
344 static void
345 eth_stats_reset(struct rte_eth_dev *dev)
346 {
347         unsigned i;
348         struct pmd_internals *internal;
349
350         if (dev == NULL)
351                 return;
352
353         internal = dev->data->dev_private;
354         for (i = 0; i < RTE_DIM(internal->rx_null_queues); i++)
355                 internal->rx_null_queues[i].rx_pkts.cnt = 0;
356         for (i = 0; i < RTE_DIM(internal->tx_null_queues); i++)
357                 internal->tx_null_queues[i].tx_pkts.cnt = 0;
358 }
359
360 static void
361 eth_queue_release(void *q)
362 {
363         struct null_queue *nq;
364
365         if (q == NULL)
366                 return;
367
368         nq = q;
369         rte_free(nq->dummy_packet);
370 }
371
372 static int
373 eth_link_update(struct rte_eth_dev *dev __rte_unused,
374                 int wait_to_complete __rte_unused) { return 0; }
375
376 static int
377 eth_rss_reta_update(struct rte_eth_dev *dev,
378                 struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
379 {
380         int i, j;
381         struct pmd_internals *internal = dev->data->dev_private;
382
383         if (reta_size != internal->reta_size)
384                 return -EINVAL;
385
386         rte_spinlock_lock(&internal->rss_lock);
387
388         /* Copy RETA table */
389         for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) {
390                 internal->reta_conf[i].mask = reta_conf[i].mask;
391                 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
392                         if ((reta_conf[i].mask >> j) & 0x01)
393                                 internal->reta_conf[i].reta[j] = reta_conf[i].reta[j];
394         }
395
396         rte_spinlock_unlock(&internal->rss_lock);
397
398         return 0;
399 }
400
401 static int
402 eth_rss_reta_query(struct rte_eth_dev *dev,
403                 struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
404 {
405         int i, j;
406         struct pmd_internals *internal = dev->data->dev_private;
407
408         if (reta_size != internal->reta_size)
409                 return -EINVAL;
410
411         rte_spinlock_lock(&internal->rss_lock);
412
413         /* Copy RETA table */
414         for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) {
415                 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
416                         if ((reta_conf[i].mask >> j) & 0x01)
417                                 reta_conf[i].reta[j] = internal->reta_conf[i].reta[j];
418         }
419
420         rte_spinlock_unlock(&internal->rss_lock);
421
422         return 0;
423 }
424
425 static int
426 eth_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf)
427 {
428         struct pmd_internals *internal = dev->data->dev_private;
429
430         rte_spinlock_lock(&internal->rss_lock);
431
432         if ((rss_conf->rss_hf & internal->flow_type_rss_offloads) != 0)
433                 dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf =
434                                 rss_conf->rss_hf & internal->flow_type_rss_offloads;
435
436         if (rss_conf->rss_key)
437                 rte_memcpy(internal->rss_key, rss_conf->rss_key, 40);
438
439         rte_spinlock_unlock(&internal->rss_lock);
440
441         return 0;
442 }
443
444 static int
445 eth_rss_hash_conf_get(struct rte_eth_dev *dev,
446                 struct rte_eth_rss_conf *rss_conf)
447 {
448         struct pmd_internals *internal = dev->data->dev_private;
449
450         rte_spinlock_lock(&internal->rss_lock);
451
452         rss_conf->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
453         if (rss_conf->rss_key)
454                 rte_memcpy(rss_conf->rss_key, internal->rss_key, 40);
455
456         rte_spinlock_unlock(&internal->rss_lock);
457
458         return 0;
459 }
460
461 static int
462 eth_mac_address_set(__rte_unused struct rte_eth_dev *dev,
463                     __rte_unused struct rte_ether_addr *addr)
464 {
465         return 0;
466 }
467
468 static const struct eth_dev_ops ops = {
469         .dev_start = eth_dev_start,
470         .dev_stop = eth_dev_stop,
471         .dev_configure = eth_dev_configure,
472         .dev_infos_get = eth_dev_info,
473         .rx_queue_setup = eth_rx_queue_setup,
474         .tx_queue_setup = eth_tx_queue_setup,
475         .rx_queue_release = eth_queue_release,
476         .tx_queue_release = eth_queue_release,
477         .mtu_set = eth_mtu_set,
478         .link_update = eth_link_update,
479         .mac_addr_set = eth_mac_address_set,
480         .stats_get = eth_stats_get,
481         .stats_reset = eth_stats_reset,
482         .reta_update = eth_rss_reta_update,
483         .reta_query = eth_rss_reta_query,
484         .rss_hash_update = eth_rss_hash_update,
485         .rss_hash_conf_get = eth_rss_hash_conf_get
486 };
487
488 static int
489 eth_dev_null_create(struct rte_vdev_device *dev,
490                 unsigned packet_size,
491                 unsigned packet_copy)
492 {
493         const unsigned nb_rx_queues = 1;
494         const unsigned nb_tx_queues = 1;
495         struct rte_eth_dev_data *data;
496         struct pmd_internals *internals = NULL;
497         struct rte_eth_dev *eth_dev = NULL;
498
499         static const uint8_t default_rss_key[40] = {
500                 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D,
501                 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
502                 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B,
503                 0xBE, 0xAC, 0x01, 0xFA
504         };
505
506         if (dev->device.numa_node == SOCKET_ID_ANY)
507                 dev->device.numa_node = rte_socket_id();
508
509         PMD_LOG(INFO, "Creating null ethdev on numa socket %u",
510                 dev->device.numa_node);
511
512         eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internals));
513         if (!eth_dev)
514                 return -ENOMEM;
515
516         /* now put it all together
517          * - store queue data in internals,
518          * - store numa_node info in ethdev data
519          * - point eth_dev_data to internals
520          * - and point eth_dev structure to new eth_dev_data structure
521          */
522         /* NOTE: we'll replace the data element, of originally allocated eth_dev
523          * so the nulls are local per-process */
524
525         internals = eth_dev->data->dev_private;
526         internals->packet_size = packet_size;
527         internals->packet_copy = packet_copy;
528         internals->port_id = eth_dev->data->port_id;
529         rte_eth_random_addr(internals->eth_addr.addr_bytes);
530
531         internals->flow_type_rss_offloads =  ETH_RSS_PROTO_MASK;
532         internals->reta_size = RTE_DIM(internals->reta_conf) * RTE_RETA_GROUP_SIZE;
533
534         rte_memcpy(internals->rss_key, default_rss_key, 40);
535
536         data = eth_dev->data;
537         data->nb_rx_queues = (uint16_t)nb_rx_queues;
538         data->nb_tx_queues = (uint16_t)nb_tx_queues;
539         data->dev_link = pmd_link;
540         data->mac_addrs = &internals->eth_addr;
541
542         eth_dev->dev_ops = &ops;
543
544         /* finally assign rx and tx ops */
545         if (packet_copy) {
546                 eth_dev->rx_pkt_burst = eth_null_copy_rx;
547                 eth_dev->tx_pkt_burst = eth_null_copy_tx;
548         } else {
549                 eth_dev->rx_pkt_burst = eth_null_rx;
550                 eth_dev->tx_pkt_burst = eth_null_tx;
551         }
552
553         rte_eth_dev_probing_finish(eth_dev);
554         return 0;
555 }
556
557 static inline int
558 get_packet_size_arg(const char *key __rte_unused,
559                 const char *value, void *extra_args)
560 {
561         const char *a = value;
562         unsigned *packet_size = extra_args;
563
564         if ((value == NULL) || (extra_args == NULL))
565                 return -EINVAL;
566
567         *packet_size = (unsigned)strtoul(a, NULL, 0);
568         if (*packet_size == UINT_MAX)
569                 return -1;
570
571         return 0;
572 }
573
574 static inline int
575 get_packet_copy_arg(const char *key __rte_unused,
576                 const char *value, void *extra_args)
577 {
578         const char *a = value;
579         unsigned *packet_copy = extra_args;
580
581         if ((value == NULL) || (extra_args == NULL))
582                 return -EINVAL;
583
584         *packet_copy = (unsigned)strtoul(a, NULL, 0);
585         if (*packet_copy == UINT_MAX)
586                 return -1;
587
588         return 0;
589 }
590
591 static int
592 rte_pmd_null_probe(struct rte_vdev_device *dev)
593 {
594         const char *name, *params;
595         unsigned packet_size = default_packet_size;
596         unsigned packet_copy = default_packet_copy;
597         struct rte_kvargs *kvlist = NULL;
598         struct rte_eth_dev *eth_dev;
599         int ret;
600
601         if (!dev)
602                 return -EINVAL;
603
604         name = rte_vdev_device_name(dev);
605         params = rte_vdev_device_args(dev);
606         PMD_LOG(INFO, "Initializing pmd_null for %s", name);
607
608         if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
609                 eth_dev = rte_eth_dev_attach_secondary(name);
610                 if (!eth_dev) {
611                         PMD_LOG(ERR, "Failed to probe %s", name);
612                         return -1;
613                 }
614                 /* TODO: request info from primary to set up Rx and Tx */
615                 eth_dev->dev_ops = &ops;
616                 eth_dev->device = &dev->device;
617                 rte_eth_dev_probing_finish(eth_dev);
618                 return 0;
619         }
620
621         if (params != NULL) {
622                 kvlist = rte_kvargs_parse(params, valid_arguments);
623                 if (kvlist == NULL)
624                         return -1;
625
626                 if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
627
628                         ret = rte_kvargs_process(kvlist,
629                                         ETH_NULL_PACKET_SIZE_ARG,
630                                         &get_packet_size_arg, &packet_size);
631                         if (ret < 0)
632                                 goto free_kvlist;
633                 }
634
635                 if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
636
637                         ret = rte_kvargs_process(kvlist,
638                                         ETH_NULL_PACKET_COPY_ARG,
639                                         &get_packet_copy_arg, &packet_copy);
640                         if (ret < 0)
641                                 goto free_kvlist;
642                 }
643         }
644
645         PMD_LOG(INFO, "Configure pmd_null: packet size is %d, "
646                         "packet copy is %s", packet_size,
647                         packet_copy ? "enabled" : "disabled");
648
649         ret = eth_dev_null_create(dev, packet_size, packet_copy);
650
651 free_kvlist:
652         if (kvlist)
653                 rte_kvargs_free(kvlist);
654         return ret;
655 }
656
657 static int
658 rte_pmd_null_remove(struct rte_vdev_device *dev)
659 {
660         struct rte_eth_dev *eth_dev = NULL;
661
662         if (!dev)
663                 return -EINVAL;
664
665         PMD_LOG(INFO, "Closing null ethdev on numa socket %u",
666                         rte_socket_id());
667
668         /* find the ethdev entry */
669         eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev));
670         if (eth_dev == NULL)
671                 return -1;
672
673         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
674                 /* mac_addrs must not be freed alone because part of dev_private */
675                 eth_dev->data->mac_addrs = NULL;
676
677         rte_eth_dev_release_port(eth_dev);
678
679         return 0;
680 }
681
682 static struct rte_vdev_driver pmd_null_drv = {
683         .probe = rte_pmd_null_probe,
684         .remove = rte_pmd_null_remove,
685 };
686
687 RTE_PMD_REGISTER_VDEV(net_null, pmd_null_drv);
688 RTE_PMD_REGISTER_ALIAS(net_null, eth_null);
689 RTE_PMD_REGISTER_PARAM_STRING(net_null,
690         "size=<int> "
691         "copy=<int>");
692
693 RTE_INIT(eth_null_init_log)
694 {
695         eth_null_logtype = rte_log_register("pmd.net.null");
696         if (eth_null_logtype >= 0)
697                 rte_log_set_level(eth_null_logtype, RTE_LOG_NOTICE);
698 }