diff options
author | Ben Pfaff <blp@nicira.com> | 2013-09-25 15:36:51 -0700 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2013-09-26 12:40:49 -0700 |
commit | 183126a1dc7e7308305f0c85a057f5e099c5a7a4 (patch) | |
tree | 73e00dbbf0263c9bf06c96c3c620da07ae1a8cda /lib/tag.c | |
parent | c906cedf2ec50baf1cb78a0c3b7f7eb016418ed2 (diff) |
classifier: Avoid accumulating junk in cls_partition 'tags'.
It's easy to add two tags together, but it's hard to subtract them. The
new "tag_tracker" data structure provides a solution.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/tag.c')
-rw-r--r-- | lib/tag.c | 33 |
1 files changed, 29 insertions, 4 deletions
@@ -16,10 +16,6 @@ #include <config.h> #include "tag.h" -#include <limits.h> - -#define N_TAG_BITS (CHAR_BIT * sizeof(tag_type)) -BUILD_ASSERT_DECL(IS_POW2(N_TAG_BITS)); #define LOG2_N_TAG_BITS (N_TAG_BITS == 32 ? 5 : N_TAG_BITS == 64 ? 6 : 0) BUILD_ASSERT_DECL(LOG2_N_TAG_BITS > 0); @@ -37,3 +33,32 @@ tag_create_deterministic(uint32_t seed) y += y >= x; return (1u << x) | (1u << y); } + +/* Initializes 'tracker'. */ +void +tag_tracker_init(struct tag_tracker *tracker) +{ + memset(tracker, 0, sizeof *tracker); +} + +/* Adds 'add' to '*tags' and records the bits added in 'tracker'. */ +void +tag_tracker_add(struct tag_tracker *tracker, tag_type *tags, tag_type add) +{ + *tags |= add; + for (; add; add = zero_rightmost_1bit(add)) { + tracker->counts[rightmost_1bit_idx(add)]++; + } +} + +/* Removes 'sub' from 'tracker' and unsets any bits in '*tags' that no + * remaining tag includes. */ +void +tag_tracker_subtract(struct tag_tracker *tracker, tag_type *tags, tag_type sub) +{ + for (; sub; sub = zero_rightmost_1bit(sub)) { + if (!--tracker->counts[rightmost_1bit_idx(sub)]) { + *tags &= ~rightmost_1bit(sub); + } + } +} |