2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 14:25:26 +00:00

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>
This commit is contained in:
Ben Pfaff
2010-12-03 14:41:38 -08:00
parent 94903c9898
commit c3827f619a
26 changed files with 504 additions and 776 deletions

View File

@@ -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",
#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 \
}
netdev_linux_init,
netdev_linux_run,
netdev_linux_wait,
const struct netdev_class netdev_linux_class =
NETDEV_LINUX_CLASS(
"system",
netdev_linux_create,
netdev_linux_enumerate,
netdev_vport_set_stats);
netdev_linux_create_system,
netdev_linux_destroy,
NULL, /* reconfigure */
const struct netdev_class netdev_tap_class =
NETDEV_LINUX_CLASS(
"tap",
netdev_linux_create_tap,
NULL, /* enumerate */
NULL); /* set_stats */
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,
};
const struct netdev_class netdev_internal_class =
NETDEV_LINUX_CLASS(
"internal",
netdev_linux_create,
NULL, /* enumerate */
netdev_vport_set_stats);
/* HTB traffic control class. */