2 * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include "dpif-netdev.h"
24 #include "dynamic-string.h"
27 #include "netdev-provider.h"
28 #include "netdev-vport.h"
30 #include "ofp-print.h"
32 #include "packet-dpif.h"
34 #include "pcap-file.h"
35 #include "poll-loop.h"
39 #include "unaligned.h"
42 #include "reconnect.h"
45 VLOG_DEFINE_THIS_MODULE(netdev_dummy
);
49 struct dummy_packet_stream
{
50 struct stream
*stream
;
55 enum dummy_packet_conn_type
{
56 NONE
, /* No connection is configured. */
57 PASSIVE
, /* Listener. */
58 ACTIVE
/* Connect to listener. */
61 enum dummy_netdev_conn_state
{
62 CONN_STATE_CONNECTED
, /* Listener connected. */
63 CONN_STATE_NOT_CONNECTED
, /* Listener not connected. */
64 CONN_STATE_UNKNOWN
, /* No relavent information. */
67 struct dummy_packet_pconn
{
68 struct pstream
*pstream
;
69 struct dummy_packet_stream
*streams
;
73 struct dummy_packet_rconn
{
74 struct dummy_packet_stream
*rstream
;
75 struct reconnect
*reconnect
;
78 struct dummy_packet_conn
{
79 enum dummy_packet_conn_type type
;
81 struct dummy_packet_pconn pconn
;
82 struct dummy_packet_rconn rconn
;
86 /* Protects 'dummy_list'. */
87 static struct ovs_mutex dummy_list_mutex
= OVS_MUTEX_INITIALIZER
;
89 /* Contains all 'struct dummy_dev's. */
90 static struct list dummy_list
OVS_GUARDED_BY(dummy_list_mutex
)
91 = LIST_INITIALIZER(&dummy_list
);
97 struct list list_node
OVS_GUARDED_BY(dummy_list_mutex
);
99 /* Protects all members below. */
100 struct ovs_mutex mutex
OVS_ACQ_AFTER(dummy_list_mutex
);
102 uint8_t hwaddr
[ETH_ADDR_LEN
] OVS_GUARDED
;
104 struct netdev_stats stats OVS_GUARDED
;
105 enum netdev_flags flags OVS_GUARDED
;
106 int ifindex OVS_GUARDED
;
108 struct dummy_packet_conn conn OVS_GUARDED
;
110 FILE *tx_pcap
, *rxq_pcap OVS_GUARDED
;
112 struct list rxes OVS_GUARDED
; /* List of child "netdev_rxq_dummy"s. */
115 /* Max 'recv_queue_len' in struct netdev_dummy. */
116 #define NETDEV_DUMMY_MAX_QUEUE 100
118 struct netdev_rxq_dummy
{
119 struct netdev_rxq up
;
120 struct list node
; /* In netdev_dummy's "rxes" list. */
121 struct list recv_queue
;
122 int recv_queue_len
; /* list_size(&recv_queue). */
123 struct seq
*seq
; /* Reports newly queued packets. */
126 static unixctl_cb_func netdev_dummy_set_admin_state
;
127 static int netdev_dummy_construct(struct netdev
*);
128 static void netdev_dummy_queue_packet(struct netdev_dummy
*, struct ofpbuf
*);
130 static void dummy_packet_stream_close(struct dummy_packet_stream
*);
133 is_dummy_class(const struct netdev_class
*class)
135 return class->construct
== netdev_dummy_construct
;
138 static struct netdev_dummy
*
139 netdev_dummy_cast(const struct netdev
*netdev
)
141 ovs_assert(is_dummy_class(netdev_get_class(netdev
)));
142 return CONTAINER_OF(netdev
, struct netdev_dummy
, up
);
145 static struct netdev_rxq_dummy
*
146 netdev_rxq_dummy_cast(const struct netdev_rxq
*rx
)
148 ovs_assert(is_dummy_class(netdev_get_class(rx
->netdev
)));
149 return CONTAINER_OF(rx
, struct netdev_rxq_dummy
, up
);
153 dummy_packet_stream_init(struct dummy_packet_stream
*s
, struct stream
*stream
)
155 int rxbuf_size
= stream
? 2048 : 0;
157 ofpbuf_init(&s
->rxbuf
, rxbuf_size
);
161 static struct dummy_packet_stream
*
162 dummy_packet_stream_create(struct stream
*stream
)
164 struct dummy_packet_stream
*s
;
166 s
= xzalloc(sizeof *s
);
167 dummy_packet_stream_init(s
, stream
);
173 dummy_packet_stream_wait(struct dummy_packet_stream
*s
)
175 stream_run_wait(s
->stream
);
176 if (!list_is_empty(&s
->txq
)) {
177 stream_send_wait(s
->stream
);
179 stream_recv_wait(s
->stream
);
183 dummy_packet_stream_send(struct dummy_packet_stream
*s
, const void *buffer
, size_t size
)
185 if (list_size(&s
->txq
) < NETDEV_DUMMY_MAX_QUEUE
) {
188 b
= ofpbuf_clone_data_with_headroom(buffer
, size
, 2);
189 put_unaligned_be16(ofpbuf_push_uninit(b
, 2), htons(size
));
190 list_push_back(&s
->txq
, &b
->list_node
);
195 dummy_packet_stream_run(struct netdev_dummy
*dev
, struct dummy_packet_stream
*s
)
200 stream_run(s
->stream
);
202 if (!list_is_empty(&s
->txq
)) {
203 struct ofpbuf
*txbuf
;
206 txbuf
= ofpbuf_from_list(list_front(&s
->txq
));
207 retval
= stream_send(s
->stream
, ofpbuf_data(txbuf
), ofpbuf_size(txbuf
));
210 ofpbuf_pull(txbuf
, retval
);
211 if (!ofpbuf_size(txbuf
)) {
212 list_remove(&txbuf
->list_node
);
213 ofpbuf_delete(txbuf
);
215 } else if (retval
!= -EAGAIN
) {
221 if (ofpbuf_size(&s
->rxbuf
) < 2) {
222 n
= 2 - ofpbuf_size(&s
->rxbuf
);
226 frame_len
= ntohs(get_unaligned_be16(ofpbuf_data(&s
->rxbuf
)));
227 if (frame_len
< ETH_HEADER_LEN
) {
231 n
= (2 + frame_len
) - ofpbuf_size(&s
->rxbuf
);
238 ofpbuf_prealloc_tailroom(&s
->rxbuf
, n
);
239 retval
= stream_recv(s
->stream
, ofpbuf_tail(&s
->rxbuf
), n
);
242 ofpbuf_set_size(&s
->rxbuf
, ofpbuf_size(&s
->rxbuf
) + retval
);
243 if (retval
== n
&& ofpbuf_size(&s
->rxbuf
) > 2) {
244 ofpbuf_pull(&s
->rxbuf
, 2);
245 netdev_dummy_queue_packet(dev
,
246 ofpbuf_clone(&s
->rxbuf
));
247 ofpbuf_clear(&s
->rxbuf
);
249 } else if (retval
!= -EAGAIN
) {
250 error
= (retval
< 0 ? -retval
251 : ofpbuf_size(&s
->rxbuf
) ? EPROTO
260 dummy_packet_stream_close(struct dummy_packet_stream
*s
)
262 stream_close(s
->stream
);
263 ofpbuf_uninit(&s
->rxbuf
);
264 ofpbuf_list_delete(&s
->txq
);
268 dummy_packet_conn_init(struct dummy_packet_conn
*conn
)
270 memset(conn
, 0, sizeof *conn
);
275 dummy_packet_conn_get_config(struct dummy_packet_conn
*conn
, struct smap
*args
)
278 switch (conn
->type
) {
280 smap_add(args
, "pstream", pstream_get_name(conn
->u
.pconn
.pstream
));
284 smap_add(args
, "stream", stream_get_name(conn
->u
.rconn
.rstream
->stream
));
294 dummy_packet_conn_close(struct dummy_packet_conn
*conn
)
297 struct dummy_packet_pconn
*pconn
= &conn
->u
.pconn
;
298 struct dummy_packet_rconn
*rconn
= &conn
->u
.rconn
;
300 switch (conn
->type
) {
302 pstream_close(pconn
->pstream
);
303 for (i
= 0; i
< pconn
->n_streams
; i
++) {
304 dummy_packet_stream_close(&pconn
->streams
[i
]);
306 free(pconn
->streams
);
307 pconn
->pstream
= NULL
;
308 pconn
->streams
= NULL
;
312 dummy_packet_stream_close(rconn
->rstream
);
313 free(rconn
->rstream
);
314 rconn
->rstream
= NULL
;
315 reconnect_destroy(rconn
->reconnect
);
316 rconn
->reconnect
= NULL
;
325 memset(conn
, 0, sizeof *conn
);
329 dummy_packet_conn_set_config(struct dummy_packet_conn
*conn
,
330 const struct smap
*args
)
332 const char *pstream
= smap_get(args
, "pstream");
333 const char *stream
= smap_get(args
, "stream");
335 if (pstream
&& stream
) {
336 VLOG_WARN("Open failed: both %s and %s are configured",
341 switch (conn
->type
) {
343 if (!strcmp(pstream_get_name(conn
->u
.pconn
.pstream
), pstream
)) {
346 dummy_packet_conn_close(conn
);
349 if (!strcmp(stream_get_name(conn
->u
.rconn
.rstream
->stream
), stream
)) {
352 dummy_packet_conn_close(conn
);
362 error
= pstream_open(pstream
, &conn
->u
.pconn
.pstream
, DSCP_DEFAULT
);
364 VLOG_WARN("%s: open failed (%s)", pstream
, ovs_strerror(error
));
366 conn
->type
= PASSIVE
;
372 struct stream
*active_stream
;
373 struct reconnect
*reconnect
;;
375 reconnect
= reconnect_create(time_msec());
376 reconnect_set_name(reconnect
, stream
);
377 reconnect_set_passive(reconnect
, false, time_msec());
378 reconnect_enable(reconnect
, time_msec());
379 reconnect_set_backoff(reconnect
, 100, INT_MAX
);
380 reconnect_set_probe_interval(reconnect
, 0);
381 conn
->u
.rconn
.reconnect
= reconnect
;
384 error
= stream_open(stream
, &active_stream
, DSCP_DEFAULT
);
385 conn
->u
.rconn
.rstream
= dummy_packet_stream_create(active_stream
);
389 reconnect_connected(reconnect
, time_msec());
393 reconnect_connecting(reconnect
, time_msec());
397 reconnect_connect_failed(reconnect
, time_msec(), error
);
398 stream_close(active_stream
);
399 conn
->u
.rconn
.rstream
->stream
= NULL
;
406 dummy_pconn_run(struct netdev_dummy
*dev
)
407 OVS_REQUIRES(dev
->mutex
)
409 struct stream
*new_stream
;
410 struct dummy_packet_pconn
*pconn
= &dev
->conn
.u
.pconn
;
414 error
= pstream_accept(pconn
->pstream
, &new_stream
);
416 struct dummy_packet_stream
*s
;
418 pconn
->streams
= xrealloc(pconn
->streams
,
419 ((pconn
->n_streams
+ 1)
421 s
= &pconn
->streams
[pconn
->n_streams
++];
422 dummy_packet_stream_init(s
, new_stream
);
423 } else if (error
!= EAGAIN
) {
424 VLOG_WARN("%s: accept failed (%s)",
425 pstream_get_name(pconn
->pstream
), ovs_strerror(error
));
426 pstream_close(pconn
->pstream
);
427 pconn
->pstream
= NULL
;
428 dev
->conn
.type
= NONE
;
431 for (i
= 0; i
< pconn
->n_streams
; i
++) {
432 struct dummy_packet_stream
*s
= &pconn
->streams
[i
];
434 error
= dummy_packet_stream_run(dev
, s
);
436 VLOG_DBG("%s: closing connection (%s)",
437 stream_get_name(s
->stream
),
438 ovs_retval_to_string(error
));
439 dummy_packet_stream_close(s
);
440 pconn
->streams
[i
] = pconn
->streams
[--pconn
->n_streams
];
446 dummy_rconn_run(struct netdev_dummy
*dev
)
447 OVS_REQUIRES(dev
->mutex
)
449 struct dummy_packet_rconn
*rconn
= &dev
->conn
.u
.rconn
;
451 switch (reconnect_run(rconn
->reconnect
, time_msec())) {
452 case RECONNECT_CONNECT
:
456 if (rconn
->rstream
->stream
) {
457 error
= stream_connect(rconn
->rstream
->stream
);
459 error
= stream_open(reconnect_get_name(rconn
->reconnect
),
460 &rconn
->rstream
->stream
, DSCP_DEFAULT
);
465 reconnect_connected(rconn
->reconnect
, time_msec());
469 reconnect_connecting(rconn
->reconnect
, time_msec());
473 reconnect_connect_failed(rconn
->reconnect
, time_msec(), error
);
474 stream_close(rconn
->rstream
->stream
);
475 rconn
->rstream
->stream
= NULL
;
481 case RECONNECT_DISCONNECT
:
482 case RECONNECT_PROBE
:
487 if (reconnect_is_connected(rconn
->reconnect
)) {
490 err
= dummy_packet_stream_run(dev
, rconn
->rstream
);
493 reconnect_disconnected(rconn
->reconnect
, time_msec(), err
);
494 stream_close(rconn
->rstream
->stream
);
495 rconn
->rstream
->stream
= NULL
;
501 dummy_packet_conn_run(struct netdev_dummy
*dev
)
502 OVS_REQUIRES(dev
->mutex
)
504 switch (dev
->conn
.type
) {
506 dummy_pconn_run(dev
);
510 dummy_rconn_run(dev
);
520 dummy_packet_conn_wait(struct dummy_packet_conn
*conn
)
523 switch (conn
->type
) {
525 pstream_wait(conn
->u
.pconn
.pstream
);
526 for (i
= 0; i
< conn
->u
.pconn
.n_streams
; i
++) {
527 struct dummy_packet_stream
*s
= &conn
->u
.pconn
.streams
[i
];
528 dummy_packet_stream_wait(s
);
532 if (reconnect_is_connected(conn
->u
.rconn
.reconnect
)) {
533 dummy_packet_stream_wait(conn
->u
.rconn
.rstream
);
544 dummy_packet_conn_send(struct dummy_packet_conn
*conn
,
545 const void *buffer
, size_t size
)
549 switch (conn
->type
) {
551 for (i
= 0; i
< conn
->u
.pconn
.n_streams
; i
++) {
552 struct dummy_packet_stream
*s
= &conn
->u
.pconn
.streams
[i
];
554 dummy_packet_stream_send(s
, buffer
, size
);
555 pstream_wait(conn
->u
.pconn
.pstream
);
560 if (reconnect_is_connected(conn
->u
.rconn
.reconnect
)) {
561 dummy_packet_stream_send(conn
->u
.rconn
.rstream
, buffer
, size
);
562 dummy_packet_stream_wait(conn
->u
.rconn
.rstream
);
572 static enum dummy_netdev_conn_state
573 dummy_netdev_get_conn_state(struct dummy_packet_conn
*conn
)
575 enum dummy_netdev_conn_state state
;
577 if (conn
->type
== ACTIVE
) {
578 if (reconnect_is_connected(conn
->u
.rconn
.reconnect
)) {
579 state
= CONN_STATE_CONNECTED
;
581 state
= CONN_STATE_NOT_CONNECTED
;
584 state
= CONN_STATE_UNKNOWN
;
591 netdev_dummy_run(void)
593 struct netdev_dummy
*dev
;
595 ovs_mutex_lock(&dummy_list_mutex
);
596 LIST_FOR_EACH (dev
, list_node
, &dummy_list
) {
597 ovs_mutex_lock(&dev
->mutex
);
598 dummy_packet_conn_run(dev
);
599 ovs_mutex_unlock(&dev
->mutex
);
601 ovs_mutex_unlock(&dummy_list_mutex
);
605 netdev_dummy_wait(void)
607 struct netdev_dummy
*dev
;
609 ovs_mutex_lock(&dummy_list_mutex
);
610 LIST_FOR_EACH (dev
, list_node
, &dummy_list
) {
611 ovs_mutex_lock(&dev
->mutex
);
612 dummy_packet_conn_wait(&dev
->conn
);
613 ovs_mutex_unlock(&dev
->mutex
);
615 ovs_mutex_unlock(&dummy_list_mutex
);
618 static struct netdev
*
619 netdev_dummy_alloc(void)
621 struct netdev_dummy
*netdev
= xzalloc(sizeof *netdev
);
626 netdev_dummy_construct(struct netdev
*netdev_
)
628 static atomic_uint next_n
= ATOMIC_VAR_INIT(0xaa550000);
629 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
632 atomic_add(&next_n
, 1, &n
);
634 ovs_mutex_init(&netdev
->mutex
);
635 ovs_mutex_lock(&netdev
->mutex
);
636 netdev
->hwaddr
[0] = 0xaa;
637 netdev
->hwaddr
[1] = 0x55;
638 netdev
->hwaddr
[2] = n
>> 24;
639 netdev
->hwaddr
[3] = n
>> 16;
640 netdev
->hwaddr
[4] = n
>> 8;
641 netdev
->hwaddr
[5] = n
;
644 netdev
->ifindex
= -EOPNOTSUPP
;
646 dummy_packet_conn_init(&netdev
->conn
);
648 list_init(&netdev
->rxes
);
649 ovs_mutex_unlock(&netdev
->mutex
);
651 ovs_mutex_lock(&dummy_list_mutex
);
652 list_push_back(&dummy_list
, &netdev
->list_node
);
653 ovs_mutex_unlock(&dummy_list_mutex
);
659 netdev_dummy_destruct(struct netdev
*netdev_
)
661 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
663 ovs_mutex_lock(&dummy_list_mutex
);
664 list_remove(&netdev
->list_node
);
665 ovs_mutex_unlock(&dummy_list_mutex
);
667 ovs_mutex_lock(&netdev
->mutex
);
668 dummy_packet_conn_close(&netdev
->conn
);
669 netdev
->conn
.type
= NONE
;
671 ovs_mutex_unlock(&netdev
->mutex
);
672 ovs_mutex_destroy(&netdev
->mutex
);
676 netdev_dummy_dealloc(struct netdev
*netdev_
)
678 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
684 netdev_dummy_get_config(const struct netdev
*netdev_
, struct smap
*args
)
686 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
688 ovs_mutex_lock(&netdev
->mutex
);
690 if (netdev
->ifindex
>= 0) {
691 smap_add_format(args
, "ifindex", "%d", netdev
->ifindex
);
694 dummy_packet_conn_get_config(&netdev
->conn
, args
);
696 ovs_mutex_unlock(&netdev
->mutex
);
701 netdev_dummy_set_config(struct netdev
*netdev_
, const struct smap
*args
)
703 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
706 ovs_mutex_lock(&netdev
->mutex
);
707 netdev
->ifindex
= smap_get_int(args
, "ifindex", -EOPNOTSUPP
);
709 dummy_packet_conn_set_config(&netdev
->conn
, args
);
711 if (netdev
->rxq_pcap
) {
712 fclose(netdev
->rxq_pcap
);
714 if (netdev
->tx_pcap
&& netdev
->tx_pcap
!= netdev
->rxq_pcap
) {
715 fclose(netdev
->tx_pcap
);
717 netdev
->rxq_pcap
= netdev
->tx_pcap
= NULL
;
718 pcap
= smap_get(args
, "pcap");
720 netdev
->rxq_pcap
= netdev
->tx_pcap
= ovs_pcap_open(pcap
, "ab");
722 const char *rxq_pcap
= smap_get(args
, "rxq_pcap");
723 const char *tx_pcap
= smap_get(args
, "tx_pcap");
726 netdev
->rxq_pcap
= ovs_pcap_open(rxq_pcap
, "ab");
729 netdev
->tx_pcap
= ovs_pcap_open(tx_pcap
, "ab");
733 ovs_mutex_unlock(&netdev
->mutex
);
738 static struct netdev_rxq
*
739 netdev_dummy_rxq_alloc(void)
741 struct netdev_rxq_dummy
*rx
= xzalloc(sizeof *rx
);
746 netdev_dummy_rxq_construct(struct netdev_rxq
*rxq_
)
748 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
749 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
751 ovs_mutex_lock(&netdev
->mutex
);
752 list_push_back(&netdev
->rxes
, &rx
->node
);
753 list_init(&rx
->recv_queue
);
754 rx
->recv_queue_len
= 0;
755 rx
->seq
= seq_create();
756 ovs_mutex_unlock(&netdev
->mutex
);
762 netdev_dummy_rxq_destruct(struct netdev_rxq
*rxq_
)
764 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
765 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
767 ovs_mutex_lock(&netdev
->mutex
);
768 list_remove(&rx
->node
);
769 ofpbuf_list_delete(&rx
->recv_queue
);
770 ovs_mutex_unlock(&netdev
->mutex
);
771 seq_destroy(rx
->seq
);
775 netdev_dummy_rxq_dealloc(struct netdev_rxq
*rxq_
)
777 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
783 netdev_dummy_rxq_recv(struct netdev_rxq
*rxq_
, struct dpif_packet
**arr
,
786 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
787 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
788 struct ofpbuf
*packet
;
790 ovs_mutex_lock(&netdev
->mutex
);
791 if (!list_is_empty(&rx
->recv_queue
)) {
792 packet
= ofpbuf_from_list(list_pop_front(&rx
->recv_queue
));
793 rx
->recv_queue_len
--;
797 ovs_mutex_unlock(&netdev
->mutex
);
802 ovs_mutex_lock(&netdev
->mutex
);
803 netdev
->stats
.rx_packets
++;
804 netdev
->stats
.rx_bytes
+= ofpbuf_size(packet
);
805 ovs_mutex_unlock(&netdev
->mutex
);
807 dp_packet_pad(packet
);
809 /* This performs a (sometimes unnecessary) copy */
810 arr
[0] = dpif_packet_clone_from_ofpbuf(packet
);
811 ofpbuf_delete(packet
);
817 netdev_dummy_rxq_wait(struct netdev_rxq
*rxq_
)
819 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
820 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
821 uint64_t seq
= seq_read(rx
->seq
);
823 ovs_mutex_lock(&netdev
->mutex
);
824 if (!list_is_empty(&rx
->recv_queue
)) {
825 poll_immediate_wake();
827 seq_wait(rx
->seq
, seq
);
829 ovs_mutex_unlock(&netdev
->mutex
);
833 netdev_dummy_rxq_drain(struct netdev_rxq
*rxq_
)
835 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
836 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
838 ovs_mutex_lock(&netdev
->mutex
);
839 ofpbuf_list_delete(&rx
->recv_queue
);
840 rx
->recv_queue_len
= 0;
841 ovs_mutex_unlock(&netdev
->mutex
);
849 netdev_dummy_send(struct netdev
*netdev
, struct dpif_packet
**pkts
, int cnt
,
852 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
856 for (i
= 0; i
< cnt
; i
++) {
857 const void *buffer
= ofpbuf_data(&pkts
[i
]->ofpbuf
);
858 size_t size
= ofpbuf_size(&pkts
[i
]->ofpbuf
);
860 if (size
< ETH_HEADER_LEN
) {
864 const struct eth_header
*eth
= buffer
;
867 ovs_mutex_lock(&dev
->mutex
);
868 max_size
= dev
->mtu
+ ETH_HEADER_LEN
;
869 ovs_mutex_unlock(&dev
->mutex
);
871 if (eth
->eth_type
== htons(ETH_TYPE_VLAN
)) {
872 max_size
+= VLAN_HEADER_LEN
;
874 if (size
> max_size
) {
880 ovs_mutex_lock(&dev
->mutex
);
881 dev
->stats
.tx_packets
++;
882 dev
->stats
.tx_bytes
+= size
;
884 dummy_packet_conn_send(&dev
->conn
, buffer
, size
);
887 struct ofpbuf packet
;
889 ofpbuf_use_const(&packet
, buffer
, size
);
890 ovs_pcap_write(dev
->tx_pcap
, &packet
);
891 fflush(dev
->tx_pcap
);
894 ovs_mutex_unlock(&dev
->mutex
);
898 for (i
= 0; i
< cnt
; i
++) {
899 dpif_packet_delete(pkts
[i
]);
907 netdev_dummy_set_etheraddr(struct netdev
*netdev
,
908 const uint8_t mac
[ETH_ADDR_LEN
])
910 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
912 ovs_mutex_lock(&dev
->mutex
);
913 if (!eth_addr_equals(dev
->hwaddr
, mac
)) {
914 memcpy(dev
->hwaddr
, mac
, ETH_ADDR_LEN
);
915 netdev_change_seq_changed(netdev
);
917 ovs_mutex_unlock(&dev
->mutex
);
923 netdev_dummy_get_etheraddr(const struct netdev
*netdev
,
924 uint8_t mac
[ETH_ADDR_LEN
])
926 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
928 ovs_mutex_lock(&dev
->mutex
);
929 memcpy(mac
, dev
->hwaddr
, ETH_ADDR_LEN
);
930 ovs_mutex_unlock(&dev
->mutex
);
936 netdev_dummy_get_mtu(const struct netdev
*netdev
, int *mtup
)
938 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
940 ovs_mutex_lock(&dev
->mutex
);
942 ovs_mutex_unlock(&dev
->mutex
);
948 netdev_dummy_set_mtu(const struct netdev
*netdev
, int mtu
)
950 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
952 ovs_mutex_lock(&dev
->mutex
);
954 ovs_mutex_unlock(&dev
->mutex
);
960 netdev_dummy_get_stats(const struct netdev
*netdev
, struct netdev_stats
*stats
)
962 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
964 ovs_mutex_lock(&dev
->mutex
);
966 ovs_mutex_unlock(&dev
->mutex
);
972 netdev_dummy_set_stats(struct netdev
*netdev
, const struct netdev_stats
*stats
)
974 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
976 ovs_mutex_lock(&dev
->mutex
);
978 ovs_mutex_unlock(&dev
->mutex
);
984 netdev_dummy_get_ifindex(const struct netdev
*netdev
)
986 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
989 ovs_mutex_lock(&dev
->mutex
);
990 ifindex
= dev
->ifindex
;
991 ovs_mutex_unlock(&dev
->mutex
);
997 netdev_dummy_update_flags__(struct netdev_dummy
*netdev
,
998 enum netdev_flags off
, enum netdev_flags on
,
999 enum netdev_flags
*old_flagsp
)
1000 OVS_REQUIRES(netdev
->mutex
)
1002 if ((off
| on
) & ~(NETDEV_UP
| NETDEV_PROMISC
)) {
1006 *old_flagsp
= netdev
->flags
;
1007 netdev
->flags
|= on
;
1008 netdev
->flags
&= ~off
;
1009 if (*old_flagsp
!= netdev
->flags
) {
1010 netdev_change_seq_changed(&netdev
->up
);
1017 netdev_dummy_update_flags(struct netdev
*netdev_
,
1018 enum netdev_flags off
, enum netdev_flags on
,
1019 enum netdev_flags
*old_flagsp
)
1021 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
1024 ovs_mutex_lock(&netdev
->mutex
);
1025 error
= netdev_dummy_update_flags__(netdev
, off
, on
, old_flagsp
);
1026 ovs_mutex_unlock(&netdev
->mutex
);
1031 /* Helper functions. */
1033 static const struct netdev_class dummy_class
= {
1040 netdev_dummy_construct
,
1041 netdev_dummy_destruct
,
1042 netdev_dummy_dealloc
,
1043 netdev_dummy_get_config
,
1044 netdev_dummy_set_config
,
1045 NULL
, /* get_tunnel_config */
1047 netdev_dummy_send
, /* send */
1048 NULL
, /* send_wait */
1050 netdev_dummy_set_etheraddr
,
1051 netdev_dummy_get_etheraddr
,
1052 netdev_dummy_get_mtu
,
1053 netdev_dummy_set_mtu
,
1054 netdev_dummy_get_ifindex
,
1055 NULL
, /* get_carrier */
1056 NULL
, /* get_carrier_resets */
1057 NULL
, /* get_miimon */
1058 netdev_dummy_get_stats
,
1059 netdev_dummy_set_stats
,
1061 NULL
, /* get_features */
1062 NULL
, /* set_advertisements */
1064 NULL
, /* set_policing */
1065 NULL
, /* get_qos_types */
1066 NULL
, /* get_qos_capabilities */
1069 NULL
, /* get_queue */
1070 NULL
, /* set_queue */
1071 NULL
, /* delete_queue */
1072 NULL
, /* get_queue_stats */
1073 NULL
, /* queue_dump_start */
1074 NULL
, /* queue_dump_next */
1075 NULL
, /* queue_dump_done */
1076 NULL
, /* dump_queue_stats */
1081 NULL
, /* add_router */
1082 NULL
, /* get_next_hop */
1083 NULL
, /* get_status */
1084 NULL
, /* arp_lookup */
1086 netdev_dummy_update_flags
,
1088 netdev_dummy_rxq_alloc
,
1089 netdev_dummy_rxq_construct
,
1090 netdev_dummy_rxq_destruct
,
1091 netdev_dummy_rxq_dealloc
,
1092 netdev_dummy_rxq_recv
,
1093 netdev_dummy_rxq_wait
,
1094 netdev_dummy_rxq_drain
,
1097 static struct ofpbuf
*
1098 eth_from_packet_or_flow(const char *s
)
1100 enum odp_key_fitness fitness
;
1101 struct ofpbuf
*packet
;
1102 struct ofpbuf odp_key
;
1106 if (!eth_from_hex(s
, &packet
)) {
1110 /* Convert string to datapath key.
1112 * It would actually be nicer to parse an OpenFlow-like flow key here, but
1113 * the code for that currently calls exit() on parse error. We have to
1114 * settle for parsing a datapath key for now.
1116 ofpbuf_init(&odp_key
, 0);
1117 error
= odp_flow_from_string(s
, NULL
, &odp_key
, NULL
);
1119 ofpbuf_uninit(&odp_key
);
1123 /* Convert odp_key to flow. */
1124 fitness
= odp_flow_key_to_flow(ofpbuf_data(&odp_key
), ofpbuf_size(&odp_key
), &flow
);
1125 if (fitness
== ODP_FIT_ERROR
) {
1126 ofpbuf_uninit(&odp_key
);
1130 packet
= ofpbuf_new(0);
1131 flow_compose(packet
, &flow
);
1133 ofpbuf_uninit(&odp_key
);
1138 netdev_dummy_queue_packet__(struct netdev_rxq_dummy
*rx
, struct ofpbuf
*packet
)
1140 list_push_back(&rx
->recv_queue
, &packet
->list_node
);
1141 rx
->recv_queue_len
++;
1142 seq_change(rx
->seq
);
1146 netdev_dummy_queue_packet(struct netdev_dummy
*dummy
, struct ofpbuf
*packet
)
1147 OVS_REQUIRES(dummy
->mutex
)
1149 struct netdev_rxq_dummy
*rx
, *prev
;
1151 if (dummy
->rxq_pcap
) {
1152 ovs_pcap_write(dummy
->rxq_pcap
, packet
);
1153 fflush(dummy
->rxq_pcap
);
1156 LIST_FOR_EACH (rx
, node
, &dummy
->rxes
) {
1157 if (rx
->recv_queue_len
< NETDEV_DUMMY_MAX_QUEUE
) {
1159 netdev_dummy_queue_packet__(prev
, ofpbuf_clone(packet
));
1165 netdev_dummy_queue_packet__(prev
, packet
);
1167 ofpbuf_delete(packet
);
1172 netdev_dummy_receive(struct unixctl_conn
*conn
,
1173 int argc
, const char *argv
[], void *aux OVS_UNUSED
)
1175 struct netdev_dummy
*dummy_dev
;
1176 struct netdev
*netdev
;
1179 netdev
= netdev_from_name(argv
[1]);
1180 if (!netdev
|| !is_dummy_class(netdev
->netdev_class
)) {
1181 unixctl_command_reply_error(conn
, "no such dummy netdev");
1184 dummy_dev
= netdev_dummy_cast(netdev
);
1186 for (i
= 2; i
< argc
; i
++) {
1187 struct ofpbuf
*packet
;
1189 packet
= eth_from_packet_or_flow(argv
[i
]);
1191 unixctl_command_reply_error(conn
, "bad packet syntax");
1195 ovs_mutex_lock(&dummy_dev
->mutex
);
1196 netdev_dummy_queue_packet(dummy_dev
, packet
);
1197 ovs_mutex_unlock(&dummy_dev
->mutex
);
1200 unixctl_command_reply(conn
, NULL
);
1203 netdev_close(netdev
);
1207 netdev_dummy_set_admin_state__(struct netdev_dummy
*dev
, bool admin_state
)
1208 OVS_REQUIRES(dev
->mutex
)
1210 enum netdev_flags old_flags
;
1213 netdev_dummy_update_flags__(dev
, 0, NETDEV_UP
, &old_flags
);
1215 netdev_dummy_update_flags__(dev
, NETDEV_UP
, 0, &old_flags
);
1220 netdev_dummy_set_admin_state(struct unixctl_conn
*conn
, int argc
,
1221 const char *argv
[], void *aux OVS_UNUSED
)
1225 if (!strcasecmp(argv
[argc
- 1], "up")) {
1227 } else if ( !strcasecmp(argv
[argc
- 1], "down")) {
1230 unixctl_command_reply_error(conn
, "Invalid Admin State");
1235 struct netdev
*netdev
= netdev_from_name(argv
[1]);
1236 if (netdev
&& is_dummy_class(netdev
->netdev_class
)) {
1237 struct netdev_dummy
*dummy_dev
= netdev_dummy_cast(netdev
);
1239 ovs_mutex_lock(&dummy_dev
->mutex
);
1240 netdev_dummy_set_admin_state__(dummy_dev
, up
);
1241 ovs_mutex_unlock(&dummy_dev
->mutex
);
1243 netdev_close(netdev
);
1245 unixctl_command_reply_error(conn
, "Unknown Dummy Interface");
1246 netdev_close(netdev
);
1250 struct netdev_dummy
*netdev
;
1252 ovs_mutex_lock(&dummy_list_mutex
);
1253 LIST_FOR_EACH (netdev
, list_node
, &dummy_list
) {
1254 ovs_mutex_lock(&netdev
->mutex
);
1255 netdev_dummy_set_admin_state__(netdev
, up
);
1256 ovs_mutex_unlock(&netdev
->mutex
);
1258 ovs_mutex_unlock(&dummy_list_mutex
);
1260 unixctl_command_reply(conn
, "OK");
1264 display_conn_state__(struct ds
*s
, const char *name
,
1265 enum dummy_netdev_conn_state state
)
1267 ds_put_format(s
, "%s: ", name
);
1270 case CONN_STATE_CONNECTED
:
1271 ds_put_cstr(s
, "connected\n");
1274 case CONN_STATE_NOT_CONNECTED
:
1275 ds_put_cstr(s
, "disconnected\n");
1278 case CONN_STATE_UNKNOWN
:
1280 ds_put_cstr(s
, "unknown\n");
1286 netdev_dummy_conn_state(struct unixctl_conn
*conn
, int argc
,
1287 const char *argv
[], void *aux OVS_UNUSED
)
1289 enum dummy_netdev_conn_state state
= CONN_STATE_UNKNOWN
;
1295 const char *dev_name
= argv
[1];
1296 struct netdev
*netdev
= netdev_from_name(dev_name
);
1298 if (netdev
&& is_dummy_class(netdev
->netdev_class
)) {
1299 struct netdev_dummy
*dummy_dev
= netdev_dummy_cast(netdev
);
1301 ovs_mutex_lock(&dummy_dev
->mutex
);
1302 state
= dummy_netdev_get_conn_state(&dummy_dev
->conn
);
1303 ovs_mutex_unlock(&dummy_dev
->mutex
);
1305 netdev_close(netdev
);
1307 display_conn_state__(&s
, dev_name
, state
);
1309 struct netdev_dummy
*netdev
;
1311 ovs_mutex_lock(&dummy_list_mutex
);
1312 LIST_FOR_EACH (netdev
, list_node
, &dummy_list
) {
1313 ovs_mutex_lock(&netdev
->mutex
);
1314 state
= dummy_netdev_get_conn_state(&netdev
->conn
);
1315 ovs_mutex_unlock(&netdev
->mutex
);
1316 if (state
!= CONN_STATE_UNKNOWN
) {
1317 display_conn_state__(&s
, netdev
->up
.name
, state
);
1320 ovs_mutex_unlock(&dummy_list_mutex
);
1323 unixctl_command_reply(conn
, ds_cstr(&s
));
1328 netdev_dummy_register(bool override
)
1330 unixctl_command_register("netdev-dummy/receive", "NAME PACKET|FLOW...",
1331 2, INT_MAX
, netdev_dummy_receive
, NULL
);
1332 unixctl_command_register("netdev-dummy/set-admin-state",
1333 "[netdev] up|down", 1, 2,
1334 netdev_dummy_set_admin_state
, NULL
);
1335 unixctl_command_register("netdev-dummy/conn-state",
1337 netdev_dummy_conn_state
, NULL
);
1344 netdev_enumerate_types(&types
);
1345 SSET_FOR_EACH (type
, &types
) {
1346 if (!strcmp(type
, "patch")) {
1349 if (!netdev_unregister_provider(type
)) {
1350 struct netdev_class
*class;
1353 class = xmemdup(&dummy_class
, sizeof dummy_class
);
1354 class->type
= xstrdup(type
);
1355 error
= netdev_register_provider(class);
1357 VLOG_ERR("%s: failed to register netdev provider (%s)",
1358 type
, ovs_strerror(error
));
1359 free(CONST_CAST(char *, class->type
));
1364 sset_destroy(&types
);
1366 netdev_register_provider(&dummy_class
);
1368 netdev_vport_tunnel_register();