2 * Copyright (c) 2010, 2011, 2012, 2013, 2015 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 "dp-packet.h"
24 #include "dpif-netdev.h"
25 #include "dynamic-string.h"
28 #include "netdev-provider.h"
29 #include "netdev-vport.h"
31 #include "ofp-print.h"
33 #include "ovs-atomic.h"
35 #include "pcap-file.h"
36 #include "poll-loop.h"
40 #include "unaligned.h"
43 #include "reconnect.h"
44 #include "openvswitch/vlog.h"
46 VLOG_DEFINE_THIS_MODULE(netdev_dummy
);
50 struct dummy_packet_stream
{
51 struct stream
*stream
;
52 struct dp_packet rxbuf
;
56 enum dummy_packet_conn_type
{
57 NONE
, /* No connection is configured. */
58 PASSIVE
, /* Listener. */
59 ACTIVE
/* Connect to listener. */
62 enum dummy_netdev_conn_state
{
63 CONN_STATE_CONNECTED
, /* Listener connected. */
64 CONN_STATE_NOT_CONNECTED
, /* Listener not connected. */
65 CONN_STATE_UNKNOWN
, /* No relavent information. */
68 struct dummy_packet_pconn
{
69 struct pstream
*pstream
;
70 struct dummy_packet_stream
*streams
;
74 struct dummy_packet_rconn
{
75 struct dummy_packet_stream
*rstream
;
76 struct reconnect
*reconnect
;
79 struct dummy_packet_conn
{
80 enum dummy_packet_conn_type type
;
82 struct dummy_packet_pconn pconn
;
83 struct dummy_packet_rconn rconn
;
87 /* Protects 'dummy_list'. */
88 static struct ovs_mutex dummy_list_mutex
= OVS_MUTEX_INITIALIZER
;
90 /* Contains all 'struct dummy_dev's. */
91 static struct ovs_list dummy_list
OVS_GUARDED_BY(dummy_list_mutex
)
92 = OVS_LIST_INITIALIZER(&dummy_list
);
98 struct ovs_list list_node
OVS_GUARDED_BY(dummy_list_mutex
);
100 /* Protects all members below. */
101 struct ovs_mutex mutex
OVS_ACQ_AFTER(dummy_list_mutex
);
103 uint8_t hwaddr
[ETH_ADDR_LEN
] OVS_GUARDED
;
105 struct netdev_stats stats OVS_GUARDED
;
106 enum netdev_flags flags OVS_GUARDED
;
107 int ifindex OVS_GUARDED
;
109 struct dummy_packet_conn conn OVS_GUARDED
;
111 FILE *tx_pcap
, *rxq_pcap OVS_GUARDED
;
113 struct in_addr address
, netmask
;
114 struct ovs_list rxes OVS_GUARDED
; /* List of child "netdev_rxq_dummy"s. */
117 /* Max 'recv_queue_len' in struct netdev_dummy. */
118 #define NETDEV_DUMMY_MAX_QUEUE 100
120 struct netdev_rxq_dummy
{
121 struct netdev_rxq up
;
122 struct ovs_list node
; /* In netdev_dummy's "rxes" list. */
123 struct ovs_list recv_queue
;
124 int recv_queue_len
; /* list_size(&recv_queue). */
125 struct seq
*seq
; /* Reports newly queued packets. */
128 static unixctl_cb_func netdev_dummy_set_admin_state
;
129 static int netdev_dummy_construct(struct netdev
*);
130 static void netdev_dummy_queue_packet(struct netdev_dummy
*, struct dp_packet
*);
132 static void dummy_packet_stream_close(struct dummy_packet_stream
*);
135 is_dummy_class(const struct netdev_class
*class)
137 return class->construct
== netdev_dummy_construct
;
140 static struct netdev_dummy
*
141 netdev_dummy_cast(const struct netdev
*netdev
)
143 ovs_assert(is_dummy_class(netdev_get_class(netdev
)));
144 return CONTAINER_OF(netdev
, struct netdev_dummy
, up
);
147 static struct netdev_rxq_dummy
*
148 netdev_rxq_dummy_cast(const struct netdev_rxq
*rx
)
150 ovs_assert(is_dummy_class(netdev_get_class(rx
->netdev
)));
151 return CONTAINER_OF(rx
, struct netdev_rxq_dummy
, up
);
155 dummy_packet_stream_init(struct dummy_packet_stream
*s
, struct stream
*stream
)
157 int rxbuf_size
= stream
? 2048 : 0;
159 dp_packet_init(&s
->rxbuf
, rxbuf_size
);
163 static struct dummy_packet_stream
*
164 dummy_packet_stream_create(struct stream
*stream
)
166 struct dummy_packet_stream
*s
;
168 s
= xzalloc(sizeof *s
);
169 dummy_packet_stream_init(s
, stream
);
175 dummy_packet_stream_wait(struct dummy_packet_stream
*s
)
177 stream_run_wait(s
->stream
);
178 if (!list_is_empty(&s
->txq
)) {
179 stream_send_wait(s
->stream
);
181 stream_recv_wait(s
->stream
);
185 dummy_packet_stream_send(struct dummy_packet_stream
*s
, const void *buffer
, size_t size
)
187 if (list_size(&s
->txq
) < NETDEV_DUMMY_MAX_QUEUE
) {
190 b
= dp_packet_clone_data_with_headroom(buffer
, size
, 2);
191 put_unaligned_be16(dp_packet_push_uninit(b
, 2), htons(size
));
192 list_push_back(&s
->txq
, &b
->list_node
);
197 dummy_packet_stream_run(struct netdev_dummy
*dev
, struct dummy_packet_stream
*s
)
202 stream_run(s
->stream
);
204 if (!list_is_empty(&s
->txq
)) {
205 struct dp_packet
*txbuf
;
208 txbuf
= dp_packet_from_list(list_front(&s
->txq
));
209 retval
= stream_send(s
->stream
, dp_packet_data(txbuf
), dp_packet_size(txbuf
));
212 dp_packet_pull(txbuf
, retval
);
213 if (!dp_packet_size(txbuf
)) {
214 list_remove(&txbuf
->list_node
);
215 dp_packet_delete(txbuf
);
217 } else if (retval
!= -EAGAIN
) {
223 if (dp_packet_size(&s
->rxbuf
) < 2) {
224 n
= 2 - dp_packet_size(&s
->rxbuf
);
228 frame_len
= ntohs(get_unaligned_be16(dp_packet_data(&s
->rxbuf
)));
229 if (frame_len
< ETH_HEADER_LEN
) {
233 n
= (2 + frame_len
) - dp_packet_size(&s
->rxbuf
);
240 dp_packet_prealloc_tailroom(&s
->rxbuf
, n
);
241 retval
= stream_recv(s
->stream
, dp_packet_tail(&s
->rxbuf
), n
);
244 dp_packet_set_size(&s
->rxbuf
, dp_packet_size(&s
->rxbuf
) + retval
);
245 if (retval
== n
&& dp_packet_size(&s
->rxbuf
) > 2) {
246 dp_packet_pull(&s
->rxbuf
, 2);
247 netdev_dummy_queue_packet(dev
,
248 dp_packet_clone(&s
->rxbuf
));
249 dp_packet_clear(&s
->rxbuf
);
251 } else if (retval
!= -EAGAIN
) {
252 error
= (retval
< 0 ? -retval
253 : dp_packet_size(&s
->rxbuf
) ? EPROTO
262 dummy_packet_stream_close(struct dummy_packet_stream
*s
)
264 stream_close(s
->stream
);
265 dp_packet_uninit(&s
->rxbuf
);
266 dp_packet_list_delete(&s
->txq
);
270 dummy_packet_conn_init(struct dummy_packet_conn
*conn
)
272 memset(conn
, 0, sizeof *conn
);
277 dummy_packet_conn_get_config(struct dummy_packet_conn
*conn
, struct smap
*args
)
280 switch (conn
->type
) {
282 smap_add(args
, "pstream", pstream_get_name(conn
->u
.pconn
.pstream
));
286 smap_add(args
, "stream", stream_get_name(conn
->u
.rconn
.rstream
->stream
));
296 dummy_packet_conn_close(struct dummy_packet_conn
*conn
)
299 struct dummy_packet_pconn
*pconn
= &conn
->u
.pconn
;
300 struct dummy_packet_rconn
*rconn
= &conn
->u
.rconn
;
302 switch (conn
->type
) {
304 pstream_close(pconn
->pstream
);
305 for (i
= 0; i
< pconn
->n_streams
; i
++) {
306 dummy_packet_stream_close(&pconn
->streams
[i
]);
308 free(pconn
->streams
);
309 pconn
->pstream
= NULL
;
310 pconn
->streams
= NULL
;
314 dummy_packet_stream_close(rconn
->rstream
);
315 free(rconn
->rstream
);
316 rconn
->rstream
= NULL
;
317 reconnect_destroy(rconn
->reconnect
);
318 rconn
->reconnect
= NULL
;
327 memset(conn
, 0, sizeof *conn
);
331 dummy_packet_conn_set_config(struct dummy_packet_conn
*conn
,
332 const struct smap
*args
)
334 const char *pstream
= smap_get(args
, "pstream");
335 const char *stream
= smap_get(args
, "stream");
337 if (pstream
&& stream
) {
338 VLOG_WARN("Open failed: both %s and %s are configured",
343 switch (conn
->type
) {
345 if (!strcmp(pstream_get_name(conn
->u
.pconn
.pstream
), pstream
)) {
348 dummy_packet_conn_close(conn
);
351 if (!strcmp(stream_get_name(conn
->u
.rconn
.rstream
->stream
), stream
)) {
354 dummy_packet_conn_close(conn
);
364 error
= pstream_open(pstream
, &conn
->u
.pconn
.pstream
, DSCP_DEFAULT
);
366 VLOG_WARN("%s: open failed (%s)", pstream
, ovs_strerror(error
));
368 conn
->type
= PASSIVE
;
374 struct stream
*active_stream
;
375 struct reconnect
*reconnect
;;
377 reconnect
= reconnect_create(time_msec());
378 reconnect_set_name(reconnect
, stream
);
379 reconnect_set_passive(reconnect
, false, time_msec());
380 reconnect_enable(reconnect
, time_msec());
381 reconnect_set_backoff(reconnect
, 100, INT_MAX
);
382 reconnect_set_probe_interval(reconnect
, 0);
383 conn
->u
.rconn
.reconnect
= reconnect
;
386 error
= stream_open(stream
, &active_stream
, DSCP_DEFAULT
);
387 conn
->u
.rconn
.rstream
= dummy_packet_stream_create(active_stream
);
391 reconnect_connected(reconnect
, time_msec());
395 reconnect_connecting(reconnect
, time_msec());
399 reconnect_connect_failed(reconnect
, time_msec(), error
);
400 stream_close(active_stream
);
401 conn
->u
.rconn
.rstream
->stream
= NULL
;
408 dummy_pconn_run(struct netdev_dummy
*dev
)
409 OVS_REQUIRES(dev
->mutex
)
411 struct stream
*new_stream
;
412 struct dummy_packet_pconn
*pconn
= &dev
->conn
.u
.pconn
;
416 error
= pstream_accept(pconn
->pstream
, &new_stream
);
418 struct dummy_packet_stream
*s
;
420 pconn
->streams
= xrealloc(pconn
->streams
,
421 ((pconn
->n_streams
+ 1)
423 s
= &pconn
->streams
[pconn
->n_streams
++];
424 dummy_packet_stream_init(s
, new_stream
);
425 } else if (error
!= EAGAIN
) {
426 VLOG_WARN("%s: accept failed (%s)",
427 pstream_get_name(pconn
->pstream
), ovs_strerror(error
));
428 pstream_close(pconn
->pstream
);
429 pconn
->pstream
= NULL
;
430 dev
->conn
.type
= NONE
;
433 for (i
= 0; i
< pconn
->n_streams
; i
++) {
434 struct dummy_packet_stream
*s
= &pconn
->streams
[i
];
436 error
= dummy_packet_stream_run(dev
, s
);
438 VLOG_DBG("%s: closing connection (%s)",
439 stream_get_name(s
->stream
),
440 ovs_retval_to_string(error
));
441 dummy_packet_stream_close(s
);
442 pconn
->streams
[i
] = pconn
->streams
[--pconn
->n_streams
];
448 dummy_rconn_run(struct netdev_dummy
*dev
)
449 OVS_REQUIRES(dev
->mutex
)
451 struct dummy_packet_rconn
*rconn
= &dev
->conn
.u
.rconn
;
453 switch (reconnect_run(rconn
->reconnect
, time_msec())) {
454 case RECONNECT_CONNECT
:
458 if (rconn
->rstream
->stream
) {
459 error
= stream_connect(rconn
->rstream
->stream
);
461 error
= stream_open(reconnect_get_name(rconn
->reconnect
),
462 &rconn
->rstream
->stream
, DSCP_DEFAULT
);
467 reconnect_connected(rconn
->reconnect
, time_msec());
471 reconnect_connecting(rconn
->reconnect
, time_msec());
475 reconnect_connect_failed(rconn
->reconnect
, time_msec(), error
);
476 stream_close(rconn
->rstream
->stream
);
477 rconn
->rstream
->stream
= NULL
;
483 case RECONNECT_DISCONNECT
:
484 case RECONNECT_PROBE
:
489 if (reconnect_is_connected(rconn
->reconnect
)) {
492 err
= dummy_packet_stream_run(dev
, rconn
->rstream
);
495 reconnect_disconnected(rconn
->reconnect
, time_msec(), err
);
496 stream_close(rconn
->rstream
->stream
);
497 rconn
->rstream
->stream
= NULL
;
503 dummy_packet_conn_run(struct netdev_dummy
*dev
)
504 OVS_REQUIRES(dev
->mutex
)
506 switch (dev
->conn
.type
) {
508 dummy_pconn_run(dev
);
512 dummy_rconn_run(dev
);
522 dummy_packet_conn_wait(struct dummy_packet_conn
*conn
)
525 switch (conn
->type
) {
527 pstream_wait(conn
->u
.pconn
.pstream
);
528 for (i
= 0; i
< conn
->u
.pconn
.n_streams
; i
++) {
529 struct dummy_packet_stream
*s
= &conn
->u
.pconn
.streams
[i
];
530 dummy_packet_stream_wait(s
);
534 if (reconnect_is_connected(conn
->u
.rconn
.reconnect
)) {
535 dummy_packet_stream_wait(conn
->u
.rconn
.rstream
);
546 dummy_packet_conn_send(struct dummy_packet_conn
*conn
,
547 const void *buffer
, size_t size
)
551 switch (conn
->type
) {
553 for (i
= 0; i
< conn
->u
.pconn
.n_streams
; i
++) {
554 struct dummy_packet_stream
*s
= &conn
->u
.pconn
.streams
[i
];
556 dummy_packet_stream_send(s
, buffer
, size
);
557 pstream_wait(conn
->u
.pconn
.pstream
);
562 if (reconnect_is_connected(conn
->u
.rconn
.reconnect
)) {
563 dummy_packet_stream_send(conn
->u
.rconn
.rstream
, buffer
, size
);
564 dummy_packet_stream_wait(conn
->u
.rconn
.rstream
);
574 static enum dummy_netdev_conn_state
575 dummy_netdev_get_conn_state(struct dummy_packet_conn
*conn
)
577 enum dummy_netdev_conn_state state
;
579 if (conn
->type
== ACTIVE
) {
580 if (reconnect_is_connected(conn
->u
.rconn
.reconnect
)) {
581 state
= CONN_STATE_CONNECTED
;
583 state
= CONN_STATE_NOT_CONNECTED
;
586 state
= CONN_STATE_UNKNOWN
;
593 netdev_dummy_run(void)
595 struct netdev_dummy
*dev
;
597 ovs_mutex_lock(&dummy_list_mutex
);
598 LIST_FOR_EACH (dev
, list_node
, &dummy_list
) {
599 ovs_mutex_lock(&dev
->mutex
);
600 dummy_packet_conn_run(dev
);
601 ovs_mutex_unlock(&dev
->mutex
);
603 ovs_mutex_unlock(&dummy_list_mutex
);
607 netdev_dummy_wait(void)
609 struct netdev_dummy
*dev
;
611 ovs_mutex_lock(&dummy_list_mutex
);
612 LIST_FOR_EACH (dev
, list_node
, &dummy_list
) {
613 ovs_mutex_lock(&dev
->mutex
);
614 dummy_packet_conn_wait(&dev
->conn
);
615 ovs_mutex_unlock(&dev
->mutex
);
617 ovs_mutex_unlock(&dummy_list_mutex
);
620 static struct netdev
*
621 netdev_dummy_alloc(void)
623 struct netdev_dummy
*netdev
= xzalloc(sizeof *netdev
);
628 netdev_dummy_construct(struct netdev
*netdev_
)
630 static atomic_count next_n
= ATOMIC_COUNT_INIT(0xaa550000);
631 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
634 n
= atomic_count_inc(&next_n
);
636 ovs_mutex_init(&netdev
->mutex
);
637 ovs_mutex_lock(&netdev
->mutex
);
638 netdev
->hwaddr
[0] = 0xaa;
639 netdev
->hwaddr
[1] = 0x55;
640 netdev
->hwaddr
[2] = n
>> 24;
641 netdev
->hwaddr
[3] = n
>> 16;
642 netdev
->hwaddr
[4] = n
>> 8;
643 netdev
->hwaddr
[5] = n
;
646 netdev
->ifindex
= -EOPNOTSUPP
;
648 dummy_packet_conn_init(&netdev
->conn
);
650 list_init(&netdev
->rxes
);
651 ovs_mutex_unlock(&netdev
->mutex
);
653 ovs_mutex_lock(&dummy_list_mutex
);
654 list_push_back(&dummy_list
, &netdev
->list_node
);
655 ovs_mutex_unlock(&dummy_list_mutex
);
661 netdev_dummy_destruct(struct netdev
*netdev_
)
663 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
665 ovs_mutex_lock(&dummy_list_mutex
);
666 list_remove(&netdev
->list_node
);
667 ovs_mutex_unlock(&dummy_list_mutex
);
669 ovs_mutex_lock(&netdev
->mutex
);
670 dummy_packet_conn_close(&netdev
->conn
);
671 netdev
->conn
.type
= NONE
;
673 ovs_mutex_unlock(&netdev
->mutex
);
674 ovs_mutex_destroy(&netdev
->mutex
);
678 netdev_dummy_dealloc(struct netdev
*netdev_
)
680 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
686 netdev_dummy_get_config(const struct netdev
*netdev_
, struct smap
*args
)
688 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
690 ovs_mutex_lock(&netdev
->mutex
);
692 if (netdev
->ifindex
>= 0) {
693 smap_add_format(args
, "ifindex", "%d", netdev
->ifindex
);
696 dummy_packet_conn_get_config(&netdev
->conn
, args
);
698 ovs_mutex_unlock(&netdev
->mutex
);
703 netdev_dummy_get_in4(const struct netdev
*netdev_
,
704 struct in_addr
*address
, struct in_addr
*netmask
)
706 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
708 ovs_mutex_lock(&netdev
->mutex
);
709 *address
= netdev
->address
;
710 *netmask
= netdev
->netmask
;
711 ovs_mutex_unlock(&netdev
->mutex
);
716 netdev_dummy_set_in4(struct netdev
*netdev_
, struct in_addr address
,
717 struct in_addr netmask
)
719 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
721 ovs_mutex_lock(&netdev
->mutex
);
722 netdev
->address
= address
;
723 netdev
->netmask
= netmask
;
724 ovs_mutex_unlock(&netdev
->mutex
);
730 netdev_dummy_set_config(struct netdev
*netdev_
, const struct smap
*args
)
732 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
735 ovs_mutex_lock(&netdev
->mutex
);
736 netdev
->ifindex
= smap_get_int(args
, "ifindex", -EOPNOTSUPP
);
738 dummy_packet_conn_set_config(&netdev
->conn
, args
);
740 if (netdev
->rxq_pcap
) {
741 fclose(netdev
->rxq_pcap
);
743 if (netdev
->tx_pcap
&& netdev
->tx_pcap
!= netdev
->rxq_pcap
) {
744 fclose(netdev
->tx_pcap
);
746 netdev
->rxq_pcap
= netdev
->tx_pcap
= NULL
;
747 pcap
= smap_get(args
, "pcap");
749 netdev
->rxq_pcap
= netdev
->tx_pcap
= ovs_pcap_open(pcap
, "ab");
751 const char *rxq_pcap
= smap_get(args
, "rxq_pcap");
752 const char *tx_pcap
= smap_get(args
, "tx_pcap");
755 netdev
->rxq_pcap
= ovs_pcap_open(rxq_pcap
, "ab");
758 netdev
->tx_pcap
= ovs_pcap_open(tx_pcap
, "ab");
762 ovs_mutex_unlock(&netdev
->mutex
);
767 static struct netdev_rxq
*
768 netdev_dummy_rxq_alloc(void)
770 struct netdev_rxq_dummy
*rx
= xzalloc(sizeof *rx
);
775 netdev_dummy_rxq_construct(struct netdev_rxq
*rxq_
)
777 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
778 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
780 ovs_mutex_lock(&netdev
->mutex
);
781 list_push_back(&netdev
->rxes
, &rx
->node
);
782 list_init(&rx
->recv_queue
);
783 rx
->recv_queue_len
= 0;
784 rx
->seq
= seq_create();
785 ovs_mutex_unlock(&netdev
->mutex
);
791 netdev_dummy_rxq_destruct(struct netdev_rxq
*rxq_
)
793 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
794 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
796 ovs_mutex_lock(&netdev
->mutex
);
797 list_remove(&rx
->node
);
798 dp_packet_list_delete(&rx
->recv_queue
);
799 ovs_mutex_unlock(&netdev
->mutex
);
800 seq_destroy(rx
->seq
);
804 netdev_dummy_rxq_dealloc(struct netdev_rxq
*rxq_
)
806 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
812 netdev_dummy_rxq_recv(struct netdev_rxq
*rxq_
, struct dp_packet
**arr
,
815 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
816 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
817 struct dp_packet
*packet
;
819 ovs_mutex_lock(&netdev
->mutex
);
820 if (!list_is_empty(&rx
->recv_queue
)) {
821 packet
= dp_packet_from_list(list_pop_front(&rx
->recv_queue
));
822 rx
->recv_queue_len
--;
826 ovs_mutex_unlock(&netdev
->mutex
);
831 ovs_mutex_lock(&netdev
->mutex
);
832 netdev
->stats
.rx_packets
++;
833 netdev
->stats
.rx_bytes
+= dp_packet_size(packet
);
834 ovs_mutex_unlock(&netdev
->mutex
);
836 dp_packet_pad(packet
);
837 dp_packet_set_dp_hash(packet
, 0);
845 netdev_dummy_rxq_wait(struct netdev_rxq
*rxq_
)
847 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
848 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
849 uint64_t seq
= seq_read(rx
->seq
);
851 ovs_mutex_lock(&netdev
->mutex
);
852 if (!list_is_empty(&rx
->recv_queue
)) {
853 poll_immediate_wake();
855 seq_wait(rx
->seq
, seq
);
857 ovs_mutex_unlock(&netdev
->mutex
);
861 netdev_dummy_rxq_drain(struct netdev_rxq
*rxq_
)
863 struct netdev_rxq_dummy
*rx
= netdev_rxq_dummy_cast(rxq_
);
864 struct netdev_dummy
*netdev
= netdev_dummy_cast(rx
->up
.netdev
);
866 ovs_mutex_lock(&netdev
->mutex
);
867 dp_packet_list_delete(&rx
->recv_queue
);
868 rx
->recv_queue_len
= 0;
869 ovs_mutex_unlock(&netdev
->mutex
);
877 netdev_dummy_send(struct netdev
*netdev
, int qid OVS_UNUSED
,
878 struct dp_packet
**pkts
, int cnt
, bool may_steal
)
880 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
884 for (i
= 0; i
< cnt
; i
++) {
885 const void *buffer
= dp_packet_data(pkts
[i
]);
886 size_t size
= dp_packet_size(pkts
[i
]);
888 if (size
< ETH_HEADER_LEN
) {
892 const struct eth_header
*eth
= buffer
;
895 ovs_mutex_lock(&dev
->mutex
);
896 max_size
= dev
->mtu
+ ETH_HEADER_LEN
;
897 ovs_mutex_unlock(&dev
->mutex
);
899 if (eth
->eth_type
== htons(ETH_TYPE_VLAN
)) {
900 max_size
+= VLAN_HEADER_LEN
;
902 if (size
> max_size
) {
908 ovs_mutex_lock(&dev
->mutex
);
909 dev
->stats
.tx_packets
++;
910 dev
->stats
.tx_bytes
+= size
;
912 dummy_packet_conn_send(&dev
->conn
, buffer
, size
);
915 struct dp_packet packet
;
917 dp_packet_use_const(&packet
, buffer
, size
);
918 ovs_pcap_write(dev
->tx_pcap
, &packet
);
919 fflush(dev
->tx_pcap
);
922 ovs_mutex_unlock(&dev
->mutex
);
926 for (i
= 0; i
< cnt
; i
++) {
927 dp_packet_delete(pkts
[i
]);
935 netdev_dummy_set_etheraddr(struct netdev
*netdev
,
936 const uint8_t mac
[ETH_ADDR_LEN
])
938 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
940 ovs_mutex_lock(&dev
->mutex
);
941 if (!eth_addr_equals(dev
->hwaddr
, mac
)) {
942 memcpy(dev
->hwaddr
, mac
, ETH_ADDR_LEN
);
943 netdev_change_seq_changed(netdev
);
945 ovs_mutex_unlock(&dev
->mutex
);
951 netdev_dummy_get_etheraddr(const struct netdev
*netdev
,
952 uint8_t mac
[ETH_ADDR_LEN
])
954 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
956 ovs_mutex_lock(&dev
->mutex
);
957 memcpy(mac
, dev
->hwaddr
, ETH_ADDR_LEN
);
958 ovs_mutex_unlock(&dev
->mutex
);
964 netdev_dummy_get_mtu(const struct netdev
*netdev
, int *mtup
)
966 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
968 ovs_mutex_lock(&dev
->mutex
);
970 ovs_mutex_unlock(&dev
->mutex
);
976 netdev_dummy_set_mtu(const struct netdev
*netdev
, int mtu
)
978 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
980 ovs_mutex_lock(&dev
->mutex
);
982 ovs_mutex_unlock(&dev
->mutex
);
988 netdev_dummy_get_stats(const struct netdev
*netdev
, struct netdev_stats
*stats
)
990 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
992 ovs_mutex_lock(&dev
->mutex
);
994 ovs_mutex_unlock(&dev
->mutex
);
1000 netdev_dummy_get_ifindex(const struct netdev
*netdev
)
1002 struct netdev_dummy
*dev
= netdev_dummy_cast(netdev
);
1005 ovs_mutex_lock(&dev
->mutex
);
1006 ifindex
= dev
->ifindex
;
1007 ovs_mutex_unlock(&dev
->mutex
);
1013 netdev_dummy_update_flags__(struct netdev_dummy
*netdev
,
1014 enum netdev_flags off
, enum netdev_flags on
,
1015 enum netdev_flags
*old_flagsp
)
1016 OVS_REQUIRES(netdev
->mutex
)
1018 if ((off
| on
) & ~(NETDEV_UP
| NETDEV_PROMISC
)) {
1022 *old_flagsp
= netdev
->flags
;
1023 netdev
->flags
|= on
;
1024 netdev
->flags
&= ~off
;
1025 if (*old_flagsp
!= netdev
->flags
) {
1026 netdev_change_seq_changed(&netdev
->up
);
1033 netdev_dummy_update_flags(struct netdev
*netdev_
,
1034 enum netdev_flags off
, enum netdev_flags on
,
1035 enum netdev_flags
*old_flagsp
)
1037 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
1040 ovs_mutex_lock(&netdev
->mutex
);
1041 error
= netdev_dummy_update_flags__(netdev
, off
, on
, old_flagsp
);
1042 ovs_mutex_unlock(&netdev
->mutex
);
1047 /* Helper functions. */
1049 static const struct netdev_class dummy_class
= {
1056 netdev_dummy_construct
,
1057 netdev_dummy_destruct
,
1058 netdev_dummy_dealloc
,
1059 netdev_dummy_get_config
,
1060 netdev_dummy_set_config
,
1061 NULL
, /* get_tunnel_config */
1062 NULL
, /* build header */
1063 NULL
, /* push header */
1064 NULL
, /* pop header */
1065 NULL
, /* get_numa_id */
1066 NULL
, /* set_multiq */
1068 netdev_dummy_send
, /* send */
1069 NULL
, /* send_wait */
1071 netdev_dummy_set_etheraddr
,
1072 netdev_dummy_get_etheraddr
,
1073 netdev_dummy_get_mtu
,
1074 netdev_dummy_set_mtu
,
1075 netdev_dummy_get_ifindex
,
1076 NULL
, /* get_carrier */
1077 NULL
, /* get_carrier_resets */
1078 NULL
, /* get_miimon */
1079 netdev_dummy_get_stats
,
1081 NULL
, /* get_features */
1082 NULL
, /* set_advertisements */
1084 NULL
, /* set_policing */
1085 NULL
, /* get_qos_types */
1086 NULL
, /* get_qos_capabilities */
1089 NULL
, /* get_queue */
1090 NULL
, /* set_queue */
1091 NULL
, /* delete_queue */
1092 NULL
, /* get_queue_stats */
1093 NULL
, /* queue_dump_start */
1094 NULL
, /* queue_dump_next */
1095 NULL
, /* queue_dump_done */
1096 NULL
, /* dump_queue_stats */
1098 netdev_dummy_get_in4
, /* get_in4 */
1101 NULL
, /* add_router */
1102 NULL
, /* get_next_hop */
1103 NULL
, /* get_status */
1104 NULL
, /* arp_lookup */
1106 netdev_dummy_update_flags
,
1108 netdev_dummy_rxq_alloc
,
1109 netdev_dummy_rxq_construct
,
1110 netdev_dummy_rxq_destruct
,
1111 netdev_dummy_rxq_dealloc
,
1112 netdev_dummy_rxq_recv
,
1113 netdev_dummy_rxq_wait
,
1114 netdev_dummy_rxq_drain
,
1117 static struct dp_packet
*
1118 eth_from_packet_or_flow(const char *s
)
1120 enum odp_key_fitness fitness
;
1121 struct dp_packet
*packet
;
1122 struct ofpbuf odp_key
;
1126 if (!eth_from_hex(s
, &packet
)) {
1130 /* Convert string to datapath key.
1132 * It would actually be nicer to parse an OpenFlow-like flow key here, but
1133 * the code for that currently calls exit() on parse error. We have to
1134 * settle for parsing a datapath key for now.
1136 ofpbuf_init(&odp_key
, 0);
1137 error
= odp_flow_from_string(s
, NULL
, &odp_key
, NULL
);
1139 ofpbuf_uninit(&odp_key
);
1143 /* Convert odp_key to flow. */
1144 fitness
= odp_flow_key_to_flow(odp_key
.data
, odp_key
.size
, &flow
);
1145 if (fitness
== ODP_FIT_ERROR
) {
1146 ofpbuf_uninit(&odp_key
);
1150 packet
= dp_packet_new(0);
1151 flow_compose(packet
, &flow
);
1153 ofpbuf_uninit(&odp_key
);
1158 netdev_dummy_queue_packet__(struct netdev_rxq_dummy
*rx
, struct dp_packet
*packet
)
1160 list_push_back(&rx
->recv_queue
, &packet
->list_node
);
1161 rx
->recv_queue_len
++;
1162 seq_change(rx
->seq
);
1166 netdev_dummy_queue_packet(struct netdev_dummy
*dummy
, struct dp_packet
*packet
)
1167 OVS_REQUIRES(dummy
->mutex
)
1169 struct netdev_rxq_dummy
*rx
, *prev
;
1171 if (dummy
->rxq_pcap
) {
1172 ovs_pcap_write(dummy
->rxq_pcap
, packet
);
1173 fflush(dummy
->rxq_pcap
);
1176 LIST_FOR_EACH (rx
, node
, &dummy
->rxes
) {
1177 if (rx
->recv_queue_len
< NETDEV_DUMMY_MAX_QUEUE
) {
1179 netdev_dummy_queue_packet__(prev
, dp_packet_clone(packet
));
1185 netdev_dummy_queue_packet__(prev
, packet
);
1187 dp_packet_delete(packet
);
1192 netdev_dummy_receive(struct unixctl_conn
*conn
,
1193 int argc
, const char *argv
[], void *aux OVS_UNUSED
)
1195 struct netdev_dummy
*dummy_dev
;
1196 struct netdev
*netdev
;
1199 netdev
= netdev_from_name(argv
[1]);
1200 if (!netdev
|| !is_dummy_class(netdev
->netdev_class
)) {
1201 unixctl_command_reply_error(conn
, "no such dummy netdev");
1204 dummy_dev
= netdev_dummy_cast(netdev
);
1206 for (i
= 2; i
< argc
; i
++) {
1207 struct dp_packet
*packet
;
1209 packet
= eth_from_packet_or_flow(argv
[i
]);
1211 unixctl_command_reply_error(conn
, "bad packet syntax");
1215 ovs_mutex_lock(&dummy_dev
->mutex
);
1216 netdev_dummy_queue_packet(dummy_dev
, packet
);
1217 ovs_mutex_unlock(&dummy_dev
->mutex
);
1220 unixctl_command_reply(conn
, NULL
);
1223 netdev_close(netdev
);
1227 netdev_dummy_set_admin_state__(struct netdev_dummy
*dev
, bool admin_state
)
1228 OVS_REQUIRES(dev
->mutex
)
1230 enum netdev_flags old_flags
;
1233 netdev_dummy_update_flags__(dev
, 0, NETDEV_UP
, &old_flags
);
1235 netdev_dummy_update_flags__(dev
, NETDEV_UP
, 0, &old_flags
);
1240 netdev_dummy_set_admin_state(struct unixctl_conn
*conn
, int argc
,
1241 const char *argv
[], void *aux OVS_UNUSED
)
1245 if (!strcasecmp(argv
[argc
- 1], "up")) {
1247 } else if ( !strcasecmp(argv
[argc
- 1], "down")) {
1250 unixctl_command_reply_error(conn
, "Invalid Admin State");
1255 struct netdev
*netdev
= netdev_from_name(argv
[1]);
1256 if (netdev
&& is_dummy_class(netdev
->netdev_class
)) {
1257 struct netdev_dummy
*dummy_dev
= netdev_dummy_cast(netdev
);
1259 ovs_mutex_lock(&dummy_dev
->mutex
);
1260 netdev_dummy_set_admin_state__(dummy_dev
, up
);
1261 ovs_mutex_unlock(&dummy_dev
->mutex
);
1263 netdev_close(netdev
);
1265 unixctl_command_reply_error(conn
, "Unknown Dummy Interface");
1266 netdev_close(netdev
);
1270 struct netdev_dummy
*netdev
;
1272 ovs_mutex_lock(&dummy_list_mutex
);
1273 LIST_FOR_EACH (netdev
, list_node
, &dummy_list
) {
1274 ovs_mutex_lock(&netdev
->mutex
);
1275 netdev_dummy_set_admin_state__(netdev
, up
);
1276 ovs_mutex_unlock(&netdev
->mutex
);
1278 ovs_mutex_unlock(&dummy_list_mutex
);
1280 unixctl_command_reply(conn
, "OK");
1284 display_conn_state__(struct ds
*s
, const char *name
,
1285 enum dummy_netdev_conn_state state
)
1287 ds_put_format(s
, "%s: ", name
);
1290 case CONN_STATE_CONNECTED
:
1291 ds_put_cstr(s
, "connected\n");
1294 case CONN_STATE_NOT_CONNECTED
:
1295 ds_put_cstr(s
, "disconnected\n");
1298 case CONN_STATE_UNKNOWN
:
1300 ds_put_cstr(s
, "unknown\n");
1306 netdev_dummy_conn_state(struct unixctl_conn
*conn
, int argc
,
1307 const char *argv
[], void *aux OVS_UNUSED
)
1309 enum dummy_netdev_conn_state state
= CONN_STATE_UNKNOWN
;
1315 const char *dev_name
= argv
[1];
1316 struct netdev
*netdev
= netdev_from_name(dev_name
);
1318 if (netdev
&& is_dummy_class(netdev
->netdev_class
)) {
1319 struct netdev_dummy
*dummy_dev
= netdev_dummy_cast(netdev
);
1321 ovs_mutex_lock(&dummy_dev
->mutex
);
1322 state
= dummy_netdev_get_conn_state(&dummy_dev
->conn
);
1323 ovs_mutex_unlock(&dummy_dev
->mutex
);
1325 netdev_close(netdev
);
1327 display_conn_state__(&s
, dev_name
, state
);
1329 struct netdev_dummy
*netdev
;
1331 ovs_mutex_lock(&dummy_list_mutex
);
1332 LIST_FOR_EACH (netdev
, list_node
, &dummy_list
) {
1333 ovs_mutex_lock(&netdev
->mutex
);
1334 state
= dummy_netdev_get_conn_state(&netdev
->conn
);
1335 ovs_mutex_unlock(&netdev
->mutex
);
1336 if (state
!= CONN_STATE_UNKNOWN
) {
1337 display_conn_state__(&s
, netdev
->up
.name
, state
);
1340 ovs_mutex_unlock(&dummy_list_mutex
);
1343 unixctl_command_reply(conn
, ds_cstr(&s
));
1348 netdev_dummy_ip4addr(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
1349 const char *argv
[], void *aux OVS_UNUSED
)
1351 struct netdev
*netdev
= netdev_from_name(argv
[1]);
1353 if (netdev
&& is_dummy_class(netdev
->netdev_class
)) {
1357 if (ovs_scan(argv
[2], IP_SCAN_FMT
"/%"SCNi16
,
1358 IP_SCAN_ARGS(&ip
.s_addr
), &plen
)) {
1359 struct in_addr mask
;
1361 mask
.s_addr
= be32_prefix_mask(plen
);
1362 netdev_dummy_set_in4(netdev
, ip
, mask
);
1363 unixctl_command_reply(conn
, "OK");
1365 unixctl_command_reply(conn
, "Invalid parameters");
1368 netdev_close(netdev
);
1370 unixctl_command_reply_error(conn
, "Unknown Dummy Interface");
1371 netdev_close(netdev
);
1378 netdev_dummy_register(bool override
)
1380 unixctl_command_register("netdev-dummy/receive", "name packet|flow...",
1381 2, INT_MAX
, netdev_dummy_receive
, NULL
);
1382 unixctl_command_register("netdev-dummy/set-admin-state",
1383 "[netdev] up|down", 1, 2,
1384 netdev_dummy_set_admin_state
, NULL
);
1385 unixctl_command_register("netdev-dummy/conn-state",
1387 netdev_dummy_conn_state
, NULL
);
1388 unixctl_command_register("netdev-dummy/ip4addr",
1389 "[netdev] ipaddr/mask-prefix-len", 2, 2,
1390 netdev_dummy_ip4addr
, NULL
);
1398 netdev_enumerate_types(&types
);
1399 SSET_FOR_EACH (type
, &types
) {
1400 if (!strcmp(type
, "patch")) {
1403 if (!netdev_unregister_provider(type
)) {
1404 struct netdev_class
*class;
1407 class = xmemdup(&dummy_class
, sizeof dummy_class
);
1408 class->type
= xstrdup(type
);
1409 error
= netdev_register_provider(class);
1411 VLOG_ERR("%s: failed to register netdev provider (%s)",
1412 type
, ovs_strerror(error
));
1413 free(CONST_CAST(char *, class->type
));
1418 sset_destroy(&types
);
1420 netdev_register_provider(&dummy_class
);
1422 netdev_vport_tunnel_register();