X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fdpif.c;h=9c5cf3d07cea8c9c23a95e2eb4d6f1cada19d948;hb=d017eeb9f9ebcb46c24a67fd301b3e36cd26a04e;hp=c4b6ff675bf51685322874ef9a307c0e18a9edce;hpb=cc36576070df622d0fc7a6e26ce01027e12b5b59;p=sliver-openvswitch.git diff --git a/lib/dpif.c b/lib/dpif.c index c4b6ff675..9c5cf3d07 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -71,6 +71,9 @@ struct registered_dpif_class { static struct shash dpif_classes = SHASH_INITIALIZER(&dpif_classes); static struct sset dpif_blacklist = SSET_INITIALIZER(&dpif_blacklist); +/* Protects 'dpif_classes', including the refcount, and 'dpif_blacklist'. */ +static struct ovs_mutex dpif_mutex = OVS_MUTEX_INITIALIZER; + /* Rate limit for individual messages going to or from the datapath, output at * DBG level. This is very high because, if these are enabled, it is because * we really need to see them. */ @@ -110,10 +113,8 @@ dp_initialize(void) } } -/* Registers a new datapath provider. After successful registration, new - * datapaths of that type can be opened using dpif_open(). */ -int -dp_register_provider(const struct dpif_class *new_class) +static int +dp_register_provider__(const struct dpif_class *new_class) { struct registered_dpif_class *registered_class; @@ -138,11 +139,25 @@ dp_register_provider(const struct dpif_class *new_class) return 0; } +/* Registers a new datapath provider. After successful registration, new + * datapaths of that type can be opened using dpif_open(). */ +int +dp_register_provider(const struct dpif_class *new_class) +{ + int error; + + ovs_mutex_lock(&dpif_mutex); + error = dp_register_provider__(new_class); + ovs_mutex_unlock(&dpif_mutex); + + return error; +} + /* Unregisters a datapath provider. 'type' must have been previously * registered and not currently be in use by any dpifs. After unregistration * new datapaths of that type cannot be opened using dpif_open(). */ -int -dp_unregister_provider(const char *type) +static int +dp_unregister_provider__(const char *type) { struct shash_node *node; struct registered_dpif_class *registered_class; @@ -166,12 +181,31 @@ dp_unregister_provider(const char *type) return 0; } +/* Unregisters a datapath provider. 'type' must have been previously + * registered and not currently be in use by any dpifs. After unregistration + * new datapaths of that type cannot be opened using dpif_open(). */ +int +dp_unregister_provider(const char *type) +{ + int error; + + dp_initialize(); + + ovs_mutex_lock(&dpif_mutex); + error = dp_unregister_provider__(type); + ovs_mutex_unlock(&dpif_mutex); + + return error; +} + /* Blacklists a provider. Causes future calls of dp_register_provider() with * a dpif_class which implements 'type' to fail. */ void dp_blacklist_provider(const char *type) { + ovs_mutex_lock(&dpif_mutex); sset_add(&dpif_blacklist, type); + ovs_mutex_unlock(&dpif_mutex); } /* Clears 'types' and enumerates the types of all currently registered datapath @@ -184,10 +218,36 @@ dp_enumerate_types(struct sset *types) dp_initialize(); sset_clear(types); + ovs_mutex_lock(&dpif_mutex); SHASH_FOR_EACH(node, &dpif_classes) { const struct registered_dpif_class *registered_class = node->data; sset_add(types, registered_class->dpif_class->type); } + ovs_mutex_unlock(&dpif_mutex); +} + +static void +dp_class_unref(struct registered_dpif_class *rc) +{ + ovs_mutex_lock(&dpif_mutex); + ovs_assert(rc->refcount); + rc->refcount--; + ovs_mutex_unlock(&dpif_mutex); +} + +static struct registered_dpif_class * +dp_class_lookup(const char *type) +{ + struct registered_dpif_class *rc; + + ovs_mutex_lock(&dpif_mutex); + rc = shash_find_data(&dpif_classes, type); + if (rc) { + rc->refcount++; + } + ovs_mutex_unlock(&dpif_mutex); + + return rc; } /* Clears 'names' and enumerates the names of all known created datapaths with @@ -199,14 +259,14 @@ dp_enumerate_types(struct sset *types) int dp_enumerate_names(const char *type, struct sset *names) { - const struct registered_dpif_class *registered_class; + struct registered_dpif_class *registered_class; const struct dpif_class *dpif_class; int error; dp_initialize(); sset_clear(names); - registered_class = shash_find_data(&dpif_classes, type); + registered_class = dp_class_lookup(type); if (!registered_class) { VLOG_WARN("could not enumerate unknown type: %s", type); return EAFNOSUPPORT; @@ -214,11 +274,11 @@ dp_enumerate_names(const char *type, struct sset *names) dpif_class = registered_class->dpif_class; error = dpif_class->enumerate ? dpif_class->enumerate(names) : 0; - if (error) { VLOG_WARN("failed to enumerate %s datapaths: %s", dpif_class->type, ovs_strerror(error)); } + dp_class_unref(registered_class); return error; } @@ -254,8 +314,7 @@ do_open(const char *name, const char *type, bool create, struct dpif **dpifp) dp_initialize(); type = dpif_normalize_type(type); - - registered_class = shash_find_data(&dpif_classes, type); + registered_class = dp_class_lookup(type); if (!registered_class) { VLOG_WARN("could not create datapath %s of unknown type %s", name, type); @@ -267,7 +326,8 @@ do_open(const char *name, const char *type, bool create, struct dpif **dpifp) name, create, &dpif); if (!error) { ovs_assert(dpif->dpif_class == registered_class->dpif_class); - registered_class->refcount++; + } else { + dp_class_unref(registered_class); } exit: @@ -327,15 +387,11 @@ void dpif_close(struct dpif *dpif) { if (dpif) { - struct registered_dpif_class *registered_class; - - registered_class = shash_find_data(&dpif_classes, - dpif->dpif_class->type); - ovs_assert(registered_class); - ovs_assert(registered_class->refcount); + struct registered_dpif_class *rc; - registered_class->refcount--; + rc = shash_find_data(&dpif_classes, dpif->dpif_class->type); dpif_uninit(dpif, true); + dp_class_unref(rc); } } @@ -422,18 +478,18 @@ dpif_get_dp_stats(const struct dpif *dpif, struct dpif_dp_stats *stats) const char * dpif_port_open_type(const char *datapath_type, const char *port_type) { - struct registered_dpif_class *registered_class; + struct registered_dpif_class *rc; datapath_type = dpif_normalize_type(datapath_type); - registered_class = shash_find_data(&dpif_classes, datapath_type); - if (!registered_class - || !registered_class->dpif_class->port_open_type) { - return port_type; + ovs_mutex_lock(&dpif_mutex); + rc = shash_find_data(&dpif_classes, datapath_type); + if (rc && rc->dpif_class->port_open_type) { + port_type = rc->dpif_class->port_open_type(rc->dpif_class, port_type); } + ovs_mutex_unlock(&dpif_mutex); - return registered_class->dpif_class->port_open_type( - registered_class->dpif_class, port_type); + return port_type; } /* Attempts to add 'netdev' as a port on 'dpif'. If 'port_nop' is