Merge branch 'mainstream'
[sliver-openvswitch.git] / utilities / ovs-ofctl.c
index a5a5c02..1cd23e6 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"
@@ -309,6 +310,14 @@ usage(void)
            "  dump-group-features SWITCH  print group features\n"
            "  dump-groups SWITCH          print group description\n"
            "  dump-group-stats SWITCH [GROUP]  print group statistics\n"
+           "  add-meter SWITCH METER      add meter described by METER\n"
+           "  mod-meter SWITCH METER      modify specific METER\n"
+           "  del-meter SWITCH METER      delete METER\n"
+           "  del-meters SWITCH           delete all meters\n"
+           "  dump-meter SWITCH METER     print METER configuration\n"
+           "  dump-meters SWITCH          print all meter configuration\n"
+           "  meter-stats SWITCH [METER]  print meter statistics\n"
+           "  meter-features SWITCH       print meter features\n"
            "\nFor OpenFlow switches and controllers:\n"
            "  probe TARGET                probe whether TARGET is up\n"
            "  ping TARGET [N]             latency of N-byte echos\n"
@@ -1113,13 +1122,12 @@ ofctl_flow_mod_file(int argc OVS_UNUSED, char *argv[], uint16_t command)
 static void
 ofctl_flow_mod(int argc, char *argv[], uint16_t command)
 {
-    enum ofputil_protocol usable_protocols;
-
     if (argc > 2 && !strcmp(argv[2], "-")) {
         ofctl_flow_mod_file(argc, argv, command);
     } else {
         struct ofputil_flow_mod fm;
         char *error;
+        enum ofputil_protocol usable_protocols;
 
         error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command,
                                        &usable_protocols);
@@ -2471,6 +2479,102 @@ ofctl_diff_flows(int argc OVS_UNUSED, char *argv[])
         exit(2);
     }
 }
+
+static void
+ofctl_meter_mod__(const char *bridge, const char *str, int command)
+{
+    struct ofputil_meter_mod mm;
+    struct vconn *vconn;
+    enum ofputil_protocol protocol;
+    enum ofputil_protocol usable_protocols;
+    enum ofp_version version;
+
+    if (str) {
+        char *error;
+        error = parse_ofp_meter_mod_str(&mm, str, command, &usable_protocols);
+        if (error) {
+            ovs_fatal(0, "%s", error);
+        }
+    } else {
+        usable_protocols = OFPUTIL_P_OF13_UP;
+        mm.command = command;
+        mm.meter.meter_id = OFPM13_ALL;
+    }
+
+    protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols);
+    version = ofputil_protocol_to_ofp_version(protocol);
+    transact_noreply(vconn, ofputil_encode_meter_mod(version, &mm));
+    vconn_close(vconn);
+}
+
+static void
+ofctl_meter_request__(const char *bridge, const char *str,
+                      enum ofputil_meter_request_type type)
+{
+    struct ofputil_meter_mod mm;
+    struct vconn *vconn;
+    enum ofputil_protocol usable_protocols;
+    enum ofputil_protocol protocol;
+    enum ofp_version version;
+
+    if (str) {
+        char *error;
+        error = parse_ofp_meter_mod_str(&mm, str, -1, &usable_protocols);
+        if (error) {
+            ovs_fatal(0, "%s", error);
+        }
+    } else {
+        usable_protocols = OFPUTIL_P_OF13_UP;
+        mm.meter.meter_id = OFPM13_ALL;
+    }
+
+    protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols);
+    version = ofputil_protocol_to_ofp_version(protocol);
+    transact_noreply(vconn, ofputil_encode_meter_request(version,
+                                                         type,
+                                                         mm.meter.meter_id));
+    vconn_close(vconn);
+}
+
+
+static void
+ofctl_add_meter(int argc OVS_UNUSED, char *argv[])
+{
+    ofctl_meter_mod__(argv[1], argv[2], OFPMC13_ADD);
+}
+
+static void
+ofctl_mod_meter(int argc OVS_UNUSED, char *argv[])
+{
+    ofctl_meter_mod__(argv[1], argv[2], OFPMC13_MODIFY);
+}
+
+static void
+ofctl_del_meters(int argc, char *argv[])
+{
+    ofctl_meter_mod__(argv[1], argc > 2 ? argv[2] : NULL, OFPMC13_DELETE);
+}
+
+static void
+ofctl_dump_meters(int argc, char *argv[])
+{
+    ofctl_meter_request__(argv[1], argc > 2 ? argv[2] : NULL,
+                          OFPUTIL_METER_CONFIG);
+}
+
+static void
+ofctl_meter_stats(int argc, char *argv[])
+{
+    ofctl_meter_request__(argv[1], argc > 2 ? argv[2] : NULL,
+                          OFPUTIL_METER_STATS);
+}
+
+static void
+ofctl_meter_features(int argc OVS_UNUSED, char *argv[])
+{
+    ofctl_meter_request__(argv[1], NULL, OFPUTIL_METER_FEATURES);
+}
+
 \f
 /* Undocumented commands for unit testing. */
 
@@ -2973,6 +3077,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
@@ -3186,6 +3320,14 @@ static const struct command all_commands[] = {
     { "del-flows", 1, 2, ofctl_del_flows },
     { "replace-flows", 2, 2, ofctl_replace_flows },
     { "diff-flows", 2, 2, ofctl_diff_flows },
+    { "add-meter", 2, 2, ofctl_add_meter },
+    { "mod-meter", 2, 2, ofctl_mod_meter },
+    { "del-meter", 2, 2, ofctl_del_meters },
+    { "del-meters", 1, 1, ofctl_del_meters },
+    { "dump-meter", 2, 2, ofctl_dump_meters },
+    { "dump-meters", 1, 1, ofctl_dump_meters },
+    { "meter-stats", 1, 2, ofctl_meter_stats },
+    { "meter-features", 1, 1, ofctl_meter_features },
     { "packet-out", 4, INT_MAX, ofctl_packet_out },
     { "dump-ports", 1, 2, ofctl_dump_ports },
     { "dump-ports-desc", 1, 1, ofctl_dump_ports_desc },
@@ -3218,6 +3360,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 },