2 * Copyright (c) 2010, 2011, 2012 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"
27 #include "ofp-print.h"
30 #include "poll-loop.h"
36 VLOG_DEFINE_THIS_MODULE(netdev_dummy
);
38 struct netdev_dev_dummy
{
39 struct netdev_dev netdev_dev
;
40 uint8_t hwaddr
[ETH_ADDR_LEN
];
42 struct netdev_stats stats
;
43 enum netdev_flags flags
;
44 unsigned int change_seq
;
46 struct list devs
; /* List of child "netdev_dummy"s. */
51 struct list node
; /* In netdev_dev_dummy's "devs" list. */
52 struct list recv_queue
;
56 static struct shash dummy_netdev_devs
= SHASH_INITIALIZER(&dummy_netdev_devs
);
58 static int netdev_dummy_create(const struct netdev_class
*, const char *,
59 struct netdev_dev
**);
60 static void netdev_dummy_poll_notify(const struct netdev
*);
63 is_dummy_class(const struct netdev_class
*class)
65 return class->create
== netdev_dummy_create
;
68 static struct netdev_dev_dummy
*
69 netdev_dev_dummy_cast(const struct netdev_dev
*netdev_dev
)
71 assert(is_dummy_class(netdev_dev_get_class(netdev_dev
)));
72 return CONTAINER_OF(netdev_dev
, struct netdev_dev_dummy
, netdev_dev
);
75 static struct netdev_dummy
*
76 netdev_dummy_cast(const struct netdev
*netdev
)
78 struct netdev_dev
*netdev_dev
= netdev_get_dev(netdev
);
79 assert(is_dummy_class(netdev_dev_get_class(netdev_dev
)));
80 return CONTAINER_OF(netdev
, struct netdev_dummy
, netdev
);
84 netdev_dummy_create(const struct netdev_class
*class, const char *name
,
85 struct netdev_dev
**netdev_devp
)
87 static unsigned int n
= 0xaa550000;
88 struct netdev_dev_dummy
*netdev_dev
;
90 netdev_dev
= xzalloc(sizeof *netdev_dev
);
91 netdev_dev_init(&netdev_dev
->netdev_dev
, name
, class);
92 netdev_dev
->hwaddr
[0] = 0xaa;
93 netdev_dev
->hwaddr
[1] = 0x55;
94 netdev_dev
->hwaddr
[2] = n
>> 24;
95 netdev_dev
->hwaddr
[3] = n
>> 16;
96 netdev_dev
->hwaddr
[4] = n
>> 8;
97 netdev_dev
->hwaddr
[5] = n
;
98 netdev_dev
->mtu
= 1500;
99 netdev_dev
->flags
= 0;
100 netdev_dev
->change_seq
= 1;
101 list_init(&netdev_dev
->devs
);
103 shash_add(&dummy_netdev_devs
, name
, netdev_dev
);
107 *netdev_devp
= &netdev_dev
->netdev_dev
;
113 netdev_dummy_destroy(struct netdev_dev
*netdev_dev_
)
115 struct netdev_dev_dummy
*netdev_dev
= netdev_dev_dummy_cast(netdev_dev_
);
117 shash_find_and_delete(&dummy_netdev_devs
,
118 netdev_dev_get_name(netdev_dev_
));
123 netdev_dummy_open(struct netdev_dev
*netdev_dev_
, struct netdev
**netdevp
)
125 struct netdev_dev_dummy
*netdev_dev
= netdev_dev_dummy_cast(netdev_dev_
);
126 struct netdev_dummy
*netdev
;
128 netdev
= xmalloc(sizeof *netdev
);
129 netdev_init(&netdev
->netdev
, netdev_dev_
);
130 list_init(&netdev
->recv_queue
);
131 netdev
->listening
= false;
133 *netdevp
= &netdev
->netdev
;
134 list_push_back(&netdev_dev
->devs
, &netdev
->node
);
139 netdev_dummy_close(struct netdev
*netdev_
)
141 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
142 list_remove(&netdev
->node
);
143 ofpbuf_list_delete(&netdev
->recv_queue
);
148 netdev_dummy_listen(struct netdev
*netdev_
)
150 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
151 netdev
->listening
= true;
156 netdev_dummy_recv(struct netdev
*netdev_
, void *buffer
, size_t size
)
158 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
159 struct ofpbuf
*packet
;
162 if (list_is_empty(&netdev
->recv_queue
)) {
166 packet
= ofpbuf_from_list(list_pop_front(&netdev
->recv_queue
));
167 if (packet
->size
> size
) {
170 packet_size
= packet
->size
;
172 memcpy(buffer
, packet
->data
, packet
->size
);
173 ofpbuf_delete(packet
);
179 netdev_dummy_recv_wait(struct netdev
*netdev_
)
181 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
182 if (!list_is_empty(&netdev
->recv_queue
)) {
183 poll_immediate_wake();
188 netdev_dummy_drain(struct netdev
*netdev_
)
190 struct netdev_dummy
*netdev
= netdev_dummy_cast(netdev_
);
191 ofpbuf_list_delete(&netdev
->recv_queue
);
196 netdev_dummy_set_etheraddr(struct netdev
*netdev
,
197 const uint8_t mac
[ETH_ADDR_LEN
])
199 struct netdev_dev_dummy
*dev
=
200 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
202 if (!eth_addr_equals(dev
->hwaddr
, mac
)) {
203 memcpy(dev
->hwaddr
, mac
, ETH_ADDR_LEN
);
204 netdev_dummy_poll_notify(netdev
);
211 netdev_dummy_get_etheraddr(const struct netdev
*netdev
,
212 uint8_t mac
[ETH_ADDR_LEN
])
214 const struct netdev_dev_dummy
*dev
=
215 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
217 memcpy(mac
, dev
->hwaddr
, ETH_ADDR_LEN
);
222 netdev_dummy_get_mtu(const struct netdev
*netdev
, int *mtup
)
224 const struct netdev_dev_dummy
*dev
=
225 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
232 netdev_dummy_set_mtu(const struct netdev
*netdev
, int mtu
)
234 struct netdev_dev_dummy
*dev
=
235 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
242 netdev_dummy_get_stats(const struct netdev
*netdev
, struct netdev_stats
*stats
)
244 const struct netdev_dev_dummy
*dev
=
245 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
252 netdev_dummy_set_stats(struct netdev
*netdev
, const struct netdev_stats
*stats
)
254 struct netdev_dev_dummy
*dev
=
255 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
262 netdev_dummy_update_flags(struct netdev
*netdev
,
263 enum netdev_flags off
, enum netdev_flags on
,
264 enum netdev_flags
*old_flagsp
)
266 struct netdev_dev_dummy
*dev
=
267 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
269 if ((off
| on
) & ~(NETDEV_UP
| NETDEV_PROMISC
)) {
273 *old_flagsp
= dev
->flags
;
276 if (*old_flagsp
!= dev
->flags
) {
277 netdev_dummy_poll_notify(netdev
);
283 netdev_dummy_change_seq(const struct netdev
*netdev
)
285 return netdev_dev_dummy_cast(netdev_get_dev(netdev
))->change_seq
;
288 /* Helper functions. */
291 netdev_dummy_poll_notify(const struct netdev
*netdev
)
293 struct netdev_dev_dummy
*dev
=
294 netdev_dev_dummy_cast(netdev_get_dev(netdev
));
297 if (!dev
->change_seq
) {
302 static const struct netdev_class dummy_class
= {
309 netdev_dummy_destroy
,
310 NULL
, /* get_config */
311 NULL
, /* set_config */
318 netdev_dummy_recv_wait
,
322 NULL
, /* send_wait */
324 netdev_dummy_set_etheraddr
,
325 netdev_dummy_get_etheraddr
,
326 netdev_dummy_get_mtu
,
327 netdev_dummy_set_mtu
,
328 NULL
, /* get_ifindex */
329 NULL
, /* get_carrier */
330 NULL
, /* get_carrier_resets */
331 NULL
, /* get_miimon */
332 netdev_dummy_get_stats
,
333 netdev_dummy_set_stats
,
335 NULL
, /* get_features */
336 NULL
, /* set_advertisements */
338 NULL
, /* set_policing */
339 NULL
, /* get_qos_types */
340 NULL
, /* get_qos_capabilities */
343 NULL
, /* get_queue */
344 NULL
, /* set_queue */
345 NULL
, /* delete_queue */
346 NULL
, /* get_queue_stats */
347 NULL
, /* dump_queues */
348 NULL
, /* dump_queue_stats */
353 NULL
, /* add_router */
354 NULL
, /* get_next_hop */
355 NULL
, /* get_drv_info */
356 NULL
, /* arp_lookup */
358 netdev_dummy_update_flags
,
360 netdev_dummy_change_seq
363 static struct ofpbuf
*
364 eth_from_packet_or_flow(const char *s
)
366 enum odp_key_fitness fitness
;
367 struct ofpbuf
*packet
;
368 struct ofpbuf odp_key
;
372 if (!eth_from_hex(s
, &packet
)) {
376 /* Convert string to datapath key.
378 * It would actually be nicer to parse an OpenFlow-like flow key here, but
379 * the code for that currently calls exit() on parse error. We have to
380 * settle for parsing a datapath key for now.
382 ofpbuf_init(&odp_key
, 0);
383 error
= odp_flow_key_from_string(s
, NULL
, &odp_key
);
385 ofpbuf_uninit(&odp_key
);
389 /* Convert odp_key to flow. */
390 fitness
= odp_flow_key_to_flow(odp_key
.data
, odp_key
.size
, &flow
);
391 if (fitness
== ODP_FIT_ERROR
) {
392 ofpbuf_uninit(&odp_key
);
396 packet
= ofpbuf_new(0);
397 flow_compose(packet
, &flow
);
399 ofpbuf_uninit(&odp_key
);
404 netdev_dummy_receive(struct unixctl_conn
*conn
,
405 int argc
, const char *argv
[], void *aux OVS_UNUSED
)
407 struct netdev_dev_dummy
*dummy_dev
;
411 dummy_dev
= shash_find_data(&dummy_netdev_devs
, argv
[1]);
413 unixctl_command_reply_error(conn
, "no such dummy netdev");
418 for (i
= 2; i
< argc
; i
++) {
419 struct netdev_dummy
*dev
;
420 struct ofpbuf
*packet
;
422 packet
= eth_from_packet_or_flow(argv
[i
]);
424 unixctl_command_reply_error(conn
, "bad packet syntax");
429 LIST_FOR_EACH (dev
, node
, &dummy_dev
->devs
) {
430 if (dev
->listening
) {
431 struct ofpbuf
*copy
= ofpbuf_clone(packet
);
432 list_push_back(&dev
->recv_queue
, ©
->list_node
);
436 ofpbuf_delete(packet
);
440 unixctl_command_reply(conn
, "packets queued but nobody listened");
442 unixctl_command_reply(conn
, "success");
447 netdev_dummy_register(bool override
)
449 unixctl_command_register("netdev-dummy/receive", "NAME PACKET|FLOW...",
450 2, INT_MAX
, netdev_dummy_receive
, NULL
);
457 netdev_enumerate_types(&types
);
458 SSET_FOR_EACH (type
, &types
) {
459 if (!netdev_unregister_provider(type
)) {
460 struct netdev_class
*class;
462 class = xmalloc(sizeof *class);
463 *class = dummy_class
;
464 class->type
= xstrdup(type
);
465 netdev_register_provider(class);
468 sset_destroy(&types
);
470 netdev_register_provider(&dummy_class
);