@@ -45,6 +45,10 @@ struct netdev {
const struct netdev_class *netdev_class; /* Functions to control
this device. */
+ /* If this is 'true' the user did not specify a netdev_class when
+ * opening this device, and therefore got assigned to the "system" class */
+ bool auto_classified;
+
/* A sequence number which indicates changes in one of 'netdev''s
* properties. It must be nonzero so that users have a value which
* they may use as a reset when tracking 'netdev'.
@@ -361,7 +361,7 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
OVS_EXCLUDED(netdev_mutex)
{
struct netdev *netdev;
- int error;
+ int error = 0;
if (!name[0]) {
/* Reject empty names. This saves the providers having to do this. At
@@ -375,6 +375,29 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
ovs_mutex_lock(&netdev_mutex);
netdev = shash_find_data(&netdev_shash, name);
+
+ if (netdev &&
+ type && type[0] && strcmp(type, netdev->netdev_class->type)) {
+
+ if (netdev->auto_classified) {
+ /* If this device was first created without a classification type,
+ * for example due to routing or tunneling code, and they keep a
+ * reference, a "classified" call to open will fail. In this case
+ * we remove the classless device, and re-add it below. We remove
+ * the netdev from the shash, and change the sequence, so owners of
+ * the old classless device can release/cleanup. */
+ if (netdev->node) {
+ shash_delete(&netdev_shash, netdev->node);
+ netdev->node = NULL;
+ netdev_change_seq_changed(netdev);
+ }
+
+ netdev = NULL;
+ } else {
+ error = EEXIST;
+ }
+ }
+
if (!netdev) {
struct netdev_registered_class *rc;
@@ -384,6 +407,7 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
if (netdev) {
memset(netdev, 0, sizeof *netdev);
netdev->netdev_class = rc->class;
+ netdev->auto_classified = type && type[0] ? false : true;
netdev->name = xstrdup(name);
netdev->change_seq = 1;
netdev->reconfigure_seq = seq_create();
@@ -416,10 +440,6 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
name, type);
error = EAFNOSUPPORT;
}
- } else if (type && type[0] && strcmp(type, netdev->netdev_class->type)) {
- error = EEXIST;
- } else {
- error = 0;
}
if (!error) {
Due to commit 67ac844 an existing issue with OVS persisten ports surfaced. If we revert the commit we no longer get the error, and basic traffic will flow. However the wrong netdev class is used, hence the wrong callbacks get called. The main issue is with netdev_open() being called with type = NULL before the interface is actually configured in the system. This patch tracks these "auto" generated interfaces, and once netdev_open() gets called with a valid type, re-configures (re-create) it. Signed-off-by: Eelco Chaudron <echaudro@redhat.com> --- lib/netdev-provider.h | 4 ++++ lib/netdev.c | 30 +++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-)