Rich Lane rlane@bigswitch.com
Rob Hoes rob.hoes@citrix.com
Romain Lenglet romain.lenglet@berabera.info
+Ryan Wilson wryan@nicira.com
Sajjad Lateef slateef@nicira.com
Sanjay Sane ssane@nicira.com
Saurabh Shah ssaurabh@nicira.com
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);
}
}
+/* 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
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);
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);