2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 14:55:18 +00:00

coverage: Make the coverage counters catalog program-specific.

Until now, the collection of coverage counters supported by a given OVS
program was not specific to that program.  That means that, for example,
even though ovs-dpctl does not have anything to do with mac_learning, it
still has a coverage counter for it.  This is confusing, at best.

This commit fixes the problem on some systems, in particular on ones that
use GCC and the GNU linker.  It uses the feature of the GNU linker
described in its manual as:

    If an orphaned section's name is representable as a C identifier then
    the linker will automatically see PROVIDE two symbols: __start_SECNAME
    and __end_SECNAME, where SECNAME is the name of the section.  These
    indicate the start address and end address of the orphaned section
    respectively.

Systems that don't support these features retain the earlier behavior.

This commit also fixes the annoyance that files that include coverage
counters must be listed on COVERAGE_FILES in lib/automake.mk.

This commit also fixes the annoyance that modifying any source file that
includes a coverage counter caused all programs that link against
libopenvswitch.a to relink, even programs that the source file was not
linked into.  For example, modifying ofproto/ofproto.c (which includes
coverage counters) caused tests/test-aes128 to relink, even though
test-aes128 does not link again ofproto.o.
This commit is contained in:
Ben Pfaff
2010-11-01 14:14:27 -07:00
parent f4e2e60be4
commit d76f09ea77
25 changed files with 170 additions and 128 deletions

View File

@@ -26,7 +26,6 @@ lib_libopenvswitch_a_SOURCES = \
lib/compiler.h \
lib/coverage.c \
lib/coverage.h \
lib/coverage-counters.h \
lib/csum.c \
lib/csum.h \
lib/daemon.c \
@@ -159,7 +158,6 @@ lib_libopenvswitch_a_SOURCES = \
lib/vlog.c \
lib/vlog.h
nodist_lib_libopenvswitch_a_SOURCES = \
lib/coverage-counters.c \
lib/dirs.c
CLEANFILES += $(nodist_lib_libopenvswitch_a_SOURCES)
@@ -246,6 +244,7 @@ lib-install-data-local:
$(MKDIR_P) $(DESTDIR)$(PKIDIR)
$(MKDIR_P) $(DESTDIR)$(LOGDIR)
if !USE_LINKER_SECTIONS
# All distributed sources, with names adjust properly for referencing
# from $(builddir).
all_sources = \
@@ -257,37 +256,11 @@ all_sources = \
fi; \
done`
# All the source files that have coverage counters.
COVERAGE_FILES = \
lib/dpif.c \
lib/flow.c \
lib/lockfile.c \
lib/hmap.c \
lib/mac-learning.c \
lib/netdev.c \
lib/netdev-linux.c \
lib/netlink.c \
lib/odp-util.c \
lib/poll-loop.c \
lib/process.c \
lib/rconn.c \
lib/rtnetlink.c \
lib/stream.c \
lib/stream-ssl.c \
lib/timeval.c \
lib/unixctl.c \
lib/util.c \
lib/vconn.c \
ofproto/ofproto.c \
ofproto/pktbuf.c \
vswitchd/bridge.c \
vswitchd/ovs-brcompatd.c
lib/coverage-counters.c: $(COVERAGE_FILES) lib/coverage-scan.pl
(cd $(srcdir) && $(PERL) lib/coverage-scan.pl $(COVERAGE_FILES)) > $@.tmp
mv $@.tmp $@
EXTRA_DIST += lib/coverage-scan.pl
lib/coverage.$(OBJEXT): lib/coverage.def
lib/coverage.def: $(DIST_SOURCES)
sed -n 's|^COVERAGE_DEFINE(\([_a-zA-Z0-9]\{1,\}\)).*$$|COVERAGE_COUNTER(\1)|p' $(all_sources) | LC_ALL=C sort -u > $@
CLEANFILES += lib/coverage.def
if !USE_LINKER_SECTIONS
lib/vlog.$(OBJEXT): lib/vlog-modules.def
lib/vlog-modules.def: $(DIST_SOURCES)
sed -n 's|^VLOG_DEFINE_\(THIS_\)\{0,1\}MODULE(\([_a-zA-Z0-9]\{1,\}\)).*$$|VLOG_MODULE(\2)|p' $(all_sources) | LC_ALL=C sort -u > $@

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) 2009 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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 */

View File

@@ -1,47 +0,0 @@
# Copyright (c) 2009 Nicira Networks.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
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";

View File

@@ -18,7 +18,6 @@
#include "coverage.h"
#include <inttypes.h>
#include <stdlib.h>
#include "coverage-counters.h"
#include "dynamic-string.h"
#include "hash.h"
#include "unixctl.h"
@@ -27,6 +26,25 @@
VLOG_DEFINE_THIS_MODULE(coverage);
/* The coverage counters. */
#if USE_LINKER_SECTIONS
extern struct coverage_counter *__start_coverage[];
extern struct coverage_counter *__stop_coverage[];
#define coverage_counters __start_coverage
#define n_coverage_counters (__stop_coverage - __start_coverage)
#else /* !USE_LINKER_SECTIONS */
#define COVERAGE_COUNTER(NAME) COVERAGE_DEFINE__(NAME);
#include "coverage.def"
#undef COVERAGE_COUNTER
struct coverage_counter *coverage_counters[] = {
#define COVERAGE_COUNTER(NAME) &counter_##NAME,
#include "coverage.def"
#undef COVERAGE_COUNTER
};
#define n_coverage_counters ARRAY_SIZE(coverage_counters)
#endif /* !USE_LINKER_SECTIONS */
static unsigned int epoch;
static void
@@ -67,15 +85,15 @@ coverage_hash(void)
int n_groups, i;
/* Sort coverage counters into groups with equal counts. */
c = xmalloc(coverage_n_counters * sizeof *c);
for (i = 0; i < coverage_n_counters; i++) {
c = xmalloc(n_coverage_counters * sizeof *c);
for (i = 0; i < n_coverage_counters; i++) {
c[i] = coverage_counters[i];
}
qsort(c, coverage_n_counters, sizeof *c, compare_coverage_counters);
qsort(c, n_coverage_counters, sizeof *c, compare_coverage_counters);
/* Hash the names in each group along with the rank. */
n_groups = 0;
for (i = 0; i < coverage_n_counters; ) {
for (i = 0; i < n_coverage_counters; ) {
int j;
if (!c[i]->count) {
@@ -83,7 +101,7 @@ coverage_hash(void)
}
n_groups++;
hash = hash_int(i, hash);
for (j = i; j < coverage_n_counters; j++) {
for (j = i; j < n_coverage_counters; j++) {
if (c[j]->count != c[i]->count) {
break;
}
@@ -150,13 +168,13 @@ coverage_log(enum vlog_level level, bool suppress_dups)
n_never_hit = 0;
VLOG(level, "Event coverage (epoch %u/entire run), hash=%08"PRIx32":",
epoch, hash);
for (i = 0; i < coverage_n_counters; i++) {
for (i = 0; i < n_coverage_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++) {
for (i = 0; i < n_coverage_counters; i++) {
struct coverage_counter *c = coverage_counters[i];
if (!c->count) {
if (c->total) {
@@ -176,7 +194,7 @@ coverage_clear(void)
size_t i;
epoch++;
for (i = 0; i < coverage_n_counters; i++) {
for (i = 0; i < n_coverage_counters; i++) {
struct coverage_counter *c = coverage_counters[i];
c->total += c->count;
c->count = 0;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 Nicira Networks.
* Copyright (c) 2009, 2010 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,24 +36,30 @@ struct coverage_counter {
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_FILES in lib/automake.mk. */
#define COVERAGE_INC(NAME) \
do { \
extern struct coverage_counter NAME##_count; \
NAME##_count.count++; \
} while (0)
/* Defines COUNTER. There must be exactly one such definition at file scope
* within a program. */
#if USE_LINKER_SECTIONS
#define COVERAGE_DEFINE(COUNTER) \
COVERAGE_DEFINE__(COUNTER); \
struct coverage_counter *counter_ptr_##COUNTER \
__attribute__((section("coverage"))) = &counter_##COUNTER
#else
#define COVERAGE_DEFINE(MODULE) \
extern struct coverage_counter counter_##MODULE
#endif
/* 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)
/* Adds 1 to COUNTER. */
#define COVERAGE_INC(COUNTER) counter_##COUNTER.count++;
/* Adds AMOUNT to COUNTER. */
#define COVERAGE_ADD(COUNTER, AMOUNT) counter_##COUNTER.count += (AMOUNT);
void coverage_init(void);
void coverage_log(enum vlog_level, bool suppress_dups);
void coverage_clear(void);
/* Implementation detail. */
#define COVERAGE_DEFINE__(COUNTER) \
struct coverage_counter counter_##COUNTER = { #COUNTER, 0, 0 }
#endif /* coverage.h */

View File

@@ -42,6 +42,18 @@
VLOG_DEFINE_THIS_MODULE(dpif);
COVERAGE_DEFINE(dpif_destroy);
COVERAGE_DEFINE(dpif_port_add);
COVERAGE_DEFINE(dpif_port_del);
COVERAGE_DEFINE(dpif_flow_flush);
COVERAGE_DEFINE(dpif_flow_get);
COVERAGE_DEFINE(dpif_flow_put);
COVERAGE_DEFINE(dpif_flow_del);
COVERAGE_DEFINE(dpif_flow_query_list);
COVERAGE_DEFINE(dpif_flow_query_list_n);
COVERAGE_DEFINE(dpif_execute);
COVERAGE_DEFINE(dpif_purge);
static const struct dpif_class *base_dpif_classes[] = {
#ifdef HAVE_NETLINK
&dpif_linux_class,
@@ -375,6 +387,7 @@ dpif_get_all_names(const struct dpif *dpif, struct svec *all_names)
}
}
/* Destroys the datapath that 'dpif' is connected to, first removing all of its
* ports. After calling this function, it does not make sense to pass 'dpif'
* to any functions other than dpif_name() or dpif_close(). */

View File

@@ -34,6 +34,8 @@
VLOG_DEFINE_THIS_MODULE(flow);
COVERAGE_DEFINE(flow_extract);
static struct arp_eth_header *
pull_arp(struct ofpbuf *packet)
{

View File

@@ -23,6 +23,11 @@
#include "random.h"
#include "util.h"
COVERAGE_DEFINE(hmap_pathological);
COVERAGE_DEFINE(hmap_expand);
COVERAGE_DEFINE(hmap_shrink);
COVERAGE_DEFINE(hmap_reserve);
/* Initializes 'hmap' as an empty hash table. */
void
hmap_init(struct hmap *hmap)

View File

@@ -33,6 +33,11 @@
VLOG_DEFINE_THIS_MODULE(lockfile);
COVERAGE_DEFINE(lockfile_lock);
COVERAGE_DEFINE(lockfile_timeout);
COVERAGE_DEFINE(lockfile_error);
COVERAGE_DEFINE(lockfile_unlock);
struct lockfile {
struct hmap_node hmap_node;
char *name;

View File

@@ -33,6 +33,9 @@
VLOG_DEFINE_THIS_MODULE(mac_learning);
COVERAGE_DEFINE(mac_learning_learned);
COVERAGE_DEFINE(mac_learning_expired);
/* Returns the number of seconds since 'e' was last learned. */
int
mac_entry_age(const struct mac_entry *e)

View File

@@ -64,6 +64,14 @@
#include "vlog.h"
VLOG_DEFINE_THIS_MODULE(netdev_linux);
COVERAGE_DEFINE(netdev_get_vlan_vid);
COVERAGE_DEFINE(netdev_set_policing);
COVERAGE_DEFINE(netdev_arp_lookup);
COVERAGE_DEFINE(netdev_get_ifindex);
COVERAGE_DEFINE(netdev_get_hwaddr);
COVERAGE_DEFINE(netdev_set_hwaddr);
COVERAGE_DEFINE(netdev_ethtool);
/* These were introduced in Linux 2.6.14, so they might be missing if we have
* old headers. */

View File

@@ -42,6 +42,11 @@
VLOG_DEFINE_THIS_MODULE(netdev);
COVERAGE_DEFINE(netdev_received);
COVERAGE_DEFINE(netdev_sent);
COVERAGE_DEFINE(netdev_add_router);
COVERAGE_DEFINE(netdev_get_stats);
static struct shash netdev_classes = SHASH_INITIALIZER(&netdev_classes);
/* All created network devices. */

View File

@@ -35,6 +35,12 @@
VLOG_DEFINE_THIS_MODULE(netlink);
COVERAGE_DEFINE(netlink_overflow);
COVERAGE_DEFINE(netlink_received);
COVERAGE_DEFINE(netlink_recv_retry);
COVERAGE_DEFINE(netlink_send);
COVERAGE_DEFINE(netlink_sent);
/* Linux header file confusion causes this to be undefined. */
#ifndef SOL_NETLINK
#define SOL_NETLINK 270

View File

@@ -32,6 +32,9 @@
VLOG_DEFINE_THIS_MODULE(poll_loop);
COVERAGE_DEFINE(poll_fd_wait);
COVERAGE_DEFINE(poll_zero_timeout);
/* An event that will wake the following call to poll_block(). */
struct poll_waiter {
/* Set when the waiter is created. */

View File

@@ -36,6 +36,11 @@
VLOG_DEFINE_THIS_MODULE(process);
COVERAGE_DEFINE(process_run);
COVERAGE_DEFINE(process_run_capture);
COVERAGE_DEFINE(process_sigchld);
COVERAGE_DEFINE(process_start);
struct process {
struct list node;
char *name;

View File

@@ -34,6 +34,11 @@
VLOG_DEFINE_THIS_MODULE(rconn);
COVERAGE_DEFINE(rconn_discarded);
COVERAGE_DEFINE(rconn_overflow);
COVERAGE_DEFINE(rconn_queued);
COVERAGE_DEFINE(rconn_sent);
#define STATES \
STATE(VOID, 1 << 0) \
STATE(BACKOFF, 1 << 1) \

View File

@@ -31,6 +31,8 @@
VLOG_DEFINE_THIS_MODULE(rtnetlink);
COVERAGE_DEFINE(rtnetlink_changed);
/* rtnetlink socket. */
static struct nl_sock *notify_sock;

View File

@@ -47,6 +47,9 @@
VLOG_DEFINE_THIS_MODULE(stream_ssl);
COVERAGE_DEFINE(ssl_session);
COVERAGE_DEFINE(ssl_session_reused);
/* Active SSL. */
enum ssl_state {

View File

@@ -39,6 +39,9 @@
VLOG_DEFINE_THIS_MODULE(stream);
COVERAGE_DEFINE(pstream_open);
COVERAGE_DEFINE(stream_open);
/* State of an active stream.*/
enum stream_state {
SCS_CONNECTING, /* Underlying stream is not connected. */

View File

@@ -43,6 +43,9 @@
#endif
VLOG_DEFINE_THIS_MODULE(unixctl);
COVERAGE_DEFINE(unixctl_received);
COVERAGE_DEFINE(unixctl_replied);
struct unixctl_command {
unixctl_cb_func *cb;

View File

@@ -27,6 +27,8 @@
VLOG_DEFINE_THIS_MODULE(util);
COVERAGE_DEFINE(util_xalloc);
const char *program_name;
void

View File

@@ -40,6 +40,10 @@
VLOG_DEFINE_THIS_MODULE(vconn);
COVERAGE_DEFINE(vconn_open);
COVERAGE_DEFINE(vconn_received);
COVERAGE_DEFINE(vconn_sent);
/* State of an active vconn.*/
enum vconn_state {
/* This is the ordinary progression of states. */

View File

@@ -63,6 +63,37 @@
VLOG_DEFINE_THIS_MODULE(ofproto);
COVERAGE_DEFINE(odp_overflow);
COVERAGE_DEFINE(ofproto_add_wc_flow);
COVERAGE_DEFINE(ofproto_agg_request);
COVERAGE_DEFINE(ofproto_costly_flags);
COVERAGE_DEFINE(ofproto_ctlr_action);
COVERAGE_DEFINE(ofproto_del_wc_flow);
COVERAGE_DEFINE(ofproto_dp_missed);
COVERAGE_DEFINE(ofproto_error);
COVERAGE_DEFINE(ofproto_expiration);
COVERAGE_DEFINE(ofproto_expired);
COVERAGE_DEFINE(ofproto_flows_req);
COVERAGE_DEFINE(ofproto_flush);
COVERAGE_DEFINE(ofproto_invalidated);
COVERAGE_DEFINE(ofproto_mod_wc_flow);
COVERAGE_DEFINE(ofproto_no_packet_in);
COVERAGE_DEFINE(ofproto_odp_unchanged);
COVERAGE_DEFINE(ofproto_ofconn_stuck);
COVERAGE_DEFINE(ofproto_ofp2odp);
COVERAGE_DEFINE(ofproto_packet_in);
COVERAGE_DEFINE(ofproto_packet_out);
COVERAGE_DEFINE(ofproto_queue_req);
COVERAGE_DEFINE(ofproto_recv_openflow);
COVERAGE_DEFINE(ofproto_reinit_ports);
COVERAGE_DEFINE(ofproto_revalidate);
COVERAGE_DEFINE(ofproto_revalidate_moved);
COVERAGE_DEFINE(ofproto_revalidate_rule);
COVERAGE_DEFINE(ofproto_subrule_create);
COVERAGE_DEFINE(ofproto_unexpected_rule);
COVERAGE_DEFINE(ofproto_uninstallable);
COVERAGE_DEFINE(ofproto_update_port);
#include "sflow_api.h"
struct ofport {

View File

@@ -28,6 +28,11 @@
VLOG_DEFINE_THIS_MODULE(pktbuf);
COVERAGE_DEFINE(pktbuf_buffer_unknown);
COVERAGE_DEFINE(pktbuf_null_cookie);
COVERAGE_DEFINE(pktbuf_retrieved);
COVERAGE_DEFINE(pktbuf_reuse_error);
/* Buffers are identified by a 32-bit opaque ID. We divide the ID
* into a buffer number (low bits) and a cookie (high bits). The buffer number
* is an index into an array of buffers. The cookie distinguishes between

View File

@@ -72,6 +72,10 @@
VLOG_DEFINE_THIS_MODULE(bridge);
COVERAGE_DEFINE(bridge_flush);
COVERAGE_DEFINE(bridge_process_flow);
COVERAGE_DEFINE(bridge_reconfigure);
struct dst {
uint16_t vlan;
uint16_t dp_ifidx;