netdev: Make netdev access thread-safe.
[cascardo/ovs.git] / lib / netdev-dummy.c
1 /*
2  * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include "dummy.h"
20
21 #include <errno.h>
22
23 #include "flow.h"
24 #include "list.h"
25 #include "netdev-provider.h"
26 #include "netdev-vport.h"
27 #include "odp-util.h"
28 #include "ofp-print.h"
29 #include "ofpbuf.h"
30 #include "packets.h"
31 #include "poll-loop.h"
32 #include "shash.h"
33 #include "sset.h"
34 #include "stream.h"
35 #include "unaligned.h"
36 #include "unixctl.h"
37 #include "vlog.h"
38
39 VLOG_DEFINE_THIS_MODULE(netdev_dummy);
40
41 struct dummy_stream {
42     struct stream *stream;
43     struct ofpbuf rxbuf;
44     struct list txq;
45 };
46
47 struct netdev_dummy {
48     struct netdev up;
49
50     /* Protects all members below. */
51     struct ovs_mutex mutex;
52
53     uint8_t hwaddr[ETH_ADDR_LEN];
54     int mtu;
55     struct netdev_stats stats;
56     enum netdev_flags flags;
57     unsigned int change_seq;
58     int ifindex;
59
60     struct pstream *pstream;
61     struct dummy_stream *streams;
62     size_t n_streams;
63
64     struct list rxes;           /* List of child "netdev_rx_dummy"s. */
65 };
66
67 static const struct netdev_class dummy_class;
68
69 /* Max 'recv_queue_len' in struct netdev_dummy. */
70 #define NETDEV_DUMMY_MAX_QUEUE 100
71
72 struct netdev_rx_dummy {
73     struct netdev_rx up;
74     struct list node;           /* In netdev_dummy's "rxes" list. */
75     struct list recv_queue;
76     int recv_queue_len;         /* list_size(&recv_queue). */
77     bool listening;
78 };
79
80 static unixctl_cb_func netdev_dummy_set_admin_state;
81 static int netdev_dummy_construct(struct netdev *);
82 static void netdev_dummy_poll_notify(struct netdev_dummy *netdev)
83     OVS_REQUIRES(netdev->mutex);
84 static void netdev_dummy_queue_packet(struct netdev_dummy *, struct ofpbuf *);
85
86 static void dummy_stream_close(struct dummy_stream *);
87
88 static bool
89 is_dummy_class(const struct netdev_class *class)
90 {
91     return class->construct == netdev_dummy_construct;
92 }
93
94 static struct netdev_dummy *
95 netdev_dummy_cast(const struct netdev *netdev)
96 {
97     ovs_assert(is_dummy_class(netdev_get_class(netdev)));
98     return CONTAINER_OF(netdev, struct netdev_dummy, up);
99 }
100
101 static struct netdev_rx_dummy *
102 netdev_rx_dummy_cast(const struct netdev_rx *rx)
103 {
104     ovs_assert(is_dummy_class(netdev_get_class(rx->netdev)));
105     return CONTAINER_OF(rx, struct netdev_rx_dummy, up);
106 }
107
108 static void
109 netdev_dummy_run(void)
110 {
111     struct shash dummy_netdevs;
112     struct shash_node *node;
113
114     shash_init(&dummy_netdevs);
115     netdev_get_devices(&dummy_class, &dummy_netdevs);
116     SHASH_FOR_EACH (node, &dummy_netdevs) {
117         struct netdev_dummy *dev = node->data;
118         size_t i;
119
120         ovs_mutex_lock(&dev->mutex);
121
122         if (dev->pstream) {
123             struct stream *new_stream;
124             int error;
125
126             error = pstream_accept(dev->pstream, &new_stream);
127             if (!error) {
128                 struct dummy_stream *s;
129
130                 dev->streams = xrealloc(dev->streams,
131                                         ((dev->n_streams + 1)
132                                          * sizeof *dev->streams));
133                 s = &dev->streams[dev->n_streams++];
134                 s->stream = new_stream;
135                 ofpbuf_init(&s->rxbuf, 2048);
136                 list_init(&s->txq);
137             } else if (error != EAGAIN) {
138                 VLOG_WARN("%s: accept failed (%s)",
139                           pstream_get_name(dev->pstream), ovs_strerror(error));
140                 pstream_close(dev->pstream);
141                 dev->pstream = NULL;
142             }
143         }
144
145         for (i = 0; i < dev->n_streams; i++) {
146             struct dummy_stream *s = &dev->streams[i];
147             int error = 0;
148             size_t n;
149
150             stream_run(s->stream);
151
152             if (!list_is_empty(&s->txq)) {
153                 struct ofpbuf *txbuf;
154                 int retval;
155
156                 txbuf = ofpbuf_from_list(list_front(&s->txq));
157                 retval = stream_send(s->stream, txbuf->data, txbuf->size);
158                 if (retval > 0) {
159                     ofpbuf_pull(txbuf, retval);
160                     if (!txbuf->size) {
161                         list_remove(&txbuf->list_node);
162                         ofpbuf_delete(txbuf);
163                     }
164                 } else if (retval != -EAGAIN) {
165                     error = -retval;
166                 }
167             }
168
169             if (!error) {
170                 if (s->rxbuf.size < 2) {
171                     n = 2 - s->rxbuf.size;
172                 } else {
173                     uint16_t frame_len;
174
175                     frame_len = ntohs(get_unaligned_be16(s->rxbuf.data));
176                     if (frame_len < ETH_HEADER_LEN) {
177                         error = EPROTO;
178                         n = 0;
179                     } else {
180                         n = (2 + frame_len) - s->rxbuf.size;
181                     }
182                 }
183             }
184             if (!error) {
185                 int retval;
186
187                 ofpbuf_prealloc_tailroom(&s->rxbuf, n);
188                 retval = stream_recv(s->stream, ofpbuf_tail(&s->rxbuf), n);
189                 if (retval > 0) {
190                     s->rxbuf.size += retval;
191                     if (retval == n && s->rxbuf.size > 2) {
192                         ofpbuf_pull(&s->rxbuf, 2);
193                         netdev_dummy_queue_packet(dev,
194                                                   ofpbuf_clone(&s->rxbuf));
195                         ofpbuf_clear(&s->rxbuf);
196                     }
197                 } else if (retval != -EAGAIN) {
198                     error = (retval < 0 ? -retval
199                              : s->rxbuf.size ? EPROTO
200                              : EOF);
201                 }
202             }
203
204             if (error) {
205                 VLOG_DBG("%s: closing connection (%s)",
206                          stream_get_name(s->stream),
207                          ovs_retval_to_string(error));
208                 dummy_stream_close(&dev->streams[i]);
209                 dev->streams[i] = dev->streams[--dev->n_streams];
210             }
211         }
212
213         ovs_mutex_unlock(&dev->mutex);
214         netdev_close(&dev->up);
215     }
216     shash_destroy(&dummy_netdevs);
217 }
218
219 static void
220 dummy_stream_close(struct dummy_stream *s)
221 {
222     stream_close(s->stream);
223     ofpbuf_uninit(&s->rxbuf);
224     ofpbuf_list_delete(&s->txq);
225 }
226
227 static void
228 netdev_dummy_wait(void)
229 {
230     struct shash dummy_netdevs;
231     struct shash_node *node;
232
233     shash_init(&dummy_netdevs);
234     netdev_get_devices(&dummy_class, &dummy_netdevs);
235     SHASH_FOR_EACH (node, &dummy_netdevs) {
236         struct netdev_dummy *dev = node->data;
237         size_t i;
238
239         ovs_mutex_lock(&dev->mutex);
240         if (dev->pstream) {
241             pstream_wait(dev->pstream);
242         }
243         for (i = 0; i < dev->n_streams; i++) {
244             struct dummy_stream *s = &dev->streams[i];
245
246             stream_run_wait(s->stream);
247             if (!list_is_empty(&s->txq)) {
248                 stream_send_wait(s->stream);
249             }
250             stream_recv_wait(s->stream);
251         }
252         ovs_mutex_unlock(&dev->mutex);
253         netdev_close(&dev->up);
254     }
255     shash_destroy(&dummy_netdevs);
256 }
257
258 static struct netdev *
259 netdev_dummy_alloc(void)
260 {
261     struct netdev_dummy *netdev = xzalloc(sizeof *netdev);
262     return &netdev->up;
263 }
264
265 static int
266 netdev_dummy_construct(struct netdev *netdev_)
267 {
268     static atomic_uint next_n = ATOMIC_VAR_INIT(0xaa550000);
269     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
270     unsigned int n;
271
272     atomic_add(&next_n, 1, &n);
273
274     ovs_mutex_init(&netdev->mutex, PTHREAD_MUTEX_NORMAL);
275     netdev->hwaddr[0] = 0xaa;
276     netdev->hwaddr[1] = 0x55;
277     netdev->hwaddr[2] = n >> 24;
278     netdev->hwaddr[3] = n >> 16;
279     netdev->hwaddr[4] = n >> 8;
280     netdev->hwaddr[5] = n;
281     netdev->mtu = 1500;
282     netdev->flags = 0;
283     netdev->change_seq = 1;
284     netdev->ifindex = -EOPNOTSUPP;
285
286     netdev->pstream = NULL;
287     netdev->streams = NULL;
288     netdev->n_streams = 0;
289
290     list_init(&netdev->rxes);
291
292     return 0;
293 }
294
295 static void
296 netdev_dummy_destruct(struct netdev *netdev_)
297 {
298     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
299     size_t i;
300
301     pstream_close(netdev->pstream);
302     for (i = 0; i < netdev->n_streams; i++) {
303         dummy_stream_close(&netdev->streams[i]);
304     }
305     free(netdev->streams);
306     ovs_mutex_destroy(&netdev->mutex);
307 }
308
309 static void
310 netdev_dummy_dealloc(struct netdev *netdev_)
311 {
312     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
313
314     free(netdev);
315 }
316
317 static int
318 netdev_dummy_get_config(const struct netdev *netdev_, struct smap *args)
319 {
320     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
321
322     if (netdev->ifindex >= 0) {
323         smap_add_format(args, "ifindex", "%d", netdev->ifindex);
324     }
325     if (netdev->pstream) {
326         smap_add(args, "pstream", pstream_get_name(netdev->pstream));
327     }
328     return 0;
329 }
330
331 static int
332 netdev_dummy_set_config(struct netdev *netdev_, const struct smap *args)
333 {
334     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
335     const char *pstream;
336
337     ovs_mutex_lock(&netdev->mutex);
338     netdev->ifindex = smap_get_int(args, "ifindex", -EOPNOTSUPP);
339
340     pstream = smap_get(args, "pstream");
341     if (!pstream
342         || !netdev->pstream
343         || strcmp(pstream_get_name(netdev->pstream), pstream)) {
344         pstream_close(netdev->pstream);
345         netdev->pstream = NULL;
346
347         if (pstream) {
348             int error;
349
350             error = pstream_open(pstream, &netdev->pstream, DSCP_DEFAULT);
351             if (error) {
352                 VLOG_WARN("%s: open failed (%s)",
353                           pstream, ovs_strerror(error));
354             }
355         }
356     }
357     ovs_mutex_unlock(&netdev->mutex);
358
359     return 0;
360 }
361
362 static struct netdev_rx *
363 netdev_dummy_rx_alloc(void)
364 {
365     struct netdev_rx_dummy *rx = xzalloc(sizeof *rx);
366     return &rx->up;
367 }
368
369 static int
370 netdev_dummy_rx_construct(struct netdev_rx *rx_)
371 {
372     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
373     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
374
375     ovs_mutex_lock(&netdev->mutex);
376     list_push_back(&netdev->rxes, &rx->node);
377     list_init(&rx->recv_queue);
378     rx->recv_queue_len = 0;
379     ovs_mutex_unlock(&netdev->mutex);
380
381     return 0;
382 }
383
384 static void
385 netdev_dummy_rx_destruct(struct netdev_rx *rx_)
386 {
387     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
388     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
389
390     ovs_mutex_lock(&netdev->mutex);
391     list_remove(&rx->node);
392     ofpbuf_list_delete(&rx->recv_queue);
393     ovs_mutex_unlock(&netdev->mutex);
394 }
395
396 static void
397 netdev_dummy_rx_dealloc(struct netdev_rx *rx_)
398 {
399     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
400
401     free(rx);
402 }
403
404 static int
405 netdev_dummy_rx_recv(struct netdev_rx *rx_, void *buffer, size_t size)
406 {
407     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
408     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
409     struct ofpbuf *packet;
410     int retval;
411
412     ovs_mutex_lock(&netdev->mutex);
413     if (!list_is_empty(&rx->recv_queue)) {
414         packet = ofpbuf_from_list(list_pop_front(&rx->recv_queue));
415         rx->recv_queue_len--;
416     } else {
417         packet = NULL;
418     }
419     ovs_mutex_unlock(&netdev->mutex);
420
421     if (!packet) {
422         return -EAGAIN;
423     }
424
425     if (packet->size <= size) {
426         memcpy(buffer, packet->data, packet->size);
427         retval = packet->size;
428     } else {
429         retval = -EMSGSIZE;
430     }
431     ofpbuf_delete(packet);
432
433     return retval;
434 }
435
436 static void
437 netdev_dummy_rx_wait(struct netdev_rx *rx_)
438 {
439     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
440     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
441
442     ovs_mutex_lock(&netdev->mutex);
443     if (!list_is_empty(&rx->recv_queue)) {
444         poll_immediate_wake();
445     }
446     ovs_mutex_unlock(&netdev->mutex);
447 }
448
449 static int
450 netdev_dummy_rx_drain(struct netdev_rx *rx_)
451 {
452     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
453     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
454
455     ovs_mutex_lock(&netdev->mutex);
456     ofpbuf_list_delete(&rx->recv_queue);
457     rx->recv_queue_len = 0;
458     ovs_mutex_unlock(&netdev->mutex);
459
460     return 0;
461 }
462
463 static int
464 netdev_dummy_send(struct netdev *netdev, const void *buffer, size_t size)
465 {
466     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
467     size_t i;
468
469     if (size < ETH_HEADER_LEN) {
470         return EMSGSIZE;
471     } else {
472         const struct eth_header *eth = buffer;
473         int max_size;
474
475         max_size = dev->mtu + ETH_HEADER_LEN;
476         if (eth->eth_type == htons(ETH_TYPE_VLAN)) {
477             max_size += VLAN_HEADER_LEN;
478         }
479         if (size > max_size) {
480             return EMSGSIZE;
481         }
482     }
483
484     ovs_mutex_lock(&dev->mutex);
485     dev->stats.tx_packets++;
486     dev->stats.tx_bytes += size;
487
488     for (i = 0; i < dev->n_streams; i++) {
489         struct dummy_stream *s = &dev->streams[i];
490
491         if (list_size(&s->txq) < NETDEV_DUMMY_MAX_QUEUE) {
492             struct ofpbuf *b;
493
494             b = ofpbuf_clone_data_with_headroom(buffer, size, 2);
495             put_unaligned_be16(ofpbuf_push_uninit(b, 2), htons(size));
496             list_push_back(&s->txq, &b->list_node);
497         }
498     }
499     ovs_mutex_unlock(&dev->mutex);
500
501     return 0;
502 }
503
504 static int
505 netdev_dummy_set_etheraddr(struct netdev *netdev,
506                            const uint8_t mac[ETH_ADDR_LEN])
507 {
508     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
509
510     ovs_mutex_lock(&dev->mutex);
511     if (!eth_addr_equals(dev->hwaddr, mac)) {
512         memcpy(dev->hwaddr, mac, ETH_ADDR_LEN);
513         netdev_dummy_poll_notify(dev);
514     }
515     ovs_mutex_unlock(&dev->mutex);
516
517     return 0;
518 }
519
520 static int
521 netdev_dummy_get_etheraddr(const struct netdev *netdev,
522                            uint8_t mac[ETH_ADDR_LEN])
523 {
524     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
525
526     ovs_mutex_lock(&dev->mutex);
527     memcpy(mac, dev->hwaddr, ETH_ADDR_LEN);
528     ovs_mutex_unlock(&dev->mutex);
529
530     return 0;
531 }
532
533 static int
534 netdev_dummy_get_mtu(const struct netdev *netdev, int *mtup)
535 {
536     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
537
538     ovs_mutex_lock(&dev->mutex);
539     *mtup = dev->mtu;
540     ovs_mutex_unlock(&dev->mutex);
541
542     return 0;
543 }
544
545 static int
546 netdev_dummy_set_mtu(const struct netdev *netdev, int mtu)
547 {
548     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
549
550     ovs_mutex_lock(&dev->mutex);
551     dev->mtu = mtu;
552     ovs_mutex_unlock(&dev->mutex);
553
554     return 0;
555 }
556
557 static int
558 netdev_dummy_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
559 {
560     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
561
562     ovs_mutex_lock(&dev->mutex);
563     *stats = dev->stats;
564     ovs_mutex_unlock(&dev->mutex);
565
566     return 0;
567 }
568
569 static int
570 netdev_dummy_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
571 {
572     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
573
574     ovs_mutex_lock(&dev->mutex);
575     dev->stats = *stats;
576     ovs_mutex_unlock(&dev->mutex);
577
578     return 0;
579 }
580
581 static int
582 netdev_dummy_get_ifindex(const struct netdev *netdev)
583 {
584     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
585     int ifindex;
586
587     ovs_mutex_lock(&dev->mutex);
588     ifindex = dev->ifindex;
589     ovs_mutex_unlock(&dev->mutex);
590
591     return ifindex;
592 }
593
594 static int
595 netdev_dummy_update_flags__(struct netdev_dummy *netdev,
596                             enum netdev_flags off, enum netdev_flags on,
597                             enum netdev_flags *old_flagsp)
598     OVS_REQUIRES(netdev->mutex)
599 {
600     if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {
601         return EINVAL;
602     }
603
604     *old_flagsp = netdev->flags;
605     netdev->flags |= on;
606     netdev->flags &= ~off;
607     if (*old_flagsp != netdev->flags) {
608         netdev_dummy_poll_notify(netdev);
609     }
610
611     return 0;
612 }
613
614 static int
615 netdev_dummy_update_flags(struct netdev *netdev_,
616                           enum netdev_flags off, enum netdev_flags on,
617                           enum netdev_flags *old_flagsp)
618 {
619     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
620     int error;
621
622     ovs_mutex_lock(&netdev->mutex);
623     error = netdev_dummy_update_flags__(netdev, off, on, old_flagsp);
624     ovs_mutex_unlock(&netdev->mutex);
625
626     return error;
627 }
628
629 static unsigned int
630 netdev_dummy_change_seq(const struct netdev *netdev_)
631 {
632     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
633     unsigned int change_seq;
634
635     ovs_mutex_lock(&netdev->mutex);
636     change_seq = netdev->change_seq;
637     ovs_mutex_unlock(&netdev->mutex);
638
639     return change_seq;
640 }
641 \f
642 /* Helper functions. */
643
644 static void
645 netdev_dummy_poll_notify(struct netdev_dummy *dev)
646 {
647     dev->change_seq++;
648     if (!dev->change_seq) {
649         dev->change_seq++;
650     }
651 }
652
653 static const struct netdev_class dummy_class = {
654     "dummy",
655     NULL,                       /* init */
656     netdev_dummy_run,
657     netdev_dummy_wait,
658
659     netdev_dummy_alloc,
660     netdev_dummy_construct,
661     netdev_dummy_destruct,
662     netdev_dummy_dealloc,
663     netdev_dummy_get_config,
664     netdev_dummy_set_config,
665     NULL,                       /* get_tunnel_config */
666
667     netdev_dummy_send,          /* send */
668     NULL,                       /* send_wait */
669
670     netdev_dummy_set_etheraddr,
671     netdev_dummy_get_etheraddr,
672     netdev_dummy_get_mtu,
673     netdev_dummy_set_mtu,
674     netdev_dummy_get_ifindex,
675     NULL,                       /* get_carrier */
676     NULL,                       /* get_carrier_resets */
677     NULL,                       /* get_miimon */
678     netdev_dummy_get_stats,
679     netdev_dummy_set_stats,
680
681     NULL,                       /* get_features */
682     NULL,                       /* set_advertisements */
683
684     NULL,                       /* set_policing */
685     NULL,                       /* get_qos_types */
686     NULL,                       /* get_qos_capabilities */
687     NULL,                       /* get_qos */
688     NULL,                       /* set_qos */
689     NULL,                       /* get_queue */
690     NULL,                       /* set_queue */
691     NULL,                       /* delete_queue */
692     NULL,                       /* get_queue_stats */
693     NULL,                       /* dump_queues */
694     NULL,                       /* dump_queue_stats */
695
696     NULL,                       /* get_in4 */
697     NULL,                       /* set_in4 */
698     NULL,                       /* get_in6 */
699     NULL,                       /* add_router */
700     NULL,                       /* get_next_hop */
701     NULL,                       /* get_status */
702     NULL,                       /* arp_lookup */
703
704     netdev_dummy_update_flags,
705
706     netdev_dummy_change_seq,
707
708     netdev_dummy_rx_alloc,
709     netdev_dummy_rx_construct,
710     netdev_dummy_rx_destruct,
711     netdev_dummy_rx_dealloc,
712     netdev_dummy_rx_recv,
713     netdev_dummy_rx_wait,
714     netdev_dummy_rx_drain,
715 };
716
717 static struct ofpbuf *
718 eth_from_packet_or_flow(const char *s)
719 {
720     enum odp_key_fitness fitness;
721     struct ofpbuf *packet;
722     struct ofpbuf odp_key;
723     struct flow flow;
724     int error;
725
726     if (!eth_from_hex(s, &packet)) {
727         return packet;
728     }
729
730     /* Convert string to datapath key.
731      *
732      * It would actually be nicer to parse an OpenFlow-like flow key here, but
733      * the code for that currently calls exit() on parse error.  We have to
734      * settle for parsing a datapath key for now.
735      */
736     ofpbuf_init(&odp_key, 0);
737     error = odp_flow_from_string(s, NULL, &odp_key, NULL);
738     if (error) {
739         ofpbuf_uninit(&odp_key);
740         return NULL;
741     }
742
743     /* Convert odp_key to flow. */
744     fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
745     if (fitness == ODP_FIT_ERROR) {
746         ofpbuf_uninit(&odp_key);
747         return NULL;
748     }
749
750     packet = ofpbuf_new(0);
751     flow_compose(packet, &flow);
752
753     ofpbuf_uninit(&odp_key);
754     return packet;
755 }
756
757 static void
758 netdev_dummy_queue_packet__(struct netdev_rx_dummy *rx, struct ofpbuf *packet)
759 {
760     list_push_back(&rx->recv_queue, &packet->list_node);
761     rx->recv_queue_len++;
762 }
763
764 static void
765 netdev_dummy_queue_packet(struct netdev_dummy *dummy, struct ofpbuf *packet)
766 {
767     struct netdev_rx_dummy *rx, *prev;
768
769     prev = NULL;
770     LIST_FOR_EACH (rx, node, &dummy->rxes) {
771         if (rx->recv_queue_len < NETDEV_DUMMY_MAX_QUEUE) {
772             if (prev) {
773                 netdev_dummy_queue_packet__(prev, ofpbuf_clone(packet));
774             }
775             prev = rx;
776         }
777     }
778     if (prev) {
779         netdev_dummy_queue_packet__(prev, packet);
780     } else {
781         ofpbuf_delete(packet);
782     }
783 }
784
785 static void
786 netdev_dummy_receive(struct unixctl_conn *conn,
787                      int argc, const char *argv[], void *aux OVS_UNUSED)
788 {
789     struct netdev_dummy *dummy_dev;
790     struct netdev *netdev;
791     int i;
792
793     netdev = netdev_from_name(argv[1]);
794     if (!netdev || !is_dummy_class(netdev->netdev_class)) {
795         unixctl_command_reply_error(conn, "no such dummy netdev");
796         goto exit;
797     }
798     dummy_dev = netdev_dummy_cast(netdev);
799
800     for (i = 2; i < argc; i++) {
801         struct ofpbuf *packet;
802
803         packet = eth_from_packet_or_flow(argv[i]);
804         if (!packet) {
805             unixctl_command_reply_error(conn, "bad packet syntax");
806             goto exit;
807         }
808
809         ovs_mutex_lock(&dummy_dev->mutex);
810         dummy_dev->stats.rx_packets++;
811         dummy_dev->stats.rx_bytes += packet->size;
812         netdev_dummy_queue_packet(dummy_dev, packet);
813         ovs_mutex_unlock(&dummy_dev->mutex);
814     }
815
816     unixctl_command_reply(conn, NULL);
817
818 exit:
819     netdev_close(netdev);
820 }
821
822 static void
823 netdev_dummy_set_admin_state__(struct netdev_dummy *dev, bool admin_state)
824     OVS_REQUIRES(dev->mutex)
825 {
826     enum netdev_flags old_flags;
827
828     if (admin_state) {
829         netdev_dummy_update_flags__(dev, 0, NETDEV_UP, &old_flags);
830     } else {
831         netdev_dummy_update_flags__(dev, NETDEV_UP, 0, &old_flags);
832     }
833 }
834
835 static void
836 netdev_dummy_set_admin_state(struct unixctl_conn *conn, int argc,
837                              const char *argv[], void *aux OVS_UNUSED)
838 {
839     bool up;
840
841     if (!strcasecmp(argv[argc - 1], "up")) {
842         up = true;
843     } else if ( !strcasecmp(argv[argc - 1], "down")) {
844         up = false;
845     } else {
846         unixctl_command_reply_error(conn, "Invalid Admin State");
847         return;
848     }
849
850     if (argc > 2) {
851         struct netdev *netdev = netdev_from_name(argv[1]);
852         if (netdev && is_dummy_class(netdev->netdev_class)) {
853             struct netdev_dummy *dummy_dev = netdev_dummy_cast(netdev);
854
855             ovs_mutex_lock(&dummy_dev->mutex);
856             netdev_dummy_set_admin_state__(dummy_dev, up);
857             ovs_mutex_unlock(&dummy_dev->mutex);
858
859             netdev_close(netdev);
860         } else {
861             unixctl_command_reply_error(conn, "Unknown Dummy Interface");
862             netdev_close(netdev);
863             return;
864         }
865     } else {
866         struct shash dummy_netdevs;
867         struct shash_node *node;
868
869         shash_init(&dummy_netdevs);
870         netdev_get_devices(&dummy_class, &dummy_netdevs);
871         SHASH_FOR_EACH (node, &dummy_netdevs) {
872             struct netdev *netdev_ = node->data;
873             struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
874
875             ovs_mutex_lock(&netdev->mutex);
876             netdev_dummy_set_admin_state__(netdev, up);
877             ovs_mutex_unlock(&netdev->mutex);
878
879             netdev_close(netdev_);
880         }
881         shash_destroy(&dummy_netdevs);
882     }
883     unixctl_command_reply(conn, "OK");
884 }
885
886 void
887 netdev_dummy_register(bool override)
888 {
889     unixctl_command_register("netdev-dummy/receive", "NAME PACKET|FLOW...",
890                              2, INT_MAX, netdev_dummy_receive, NULL);
891     unixctl_command_register("netdev-dummy/set-admin-state",
892                              "[netdev] up|down", 1, 2,
893                              netdev_dummy_set_admin_state, NULL);
894
895     if (override) {
896         struct sset types;
897         const char *type;
898
899         sset_init(&types);
900         netdev_enumerate_types(&types);
901         SSET_FOR_EACH (type, &types) {
902             if (!netdev_unregister_provider(type)) {
903                 struct netdev_class *class;
904                 int error;
905
906                 class = xmemdup(&dummy_class, sizeof dummy_class);
907                 class->type = xstrdup(type);
908                 error = netdev_register_provider(class);
909                 if (error) {
910                     VLOG_ERR("%s: failed to register netdev provider (%s)",
911                              type, ovs_strerror(error));
912                     free(CONST_CAST(char *, class->type));
913                     free(class);
914                 }
915             }
916         }
917         sset_destroy(&types);
918     }
919     netdev_register_provider(&dummy_class);
920
921     netdev_vport_tunnel_register();
922 }