Add support for coverage counters.
authorBen Pfaff <blp@nicira.com>
Tue, 5 May 2009 17:23:02 +0000 (10:23 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 5 May 2009 17:23:02 +0000 (10:23 -0700)
This commit implements a simple form of coverage instrumentation.  Points
in source code that are of interest must be explicitly annotated with
COVERAGE_INC.  The coverage counters may be logged at any time with
coverage_log().

This form of coverage instrumentation is intended to be so lightweight that
it can be enabled in production builds.  It is obviously not a substitute
for traditional coverage instrumentation with e.g. "gcov", but it is still
a useful debugging tool.

25 files changed:
lib/.gitignore
lib/automake.mk
lib/coverage-counters.h [new file with mode: 0644]
lib/coverage-scan.pl [new file with mode: 0755]
lib/coverage.c [new file with mode: 0644]
lib/coverage.h [new file with mode: 0644]
lib/dpif.c
lib/flow.c
lib/hmap.c
lib/mac-learning.c
lib/netdev.c
lib/netlink.c
lib/odp-util.c
lib/poll-loop.c
lib/process.c
lib/rconn.c
lib/timeval.c
lib/unixctl.c
lib/util.c
lib/vconn.c
lib/vlog-modules.def
secchan/ofproto.c
secchan/pktbuf.c
vswitchd/bridge.c
vswitchd/mgmt.c

index b069cc186bb900eac0c347d8cf080efe368bd22e..6a3f65ce14e6cdd3d34a7c34cded1d4f207abcca 100644 (file)
@@ -1,3 +1,4 @@
 /Makefile
 /Makefile.in
 /dhparams.c
+/coverage-counters.c
index 66edf4938396724e7ea12d01d27a1d39bc604e21..e76881aa91bd2a8b9c00ba94801edfcacf12bd9c 100644 (file)
@@ -12,6 +12,10 @@ lib_libopenflow_a_SOURCES = \
        lib/command-line.c \
        lib/command-line.h \
        lib/compiler.h \
+       lib/coverage.c \
+       lib/coverage.h \
+       lib/coverage-counters.c \
+       lib/coverage-counters.h \
        lib/csum.c \
        lib/csum.h \
        lib/daemon.c \
@@ -152,3 +156,28 @@ install-data-local:
        $(MKDIR_P) $(DESTDIR)$(RUNDIR)
        $(MKDIR_P) $(DESTDIR)$(PKIDIR)
        $(MKDIR_P) $(DESTDIR)$(LOGDIR)
+
+# All the source files that have coverage counters.
+COVERAGE_SOURCES = \
+       lib/dpif.c \
+       lib/flow.c \
+       lib/hmap.c \
+       lib/mac-learning.c \
+       lib/netdev.c \
+       lib/netlink.c \ 
+       lib/odp-util.c \
+       lib/poll-loop.c \
+       lib/process.c \
+       lib/rconn.c \
+       lib/timeval.c \
+       lib/unixctl.c \
+       lib/util.c \
+       lib/vconn.c \
+       secchan/ofproto.c \
+       secchan/pktbuf.c \
+       vswitchd/bridge.c \
+       vswitchd/mgmt.c
+lib/coverage-counters.c: $(COVERAGE_SOURCES) lib/coverage-scan.pl
+       (cd $(srcdir) && $(PERL) lib/coverage-scan.pl $(COVERAGE_SOURCES)) > $@.tmp
+       mv $@.tmp $@
+EXTRA_DIST += lib/coverage-scan.pl
diff --git a/lib/coverage-counters.h b/lib/coverage-counters.h
new file mode 100644 (file)
index 0000000..e6adbed
--- /dev/null
@@ -0,0 +1,42 @@
+/* Copyright (c) 2009 The Board of Trustees of The Leland Stanford Junior
+ * University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#ifndef COVERAGE_COUNTERS_H
+#define COVERAGE_COUNTERS_H 1
+
+#include <stddef.h>
+
+extern struct coverage_counter *coverage_counters[];
+extern size_t coverage_n_counters;
+
+#endif /* coverage.h */
diff --git a/lib/coverage-scan.pl b/lib/coverage-scan.pl
new file mode 100755 (executable)
index 0000000..f9dc2d8
--- /dev/null
@@ -0,0 +1,65 @@
+# Copyright (c) 2009 The Board of Trustees of The Leland Stanford Junior
+# University
+#
+# We are making the OpenFlow specification and associated documentation
+# (Software) available for public use and benefit with the expectation
+# that others will use, modify and enhance the Software and contribute
+# those enhancements back to the community. However, since we would
+# like to make the Software available for broadest use, with as few
+# restrictions as possible permission is hereby granted, free of
+# charge, to any person obtaining a copy of this Software to deal in
+# the Software under the copyrights without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# The name and trademarks of copyright holder(s) may NOT be used in
+# advertising or publicity pertaining to the Software or any
+# derivatives without specific, written prior permission.
+
+use strict;
+use warnings;
+
+my %counters;
+while (<>) {
+    my ($counter) = /^\s*COVERAGE_(?:INC|ADD)\s*\(\s*([a-zA-Z_][a-zA-Z_0-9]*)/
+      or next;
+    push (@{$counters{$counter}}, "$ARGV:$.");
+} continue {
+    # This magic resets $. from one file to the next.  See "perldoc -f eof".
+    close ARGV if eof;
+}
+
+print <<EOF;
+#include "coverage-counters.h"
+#include <stddef.h>
+#include "coverage.h"
+#include "util.h"
+
+EOF
+
+for my $counter (sort(keys(%counters))) {
+    my $locations = join(', ', @{$counters{$counter}});
+    print <<EOF;
+/* $locations */
+struct coverage_counter ${counter}_count = { "$counter", 0, 0 };
+
+EOF
+}
+print "struct coverage_counter *coverage_counters[] = {\n";
+print "    \&${_}_count,\n" foreach (sort(keys(%counters)));
+print "};\n";
+print "size_t coverage_n_counters = ARRAY_SIZE(coverage_counters);\n";
diff --git a/lib/coverage.c b/lib/coverage.c
new file mode 100644 (file)
index 0000000..4355f67
--- /dev/null
@@ -0,0 +1,95 @@
+/* Copyright (c) 2009 The Board of Trustees of The Leland Stanford Junior
+ * University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#include <config.h>
+#include "coverage.h"
+#include "coverage-counters.h"
+#include "dynamic-string.h"
+#include "util.h"
+
+#define THIS_MODULE VLM_coverage
+#include "vlog.h"
+
+static unsigned int epoch;
+
+static void
+coverage_log_counter(enum vlog_level level, const struct coverage_counter *c)
+{
+    VLOG(level, "%-24s %5u / %9llu", c->name, c->count, c->count + c->total);
+}
+
+/* Logs the coverage counters at the given vlog 'level'. */
+void
+coverage_log(enum vlog_level level)
+{
+    size_t i;
+    size_t n_never_hit;
+
+    if (!vlog_is_enabled(THIS_MODULE, level)) {
+        return;
+    }
+
+    n_never_hit = 0;
+    VLOG(level, "Event coverage (epoch %u/entire run):", epoch);
+    for (i = 0; i < coverage_n_counters; i++) {
+        struct coverage_counter *c = coverage_counters[i];
+        if (c->count) {
+            coverage_log_counter(level, c);
+        }
+    }
+    for (i = 0; i < coverage_n_counters; i++) {
+        struct coverage_counter *c = coverage_counters[i];
+        if (!c->count) {
+            if (c->total) {
+                coverage_log_counter(level, c);
+            } else {
+                n_never_hit++;
+            }
+        }
+    }
+    VLOG(level, "%zu events never hit", n_never_hit);
+}
+
+/* Advances to the next epoch of coverage, resetting all the counters to 0. */
+void
+coverage_clear(void)
+{
+    size_t i;
+
+    epoch++;
+    for (i = 0; i < coverage_n_counters; i++) {
+        struct coverage_counter *c = coverage_counters[i];
+        c->total += c->count;
+        c->count = 0;
+    }
+}
diff --git a/lib/coverage.h b/lib/coverage.h
new file mode 100644 (file)
index 0000000..1d5bcc2
--- /dev/null
@@ -0,0 +1,75 @@
+/* Copyright (c) 2009 The Board of Trustees of The Leland Stanford Junior
+ * University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#ifndef COVERAGE_H
+#define COVERAGE_H 1
+
+/* This file implements a simple form of coverage instrumentation.  Points in
+ * source code that are of interest must be explicitly annotated with
+ * COVERAGE_INC.  The coverage counters may be logged at any time with
+ * coverage_log().
+ *
+ * This form of coverage instrumentation is intended to be so lightweight that
+ * it can be enabled in production builds.  It is obviously not a substitute
+ * for traditional coverage instrumentation with e.g. "gcov", but it is still
+ * a useful debugging tool. */
+
+#include "vlog.h"
+
+/* A coverage counter. */
+struct coverage_counter {
+    const char *name;           /* Textual name. */
+    unsigned int count;         /* Count within the current epoch. */
+    unsigned long long int total; /* Total count over all epochs. */
+};
+
+/* Increments the counter with the given NAME.  Coverage counters need not be
+ * declared explicitly, but when you add the first coverage counter to a given
+ * file, you must also add that file to COVERAGE_SOURCES in lib/automake.mk. */
+#define COVERAGE_INC(NAME)                              \
+    do {                                                \
+        extern struct coverage_counter NAME##_count;    \
+        NAME##_count.count++;                           \
+    } while (0)
+
+/* Adds AMOUNT to the coverage counter with the given NAME. */
+#define COVERAGE_ADD(NAME, AMOUNT)                      \
+    do {                                                \
+        extern struct coverage_counter NAME##_count;    \
+        NAME##_count.count += AMOUNT;                   \
+    } while (0)
+
+void coverage_log(enum vlog_level);
+void coverage_clear(void);
+
+#endif /* coverage.h */
index 0ff68a5a2fb4946d444f486bfd283b5e4fb3f336..f30b0bbad31580f5633c18f9841b27c1d6ceb6a0 100644 (file)
@@ -51,6 +51,7 @@
 #include <sys/sysmacros.h>
 #include <unistd.h>
 
+#include "coverage.h"
 #include "dynamic-string.h"
 #include "flow.h"
 #include "netlink.h"
@@ -203,6 +204,7 @@ dpif_get_name(struct dpif *dpif, char *name, size_t name_size)
 int
 dpif_delete(struct dpif *dpif)
 {
+    COVERAGE_INC(dpif_destroy);
     return do_ioctl(dpif, ODP_DP_DESTROY, "ODP_DP_DESTROY", NULL);
 }
 
@@ -254,6 +256,8 @@ dpif_purge(struct dpif *dpif)
     unsigned int i;
     int error;
 
+    COVERAGE_INC(dpif_purge);
+
     error = dpif_get_dp_stats(dpif, &stats);
     if (error) {
         return error;
@@ -275,6 +279,7 @@ dpif_port_add(struct dpif *dpif, const char *devname, uint16_t port_no)
 {
     struct odp_port port;
 
+    COVERAGE_INC(dpif_port_add);
     memset(&port, 0, sizeof port);
     strncpy(port.devname, devname, sizeof port.devname);
     port.port = port_no;
@@ -294,6 +299,7 @@ int
 dpif_port_del(struct dpif *dpif, uint16_t port_no)
 {
     int tmp = port_no;
+    COVERAGE_INC(dpif_port_del);
     return do_ioctl(dpif, ODP_PORT_DEL, "ODP_PORT_DEL", &tmp);
 }
 
@@ -369,6 +375,7 @@ dpif_port_group_set(struct dpif *dpif, uint16_t group,
 {
     struct odp_port_group pg;
 
+    COVERAGE_INC(dpif_port_group_set);
     assert(n_ports <= UINT16_MAX);
     pg.group = group;
     pg.ports = (uint16_t *) ports;
@@ -397,6 +404,7 @@ dpif_port_group_get(const struct dpif *dpif, uint16_t group,
 int
 dpif_flow_flush(struct dpif *dpif)
 {
+    COVERAGE_INC(dpif_flow_flush);
     return do_ioctl(dpif, ODP_FLOW_FLUSH, "ODP_FLOW_FLUSH", NULL);
 }
 
@@ -461,6 +469,7 @@ int
 dpif_flow_put(struct dpif *dpif, struct odp_flow_put *put)
 {
     int error = do_ioctl(dpif, ODP_FLOW_PUT, NULL, put);
+    COVERAGE_INC(dpif_flow_put);
     if (should_log_flow_message(error)) {
         struct ds operation = DS_EMPTY_INITIALIZER;
         ds_put_cstr(&operation, "put");
@@ -488,6 +497,7 @@ dpif_flow_put(struct dpif *dpif, struct odp_flow_put *put)
 int
 dpif_flow_del(struct dpif *dpif, struct odp_flow *flow)
 {
+    COVERAGE_INC(dpif_flow_del);
     check_rw_odp_flow(flow);
     memset(&flow->stats, 0, sizeof flow->stats);
     return do_flow_ioctl(dpif, ODP_FLOW_DEL, flow, "delete flow", true);
@@ -496,6 +506,7 @@ dpif_flow_del(struct dpif *dpif, struct odp_flow *flow)
 int
 dpif_flow_get(const struct dpif *dpif, struct odp_flow *flow)
 {
+    COVERAGE_INC(dpif_flow_query);
     check_rw_odp_flow(flow);
     memset(&flow->stats, 0, sizeof flow->stats);
     return do_flow_ioctl(dpif, ODP_FLOW_GET, flow, "get flow", true);
@@ -508,6 +519,7 @@ dpif_flow_get_multiple(const struct dpif *dpif,
     struct odp_flowvec fv;
     size_t i;
 
+    COVERAGE_ADD(dpif_flow_query_multiple, n);
     fv.flows = flows;
     fv.n_flows = n;
     for (i = 0; i < n; i++) {
@@ -525,6 +537,7 @@ dpif_flow_list(const struct dpif *dpif, struct odp_flow flows[], size_t n,
     uint32_t i;
     int error;
 
+    COVERAGE_INC(dpif_flow_query_list);
     fv.flows = flows;
     fv.n_flows = n;
     if (RUNNING_ON_VALGRIND) {
@@ -541,6 +554,7 @@ dpif_flow_list(const struct dpif *dpif, struct odp_flow flows[], size_t n,
         VLOG_WARN_RL(&error_rl, "dp%u: flow list failed (%s)",
                      dpif->minor, strerror(error));
     } else {
+        COVERAGE_ADD(dpif_flow_query_list_n, fv.n_flows);
         *n_out = fv.n_flows;
         VLOG_DBG_RL(&dpmsg_rl, "dp%u: listed %zu flows", dpif->minor, *n_out);
     }
@@ -588,6 +602,7 @@ dpif_execute(struct dpif *dpif, uint16_t in_port,
 {
     int error;
 
+    COVERAGE_INC(dpif_execute);
     if (n_actions > 0) {
         struct odp_execute execute;
         memset(&execute, 0, sizeof execute);
@@ -620,6 +635,7 @@ dpif_execute(struct dpif *dpif, uint16_t in_port,
 int
 dpif_snat_add_port(struct dpif *dpif, const struct odp_snat_config *osc)
 {
+    COVERAGE_INC(dpif_snat_add_port);
     return do_ioctl(dpif, ODP_SNAT_ADD_PORT, "ODP_SNAT_ADD_PORT", osc);
 }
 
@@ -627,6 +643,7 @@ int
 dpif_snat_del_port(struct dpif *dpif, uint16_t port)
 {
     int tmp = port;
+    COVERAGE_INC(dpif_snat_del_port);
     return do_ioctl(dpif, ODP_SNAT_DEL_PORT, "ODP_SNAT_DEL_PORT", &tmp);
 }
 
@@ -663,6 +680,7 @@ dpif_recv(struct dpif *dpif, struct ofpbuf **bufp)
                 free(s);
             }
             *bufp = buf;
+            COVERAGE_INC(dpif_recv);
             return 0;
         } else {
             VLOG_WARN_RL(&error_rl, "dp%u: discarding message truncated "
@@ -790,8 +808,10 @@ again:
             if (!for_us) {
                 /* Not for us, try again. */
                 ofpbuf_delete(buf);
+                COVERAGE_INC(dpifmon_poll_false_wakeup);
                 goto again;
             }
+            COVERAGE_INC(dpifmon_poll_changed);
             *devnamep = xstrdup(devname);
         }
         ofpbuf_delete(buf);
index 156416a171a9d647deae430d27421bb5b14d6c80..d2545d5fe07d5b09da939b7178b4c8d7f17dc83f 100644 (file)
@@ -37,6 +37,7 @@
 #include <netinet/in.h>
 #include <stdlib.h>
 #include <string.h>
+#include "coverage.h"
 #include "dynamic-string.h"
 #include "hash.h"
 #include "ofpbuf.h"
@@ -105,6 +106,8 @@ flow_extract(struct ofpbuf *packet, uint16_t in_port, flow_t *flow)
     struct eth_header *eth;
     int retval = 0;
 
+    COVERAGE_INC(flow_extract);
+
     memset(flow, 0, sizeof *flow);
     flow->dl_vlan = htons(OFP_VLAN_NONE);
     flow->in_port = in_port;
index f05bdb7744655902f3391b9702afc33ad6609b55..e55e6076d9a2b114d41e218a1625d1a60a10a5ae 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
  * Junior University
  *
  * We are making the OpenFlow specification and associated documentation
@@ -35,6 +35,7 @@
 #include "hmap.h"
 #include <assert.h>
 #include <stdint.h>
+#include "coverage.h"
 #include "util.h"
 
 /* Initializes 'hmap' as an empty hash table. */
@@ -91,9 +92,14 @@ resize(struct hmap *hmap, size_t new_mask)
     }
     for (i = 0; i <= hmap->mask; i++) {
         struct hmap_node *node, *next;
+        int count = 0;
         for (node = hmap->buckets[i]; node; node = next) {
             next = node->next;
             hmap_insert_fast(&tmp, node, node->hash);
+            count++;
+        }
+        if (count > 5) {
+            COVERAGE_INC(hmap_pathological);
         }
     }
     hmap_swap(hmap, &tmp);
@@ -126,6 +132,7 @@ hmap_expand(struct hmap *hmap)
 {
     size_t new_mask = calc_mask(hmap->n);
     if (new_mask > hmap->mask) {
+        COVERAGE_INC(hmap_expand);
         resize(hmap, new_mask);
     }
 }
@@ -136,6 +143,7 @@ hmap_shrink(struct hmap *hmap)
 {
     size_t new_mask = calc_mask(hmap->n);
     if (new_mask < hmap->mask) {
+        COVERAGE_INC(hmap_shrink);
         resize(hmap, new_mask);
     }
 }
@@ -148,6 +156,7 @@ hmap_reserve(struct hmap *hmap, size_t n)
 {
     size_t new_mask = calc_mask(n);
     if (new_mask > hmap->mask) {
+        COVERAGE_INC(hmap_reserve);
         resize(hmap, new_mask);
     }
 }
index 73e1eef99bc5113351e0a683030bf48d12a782d9..f82e030b8b0b24a5834260be3472c3f228681424 100644 (file)
@@ -38,6 +38,7 @@
 #include <inttypes.h>
 #include <stdlib.h>
 
+#include "coverage.h"
 #include "hash.h"
 #include "list.h"
 #include "poll-loop.h"
@@ -225,6 +226,7 @@ mac_learning_learn(struct mac_learning *ml,
         tag_type old_tag = e->tag;
         e->port = src_port;
         e->tag = tag_create_random();
+        COVERAGE_INC(mac_learning_learned);
         return old_tag;
     }
     return 0;
@@ -283,6 +285,7 @@ mac_learning_run(struct mac_learning *ml, struct tag_set *set)
 {
     struct mac_entry *e;
     while (get_lru(ml, &e) && time_now() >= e->expires) {
+        COVERAGE_INC(mac_learning_expired);
         if (set) {
             tag_set_add(set, e->tag);
         }
index 5704777ca3129ffdfe2ba2437d34b0c3ca84b7c4..0935efa24ec8ddf6804bf6a3acb3062fd08d6eda 100644 (file)
@@ -59,6 +59,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "coverage.h"
 #include "dynamic-string.h"
 #include "fatal-signal.h"
 #include "list.h"
@@ -201,6 +202,7 @@ do_ethtool(struct netdev *netdev, struct ethtool_cmd *ecmd,
     ifr.ifr_data = (caddr_t) ecmd;
 
     ecmd->cmd = cmd;
+    COVERAGE_INC(netdev_ethtool);
     if (ioctl(netdev->netdev_fd, SIOCETHTOOL, &ifr) == 0) {
         return 0;
     } else {
@@ -419,6 +421,7 @@ do_open_netdev(const char *name, int ethertype, int tap_fd,
 
     init_netdev();
     *netdev_ = NULL;
+    COVERAGE_INC(netdev_open);
 
     /* Create raw socket. */
     netdev_fd = socket(PF_PACKET, SOCK_RAW,
@@ -590,6 +593,7 @@ netdev_recv(struct netdev *netdev, struct ofpbuf *buffer)
         }
         return errno;
     } else {
+        COVERAGE_INC(netdev_received);
         buffer->size += n_bytes;
 
         /* When the kernel internally sends out an Ethernet frame on an
@@ -657,6 +661,7 @@ netdev_send(struct netdev *netdev, const struct ofpbuf *buffer)
                      (int) n_bytes, buffer->size, netdev->name);
         return EMSGSIZE;
     } else {
+        COVERAGE_INC(netdev_sent);
         return 0;
     }
 }
@@ -803,6 +808,7 @@ netdev_get_in4(const struct netdev *netdev, struct in_addr *in4)
 
     strncpy(ifr.ifr_name, netdev->name, sizeof ifr.ifr_name);
     ifr.ifr_addr.sa_family = AF_INET;
+    COVERAGE_INC(netdev_get_in4);
     if (ioctl(af_inet_sock, SIOCGIFADDR, &ifr) == 0) {
         struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr;
         ip = sin->sin_addr;
@@ -838,6 +844,7 @@ do_set_addr(struct netdev *netdev, int sock,
 
     strncpy(ifr.ifr_name, netdev->name, sizeof ifr.ifr_name);
     make_in4_sockaddr(&ifr.ifr_addr, addr);
+    COVERAGE_INC(netdev_set_in4);
     error = ioctl(sock, ioctl_nr, &ifr) < 0 ? errno : 0;
     if (error) {
         VLOG_WARN("ioctl(%s): %s", ioctl_name, strerror(error));
@@ -875,6 +882,7 @@ netdev_add_router(struct in_addr router)
     make_in4_sockaddr(&rt.rt_gateway, router);
     make_in4_sockaddr(&rt.rt_genmask, any);
     rt.rt_flags = RTF_UP | RTF_GATEWAY;
+    COVERAGE_INC(netdev_add_router);
     error = ioctl(af_inet_sock, SIOCADDRT, &rt) < 0 ? errno : 0;
     if (error) {
         VLOG_WARN("ioctl(SIOCADDRT): %s", strerror(error));
@@ -994,6 +1002,7 @@ netdev_arp_lookup(const struct netdev *netdev,
     r.arp_ha.sa_family = ARPHRD_ETHER;
     r.arp_flags = 0;
     strncpy(r.arp_dev, netdev->name, sizeof r.arp_dev);
+    COVERAGE_INC(netdev_arp_lookup);
     retval = ioctl(af_inet_sock, SIOCGARP, &r) < 0 ? errno : 0;
     if (!retval) {
         memcpy(mac, r.arp_ha.sa_data, ETH_ADDR_LEN);
@@ -1176,6 +1185,7 @@ netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
 {
     int error;
 
+    COVERAGE_INC(netdev_get_stats);
     if (use_netlink_stats) {
         int ifindex;
 
@@ -1206,6 +1216,7 @@ netdev_nodev_set_policing(const char *netdev_name, uint32_t kbits_rate,
 
     init_netdev();
 
+    COVERAGE_INC(netdev_set_policing);
     if (kbits_rate) {
         if (!kbits_burst) {
             /* Default to 10 kilobits if not specified. */
@@ -1318,6 +1329,7 @@ netdev_get_vlan_vid(const char *netdev_name, int *vlan_vid)
     int error;
     char *fn;
 
+    COVERAGE_INC(netdev_get_vlan_vid);
     fn = xasprintf("/proc/net/vlan/%s", netdev_name);
     stream = fopen(fn, "r");
     if (!stream) {
@@ -1419,6 +1431,7 @@ restore_flags(struct netdev *netdev)
 
     /* Get current flags. */
     strncpy(ifr.ifr_name, netdev->name, sizeof ifr.ifr_name);
+    COVERAGE_INC(netdev_get_flags);
     if (ioctl(netdev->netdev_fd, SIOCGIFFLAGS, &ifr) < 0) {
         return errno;
     }
@@ -1428,6 +1441,7 @@ restore_flags(struct netdev *netdev)
     if ((ifr.ifr_flags ^ netdev->save_flags) & restore_flags) {
         ifr.ifr_flags &= ~restore_flags;
         ifr.ifr_flags |= netdev->save_flags & restore_flags;
+        COVERAGE_INC(netdev_set_flags);
         if (ioctl(netdev->netdev_fd, SIOCSIFFLAGS, &ifr) < 0) {
             return errno;
         }
@@ -1452,6 +1466,7 @@ get_flags(const char *netdev_name, int *flags)
 {
     struct ifreq ifr;
     strncpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
+    COVERAGE_INC(netdev_get_flags);
     if (ioctl(af_inet_sock, SIOCGIFFLAGS, &ifr) < 0) {
         VLOG_ERR("ioctl(SIOCGIFFLAGS) on %s device failed: %s",
                  netdev_name, strerror(errno));
@@ -1467,6 +1482,7 @@ set_flags(const char *netdev_name, int flags)
     struct ifreq ifr;
     strncpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
     ifr.ifr_flags = flags;
+    COVERAGE_INC(netdev_set_flags);
     if (ioctl(af_inet_sock, SIOCSIFFLAGS, &ifr) < 0) {
         VLOG_ERR("ioctl(SIOCSIFFLAGS) on %s device failed: %s",
                  netdev_name, strerror(errno));
@@ -1481,6 +1497,7 @@ do_get_ifindex(const char *netdev_name)
     struct ifreq ifr;
 
     strncpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
+    COVERAGE_INC(netdev_get_ifindex);
     if (ioctl(af_inet_sock, SIOCGIFINDEX, &ifr) < 0) {
         VLOG_WARN_RL(&rl, "ioctl(SIOCGIFINDEX) on %s device failed: %s",
                      netdev_name, strerror(errno));
@@ -1512,6 +1529,7 @@ get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN],
 
     memset(&ifr, 0, sizeof ifr);
     strncpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
+    COVERAGE_INC(netdev_get_hwaddr);
     if (ioctl(af_inet_sock, SIOCGIFHWADDR, &ifr) < 0) {
         VLOG_ERR("ioctl(SIOCGIFHWADDR) on %s device failed: %s",
                  netdev_name, strerror(errno));
@@ -1539,6 +1557,7 @@ set_etheraddr(const char *netdev_name, int hwaddr_family,
     strncpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
     ifr.ifr_hwaddr.sa_family = hwaddr_family;
     memcpy(ifr.ifr_hwaddr.sa_data, mac, ETH_ADDR_LEN);
+    COVERAGE_INC(netdev_set_hwaddr);
     if (ioctl(af_inet_sock, SIOCSIFHWADDR, &ifr) < 0) {
         VLOG_ERR("ioctl(SIOCSIFHWADDR) on %s device failed: %s",
                  netdev_name, strerror(errno));
index 52416a632e0e4538a0ab9bc52084341dbdd8c82e..301a2e844eb08b32eb55653e7c5e02e0461bbc7f 100644 (file)
@@ -41,6 +41,7 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include "coverage.h"
 #include "dynamic-string.h"
 #include "netlink-protocol.h"
 #include "ofpbuf.h"
@@ -229,6 +230,9 @@ nl_sock_send(struct nl_sock *sock, const struct ofpbuf *msg, bool wait)
         error = retval < 0 ? errno : 0;
     } while (error == EINTR);
     log_nlmsg(__func__, error, msg->data, msg->size);
+    if (!error) {
+        COVERAGE_INC(netlink_sent);
+    }
     return error;
 }
 
@@ -246,6 +250,7 @@ nl_sock_sendv(struct nl_sock *sock, const struct iovec iov[], size_t n_iov,
     struct msghdr msg;
     int error;
 
+    COVERAGE_INC(netlink_send);
     memset(&msg, 0, sizeof msg);
     msg.msg_iov = (struct iovec *) iov;
     msg.msg_iovlen = n_iov;
@@ -256,6 +261,9 @@ nl_sock_sendv(struct nl_sock *sock, const struct iovec iov[], size_t n_iov,
     } while (error == EINTR);
     if (error != EAGAIN) {
         log_nlmsg(__func__, error, iov[0].iov_base, iov[0].iov_len);
+        if (!error) {
+            COVERAGE_INC(netlink_sent);
+        }
     }
     return error;
 }
@@ -306,6 +314,7 @@ try_again:
         return errno;
     }
     if (msg.msg_flags & MSG_TRUNC) {
+        COVERAGE_INC(netlink_recv_retry);
         bufsize *= 2;
         ofpbuf_reinit(buf, bufsize);
         goto try_again;
@@ -324,6 +333,7 @@ try_again:
              * was dropped.  We have to pass this along to the caller in case
              * it wants to retry a request.  So kill the buffer, which we can
              * re-read next time. */
+            COVERAGE_INC(netlink_overflow);
             ofpbuf_delete(buf);
             return ENOBUFS;
         } else {
@@ -341,6 +351,7 @@ try_again:
     }
     *bufp = buf;
     log_nlmsg(__func__, 0, buf->data, buf->size);
+    COVERAGE_INC(netlink_received);
     return 0;
 }
 
@@ -402,6 +413,7 @@ recv:
     retval = nl_sock_recv(sock, &reply, true);
     if (retval) {
         if (retval == ENOBUFS) {
+            COVERAGE_INC(netlink_overflow);
             VLOG_DBG_RL(&rl, "receive buffer overflow, resending request");
             goto send;
         } else {
index 63b3da1639463f34c5748f53385db03dcea9a4f3..9c2a57c34bcb4518a019c165b21f2ae22597a480 100644 (file)
@@ -36,6 +36,7 @@
 #include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
+#include "coverage.h"
 #include "dynamic-string.h"
 #include "flow.h"
 #include "packets.h"
@@ -49,6 +50,7 @@ odp_actions_add(struct odp_actions *actions, uint16_t type)
     if (actions->n_actions < MAX_ODP_ACTIONS) {
         a = &actions->actions[actions->n_actions++];
     } else {
+        COVERAGE_INC(odp_overflow);
         actions->n_actions = MAX_ODP_ACTIONS + 1;
         a = &actions->actions[MAX_ODP_ACTIONS - 1];
     }
index 09df03611cccb658733b24c6712c3b7b677424d2..aed21265d9a3f1a872af96b25b61d2d25f778ea4 100644 (file)
@@ -39,6 +39,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "backtrace.h"
+#include "coverage.h"
 #include "dynamic-string.h"
 #include "list.h"
 #include "timeval.h"
@@ -92,6 +93,7 @@ static struct poll_waiter *new_waiter(int fd, short int events);
 struct poll_waiter *
 poll_fd_wait(int fd, short int events)
 {
+    COVERAGE_INC(poll_fd_wait);
     return new_waiter(fd, events);
 }
 
@@ -176,6 +178,9 @@ poll_block(void)
         n_pollfds++;
     }
 
+    if (!timeout) {
+        COVERAGE_INC(poll_zero_timeout);
+    }
     retval = time_poll(pollfds, n_pollfds, timeout);
     if (retval < 0) {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
index e27f6547ff1f34383c2d1d6222e74567998d37e0..755ad2e165eaa838ff7691b700c4dd02c133d1c8 100644 (file)
@@ -42,6 +42,7 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include "coverage.h"
 #include "dynamic-string.h"
 #include "list.h"
 #include "poll-loop.h"
@@ -156,6 +157,7 @@ process_start(char **argv,
 
     *pp = NULL;
     process_init();
+    COVERAGE_INC(process_start);
 
     if (VLOG_IS_DBG_ENABLED()) {
         char *args = process_escape_args(argv);
@@ -289,6 +291,7 @@ process_run(char **argv,
     struct process *p;
     int retval;
 
+    COVERAGE_INC(process_run);
     retval = process_start(argv, keep_fds, n_keep_fds, null_fds, n_null_fds,
                            &p);
     if (retval) {
@@ -377,6 +380,7 @@ sigchld_handler(int signr UNUSED)
 {
     struct process *p;
 
+    COVERAGE_INC(process_sigchld);
     LIST_FOR_EACH (p, struct process, node, &all_processes) {
         if (!p->exited) {
             int retval, status;
index f7a5e4b56211f63511c41aebc78329222638b8d7..b045342275cd9d2cbc52818b32b5c1f6c8063977 100644 (file)
@@ -38,6 +38,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include "coverage.h"
 #include "ofpbuf.h"
 #include "openflow/openflow.h"
 #include "poll-loop.h"
@@ -548,6 +549,7 @@ rconn_send(struct rconn *rc, struct ofpbuf *b,
            struct rconn_packet_counter *counter)
 {
     if (rconn_is_connected(rc)) {
+        COVERAGE_INC(rconn_queued);
         copy_to_monitor(rc, b);
         b->private = counter;
         if (counter) {
@@ -587,6 +589,7 @@ rconn_send_with_limit(struct rconn *rc, struct ofpbuf *b,
     int retval;
     retval = counter->n >= queue_limit ? EAGAIN : rconn_send(rc, b, counter);
     if (retval) {
+        COVERAGE_INC(rconn_overflow);
         ofpbuf_delete(b);
     }
     return retval;
@@ -800,6 +803,7 @@ try_send(struct rconn *rc)
         }
         return retval;
     }
+    COVERAGE_INC(rconn_sent);
     rc->packets_sent++;
     if (counter) {
         rconn_packet_counter_dec(counter);
@@ -864,6 +868,7 @@ flush_queue(struct rconn *rc)
         if (counter) {
             rconn_packet_counter_dec(counter);
         }
+        COVERAGE_INC(rconn_discarded);
         ofpbuf_delete(b);
     }
     poll_immediate_wake();
index 00cf0551d7d54a11695408b1ad96fcac0299f637..0755e0d2d1a9af6748fafaa331bd41c4eb6f61cd 100644 (file)
@@ -39,6 +39,7 @@
 #include <signal.h>
 #include <string.h>
 #include <sys/time.h>
+#include "coverage.h"
 #include "fatal-signal.h"
 #include "util.h"
 
@@ -166,6 +167,7 @@ time_poll(struct pollfd *pollfds, int n_pollfds, int timeout)
 
     time_refresh();
     log_poll_interval(last_wakeup);
+    coverage_clear();
     start = time_msec();
     blocked = false;
     for (;;) {
@@ -264,6 +266,7 @@ log_poll_interval(long long int last_wakeup)
                   "the weighted mean interval %u ms (%u samples)",
                   (interval + 8) / 16, interval / mean_interval,
                   (mean_interval + 8) / 16, n_samples);
+        coverage_log(VLL_WARN);
     }
 
     /* Update exponentially weighted moving average.  With these parameters, a
index 81794f27ab42bfc16a2f65bd12e5d27c44bad019..4bf1c7a4c65aea6550fdbcf41f8db52c1de87597 100644 (file)
@@ -42,6 +42,7 @@
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include "coverage.h"
 #include "dirs.h"
 #include "dynamic-string.h"
 #include "fatal-signal.h"
@@ -145,6 +146,7 @@ unixctl_command_reply(struct unixctl_conn *conn,
 {
     struct ds *out = &conn->out;
 
+    COVERAGE_INC(unixctl_replied);
     assert(conn->state == S_PROCESS);
     conn->state = S_SEND;
     conn->out_pos = 0;
@@ -286,6 +288,7 @@ process_command(struct unixctl_conn *conn, char *s)
     size_t name_len;
     char *name, *args;
 
+    COVERAGE_INC(unixctl_received);
     conn->state = S_PROCESS;
 
     name = s;
index 21cc28d2b98638d4c2fa094127cd1bb7d551292a..d39a93180c8855906d0da6ee20f90a828410d29e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
  * Junior University
  * 
  * We are making the OpenFlow specification and associated documentation
@@ -38,6 +38,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include "coverage.h"
 
 const char *program_name;
 
@@ -51,6 +52,7 @@ void *
 xcalloc(size_t count, size_t size) 
 {
     void *p = count && size ? calloc(count, size) : malloc(1);
+    COVERAGE_INC(util_xalloc);
     if (p == NULL) {
         out_of_memory();
     }
@@ -61,6 +63,7 @@ void *
 xmalloc(size_t size) 
 {
     void *p = malloc(size ? size : 1);
+    COVERAGE_INC(util_xalloc);
     if (p == NULL) {
         out_of_memory();
     }
@@ -71,6 +74,7 @@ void *
 xrealloc(void *p, size_t size) 
 {
     p = realloc(p, size ? size : 1);
+    COVERAGE_INC(util_xalloc);
     if (p == NULL) {
         out_of_memory();
     }
index df7d5c0eda89ffb8ff122e74556c5eda1662437d..ec1da4b4b05a593e865861580e104c2a7f281ddd 100644 (file)
@@ -40,6 +40,7 @@
 #include <poll.h>
 #include <stdlib.h>
 #include <string.h>
+#include "coverage.h"
 #include "dynamic-string.h"
 #include "flow.h"
 #include "ofp-print.h"
@@ -196,6 +197,7 @@ vconn_open(const char *name, int min_version, struct vconn **vconnp)
     size_t prefix_len;
     size_t i;
 
+    COVERAGE_INC(vconn_open);
     check_vconn_classes();
 
     *vconnp = NULL;
@@ -455,6 +457,7 @@ again:
     if (!retval) {
         struct ofp_header *oh;
 
+        COVERAGE_INC(vconn_received);
         if (VLOG_IS_DBG_ENABLED()) {
             char *s = ofp_to_string((*msgp)->data, (*msgp)->size, 1);
             VLOG_DBG_RL(&ofmsg_rl, "%s: received: %s", vconn->name, s);
@@ -533,6 +536,7 @@ do_send(struct vconn *vconn, struct ofpbuf *msg)
     assert(msg->size >= sizeof(struct ofp_header));
     assert(((struct ofp_header *) msg->data)->length == htons(msg->size));
     if (!VLOG_IS_DBG_ENABLED()) {
+        COVERAGE_INC(vconn_sent);
         retval = (vconn->class->send)(vconn, msg);
     } else {
         char *s = ofp_to_string(msg->data, msg->size, 1);
index 94f28d792d5100933ffc488ebab9beb56e8505aa..f0f52f5b1ecb4254d14e9e0867409e8b9847e79d 100644 (file)
@@ -5,6 +5,7 @@ VLOG_MODULE(bridge)
 VLOG_MODULE(chain)
 VLOG_MODULE(cfg)
 VLOG_MODULE(controller)
+VLOG_MODULE(coverage)
 VLOG_MODULE(ctlpath)
 VLOG_MODULE(daemon)
 VLOG_MODULE(datapath)
index 6675692f4b21eedb81352e9eb004bae115bac184..b3bc065b42d150b4e936d0f9437a41368f99ba0b 100644 (file)
@@ -40,6 +40,7 @@
 #include <stdbool.h>
 #include <stdlib.h>
 #include "classifier.h"
+#include "coverage.h"
 #include "discovery.h"
 #include "dpif.h"
 #include "executer.h"
@@ -843,6 +844,7 @@ ofproto_run1(struct ofproto *p)
     }
 
     if (time_msec() >= p->next_expiration) {
+        COVERAGE_INC(ofproto_expiration);
         p->next_expiration = time_msec() + 1000;
         update_used(p);
 
@@ -874,6 +876,7 @@ ofproto_run2(struct ofproto *p, bool revalidate_all)
         cbdata.revalidate_subrules = p->need_revalidate;
         cbdata.revalidate_set = p->revalidate_set;
         tag_set_init(&p->revalidate_set);
+        COVERAGE_INC(ofproto_revalidate);
         classifier_for_each(&p->cls, CLS_INC_EXACT, revalidate_cb, &cbdata);
         p->need_revalidate = false;
     }
@@ -1008,6 +1011,7 @@ destroy_rule(struct cls_rule *rule_, void *ofproto_)
 void
 ofproto_flush_flows(struct ofproto *ofproto)
 {
+    COVERAGE_INC(ofproto_flush);
     classifier_for_each(&ofproto->cls, CLS_INC_ALL, destroy_rule, ofproto);
     dpif_flow_flush(&ofproto->dpif);
     if (ofproto->in_band) {
@@ -1198,6 +1202,7 @@ update_port(struct ofproto *p, const char *devname)
     struct ofport *ofport;
     int error;
 
+    COVERAGE_INC(ofproto_update_port);
     ofport = shash_find_data(&p->port_by_name, devname);
     error = dpif_port_query_by_name(&p->dpif, devname, &odp_port);
     if (!error) {
@@ -1331,6 +1336,8 @@ ofconn_wait(struct ofconn *ofconn)
     rconn_run_wait(ofconn->rconn);
     if (rconn_packet_counter_read (ofconn->reply_counter) < OFCONN_REPLY_MAX) {
         rconn_recv_wait(ofconn->rconn);
+    } else {
+        COVERAGE_INC(ofproto_ofconn_stuck);
     }
 }
 \f
@@ -1483,6 +1490,7 @@ rule_insert(struct ofproto *p, struct rule *rule, struct ofpbuf *packet,
     /* Install the rule in the datapath only after sending the packet, to
      * avoid packet reordering.  */
     if (rule->cr.wc.wildcards) {
+        COVERAGE_INC(ofproto_add_wc_flow);
         p->need_revalidate = true;
     } else {
         rule_install(p, rule, displaced_rule);
@@ -1500,6 +1508,7 @@ rule_create_subrule(struct ofproto *ofproto, struct rule *rule,
 {
     struct rule *subrule = rule_create(rule, NULL, 0,
                                        rule->idle_timeout, rule->hard_timeout);
+    COVERAGE_INC(ofproto_subrule_create);
     cls_rule_from_flow(&subrule->cr, flow, 0,
                        (rule->cr.priority <= UINT16_MAX ? UINT16_MAX
                         : rule->cr.priority));
@@ -1512,6 +1521,7 @@ static void
 rule_remove(struct ofproto *ofproto, struct rule *rule)
 {
     if (rule->cr.wc.wildcards) {
+        COVERAGE_INC(ofproto_del_wc_flow);
         ofproto->need_revalidate = true;
     } else {
         rule_uninstall(ofproto, rule);
@@ -1539,6 +1549,7 @@ rule_make_actions(struct ofproto *p, struct rule *rule,
     actions_len = a.n_actions * sizeof *a.actions;
     if (rule->n_odp_actions != a.n_actions
         || memcmp(rule->odp_actions, a.actions, actions_len)) {
+        COVERAGE_INC(ofproto_odp_unchanged);
         free(rule->odp_actions);
         rule->n_odp_actions = a.n_actions;
         rule->odp_actions = xmemdup(a.actions, actions_len);
@@ -1586,6 +1597,7 @@ rule_reinstall(struct ofproto *ofproto, struct rule *rule)
 {
     if (rule->installed) {
         struct odp_flow_put put;
+        COVERAGE_INC(ofproto_dp_missed);
         do_put_flow(ofproto, rule, ODPPF_CREATE | ODPPF_MODIFY, &put);
     } else {
         rule_install(ofproto, rule, NULL);
@@ -1687,6 +1699,7 @@ send_error(const struct ofconn *ofconn, const struct ofp_header *oh,
         return;
     }
 
+    COVERAGE_INC(ofproto_error);
     oem = make_openflow_xid(len + sizeof *oem, OFPT_ERROR,
                             oh ? oh->xid : 0, &buf);
     oem->type = htons((unsigned int) error >> 16);
@@ -1879,6 +1892,7 @@ lookup_valid_rule(struct ofproto *ofproto, const flow_t *flow)
         && rule->super
         && ofproto->need_revalidate
         && !revalidate_rule(ofproto, rule)) {
+        COVERAGE_INC(ofproto_invalidated);
         return NULL;
     }
 
@@ -1925,6 +1939,7 @@ xlate_output_action(struct action_xlate_ctx *ctx,
         if (!ctx->ofproto->ofhooks->normal_cb(ctx->flow, ctx->packet,
                                               ctx->out, ctx->tags,
                                               ctx->ofproto->aux)) {
+            COVERAGE_INC(ofproto_uninstallable);
             ctx->may_setup_flow = false;
         }
         break;
@@ -2057,6 +2072,7 @@ xlate_actions(const union ofp_action *in, size_t n_in,
 {
     tag_type no_tags = 0;
     struct action_xlate_ctx ctx;
+    COVERAGE_INC(ofproto_ofp2odp);
     odp_actions_init(out);
     ctx.flow = flow;
     ctx.recurse = 0;
@@ -2094,6 +2110,7 @@ handle_packet_out(struct ofproto *p, struct ofconn *ofconn,
     }
     opo = (struct ofp_packet_out *) oh;
 
+    COVERAGE_INC(ofproto_packet_out);
     if (opo->buffer_id != htonl(UINT32_MAX)) {
         error = pktbuf_retrieve(ofconn->pktbuf, ntohl(opo->buffer_id),
                                 &buffer, &in_port);
@@ -2133,6 +2150,7 @@ update_port_config(struct ofproto *p, struct ofport *port,
     }
 #define REVALIDATE_BITS (OFPPC_NO_RECV | OFPPC_NO_RECV_STP | OFPPC_NO_FWD)
     if (mask & REVALIDATE_BITS) {
+        COVERAGE_INC(ofproto_costly_flags);
         port->opp.config ^= mask & REVALIDATE_BITS;
         p->need_revalidate = true;
     }
@@ -2419,6 +2437,7 @@ handle_flow_stats_request(struct ofproto *p, struct ofconn *ofconn,
     }
     fsr = (struct ofp_flow_stats_request *) osr->body;
 
+    COVERAGE_INC(ofproto_flows_req);
     cbdata.ofproto = p;
     cbdata.ofconn = ofconn;
     cbdata.out_port = fsr->out_port;
@@ -2473,6 +2492,7 @@ handle_aggregate_stats_request(struct ofproto *p, struct ofconn *ofconn,
     }
     asr = (struct ofp_aggregate_stats_request *) osr->body;
 
+    COVERAGE_INC(ofproto_agg_request);
     cbdata.ofproto = p;
     cbdata.out_port = asr->out_port;
     cbdata.packet_count = 0;
@@ -2608,6 +2628,7 @@ modify_flow(struct ofproto *p, const struct ofp_flow_mod *ofm,
         rule->n_actions = n_actions;
 
         if (rule->cr.wc.wildcards) {
+            COVERAGE_INC(ofproto_mod_wc_flow);
             p->need_revalidate = true;
         } else {
             rule_update_actions(p, rule);
@@ -2831,6 +2852,7 @@ handle_openflow(struct ofconn *ofconn, struct ofproto *p,
     struct ofp_header *oh = ofp_msg->data;
     int error;
 
+    COVERAGE_INC(ofproto_recv_openflow);
     switch (oh->type) {
     case OFPT_ECHO_REQUEST:
         error = handle_echo_request(ofconn, oh);
@@ -2898,6 +2920,7 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
 
     /* Handle controller actions. */
     if (msg->type == _ODPL_ACTION_NR) {
+        COVERAGE_INC(ofproto_ctlr_action);
         pinsched_send(p->action_sched, in_port, packet,
                       send_packet_in_action, p);
         return;
@@ -2913,6 +2936,7 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
         struct ofport *port = port_array_get(&p->ports, msg->port);
         if (port) {
             if (port->opp.config & OFPPC_NO_PACKET_IN) {
+                COVERAGE_INC(ofproto_no_packet_in);
                 /* XXX install 'drop' flow entry */
                 ofpbuf_delete(packet);
                 return;
@@ -2921,6 +2945,7 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
             VLOG_WARN_RL(&rl, "packet-in on unknown port %"PRIu16, msg->port);
         }
 
+        COVERAGE_INC(ofproto_packet_in);
         pinsched_send(p->miss_sched, in_port, packet, send_packet_in_miss, p);
         return;
     }
@@ -2962,6 +2987,7 @@ revalidate_rule(struct ofproto *p, struct rule *rule)
 {
     const flow_t *flow = &rule->cr.flow;
 
+    COVERAGE_INC(ofproto_revalidate_rule);
     if (rule->super) {
         struct rule *super;
         super = rule_from_cls_rule(classifier_lookup_wild(&p->cls, flow));
@@ -2969,6 +2995,7 @@ revalidate_rule(struct ofproto *p, struct rule *rule)
             rule_remove(p, rule);
             return false;
         } else if (super != rule->super) {
+            COVERAGE_INC(ofproto_revalidate_moved);
             list_remove(&rule->list);
             list_push_back(&super->list, &rule->list);
             rule->super = super;
@@ -3073,6 +3100,7 @@ expire_rule(struct cls_rule *cls_rule, void *p_)
         return;
     }
 
+    COVERAGE_INC(ofproto_expired);
     if (rule->cr.wc.wildcards) {
         /* Update stats.  (This code will be a no-op if the rule expired
          * due to an idle timeout, because in that case the rule has no
@@ -3109,6 +3137,7 @@ update_used(struct ofproto *p)
         rule = rule_from_cls_rule(
             classifier_find_rule_exactly(&p->cls, &f->key, 0, UINT16_MAX));
         if (!rule || !rule->installed) {
+            COVERAGE_INC(ofproto_unexpected_rule);
             dpif_flow_del(&p->dpif, f);
             continue;
         }
index 1370f649f100f268b9f69d9cca80e1e9f3f9507f..ba0b5d2ea9b72f2c854a7cf74fc9d6b02b6a8a7c 100644 (file)
@@ -35,6 +35,7 @@
 #include "pktbuf.h"
 #include <inttypes.h>
 #include <stdlib.h>
+#include "coverage.h"
 #include "ofpbuf.h"
 #include "timeval.h"
 #include "util.h"
@@ -137,12 +138,15 @@ pktbuf_retrieve(struct pktbuf *pb, uint32_t id, struct ofpbuf **bufferp,
             *bufferp = buffer;
             *in_port = p->in_port;
             p->buffer = NULL;
+            COVERAGE_INC(pktbuf_retrieved);
             return 0;
         } else {
+            COVERAGE_INC(pktbuf_reuse_error);
             VLOG_WARN_RL(&rl, "attempt to reuse buffer %08"PRIx32, id);
             error = ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BUFFER_EMPTY);
         }
     } else {
+        COVERAGE_INC(pktbuf_bad_cookie);
         VLOG_WARN_RL(&rl, "cookie mismatch: %08"PRIx32" != %08"PRIx32,
                      id, (id & PKTBUF_MASK) | (p->cookie << PKTBUF_BITS));
         error = ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_COOKIE);
index e0706a858de0501033270648048cb86094afa209..f2692817f29b5e24e50b08f12a8467862e3e62c4 100644 (file)
@@ -43,6 +43,7 @@
 #include <unistd.h>
 #include "bitmap.h"
 #include "cfg.h"
+#include "coverage.h"
 #include "dirs.h"
 #include "dpif.h"
 #include "flow.h"
@@ -346,6 +347,8 @@ bridge_reconfigure(void)
     struct bridge *br, *next;
     size_t i, j;
 
+    COVERAGE_INC(bridge_reconfigure);
+
     /* Collect old bridges. */
     svec_init(&old_br);
     LIST_FOR_EACH (br, struct bridge, node, &all_bridges) {
@@ -739,6 +742,7 @@ bridge_wait(void)
 static void
 bridge_flush(struct bridge *br)
 {
+    COVERAGE_INC(bridge_flush);
     br->flush = true;
     if (br->ml) {
         mac_learning_flush(br->ml);
@@ -1789,6 +1793,7 @@ bridge_normal_ofhook_cb(const flow_t *flow, const struct ofpbuf *packet,
     }
 #endif
 
+    COVERAGE_INC(bridge_process_flow);
     return process_flow(br, flow, packet, actions, tags);
 }
 
index ab1b36a9686bd0d96d7ace437447efe11a3df624..5ffccb7068c8d468aaadf1146abb2f46b8a93748 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "bridge.h"
 #include "cfg.h"
+#include "coverage.h"
 #include "list.h"
 #include "mgmt.h"
 #include "openflow/nicira-ext.h"
@@ -583,6 +584,8 @@ handle_msg(uint32_t xid, const void *msg, size_t length)
     struct ofp_header *oh;
     size_t min_size;
 
+    COVERAGE_INC(mgmt_received);
+
     /* Check encapsulated length. */
     oh = (struct ofp_header *) msg;
     if (ntohs(oh->length) > length) {