#include "ofpbuf.h"
#include "packets.h"
#include "poll-loop.h"
+#include "svec.h"
#include "util.h"
#include "valgrind.h"
/* 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)
{
/* 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)
{
}
}
+/* 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)
{
/* 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
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(). */
struct odp_port **portsp, size_t *n_portsp)
{
struct odp_port *ports;
- size_t n_ports;
+ size_t n_ports = 0;
int error;
for (;;) {