netdev-dummy: Include all dummy classes in iterations.
[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     if (netdev->ifindex >= 0) {
331         smap_add_format(args, "ifindex", "%d", netdev->ifindex);
332     }
333     if (netdev->pstream) {
334         smap_add(args, "pstream", pstream_get_name(netdev->pstream));
335     }
336     return 0;
337 }
338
339 static int
340 netdev_dummy_set_config(struct netdev *netdev_, const struct smap *args)
341 {
342     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
343     const char *pstream;
344
345     ovs_mutex_lock(&netdev->mutex);
346     netdev->ifindex = smap_get_int(args, "ifindex", -EOPNOTSUPP);
347
348     pstream = smap_get(args, "pstream");
349     if (!pstream
350         || !netdev->pstream
351         || strcmp(pstream_get_name(netdev->pstream), pstream)) {
352         pstream_close(netdev->pstream);
353         netdev->pstream = NULL;
354
355         if (pstream) {
356             int error;
357
358             error = pstream_open(pstream, &netdev->pstream, DSCP_DEFAULT);
359             if (error) {
360                 VLOG_WARN("%s: open failed (%s)",
361                           pstream, ovs_strerror(error));
362             }
363         }
364     }
365     ovs_mutex_unlock(&netdev->mutex);
366
367     return 0;
368 }
369
370 static struct netdev_rx *
371 netdev_dummy_rx_alloc(void)
372 {
373     struct netdev_rx_dummy *rx = xzalloc(sizeof *rx);
374     return &rx->up;
375 }
376
377 static int
378 netdev_dummy_rx_construct(struct netdev_rx *rx_)
379 {
380     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
381     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
382
383     ovs_mutex_lock(&netdev->mutex);
384     list_push_back(&netdev->rxes, &rx->node);
385     list_init(&rx->recv_queue);
386     rx->recv_queue_len = 0;
387     ovs_mutex_unlock(&netdev->mutex);
388
389     return 0;
390 }
391
392 static void
393 netdev_dummy_rx_destruct(struct netdev_rx *rx_)
394 {
395     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
396     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
397
398     ovs_mutex_lock(&netdev->mutex);
399     list_remove(&rx->node);
400     ofpbuf_list_delete(&rx->recv_queue);
401     ovs_mutex_unlock(&netdev->mutex);
402 }
403
404 static void
405 netdev_dummy_rx_dealloc(struct netdev_rx *rx_)
406 {
407     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
408
409     free(rx);
410 }
411
412 static int
413 netdev_dummy_rx_recv(struct netdev_rx *rx_, void *buffer, size_t size)
414 {
415     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
416     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
417     struct ofpbuf *packet;
418     int retval;
419
420     ovs_mutex_lock(&netdev->mutex);
421     if (!list_is_empty(&rx->recv_queue)) {
422         packet = ofpbuf_from_list(list_pop_front(&rx->recv_queue));
423         rx->recv_queue_len--;
424     } else {
425         packet = NULL;
426     }
427     ovs_mutex_unlock(&netdev->mutex);
428
429     if (!packet) {
430         return -EAGAIN;
431     }
432
433     if (packet->size <= size) {
434         memcpy(buffer, packet->data, packet->size);
435         retval = packet->size;
436     } else {
437         retval = -EMSGSIZE;
438     }
439     ofpbuf_delete(packet);
440
441     return retval;
442 }
443
444 static void
445 netdev_dummy_rx_wait(struct netdev_rx *rx_)
446 {
447     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
448     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
449
450     ovs_mutex_lock(&netdev->mutex);
451     if (!list_is_empty(&rx->recv_queue)) {
452         poll_immediate_wake();
453     }
454     ovs_mutex_unlock(&netdev->mutex);
455 }
456
457 static int
458 netdev_dummy_rx_drain(struct netdev_rx *rx_)
459 {
460     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
461     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
462
463     ovs_mutex_lock(&netdev->mutex);
464     ofpbuf_list_delete(&rx->recv_queue);
465     rx->recv_queue_len = 0;
466     ovs_mutex_unlock(&netdev->mutex);
467
468     return 0;
469 }
470
471 static int
472 netdev_dummy_send(struct netdev *netdev, const void *buffer, size_t size)
473 {
474     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
475     size_t i;
476
477     if (size < ETH_HEADER_LEN) {
478         return EMSGSIZE;
479     } else {
480         const struct eth_header *eth = buffer;
481         int max_size;
482
483         max_size = dev->mtu + ETH_HEADER_LEN;
484         if (eth->eth_type == htons(ETH_TYPE_VLAN)) {
485             max_size += VLAN_HEADER_LEN;
486         }
487         if (size > max_size) {
488             return EMSGSIZE;
489         }
490     }
491
492     ovs_mutex_lock(&dev->mutex);
493     dev->stats.tx_packets++;
494     dev->stats.tx_bytes += size;
495
496     for (i = 0; i < dev->n_streams; i++) {
497         struct dummy_stream *s = &dev->streams[i];
498
499         if (list_size(&s->txq) < NETDEV_DUMMY_MAX_QUEUE) {
500             struct ofpbuf *b;
501
502             b = ofpbuf_clone_data_with_headroom(buffer, size, 2);
503             put_unaligned_be16(ofpbuf_push_uninit(b, 2), htons(size));
504             list_push_back(&s->txq, &b->list_node);
505         }
506     }
507     ovs_mutex_unlock(&dev->mutex);
508
509     return 0;
510 }
511
512 static int
513 netdev_dummy_set_etheraddr(struct netdev *netdev,
514                            const uint8_t mac[ETH_ADDR_LEN])
515 {
516     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
517
518     ovs_mutex_lock(&dev->mutex);
519     if (!eth_addr_equals(dev->hwaddr, mac)) {
520         memcpy(dev->hwaddr, mac, ETH_ADDR_LEN);
521         netdev_dummy_poll_notify(dev);
522     }
523     ovs_mutex_unlock(&dev->mutex);
524
525     return 0;
526 }
527
528 static int
529 netdev_dummy_get_etheraddr(const struct netdev *netdev,
530                            uint8_t mac[ETH_ADDR_LEN])
531 {
532     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
533
534     ovs_mutex_lock(&dev->mutex);
535     memcpy(mac, dev->hwaddr, ETH_ADDR_LEN);
536     ovs_mutex_unlock(&dev->mutex);
537
538     return 0;
539 }
540
541 static int
542 netdev_dummy_get_mtu(const struct netdev *netdev, int *mtup)
543 {
544     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
545
546     ovs_mutex_lock(&dev->mutex);
547     *mtup = dev->mtu;
548     ovs_mutex_unlock(&dev->mutex);
549
550     return 0;
551 }
552
553 static int
554 netdev_dummy_set_mtu(const struct netdev *netdev, int mtu)
555 {
556     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
557
558     ovs_mutex_lock(&dev->mutex);
559     dev->mtu = mtu;
560     ovs_mutex_unlock(&dev->mutex);
561
562     return 0;
563 }
564
565 static int
566 netdev_dummy_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
567 {
568     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
569
570     ovs_mutex_lock(&dev->mutex);
571     *stats = dev->stats;
572     ovs_mutex_unlock(&dev->mutex);
573
574     return 0;
575 }
576
577 static int
578 netdev_dummy_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
579 {
580     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
581
582     ovs_mutex_lock(&dev->mutex);
583     dev->stats = *stats;
584     ovs_mutex_unlock(&dev->mutex);
585
586     return 0;
587 }
588
589 static int
590 netdev_dummy_get_ifindex(const struct netdev *netdev)
591 {
592     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
593     int ifindex;
594
595     ovs_mutex_lock(&dev->mutex);
596     ifindex = dev->ifindex;
597     ovs_mutex_unlock(&dev->mutex);
598
599     return ifindex;
600 }
601
602 static int
603 netdev_dummy_update_flags__(struct netdev_dummy *netdev,
604                             enum netdev_flags off, enum netdev_flags on,
605                             enum netdev_flags *old_flagsp)
606     OVS_REQUIRES(netdev->mutex)
607 {
608     if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {
609         return EINVAL;
610     }
611
612     *old_flagsp = netdev->flags;
613     netdev->flags |= on;
614     netdev->flags &= ~off;
615     if (*old_flagsp != netdev->flags) {
616         netdev_dummy_poll_notify(netdev);
617     }
618
619     return 0;
620 }
621
622 static int
623 netdev_dummy_update_flags(struct netdev *netdev_,
624                           enum netdev_flags off, enum netdev_flags on,
625                           enum netdev_flags *old_flagsp)
626 {
627     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
628     int error;
629
630     ovs_mutex_lock(&netdev->mutex);
631     error = netdev_dummy_update_flags__(netdev, off, on, old_flagsp);
632     ovs_mutex_unlock(&netdev->mutex);
633
634     return error;
635 }
636
637 static unsigned int
638 netdev_dummy_change_seq(const struct netdev *netdev_)
639 {
640     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
641     unsigned int change_seq;
642
643     ovs_mutex_lock(&netdev->mutex);
644     change_seq = netdev->change_seq;
645     ovs_mutex_unlock(&netdev->mutex);
646
647     return change_seq;
648 }
649 \f
650 /* Helper functions. */
651
652 static void
653 netdev_dummy_poll_notify(struct netdev_dummy *dev)
654 {
655     dev->change_seq++;
656     if (!dev->change_seq) {
657         dev->change_seq++;
658     }
659 }
660
661 static const struct netdev_class dummy_class = {
662     "dummy",
663     NULL,                       /* init */
664     netdev_dummy_run,
665     netdev_dummy_wait,
666
667     netdev_dummy_alloc,
668     netdev_dummy_construct,
669     netdev_dummy_destruct,
670     netdev_dummy_dealloc,
671     netdev_dummy_get_config,
672     netdev_dummy_set_config,
673     NULL,                       /* get_tunnel_config */
674
675     netdev_dummy_send,          /* send */
676     NULL,                       /* send_wait */
677
678     netdev_dummy_set_etheraddr,
679     netdev_dummy_get_etheraddr,
680     netdev_dummy_get_mtu,
681     netdev_dummy_set_mtu,
682     netdev_dummy_get_ifindex,
683     NULL,                       /* get_carrier */
684     NULL,                       /* get_carrier_resets */
685     NULL,                       /* get_miimon */
686     netdev_dummy_get_stats,
687     netdev_dummy_set_stats,
688
689     NULL,                       /* get_features */
690     NULL,                       /* set_advertisements */
691
692     NULL,                       /* set_policing */
693     NULL,                       /* get_qos_types */
694     NULL,                       /* get_qos_capabilities */
695     NULL,                       /* get_qos */
696     NULL,                       /* set_qos */
697     NULL,                       /* get_queue */
698     NULL,                       /* set_queue */
699     NULL,                       /* delete_queue */
700     NULL,                       /* get_queue_stats */
701     NULL,                       /* dump_queues */
702     NULL,                       /* dump_queue_stats */
703
704     NULL,                       /* get_in4 */
705     NULL,                       /* set_in4 */
706     NULL,                       /* get_in6 */
707     NULL,                       /* add_router */
708     NULL,                       /* get_next_hop */
709     NULL,                       /* get_status */
710     NULL,                       /* arp_lookup */
711
712     netdev_dummy_update_flags,
713
714     netdev_dummy_change_seq,
715
716     netdev_dummy_rx_alloc,
717     netdev_dummy_rx_construct,
718     netdev_dummy_rx_destruct,
719     netdev_dummy_rx_dealloc,
720     netdev_dummy_rx_recv,
721     netdev_dummy_rx_wait,
722     netdev_dummy_rx_drain,
723 };
724
725 static struct ofpbuf *
726 eth_from_packet_or_flow(const char *s)
727 {
728     enum odp_key_fitness fitness;
729     struct ofpbuf *packet;
730     struct ofpbuf odp_key;
731     struct flow flow;
732     int error;
733
734     if (!eth_from_hex(s, &packet)) {
735         return packet;
736     }
737
738     /* Convert string to datapath key.
739      *
740      * It would actually be nicer to parse an OpenFlow-like flow key here, but
741      * the code for that currently calls exit() on parse error.  We have to
742      * settle for parsing a datapath key for now.
743      */
744     ofpbuf_init(&odp_key, 0);
745     error = odp_flow_from_string(s, NULL, &odp_key, NULL);
746     if (error) {
747         ofpbuf_uninit(&odp_key);
748         return NULL;
749     }
750
751     /* Convert odp_key to flow. */
752     fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
753     if (fitness == ODP_FIT_ERROR) {
754         ofpbuf_uninit(&odp_key);
755         return NULL;
756     }
757
758     packet = ofpbuf_new(0);
759     flow_compose(packet, &flow);
760
761     ofpbuf_uninit(&odp_key);
762     return packet;
763 }
764
765 static void
766 netdev_dummy_queue_packet__(struct netdev_rx_dummy *rx, struct ofpbuf *packet)
767 {
768     list_push_back(&rx->recv_queue, &packet->list_node);
769     rx->recv_queue_len++;
770 }
771
772 static void
773 netdev_dummy_queue_packet(struct netdev_dummy *dummy, struct ofpbuf *packet)
774 {
775     struct netdev_rx_dummy *rx, *prev;
776
777     prev = NULL;
778     LIST_FOR_EACH (rx, node, &dummy->rxes) {
779         if (rx->recv_queue_len < NETDEV_DUMMY_MAX_QUEUE) {
780             if (prev) {
781                 netdev_dummy_queue_packet__(prev, ofpbuf_clone(packet));
782             }
783             prev = rx;
784         }
785     }
786     if (prev) {
787         netdev_dummy_queue_packet__(prev, packet);
788     } else {
789         ofpbuf_delete(packet);
790     }
791 }
792
793 static void
794 netdev_dummy_receive(struct unixctl_conn *conn,
795                      int argc, const char *argv[], void *aux OVS_UNUSED)
796 {
797     struct netdev_dummy *dummy_dev;
798     struct netdev *netdev;
799     int i;
800
801     netdev = netdev_from_name(argv[1]);
802     if (!netdev || !is_dummy_class(netdev->netdev_class)) {
803         unixctl_command_reply_error(conn, "no such dummy netdev");
804         goto exit;
805     }
806     dummy_dev = netdev_dummy_cast(netdev);
807
808     for (i = 2; i < argc; i++) {
809         struct ofpbuf *packet;
810
811         packet = eth_from_packet_or_flow(argv[i]);
812         if (!packet) {
813             unixctl_command_reply_error(conn, "bad packet syntax");
814             goto exit;
815         }
816
817         ovs_mutex_lock(&dummy_dev->mutex);
818         dummy_dev->stats.rx_packets++;
819         dummy_dev->stats.rx_bytes += packet->size;
820         netdev_dummy_queue_packet(dummy_dev, packet);
821         ovs_mutex_unlock(&dummy_dev->mutex);
822     }
823
824     unixctl_command_reply(conn, NULL);
825
826 exit:
827     netdev_close(netdev);
828 }
829
830 static void
831 netdev_dummy_set_admin_state__(struct netdev_dummy *dev, bool admin_state)
832     OVS_REQUIRES(dev->mutex)
833 {
834     enum netdev_flags old_flags;
835
836     if (admin_state) {
837         netdev_dummy_update_flags__(dev, 0, NETDEV_UP, &old_flags);
838     } else {
839         netdev_dummy_update_flags__(dev, NETDEV_UP, 0, &old_flags);
840     }
841 }
842
843 static void
844 netdev_dummy_set_admin_state(struct unixctl_conn *conn, int argc,
845                              const char *argv[], void *aux OVS_UNUSED)
846 {
847     bool up;
848
849     if (!strcasecmp(argv[argc - 1], "up")) {
850         up = true;
851     } else if ( !strcasecmp(argv[argc - 1], "down")) {
852         up = false;
853     } else {
854         unixctl_command_reply_error(conn, "Invalid Admin State");
855         return;
856     }
857
858     if (argc > 2) {
859         struct netdev *netdev = netdev_from_name(argv[1]);
860         if (netdev && is_dummy_class(netdev->netdev_class)) {
861             struct netdev_dummy *dummy_dev = netdev_dummy_cast(netdev);
862
863             ovs_mutex_lock(&dummy_dev->mutex);
864             netdev_dummy_set_admin_state__(dummy_dev, up);
865             ovs_mutex_unlock(&dummy_dev->mutex);
866
867             netdev_close(netdev);
868         } else {
869             unixctl_command_reply_error(conn, "Unknown Dummy Interface");
870             netdev_close(netdev);
871             return;
872         }
873     } else {
874         struct netdev_dummy *netdev;
875
876         ovs_mutex_lock(&dummy_list_mutex);
877         LIST_FOR_EACH (netdev, list_node, &dummy_list) {
878             ovs_mutex_lock(&netdev->mutex);
879             netdev_dummy_set_admin_state__(netdev, up);
880             ovs_mutex_unlock(&netdev->mutex);
881         }
882         ovs_mutex_unlock(&dummy_list_mutex);
883     }
884     unixctl_command_reply(conn, "OK");
885 }
886
887 void
888 netdev_dummy_register(bool override)
889 {
890     unixctl_command_register("netdev-dummy/receive", "NAME PACKET|FLOW...",
891                              2, INT_MAX, netdev_dummy_receive, NULL);
892     unixctl_command_register("netdev-dummy/set-admin-state",
893                              "[netdev] up|down", 1, 2,
894                              netdev_dummy_set_admin_state, NULL);
895
896     if (override) {
897         struct sset types;
898         const char *type;
899
900         sset_init(&types);
901         netdev_enumerate_types(&types);
902         SSET_FOR_EACH (type, &types) {
903             if (!netdev_unregister_provider(type)) {
904                 struct netdev_class *class;
905                 int error;
906
907                 class = xmemdup(&dummy_class, sizeof dummy_class);
908                 class->type = xstrdup(type);
909                 error = netdev_register_provider(class);
910                 if (error) {
911                     VLOG_ERR("%s: failed to register netdev provider (%s)",
912                              type, ovs_strerror(error));
913                     free(CONST_CAST(char *, class->type));
914                     free(class);
915                 }
916             }
917         }
918         sset_destroy(&types);
919     }
920     netdev_register_provider(&dummy_class);
921
922     netdev_vport_tunnel_register();
923 }