diff options
| author | Ben Pfaff <blp@nicira.com> | 2010-12-03 14:41:38 -0800 |
|---|---|---|
| committer | Ben Pfaff <blp@nicira.com> | 2010-12-03 14:41:38 -0800 |
| commit | c3827f619a38d3d202020838e1f92860046a3dbe (patch) | |
| tree | 7f4b1c921a95a62ebbbc80ec1af04ae246a9d1fc /lib/netdev-linux.c | |
| parent | 94903c989826268a7fab3c730cd7d0b35ef423d5 (diff) | |
| download | openvswitch-c3827f619a38d3d202020838e1f92860046a3dbe.tar.gz | |
datapath: Make adding and attaching a vport a single step.
For some time now, Open vSwitch datapaths have internally made a
distinction between adding a vport and attaching it to a datapath. Adding
a vport just means to create it, as an entity detached from any datapath.
Attaching it gives it a port number and a datapath. Similarly, a vport
could be detached and deleted separately.
After some study, I think I understand why this distinction exists. It is
because ovs-vswitchd tries to open all the datapath ports before it tries
to create them. However, changing it to create them before it tries to
open them is not difficult, so this commit does this.
The bulk of this commit, however, changes the datapath interface to one
that always creates a vport and attaches it to a datapath in a single step,
and similarly detaches a vport and deletes it in a single step.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'lib/netdev-linux.c')
| -rw-r--r-- | lib/netdev-linux.c | 225 |
1 files changed, 99 insertions, 126 deletions
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index bcd1633e3..cbe4222c7 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -495,9 +495,9 @@ netdev_linux_cache_cb(const struct rtnetlink_change *change, } } -/* Creates the netdev device of 'type' with 'name'. */ +/* Creates system and internal devices. */ static int -netdev_linux_create_system(const struct netdev_class *class OVS_UNUSED, +netdev_linux_create(const struct netdev_class *class, const char *name, const struct shash *args, struct netdev_dev **netdev_devp) { @@ -505,7 +505,8 @@ netdev_linux_create_system(const struct netdev_class *class OVS_UNUSED, int error; if (!shash_is_empty(args)) { - VLOG_WARN("%s: arguments for system devices should be empty", name); + VLOG_WARN("%s: arguments for %s devices should be empty", + name, class->type); } if (!cache_notifier_refcount) { @@ -518,7 +519,7 @@ netdev_linux_create_system(const struct netdev_class *class OVS_UNUSED, cache_notifier_refcount++; netdev_dev = xzalloc(sizeof *netdev_dev); - netdev_dev_init(&netdev_dev->netdev_dev, name, &netdev_linux_class); + netdev_dev_init(&netdev_dev->netdev_dev, name, class); *netdev_devp = &netdev_dev->netdev_dev; return 0; @@ -629,9 +630,19 @@ netdev_linux_open(struct netdev_dev *netdev_dev_, int ethertype, netdev->fd = -1; netdev_init(&netdev->netdev, netdev_dev_); - error = netdev_get_flags(&netdev->netdev, &flags); - if (error == ENODEV) { - goto error; + /* Verify that the device really exists, by attempting to read its flags. + * (The flags might be cached, in which case this won't actually do an + * ioctl.) + * + * Don't do this for "internal" netdevs, though, because those have to be + * created as netdev objects before they exist in the kernel, because + * creating them in the kernel happens by passing a netdev object to + * dpif_port_add(). */ + if (netdev_dev_get_class(netdev_dev_) != &netdev_internal_class) { + error = netdev_get_flags(&netdev->netdev, &flags); + if (error == ENODEV) { + goto error; + } } if (!strcmp(netdev_dev_get_type(netdev_dev_), "tap") && @@ -2107,125 +2118,87 @@ netdev_linux_poll_remove(struct netdev_notifier *notifier_) } } -const struct netdev_class netdev_linux_class = { - "system", - - netdev_linux_init, - netdev_linux_run, - netdev_linux_wait, - - netdev_linux_create_system, - netdev_linux_destroy, - NULL, /* reconfigure */ - - netdev_linux_open, - netdev_linux_close, - - netdev_linux_enumerate, - - netdev_linux_recv, - netdev_linux_recv_wait, - netdev_linux_drain, - - netdev_linux_send, - netdev_linux_send_wait, - - netdev_linux_set_etheraddr, - netdev_linux_get_etheraddr, - netdev_linux_get_mtu, - netdev_linux_get_ifindex, - netdev_linux_get_carrier, - netdev_linux_get_stats, - netdev_vport_set_stats, - - netdev_linux_get_features, - netdev_linux_set_advertisements, - netdev_linux_get_vlan_vid, - - netdev_linux_set_policing, - netdev_linux_get_qos_types, - netdev_linux_get_qos_capabilities, - netdev_linux_get_qos, - netdev_linux_set_qos, - netdev_linux_get_queue, - netdev_linux_set_queue, - netdev_linux_delete_queue, - netdev_linux_get_queue_stats, - netdev_linux_dump_queues, - netdev_linux_dump_queue_stats, - - netdev_linux_get_in4, - netdev_linux_set_in4, - netdev_linux_get_in6, - netdev_linux_add_router, - netdev_linux_get_next_hop, - netdev_linux_arp_lookup, - - netdev_linux_update_flags, - - netdev_linux_poll_add, - netdev_linux_poll_remove, -}; - -const struct netdev_class netdev_tap_class = { - "tap", - - netdev_linux_init, - netdev_linux_run, - netdev_linux_wait, - - netdev_linux_create_tap, - netdev_linux_destroy, - NULL, /* reconfigure */ - - netdev_linux_open, - netdev_linux_close, - - NULL, /* enumerate */ - - netdev_linux_recv, - netdev_linux_recv_wait, - netdev_linux_drain, - - netdev_linux_send, - netdev_linux_send_wait, - - netdev_linux_set_etheraddr, - netdev_linux_get_etheraddr, - netdev_linux_get_mtu, - netdev_linux_get_ifindex, - netdev_linux_get_carrier, - netdev_linux_get_stats, - NULL, /* set_stats */ - - netdev_linux_get_features, - netdev_linux_set_advertisements, - netdev_linux_get_vlan_vid, - - netdev_linux_set_policing, - netdev_linux_get_qos_types, - netdev_linux_get_qos_capabilities, - netdev_linux_get_qos, - netdev_linux_set_qos, - netdev_linux_get_queue, - netdev_linux_set_queue, - netdev_linux_delete_queue, - netdev_linux_get_queue_stats, - netdev_linux_dump_queues, - netdev_linux_dump_queue_stats, - - netdev_linux_get_in4, - netdev_linux_set_in4, - netdev_linux_get_in6, - netdev_linux_add_router, - netdev_linux_get_next_hop, - netdev_linux_arp_lookup, - - netdev_linux_update_flags, - - netdev_linux_poll_add, - netdev_linux_poll_remove, -}; +#define NETDEV_LINUX_CLASS(NAME, CREATE, ENUMERATE, SET_STATS) \ +{ \ + NAME, \ + \ + netdev_linux_init, \ + netdev_linux_run, \ + netdev_linux_wait, \ + \ + CREATE, \ + netdev_linux_destroy, \ + NULL, /* reconfigure */ \ + \ + netdev_linux_open, \ + netdev_linux_close, \ + \ + ENUMERATE, \ + \ + netdev_linux_recv, \ + netdev_linux_recv_wait, \ + netdev_linux_drain, \ + \ + netdev_linux_send, \ + netdev_linux_send_wait, \ + \ + netdev_linux_set_etheraddr, \ + netdev_linux_get_etheraddr, \ + netdev_linux_get_mtu, \ + netdev_linux_get_ifindex, \ + netdev_linux_get_carrier, \ + netdev_linux_get_stats, \ + SET_STATS, \ + \ + netdev_linux_get_features, \ + netdev_linux_set_advertisements, \ + netdev_linux_get_vlan_vid, \ + \ + netdev_linux_set_policing, \ + netdev_linux_get_qos_types, \ + netdev_linux_get_qos_capabilities, \ + netdev_linux_get_qos, \ + netdev_linux_set_qos, \ + netdev_linux_get_queue, \ + netdev_linux_set_queue, \ + netdev_linux_delete_queue, \ + netdev_linux_get_queue_stats, \ + netdev_linux_dump_queues, \ + netdev_linux_dump_queue_stats, \ + \ + netdev_linux_get_in4, \ + netdev_linux_set_in4, \ + netdev_linux_get_in6, \ + netdev_linux_add_router, \ + netdev_linux_get_next_hop, \ + netdev_linux_arp_lookup, \ + \ + netdev_linux_update_flags, \ + \ + netdev_linux_poll_add, \ + netdev_linux_poll_remove \ +} + +const struct netdev_class netdev_linux_class = + NETDEV_LINUX_CLASS( + "system", + netdev_linux_create, + netdev_linux_enumerate, + netdev_vport_set_stats); + +const struct netdev_class netdev_tap_class = + NETDEV_LINUX_CLASS( + "tap", + netdev_linux_create_tap, + NULL, /* enumerate */ + NULL); /* set_stats */ + +const struct netdev_class netdev_internal_class = + NETDEV_LINUX_CLASS( + "internal", + netdev_linux_create, + NULL, /* enumerate */ + netdev_vport_set_stats); /* HTB traffic control class. */ |
