/Makefile
/Makefile.in
/dhparams.c
+/coverage-counters.c
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 \
$(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
--- /dev/null
+/* 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 */
--- /dev/null
+# 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";
--- /dev/null
+/* 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;
+ }
+}
--- /dev/null
+/* 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 */
#include <sys/sysmacros.h>
#include <unistd.h>
+#include "coverage.h"
#include "dynamic-string.h"
#include "flow.h"
#include "netlink.h"
int
dpif_delete(struct dpif *dpif)
{
+ COVERAGE_INC(dpif_destroy);
return do_ioctl(dpif, ODP_DP_DESTROY, "ODP_DP_DESTROY", NULL);
}
unsigned int i;
int error;
+ COVERAGE_INC(dpif_purge);
+
error = dpif_get_dp_stats(dpif, &stats);
if (error) {
return error;
{
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;
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);
}
{
struct odp_port_group pg;
+ COVERAGE_INC(dpif_port_group_set);
assert(n_ports <= UINT16_MAX);
pg.group = group;
pg.ports = (uint16_t *) ports;
int
dpif_flow_flush(struct dpif *dpif)
{
+ COVERAGE_INC(dpif_flow_flush);
return do_ioctl(dpif, ODP_FLOW_FLUSH, "ODP_FLOW_FLUSH", NULL);
}
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");
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);
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);
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++) {
uint32_t i;
int error;
+ COVERAGE_INC(dpif_flow_query_list);
fv.flows = flows;
fv.n_flows = n;
if (RUNNING_ON_VALGRIND) {
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);
}
{
int error;
+ COVERAGE_INC(dpif_execute);
if (n_actions > 0) {
struct odp_execute execute;
memset(&execute, 0, sizeof execute);
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);
}
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);
}
free(s);
}
*bufp = buf;
+ COVERAGE_INC(dpif_recv);
return 0;
} else {
VLOG_WARN_RL(&error_rl, "dp%u: discarding message truncated "
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);
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
+#include "coverage.h"
#include "dynamic-string.h"
#include "hash.h"
#include "ofpbuf.h"
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;
-/* 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
#include "hmap.h"
#include <assert.h>
#include <stdint.h>
+#include "coverage.h"
#include "util.h"
/* Initializes 'hmap' as an empty hash table. */
}
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);
{
size_t new_mask = calc_mask(hmap->n);
if (new_mask > hmap->mask) {
+ COVERAGE_INC(hmap_expand);
resize(hmap, new_mask);
}
}
{
size_t new_mask = calc_mask(hmap->n);
if (new_mask < hmap->mask) {
+ COVERAGE_INC(hmap_shrink);
resize(hmap, new_mask);
}
}
{
size_t new_mask = calc_mask(n);
if (new_mask > hmap->mask) {
+ COVERAGE_INC(hmap_reserve);
resize(hmap, new_mask);
}
}
#include <inttypes.h>
#include <stdlib.h>
+#include "coverage.h"
#include "hash.h"
#include "list.h"
#include "poll-loop.h"
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;
{
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);
}
#include <string.h>
#include <unistd.h>
+#include "coverage.h"
#include "dynamic-string.h"
#include "fatal-signal.h"
#include "list.h"
ifr.ifr_data = (caddr_t) ecmd;
ecmd->cmd = cmd;
+ COVERAGE_INC(netdev_ethtool);
if (ioctl(netdev->netdev_fd, SIOCETHTOOL, &ifr) == 0) {
return 0;
} else {
init_netdev();
*netdev_ = NULL;
+ COVERAGE_INC(netdev_open);
/* Create raw socket. */
netdev_fd = socket(PF_PACKET, SOCK_RAW,
}
return errno;
} else {
+ COVERAGE_INC(netdev_received);
buffer->size += n_bytes;
/* When the kernel internally sends out an Ethernet frame on an
(int) n_bytes, buffer->size, netdev->name);
return EMSGSIZE;
} else {
+ COVERAGE_INC(netdev_sent);
return 0;
}
}
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;
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));
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));
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);
{
int error;
+ COVERAGE_INC(netdev_get_stats);
if (use_netlink_stats) {
int ifindex;
init_netdev();
+ COVERAGE_INC(netdev_set_policing);
if (kbits_rate) {
if (!kbits_burst) {
/* Default to 10 kilobits if not specified. */
int error;
char *fn;
+ COVERAGE_INC(netdev_get_vlan_vid);
fn = xasprintf("/proc/net/vlan/%s", netdev_name);
stream = fopen(fn, "r");
if (!stream) {
/* 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;
}
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;
}
{
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));
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));
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));
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));
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));
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include "coverage.h"
#include "dynamic-string.h"
#include "netlink-protocol.h"
#include "ofpbuf.h"
error = retval < 0 ? errno : 0;
} while (error == EINTR);
log_nlmsg(__func__, error, msg->data, msg->size);
+ if (!error) {
+ COVERAGE_INC(netlink_sent);
+ }
return error;
}
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;
} 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;
}
return errno;
}
if (msg.msg_flags & MSG_TRUNC) {
+ COVERAGE_INC(netlink_recv_retry);
bufsize *= 2;
ofpbuf_reinit(buf, bufsize);
goto 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 {
}
*bufp = buf;
log_nlmsg(__func__, 0, buf->data, buf->size);
+ COVERAGE_INC(netlink_received);
return 0;
}
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 {
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
+#include "coverage.h"
#include "dynamic-string.h"
#include "flow.h"
#include "packets.h"
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];
}
#include <stdlib.h>
#include <string.h>
#include "backtrace.h"
+#include "coverage.h"
#include "dynamic-string.h"
#include "list.h"
#include "timeval.h"
struct poll_waiter *
poll_fd_wait(int fd, short int events)
{
+ COVERAGE_INC(poll_fd_wait);
return new_waiter(fd, events);
}
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);
#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"
*pp = NULL;
process_init();
+ COVERAGE_INC(process_start);
if (VLOG_IS_DBG_ENABLED()) {
char *args = process_escape_args(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) {
{
struct process *p;
+ COVERAGE_INC(process_sigchld);
LIST_FOR_EACH (p, struct process, node, &all_processes) {
if (!p->exited) {
int retval, status;
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include "coverage.h"
#include "ofpbuf.h"
#include "openflow/openflow.h"
#include "poll-loop.h"
struct rconn_packet_counter *counter)
{
if (rconn_is_connected(rc)) {
+ COVERAGE_INC(rconn_queued);
copy_to_monitor(rc, b);
b->private = counter;
if (counter) {
int retval;
retval = counter->n >= queue_limit ? EAGAIN : rconn_send(rc, b, counter);
if (retval) {
+ COVERAGE_INC(rconn_overflow);
ofpbuf_delete(b);
}
return retval;
}
return retval;
}
+ COVERAGE_INC(rconn_sent);
rc->packets_sent++;
if (counter) {
rconn_packet_counter_dec(counter);
if (counter) {
rconn_packet_counter_dec(counter);
}
+ COVERAGE_INC(rconn_discarded);
ofpbuf_delete(b);
}
poll_immediate_wake();
#include <signal.h>
#include <string.h>
#include <sys/time.h>
+#include "coverage.h"
#include "fatal-signal.h"
#include "util.h"
time_refresh();
log_poll_interval(last_wakeup);
+ coverage_clear();
start = time_msec();
blocked = false;
for (;;) {
"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
#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"
{
struct ds *out = &conn->out;
+ COVERAGE_INC(unixctl_replied);
assert(conn->state == S_PROCESS);
conn->state = S_SEND;
conn->out_pos = 0;
size_t name_len;
char *name, *args;
+ COVERAGE_INC(unixctl_received);
conn->state = S_PROCESS;
name = s;
-/* 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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "coverage.h"
const char *program_name;
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();
}
xmalloc(size_t size)
{
void *p = malloc(size ? size : 1);
+ COVERAGE_INC(util_xalloc);
if (p == NULL) {
out_of_memory();
}
xrealloc(void *p, size_t size)
{
p = realloc(p, size ? size : 1);
+ COVERAGE_INC(util_xalloc);
if (p == NULL) {
out_of_memory();
}
#include <poll.h>
#include <stdlib.h>
#include <string.h>
+#include "coverage.h"
#include "dynamic-string.h"
#include "flow.h"
#include "ofp-print.h"
size_t prefix_len;
size_t i;
+ COVERAGE_INC(vconn_open);
check_vconn_classes();
*vconnp = NULL;
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);
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);
VLOG_MODULE(chain)
VLOG_MODULE(cfg)
VLOG_MODULE(controller)
+VLOG_MODULE(coverage)
VLOG_MODULE(ctlpath)
VLOG_MODULE(daemon)
VLOG_MODULE(datapath)
#include <stdbool.h>
#include <stdlib.h>
#include "classifier.h"
+#include "coverage.h"
#include "discovery.h"
#include "dpif.h"
#include "executer.h"
}
if (time_msec() >= p->next_expiration) {
+ COVERAGE_INC(ofproto_expiration);
p->next_expiration = time_msec() + 1000;
update_used(p);
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;
}
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) {
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) {
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
/* 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);
{
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));
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);
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);
{
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);
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);
&& rule->super
&& ofproto->need_revalidate
&& !revalidate_rule(ofproto, rule)) {
+ COVERAGE_INC(ofproto_invalidated);
return NULL;
}
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;
{
tag_type no_tags = 0;
struct action_xlate_ctx ctx;
+ COVERAGE_INC(ofproto_ofp2odp);
odp_actions_init(out);
ctx.flow = flow;
ctx.recurse = 0;
}
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);
}
#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;
}
}
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;
}
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;
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);
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);
/* 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;
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;
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;
}
{
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));
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;
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
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;
}
#include "pktbuf.h"
#include <inttypes.h>
#include <stdlib.h>
+#include "coverage.h"
#include "ofpbuf.h"
#include "timeval.h"
#include "util.h"
*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);
#include <unistd.h>
#include "bitmap.h"
#include "cfg.h"
+#include "coverage.h"
#include "dirs.h"
#include "dpif.h"
#include "flow.h"
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) {
static void
bridge_flush(struct bridge *br)
{
+ COVERAGE_INC(bridge_flush);
br->flush = true;
if (br->ml) {
mac_learning_flush(br->ml);
}
#endif
+ COVERAGE_INC(bridge_process_flow);
return process_flow(br, flow, packet, actions, tags);
}
#include "bridge.h"
#include "cfg.h"
+#include "coverage.h"
#include "list.h"
#include "mgmt.h"
#include "openflow/nicira-ext.h"
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) {