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