COVERAGE_DEFINE(dpif_flow_get);
COVERAGE_DEFINE(dpif_flow_put);
COVERAGE_DEFINE(dpif_flow_del);
-COVERAGE_DEFINE(dpif_flow_query_list);
-COVERAGE_DEFINE(dpif_flow_query_list_n);
COVERAGE_DEFINE(dpif_execute);
COVERAGE_DEFINE(dpif_purge);
&dpif_linux_class,
#endif
&dpif_netdev_class,
+ &dpif_planetlab_class,
};
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. */
}
}
-/* 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;
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;
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
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
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;
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;
}
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);
name, create, &dpif);
if (!error) {
ovs_assert(dpif->dpif_class == registered_class->dpif_class);
- registered_class->refcount++;
+ } else {
+ dp_class_unref(registered_class);
}
exit:
dpif_close(struct dpif *dpif)
{
if (dpif) {
- struct registered_dpif_class *registered_class;
+ struct registered_dpif_class *rc;
- registered_class = shash_find_data(&dpif_classes,
- dpif->dpif_class->type);
- ovs_assert(registered_class);
- ovs_assert(registered_class->refcount);
-
- registered_class->refcount--;
+ rc = shash_find_data(&dpif_classes, dpif->dpif_class->type);
dpif_uninit(dpif, true);
+ dp_class_unref(rc);
}
}
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
/* Returns one greater than the maximum port number accepted in flow
* actions. */
-odp_port_t
+uint32_t
dpif_get_max_ports(const struct dpif *dpif)
{
return dpif->dpif_class->get_max_ports(dpif);
if (error) {
ds_put_format(&ds, "(%s) ", ovs_strerror(error));
}
- odp_flow_format(key, key_len, mask, mask_len, &ds);
+ odp_flow_format(key, key_len, mask, mask_len, NULL, &ds, true);
if (stats) {
ds_put_cstr(&ds, ", ");
dpif_flow_stats_format(stats, &ds);