X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fdpif.c;h=9c5cf3d07cea8c9c23a95e2eb4d6f1cada19d948;hb=d017eeb9f9ebcb46c24a67fd301b3e36cd26a04e;hp=bab1ffebfec706fc834caaa18b0009c96c8d8694;hpb=9b1a48c210ffa95c6323d5db05958aba35802c49;p=sliver-openvswitch.git diff --git a/lib/dpif.c b/lib/dpif.c index bab1ffebf..9c5cf3d07 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,6 +61,7 @@ static const struct dpif_class *base_dpif_classes[] = { &dpif_linux_class, #endif &dpif_netdev_class, + &dpif_planetlab_class, }; struct registered_dpif_class { @@ -70,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. */ @@ -81,6 +85,7 @@ static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5); static void log_flow_message(const struct dpif *dpif, int error, const char *operation, const struct nlattr *key, size_t key_len, + const struct nlattr *mask, size_t mask_len, const struct dpif_flow_stats *stats, const struct nlattr *actions, size_t actions_len); static void log_operation(const struct dpif *, const char *operation, @@ -96,22 +101,20 @@ static void log_execute_message(struct dpif *, const struct dpif_execute *, static void dp_initialize(void) { - static int status = -1; + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; - if (status < 0) { + if (ovsthread_once_start(&once)) { int i; - status = 0; for (i = 0; i < ARRAY_SIZE(base_dpif_classes); i++) { dp_register_provider(base_dpif_classes[i]); } + ovsthread_once_done(&once); } } -/* 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; @@ -136,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; @@ -164,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 @@ -182,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 @@ -197,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; @@ -212,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, - strerror(error)); + ovs_strerror(error)); } + dp_class_unref(registered_class); return error; } @@ -252,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); @@ -265,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: @@ -310,10 +372,11 @@ dpif_create_and_open(const char *name, const char *type, struct dpif **dpifp) error = dpif_open(name, type, dpifp); if (error) { VLOG_WARN("datapath %s already exists but cannot be opened: %s", - name, strerror(error)); + name, ovs_strerror(error)); } } else if (error) { - VLOG_WARN("failed to create datapath %s: %s", name, strerror(error)); + VLOG_WARN("failed to create datapath %s: %s", + name, ovs_strerror(error)); } return error; } @@ -324,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); } } @@ -419,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 @@ -460,7 +519,7 @@ dpif_port_add(struct dpif *dpif, struct netdev *netdev, odp_port_t *port_nop) dpif_name(dpif), netdev_name, port_no); } else { VLOG_WARN_RL(&error_rl, "%s: failed to add %s as port: %s", - dpif_name(dpif), netdev_name, strerror(error)); + dpif_name(dpif), netdev_name, ovs_strerror(error)); port_no = ODPP_NONE; } if (port_nop) { @@ -517,7 +576,7 @@ dpif_port_exists(const struct dpif *dpif, const char *devname) int error = dpif->dpif_class->port_query_by_name(dpif, devname, NULL); if (error != 0 && error != ENOENT && error != ENODEV) { VLOG_WARN_RL(&error_rl, "%s: failed to query port %s: %s", - dpif_name(dpif), devname, strerror(error)); + dpif_name(dpif), devname, ovs_strerror(error)); } return !error; @@ -540,7 +599,7 @@ dpif_port_query_by_number(const struct dpif *dpif, odp_port_t port_no, } else { memset(port, 0, sizeof *port); VLOG_WARN_RL(&error_rl, "%s: failed to query port %"PRIu32": %s", - dpif_name(dpif), port_no, strerror(error)); + dpif_name(dpif), port_no, ovs_strerror(error)); } return error; } @@ -569,7 +628,7 @@ dpif_port_query_by_name(const struct dpif *dpif, const char *devname, VLOG_RL(&error_rl, error == ENOENT || error == ENODEV ? VLL_DBG : VLL_WARN, "%s: failed to query port %s: %s", - dpif_name(dpif), devname, strerror(error)); + dpif_name(dpif), devname, ovs_strerror(error)); } return error; } @@ -808,8 +867,8 @@ dpif_flow_get(const struct dpif *dpif, actions = NULL; actions_len = 0; } - log_flow_message(dpif, error, "flow_get", key, key_len, stats, - actions, actions_len); + log_flow_message(dpif, error, "flow_get", key, key_len, + NULL, 0, stats, actions, actions_len); } return error; } @@ -982,6 +1041,7 @@ dpif_flow_dump_next(struct dpif_flow_dump *dump, } else if (should_log_flow_message(error)) { log_flow_message(dpif, error, "flow_dump", key ? *key : NULL, key ? *key_len : 0, + mask ? *mask : NULL, mask ? *mask_len : 0, stats ? *stats : NULL, actions ? *actions : NULL, actions ? *actions_len : 0); } @@ -1254,7 +1314,7 @@ log_operation(const struct dpif *dpif, const char *operation, int error) dpif_name(dpif), operation, ofperr_get_name(error)); } else { VLOG_WARN_RL(&error_rl, "%s: %s failed (%s)", - dpif_name(dpif), operation, strerror(error)); + dpif_name(dpif), operation, ovs_strerror(error)); } } @@ -1279,6 +1339,7 @@ should_log_flow_message(int error) static void log_flow_message(const struct dpif *dpif, int error, const char *operation, const struct nlattr *key, size_t key_len, + const struct nlattr *mask, size_t mask_len, const struct dpif_flow_stats *stats, const struct nlattr *actions, size_t actions_len) { @@ -1289,9 +1350,9 @@ log_flow_message(const struct dpif *dpif, int error, const char *operation, } ds_put_format(&ds, "%s ", operation); if (error) { - ds_put_format(&ds, "(%s) ", strerror(error)); + ds_put_format(&ds, "(%s) ", ovs_strerror(error)); } - odp_flow_key_format(key, key_len, &ds); + odp_flow_format(key, key_len, mask, mask_len, &ds); if (stats) { ds_put_cstr(&ds, ", "); dpif_flow_stats_format(stats, &ds); @@ -1323,8 +1384,8 @@ log_flow_put_message(struct dpif *dpif, const struct dpif_flow_put *put, ds_put_cstr(&s, "[zero]"); } log_flow_message(dpif, error, ds_cstr(&s), - put->key, put->key_len, put->stats, - put->actions, put->actions_len); + put->key, put->key_len, put->mask, put->mask_len, + put->stats, put->actions, put->actions_len); ds_destroy(&s); } } @@ -1335,7 +1396,7 @@ log_flow_del_message(struct dpif *dpif, const struct dpif_flow_del *del, { if (should_log_flow_message(error)) { log_flow_message(dpif, error, "flow_del", del->key, del->key_len, - !error ? del->stats : NULL, NULL, 0); + NULL, 0, !error ? del->stats : NULL, NULL, 0); } } @@ -1352,7 +1413,7 @@ log_execute_message(struct dpif *dpif, const struct dpif_execute *execute, ds_put_format(&ds, "%s: execute ", dpif_name(dpif)); format_odp_actions(&ds, execute->actions, execute->actions_len); if (error) { - ds_put_format(&ds, " failed (%s)", strerror(error)); + ds_put_format(&ds, " failed (%s)", ovs_strerror(error)); } ds_put_format(&ds, " on packet %s", packet); vlog(THIS_MODULE, error ? VLL_WARN : VLL_DBG, "%s", ds_cstr(&ds));