X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fdpif.c;h=793eaa1189a9533ce7f469a8d720107165660af2;hb=8f7501e83f4aa3d395287ef91f4910e32b55643e;hp=0e83a9e2afaea4403284360cbd41974983be0e24;hpb=72865317a41d065fcc47a33fc68cdd2081cecb3d;p=openvswitch diff --git a/lib/dpif.c b/lib/dpif.c index 0e83a9e2..793eaa11 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -33,6 +33,7 @@ #include "ofpbuf.h" #include "packets.h" #include "poll-loop.h" +#include "svec.h" #include "util.h" #include "valgrind.h" @@ -64,8 +65,8 @@ static void check_rw_odp_flow(struct odp_flow *); /* Performs periodic work needed by all the various kinds of dpifs. * - * If your program opens any dpifs, it must call this function within its main - * poll loop. */ + * If your program opens any dpifs, it must call both this function and + * netdev_run() within its main poll loop. */ void dp_run(void) { @@ -80,8 +81,8 @@ dp_run(void) /* Arranges for poll_block() to wake up when dp_run() needs to be called. * - * If your program opens any dpifs, it must call this function within its main - * poll loop. */ + * If your program opens any dpifs, it must call both this function and + * netdev_wait() within its main poll loop. */ void dp_wait(void) { @@ -94,6 +95,34 @@ dp_wait(void) } } +/* Clears 'all_dps' and enumerates the names of all known created datapaths, + * where possible, into it. The caller must first initialize 'all_dps'. + * 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 +dp_enumerate(struct svec *all_dps) +{ + int error; + int i; + + svec_clear(all_dps); + error = 0; + for (i = 0; i < N_DPIF_CLASSES; i++) { + const struct dpif_class *class = dpif_classes[i]; + int retval = class->enumerate ? class->enumerate(all_dps) : 0; + if (retval) { + VLOG_WARN("failed to enumerate %s datapaths: %s", + class->name, strerror(retval)); + if (!error) { + error = retval; + } + } + } + return error; +} + static int do_open(const char *name_, bool create, struct dpif **dpifp) { @@ -140,13 +169,35 @@ dpif_open(const char *name, struct dpif **dpifp) /* Tries to create and open a new datapath with the given 'name'. Will fail if * a datapath named 'name' already exists. Returns 0 if successful, otherwise * a positive errno value. On success stores a pointer to the datapath in - * '*dpifp', otherwise a null pointer.*/ + * '*dpifp', otherwise a null pointer. */ int dpif_create(const char *name, struct dpif **dpifp) { return do_open(name, true, dpifp); } +/* Tries to open a datapath with the given 'name', creating it if it does not + * exist. Returns 0 if successful, otherwise a positive errno value. On + * success stores a pointer to the datapath in '*dpifp', otherwise a null + * pointer. */ +int +dpif_create_and_open(const char *name, struct dpif **dpifp) +{ + int error; + + error = dpif_create(name, dpifp); + if (error == EEXIST || error == EBUSY) { + error = dpif_open(name, dpifp); + if (error) { + VLOG_WARN("datapath %s already exists but cannot be opened: %s", + name, strerror(error)); + } + } else if (error) { + VLOG_WARN("failed to create datapath %s: %s", name, strerror(error)); + } + return error; +} + /* Closes and frees the connection to 'dpif'. Does not destroy the datapath * itself; call dpif_delete() first, instead, if that is desirable. */ void @@ -166,6 +217,32 @@ dpif_name(const struct dpif *dpif) return dpif->name; } +/* Enumerates all names that may be used to open 'dpif' into 'all_names'. The + * Linux datapath, for example, supports opening a datapath both by number, + * e.g. "dp0", and by the name of the datapath's local port. For some + * datapaths, this might be an infinite set (e.g. in a file name, slashes may + * be duplicated any number of times), in which case only the names most likely + * to be used will be enumerated. + * + * The caller must already have initialized 'all_names'. Any existing names in + * 'all_names' will not be disturbed. */ +int +dpif_get_all_names(const struct dpif *dpif, struct svec *all_names) +{ + if (dpif->class->get_all_names) { + int error = dpif->class->get_all_names(dpif, all_names); + if (error) { + VLOG_WARN_RL(&error_rl, + "failed to retrieve names for datpath %s: %s", + dpif_name(dpif), strerror(error)); + } + return error; + } else { + svec_add(all_names, dpif_name(dpif)); + return 0; + } +} + /* Destroys the datapath that 'dpif' is connected to, first removing all of its * ports. After calling this function, it does not make sense to pass 'dpif' * to any functions other than dpif_name() or dpif_close(). */ @@ -342,7 +419,7 @@ dpif_port_list(const struct dpif *dpif, struct odp_port **portsp, size_t *n_portsp) { struct odp_port *ports; - size_t n_ports; + size_t n_ports = 0; int error; for (;;) {