Skip to content

Commit

Permalink
netdev: Remove netdev from global shash when the user is changing int…
Browse files Browse the repository at this point in the history
…erface configuration.

When the user changes port type (i.e. changing p0 from type 'internal' to
'gre'), the netdev must first be deleted, then re-created with the new type.
Deleting the netdev requires there exist no more references to the netdev.
However, the xlate cache holds references to netdevs and the cache is only
invalidated by revalidator threads. Thus, if cache is not invalidated prior to
the netdev being re-created, the netdev will not be able to be re-created and
the configuration change will fail.

This patch always removes the netdev from the global netdev shash when the
user changes port type. This ensures that the new netdev can always be created
while handler and revalidator threads can retain references to the old netdev
until they are finished.

Signed-off-by: Ryan Wilson <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
Ryan Wilson authored and blp committed May 16, 2014
1 parent fe99c36 commit fe83f81
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 2 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Remko Tronçon [email protected]
Rich Lane [email protected]
Rob Hoes [email protected]
Romain Lenglet [email protected]
Ryan Wilson [email protected]
Sajjad Lateef [email protected]
Sanjay Sane [email protected]
Saurabh Shah [email protected]
Expand Down
26 changes: 25 additions & 1 deletion lib/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,9 @@ netdev_unref(struct netdev *dev)

dev->netdev_class->destruct(dev);

shash_delete(&netdev_shash, dev->node);
if (dev->node) {
shash_delete(&netdev_shash, dev->node);
}
free(dev->name);
dev->netdev_class->dealloc(dev);
ovs_mutex_unlock(&netdev_mutex);
Expand All @@ -515,6 +517,28 @@ netdev_close(struct netdev *netdev)
}
}

/* Removes 'netdev' from the global shash and unrefs 'netdev'.
*
* This allows handler and revalidator threads to still retain references
* to this netdev while the main thread changes interface configuration.
*
* This function should only be called by the main thread when closing
* netdevs during user configuration changes. Otherwise, netdev_close should be
* used to close netdevs. */
void
netdev_remove(struct netdev *netdev)
{
if (netdev) {
ovs_mutex_lock(&netdev_mutex);
if (netdev->node) {
shash_delete(&netdev_shash, netdev->node);
netdev->node = NULL;
netdev_change_seq_changed(netdev);
}
netdev_unref(netdev);
}
}

/* Parses 'netdev_name_', which is of the form [type@]name into its component
* pieces. 'name' and 'type' must be freed by the caller. */
void
Expand Down
1 change: 1 addition & 0 deletions lib/netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ bool netdev_is_pmd(const struct netdev *netdev);
int netdev_open(const char *name, const char *type, struct netdev **netdevp);

struct netdev *netdev_ref(const struct netdev *);
void netdev_remove(struct netdev *);
void netdev_close(struct netdev *);

void netdev_parse_name(const char *netdev_name, char **name, char **type);
Expand Down
4 changes: 3 additions & 1 deletion vswitchd/bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -3452,7 +3452,9 @@ iface_destroy__(struct iface *iface)
list_remove(&iface->port_elem);
hmap_remove(&br->iface_by_name, &iface->name_node);

netdev_close(iface->netdev);
/* The user is changing configuration here, so netdev_remove needs to be
* used as opposed to netdev_close */
netdev_remove(iface->netdev);

free(iface->name);
free(iface);
Expand Down

0 comments on commit fe83f81

Please sign in to comment.