ovs-ofctl: Add meter support.
authorJarno Rajahalme <jrajahalme@nicira.com>
Fri, 13 Sep 2013 22:03:33 +0000 (15:03 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 16 Sep 2013 22:43:18 +0000 (15:43 -0700)
Adds commands add-meter, mod-meter, del-meter, del-meters, dump-meter,
dump-meters, meter-stats, and meter-features.

Syntax is as follows:

add-meter <br> meter=<n> (kbps|pktps) [burst] [stats] bands= type=(drop|dscp_remark) rate=<n> [burst_size=<n>] [prec_level=<n>] <more bands>

mod-meter <br> meter=<n> (kbps|pktps) [burst] [stats] bands= type=(drop|dscp_remark) rate=<n> [burst_size=<n>] [prec_level=<n>] <more bands>

del-meter <br> meter=(<n>|all)

del-meters <br>

dump-meter <br> meter=(<n>|all)

dump-meters <br>

meter-stats <br> [meter=(<n>|all)]

meter-features <br>

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
utilities/ovs-ofctl.8.in
utilities/ovs-ofctl.c

index 3141eff..526e12c 100644 (file)
@@ -190,7 +190,7 @@ statistics are printed for all queues on \fIport\fR; if only
 \fIport\fR is omitted, then statistics are printed for \fIqueue\fR on
 every port where it exists.
 .
-.SS "OpenFlow 1.1+ Switch Management Commands"
+.SS "OpenFlow 1.1+ Group Table Commands"
 .
 The following commands work only with switches that support OpenFlow
 1.1 or later.  Because support for OpenFlow 1.1 and later is still
@@ -238,6 +238,42 @@ Send to controller.  (This is how an OpenFlow 1.0 switch always
 handles packets that do not match any flow in the last table.)
 .RE
 .
+.SS "OpenFlow 1.3+ Switch Meter Table Commands"
+.
+These commands manage the meter table in an OpenFlow switch.  In each
+case, \fImeter\fR specifies a meter entry in the format described in
+\fBMeter Syntax\fR, below.
+.
+.PP
+OpenFlow 1.3 introduced support for meters, so these commands only
+work with switches that support OpenFlow 1.3 or later.  The caveats
+described for groups in the previous section also apply to meters.
+.
+.IP "\fBadd\-meter \fIswitch meter\fR"
+Add a meter entry to \fIswitch\fR's tables. The \fImeter\fR syntax is
+described in section \fBMeter Syntax\fR, below.
+.
+.IP "\fBmod\-meter \fIswitch meter\fR"
+Modify an existing meter.
+.
+.IP "\fBdel\-meters \fIswitch\fR"
+.IQ "\fBdel\-meter \fIswitch\fR [\fImeter\fR]"
+Delete entries from \fIswitch\fR's meter table.  \fImeter\fR can specify
+a single meter with syntax \fBmeter=\fIid\fR, or all meters with syntax
+\fBmeter=all\fR.
+.
+.IP "\fBdump\-meters \fIswitch\fR"
+.IQ "\fBdump\-meter \fIswitch\fR [\fImeter\fR]"
+Print meter configuration.  \fImeter\fR can specify a single meter with
+syntax \fBmeter=\fIid\fR, or all meters with syntax \fBmeter=all\fR.
+.
+.IP "\fBmeter\-stats \fIswitch\fR [\fImeter\fR]"
+Print meter statistics.  \fImeter\fR can specify a single meter with
+syntax \fBmeter=\fIid\fR, or all meters with syntax \fBmeter=all\fR.
+.
+.IP "\fBmeter\-features \fIswitch\fR"
+Print meter features.
+.
 .SS "OpenFlow Switch Flow Table Commands"
 .
 These commands manage the flow table in an OpenFlow switch.  In each
@@ -1322,6 +1358,12 @@ field will be replaced with the corresponding bit from \fIvalue\fR. Both
 \fIvalue\fR and \fImask\fR are 64-bit values that are decimal by default; use
 a \fB0x\fR prefix to specify them in hexadecimal.
 .
+.IP \fBmeter\fR:\fImeter_id\fR
+Apply the \fImeter_id\fR before any other actions. If a meter band rate is
+exceeded, the packet may be dropped, or modified, depending on the meter
+band type. See the description of the \fBMeter Table Commands\fR, above,
+for more details.
+.
 .IP \fBgoto_table\fR:\fItable\fR
 Indicates the next table in the process pipeline.
 .
@@ -1580,6 +1622,62 @@ This or the \fBwatch_port\fR field is required
 for groups whose \fBtype\fR is \fBff\fR or \fBfast_failover\fR.
 .RE
 .
+.SS "Meter Syntax"
+.PP
+The meter table commands accept an argument that describes a meter.
+Such meter descriptions comprise a series \fIfield\fB=\fIvalue\fR
+assignments, separated by commas or white space.
+(Embedding spaces into a group description normally requires
+quoting to prevent the shell from breaking the description into
+multiple arguments.). Unless noted otherwise only the last instance
+of each field is honoured.
+.PP
+.IP \fBmeter=\fIid\fR
+The integer meter id of the meter.
+When this field is specified in \fBdel-meter\fR, \fBdump-meter\fR, or
+\fBmeter-stats\fR, the keyword "all" may be used to designate all meters.
+.
+This field is required, exept for \fBmeter-stats\fR, which dumps all stats
+when this field is not specified.
+
+.IP \fBkbps\fR
+.IQ \fBpktps\fR
+The unit for the meter band rate parameters, either kilobits per second, or
+packets per second, respectively.  One of these must be specified.  The burst
+size unit corresponds to the rate unit by dropping the "per second", i.e.,
+burst is in units of kilobits or packets, respectively.
+
+.IP \fBburst\fR
+Specify burst size for all bands, or none of them, if this flag is not given.
+
+.IP \fBstats\fR
+Collect meter and band statistics.
+
+.IP \fBbands\fR=\fIband_parameters\fR
+The \fBadd-meter\fR and \fBmod-meter\fR commands require at least one
+band specification. Bands must appear after all other fields.
+.RS
+.IP \fBtype=\fItype\fR
+The type of the meter band.  This keyword starts a new band specification.
+Each band specifies a rate above which the band is to take some action. The
+action depends on the band type.  If multiple bands' rate is exceeded, then
+the band with the highest rate among the exceeded bands is selected.
+The following keywords designate the allowed
+meter band types:
+.RS
+.IP \fBdrop\fR
+Drop packets exceeding the band's rate limit.
+.RE
+.
+.IP "The other \fIband_parameters\fR are:"
+.IP \fBrate=\fIvalue\fR
+The relative rate limit for this band, in kilobits per second or packets per
+second, depending on the meter flags defined above.
+.IP \fBburst_size=\fIport\fR
+The maximum burst allowed for the band.  If unspecified, the switch is free to
+select some reasonable value depending on it's configuration.
+.RE
+.
 .SH OPTIONS
 .TP
 \fB\-\-strict\fR
index a5a5c02..c2cc1f6 100644 (file)
@@ -309,6 +309,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 +1121,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 +2478,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. */
 
@@ -3186,6 +3289,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 },