diff --git a/lib/dpif.h b/lib/dpif.h index a4e5568f9..447ccd980 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -40,6 +40,7 @@ struct dpif_class; int dp_register_provider(const struct dpif_class *); int dp_unregister_provider(const char *type); void dp_enumerate_types(struct sset *types); +const char *dpif_normalize_type(const char *); int dp_enumerate_names(const char *type, struct sset *names); void dp_parse_name(const char *datapath_name, char **name, char **type); @@ -55,8 +56,6 @@ void dpif_wait(struct dpif *); const char *dpif_name(const struct dpif *); const char *dpif_base_name(const struct dpif *); -const char *dpif_normalize_type(const char *); - int dpif_delete(struct dpif *); int dpif_get_dp_stats(const struct dpif *, struct odp_stats *); diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 7ca859bea..dadc546b2 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -409,6 +409,36 @@ static bool is_admissible(struct ofproto *, const struct flow *, static void ofproto_unixctl_init(void); +/* Clears 'types' and enumerates all registered ofproto types into it. The + * caller must first initialize the sset. */ +void +ofproto_enumerate_types(struct sset *types) +{ + dp_enumerate_types(types); +} + +/* Returns the fully spelled out name for the given ofproto 'type'. + * + * Normalized type string can be compared with strcmp(). Unnormalized type + * string might be the same even if they have different spellings. */ +const char * +ofproto_normalize_type(const char *type) +{ + return dpif_normalize_type(type); +} + +/* Clears 'names' and enumerates the names of all known created ofprotos with + * the given 'type'. The caller must first initialize the sset. Returns 0 if + * successful, otherwise a positive errno value. + * + * Some kinds of datapaths might not be practically enumerable. This is not + * considered an error. */ +int +ofproto_enumerate_names(const char *type, struct sset *names) +{ + return dp_enumerate_names(type, names); +} + int ofproto_create(const char *datapath, const char *datapath_type, struct ofproto **ofprotop) @@ -1331,6 +1361,26 @@ ofproto_destroy(struct ofproto *p) free(p); } +/* Destroys the datapath with the respective 'name' and 'type'. With the Linux + * kernel datapath, for example, this destroys the datapath in the kernel, and + * with the netdev-based datapath, it tears down the data structures that + * represent the datapath. + * + * The datapath should not be currently open as an ofproto. */ +int +ofproto_delete(const char *name, const char *type) +{ + struct dpif *dpif; + int error; + + error = dpif_open(name, type, &dpif); + if (!error) { + error = dpif_delete(dpif); + dpif_close(dpif); + } + return error; +} + static void process_port_change(struct ofproto *ofproto, int error, char *devname) { diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 2fb951a23..183e58865 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -92,11 +92,17 @@ struct ofproto_controller { #define DEFAULT_SERIAL_DESC "None" #define DEFAULT_DP_DESC "None" +void ofproto_enumerate_types(struct sset *types); +const char *ofproto_normalize_type(const char *); + +int ofproto_enumerate_names(const char *type, struct sset *names); void ofproto_parse_name(const char *name, char **dp_name, char **dp_type); int ofproto_create(const char *datapath, const char *datapath_type, struct ofproto **ofprotop); void ofproto_destroy(struct ofproto *); +int ofproto_delete(const char *name, const char *type); + int ofproto_run(struct ofproto *); void ofproto_wait(struct ofproto *); bool ofproto_is_alive(const struct ofproto *); diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 6caf086a8..e23ee6fcf 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -38,7 +38,6 @@ #include "coverage.h" #include "daemon.h" #include "dirs.h" -#include "dpif.h" #include "dynamic-string.h" #include "flow.h" #include "hash.h" @@ -158,8 +157,8 @@ static long long int stats_timer = LLONG_MIN; static long long int db_limiter = LLONG_MIN; static void add_del_bridges(const struct ovsrec_open_vswitch *); -static void bridge_del_dps(void); -static bool bridge_add_dp(struct bridge *); +static void bridge_del_ofprotos(void); +static bool bridge_add_ofprotos(struct bridge *); static void bridge_create(const struct ovsrec_bridge *); static void bridge_destroy(struct bridge *); static struct bridge *bridge_lookup(const char *name); @@ -395,7 +394,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) * that port already belongs to a different datapath, so we must do all * port deletions before any port additions. A datapath always has a * "local port" so we must delete not-configured datapaths too. */ - bridge_del_dps(); + bridge_del_ofprotos(); HMAP_FOR_EACH (br, node, &all_bridges) { if (br->ofproto) { bridge_del_ofproto_ports(br); @@ -409,7 +408,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) * has at least one iface, every "struct iface" has a valid ofp_port and * netdev. */ HMAP_FOR_EACH_SAFE (br, next, node, &all_bridges) { - if (!br->ofproto && !bridge_add_dp(br)) { + if (!br->ofproto && !bridge_add_ofprotos(br)) { bridge_destroy(br); } } @@ -448,40 +447,35 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) daemonize_complete(); } -/* Iterate over all system dpifs and delete any of them that do not have a +/* Iterate over all ofprotos and delete any of them that do not have a * configured bridge or that are the wrong type. */ static void -bridge_del_dps(void) +bridge_del_ofprotos(void) { - struct sset dpif_names; - struct sset dpif_types; + struct sset names; + struct sset types; const char *type; - sset_init(&dpif_names); - sset_init(&dpif_types); - dp_enumerate_types(&dpif_types); - SSET_FOR_EACH (type, &dpif_types) { + sset_init(&names); + sset_init(&types); + ofproto_enumerate_types(&types); + SSET_FOR_EACH (type, &types) { const char *name; - dp_enumerate_names(type, &dpif_names); - SSET_FOR_EACH (name, &dpif_names) { + ofproto_enumerate_names(type, &names); + SSET_FOR_EACH (name, &names) { struct bridge *br = bridge_lookup(name); if (!br || strcmp(type, br->type)) { - struct dpif *dpif; - - if (!dpif_open(name, type, &dpif)) { - dpif_delete(dpif); - dpif_close(dpif); - } + ofproto_delete(name, type); } } } - sset_destroy(&dpif_names); - sset_destroy(&dpif_types); + sset_destroy(&names); + sset_destroy(&types); } static bool -bridge_add_dp(struct bridge *br) +bridge_add_ofprotos(struct bridge *br) { int error = ofproto_create(br->name, br->type, &br->ofproto); if (error) { @@ -740,8 +734,8 @@ add_del_bridges(const struct ovsrec_open_vswitch *cfg) * Update 'cfg' of bridges that still exist. */ HMAP_FOR_EACH_SAFE (br, next, node, &all_bridges) { br->cfg = shash_find_data(&new_br, br->name); - if (!br->cfg || strcmp(br->type, - dpif_normalize_type(br->cfg->datapath_type))) { + if (!br->cfg || strcmp(br->type, ofproto_normalize_type( + br->cfg->datapath_type))) { bridge_destroy(br); } } @@ -854,7 +848,7 @@ bridge_refresh_ofp_port(struct bridge *br) } } -/* Add a dpif port for any "struct iface" that doesn't have one. +/* Add an ofproto port for any "struct iface" that doesn't have one. * Delete any "struct iface" for which this fails. * Delete any "struct port" that thereby ends up with no ifaces. */ static void @@ -1654,7 +1648,7 @@ bridge_create(const struct ovsrec_bridge *br_cfg) br = xzalloc(sizeof *br); br->name = xstrdup(br_cfg->name); - br->type = xstrdup(dpif_normalize_type(br_cfg->datapath_type)); + br->type = xstrdup(ofproto_normalize_type(br_cfg->datapath_type)); br->cfg = br_cfg; eth_addr_nicira_random(br->default_ea);