ovs-ofctl: Fix reading flows from file for "replace-flows", "diff-flows".
[sliver-openvswitch.git] / utilities / ovs-ofctl.c
index 5f9c830..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
 
@@ -172,6 +182,7 @@ usage(void)
            "  add-flows SWITCH FILE       add flows from FILE\n"
            "  mod-flows SWITCH FLOW       modify actions of matching FLOWs\n"
            "  del-flows SWITCH [FLOW]     delete matching FLOWs\n"
+           "  replace-flows SWITCH FILE   replace flows with those in FILE\n"
            "  monitor SWITCH [MISSLEN]    print packets received from SWITCH\n"
            "\nFor OpenFlow switches and controllers:\n"
            "  probe VCONN                 probe whether VCONN is up\n"
@@ -183,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"
@@ -232,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)) {
@@ -246,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);
@@ -260,14 +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_request *rq;
-    rq = make_openflow((offsetof(struct ofp_stats_request, body)
-                        + body_len), OFPT_STATS_REQUEST, bufferp);
+    struct ofp_stats_msg *rq;
+
+    rq = make_openflow(rq_len, OFPT_STATS_REQUEST, bufferp);
     rq->type = htons(type);
     rq->flags = htons(0);
-    return rq->body;
+    return rq;
 }
 
 static void
@@ -314,12 +326,12 @@ dump_stats_transaction(const char *vconn_name, struct ofpbuf *request)
         run(vconn_recv_block(vconn, &reply), "OpenFlow packet receive failed");
         recv_xid = ((struct ofp_header *) reply->data)->xid;
         if (send_xid == recv_xid) {
-            struct ofp_stats_reply *osr;
+            struct ofp_stats_msg *osm;
 
             ofp_print(stdout, reply->data, reply->size, verbosity + 1);
 
-            osr = ofpbuf_at(reply, 0, sizeof *osr);
-            done = !osr || !(ntohs(osr->flags) & OFPSF_REPLY_MORE);
+            osm = ofpbuf_at(reply, 0, sizeof *osm);
+            done = !osm || !(ntohs(osm->flags) & OFPSF_REPLY_MORE);
         } else {
             VLOG_DBG("received reply with xid %08"PRIx32" "
                      "!= expected %08"PRIx32, recv_xid, send_xid);
@@ -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);
 }
 
@@ -658,7 +670,7 @@ do_flow_mod__(int argc, char *argv[], uint16_t command)
     flow_mod_table_id = false;
 
     parse_ofp_flow_mod_str(&requests, &flow_format, &flow_mod_table_id,
-                           argc > 2 ? argv[2] : "", command);
+                           argc > 2 ? argv[2] : "", command, false);
     check_final_format_for_flow_mod(flow_format);
 
     open_vconn(argv[1], &vconn);
@@ -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,19 +1042,17 @@ 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, &actions, ds_cstr(&s));
+        parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), true);
 
         version = xmalloc(sizeof *version);
         version->cookie = fm.cookie;
         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);
@@ -1089,7 +1098,7 @@ read_flows_from_switch(struct vconn *vconn, enum nx_flow_format flow_format,
         recv_xid = ((struct ofp_header *) reply->data)->xid;
         if (send_xid == recv_xid) {
             const struct ofputil_msg_type *type;
-            const struct ofp_stats_reply *osr;
+            const struct ofp_stats_msg *osm;
             enum ofputil_msg_code code;
 
             ofputil_decode_msg_type(reply->data, &type);
@@ -1101,8 +1110,8 @@ read_flows_from_switch(struct vconn *vconn, enum nx_flow_format flow_format,
                                         verbosity + 1));
             }
 
-            osr = reply->data;
-            if (!(osr->flags & htons(OFPSF_REPLY_MORE))) {
+            osm = reply->data;
+            if (!(osm->flags & htons(OFPSF_REPLY_MORE))) {
                 done = true;
             }
 
@@ -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);
         }
@@ -1308,7 +1318,7 @@ do_parse_flow(int argc OVS_UNUSED, char *argv[])
 
     list_init(&packets);
     parse_ofp_flow_mod_str(&packets, &flow_format, &flow_mod_table_id,
-                           argv[1], OFPFC_ADD);
+                           argv[1], OFPFC_ADD, false);
     print_packet_list(&packets);
 }
 
@@ -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);