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 <wanjun...@bytedance.com>
---
 include/openvswitch/ofp-meter.h |  6 +++
 lib/ofp-meter.c                 | 94 ++++++++++++++++++++++++++++++++-
 utilities/ovs-ofctl.c           | 86 +++++++++++++++++++++++-------
 utilities/ovs-save              |  8 +++
 4 files changed, 174 insertions(+), 20 deletions(-)

diff --git a/include/openvswitch/ofp-meter.h b/include/openvswitch/ofp-meter.h
index 6776eae87..34ecbfdb2 100644
--- a/include/openvswitch/ofp-meter.h
+++ b/include/openvswitch/ofp-meter.h
@@ -79,6 +79,12 @@ 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;
diff --git a/lib/ofp-meter.c b/lib/ofp-meter.c
index 9ea40a0bf..5fb780ba3 100644
--- a/lib/ofp-meter.c
+++ b/lib/ofp-meter.c
@@ -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");
@@ -578,6 +579,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 +625,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) {
@@ -807,3 +831,71 @@ ofputil_format_meter_mod(struct ds *s, const struct 
ofputil_meter_mod *mm)
 
     ofputil_format_meter_config(s, &mm->meter);
 }
+
+/* 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;
+}
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index ede7f1e61..152836276 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -474,6 +474,7 @@ 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"
@@ -4012,32 +4013,70 @@ 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 ofputil_meter_mod *mm;
     struct vconn *vconn;
     enum ofputil_protocol protocol;
-    enum ofputil_protocol usable_protocols;
     enum ofp_version version;
+    struct ofpbuf *request;
+    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);
+        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
@@ -4074,19 +4113,26 @@ ofctl_meter_request__(const char *bridge, const char 
*str,
 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
@@ -5000,9 +5046,11 @@ 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 },
diff --git a/utilities/ovs-save b/utilities/ovs-save
index fb2025b76..e3551b9f9 100755
--- a/utilities/ovs-save
+++ b/utilities/ovs-save
@@ -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" | \
+            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' \
-- 
2.33.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to