ovs-ofctl: Fix reading flows from file for "replace-flows", "diff-flows".
[sliver-openvswitch.git] / utilities / ovs-ofctl.c
index 3d10178..d7c88b6 100644 (file)
@@ -55,6 +55,10 @@ VLOG_DEFINE_THIS_MODULE(ofctl);
 /* --strict: Use strict matching for flow mod commands? */
 static bool strict;
 
+/* --readd: If ture, on replace-flows, re-add even flows that have not changed
+ * (to reset flow counters). */
+static bool readd;
+
 /* -F, --flow-format: Flow format to use.  Either one of NXFF_* to force a
  * particular flow format or -1 to let ovs-ofctl choose intelligently. */
 static int preferred_flow_format = -1;
@@ -82,11 +86,13 @@ parse_options(int argc, char *argv[])
 {
     enum {
         OPT_STRICT = UCHAR_MAX + 1,
+        OPT_READD,
         VLOG_OPTION_ENUMS
     };
     static struct option long_options[] = {
         {"timeout", required_argument, NULL, 't'},
         {"strict", no_argument, NULL, OPT_STRICT},
+        {"readd", no_argument, NULL, OPT_READD},
         {"flow-format", required_argument, NULL, 'F'},
         {"more", no_argument, NULL, 'm'},
         {"help", no_argument, NULL, 'h'},
@@ -132,13 +138,17 @@ parse_options(int argc, char *argv[])
             usage();
 
         case 'V':
-            OVS_PRINT_VERSION(OFP_VERSION, OFP_VERSION);
+            ovs_print_version(OFP_VERSION, OFP_VERSION);
             exit(EXIT_SUCCESS);
 
         case OPT_STRICT:
             strict = true;
             break;
 
+        case OPT_READD:
+            readd = true;
+            break;
+
         VLOG_OPTION_HANDLERS
         STREAM_SSL_OPTION_HANDLERS
 
@@ -184,6 +194,7 @@ usage(void)
     vlog_usage();
     printf("\nOther options:\n"
            "  --strict                    use strict match for flow commands\n"
+           "  --readd                     replace flows that haven't changed\n"
            "  -F, --flow-format=FORMAT    force particular flow format\n"
            "  -m, --more                  be more verbose printing OpenFlow\n"
            "  -t, --timeout=SECS          give up after SECS seconds\n"
@@ -233,7 +244,7 @@ open_vconn__(const char *name, const char *default_suffix,
     free(datapath_name);
     free(datapath_type);
 
-    if (strstr(name, ":")) {
+    if (strchr(name, ':')) {
         run(vconn_open_block(name, OFP_VERSION, vconnp),
             "connecting to %s", name);
     } else if (!stat(name, &s) && S_ISSOCK(s.st_mode)) {
@@ -247,7 +258,7 @@ open_vconn__(const char *name, const char *default_suffix,
         }
         open_vconn_socket(socket_name, vconnp);
     } else {
-        ovs_fatal(0, "%s is not a valid connection method", name);
+        ovs_fatal(0, "%s is not a bridge or a socket", name);
     }
 
     free(bridge_path);
@@ -261,13 +272,14 @@ open_vconn(const char *name, struct vconn **vconnp)
 }
 
 static void *
-alloc_stats_request(size_t body_len, uint16_t type, struct ofpbuf **bufferp)
+alloc_stats_request(size_t rq_len, uint16_t type, struct ofpbuf **bufferp)
 {
     struct ofp_stats_msg *rq;
-    rq = make_openflow(sizeof *rq + body_len, OFPT_STATS_REQUEST, bufferp);
+
+    rq = make_openflow(rq_len, OFPT_STATS_REQUEST, bufferp);
     rq->type = htons(type);
     rq->flags = htons(0);
-    return rq + 1;
+    return rq;
 }
 
 static void
@@ -333,7 +345,7 @@ static void
 dump_trivial_stats_transaction(const char *vconn_name, uint8_t stats_type)
 {
     struct ofpbuf *request;
-    alloc_stats_request(0, stats_type, &request);
+    alloc_stats_request(sizeof(struct ofp_stats_msg), stats_type, &request);
     dump_stats_transaction(vconn_name, request);
 }
 
@@ -951,8 +963,7 @@ fte_version_print(const struct fte_version *version)
     }
 
     ds_init(&s);
-    ofp_print_actions(&s, (const struct ofp_action_header *) version->actions,
-                      version->n_actions * sizeof *version->actions);
+    ofp_print_actions(&s, version->actions, version->n_actions);
     printf(" %s\n", ds_cstr(&s));
     ds_destroy(&s);
 }
@@ -1031,10 +1042,8 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
     while (!ds_get_preprocessed_line(&s, file)) {
         struct fte_version *version;
         enum nx_flow_format min_ff;
-        struct ofpbuf actions;
         struct flow_mod fm;
 
-        ofpbuf_init(&actions, 64);
         parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), true);
 
         version = xmalloc(sizeof *version);
@@ -1042,8 +1051,8 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
         version->idle_timeout = fm.idle_timeout;
         version->hard_timeout = fm.hard_timeout;
         version->flags = fm.flags & (OFPFF_SEND_FLOW_REM | OFPFF_EMERG);
-        version->n_actions = actions.size / sizeof *version->actions;
-        version->actions = ofpbuf_steal_data(&actions);
+        version->actions = fm.actions;
+        version->n_actions = fm.n_actions;
 
         min_ff = ofputil_min_flow_format(&fm.cr);
         min_flow_format = MAX(min_flow_format, min_ff);
@@ -1207,7 +1216,8 @@ do_replace_flows(int argc OVS_UNUSED, char *argv[])
         struct fte_version *file_ver = fte->versions[FILE_IDX];
         struct fte_version *sw_ver = fte->versions[SWITCH_IDX];
 
-        if (file_ver && (!sw_ver || !fte_version_equals(sw_ver, file_ver))) {
+        if (file_ver
+            && (readd || !sw_ver || !fte_version_equals(sw_ver, file_ver))) {
             fte_make_flow_mod(fte, FILE_IDX, OFPFC_ADD, flow_format,
                               &requests);
         }
@@ -1390,7 +1400,8 @@ do_parse_nx_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
             puts(out);
             free(out);
         } else {
-            printf("nx_pull_match() returned error %x\n", error);
+            printf("nx_pull_match() returned error %x (%s)\n", error,
+                   ofputil_error_to_string(error));
         }
 
         ofpbuf_uninit(&nx_match);