Merge branch 'mainstream'
[sliver-openvswitch.git] / utilities / ovs-ofctl.c
index c2cc1f6..1a1d423 100644 (file)
@@ -50,6 +50,7 @@
 #include "openflow/nicira-ext.h"
 #include "openflow/openflow.h"
 #include "packets.h"
+#include "pcap-file.h"
 #include "poll-loop.h"
 #include "random.h"
 #include "stream-ssl.h"
@@ -888,7 +889,9 @@ prepare_dump_flows(int argc, char *argv[], bool aggregate,
 
     error = parse_ofp_flow_stats_request_str(&fsr, aggregate,
                                              argc > 2 ? argv[2] : "",
-                                             &usable_protocols);
+                                             &usable_protocols,
+                                             !(allowed_protocols
+                                               & OFPUTIL_P_OF10_ANY));
     if (error) {
         ovs_fatal(0, "%s", error);
     }
@@ -1110,7 +1113,8 @@ ofctl_flow_mod_file(int argc OVS_UNUSED, char *argv[], uint16_t command)
     char *error;
 
     error = parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms,
-                                    &usable_protocols);
+                                    &usable_protocols,
+                                    !(allowed_protocols & OFPUTIL_P_OF10_ANY));
     if (error) {
         ovs_fatal(0, "%s", error);
     }
@@ -1129,7 +1133,9 @@ ofctl_flow_mod(int argc, char *argv[], uint16_t command)
         enum ofputil_protocol usable_protocols;
 
         error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command,
-                                       &usable_protocols);
+                                       &usable_protocols,
+                                       !(allowed_protocols
+                                         & OFPUTIL_P_OF10_ANY));
         if (error) {
             ovs_fatal(0, "%s", error);
         }
@@ -2112,7 +2118,7 @@ fte_version_format(const struct fte *fte, int index, struct ds *s)
         ds_put_format(s, " hard_timeout=%"PRIu16, version->hard_timeout);
     }
 
-    ds_put_char(s, ' ');
+    ds_put_cstr(s, " actions=");
     ofpacts_format(version->ofpacts, version->ofpacts_len, s);
 
     ds_put_char(s, '\n');
@@ -2204,7 +2210,8 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
         char *error;
         enum ofputil_protocol usable;
 
-        error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), &usable);
+        error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), &usable,
+                              !(allowed_protocols & OFPUTIL_P_OF10_ANY));
         if (error) {
             ovs_fatal(0, "%s:%d: %s", filename, line_number, error);
         }
@@ -2623,7 +2630,8 @@ ofctl_parse_flow(int argc OVS_UNUSED, char *argv[])
     struct ofputil_flow_mod fm;
     char *error;
 
-    error = parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD, &usable_protocols);
+    error = parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD, &usable_protocols,
+                                   !(allowed_protocols & OFPUTIL_P_OF10_ANY));
     if (error) {
         ovs_fatal(0, "%s", error);
     }
@@ -2641,7 +2649,8 @@ ofctl_parse_flows(int argc OVS_UNUSED, char *argv[])
     char *error;
 
     error = parse_ofp_flow_mod_file(argv[1], OFPFC_ADD, &fms, &n_fms,
-                                    &usable_protocols);
+                                    &usable_protocols,
+                                    !(allowed_protocols & OFPUTIL_P_OF10_ANY));
     if (error) {
         ovs_fatal(0, "%s", error);
     }
@@ -2794,6 +2803,7 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 
         /* Print cls_rule. */
         ds_init(&s);
+        ds_put_cstr(&s, "actions=");
         ofpacts_format(ofpacts.data, ofpacts.size, &s);
         puts(ds_cstr(&s));
         ds_destroy(&s);
@@ -2968,8 +2978,8 @@ ofctl_parse_ofp11_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
         /* Convert to ofpacts. */
         ofpbuf_init(&ofpacts, 0);
         size = of11_in.size;
-        error = ofpacts_pull_openflow11_actions(&of11_in, of11_in.size,
-                                                &ofpacts);
+        error = ofpacts_pull_openflow11_actions(&of11_in, OFP11_VERSION,
+                                                of11_in.size, &ofpacts);
         if (error) {
             printf("bad OF1.1 actions: %s\n\n", ofperr_get_name(error));
             ofpbuf_uninit(&ofpacts);
@@ -2980,6 +2990,7 @@ ofctl_parse_ofp11_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 
         /* Print cls_rule. */
         ds_init(&s);
+        ds_put_cstr(&s, "actions=");
         ofpacts_format(ofpacts.data, ofpacts.size, &s);
         puts(ds_cstr(&s));
         ds_destroy(&s);
@@ -3036,14 +3047,14 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
         /* Convert to ofpacts. */
         ofpbuf_init(&ofpacts, 0);
         size = of11_in.size;
-        error = ofpacts_pull_openflow11_instructions(&of11_in, of11_in.size,
-                                                     &ofpacts);
+        error = ofpacts_pull_openflow11_instructions(&of11_in, OFP11_VERSION,
+                                                     of11_in.size, &ofpacts);
         if (!error) {
-            /* Verify actions. */
+            /* Verify actions, enforce consistency. */
             struct flow flow;
             memset(&flow, 0, sizeof flow);
             error = ofpacts_check(ofpacts.data, ofpacts.size, &flow, OFPP_MAX,
-                                  table_id ? atoi(table_id) : 0);
+                                  table_id ? atoi(table_id) : 0, true);
         }
         if (error) {
             printf("bad OF1.1 instructions: %s\n\n", ofperr_get_name(error));
@@ -3055,6 +3066,7 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 
         /* Print cls_rule. */
         ds_init(&s);
+        ds_put_cstr(&s, "actions=");
         ofpacts_format(ofpacts.data, ofpacts.size, &s);
         puts(ds_cstr(&s));
         ds_destroy(&s);
@@ -3076,6 +3088,36 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
     ds_destroy(&in);
 }
 
+/* "parse-pcap PCAP": read packets from PCAP and print their flows. */
+static void
+ofctl_parse_pcap(int argc OVS_UNUSED, char *argv[])
+{
+    FILE *pcap;
+
+    pcap = pcap_open(argv[1], "rb");
+    if (!pcap) {
+        ovs_fatal(errno, "%s: open failed", argv[1]);
+    }
+
+    for (;;) {
+        struct ofpbuf *packet;
+        struct flow flow;
+        int error;
+
+        error = pcap_read(pcap, &packet);
+        if (error == EOF) {
+            break;
+        } else if (error) {
+            ovs_fatal(error, "%s: read failed", argv[1]);
+        }
+
+        flow_extract(packet, 0, 0, NULL, NULL, &flow);
+        flow_print(stdout, &flow);
+        putchar('\n');
+        ofpbuf_delete(packet);
+    }
+}
+
 /* "check-vlan VLAN_TCI VLAN_TCI_MASK": converts the specified vlan_tci and
  * mask values to and from various formats and prints the results. */
 static void
@@ -3110,7 +3152,8 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[])
     string_s = match_to_string(&match, OFP_DEFAULT_PRIORITY);
     printf("%s -> ", string_s);
     fflush(stdout);
-    error_s = parse_ofp_str(&fm, -1, string_s, &usable_protocols);
+    error_s = parse_ofp_str(&fm, -1, string_s, &usable_protocols,
+                            !(allowed_protocols & OFPUTIL_P_OF10_ANY));
     if (error_s) {
         ovs_fatal(0, "%s", error_s);
     }
@@ -3329,6 +3372,7 @@ static const struct command all_commands[] = {
     { "parse-ofp11-match", 0, 0, ofctl_parse_ofp11_match },
     { "parse-ofp11-actions", 0, 0, ofctl_parse_ofp11_actions },
     { "parse-ofp11-instructions", 0, 0, ofctl_parse_ofp11_instructions },
+    { "parse-pcap", 1, 1, ofctl_parse_pcap },
     { "check-vlan", 2, 2, ofctl_check_vlan },
     { "print-error", 1, 1, ofctl_print_error },
     { "encode-error-reply", 2, 2, ofctl_encode_error_reply },