Functions to manipulate a bitmap of allowed versions. The bitmap is simple a uint32_t, allowing for versions up until wire-protocol number 31.
Bit offsets correspond to ofp_version numbers which in turn correspond to wire-protocol numbers for Open Flow versions.. E.g. (1 << OFP10_VERSION) is the mask for Open Flow 1.1. If the bit for a version is set then it is allowed, otherwise it is disallowed. This is in preparation for allowing the range of allowed OpenFlow versions to be configured. Signed-off-by: Simon Horman <ho...@verge.net.au> --- lib/ofp-util.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/ofp-util.h | 52 ++++++++++++++++++ 2 files changed, 214 insertions(+) diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 34255da..cc70017 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -16,6 +16,7 @@ #include <config.h> #include "ofp-print.h" +#include <ctype.h> #include <errno.h> #include <inttypes.h> #include <sys/types.h> @@ -845,6 +846,71 @@ ofputil_protocols_from_string(const char *s) return protocols; } +static enum ofp_version +ofputil_version_from_string(const char *s) +{ + if (!strcasecmp(s, "OpenFlow10")) { + return OFP10_VERSION; + } + if (!strcasecmp(s, "OpenFlow11")) { + return OFP11_VERSION; + } + if (!strcasecmp(s, "OpenFlow12")) { + return OFP12_VERSION; + } + VLOG_FATAL("Unknown OpenFlow version: \"%s\"", s); +} + +static bool +is_delimiter(char c) +{ + return isspace(c) || c == ','; +} + +uint32_t +ofputil_versions_from_string(const char *s) +{ + size_t i = 0; + uint32_t bitmap = 0; + + while (s[i]) { + size_t j; + enum ofp_version version; + char *key; + + if (is_delimiter(s[i])) { + i++; + continue; + } + j = 0; + while (s[i + j] && !is_delimiter(s[i + j])) { + j++; + } + key = xmemdup0(s + i, j); + version = ofputil_version_from_string(key); + free(key); + bitmap |= ofputil_version_bitmap_set1(version); + i += j; + } + + return bitmap; +} + +const char * +ofputil_version_to_string(enum ofp_version ofp_version) +{ + switch (ofp_version) { + case OFP10_VERSION: + return "OpenFlow10"; + case OFP11_VERSION: + return "OpenFlow11"; + case OFP12_VERSION: + return "OpenFlow12"; + default: + NOT_REACHED(); + } +} + bool ofputil_packet_in_format_is_valid(enum nx_packet_in_format packet_in_format) { @@ -973,6 +1039,102 @@ ofputil_usable_protocols(const struct match *match) return OFPUTIL_P_ANY; } +#define VERSION_BITMAP_W (sizeof(uint32_t) * CHAR_BIT) + +/* Set the bit offsets of 'ovb' from 0 to 'end', excluding 'end' itself to one + * Expands bitmap as necessary */ +uint32_t +ofputil_version_bitmap_set_range1(size_t start, size_t end) +{ + uint32_t new = ~0U; + + assert(start < VERSION_BITMAP_W); + assert(end < VERSION_BITMAP_W); + + if (end >= start) { + new >>= (VERSION_BITMAP_W - end + start - 1); + new <<= start; + } + + return new; +} + +/* Scans 'ovb'. Returns the bit offset of the highest-numbered bit set to 1, + * or VERSION_BITMAP_W if all of the bits are set to 0. */ +size_t +ofputil_version_bitmap_scanr(uint32_t bitmap) +{ + /* N.B: When using GCC 3.4 or newer this may be made + * faster using __builtin_clz() + */ + size_t i = VERSION_BITMAP_W - 1; + + do { + if (ofputil_version_bitmap_is_set(bitmap, i)) { + return i; + } + } while (i--); + + return VERSION_BITMAP_W; +} + +/* Find the number of bits in 'ovb' that are set to one. */ +size_t +ofputil_version_bitmap_count_set(uint32_t bitmap) +{ + size_t i, n = 0; + + for (i = 0; i < VERSION_BITMAP_W; i++) { + if (ofputil_version_bitmap_is_set(bitmap, i)) { + n++; + } + } + + return n; +} + +static void +ofputil_format_version(struct ds *msg, size_t version) +{ + ds_put_format(msg, "0x%02zx", version); +} + +static void +ofputil_format_version_name(struct ds *msg, size_t version) +{ + ds_put_cstr(msg, ofputil_version_to_string(version)); +} + +static void +ofputil_format_version_bitmap__(struct ds *msg, uint32_t bitmap, + void (*format_version)(struct ds *msg, + size_t version)) +{ + size_t i, max; + + max = ofputil_version_bitmap_scanr(bitmap); + for (i = 0; i <= max; i++) { + if (ofputil_version_bitmap_is_set(bitmap, i)) { + format_version(msg, i); + if (i != max) { + ds_put_cstr(msg, ", "); + } + } + } +} + +void +ofputil_format_version_bitmap(struct ds *msg, uint32_t bitmap) +{ + ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version); +} + +void +ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap) +{ + ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version_name); +} + /* Returns an OpenFlow message that, sent on an OpenFlow connection whose * protocol is 'current', at least partly transitions the protocol to 'want'. * Stores in '*next' the protocol that will be in effect on the OpenFlow diff --git a/lib/ofp-util.h b/lib/ofp-util.h index b6268da..4838e20 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -98,6 +98,58 @@ char *ofputil_protocols_to_string(enum ofputil_protocol); enum ofputil_protocol ofputil_protocols_from_string(const char *); enum ofputil_protocol ofputil_usable_protocols(const struct match *); +/* A bitmap of version numbers + * + * Bit offsets correspond to ofp_version numbers which in turn + * correspond to wire-protocol numbers for Open Flow versions.. + * E.g. (1 << OFP10_VERSION) is the mask for Open Flow 1.1. + * If the bit for a version is set then it is allowed, otherwise it is + * disallowed. */ + +#define VERSION_BITMAP_W (sizeof(uint32_t) * CHAR_BIT) + +/* Set the bit 'offset' in 'ovb' to one + * Expands bitmap as necessary */ +static inline uint32_t +ofputil_version_bitmap_set1(size_t offset) +{ + assert(offset < VERSION_BITMAP_W); + return 1u << offset; +} + +/* Test if bit offset is set in ovb. */ +static inline bool +ofputil_version_bitmap_is_set(uint32_t bitmap, size_t offset) +{ + assert(offset < VERSION_BITMAP_W); + return (bitmap & (1u << offset)) != 0; +} + +uint32_t ofputil_version_bitmap_set_range1(size_t start, size_t end); +size_t ofputil_version_bitmap_scanr(uint32_t bitmap); +size_t ofputil_version_bitmap_count_set(uint32_t bitmap); + +void ofputil_format_version_bitmap(struct ds *msg, uint32_t bitmap); +void ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap); + +static inline uint32_t +ofputil_get_supported_versions(void) +{ + return ofputil_version_bitmap_set1(OFP10_VERSION) | + ofputil_version_bitmap_set1(OFP12_VERSION); +} + +static inline uint32_t +ofputil_get_allowed_versions_default(void) +{ + return ofputil_version_bitmap_set1(OFP10_VERSION); +} + +enum ofputil_protocol ofputil_protocols_from_string(const char *s); + +const char *ofputil_version_to_string(enum ofp_version ofp_version); +uint32_t ofputil_versions_from_string(const char *s); + struct ofpbuf *ofputil_encode_set_protocol(enum ofputil_protocol current, enum ofputil_protocol want, enum ofputil_protocol *next); -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev