Skip to content

Commit d76f09e

Browse files
committed
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.
1 parent f4e2e60 commit d76f09e

25 files changed

Lines changed: 171 additions & 129 deletions

lib/automake.mk

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ lib_libopenvswitch_a_SOURCES = \
2626
lib/compiler.h \
2727
lib/coverage.c \
2828
lib/coverage.h \
29-
lib/coverage-counters.h \
3029
lib/csum.c \
3130
lib/csum.h \
3231
lib/daemon.c \
@@ -159,7 +158,6 @@ lib_libopenvswitch_a_SOURCES = \
159158
lib/vlog.c \
160159
lib/vlog.h
161160
nodist_lib_libopenvswitch_a_SOURCES = \
162-
lib/coverage-counters.c \
163161
lib/dirs.c
164162
CLEANFILES += $(nodist_lib_libopenvswitch_a_SOURCES)
165163

@@ -246,6 +244,7 @@ lib-install-data-local:
246244
$(MKDIR_P) $(DESTDIR)$(PKIDIR)
247245
$(MKDIR_P) $(DESTDIR)$(LOGDIR)
248246

247+
if !USE_LINKER_SECTIONS
249248
# All distributed sources, with names adjust properly for referencing
250249
# from $(builddir).
251250
all_sources = \
@@ -257,37 +256,11 @@ all_sources = \
257256
fi; \
258257
done`
259258

260-
# All the source files that have coverage counters.
261-
COVERAGE_FILES = \
262-
lib/dpif.c \
263-
lib/flow.c \
264-
lib/lockfile.c \
265-
lib/hmap.c \
266-
lib/mac-learning.c \
267-
lib/netdev.c \
268-
lib/netdev-linux.c \
269-
lib/netlink.c \
270-
lib/odp-util.c \
271-
lib/poll-loop.c \
272-
lib/process.c \
273-
lib/rconn.c \
274-
lib/rtnetlink.c \
275-
lib/stream.c \
276-
lib/stream-ssl.c \
277-
lib/timeval.c \
278-
lib/unixctl.c \
279-
lib/util.c \
280-
lib/vconn.c \
281-
ofproto/ofproto.c \
282-
ofproto/pktbuf.c \
283-
vswitchd/bridge.c \
284-
vswitchd/ovs-brcompatd.c
285-
lib/coverage-counters.c: $(COVERAGE_FILES) lib/coverage-scan.pl
286-
(cd $(srcdir) && $(PERL) lib/coverage-scan.pl $(COVERAGE_FILES)) > $@.tmp
287-
mv $@.tmp $@
288-
EXTRA_DIST += lib/coverage-scan.pl
259+
lib/coverage.$(OBJEXT): lib/coverage.def
260+
lib/coverage.def: $(DIST_SOURCES)
261+
sed -n 's|^COVERAGE_DEFINE(\([_a-zA-Z0-9]\{1,\}\)).*$$|COVERAGE_COUNTER(\1)|p' $(all_sources) | LC_ALL=C sort -u > $@
262+
CLEANFILES += lib/coverage.def
289263

290-
if !USE_LINKER_SECTIONS
291264
lib/vlog.$(OBJEXT): lib/vlog-modules.def
292265
lib/vlog-modules.def: $(DIST_SOURCES)
293266
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 > $@

lib/coverage-counters.h

Lines changed: 0 additions & 25 deletions
This file was deleted.

lib/coverage-scan.pl

Lines changed: 0 additions & 47 deletions
This file was deleted.

lib/coverage.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include "coverage.h"
1919
#include <inttypes.h>
2020
#include <stdlib.h>
21-
#include "coverage-counters.h"
2221
#include "dynamic-string.h"
2322
#include "hash.h"
2423
#include "unixctl.h"
@@ -27,6 +26,25 @@
2726

2827
VLOG_DEFINE_THIS_MODULE(coverage);
2928

29+
/* The coverage counters. */
30+
#if USE_LINKER_SECTIONS
31+
extern struct coverage_counter *__start_coverage[];
32+
extern struct coverage_counter *__stop_coverage[];
33+
#define coverage_counters __start_coverage
34+
#define n_coverage_counters (__stop_coverage - __start_coverage)
35+
#else /* !USE_LINKER_SECTIONS */
36+
#define COVERAGE_COUNTER(NAME) COVERAGE_DEFINE__(NAME);
37+
#include "coverage.def"
38+
#undef COVERAGE_COUNTER
39+
40+
struct coverage_counter *coverage_counters[] = {
41+
#define COVERAGE_COUNTER(NAME) &counter_##NAME,
42+
#include "coverage.def"
43+
#undef COVERAGE_COUNTER
44+
};
45+
#define n_coverage_counters ARRAY_SIZE(coverage_counters)
46+
#endif /* !USE_LINKER_SECTIONS */
47+
3048
static unsigned int epoch;
3149

3250
static void
@@ -67,23 +85,23 @@ coverage_hash(void)
6785
int n_groups, i;
6886

6987
/* Sort coverage counters into groups with equal counts. */
70-
c = xmalloc(coverage_n_counters * sizeof *c);
71-
for (i = 0; i < coverage_n_counters; i++) {
88+
c = xmalloc(n_coverage_counters * sizeof *c);
89+
for (i = 0; i < n_coverage_counters; i++) {
7290
c[i] = coverage_counters[i];
7391
}
74-
qsort(c, coverage_n_counters, sizeof *c, compare_coverage_counters);
92+
qsort(c, n_coverage_counters, sizeof *c, compare_coverage_counters);
7593

7694
/* Hash the names in each group along with the rank. */
7795
n_groups = 0;
78-
for (i = 0; i < coverage_n_counters; ) {
96+
for (i = 0; i < n_coverage_counters; ) {
7997
int j;
8098

8199
if (!c[i]->count) {
82100
break;
83101
}
84102
n_groups++;
85103
hash = hash_int(i, hash);
86-
for (j = i; j < coverage_n_counters; j++) {
104+
for (j = i; j < n_coverage_counters; j++) {
87105
if (c[j]->count != c[i]->count) {
88106
break;
89107
}
@@ -150,13 +168,13 @@ coverage_log(enum vlog_level level, bool suppress_dups)
150168
n_never_hit = 0;
151169
VLOG(level, "Event coverage (epoch %u/entire run), hash=%08"PRIx32":",
152170
epoch, hash);
153-
for (i = 0; i < coverage_n_counters; i++) {
171+
for (i = 0; i < n_coverage_counters; i++) {
154172
struct coverage_counter *c = coverage_counters[i];
155173
if (c->count) {
156174
coverage_log_counter(level, c);
157175
}
158176
}
159-
for (i = 0; i < coverage_n_counters; i++) {
177+
for (i = 0; i < n_coverage_counters; i++) {
160178
struct coverage_counter *c = coverage_counters[i];
161179
if (!c->count) {
162180
if (c->total) {
@@ -176,7 +194,7 @@ coverage_clear(void)
176194
size_t i;
177195

178196
epoch++;
179-
for (i = 0; i < coverage_n_counters; i++) {
197+
for (i = 0; i < n_coverage_counters; i++) {
180198
struct coverage_counter *c = coverage_counters[i];
181199
c->total += c->count;
182200
c->count = 0;

lib/coverage.h

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009 Nicira Networks.
2+
* Copyright (c) 2009, 2010 Nicira Networks.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,24 +36,30 @@ struct coverage_counter {
3636
unsigned long long int total; /* Total count over all epochs. */
3737
};
3838

39-
/* Increments the counter with the given NAME. Coverage counters need not be
40-
* declared explicitly, but when you add the first coverage counter to a given
41-
* file, you must also add that file to COVERAGE_FILES in lib/automake.mk. */
42-
#define COVERAGE_INC(NAME) \
43-
do { \
44-
extern struct coverage_counter NAME##_count; \
45-
NAME##_count.count++; \
46-
} while (0)
47-
48-
/* Adds AMOUNT to the coverage counter with the given NAME. */
49-
#define COVERAGE_ADD(NAME, AMOUNT) \
50-
do { \
51-
extern struct coverage_counter NAME##_count; \
52-
NAME##_count.count += AMOUNT; \
53-
} while (0)
39+
/* Defines COUNTER. There must be exactly one such definition at file scope
40+
* within a program. */
41+
#if USE_LINKER_SECTIONS
42+
#define COVERAGE_DEFINE(COUNTER) \
43+
COVERAGE_DEFINE__(COUNTER); \
44+
struct coverage_counter *counter_ptr_##COUNTER \
45+
__attribute__((section("coverage"))) = &counter_##COUNTER
46+
#else
47+
#define COVERAGE_DEFINE(MODULE) \
48+
extern struct coverage_counter counter_##MODULE
49+
#endif
50+
51+
/* Adds 1 to COUNTER. */
52+
#define COVERAGE_INC(COUNTER) counter_##COUNTER.count++;
53+
54+
/* Adds AMOUNT to COUNTER. */
55+
#define COVERAGE_ADD(COUNTER, AMOUNT) counter_##COUNTER.count += (AMOUNT);
5456

5557
void coverage_init(void);
5658
void coverage_log(enum vlog_level, bool suppress_dups);
5759
void coverage_clear(void);
5860

61+
/* Implementation detail. */
62+
#define COVERAGE_DEFINE__(COUNTER) \
63+
struct coverage_counter counter_##COUNTER = { #COUNTER, 0, 0 }
64+
5965
#endif /* coverage.h */

lib/dpif.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@
4242

4343
VLOG_DEFINE_THIS_MODULE(dpif);
4444

45+
COVERAGE_DEFINE(dpif_destroy);
46+
COVERAGE_DEFINE(dpif_port_add);
47+
COVERAGE_DEFINE(dpif_port_del);
48+
COVERAGE_DEFINE(dpif_flow_flush);
49+
COVERAGE_DEFINE(dpif_flow_get);
50+
COVERAGE_DEFINE(dpif_flow_put);
51+
COVERAGE_DEFINE(dpif_flow_del);
52+
COVERAGE_DEFINE(dpif_flow_query_list);
53+
COVERAGE_DEFINE(dpif_flow_query_list_n);
54+
COVERAGE_DEFINE(dpif_execute);
55+
COVERAGE_DEFINE(dpif_purge);
56+
4557
static const struct dpif_class *base_dpif_classes[] = {
4658
#ifdef HAVE_NETLINK
4759
&dpif_linux_class,
@@ -375,6 +387,7 @@ dpif_get_all_names(const struct dpif *dpif, struct svec *all_names)
375387
}
376388
}
377389

390+
378391
/* Destroys the datapath that 'dpif' is connected to, first removing all of its
379392
* ports. After calling this function, it does not make sense to pass 'dpif'
380393
* to any functions other than dpif_name() or dpif_close(). */

lib/flow.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434

3535
VLOG_DEFINE_THIS_MODULE(flow);
3636

37+
COVERAGE_DEFINE(flow_extract);
38+
3739
static struct arp_eth_header *
3840
pull_arp(struct ofpbuf *packet)
3941
{

lib/hmap.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
#include "random.h"
2424
#include "util.h"
2525

26+
COVERAGE_DEFINE(hmap_pathological);
27+
COVERAGE_DEFINE(hmap_expand);
28+
COVERAGE_DEFINE(hmap_shrink);
29+
COVERAGE_DEFINE(hmap_reserve);
30+
2631
/* Initializes 'hmap' as an empty hash table. */
2732
void
2833
hmap_init(struct hmap *hmap)

lib/lockfile.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333

3434
VLOG_DEFINE_THIS_MODULE(lockfile);
3535

36+
COVERAGE_DEFINE(lockfile_lock);
37+
COVERAGE_DEFINE(lockfile_timeout);
38+
COVERAGE_DEFINE(lockfile_error);
39+
COVERAGE_DEFINE(lockfile_unlock);
40+
3641
struct lockfile {
3742
struct hmap_node hmap_node;
3843
char *name;

lib/mac-learning.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333

3434
VLOG_DEFINE_THIS_MODULE(mac_learning);
3535

36+
COVERAGE_DEFINE(mac_learning_learned);
37+
COVERAGE_DEFINE(mac_learning_expired);
38+
3639
/* Returns the number of seconds since 'e' was last learned. */
3740
int
3841
mac_entry_age(const struct mac_entry *e)

0 commit comments

Comments
 (0)