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.
25 #include "netdev-provider.h"
26 #include "netdev-vport.h"
28 #include "ofp-print.h"
31 #include "poll-loop.h"
37 VLOG_DEFINE_THIS_MODULE(netdev_dummy
);
45 struct netdev_dev_dummy
{
47 uint8_t hwaddr
[ETH_ADDR_LEN
];
49 struct netdev_stats stats
;
50 enum netdev_flags flags
;
51 unsigned int change_seq
;
54 struct list rxes
; /* List of child "netdev_rx_dummy"s. */
61 struct netdev_rx_dummy
{
63 struct list node
; /* In netdev_dev_dummy's "rxes" list. */
64 struct list recv_queue
;
67 static struct shash dummy_netdev_devs
= SHASH_INITIALIZER(&dummy_netdev_devs
);
69 static const struct netdev_rx_class netdev_rx_dummy_class
;
71 static unixctl_cb_func netdev_dummy_set_admin_state
;
72 static int netdev_dummy_create(const struct netdev_class
*, const char *,
73 struct netdev_dev
**);
74 static void netdev_dev_dummy_poll_notify(struct netdev_dev_dummy
*);
75 static int netdev_dev_dummy_update_flags(struct netdev_dev_dummy
*,
76 enum netdev_flags off
,
78 enum netdev_flags
*old_flagsp
);
81 is_dummy_class(const struct netdev_class
*class)
83 return class->create
== netdev_dummy_create
;
86 static struct netdev_dev_dummy
*
87 netdev_dev_dummy_cast(const struct netdev_dev
*netdev_dev
)
89 ovs_assert(is_dummy_class(netdev_dev_get_class(netdev_dev
)));
90 return CONTAINER_OF(netdev_dev
, struct netdev_dev_dummy
, up
);
93 static struct netdev_dummy
*
94 netdev_dummy_cast(const struct netdev
*netdev
)
96 struct netdev_dev
*netdev_dev
= netdev_get_dev(netdev
);
97 ovs_assert(is_dummy_class(netdev_dev_get_class(netdev_dev
)));
98 return CONTAINER_OF(netdev
, struct netdev_dummy
, up
);
101 static struct netdev_rx_dummy
*
102 netdev_rx_dummy_cast(const struct netdev_rx
*rx
)
104 netdev_rx_assert_class(rx
, &netdev_rx_dummy_class
);
105 return CONTAINER_OF(rx
, struct netdev_rx_dummy
, up
);
109 netdev_dummy_create(const struct netdev_class
*class, const char *name
,
110 struct netdev_dev
**netdev_devp
)
112 static unsigned int n
= 0xaa550000;
113 struct netdev_dev_dummy
*netdev_dev
;
115 netdev_dev
= xzalloc(sizeof *netdev_dev
);
116 netdev_dev_init(&netdev_dev
->up
, name
, class);
117 netdev_dev
->hwaddr
[0] = 0xaa;
118 netdev_dev
->hwaddr
[1] = 0x55;
119 netdev_dev
->hwaddr
[2] = n
>> 24;
120 netdev_dev
->hwaddr
[3] = n
>> 16;
121 netdev_dev
->hwaddr
[4] = n
>> 8;
122 netdev_dev
->hwaddr
[5] = n
;
123 netdev_dev
->mtu
= 1500;
124 netdev_dev
->flags
= 0;
125 netdev_dev
->change_seq
= 1;
126 netdev_dev
->ifindex
= -EOPNOTSUPP
;
127 list_init(&netdev_dev
->rxes
);
129 shash_add(&dummy_netdev_devs
, name
, netdev_dev
);
133 *netdev_devp
= &netdev_dev
->up
;
139 netdev_dummy_destroy(struct netdev_dev
*netdev_dev_
)
141 struct netdev_dev_dummy
*netdev_dev
= netdev_dev_dummy_cast(netdev_dev_
);
143 shash_find_and_delete(&dummy_netdev_devs
,
144 netdev_dev_get_name(netdev_dev_
));
149 netdev_dummy_get_config(struct netdev_dev
*netdev_dev_
, struct smap
*args
)
151 struct netdev_dev_dummy
*netdev_dev
= netdev_dev_dummy_cast(netdev_dev_
);
153 if (netdev_dev
->ifindex
>= 0) {
154 smap_add_format(args
, "ifindex", "%d", netdev_dev
->ifindex
);
160 netdev_dummy_set_config(struct netdev_dev
*netdev_dev_
,
161 const struct smap
*args
)
163 struct netdev_dev_dummy
*netdev_dev
= netdev_dev_dummy_cast(netdev_dev_
);
165 netdev_dev
->ifindex
= smap_get_int(args
, "ifindex", -EOPNOTSUPP
);
170 netdev_dummy_open(struct netdev_dev
*netdev_dev_
, struct netdev
**netdevp
)
172 struct netdev_dummy
*netdev
;
174 netdev
= xmalloc(sizeof *netdev
);
175 netdev_init(&netdev
->up
, netdev_dev_
);
177 *netdevp
= &netdev
->up
;
182 netdev_dummy_close(struct netdev
*netdev_
)
184 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
189 netdev_dummy_rx_open(struct netdev
*netdev_
, struct netdev_rx
**rxp
)
191 struct netdev_dev_dummy
*dev
192 = netdev_dev_dummy_cast(netdev_get_dev(netdev_
));
193 struct netdev_rx_dummy
*rx
;
195 rx
= xmalloc(sizeof *rx
);
196 netdev_rx_init(&rx
->up
, &dev
->up
, &netdev_rx_dummy_class
);
197 list_push_back(&dev
->rxes
, &rx
->node
);
198 list_init(&rx
->recv_queue
);
205 netdev_rx_dummy_recv(struct netdev_rx
*rx_
, void *buffer
, size_t size
)
207 struct netdev_rx_dummy
*rx
= netdev_rx_dummy_cast(rx_
);
208 struct ofpbuf
*packet
;
211 if (list_is_empty(&rx
->recv_queue
)) {
215 packet
= ofpbuf_from_list(list_pop_front(&rx
->recv_queue
));
216 if (packet
->size
> size
) {
219 packet_size
= packet
->size
;
221 memcpy(buffer
, packet
->data
, packet
->size
);
222 ofpbuf_delete(packet
);
228 netdev_rx_dummy_destroy(struct netdev_rx
*rx_
)
230 struct netdev_rx_dummy
*rx
= netdev_rx_dummy_cast(rx_
);
231 list_remove(&rx
->node
);
232 ofpbuf_list_delete(&rx
->recv_queue
);
237 netdev_rx_dummy_wait(struct netdev_rx
*rx_
)
239 struct netdev_rx_dummy
*rx
= netdev_rx_dummy_cast(rx_
);
240 if (!list_is_empty(&rx
->recv_queue
)) {
241 poll_immediate_wake();
246 netdev_rx_dummy_drain(struct netdev_rx
*rx_
)
248 struct netdev_rx_dummy
*rx
= netdev_rx_dummy_cast(rx_
);
249 ofpbuf_list_delete(&rx
->recv_queue
);
254 netdev_dummy_send(struct netdev
*netdev
, const void *buffer OVS_UNUSED
,
257 struct netdev_dev_dummy
*dev
=
258 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
260 dev
->stats
.tx_packets
++;
261 dev
->stats
.tx_bytes
+= size
;
267 netdev_dummy_set_etheraddr(struct netdev
*netdev
,
268 const uint8_t mac
[ETH_ADDR_LEN
])
270 struct netdev_dev_dummy
*dev
=
271 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
273 if (!eth_addr_equals(dev
->hwaddr
, mac
)) {
274 memcpy(dev
->hwaddr
, mac
, ETH_ADDR_LEN
);
275 netdev_dev_dummy_poll_notify(dev
);
282 netdev_dummy_get_etheraddr(const struct netdev
*netdev
,
283 uint8_t mac
[ETH_ADDR_LEN
])
285 const struct netdev_dev_dummy
*dev
=
286 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
288 memcpy(mac
, dev
->hwaddr
, ETH_ADDR_LEN
);
293 netdev_dummy_get_mtu(const struct netdev
*netdev
, int *mtup
)
295 const struct netdev_dev_dummy
*dev
=
296 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
303 netdev_dummy_set_mtu(const struct netdev
*netdev
, int mtu
)
305 struct netdev_dev_dummy
*dev
=
306 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
313 netdev_dummy_get_stats(const struct netdev
*netdev
, struct netdev_stats
*stats
)
315 const struct netdev_dev_dummy
*dev
=
316 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
323 netdev_dummy_set_stats(struct netdev
*netdev
, const struct netdev_stats
*stats
)
325 struct netdev_dev_dummy
*dev
=
326 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
333 netdev_dummy_get_ifindex(const struct netdev
*netdev
)
335 struct netdev_dev_dummy
*dev
=
336 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
342 netdev_dummy_update_flags(struct netdev_dev
*dev_
,
343 enum netdev_flags off
, enum netdev_flags on
,
344 enum netdev_flags
*old_flagsp
)
346 struct netdev_dev_dummy
*dev
= netdev_dev_dummy_cast(dev_
);
348 return netdev_dev_dummy_update_flags(dev
, off
, on
, old_flagsp
);
352 netdev_dev_dummy_update_flags(struct netdev_dev_dummy
*dev
,
353 enum netdev_flags off
, enum netdev_flags on
,
354 enum netdev_flags
*old_flagsp
)
356 if ((off
| on
) & ~(NETDEV_UP
| NETDEV_PROMISC
)) {
360 *old_flagsp
= dev
->flags
;
363 if (*old_flagsp
!= dev
->flags
) {
364 netdev_dev_dummy_poll_notify(dev
);
370 netdev_dummy_change_seq(const struct netdev
*netdev
)
372 return netdev_dev_dummy_cast(netdev_get_dev(netdev
))->change_seq
;
375 /* Helper functions. */
378 netdev_dev_dummy_poll_notify(struct netdev_dev_dummy
*dev
)
381 if (!dev
->change_seq
) {
386 static const struct netdev_class dummy_class
= {
393 netdev_dummy_destroy
,
394 netdev_dummy_get_config
,
395 netdev_dummy_set_config
,
396 NULL
, /* get_tunnel_config */
401 netdev_dummy_rx_open
,
403 netdev_dummy_send
, /* send */
404 NULL
, /* send_wait */
406 netdev_dummy_set_etheraddr
,
407 netdev_dummy_get_etheraddr
,
408 netdev_dummy_get_mtu
,
409 netdev_dummy_set_mtu
,
410 netdev_dummy_get_ifindex
,
411 NULL
, /* get_carrier */
412 NULL
, /* get_carrier_resets */
413 NULL
, /* get_miimon */
414 netdev_dummy_get_stats
,
415 netdev_dummy_set_stats
,
417 NULL
, /* get_features */
418 NULL
, /* set_advertisements */
420 NULL
, /* set_policing */
421 NULL
, /* get_qos_types */
422 NULL
, /* get_qos_capabilities */
425 NULL
, /* get_queue */
426 NULL
, /* set_queue */
427 NULL
, /* delete_queue */
428 NULL
, /* get_queue_stats */
429 NULL
, /* dump_queues */
430 NULL
, /* dump_queue_stats */
435 NULL
, /* add_router */
436 NULL
, /* get_next_hop */
437 NULL
, /* get_status */
438 NULL
, /* arp_lookup */
440 netdev_dummy_update_flags
,
442 netdev_dummy_change_seq
445 static const struct netdev_rx_class netdev_rx_dummy_class
= {
446 netdev_rx_dummy_destroy
,
447 netdev_rx_dummy_recv
,
448 netdev_rx_dummy_wait
,
449 netdev_rx_dummy_drain
,
452 static struct ofpbuf
*
453 eth_from_packet_or_flow(const char *s
)
455 enum odp_key_fitness fitness
;
456 struct ofpbuf
*packet
;
457 struct ofpbuf odp_key
;
461 if (!eth_from_hex(s
, &packet
)) {
465 /* Convert string to datapath key.
467 * It would actually be nicer to parse an OpenFlow-like flow key here, but
468 * the code for that currently calls exit() on parse error. We have to
469 * settle for parsing a datapath key for now.
471 ofpbuf_init(&odp_key
, 0);
472 error
= odp_flow_key_from_string(s
, NULL
, &odp_key
);
474 ofpbuf_uninit(&odp_key
);
478 /* Convert odp_key to flow. */
479 fitness
= odp_flow_key_to_flow(odp_key
.data
, odp_key
.size
, &flow
);
480 if (fitness
== ODP_FIT_ERROR
) {
481 ofpbuf_uninit(&odp_key
);
485 packet
= ofpbuf_new(0);
486 flow_compose(packet
, &flow
);
488 ofpbuf_uninit(&odp_key
);
493 netdev_dummy_receive(struct unixctl_conn
*conn
,
494 int argc
, const char *argv
[], void *aux OVS_UNUSED
)
496 struct netdev_dev_dummy
*dummy_dev
;
500 dummy_dev
= shash_find_data(&dummy_netdev_devs
, argv
[1]);
502 unixctl_command_reply_error(conn
, "no such dummy netdev");
507 for (i
= 2; i
< argc
; i
++) {
508 struct netdev_rx_dummy
*rx
;
509 struct ofpbuf
*packet
;
511 packet
= eth_from_packet_or_flow(argv
[i
]);
513 unixctl_command_reply_error(conn
, "bad packet syntax");
517 dummy_dev
->stats
.rx_packets
++;
518 dummy_dev
->stats
.rx_bytes
+= packet
->size
;
521 LIST_FOR_EACH (rx
, node
, &dummy_dev
->rxes
) {
522 struct ofpbuf
*copy
= ofpbuf_clone(packet
);
523 list_push_back(&rx
->recv_queue
, ©
->list_node
);
526 ofpbuf_delete(packet
);
530 unixctl_command_reply(conn
, "packets queued but nobody listened");
532 unixctl_command_reply(conn
, "success");
537 netdev_dev_dummy_set_admin_state(struct netdev_dev_dummy
*dev
,
540 enum netdev_flags old_flags
;
543 netdev_dev_dummy_update_flags(dev
, 0, NETDEV_UP
, &old_flags
);
545 netdev_dev_dummy_update_flags(dev
, NETDEV_UP
, 0, &old_flags
);
550 netdev_dummy_set_admin_state(struct unixctl_conn
*conn
, int argc
,
551 const char *argv
[], void *aux OVS_UNUSED
)
555 if (!strcasecmp(argv
[argc
- 1], "up")) {
557 } else if ( !strcasecmp(argv
[argc
- 1], "down")) {
560 unixctl_command_reply_error(conn
, "Invalid Admin State");
565 struct netdev_dev_dummy
*dummy_dev
;
567 dummy_dev
= shash_find_data(&dummy_netdev_devs
, argv
[1]);
569 netdev_dev_dummy_set_admin_state(dummy_dev
, up
);
571 unixctl_command_reply_error(conn
, "Unknown Dummy Interface");
575 struct shash_node
*node
;
577 SHASH_FOR_EACH (node
, &dummy_netdev_devs
) {
578 netdev_dev_dummy_set_admin_state(node
->data
, up
);
581 unixctl_command_reply(conn
, "OK");
585 netdev_dummy_register(bool override
)
587 unixctl_command_register("netdev-dummy/receive", "NAME PACKET|FLOW...",
588 2, INT_MAX
, netdev_dummy_receive
, NULL
);
589 unixctl_command_register("netdev-dummy/set-admin-state",
590 "[netdev] up|down", 1, 2,
591 netdev_dummy_set_admin_state
, NULL
);
598 netdev_enumerate_types(&types
);
599 SSET_FOR_EACH (type
, &types
) {
600 if (!netdev_unregister_provider(type
)) {
601 struct netdev_class
*class;
603 class = xmalloc(sizeof *class);
604 *class = dummy_class
;
605 class->type
= xstrdup(type
);
606 netdev_register_provider(class);
609 sset_destroy(&types
);
611 netdev_register_provider(&dummy_class
);
614 netdev_vport_tunnel_register();