appveyor: Renew SSL link.
[cascardo/ovs.git] / lib / dpctl.c
index a9a56ff..48bf6bc 100644 (file)
@@ -60,6 +60,11 @@ struct dpctl_command {
     dpctl_command_handler *handler;
 };
 static const struct dpctl_command *get_all_dpctl_commands(void);
+static void dpctl_print(struct dpctl_params *dpctl_p, const char *fmt, ...)
+    OVS_PRINTF_FORMAT(2, 3);
+static void dpctl_error(struct dpctl_params* dpctl_p, int err_no,
+                        const char *fmt, ...)
+    OVS_PRINTF_FORMAT(3, 4);
 
 static void
 dpctl_puts(struct dpctl_params *dpctl_p, bool error, const char *string)
@@ -402,7 +407,7 @@ dpctl_set_if(int argc, const char *argv[], struct dpctl_params *dpctl_p)
         char *err_s = NULL;
         error = netdev_set_config(netdev, &args, &err_s);
         if (err_s || error) {
-            dpctl_error(dpctl_p, error,
+            dpctl_error(dpctl_p, error, "%s",
                         err_s ? err_s : "Error updating configuration");
             free(err_s);
         }
@@ -607,7 +612,57 @@ show_dpif(struct dpif *dpif, struct dpctl_params *dpctl_p)
             }
         }
     }
-    dpif_close(dpif);
+}
+
+typedef void (*dps_for_each_cb)(struct dpif *, struct dpctl_params *);
+
+static int
+dps_for_each(struct dpctl_params *dpctl_p, dps_for_each_cb cb)
+{
+    struct sset dpif_names = SSET_INITIALIZER(&dpif_names),
+                dpif_types = SSET_INITIALIZER(&dpif_types);
+    int error, openerror = 0, enumerror = 0;
+    const char *type, *name;
+    bool at_least_one = false;
+
+    dp_enumerate_types(&dpif_types);
+
+    SSET_FOR_EACH (type, &dpif_types) {
+        error = dp_enumerate_names(type, &dpif_names);
+        if (error) {
+            enumerror = error;
+        }
+
+        SSET_FOR_EACH (name, &dpif_names) {
+            struct dpif *dpif;
+
+            at_least_one = true;
+            error = dpif_open(name, type, &dpif);
+            if (!error) {
+                cb(dpif, dpctl_p);
+                dpif_close(dpif);
+            } else {
+                openerror = error;
+                dpctl_error(dpctl_p, error, "opening datapath %s failed",
+                            name);
+            }
+        }
+    }
+
+    sset_destroy(&dpif_names);
+    sset_destroy(&dpif_types);
+
+    /* If there has been an error while opening a datapath it should be
+     * reported.  Otherwise, we want to ignore the errors generated by
+     * dp_enumerate_names() if at least one datapath has been discovered,
+     * because they're not interesting for the user.  This happens, for
+     * example, if OVS is using a userspace datapath and the kernel module
+     * is not loaded. */
+    if (openerror) {
+        return openerror;
+    } else {
+        return at_least_one ? 0 : enumerror;
+    }
 }
 
 static int
@@ -623,6 +678,7 @@ dpctl_show(int argc, const char *argv[], struct dpctl_params *dpctl_p)
             error = parsed_dpif_open(name, false, &dpif);
             if (!error) {
                 show_dpif(dpif, dpctl_p);
+                dpif_close(dpif);
             } else {
                 dpctl_error(dpctl_p, error, "opening datapath %s failed",
                             name);
@@ -630,86 +686,32 @@ dpctl_show(int argc, const char *argv[], struct dpctl_params *dpctl_p)
             }
         }
     } else {
-        struct sset types;
-        const char *type;
-
-        sset_init(&types);
-        dp_enumerate_types(&types);
-        SSET_FOR_EACH (type, &types) {
-            struct sset names;
-            const char *name;
-
-            sset_init(&names);
-            error = dp_enumerate_names(type, &names);
-            if (error) {
-                lasterror = error;
-                goto next;
-            }
-            SSET_FOR_EACH (name, &names) {
-                struct dpif *dpif;
-
-                error = dpif_open(name, type, &dpif);
-                if (!error) {
-                    show_dpif(dpif, dpctl_p);
-                } else {
-                    dpctl_error(dpctl_p, error, "opening datapath %s failed",
-                                name);
-                    lasterror = error;
-                }
-            }
-next:
-            sset_destroy(&names);
-        }
-        sset_destroy(&types);
+        lasterror = dps_for_each(dpctl_p, show_dpif);
     }
+
     return lasterror;
 }
 
+static void
+dump_cb(struct dpif *dpif, struct dpctl_params *dpctl_p)
+{
+    dpctl_print(dpctl_p, "%s\n", dpif_name(dpif));
+}
+
 static int
 dpctl_dump_dps(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
                struct dpctl_params *dpctl_p)
 {
-    struct sset dpif_names, dpif_types;
-    const char *type;
-    int error, lasterror = 0;
-
-    sset_init(&dpif_names);
-    sset_init(&dpif_types);
-    dp_enumerate_types(&dpif_types);
-
-    SSET_FOR_EACH (type, &dpif_types) {
-        const char *name;
-
-        error = dp_enumerate_names(type, &dpif_names);
-        if (error) {
-            lasterror = error;
-        }
-
-        SSET_FOR_EACH (name, &dpif_names) {
-            struct dpif *dpif;
-            if (!dpif_open(name, type, &dpif)) {
-                dpctl_print(dpctl_p, "%s\n", dpif_name(dpif));
-                dpif_close(dpif);
-            }
-        }
-    }
-
-    sset_destroy(&dpif_names);
-    sset_destroy(&dpif_types);
-    return lasterror;
+    return dps_for_each(dpctl_p, dump_cb);
 }
 
 static void
 format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports,
                  struct dpctl_params *dpctl_p)
 {
-    if (dpctl_p->verbosity) {
-        if (f->ufid_present) {
-            odp_format_ufid(&f->ufid, ds);
-            ds_put_cstr(ds, ", ");
-        } else {
-            ds_put_cstr(ds, "ufid:<empty>, ");
-        }
+    if (dpctl_p->verbosity && f->ufid_present) {
+        odp_format_ufid(&f->ufid, ds);
+        ds_put_cstr(ds, ", ");
     }
     odp_flow_format(f->key, f->key_len, f->mask, f->mask_len, ports, ds,
                     dpctl_p->verbosity);
@@ -777,6 +779,12 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
         }
     }
 
+    /* Make sure that these values are different. PMD_ID_NULL means that the
+     * pmd is unspecified (e.g. because the datapath doesn't have different
+     * pmd threads), while NON_PMD_CORE_ID refers to every non pmd threads
+     * in the userspace datapath */
+    BUILD_ASSERT(PMD_ID_NULL != NON_PMD_CORE_ID);
+
     ds_init(&ds);
     flow_dump = dpif_flow_dump_create(dpif, false);
     flow_dump_thread = dpif_flow_dump_thread_create(flow_dump);
@@ -788,7 +796,8 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
             struct minimatch minimatch;
 
             odp_flow_key_to_flow(f.key, f.key_len, &flow);
-            odp_flow_key_to_mask(f.mask, f.mask_len, &wc.masks, &flow);
+            odp_flow_key_to_mask(f.mask, f.mask_len, f.key, f.key_len,
+                                 &wc.masks, &flow);
             match_init(&match, &flow, &wc);
 
             match_init(&match_filter, &flow_filter, &wc);
@@ -1477,7 +1486,7 @@ dpctl_normalize_actions(int argc, const char *argv[],
 
         ds_clear(&s);
         format_odp_actions(&s, af->actions.data, af->actions.size);
-        dpctl_print(dpctl_p, ds_cstr(&s));
+        dpctl_puts(dpctl_p, false, ds_cstr(&s));
 
         ofpbuf_uninit(&af->actions);
         free(af);