@@ -17,6 +17,7 @@
#ifndef OPENVSWITCH_OFP_METER_H
#define OPENVSWITCH_OFP_METER_H 1
+#include <stdbool.h>
#include "openflow/openflow.h"
#include "openvswitch/ofp-protocol.h"
@@ -61,7 +62,8 @@ int ofputil_decode_meter_config(struct ofpbuf *,
struct ofputil_meter_config *,
struct ofpbuf *bands);
void ofputil_format_meter_config(struct ds *,
- const struct ofputil_meter_config *);
+ const struct ofputil_meter_config *,
+ bool oneline);
struct ofputil_meter_mod {
uint16_t command;
@@ -79,6 +81,11 @@ char *parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string,
OVS_WARN_UNUSED_RESULT;
void ofputil_format_meter_mod(struct ds *, const struct ofputil_meter_mod *);
+char *parse_ofp_meter_mod_file(const char *file_name, int command,
+ struct ofputil_meter_mod **mms, size_t *n_mms,
+ enum ofputil_protocol *usable_protocols)
+ OVS_WARN_UNUSED_RESULT;
+
struct ofputil_meter_stats {
uint32_t meter_id;
uint32_t flow_count;
@@ -38,6 +38,16 @@ struct dp_packet;
extern "C" {
#endif
+/* manipulate higher bits in verbosity for other usage */
+#define OFP_ONELINE_BIT 7
+#define OFP_ONELINE_MASK (1 << OFP_ONELINE_BIT)
+#define OFP_VERBOSITY_MASK (~OFP_ONELINE_MASK)
+
+#define OFP_VERBOSITY(verbosity) (verbosity & OFP_VERBOSITY_MASK)
+
+#define OFP_ONELINE_SET(verbosity) (verbosity | OFP_ONELINE_MASK)
+#define OFP_ONELINE_GET(verbosity) (verbosity & OFP_ONELINE_MASK)
+
void ofp_print(FILE *, const void *, size_t, const struct ofputil_port_map *,
const struct ofputil_table_map *, int verbosity);
void ofp_print_packet(FILE *stream, const void *data,
@@ -15,6 +15,7 @@
*/
#include <config.h>
+#include <errno.h>
#include "openvswitch/ofp-meter.h"
#include "byte-order.h"
#include "nx-match.h"
@@ -57,7 +58,7 @@ void
ofputil_format_meter_band(struct ds *s, enum ofp13_meter_flags flags,
const struct ofputil_meter_band *mb)
{
- ds_put_cstr(s, "\ntype=");
+ ds_put_cstr(s, "type=");
switch (mb->type) {
case OFPMBT13_DROP:
ds_put_cstr(s, "drop");
@@ -343,7 +344,8 @@ ofp_print_meter_flags(struct ds *s, enum ofp13_meter_flags flags)
void
ofputil_format_meter_config(struct ds *s,
- const struct ofputil_meter_config *mc)
+ const struct ofputil_meter_config *mc,
+ bool oneline)
{
uint16_t i;
@@ -354,6 +356,7 @@ ofputil_format_meter_config(struct ds *s,
ds_put_cstr(s, "bands=");
for (i = 0; i < mc->n_bands; ++i) {
+ ds_put_cstr(s, oneline ? " ": "\n");
ofputil_format_meter_band(s, mc->flags, &mc->bands[i]);
}
ds_put_char(s, '\n');
@@ -578,6 +581,24 @@ parse_ofp_meter_mod_str__(struct ofputil_meter_mod *mm, char *string,
/* Meters require at least OF 1.3. */
*usable_protocols = OFPUTIL_P_OF13_UP;
+ if (command == -2) {
+ size_t len;
+
+ string += strspn(string, " \t\r\n"); /* Skip white space. */
+ len = strcspn(string, ", \t\r\n"); /* Get length of the first token. */
+
+ if (!strncmp(string, "add", len)) {
+ command = OFPMC13_ADD;
+ } else if (!strncmp(string, "delete", len)) {
+ command = OFPMC13_DELETE;
+ } else if (!strncmp(string, "modify", len)) {
+ command = OFPMC13_MODIFY;
+ } else {
+ len = 0;
+ command = OFPMC13_ADD;
+ }
+ string += len;
+ }
switch (command) {
case -1:
@@ -606,6 +627,11 @@ parse_ofp_meter_mod_str__(struct ofputil_meter_mod *mm, char *string,
mm->meter.n_bands = 0;
mm->meter.bands = NULL;
+ if (command == OFPMC13_DELETE && string[0] == '\0') {
+ mm->meter.meter_id = OFPM13_ALL;
+ return NULL;
+ }
+
if (fields & F_BANDS) {
band_str = strstr(string, "band");
if (!band_str) {
@@ -805,5 +831,73 @@ ofputil_format_meter_mod(struct ds *s, const struct ofputil_meter_mod *mm)
ds_put_format(s, " cmd:%d ", mm->command);
}
- ofputil_format_meter_config(s, &mm->meter);
+ ofputil_format_meter_config(s, &mm->meter, false);
+}
+
+/* If 'command' is given as -2, each line may start with a command name ("add",
+ * "modify", "delete"). A missing command name is treated as "add".
+ */
+char * OVS_WARN_UNUSED_RESULT
+parse_ofp_meter_mod_file(const char *file_name,
+ int command,
+ struct ofputil_meter_mod **mms, size_t *n_mms,
+ enum ofputil_protocol *usable_protocols)
+{
+ size_t allocated_mms;
+ int line_number;
+ FILE *stream;
+ struct ds s;
+
+ *mms = NULL;
+ *n_mms = 0;
+
+ stream = !strcmp(file_name, "-") ? stdin : fopen(file_name, "r");
+ if (stream == NULL) {
+ return xasprintf("%s: open failed (%s)",
+ file_name, ovs_strerror(errno));
+ }
+
+ allocated_mms = *n_mms;
+ ds_init(&s);
+ line_number = 0;
+ *usable_protocols = OFPUTIL_P_ANY;
+ while (!ds_get_preprocessed_line(&s, stream, &line_number)) {
+ enum ofputil_protocol usable;
+ char *error;
+
+ if (*n_mms >= allocated_mms) {
+ *mms = x2nrealloc(*mms, &allocated_mms, sizeof **mms);
+ }
+ error = parse_ofp_meter_mod_str(&(*mms)[*n_mms], ds_cstr(&s), command,
+ &usable);
+ if (error) {
+ size_t i;
+
+ for (i = 0; i < *n_mms; i++) {
+ if (mms[i]->meter.bands) {
+ free(mms[i]->meter.bands);
+ }
+ }
+ free(*mms);
+ *mms = NULL;
+ *n_mms = 0;
+
+ ds_destroy(&s);
+ if (stream != stdin) {
+ fclose(stream);
+ }
+
+ char *ret = xasprintf("%s:%d: %s", file_name, line_number, error);
+ free(error);
+ return ret;
+ }
+ *usable_protocols &= usable;
+ *n_mms += 1;
+ }
+
+ ds_destroy(&s);
+ if (stream != stdin) {
+ fclose(stream);
+ }
+ return NULL;
}
@@ -54,6 +54,7 @@
#include "openvswitch/ofp-monitor.h"
#include "openvswitch/ofp-msgs.h"
#include "openvswitch/ofp-port.h"
+#include "openvswitch/ofp-print.h"
#include "openvswitch/ofp-queue.h"
#include "openvswitch/ofp-switch.h"
#include "openvswitch/ofp-table.h"
@@ -365,12 +366,17 @@ ofp_print_meter_features_reply(struct ds *s, const struct ofp_header *oh)
}
static enum ofperr
-ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh)
+ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh,
+ bool oneline)
{
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
struct ofpbuf bands;
int retval;
+ if (oneline) {
+ ds_put_char(s, '\n');
+ }
+
ofpbuf_init(&bands, 64);
for (;;) {
struct ofputil_meter_config mc;
@@ -379,8 +385,10 @@ ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh)
if (retval) {
break;
}
- ds_put_char(s, '\n');
- ofputil_format_meter_config(s, &mc);
+ if (!oneline) {
+ ds_put_char(s, '\n');
+ }
+ ofputil_format_meter_config(s, &mc, oneline ? true : false);
}
ofpbuf_uninit(&bands);
@@ -977,6 +985,8 @@ ofp_to_string__(const struct ofp_header *oh,
ofp_print_stats(string, oh);
}
+ bool oneline = !!OFP_ONELINE_GET(verbosity);
+ verbosity = OFP_VERBOSITY(verbosity);
const void *msg = oh;
enum ofptype type = ofptype_from_ofpraw(raw);
switch (type) {
@@ -1090,7 +1100,7 @@ ofp_to_string__(const struct ofp_header *oh,
return ofp_print_meter_stats_reply(string, oh);
case OFPTYPE_METER_CONFIG_STATS_REPLY:
- return ofp_print_meter_config_reply(string, oh);
+ return ofp_print_meter_config_reply(string, oh, oneline);
case OFPTYPE_METER_FEATURES_STATS_REPLY:
return ofp_print_meter_features_reply(string, oh);
@@ -1278,7 +1288,7 @@ ofp_to_string(const void *oh_, size_t len,
ofp_print_error(&string, error);
}
- if (verbosity >= 5 || error) {
+ if (OFP_VERBOSITY(verbosity) >= 5 || error) {
add_newline(&string);
ds_put_hex_dump(&string, oh, len, 0, true);
}
@@ -283,11 +283,6 @@ AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=1 pktps burst stats bands=type=drop rate=1 burst_size=1'])
AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=2 kbps burst stats bands=type=drop rate=1 burst_size=2'])
-AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 'in_port=1 action=meter:1,7'])
-AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 'in_port=7 action=meter:2,1'])
-AT_CHECK([ovs-ofctl add-flow br1 'in_port=2 action=8'])
-AT_CHECK([ovs-ofctl add-flow br1 'in_port=8 action=2'])
-ovs-appctl time/stop
AT_CHECK([ovs-ofctl -O OpenFlow13 dump-meters br0], [0], [dnl
OFPST_METER_CONFIG reply (OF1.3) (xid=0x2):
@@ -298,6 +293,45 @@ meter=2 kbps burst stats bands=
type=drop rate=1 burst_size=2
])
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-meters br0 --oneline], [0], [dnl
+OFPST_METER_CONFIG reply (OF1.3) (xid=0x2):
+meter=1 pktps burst stats bands= type=drop rate=1 burst_size=1
+meter=2 kbps burst stats bands= type=drop rate=1 burst_size=2
+])
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-meters br0 meter=1 --oneline], [0], [dnl
+OFPST_METER_CONFIG reply (OF1.3) (xid=0x2):
+meter=1 pktps burst stats bands= type=drop rate=1 burst_size=1
+])
+
+AT_CHECK([ovs-ofctl del-meters -O openflow13 br0])
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-meters br0], [0], [dnl
+OFPST_METER_CONFIG reply (OF1.3) (xid=0x2):
+])
+
+AT_DATA([meters.txt], [dnl
+meter=1 pktps burst stats bands= type=drop rate=1 burst_size=1
+
+meter=2 kbps burst stats bands= type=drop rate=1 burst_size=2
+meter=3 kbps burst stats bands= type=drop rate=2 burst_size=3
+])
+
+AT_CHECK([ovs-ofctl add-meters -O openflow13 br0 meters.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-meters br0 --oneline], [0], [dnl
+OFPST_METER_CONFIG reply (OF1.3) (xid=0x2):
+meter=1 pktps burst stats bands= type=drop rate=1 burst_size=1
+meter=2 kbps burst stats bands= type=drop rate=1 burst_size=2
+meter=3 kbps burst stats bands= type=drop rate=2 burst_size=3
+])
+
+AT_CHECK([ovs-ofctl del-meters -O openflow13 br0 meter=3])
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 'in_port=1 action=meter:1,7'])
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 'in_port=7 action=meter:2,1'])
+AT_CHECK([ovs-ofctl add-flow br1 'in_port=2 action=8'])
+AT_CHECK([ovs-ofctl add-flow br1 'in_port=8 action=2'])
+ovs-appctl time/stop
+
ovs-appctl time/warp 5000
for i in `seq 1 7`; do
AT_CHECK(
@@ -3309,3 +3309,73 @@ AT_CHECK([grep -q "ct_dpif|DBG|.*ct_flush: <all>" ovs-vswitchd.log])
OVS_VSWITCHD_STOP
AT_CLEANUP
+
+
+dnl This checks basic add_meter --oneline operations.
+AT_SETUP([ofproto - add meters and dump meters with oneline option (OpenFlow 1.3)])
+OVS_VSWITCHD_START
+AT_DATA([meters.txt], [dnl
+meter=12 pktps burst stats bands=type=drop rate=1 burst_size=1
+meter=34 pktps burst stats bands=type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+meter=56 kbps burst stats bands=type=drop rate=1 burst_size=1
+meter=78 kbps burst stats bands=type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+])
+AT_CHECK([ovs-ofctl -O openflow13 -vwarn add-meters br0 meters.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn dump-meters br0 --oneline], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sort -f], [0], [dnl
+meter=12 pktps burst stats bands= type=drop rate=1 burst_size=1
+meter=34 pktps burst stats bands= type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+meter=56 kbps burst stats bands= type=drop rate=1 burst_size=1
+meter=78 kbps burst stats bands= type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+OFPST_METER_CONFIG reply (OF1.3):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn del-meters br0 meter=12])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn dump-meters br0 --oneline], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sort -f], [0], [dnl
+meter=34 pktps burst stats bands= type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+meter=56 kbps burst stats bands= type=drop rate=1 burst_size=1
+meter=78 kbps burst stats bands= type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+OFPST_METER_CONFIG reply (OF1.3):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn del-meters br0 meter=34])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn dump-meters br0 --oneline], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sort -f], [0], [dnl
+meter=56 kbps burst stats bands= type=drop rate=1 burst_size=1
+meter=78 kbps burst stats bands= type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+OFPST_METER_CONFIG reply (OF1.3):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn del-meters br0], [0])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn dump-meters br0 --oneline], [0], [stdout])
+AT_CHECK([strip_xids < stdout], [0], [dnl
+OFPST_METER_CONFIG reply (OF1.3):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
+dnl This checks basic meter operations in file.
+AT_SETUP([ofproto - add modify and delete meter in files (OpenFlow 1.3)])
+OVS_VSWITCHD_START
+AT_DATA([meters.txt], [dnl
+add meter=12 pktps burst stats bands=type=drop rate=1 burst_size=1
+add meter=34 pktps burst stats bands=type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+add meter=56 pktps burst stats bands=type=drop rate=2 burst_size=2 type=drop rate=10 burst_size=10
+modify meter=12 kbps burst stats bands=type=drop rate=1 burst_size=1
+modify meter=34 kbps burst stats bands=type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+delete meter=56
+])
+AT_CHECK([ovs-ofctl -O openflow13 -vwarn add-meters br0 meters.txt])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn dump-meters br0 --oneline], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sort -f], [0], [dnl
+meter=12 kbps burst stats bands= type=drop rate=1 burst_size=1
+meter=34 kbps burst stats bands= type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+OFPST_METER_CONFIG reply (OF1.3):
+])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn mod-meter br0 "meter=12 pktps burst stats bands=type=drop rate=2 burst_size=2"])
+AT_CHECK([ovs-ofctl -O OpenFlow13 -vwarn dump-meters br0 --oneline], [0], [stdout])
+AT_CHECK([strip_xids < stdout | sort -f], [0], [dnl
+meter=12 pktps burst stats bands= type=drop rate=2 burst_size=2
+meter=34 kbps burst stats bands= type=drop rate=1 burst_size=1 type=drop rate=10 burst_size=10
+OFPST_METER_CONFIG reply (OF1.3):
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
\ No newline at end of file
@@ -492,23 +492,35 @@ the \fBBridge\fR table). For more information, see ``Q: What versions
of OpenFlow does Open vSwitch support?'' in the Open vSwitch FAQ.
.
.IP "\fBadd\-meter \fIswitch meter\fR"
+.IQ "\fBadd\-meter \fIswitch - < file\fR"
Add a meter entry to \fIswitch\fR's tables. The \fImeter\fR syntax is
described in section \fBMeter Syntax\fR, below.
.
+.IP "\fBadd\-meters \fIswitch file\fR"
+Add each meter entry to \fIswitch\fR's tables. Each meter specification
+(each line in file) may start with \fBadd\fI, \fBmodify\fI or \fBdelete\fI
+keyword to specify whether a meter is to be added, modified, or deleted.
+For backwards compatibility a meter specification without one of these keywords
+is treated as a meter add. The \fImeter\fR syntax is described in section
+\fBMeter Syntax\fR, below.
+.
.IP "\fBmod\-meter \fIswitch meter\fR"
+.IQ "\fBmod\-meter \fIswitch - < file\fR"
Modify an existing meter.
.
.IP "\fBdel\-meters \fIswitch\fR [\fImeter\fR]"
+.IQ "\fBdel\-meters \fIswitch\fR - < file"
Delete entries from \fIswitch\fR's meter table. To delete only a
-specific meter, specify its number as \fImeter\fR. Otherwise, if
+specific meter, specify a meter syntax \fBmeter=\fIid\fR. Otherwise, if
\fImeter\fR is omitted, or if it is specified as \fBall\fR, then all
meters are deleted.
.
-.IP "\fBdump\-meters \fIswitch\fR [\fImeter\fR]"
+.IP "[\fB\-\-oneline\fR] \fBdump\-meters \fIswitch\fR [\fImeter\fR]"
Print entries from \fIswitch\fR's meter table. To print only a
-specific meter, specify its number as \fImeter\fR. Otherwise, if
+specific meter, specify a meter syntax \fBmeter=\fIid\fR. Otherwise, if
\fImeter\fR is omitted, or if it is specified as \fBall\fR, then all
-meters are printed.
+meters are printed. With \fB\-\-oneline\fR, band information will be
+combined into one line.
.
.IP "\fBmeter\-stats \fIswitch\fR [\fImeter\fR]"
Print meter statistics. \fImeter\fR can specify a single meter with
@@ -1342,6 +1354,11 @@ includes flow duration, packet and byte counts, and idle and hard age
in its output. With \fB\-\-no\-stats\fR, it omits all of these, as
well as cookie values and table IDs if they are zero.
.
+.IP "\fB\-\-oneline\fR"
+The \fBdump\-meters\fR command prints each band in a separate line by
+default. With \fB\-\-oneline\fR, all bands will be printed in a single
+line. This is useful for dumping meters to a file and restoring them.
+.
.IP "\fB\-\-read-only\fR"
Do not execute read/write commands.
.
@@ -157,6 +157,9 @@ static int print_pcap = 0;
/* --raw: Makes "ofp-print" read binary data from stdin. */
static int raw = 0;
+/* --oneline: show meter config in a single line. */
+static bool oneline = false;
+
static const struct ovs_cmdl_command *get_all_commands(void);
OVS_NO_RETURN static void usage(void);
@@ -217,6 +220,7 @@ parse_options(int argc, char *argv[])
OPT_COLOR,
OPT_MAY_CREATE,
OPT_READ_ONLY,
+ OPT_ONELINE,
DAEMON_OPTION_ENUMS,
OFP_VERSION_OPTION_ENUMS,
VLOG_OPTION_ENUMS,
@@ -245,6 +249,7 @@ parse_options(int argc, char *argv[])
{"pcap", no_argument, &print_pcap, 1},
{"raw", no_argument, &raw, 1},
{"read-only", no_argument, NULL, OPT_READ_ONLY},
+ {"oneline", no_argument, NULL, OPT_ONELINE},
DAEMON_LONG_OPTIONS,
OFP_VERSION_LONG_OPTIONS,
VLOG_LONG_OPTIONS,
@@ -314,6 +319,10 @@ parse_options(int argc, char *argv[])
ovs_cmdl_print_options(long_options);
exit(EXIT_SUCCESS);
+ case OPT_ONELINE:
+ oneline = true;
+ break;
+
case OPT_BUNDLE:
bundle = true;
break;
@@ -390,6 +399,10 @@ parse_options(int argc, char *argv[])
}
}
+ if (oneline) {
+ verbosity = OFP_ONELINE_SET(verbosity);
+ }
+
ctl_timeout_setup(timeout);
if (n_criteria) {
@@ -475,9 +488,10 @@ usage(void)
" dump-group-stats SWITCH [GROUP] print group statistics\n"
" queue-get-config SWITCH [PORT] print queue config for PORT\n"
" add-meter SWITCH METER add meter described by METER\n"
+ " add-meters SWITCH FILE add meters from FILE\n"
" mod-meter SWITCH METER modify specific METER\n"
" del-meters SWITCH [METER] delete meters matching METER\n"
- " dump-meters SWITCH [METER] print METER configuration\n"
+ " dump-meters SWITCH [METER] print METER entries\n"
" meter-stats SWITCH [METER] print meter statistics\n"
" meter-features SWITCH print meter features\n"
" add-tlv-map SWITCH MAP add TLV option MAPpings\n"
@@ -515,6 +529,7 @@ usage(void)
" --rsort[=field] sort in descending order\n"
" --names show port names instead of numbers\n"
" --no-names show port numbers, but not names\n"
+ " --oneline show meter bands in a single line\n"
" --unixctl=SOCKET set control socket name\n"
" --color[=always|never|auto] control use of color in output\n"
" -h, --help display this help message\n"
@@ -1443,7 +1458,7 @@ set_protocol_for_flow_dump(struct vconn *vconn,
if (usable_protocols & allowed_protocols) {
ovs_fatal(0, "switch does not support any of the usable flow "
"formats (%s)", usable_s);
-} else {
+ } else {
char *allowed_s = ofputil_protocols_to_string(allowed_protocols);
ovs_fatal(0, "none of the usable flow formats (%s) is among the "
"allowed flow formats (%s)", usable_s, allowed_s);
@@ -4084,57 +4099,107 @@ ofctl_diff_flows(struct ovs_cmdl_context *ctx)
}
static void
-ofctl_meter_mod__(const char *bridge, const char *str, int command)
+ofctl_meter_mod__(const char *remote, struct ofputil_meter_mod *mms,
+ size_t n_mms, enum ofputil_protocol usable_protocols)
{
- struct ofputil_meter_mod mm;
- struct vconn *vconn;
enum ofputil_protocol protocol;
- enum ofputil_protocol usable_protocols;
+ struct ofputil_meter_mod *mm;
enum ofp_version version;
+ struct ofpbuf *request;
+ struct vconn *vconn;
+ size_t i;
- memset(&mm, 0, sizeof mm);
- if (str) {
+ protocol = open_vconn_for_flow_mod(remote, &vconn, usable_protocols);
+ version = ofputil_protocol_to_ofp_version(protocol);
+
+ for (i = 0; i < n_mms; i++) {
+ mm = &mms[i];
+ request = ofputil_encode_meter_mod(version, mm);
+ transact_noreply(vconn, request);
+ free(mm->meter.bands);
+ }
+
+ vconn_close(vconn);
+}
+
+static void
+ofctl_meter_mod_file(int argc OVS_UNUSED, char *argv[], int command)
+{
+ enum ofputil_protocol usable_protocols;
+ struct ofputil_meter_mod *mms = NULL;
+ size_t n_mms = 0;
+ char *error;
+
+ if (command == OFPMC13_ADD) {
+ /* Allow the file to specify a mix of commands. If none specified at
+ * the beginning of any given line, then the default is OFPMC13_ADD, so
+ * this is backwards compatible. */
+ command = -2;
+ }
+ error = parse_ofp_meter_mod_file(argv[2], command,
+ &mms, &n_mms, &usable_protocols);
+ if (error) {
+ ovs_fatal(0, "%s", error);
+ }
+ ofctl_meter_mod__(argv[1], mms, n_mms, usable_protocols);
+ free(mms);
+}
+
+static void
+ofctl_meter_mod(int argc, char *argv[], uint16_t command)
+{
+ if (argc > 2 && !strcmp(argv[2], "-")) {
+ ofctl_meter_mod_file(argc, argv, command);
+ } else {
+ enum ofputil_protocol usable_protocols;
+ struct ofputil_meter_mod mm;
char *error;
- error = parse_ofp_meter_mod_str(&mm, str, command, &usable_protocols);
+ memset(&mm, 0, sizeof mm);
+ error = parse_ofp_meter_mod_str(&mm, argc > 2 ? argv[2] : "", 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;
+ ofctl_meter_mod__(argv[1], &mm, 1, usable_protocols);
}
-
- 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));
- free(mm.meter.bands);
- vconn_close(vconn);
}
-static void
-ofctl_meter_request__(const char *bridge, const char *str,
- enum ofputil_meter_request_type type)
+static struct vconn *
+prepare_dump_meters(const char *bridge, const char *str,
+ struct ofputil_meter_mod *mm,
+ enum ofputil_protocol *protocolp)
{
- struct ofputil_meter_mod mm;
struct vconn *vconn;
enum ofputil_protocol usable_protocols;
enum ofputil_protocol protocol;
- enum ofp_version version;
- memset(&mm, 0, sizeof mm);
if (str) {
char *error;
- error = parse_ofp_meter_mod_str(&mm, str, -1, &usable_protocols);
+ 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;
+ mm->meter.meter_id = OFPM13_ALL;
}
- protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols);
+ protocol = open_vconn(bridge, &vconn);
+ *protocolp = set_protocol_for_flow_dump(vconn, protocol, usable_protocols);
+ return vconn;
+}
+
+static void
+ofctl_meter_request__(const char *bridge, const char *str,
+ enum ofputil_meter_request_type type)
+{
+ enum ofputil_protocol protocol;
+ struct ofputil_meter_mod mm;
+ enum ofp_version version;
+ struct vconn *vconn;
+
+ memset(&mm, 0, sizeof mm);
+ vconn = prepare_dump_meters(bridge, str, &mm, &protocol);
version = ofputil_protocol_to_ofp_version(protocol);
dump_transaction(vconn, ofputil_encode_meter_request(version, type,
mm.meter.meter_id));
@@ -4142,23 +4207,28 @@ ofctl_meter_request__(const char *bridge, const char *str,
vconn_close(vconn);
}
-
static void
ofctl_add_meter(struct ovs_cmdl_context *ctx)
{
- ofctl_meter_mod__(ctx->argv[1], ctx->argv[2], OFPMC13_ADD);
+ ofctl_meter_mod(ctx->argc, ctx->argv, OFPMC13_ADD);
+}
+
+static void
+ofctl_add_meters(struct ovs_cmdl_context *ctx)
+{
+ ofctl_meter_mod_file(ctx->argc, ctx->argv, OFPMC13_ADD);
}
static void
ofctl_mod_meter(struct ovs_cmdl_context *ctx)
{
- ofctl_meter_mod__(ctx->argv[1], ctx->argv[2], OFPMC13_MODIFY);
+ ofctl_meter_mod(ctx->argc, ctx->argv, OFPMC13_MODIFY);
}
static void
ofctl_del_meters(struct ovs_cmdl_context *ctx)
{
- ofctl_meter_mod__(ctx->argv[1], ctx->argc > 2 ? ctx->argv[2] : NULL, OFPMC13_DELETE);
+ ofctl_meter_mod(ctx->argc, ctx->argv, OFPMC13_DELETE);
}
static void
@@ -5072,15 +5142,17 @@ static const struct ovs_cmdl_command all_commands[] = {
2, 2, ofctl_diff_flows, OVS_RW },
{ "add-meter", "switch meter",
2, 2, ofctl_add_meter, OVS_RW },
+ { "add-meters", "switch file",
+ 2, 2, ofctl_add_meters, OVS_RW },
{ "mod-meter", "switch meter",
2, 2, ofctl_mod_meter, OVS_RW },
- { "del-meter", "switch meter",
+ { "del-meter", "switch [meter]",
1, 2, ofctl_del_meters, OVS_RW },
{ "del-meters", "switch",
1, 2, ofctl_del_meters, OVS_RW },
{ "dump-meter", "switch meter",
1, 2, ofctl_dump_meters, OVS_RO },
- { "dump-meters", "switch",
+ { "dump-meters", "switch [meter]",
1, 2, ofctl_dump_meters, OVS_RO },
{ "meter-stats", "switch [meter]",
1, 2, ofctl_meter_stats, OVS_RO },
@@ -139,6 +139,9 @@ save_flows () {
echo "ovs-ofctl -O $ofp_version add-groups ${bridge} \
\"$workdir/$bridge.groups.dump\" ${bundle}"
+ echo "ovs-ofctl -O $ofp_version add-meters ${bridge} \
+ \"$workdir/$bridge.meters.dump\""
+
echo "ovs-ofctl -O $ofp_version replace-flows ${bridge} \
\"$workdir/$bridge.flows.dump\" ${bundle}"
@@ -147,6 +150,11 @@ save_flows () {
-e '/^NXST_GROUP_DESC/d' > \
"$workdir/$bridge.groups.dump"
+ ovs-ofctl -O $ofp_version dump-meters "$bridge" --oneline | \
+ sed -e '/^OFPST_METER_CONFIG/d' \
+ -e '/^NXST_METER_CONFIG/d' > \
+ "$workdir/$bridge.meters.dump"
+
ovs-ofctl -O $ofp_version dump-flows --no-names --no-stats "$bridge" | \
sed -e '/NXST_FLOW/d' \
-e '/OFPST_FLOW/d' \
put dump-meters' result in one line so add-meters can handle. save and restore meters when restart ovs. bundle functions are not implemented in this patch. Signed-off-by: Wan Junjie <wanjunjie@bytedance.com> --- v11: add OFP_ prefix to macro add testcases for meters v10: merge oneline to verbosity in parse_options ofp_to_string__ handle verbosity bits right v9: fix verbosity mask bits for testcase apologies for mess v8: fix missing code for testcase v7: typo in code v6: code style v5: merge oneline to verbosity higher bits remove duplicate dump_meters code v4: code refactor according to comments v3: add '--oneline' option for dump-meter(s) command v2: fix failed testcases, as dump-meters format changes --- include/openvswitch/ofp-meter.h | 9 +- include/openvswitch/ofp-print.h | 10 +++ lib/ofp-meter.c | 100 ++++++++++++++++++++++- lib/ofp-print.c | 20 +++-- tests/dpif-netdev.at | 44 ++++++++-- tests/ovs-ofctl.at | 70 ++++++++++++++++ utilities/ovs-ofctl.8.in | 25 +++++- utilities/ovs-ofctl.c | 140 ++++++++++++++++++++++++-------- utilities/ovs-save | 8 ++ 9 files changed, 374 insertions(+), 52 deletions(-)