[ovs-dev] [PATCH 2/2] ofproto: Track subfacet stats in the backer.

Ethan Jackson ethan at nicira.com
Wed Jun 5 02:18:34 UTC 2013


Subfacets being per-datapath entities, their statistics are really
only interesting at per-datapath granularity.  This patch moves
them to the dpif_backer and makes some related simplifications.

Signed-off-by: Ethan Jackson <ethan at nicira.com>
---
 ofproto/ofproto-dpif-unixctl.man |    6 +-
 ofproto/ofproto-dpif.c           |  360 ++++++++++++++++++--------------------
 tests/ofproto-dpif.at            |   74 +++-----
 tests/tunnel.at                  |  162 ++++++-----------
 4 files changed, 258 insertions(+), 344 deletions(-)

diff --git a/ofproto/ofproto-dpif-unixctl.man b/ofproto/ofproto-dpif-unixctl.man
index daacd3a..0512b21 100644
--- a/ofproto/ofproto-dpif-unixctl.man
+++ b/ofproto/ofproto-dpif-unixctl.man
@@ -5,15 +5,11 @@ equivalent \fBovs\-dpctl\fR commands.
 .IP "\fBdpif/dump\-dps\fR"
 Prints the name of each configured datapath on a separate line.
 .
-.IP "\fBdpif/show\fR [\fIdp\fR...]"
+.IP "\fBdpif/show\fR"
 Prints a summary of configured datapaths, including statistics and a
 list of connected ports.  The port information includes the OpenFlow
 port number, datapath port number, and the type.  (The local port is
 identified as OpenFlow port 65534.)
-.IP
-If one or more datapaths are specified, information on only those
-datapaths are displayed.  Otherwise, information about all configured
-datapaths are shown.
 .
 .IP "\fBdpif/dump\-flows \fIdp\fR"
 Prints to the console all flow entries in datapath \fIdp\fR's
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 327a298..4fb4ddf 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -635,6 +635,11 @@ struct drop_key {
     size_t key_len;
 };
 
+struct avg_subfacet_rates {
+    double add_rate;   /* Moving average of new flows created per minute. */
+    double del_rate;   /* Moving average of flows deleted per minute. */
+};
+
 /* All datapaths of a given type share a single dpif backer instance. */
 struct dpif_backer {
     char *type;
@@ -651,6 +656,32 @@ struct dpif_backer {
 
     struct hmap drop_keys; /* Set of dropped odp keys. */
     bool recv_set_enable; /* Enables or disables receiving packets. */
+
+    /* Subfacet statistics.
+     *
+     * These keep track of the total number of subfacets added and deleted and
+     * flow life span.  They are useful for computing the flow rates stats
+     * exposed via "ovs-appctl dpif/show".  The goal is to learn about
+     * traffic patterns in ways that we can use later to improve Open vSwitch
+     * performance in new situations.  */
+    long long int created;           /* Time when it is created. */
+    unsigned max_n_subfacet;         /* Maximum number of flows */
+    unsigned avg_n_subfacet;         /* Average number of flows. */
+    long long int avg_subfacet_life; /* Average life span of subfacets. */
+
+    /* The average number of subfacets... */
+    struct avg_subfacet_rates hourly;   /* ...over the last hour. */
+    struct avg_subfacet_rates daily;    /* ...over the last day. */
+    struct avg_subfacet_rates lifetime; /* ...over the switch lifetime. */
+    long long int last_minute;          /* Last time 'hourly' was updated. */
+
+    /* Number of subfacets added or deleted since 'last_minute'. */
+    unsigned subfacet_add_count;
+    unsigned subfacet_del_count;
+
+    /* Number of subfacets added or deleted from 'created' to 'last_minute.' */
+    unsigned long long int total_subfacet_add_count;
+    unsigned long long int total_subfacet_del_count;
 };
 
 /* All existing ofproto_backer instances, indexed by ofproto->up.type. */
@@ -659,14 +690,7 @@ static struct shash all_dpif_backers = SHASH_INITIALIZER(&all_dpif_backers);
 static void drop_key_clear(struct dpif_backer *);
 static struct ofport_dpif *
 odp_port_to_ofport(const struct dpif_backer *, uint32_t odp_port);
-
-struct avg_subfacet_rates {
-    double add_rate;     /* Moving average of new flows created per minute. */
-    double del_rate;     /* Moving average of flows deleted per minute. */
-};
-static void show_dp_rates(struct ds *ds, const char *heading,
-                          const struct avg_subfacet_rates *rates);
-static void exp_mavg(double *avg, int base, double new);
+static void update_moving_averages(struct dpif_backer *backer);
 
 struct ofproto_dpif {
     struct hmap_node all_ofproto_dpifs_node; /* In 'all_ofproto_dpifs'. */
@@ -720,33 +744,7 @@ struct ofproto_dpif {
     /* Per ofproto's dpif stats. */
     uint64_t n_hit;
     uint64_t n_missed;
-
-    /* Subfacet statistics.
-     *
-     * These keep track of the total number of subfacets added and deleted and
-     * flow life span.  They are useful for computing the flow rates stats
-     * exposed via "ovs-appctl dpif/show".  The goal is to learn about
-     * traffic patterns in ways that we can use later to improve Open vSwitch
-     * performance in new situations.  */
-    long long int created;         /* Time when it is created. */
-    unsigned int max_n_subfacet;   /* Maximum number of flows */
-    unsigned int avg_n_subfacet;   /* Average number of flows. */
-    long long int avg_subfacet_life_span;
-
-    /* The average number of subfacets... */
-    struct avg_subfacet_rates hourly; /* ...over the last hour. */
-    struct avg_subfacet_rates daily;  /* ...over the last day. */
-    long long int last_minute;        /* Last time 'hourly' was updated. */
-
-    /* Number of subfacets added or deleted since 'last_minute'. */
-    unsigned int subfacet_add_count;
-    unsigned int subfacet_del_count;
-
-    /* Number of subfacets added or deleted from 'created' to 'last_minute.' */
-    unsigned long long int total_subfacet_add_count;
-    unsigned long long int total_subfacet_del_count;
 };
-static void update_moving_averages(struct ofproto_dpif *ofproto);
 
 /* Defer flow mod completion until "ovs-appctl ofproto/unclog"?  (Useful only
  * for debugging the asynchronous flow_mod implementation.) */
@@ -1325,6 +1323,19 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
         return error;
     }
 
+    backer->max_n_subfacet = 0;
+    backer->created = time_msec();
+    backer->last_minute = backer->created;
+    memset(&backer->hourly, 0, sizeof backer->hourly);
+    memset(&backer->daily, 0, sizeof backer->daily);
+    memset(&backer->lifetime, 0, sizeof backer->lifetime);
+    backer->subfacet_add_count = 0;
+    backer->subfacet_del_count = 0;
+    backer->total_subfacet_add_count = 0;
+    backer->total_subfacet_del_count = 0;
+    backer->avg_n_subfacet = 0;
+    backer->avg_subfacet_life = 0;
+
     return error;
 }
 
@@ -1411,18 +1422,6 @@ construct(struct ofproto *ofproto_)
     ofproto->n_hit = 0;
     ofproto->n_missed = 0;
 
-    ofproto->max_n_subfacet = 0;
-    ofproto->created = time_msec();
-    ofproto->last_minute = ofproto->created;
-    memset(&ofproto->hourly, 0, sizeof ofproto->hourly);
-    memset(&ofproto->daily, 0, sizeof ofproto->daily);
-    ofproto->subfacet_add_count = 0;
-    ofproto->subfacet_del_count = 0;
-    ofproto->total_subfacet_add_count = 0;
-    ofproto->total_subfacet_del_count = 0;
-    ofproto->avg_subfacet_life_span = 0;
-    ofproto->avg_n_subfacet = 0;
-
     return error;
 }
 
@@ -4272,8 +4271,10 @@ static void expire_subfacets(struct ofproto_dpif *, int dp_max_idle);
 static int
 expire(struct dpif_backer *backer)
 {
+    long long int total_subfacet_life, now;
     struct ofproto_dpif *ofproto;
     int max_idle = INT32_MAX;
+    size_t n_subfacets;
 
     /* Periodically clear out the drop keys in an effort to keep them
      * relatively few. */
@@ -4282,8 +4283,9 @@ expire(struct dpif_backer *backer)
     /* Update stats for each flow in the backer. */
     update_stats(backer);
 
+    now = time_msec();
+    total_subfacet_life = n_subfacets = 0;
     HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
-        long long int avg_subfacet_life_span;
         struct rule *rule, *next_rule;
         struct subfacet *subfacet;
         int dp_max_idle;
@@ -4292,21 +4294,10 @@ expire(struct dpif_backer *backer)
             continue;
         }
 
-        avg_subfacet_life_span = 0;
-        if (!hmap_is_empty(&ofproto->subfacets)) {
-            long long int now = time_msec();
-            HMAP_FOR_EACH (subfacet, hmap_node, &ofproto->subfacets) {
-                avg_subfacet_life_span += now - subfacet->created;
-            }
-            avg_subfacet_life_span /= hmap_count(&ofproto->subfacets);
+        n_subfacets += hmap_count(&ofproto->subfacets);
+        HMAP_FOR_EACH (subfacet, hmap_node, &ofproto->subfacets) {
+            total_subfacet_life += now - subfacet->created;
         }
-        ofproto->avg_subfacet_life_span =
-            (ofproto->avg_subfacet_life_span + avg_subfacet_life_span) / 2;
-
-        ofproto->avg_n_subfacet += hmap_count(&ofproto->subfacets);
-        ofproto->avg_n_subfacet /= 2;
-        ofproto->max_n_subfacet = MAX(ofproto->max_n_subfacet,
-                                      hmap_count(&ofproto->subfacets));
 
         /* Expire subfacets that have been idle too long. */
         dp_max_idle = subfacet_max_idle(ofproto);
@@ -4334,6 +4325,14 @@ expire(struct dpif_backer *backer)
         }
     }
 
+    if (n_subfacets) {
+        backer->avg_subfacet_life += total_subfacet_life / n_subfacets;
+    }
+    backer->avg_subfacet_life /= 2;
+
+    backer->avg_n_subfacet = (n_subfacets + backer->avg_n_subfacet) / 2;
+    backer->max_n_subfacet = MAX(backer->max_n_subfacet, n_subfacets);
+
     return MIN(max_idle, 1000);
 }
 
@@ -4417,11 +4416,11 @@ update_stats(struct dpif_backer *backer)
     const struct dpif_flow_stats *stats;
     struct dpif_flow_dump dump;
     const struct nlattr *key;
-    struct ofproto_dpif *ofproto;
     size_t key_len;
 
     dpif_flow_dump_start(&dump, backer->dpif);
     while (dpif_flow_dump_next(&dump, &key, &key_len, NULL, NULL, &stats)) {
+        struct ofproto_dpif *ofproto;
         struct flow flow;
         struct subfacet *subfacet;
         uint32_t key_hash;
@@ -4451,9 +4450,7 @@ update_stats(struct dpif_backer *backer)
     }
     dpif_flow_dump_done(&dump);
 
-    HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
-        update_moving_averages(ofproto);
-    }
+    update_moving_averages(backer);
 }
 
 /* Calculates and returns the number of milliseconds of idle time after which
@@ -5232,7 +5229,7 @@ subfacet_create(struct facet *facet, struct flow_miss *miss,
     subfacet->dp_byte_count = 0;
     subfacet->path = SF_NOT_INSTALLED;
 
-    ofproto->subfacet_add_count++;
+    ofproto->backer->subfacet_add_count++;
     return subfacet;
 }
 
@@ -5245,7 +5242,7 @@ subfacet_destroy__(struct subfacet *subfacet)
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto);
 
     /* Update ofproto stats before uninstall the subfacet. */
-    ofproto->subfacet_del_count++;
+    ofproto->backer->subfacet_del_count++;
 
     subfacet_uninstall(subfacet);
     hmap_remove(&ofproto->subfacets, &subfacet->hmap_node);
@@ -8280,131 +8277,117 @@ ofproto_unixctl_dpif_dump_dps(struct unixctl_conn *conn, int argc OVS_UNUSED,
 }
 
 static void
-show_dp_format(const struct ofproto_dpif *ofproto, struct ds *ds)
+show_dp_rates(struct ds *ds, const char *heading,
+              const struct avg_subfacet_rates *rates)
+{
+    ds_put_format(ds, "%s add rate: %5.3f/min, del rate: %5.3f/min\n",
+                  heading, rates->add_rate, rates->del_rate);
+}
+
+static void
+dpif_show_backer(const struct dpif_backer *backer, struct ds *ds)
 {
-    const struct shash_node **ports;
-    int i;
-    struct avg_subfacet_rates lifetime;
-    unsigned long long int minutes;
-    const int min_ms = 60 * 1000; /* milliseconds in one minute. */
+    size_t n_hit, n_missed, n_subfacets, i;
+    const struct shash_node **ofprotos;
+    struct ofproto_dpif *ofproto;
+    struct shash ofproto_shash;
+    long long int minutes;
+
+    n_hit = n_missed = n_subfacets = 0;
+    HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+        if (ofproto->backer == backer) {
+            n_subfacets += hmap_count(&ofproto->subfacets);
+            n_missed += ofproto->n_missed;
+            n_hit += ofproto->n_hit;
+        }
+    }
 
-    minutes = (time_msec() - ofproto->created) / min_ms;
+    ds_put_format(ds, "%s: hit:%"PRIu64" missed:%"PRIu64"\n",
+                  dpif_name(backer->dpif), n_hit, n_missed);
+    ds_put_format(ds, "\tflows: cur: %zu, avg: %u, max: %u,"
+                  " life span: %lldms\n", n_subfacets,
+                  backer->avg_n_subfacet, backer->max_n_subfacet,
+                  backer->avg_subfacet_life);
 
-    if (minutes > 0) {
-        lifetime.add_rate = (double)ofproto->total_subfacet_add_count
-                            / minutes;
-        lifetime.del_rate = (double)ofproto->total_subfacet_del_count
-                            / minutes;
-    }else {
-        lifetime.add_rate = 0.0;
-        lifetime.del_rate = 0.0;
-    }
-
-    ds_put_format(ds, "%s (%s):\n", ofproto->up.name,
-                  dpif_name(ofproto->backer->dpif));
-    ds_put_format(ds,
-                  "\tlookups: hit:%"PRIu64" missed:%"PRIu64"\n",
-                  ofproto->n_hit, ofproto->n_missed);
-    ds_put_format(ds, "\tflows: cur: %zu, avg: %d, max: %d,"
-                  " life span: %llu(ms)\n",
-                  hmap_count(&ofproto->subfacets),
-                  ofproto->avg_n_subfacet,
-                  ofproto->max_n_subfacet,
-                  ofproto->avg_subfacet_life_span);
+    minutes = (time_msec() - backer->created) / (1000 * 60);
     if (minutes >= 60) {
-        show_dp_rates(ds, "\t\thourly avg:", &ofproto->hourly);
+        show_dp_rates(ds, "\thourly avg:", &backer->hourly);
     }
     if (minutes >= 60 * 24) {
-        show_dp_rates(ds, "\t\tdaily avg:",  &ofproto->daily);
+        show_dp_rates(ds, "\tdaily avg:",  &backer->daily);
     }
-    show_dp_rates(ds, "\t\toverall avg:",  &lifetime);
+    show_dp_rates(ds, "\toverall avg:",  &backer->lifetime);
 
-    ports = shash_sort(&ofproto->up.port_by_name);
-    for (i = 0; i < shash_count(&ofproto->up.port_by_name); i++) {
-        const struct shash_node *node = ports[i];
-        struct ofport *ofport = node->data;
-        const char *name = netdev_get_name(ofport->netdev);
-        const char *type = netdev_get_type(ofport->netdev);
-        uint32_t odp_port;
-
-        ds_put_format(ds, "\t%s %u/", name, ofport->ofp_port);
+    shash_init(&ofproto_shash);
+    ofprotos = get_ofprotos(&ofproto_shash);
+    for (i = 0; i < shash_count(&ofproto_shash); i++) {
+        struct ofproto_dpif *ofproto = ofprotos[i]->data;
+        const struct shash_node **ports;
+        size_t j;
 
-        odp_port = ofp_port_to_odp_port(ofproto, ofport->ofp_port);
-        if (odp_port != OVSP_NONE) {
-            ds_put_format(ds, "%"PRIu32":", odp_port);
-        } else {
-            ds_put_cstr(ds, "none:");
+        if (ofproto->backer != backer) {
+            continue;
         }
 
-        if (strcmp(type, "system")) {
-            struct netdev *netdev;
-            int error;
+        ds_put_format(ds, "\t%s: hit:%"PRIu64" missed:%"PRIu64"\n",
+                      ofproto->up.name, ofproto->n_hit, ofproto->n_missed);
+
+        ports = shash_sort(&ofproto->up.port_by_name);
+        for (j = 0; j < shash_count(&ofproto->up.port_by_name); j++) {
+            const struct shash_node *node = ports[j];
+            struct ofport *ofport = node->data;
+            struct smap config;
+            uint32_t odp_port;
 
-            ds_put_format(ds, " (%s", type);
+            ds_put_format(ds, "\t\t%s %u/", netdev_get_name(ofport->netdev),
+                          ofport->ofp_port);
 
-            error = netdev_open(name, type, &netdev);
-            if (!error) {
-                struct smap config;
+            odp_port = ofp_port_to_odp_port(ofproto, ofport->ofp_port);
+            if (odp_port != OVSP_NONE) {
+                ds_put_format(ds, "%"PRIu32":", odp_port);
+            } else {
+                ds_put_cstr(ds, "none:");
+            }
 
-                smap_init(&config);
-                error = netdev_get_config(netdev, &config);
-                if (!error) {
-                    const struct smap_node **nodes;
-                    size_t i;
+            ds_put_format(ds, " (%s", netdev_get_type(ofport->netdev));
 
-                    nodes = smap_sort(&config);
-                    for (i = 0; i < smap_count(&config); i++) {
-                        const struct smap_node *node = nodes[i];
-                        ds_put_format(ds, "%c %s=%s", i ? ',' : ':',
-                                      node->key, node->value);
-                    }
-                    free(nodes);
-                }
-                smap_destroy(&config);
+            smap_init(&config);
+            if (!netdev_get_config(ofport->netdev, &config)) {
+                const struct smap_node **nodes;
+                size_t i;
 
-                netdev_close(netdev);
+                nodes = smap_sort(&config);
+                for (i = 0; i < smap_count(&config); i++) {
+                    const struct smap_node *node = nodes[i];
+                    ds_put_format(ds, "%c %s=%s", i ? ',' : ':',
+                                  node->key, node->value);
+                }
+                free(nodes);
             }
+            smap_destroy(&config);
+
             ds_put_char(ds, ')');
+            ds_put_char(ds, '\n');
         }
-        ds_put_char(ds, '\n');
+        free(ports);
     }
-    free(ports);
+    shash_destroy(&ofproto_shash);
+    free(ofprotos);
 }
 
 static void
-ofproto_unixctl_dpif_show(struct unixctl_conn *conn, int argc,
-                          const char *argv[], void *aux OVS_UNUSED)
+ofproto_unixctl_dpif_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                          const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
-    const struct ofproto_dpif *ofproto;
-
-    if (argc > 1) {
-        int i;
-        for (i = 1; i < argc; i++) {
-            ofproto = ofproto_dpif_lookup(argv[i]);
-            if (!ofproto) {
-                ds_put_format(&ds, "Unknown bridge %s (use dpif/dump-dps "
-                                   "for help)", argv[i]);
-                unixctl_command_reply_error(conn, ds_cstr(&ds));
-                return;
-            }
-            show_dp_format(ofproto, &ds);
-        }
-    } else {
-        struct shash ofproto_shash;
-        const struct shash_node **sorted_ofprotos;
-        int i;
-
-        shash_init(&ofproto_shash);
-        sorted_ofprotos = get_ofprotos(&ofproto_shash);
-        for (i = 0; i < shash_count(&ofproto_shash); i++) {
-            const struct shash_node *node = sorted_ofprotos[i];
-            show_dp_format(node->data, &ds);
-        }
+    const struct shash_node **backers;
+    int i;
 
-        shash_destroy(&ofproto_shash);
-        free(sorted_ofprotos);
+    backers = shash_sort(&all_dpif_backers);
+    for (i = 0; i < shash_count(&all_dpif_backers); i++) {
+        dpif_show_backer(backers[i]->data, &ds);
     }
+    free(backers);
 
     unixctl_command_reply(conn, ds_cstr(&ds));
     ds_destroy(&ds);
@@ -8511,8 +8494,8 @@ ofproto_dpif_unixctl_init(void)
                              ofproto_dpif_self_check, NULL);
     unixctl_command_register("dpif/dump-dps", "", 0, 0,
                              ofproto_unixctl_dpif_dump_dps, NULL);
-    unixctl_command_register("dpif/show", "[bridge]", 0, INT_MAX,
-                             ofproto_unixctl_dpif_show, NULL);
+    unixctl_command_register("dpif/show", "", 0, 0, ofproto_unixctl_dpif_show,
+                             NULL);
     unixctl_command_register("dpif/dump-flows", "bridge", 1, 1,
                              ofproto_unixctl_dpif_dump_flows, NULL);
     unixctl_command_register("dpif/del-flows", "bridge", 1, 1,
@@ -8736,14 +8719,6 @@ odp_port_to_ofp_port(const struct ofproto_dpif *ofproto, uint32_t odp_port)
     }
 }
 
-static void
-show_dp_rates(struct ds *ds, const char *heading,
-              const struct avg_subfacet_rates *rates)
-{
-    ds_put_format(ds, "%s add rate: %5.3f/min, del rate: %5.3f/min\n",
-                  heading, rates->add_rate, rates->del_rate);
-}
-
 /* Compute exponentially weighted moving average, adding 'new' as the newest,
  * most heavily weighted element.  'base' designates the rate of decay: after
  * 'base' further updates, 'new''s weight in the EWMA decays to about 1/e
@@ -8755,26 +8730,37 @@ exp_mavg(double *avg, int base, double new)
 }
 
 static void
-update_moving_averages(struct ofproto_dpif *ofproto)
+update_moving_averages(struct dpif_backer *backer)
 {
     const int min_ms = 60 * 1000; /* milliseconds in one minute. */
+    long long int minutes = (time_msec() - backer->created) / min_ms;
+
+    if (minutes > 0) {
+        backer->lifetime.add_rate = (double) backer->total_subfacet_add_count
+            / minutes;
+        backer->lifetime.del_rate = (double) backer->total_subfacet_del_count
+            / minutes;
+    } else {
+        backer->lifetime.add_rate = 0.0;
+        backer->lifetime.del_rate = 0.0;
+    }
 
     /* Update hourly averages on the minute boundaries. */
-    if (time_msec() - ofproto->last_minute >= min_ms) {
-        exp_mavg(&ofproto->hourly.add_rate, 60, ofproto->subfacet_add_count);
-        exp_mavg(&ofproto->hourly.del_rate, 60, ofproto->subfacet_del_count);
+    if (time_msec() - backer->last_minute >= min_ms) {
+        exp_mavg(&backer->hourly.add_rate, 60, backer->subfacet_add_count);
+        exp_mavg(&backer->hourly.del_rate, 60, backer->subfacet_del_count);
 
         /* Update daily averages on the hour boundaries. */
-        if ((ofproto->last_minute - ofproto->created) / min_ms % 60 == 59) {
-            exp_mavg(&ofproto->daily.add_rate, 24, ofproto->hourly.add_rate);
-            exp_mavg(&ofproto->daily.del_rate, 24, ofproto->hourly.del_rate);
+        if ((backer->last_minute - backer->created) / min_ms % 60 == 59) {
+            exp_mavg(&backer->daily.add_rate, 24, backer->hourly.add_rate);
+            exp_mavg(&backer->daily.del_rate, 24, backer->hourly.del_rate);
         }
 
-        ofproto->total_subfacet_add_count += ofproto->subfacet_add_count;
-        ofproto->total_subfacet_del_count += ofproto->subfacet_del_count;
-        ofproto->subfacet_add_count = 0;
-        ofproto->subfacet_del_count = 0;
-        ofproto->last_minute += min_ms;
+        backer->total_subfacet_add_count += backer->subfacet_add_count;
+        backer->total_subfacet_del_count += backer->subfacet_del_count;
+        backer->subfacet_add_count = 0;
+        backer->subfacet_del_count = 0;
+        backer->last_minute += min_ms;
     }
 }
 
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index cd53c8b..4a605ca 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -2024,29 +2024,16 @@ ADD_OF_PORTS([br0], [1], [2])
 ADD_OF_PORTS([br1], [3])
 
 AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (dummy)
-	p2 2/2: (dummy)
-br1 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br1 65534/101: (dummy)
-	p3 3/3: (dummy)
-])
-
-AT_CHECK([ovs-appctl dpif/show br0], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (dummy)
-	p2 2/2: (dummy)
+dummy at ovs-dummy: hit:0 missed:0
+	flows: cur: 0, avg: 0, max: 0, life span: 0ms
+	overall avg: add rate: 0.000/min, del rate: 0.000/min
+	br0: hit:0 missed:0
+		br0 65534/100: (dummy)
+		p1 1/1: (dummy)
+		p2 2/2: (dummy)
+	br1: hit:0 missed:0
+		br1 65534/101: (dummy)
+		p3 3/3: (dummy)
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
@@ -2130,20 +2117,17 @@ warped
 ])
 
 AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:9 missed:1
-	flows: cur: 1, avg: 0, max: 1, life span: 1250(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p2 2/2: (dummy)
-	pbr0 1/none: (patch: peer=pbr1)
-br1 (dummy at ovs-dummy):
-	lookups: hit:4 missed:1
-	flows: cur: 1, avg: 0, max: 1, life span: 1250(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br1 65534/101: (dummy)
-	p3 3/3: (dummy)
-	pbr1 1/none: (patch: peer=pbr0)
+dummy at ovs-dummy: hit:13 missed:2
+	flows: cur: 2, avg: 1, max: 2, life span: 1250ms
+	overall avg: add rate: 0.000/min, del rate: 0.000/min
+	br0: hit:9 missed:1
+		br0 65534/100: (dummy)
+		p2 2/2: (dummy)
+		pbr0 1/none: (patch: peer=pbr1)
+	br1: hit:4 missed:1
+		br1 65534/101: (dummy)
+		p3 3/3: (dummy)
+		pbr1 1/none: (patch: peer=pbr0)
 ])
 
 AT_CHECK([ovs-appctl dpif/dump-flows br0 | STRIP_USED], [0], [dnl
@@ -2185,14 +2169,14 @@ AT_CHECK([ovs-appctl time/warp 10000], [0], [warped
 ])
 
 AT_CHECK([ovs-appctl dpif/show | sed 's/ 10[[0-9]]\{3\}(ms)$/ 10000(ms)/'], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:61
-	flows: cur: 0, avg: 0, max: 1, life span: 1666(ms)
-		hourly avg: add rate: 0.641/min, del rate: 0.641/min
-		overall avg: add rate: 1.000/min, del rate: 1.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (dummy)
-	p2 2/2: (dummy)
+dummy at ovs-dummy: hit:0 missed:61
+	flows: cur: 0, avg: 0, max: 1, life span: 1666ms
+	hourly avg: add rate: 0.641/min, del rate: 0.641/min
+	overall avg: add rate: 1.000/min, del rate: 1.000/min
+	br0: hit:0 missed:61
+		br0 65534/100: (dummy)
+		p1 1/1: (dummy)
+		p2 2/2: (dummy)
 ])
 
 OVS_VSWITCHD_STOP
diff --git a/tests/tunnel.at b/tests/tunnel.at
index 16f5aef..697c217 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -14,15 +14,11 @@ actions=IN_PORT
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (gre: remote_ip=1.1.1.1)
-	p2 2/1: (gre: local_ip=2.2.2.2, remote_ip=1.1.1.1)
-	p3 3/1: (gre: remote_ip=2.2.2.2)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (gre: remote_ip=1.1.1.1)
+		p2 2/1: (gre: local_ip=2.2.2.2, remote_ip=1.1.1.1)
+		p3 3/1: (gre: remote_ip=2.2.2.2)
 ])
 
 dnl remote_ip
@@ -41,15 +37,11 @@ dnl reconfigure, local_ip, remote_ip
 AT_CHECK([ovs-vsctl set Interface p2 type=gre options:local_ip=2.2.2.3 \
           options:df_default=false options:ttl=1 options:csum=true \
           -- set Interface p3 type=gre64])
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (gre: remote_ip=1.1.1.1)
-	p2 2/1: (gre: csum=true, df_default=false, local_ip=2.2.2.3, remote_ip=1.1.1.1, ttl=1)
-	p3 3/64: (gre64: remote_ip=2.2.2.2)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (gre: remote_ip=1.1.1.1)
+		p2 2/1: (gre: csum=true, df_default=false, local_ip=2.2.2.3, remote_ip=1.1.1.1, ttl=1)
+		p3 3/64: (gre64: remote_ip=2.2.2.2)
 ])
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x0,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags()),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
@@ -80,14 +72,10 @@ actions=2
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (gre: remote_ip=1.1.1.1)
-	p2 2/2: (dummy)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (gre: remote_ip=1.1.1.1)
+		p2 2/2: (dummy)
 ])
 
 dnl Tunnel CE and encapsulated packet CE
@@ -128,14 +116,10 @@ actions=output:1
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (gre: key=5, local_ip=2.2.2.2, remote_ip=1.1.1.1)
-	p2 2/2: (dummy)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (gre: key=5, local_ip=2.2.2.2, remote_ip=1.1.1.1)
+		p2 2/2: (dummy)
 ])
 
 dnl Basic
@@ -164,14 +148,10 @@ actions=output:1
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (gre: remote_ip=1.1.1.1, tos=inherit, ttl=inherit)
-	p2 2/2: (dummy)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (gre: remote_ip=1.1.1.1, tos=inherit, ttl=inherit)
+		p2 2/2: (dummy)
 ])
 
 dnl Basic
@@ -210,16 +190,12 @@ actions=set_tunnel:1,output:1,set_tunnel:2,output:2,set_tunnel:3,output:3,set_tu
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (gre: key=flow, remote_ip=1.1.1.1)
-	p2 2/1: (gre: key=flow, remote_ip=2.2.2.2)
-	p3 3/1: (gre: key=flow, remote_ip=3.3.3.3)
-	p4 4/1: (gre: key=flow, remote_ip=4.4.4.4)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (gre: key=flow, remote_ip=1.1.1.1)
+		p2 2/1: (gre: key=flow, remote_ip=2.2.2.2)
+		p3 3/1: (gre: key=flow, remote_ip=3.3.3.3)
+		p4 4/1: (gre: key=flow, remote_ip=4.4.4.4)
 ])
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
@@ -246,15 +222,11 @@ actions=IN_PORT,output:1,output:2,output:3
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (gre: key=1, remote_ip=1.1.1.1)
-	p2 2/1: (gre: in_key=2, out_key=3, remote_ip=1.1.1.1)
-	p3 3/1: (gre: out_key=5, remote_ip=1.1.1.1)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (gre: key=1, remote_ip=1.1.1.1)
+		p2 2/1: (gre: in_key=2, out_key=3, remote_ip=1.1.1.1)
+		p3 3/1: (gre: out_key=5, remote_ip=1.1.1.1)
 ])
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x1,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
@@ -302,17 +274,13 @@ tun_id=4,actions=output:5
 
 AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (gre: key=flow, remote_ip=1.1.1.1)
-	p2 2/1: (gre: key=3, remote_ip=3.3.3.3)
-	p3 3/3: (dummy)
-	p4 4/4: (dummy)
-	p5 5/5: (dummy)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (gre: key=flow, remote_ip=1.1.1.1)
+		p2 2/1: (gre: key=3, remote_ip=3.3.3.3)
+		p3 3/3: (dummy)
+		p4 4/4: (dummy)
+		p5 5/5: (dummy)
 ])
 
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'tunnel(tun_id=0x2,src=1.1.1.1,dst=2.2.2.2,tos=0x0,ttl=64,flags(key)),in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=9)'], [0], [stdout])
@@ -342,13 +310,9 @@ AT_SETUP([tunnel - VXLAN])
 OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \
                     options:remote_ip=1.1.1.1 ofport_request=1])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (vxlan: remote_ip=1.1.1.1)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (vxlan: remote_ip=1.1.1.1)
 ])
 
 OVS_VSWITCHD_STOP
@@ -358,13 +322,9 @@ AT_SETUP([tunnel - LISP])
 OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=lisp \
                     options:remote_ip=1.1.1.1 ofport_request=1])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (lisp: remote_ip=1.1.1.1)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (lisp: remote_ip=1.1.1.1)
 ])
 
 OVS_VSWITCHD_STOP
@@ -374,39 +334,27 @@ AT_SETUP([tunnel - different VXLAN UDP port])
 OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \
                     options:remote_ip=1.1.1.1 ofport_request=1 options:dst_port=4341])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (vxlan: dst_port=4341, remote_ip=1.1.1.1)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (vxlan: dst_port=4341, remote_ip=1.1.1.1)
 ])
 
 dnl change UDP port
 
 AT_CHECK([ovs-vsctl -- set Interface p1 options:dst_port=5000])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/2: (vxlan: dst_port=5000, remote_ip=1.1.1.1)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/2: (vxlan: dst_port=5000, remote_ip=1.1.1.1)
 ])
 
 dnl change UDP port to default
 
 AT_CHECK([ovs-vsctl -- set Interface p1 options:dst_port=4789])
 
-AT_CHECK([ovs-appctl dpif/show], [0], [dnl
-br0 (dummy at ovs-dummy):
-	lookups: hit:0 missed:0
-	flows: cur: 0, avg: 0, max: 0, life span: 0(ms)
-		overall avg: add rate: 0.000/min, del rate: 0.000/min
-	br0 65534/100: (dummy)
-	p1 1/1: (vxlan: remote_ip=1.1.1.1)
+AT_CHECK([ovs-appctl dpif/show | tail -n +5], [0], [dnl
+		br0 65534/100: (dummy)
+		p1 1/1: (vxlan: remote_ip=1.1.1.1)
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
-- 
1.7.9.5




More information about the dev mailing list