[ovs-dev] [PATCH 01/18] vconn: Add ofputil_version_bitmap
Simon Horman
horms at verge.net.au
Fri Oct 26 02:35:49 UTC 2012
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 <horms at 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
More information about the dev
mailing list