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);
41 uint8_t hwaddr[ETH_ADDR_LEN];
43 struct netdev_stats stats;
44 enum netdev_flags flags;
45 unsigned int change_seq;
48 struct list rxes; /* List of child "netdev_rx_dummy"s. */
51 struct netdev_rx_dummy {
53 struct list node; /* In netdev_dummy's "rxes" list. */
54 struct list recv_queue;
57 static struct shash dummy_netdevs = SHASH_INITIALIZER(&dummy_netdevs);
59 static const struct netdev_rx_class netdev_rx_dummy_class;
61 static unixctl_cb_func netdev_dummy_set_admin_state;
62 static int netdev_dummy_create(const struct netdev_class *, const char *,
64 static void netdev_dummy_poll_notify(struct netdev_dummy *);
67 is_dummy_class(const struct netdev_class *class)
69 return class->create == netdev_dummy_create;
72 static struct netdev_dummy *
73 netdev_dummy_cast(const struct netdev *netdev)
75 ovs_assert(is_dummy_class(netdev_get_class(netdev)));
76 return CONTAINER_OF(netdev, struct netdev_dummy, up);
79 static struct netdev_rx_dummy *
80 netdev_rx_dummy_cast(const struct netdev_rx *rx)
82 netdev_rx_assert_class(rx, &netdev_rx_dummy_class);
83 return CONTAINER_OF(rx, struct netdev_rx_dummy, up);
87 netdev_dummy_create(const struct netdev_class *class, const char *name,
88 struct netdev **netdevp)
90 static unsigned int n = 0xaa550000;
91 struct netdev_dummy *netdev;
93 netdev = xzalloc(sizeof *netdev);
94 netdev_init(&netdev->up, name, class);
95 netdev->hwaddr[0] = 0xaa;
96 netdev->hwaddr[1] = 0x55;
97 netdev->hwaddr[2] = n >> 24;
98 netdev->hwaddr[3] = n >> 16;
99 netdev->hwaddr[4] = n >> 8;
100 netdev->hwaddr[5] = n;
103 netdev->change_seq = 1;
104 netdev->ifindex = -EOPNOTSUPP;
105 list_init(&netdev->rxes);
107 shash_add(&dummy_netdevs, name, netdev);
111 *netdevp = &netdev->up;
117 netdev_dummy_destroy(struct netdev *netdev_)
119 struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
121 shash_find_and_delete(&dummy_netdevs,
122 netdev_get_name(netdev_));
127 netdev_dummy_get_config(const struct netdev *netdev_, struct smap *args)
129 struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
131 if (netdev->ifindex >= 0) {
132 smap_add_format(args, "ifindex", "%d", netdev->ifindex);
138 netdev_dummy_set_config(struct netdev *netdev_, const struct smap *args)
140 struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
142 netdev->ifindex = smap_get_int(args, "ifindex", -EOPNOTSUPP);
147 netdev_dummy_rx_open(struct netdev *netdev_, struct netdev_rx **rxp)
149 struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
150 struct netdev_rx_dummy *rx;
152 rx = xmalloc(sizeof *rx);
153 netdev_rx_init(&rx->up, &netdev->up, &netdev_rx_dummy_class);
154 list_push_back(&netdev->rxes, &rx->node);
155 list_init(&rx->recv_queue);
162 netdev_rx_dummy_recv(struct netdev_rx *rx_, void *buffer, size_t size)
164 struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
165 struct ofpbuf *packet;
168 if (list_is_empty(&rx->recv_queue)) {
172 packet = ofpbuf_from_list(list_pop_front(&rx->recv_queue));
173 if (packet->size > size) {
176 packet_size = packet->size;
178 memcpy(buffer, packet->data, packet->size);
179 ofpbuf_delete(packet);
185 netdev_rx_dummy_destroy(struct netdev_rx *rx_)
187 struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
188 list_remove(&rx->node);
189 ofpbuf_list_delete(&rx->recv_queue);
194 netdev_rx_dummy_wait(struct netdev_rx *rx_)
196 struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
197 if (!list_is_empty(&rx->recv_queue)) {
198 poll_immediate_wake();
203 netdev_rx_dummy_drain(struct netdev_rx *rx_)
205 struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
206 ofpbuf_list_delete(&rx->recv_queue);
211 netdev_dummy_send(struct netdev *netdev, const void *buffer OVS_UNUSED,
214 struct netdev_dummy *dev = netdev_dummy_cast(netdev);
216 dev->stats.tx_packets++;
217 dev->stats.tx_bytes += size;
223 netdev_dummy_set_etheraddr(struct netdev *netdev,
224 const uint8_t mac[ETH_ADDR_LEN])
226 struct netdev_dummy *dev = netdev_dummy_cast(netdev);
228 if (!eth_addr_equals(dev->hwaddr, mac)) {
229 memcpy(dev->hwaddr, mac, ETH_ADDR_LEN);
230 netdev_dummy_poll_notify(dev);
237 netdev_dummy_get_etheraddr(const struct netdev *netdev,
238 uint8_t mac[ETH_ADDR_LEN])
240 const struct netdev_dummy *dev = netdev_dummy_cast(netdev);
242 memcpy(mac, dev->hwaddr, ETH_ADDR_LEN);
247 netdev_dummy_get_mtu(const struct netdev *netdev, int *mtup)
249 const struct netdev_dummy *dev = netdev_dummy_cast(netdev);
256 netdev_dummy_set_mtu(const struct netdev *netdev, int mtu)
258 struct netdev_dummy *dev = netdev_dummy_cast(netdev);
265 netdev_dummy_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
267 const struct netdev_dummy *dev = netdev_dummy_cast(netdev);
274 netdev_dummy_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
276 struct netdev_dummy *dev = netdev_dummy_cast(netdev);
283 netdev_dummy_get_ifindex(const struct netdev *netdev)
285 struct netdev_dummy *dev = netdev_dummy_cast(netdev);
291 netdev_dummy_update_flags(struct netdev *netdev_,
292 enum netdev_flags off, enum netdev_flags on,
293 enum netdev_flags *old_flagsp)
295 struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
297 if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {
301 *old_flagsp = netdev->flags;
303 netdev->flags &= ~off;
304 if (*old_flagsp != netdev->flags) {
305 netdev_dummy_poll_notify(netdev);
311 netdev_dummy_change_seq(const struct netdev *netdev)
313 return netdev_dummy_cast(netdev)->change_seq;
316 /* Helper functions. */
319 netdev_dummy_poll_notify(struct netdev_dummy *dev)
322 if (!dev->change_seq) {
327 static const struct netdev_class dummy_class = {
334 netdev_dummy_destroy,
335 netdev_dummy_get_config,
336 netdev_dummy_set_config,
337 NULL, /* get_tunnel_config */
339 netdev_dummy_rx_open,
341 netdev_dummy_send, /* send */
342 NULL, /* send_wait */
344 netdev_dummy_set_etheraddr,
345 netdev_dummy_get_etheraddr,
346 netdev_dummy_get_mtu,
347 netdev_dummy_set_mtu,
348 netdev_dummy_get_ifindex,
349 NULL, /* get_carrier */
350 NULL, /* get_carrier_resets */
351 NULL, /* get_miimon */
352 netdev_dummy_get_stats,
353 netdev_dummy_set_stats,
355 NULL, /* get_features */
356 NULL, /* set_advertisements */
358 NULL, /* set_policing */
359 NULL, /* get_qos_types */
360 NULL, /* get_qos_capabilities */
363 NULL, /* get_queue */
364 NULL, /* set_queue */
365 NULL, /* delete_queue */
366 NULL, /* get_queue_stats */
367 NULL, /* dump_queues */
368 NULL, /* dump_queue_stats */
373 NULL, /* add_router */
374 NULL, /* get_next_hop */
375 NULL, /* get_status */
376 NULL, /* arp_lookup */
378 netdev_dummy_update_flags,
380 netdev_dummy_change_seq
383 static const struct netdev_rx_class netdev_rx_dummy_class = {
384 netdev_rx_dummy_destroy,
385 netdev_rx_dummy_recv,
386 netdev_rx_dummy_wait,
387 netdev_rx_dummy_drain,
390 static struct ofpbuf *
391 eth_from_packet_or_flow(const char *s)
393 enum odp_key_fitness fitness;
394 struct ofpbuf *packet;
395 struct ofpbuf odp_key;
399 if (!eth_from_hex(s, &packet)) {
403 /* Convert string to datapath key.
405 * It would actually be nicer to parse an OpenFlow-like flow key here, but
406 * the code for that currently calls exit() on parse error. We have to
407 * settle for parsing a datapath key for now.
409 ofpbuf_init(&odp_key, 0);
410 error = odp_flow_key_from_string(s, NULL, &odp_key);
412 ofpbuf_uninit(&odp_key);
416 /* Convert odp_key to flow. */
417 fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
418 if (fitness == ODP_FIT_ERROR) {
419 ofpbuf_uninit(&odp_key);
423 packet = ofpbuf_new(0);
424 flow_compose(packet, &flow);
426 ofpbuf_uninit(&odp_key);
431 netdev_dummy_receive(struct unixctl_conn *conn,
432 int argc, const char *argv[], void *aux OVS_UNUSED)
434 struct netdev_dummy *dummy_dev;
438 dummy_dev = shash_find_data(&dummy_netdevs, argv[1]);
440 unixctl_command_reply_error(conn, "no such dummy netdev");
445 for (i = 2; i < argc; i++) {
446 struct netdev_rx_dummy *rx;
447 struct ofpbuf *packet;
449 packet = eth_from_packet_or_flow(argv[i]);
451 unixctl_command_reply_error(conn, "bad packet syntax");
455 dummy_dev->stats.rx_packets++;
456 dummy_dev->stats.rx_bytes += packet->size;
459 LIST_FOR_EACH (rx, node, &dummy_dev->rxes) {
460 struct ofpbuf *copy = ofpbuf_clone(packet);
461 list_push_back(&rx->recv_queue, ©->list_node);
464 ofpbuf_delete(packet);
468 unixctl_command_reply(conn, "packets queued but nobody listened");
470 unixctl_command_reply(conn, "success");
475 netdev_dummy_set_admin_state__(struct netdev_dummy *dev, bool admin_state)
477 enum netdev_flags old_flags;
480 netdev_dummy_update_flags(&dev->up, 0, NETDEV_UP, &old_flags);
482 netdev_dummy_update_flags(&dev->up, NETDEV_UP, 0, &old_flags);
487 netdev_dummy_set_admin_state(struct unixctl_conn *conn, int argc,
488 const char *argv[], void *aux OVS_UNUSED)
492 if (!strcasecmp(argv[argc - 1], "up")) {
494 } else if ( !strcasecmp(argv[argc - 1], "down")) {
497 unixctl_command_reply_error(conn, "Invalid Admin State");
502 struct netdev_dummy *dummy_dev;
504 dummy_dev = shash_find_data(&dummy_netdevs, argv[1]);
506 netdev_dummy_set_admin_state__(dummy_dev, up);
508 unixctl_command_reply_error(conn, "Unknown Dummy Interface");
512 struct shash_node *node;
514 SHASH_FOR_EACH (node, &dummy_netdevs) {
515 netdev_dummy_set_admin_state__(node->data, up);
518 unixctl_command_reply(conn, "OK");
522 netdev_dummy_register(bool override)
524 unixctl_command_register("netdev-dummy/receive", "NAME PACKET|FLOW...",
525 2, INT_MAX, netdev_dummy_receive, NULL);
526 unixctl_command_register("netdev-dummy/set-admin-state",
527 "[netdev] up|down", 1, 2,
528 netdev_dummy_set_admin_state, NULL);
535 netdev_enumerate_types(&types);
536 SSET_FOR_EACH (type, &types) {
537 if (!netdev_unregister_provider(type)) {
538 struct netdev_class *class;
540 class = xmalloc(sizeof *class);
541 *class = dummy_class;
542 class->type = xstrdup(type);
543 netdev_register_provider(class);
546 sset_destroy(&types);
548 netdev_register_provider(&dummy_class);
550 netdev_vport_tunnel_register();