Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Cloud:OpenStack:Newton
python-ovs
ovs-headers.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File ovs-headers.patch of Package python-ovs
--- /dev/null +++ ovs/lib/shash.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009, 2010, 2011 Nicira, Inc. + * + * 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 SHASH_H +#define SHASH_H 1 + +#include "hmap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct shash_node { + struct hmap_node node; + char *name; + void *data; +}; + +struct shash { + struct hmap map; +}; + +#define SHASH_INITIALIZER(SHASH) { HMAP_INITIALIZER(&(SHASH)->map) } + +#define SHASH_FOR_EACH(SHASH_NODE, SHASH) \ + HMAP_FOR_EACH (SHASH_NODE, node, &(SHASH)->map) + +#define SHASH_FOR_EACH_SAFE(SHASH_NODE, NEXT, SHASH) \ + HMAP_FOR_EACH_SAFE (SHASH_NODE, NEXT, node, &(SHASH)->map) + +void shash_init(struct shash *); +void shash_destroy(struct shash *); +void shash_destroy_free_data(struct shash *); +void shash_swap(struct shash *, struct shash *); +void shash_moved(struct shash *); +void shash_clear(struct shash *); +void shash_clear_free_data(struct shash *); +bool shash_is_empty(const struct shash *); +size_t shash_count(const struct shash *); +struct shash_node *shash_add(struct shash *, const char *, const void *); +struct shash_node *shash_add_nocopy(struct shash *, char *, const void *); +bool shash_add_once(struct shash *, const char *, const void *); +void shash_add_assert(struct shash *, const char *, const void *); +void *shash_replace(struct shash *, const char *, const void *data); +void shash_delete(struct shash *, struct shash_node *); +char *shash_steal(struct shash *, struct shash_node *); +struct shash_node *shash_find(const struct shash *, const char *); +struct shash_node *shash_find_len(const struct shash *, const char *, size_t); +void *shash_find_data(const struct shash *, const char *); +void *shash_find_and_delete(struct shash *, const char *); +void *shash_find_and_delete_assert(struct shash *, const char *); +struct shash_node *shash_first(const struct shash *); +const struct shash_node **shash_sort(const struct shash *); +bool shash_equal_keys(const struct shash *, const struct shash *); +struct shash_node *shash_random_node(struct shash *); + +#ifdef __cplusplus +} +#endif + +#endif /* shash.h */ --- /dev/null +++ ovs/lib/json.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2009, 2010, 2015 Nicira, Inc. + * + * 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 JSON_H +#define JSON_H 1 + +/* This is an implementation of JavaScript Object Notation (JSON) as specified + * by RFC 4627. It is intended to fully comply with RFC 4627, with the + * following known exceptions and clarifications: + * + * - Null bytes (\u0000) are not allowed in strings. + * + * - Only UTF-8 encoding is supported (RFC 4627 allows for other Unicode + * encodings). + * + * - Names within an object must be unique (RFC 4627 says that they + * "should" be unique). + */ + +#include "shash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds; + +/* Type of a JSON value. */ +enum json_type { + JSON_NULL, /* null */ + JSON_FALSE, /* false */ + JSON_TRUE, /* true */ + JSON_OBJECT, /* {"a": b, "c": d, ...} */ + JSON_ARRAY, /* [1, 2, 3, ...] */ + JSON_INTEGER, /* 123. */ + JSON_REAL, /* 123.456. */ + JSON_STRING, /* "..." */ + JSON_N_TYPES +}; + +const char *json_type_to_string(enum json_type); + +/* A JSON array. */ +struct json_array { + size_t n, n_allocated; + struct json **elems; +}; + +/* A JSON value. */ +struct json { + enum json_type type; + union { + struct shash *object; /* Contains "struct json *"s. */ + struct json_array array; + long long int integer; + double real; + char *string; + } u; +}; + +struct json *json_null_create(void); +struct json *json_boolean_create(bool); +struct json *json_string_create(const char *); +struct json *json_string_create_nocopy(char *); +struct json *json_integer_create(long long int); +struct json *json_real_create(double); + +struct json *json_array_create_empty(void); +void json_array_add(struct json *, struct json *element); +void json_array_trim(struct json *); +struct json *json_array_create(struct json **, size_t n); +struct json *json_array_create_1(struct json *); +struct json *json_array_create_2(struct json *, struct json *); +struct json *json_array_create_3(struct json *, struct json *, struct json *); + +struct json *json_object_create(void); +void json_object_put(struct json *, const char *name, struct json *value); +void json_object_put_string(struct json *, + const char *name, const char *value); + +const char *json_string(const struct json *); +struct json_array *json_array(const struct json *); +struct shash *json_object(const struct json *); +bool json_boolean(const struct json *); +double json_real(const struct json *); +int64_t json_integer(const struct json *); + +struct json *json_clone(const struct json *); +void json_destroy(struct json *); + +size_t json_hash(const struct json *, size_t basis); +bool json_equal(const struct json *, const struct json *); + +/* Parsing JSON. */ +enum { + JSPF_TRAILER = 1 << 0 /* Check for garbage following input. */ +}; + +struct json_parser *json_parser_create(int flags); +size_t json_parser_feed(struct json_parser *, const char *, size_t); +bool json_parser_is_done(const struct json_parser *); +struct json *json_parser_finish(struct json_parser *); +void json_parser_abort(struct json_parser *); + +struct json *json_from_string(const char *string); +struct json *json_from_file(const char *file_name); +struct json *json_from_stream(FILE *stream); + +/* Serializing JSON. */ + +enum { + JSSF_PRETTY = 1 << 0, /* Multiple lines with indentation, if true. */ + JSSF_SORT = 1 << 1 /* Object members in sorted order, if true. */ +}; +char *json_to_string(const struct json *, int flags); +void json_to_ds(const struct json *, int flags, struct ds *); + +/* JSON string formatting operations. */ + +bool json_string_unescape(const char *in, size_t in_len, char **outp); +void json_string_escape(const char *in, struct ds *out); + +#ifdef __cplusplus +} +#endif + +#endif /* json.h */ --- /dev/null +++ ovs/lib/hmap.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015 Nicira, Inc. + * + * 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 HMAP_H +#define HMAP_H 1 + +#include <stdbool.h> +#include <stdlib.h> +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* A hash map node, to be embedded inside the data structure being mapped. */ +struct hmap_node { + size_t hash; /* Hash value. */ + struct hmap_node *next; /* Next in linked list. */ +}; + +/* Returns the hash value embedded in 'node'. */ +static inline size_t hmap_node_hash(const struct hmap_node *node) +{ + return node->hash; +} + +#define HMAP_NODE_NULL ((struct hmap_node *) 1) +#define HMAP_NODE_NULL_INITIALIZER { 0, HMAP_NODE_NULL } + +/* Returns true if 'node' has been set to null by hmap_node_nullify() and has + * not been un-nullified by being inserted into an hmap. */ +static inline bool +hmap_node_is_null(const struct hmap_node *node) +{ + return node->next == HMAP_NODE_NULL; +} + +/* Marks 'node' with a distinctive value that can be tested with + * hmap_node_is_null(). */ +static inline void +hmap_node_nullify(struct hmap_node *node) +{ + node->next = HMAP_NODE_NULL; +} + +/* A hash map. */ +struct hmap { + struct hmap_node **buckets; /* Must point to 'one' iff 'mask' == 0. */ + struct hmap_node *one; + size_t mask; + size_t n; +}; + +/* Initializer for an empty hash map. */ +#define HMAP_INITIALIZER(HMAP) \ + { (struct hmap_node **const) &(HMAP)->one, NULL, 0, 0 } + +/* Initializer for an immutable struct hmap 'HMAP' that contains a single + * 'NODE'. */ +#define HMAP_CONST1(HMAP, NODE) { \ + CONST_CAST(struct hmap_node **, &(HMAP)->one), NODE, 0, 1 } +#define HMAP_NODE_INIT(HASH) { HASH, NULL } + +/* Initialization. */ +void hmap_init(struct hmap *); +void hmap_destroy(struct hmap *); +void hmap_clear(struct hmap *); +void hmap_swap(struct hmap *a, struct hmap *b); +void hmap_moved(struct hmap *hmap); +static inline size_t hmap_count(const struct hmap *); +static inline bool hmap_is_empty(const struct hmap *); + +/* Adjusting capacity. */ +void hmap_expand_at(struct hmap *, const char *where); +#define hmap_expand(HMAP) hmap_expand_at(HMAP, OVS_SOURCE_LOCATOR) + +void hmap_shrink_at(struct hmap *, const char *where); +#define hmap_shrink(HMAP) hmap_shrink_at(HMAP, OVS_SOURCE_LOCATOR) + +void hmap_reserve_at(struct hmap *, size_t capacity, const char *where); +#define hmap_reserve(HMAP, CAPACITY) \ + hmap_reserve_at(HMAP, CAPACITY, OVS_SOURCE_LOCATOR) + +/* Insertion and deletion. */ +static inline void hmap_insert_at(struct hmap *, struct hmap_node *, + size_t hash, const char *where); +#define hmap_insert(HMAP, NODE, HASH) \ + hmap_insert_at(HMAP, NODE, HASH, OVS_SOURCE_LOCATOR) + +static inline void hmap_insert_fast(struct hmap *, + struct hmap_node *, size_t hash); +static inline void hmap_remove(struct hmap *, struct hmap_node *); + +void hmap_node_moved(struct hmap *, struct hmap_node *, struct hmap_node *); +static inline void hmap_replace(struct hmap *, const struct hmap_node *old, + struct hmap_node *new_node); + +struct hmap_node *hmap_random_node(const struct hmap *); + +/* Search. + * + * HMAP_FOR_EACH_WITH_HASH iterates NODE over all of the nodes in HMAP that + * have hash value equal to HASH. HMAP_FOR_EACH_IN_BUCKET iterates NODE over + * all of the nodes in HMAP that would fall in the same bucket as HASH. MEMBER + * must be the name of the 'struct hmap_node' member within NODE. + * + * These macros may be used interchangeably to search for a particular value in + * an hmap, see, e.g. shash_find() for an example. Usually, using + * HMAP_FOR_EACH_WITH_HASH provides an optimization, because comparing a hash + * value is usually cheaper than comparing an entire hash map key. But for + * simple hash map keys, it makes sense to use HMAP_FOR_EACH_IN_BUCKET because + * it avoids doing two comparisons when a single simple comparison suffices. + * + * The loop should not change NODE to point to a different node or insert or + * delete nodes in HMAP (unless it "break"s out of the loop to terminate + * iteration). + * + * HASH is only evaluated once. + * + * When the loop terminates normally, meaning the iteration has completed + * without using 'break', NODE will be NULL. This is true for all of the + * HMAP_FOR_EACH_*() macros. + */ +#define HMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HMAP) \ + for (INIT_CONTAINER(NODE, hmap_first_with_hash(HMAP, HASH), MEMBER); \ + (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \ + ASSIGN_CONTAINER(NODE, hmap_next_with_hash(&(NODE)->MEMBER), \ + MEMBER)) +#define HMAP_FOR_EACH_IN_BUCKET(NODE, MEMBER, HASH, HMAP) \ + for (INIT_CONTAINER(NODE, hmap_first_in_bucket(HMAP, HASH), MEMBER); \ + (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \ + ASSIGN_CONTAINER(NODE, hmap_next_in_bucket(&(NODE)->MEMBER), MEMBER)) + +static inline struct hmap_node *hmap_first_with_hash(const struct hmap *, + size_t hash); +static inline struct hmap_node *hmap_next_with_hash(const struct hmap_node *); +static inline struct hmap_node *hmap_first_in_bucket(const struct hmap *, + size_t hash); +static inline struct hmap_node *hmap_next_in_bucket(const struct hmap_node *); + +bool hmap_contains(const struct hmap *, const struct hmap_node *); + +/* Iteration. */ + +/* Iterates through every node in HMAP. */ +#define HMAP_FOR_EACH(NODE, MEMBER, HMAP) \ + for (INIT_CONTAINER(NODE, hmap_first(HMAP), MEMBER); \ + (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \ + ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER)) + +/* Safe when NODE may be freed (not needed when NODE may be removed from the + * hash map but its members remain accessible and intact). */ +#define HMAP_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HMAP) \ + for (INIT_CONTAINER(NODE, hmap_first(HMAP), MEMBER); \ + ((NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL) \ + ? INIT_CONTAINER(NEXT, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER), 1 \ + : 0); \ + (NODE) = (NEXT)) + +/* Continues an iteration from just after NODE. */ +#define HMAP_FOR_EACH_CONTINUE(NODE, MEMBER, HMAP) \ + for (ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER); \ + (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \ + ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER)) + +static inline struct hmap_node *hmap_first(const struct hmap *); +static inline struct hmap_node *hmap_next(const struct hmap *, + const struct hmap_node *); + +struct hmap_node *hmap_at_position(const struct hmap *, + uint32_t *bucket, uint32_t *offset); + +/* Returns the number of nodes currently in 'hmap'. */ +static inline size_t +hmap_count(const struct hmap *hmap) +{ + return hmap->n; +} + +/* Returns the maximum number of nodes that 'hmap' may hold before it should be + * rehashed. */ +static inline size_t +hmap_capacity(const struct hmap *hmap) +{ + return hmap->mask * 2 + 1; +} + +/* Returns true if 'hmap' currently contains no nodes, + * false otherwise. + * Note: While hmap in general is not thread-safe without additional locking, + * hmap_is_empty() is. */ +static inline bool +hmap_is_empty(const struct hmap *hmap) +{ + return hmap->n == 0; +} + +/* Inserts 'node', with the given 'hash', into 'hmap'. 'hmap' is never + * expanded automatically. */ +static inline void +hmap_insert_fast(struct hmap *hmap, struct hmap_node *node, size_t hash) +{ + struct hmap_node **bucket = &hmap->buckets[hash & hmap->mask]; + node->hash = hash; + node->next = *bucket; + *bucket = node; + hmap->n++; +} + +/* Inserts 'node', with the given 'hash', into 'hmap', and expands 'hmap' if + * necessary to optimize search performance. + * + * ('where' is used in debug logging. Commonly one would use hmap_insert() to + * automatically provide the caller's source file and line number for + * 'where'.) */ +static inline void +hmap_insert_at(struct hmap *hmap, struct hmap_node *node, size_t hash, + const char *where) +{ + hmap_insert_fast(hmap, node, hash); + if (hmap->n / 2 > hmap->mask) { + hmap_expand_at(hmap, where); + } +} + +/* Removes 'node' from 'hmap'. Does not shrink the hash table; call + * hmap_shrink() directly if desired. */ +static inline void +hmap_remove(struct hmap *hmap, struct hmap_node *node) +{ + struct hmap_node **bucket = &hmap->buckets[node->hash & hmap->mask]; + while (*bucket != node) { + bucket = &(*bucket)->next; + } + *bucket = node->next; + hmap->n--; +} + +/* Puts 'new_node' in the position in 'hmap' currently occupied by 'old_node'. + * The 'new_node' must hash to the same value as 'old_node'. The client is + * responsible for ensuring that the replacement does not violate any + * client-imposed invariants (e.g. uniqueness of keys within a map). + * + * Afterward, 'old_node' is not part of 'hmap', and the client is responsible + * for freeing it (if this is desirable). */ +static inline void +hmap_replace(struct hmap *hmap, + const struct hmap_node *old_node, struct hmap_node *new_node) +{ + struct hmap_node **bucket = &hmap->buckets[old_node->hash & hmap->mask]; + while (*bucket != old_node) { + bucket = &(*bucket)->next; + } + *bucket = new_node; + new_node->hash = old_node->hash; + new_node->next = old_node->next; +} + +static inline struct hmap_node * +hmap_next_with_hash__(const struct hmap_node *node, size_t hash) +{ + while (node != NULL && node->hash != hash) { + node = node->next; + } + return CONST_CAST(struct hmap_node *, node); +} + +/* Returns the first node in 'hmap' with the given 'hash', or a null pointer if + * no nodes have that hash value. */ +static inline struct hmap_node * +hmap_first_with_hash(const struct hmap *hmap, size_t hash) +{ + return hmap_next_with_hash__(hmap->buckets[hash & hmap->mask], hash); +} + +/* Returns the first node in 'hmap' in the bucket in which the given 'hash' + * would land, or a null pointer if that bucket is empty. */ +static inline struct hmap_node * +hmap_first_in_bucket(const struct hmap *hmap, size_t hash) +{ + return hmap->buckets[hash & hmap->mask]; +} + +/* Returns the next node in the same bucket as 'node', or a null pointer if + * there are no more nodes in that bucket. + * + * If the hash map has been reallocated since 'node' was visited, some nodes + * may be skipped; if new nodes with the same hash value have been added, they + * will be skipped. (Removing 'node' from the hash map does not prevent + * calling this function, since node->next is preserved, although freeing + * 'node' of course does.) */ +static inline struct hmap_node * +hmap_next_in_bucket(const struct hmap_node *node) +{ + return node->next; +} + +/* Returns the next node in the same hash map as 'node' with the same hash + * value, or a null pointer if no more nodes have that hash value. + * + * If the hash map has been reallocated since 'node' was visited, some nodes + * may be skipped; if new nodes with the same hash value have been added, they + * will be skipped. (Removing 'node' from the hash map does not prevent + * calling this function, since node->next is preserved, although freeing + * 'node' of course does.) */ +static inline struct hmap_node * +hmap_next_with_hash(const struct hmap_node *node) +{ + return hmap_next_with_hash__(node->next, node->hash); +} + +static inline struct hmap_node * +hmap_next__(const struct hmap *hmap, size_t start) +{ + size_t i; + for (i = start; i <= hmap->mask; i++) { + struct hmap_node *node = hmap->buckets[i]; + if (node) { + return node; + } + } + return NULL; +} + +/* Returns the first node in 'hmap', in arbitrary order, or a null pointer if + * 'hmap' is empty. */ +static inline struct hmap_node * +hmap_first(const struct hmap *hmap) +{ + return hmap_next__(hmap, 0); +} + +/* Returns the next node in 'hmap' following 'node', in arbitrary order, or a + * null pointer if 'node' is the last node in 'hmap'. + * + * If the hash map has been reallocated since 'node' was visited, some nodes + * may be skipped or visited twice. (Removing 'node' from the hash map does + * not prevent calling this function, since node->next is preserved, although + * freeing 'node' of course does.) */ +static inline struct hmap_node * +hmap_next(const struct hmap *hmap, const struct hmap_node *node) +{ + return (node->next + ? node->next + : hmap_next__(hmap, (node->hash & hmap->mask) + 1)); +} + +#ifdef __cplusplus +} +#endif + +#endif /* hmap.h */ --- /dev/null +++ ovs/lib/util.h @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. + * + * 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 UTIL_H +#define UTIL_H 1 + +#include <arpa/inet.h> +#include <inttypes.h> +#include <limits.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "compiler.h" +#include "openvswitch/types.h" +#include "openvswitch/util.h" + +#ifndef va_copy +#ifdef __va_copy +#define va_copy __va_copy +#else +#define va_copy(dst, src) ((dst) = (src)) +#endif +#endif + +#ifdef __CHECKER__ +#define BUILD_ASSERT(EXPR) ((void) 0) +#define BUILD_ASSERT_DECL(EXPR) extern int (*build_assert(void))[1] +#elif !defined(__cplusplus) +/* Build-time assertion building block. */ +#define BUILD_ASSERT__(EXPR) \ + sizeof(struct { unsigned int build_assert_failed : (EXPR) ? 1 : -1; }) + +/* Build-time assertion for use in a statement context. */ +#define BUILD_ASSERT(EXPR) (void) BUILD_ASSERT__(EXPR) + +/* Build-time assertion for use in a declaration context. */ +#define BUILD_ASSERT_DECL(EXPR) \ + extern int (*build_assert(void))[BUILD_ASSERT__(EXPR)] +#else /* __cplusplus */ +#include <boost/static_assert.hpp> +#define BUILD_ASSERT BOOST_STATIC_ASSERT +#define BUILD_ASSERT_DECL BOOST_STATIC_ASSERT +#endif /* __cplusplus */ + +#ifdef __GNUC__ +#define BUILD_ASSERT_GCCONLY(EXPR) BUILD_ASSERT(EXPR) +#define BUILD_ASSERT_DECL_GCCONLY(EXPR) BUILD_ASSERT_DECL(EXPR) +#else +#define BUILD_ASSERT_GCCONLY(EXPR) ((void) 0) +#define BUILD_ASSERT_DECL_GCCONLY(EXPR) ((void) 0) +#endif + +/* Like the standard assert macro, except writes the failure message to the + * log. */ +#ifndef NDEBUG +#define ovs_assert(CONDITION) \ + if (!OVS_LIKELY(CONDITION)) { \ + ovs_assert_failure(OVS_SOURCE_LOCATOR, __func__, #CONDITION); \ + } +#else +#define ovs_assert(CONDITION) ((void) (CONDITION)) +#endif +OVS_NO_RETURN void ovs_assert_failure(const char *, const char *, const char *); + +/* Casts 'pointer' to 'type' and issues a compiler warning if the cast changes + * anything other than an outermost "const" or "volatile" qualifier. + * + * The cast to int is present only to suppress an "expression using sizeof + * bool" warning from "sparse" (see + * http://permalink.gmane.org/gmane.comp.parsers.sparse/2967). */ +#define CONST_CAST(TYPE, POINTER) \ + ((void) sizeof ((int) ((POINTER) == (TYPE) (POINTER))), \ + (TYPE) (POINTER)) + +extern char *program_name; + +#define __ARRAY_SIZE_NOCHECK(ARRAY) (sizeof(ARRAY) / sizeof((ARRAY)[0])) +#ifdef __GNUC__ +/* return 0 for array types, 1 otherwise */ +#define __ARRAY_CHECK(ARRAY) \ + !__builtin_types_compatible_p(typeof(ARRAY), typeof(&ARRAY[0])) + +/* compile-time fail if not array */ +#define __ARRAY_FAIL(ARRAY) (sizeof(char[-2*!__ARRAY_CHECK(ARRAY)])) +#define __ARRAY_SIZE(ARRAY) \ + __builtin_choose_expr(__ARRAY_CHECK(ARRAY), \ + __ARRAY_SIZE_NOCHECK(ARRAY), __ARRAY_FAIL(ARRAY)) +#else +#define __ARRAY_SIZE(ARRAY) __ARRAY_SIZE_NOCHECK(ARRAY) +#endif + +/* Returns the number of elements in ARRAY. */ +#define ARRAY_SIZE(ARRAY) __ARRAY_SIZE(ARRAY) + +/* Returns X / Y, rounding up. X must be nonnegative to round correctly. */ +#define DIV_ROUND_UP(X, Y) (((X) + ((Y) - 1)) / (Y)) + +/* Returns X rounded up to the nearest multiple of Y. */ +#define ROUND_UP(X, Y) (DIV_ROUND_UP(X, Y) * (Y)) + +/* Returns the least number that, when added to X, yields a multiple of Y. */ +#define PAD_SIZE(X, Y) (ROUND_UP(X, Y) - (X)) + +/* Returns X rounded down to the nearest multiple of Y. */ +#define ROUND_DOWN(X, Y) ((X) / (Y) * (Y)) + +/* Returns true if X is a power of 2, otherwise false. */ +#define IS_POW2(X) ((X) && !((X) & ((X) - 1))) + +static inline bool +is_pow2(uintmax_t x) +{ + return IS_POW2(x); +} + +/* Returns X rounded up to a power of 2. X must be a constant expression. */ +#define ROUND_UP_POW2(X) RUP2__(X) +#define RUP2__(X) (RUP2_1(X) + 1) +#define RUP2_1(X) (RUP2_2(X) | (RUP2_2(X) >> 16)) +#define RUP2_2(X) (RUP2_3(X) | (RUP2_3(X) >> 8)) +#define RUP2_3(X) (RUP2_4(X) | (RUP2_4(X) >> 4)) +#define RUP2_4(X) (RUP2_5(X) | (RUP2_5(X) >> 2)) +#define RUP2_5(X) (RUP2_6(X) | (RUP2_6(X) >> 1)) +#define RUP2_6(X) ((X) - 1) + +/* Returns X rounded down to a power of 2. X must be a constant expression. */ +#define ROUND_DOWN_POW2(X) RDP2__(X) +#define RDP2__(X) (RDP2_1(X) - (RDP2_1(X) >> 1)) +#define RDP2_1(X) (RDP2_2(X) | (RDP2_2(X) >> 16)) +#define RDP2_2(X) (RDP2_3(X) | (RDP2_3(X) >> 8)) +#define RDP2_3(X) (RDP2_4(X) | (RDP2_4(X) >> 4)) +#define RDP2_4(X) (RDP2_5(X) | (RDP2_5(X) >> 2)) +#define RDP2_5(X) ( (X) | ( (X) >> 1)) + +/* This system's cache line size, in bytes. + * Being wrong hurts performance but not correctness. */ +#define CACHE_LINE_SIZE 64 +BUILD_ASSERT_DECL(IS_POW2(CACHE_LINE_SIZE)); + +static inline void +ovs_prefetch_range(const void *start, size_t size) +{ + const char *addr = (const char *)start; + size_t ofs; + + for (ofs = 0; ofs < size; ofs += CACHE_LINE_SIZE) { + OVS_PREFETCH(addr + ofs); + } +} + +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + +#ifndef MAX +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif + +#define OVS_NOT_REACHED() abort() + +/* Given a pointer-typed lvalue OBJECT, expands to a pointer type that may be + * assigned to OBJECT. */ +#ifdef __GNUC__ +#define OVS_TYPEOF(OBJECT) typeof(OBJECT) +#else +#define OVS_TYPEOF(OBJECT) void * +#endif + +/* Given OBJECT of type pointer-to-structure, expands to the offset of MEMBER + * within an instance of the structure. + * + * The GCC-specific version avoids the technicality of undefined behavior if + * OBJECT is null, invalid, or not yet initialized. This makes some static + * checkers (like Coverity) happier. But the non-GCC version does not actually + * dereference any pointer, so it would be surprising for it to cause any + * problems in practice. + */ +#ifdef __GNUC__ +#define OBJECT_OFFSETOF(OBJECT, MEMBER) offsetof(typeof(*(OBJECT)), MEMBER) +#else +#define OBJECT_OFFSETOF(OBJECT, MEMBER) \ + ((char *) &(OBJECT)->MEMBER - (char *) (OBJECT)) +#endif + +/* Yields the size of MEMBER within STRUCT. */ +#define MEMBER_SIZEOF(STRUCT, MEMBER) (sizeof(((STRUCT *) NULL)->MEMBER)) + +/* Given POINTER, the address of the given MEMBER in a STRUCT object, returns + the STRUCT object. */ +#define CONTAINER_OF(POINTER, STRUCT, MEMBER) \ + ((STRUCT *) (void *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER))) + +/* Given POINTER, the address of the given MEMBER within an object of the type + * that that OBJECT points to, returns OBJECT as an assignment-compatible + * pointer type (either the correct pointer type or "void *"). OBJECT must be + * an lvalue. + * + * This is the same as CONTAINER_OF except that it infers the structure type + * from the type of '*OBJECT'. */ +#define OBJECT_CONTAINING(POINTER, OBJECT, MEMBER) \ + ((OVS_TYPEOF(OBJECT)) (void *) \ + ((char *) (POINTER) - OBJECT_OFFSETOF(OBJECT, MEMBER))) + +/* Given POINTER, the address of the given MEMBER within an object of the type + * that that OBJECT points to, assigns the address of the outer object to + * OBJECT, which must be an lvalue. + * + * Evaluates to (void) 0 as the result is not to be used. */ +#define ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER) \ + ((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), (void) 0) + +/* As explained in the comment above OBJECT_OFFSETOF(), non-GNUC compilers + * like MSVC will complain about un-initialized variables if OBJECT + * hasn't already been initialized. To prevent such warnings, INIT_CONTAINER() + * can be used as a wrapper around ASSIGN_CONTAINER. */ +#define INIT_CONTAINER(OBJECT, POINTER, MEMBER) \ + ((OBJECT) = NULL, ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER)) + +/* Given ATTR, and TYPE, cast the ATTR to TYPE by first casting ATTR to + * (void *). This is to suppress the alignment warning issued by clang. */ +#define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR)) + +/* Use "%"PRIuSIZE to format size_t with printf(). */ +#ifdef _WIN32 +#define PRIdSIZE "Id" +#define PRIiSIZE "Ii" +#define PRIoSIZE "Io" +#define PRIuSIZE "Iu" +#define PRIxSIZE "Ix" +#define PRIXSIZE "IX" +#else +#define PRIdSIZE "zd" +#define PRIiSIZE "zi" +#define PRIoSIZE "zo" +#define PRIuSIZE "zu" +#define PRIxSIZE "zx" +#define PRIXSIZE "zX" +#endif + +#ifndef _WIN32 +typedef uint32_t HANDLE; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define set_program_name(name) \ + ovs_set_program_name(name, OVS_PACKAGE_VERSION) + +const char *get_subprogram_name(void); + void set_subprogram_name(const char *); + +void ovs_print_version(uint8_t min_ofp, uint8_t max_ofp); + +OVS_NO_RETURN void out_of_memory(void); +void *xmalloc(size_t) MALLOC_LIKE; +void *xcalloc(size_t, size_t) MALLOC_LIKE; +void *xzalloc(size_t) MALLOC_LIKE; +void *xrealloc(void *, size_t); +void *xmemdup(const void *, size_t) MALLOC_LIKE; +char *xmemdup0(const char *, size_t) MALLOC_LIKE; +char *xstrdup(const char *) MALLOC_LIKE; +char *xasprintf(const char *format, ...) OVS_PRINTF_FORMAT(1, 2) MALLOC_LIKE; +char *xvasprintf(const char *format, va_list) OVS_PRINTF_FORMAT(1, 0) MALLOC_LIKE; +void *x2nrealloc(void *p, size_t *n, size_t s); + +void *xmalloc_cacheline(size_t) MALLOC_LIKE; +void *xzalloc_cacheline(size_t) MALLOC_LIKE; +void free_cacheline(void *); + +void ovs_strlcpy(char *dst, const char *src, size_t size); +void ovs_strzcpy(char *dst, const char *src, size_t size); + +OVS_NO_RETURN void ovs_abort(int err_no, const char *format, ...) + OVS_PRINTF_FORMAT(2, 3); +OVS_NO_RETURN void ovs_abort_valist(int err_no, const char *format, va_list) + OVS_PRINTF_FORMAT(2, 0); +OVS_NO_RETURN void ovs_fatal(int err_no, const char *format, ...) + OVS_PRINTF_FORMAT(2, 3); +OVS_NO_RETURN void ovs_fatal_valist(int err_no, const char *format, va_list) + OVS_PRINTF_FORMAT(2, 0); +void ovs_error(int err_no, const char *format, ...) OVS_PRINTF_FORMAT(2, 3); +void ovs_error_valist(int err_no, const char *format, va_list) + OVS_PRINTF_FORMAT(2, 0); +const char *ovs_retval_to_string(int); +const char *ovs_strerror(int); +void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii); + +bool str_to_int(const char *, int base, int *); +bool str_to_long(const char *, int base, long *); +bool str_to_llong(const char *, int base, long long *); +bool str_to_uint(const char *, int base, unsigned int *); + +bool ovs_scan(const char *s, const char *format, ...) OVS_SCANF_FORMAT(2, 3); +bool ovs_scan_len(const char *s, int *n, const char *format, ...); + +bool str_to_double(const char *, double *); + +int hexit_value(int c); +uintmax_t hexits_value(const char *s, size_t n, bool *ok); + +int parse_int_string(const char *s, uint8_t *valuep, int field_width, + char **tail); + +const char *english_list_delimiter(size_t index, size_t total); + +char *get_cwd(void); +#ifndef _WIN32 +char *dir_name(const char *file_name); +char *base_name(const char *file_name); +#endif +char *abs_file_name(const char *dir, const char *file_name); + +char *follow_symlinks(const char *filename); + +void ignore(bool x OVS_UNUSED); + +/* Bitwise tests. */ + +/* Returns the number of trailing 0-bits in 'n'. Undefined if 'n' == 0. */ +#if __GNUC__ >= 4 +static inline int +raw_ctz(uint64_t n) +{ + /* With GCC 4.7 on 32-bit x86, if a 32-bit integer is passed as 'n', using + * a plain __builtin_ctzll() here always generates an out-of-line function + * call. The test below helps it to emit a single 'bsf' instruction. */ + return (__builtin_constant_p(n <= UINT32_MAX) && n <= UINT32_MAX + ? __builtin_ctz(n) + : __builtin_ctzll(n)); +} + +static inline int +raw_clz64(uint64_t n) +{ + return __builtin_clzll(n); +} +#elif _MSC_VER +static inline int +raw_ctz(uint64_t n) +{ +#ifdef _WIN64 + unsigned long r = 0; + _BitScanForward64(&r, n); + return r; +#else + unsigned long low = n, high, r = 0; + if (_BitScanForward(&r, low)) { + return r; + } + high = n >> 32; + _BitScanForward(&r, high); + return r + 32; +#endif +} + +static inline int +raw_clz64(uint64_t n) +{ +#ifdef _WIN64 + unsigned long r = 0; + _BitScanReverse64(&r, n); + return 63 - r; +#else + unsigned long low, high = n >> 32, r = 0; + if (_BitScanReverse(&r, high)) { + return 31 - r; + } + low = n; + _BitScanReverse(&r, low); + return 63 - r; +#endif +} +#else +/* Defined in util.c. */ +int raw_ctz(uint64_t n); +int raw_clz64(uint64_t n); +#endif + +/* Returns the number of trailing 0-bits in 'n', or 32 if 'n' is 0. */ +static inline int +ctz32(uint32_t n) +{ + return n ? raw_ctz(n) : 32; +} + +/* Returns the number of trailing 0-bits in 'n', or 64 if 'n' is 0. */ +static inline int +ctz64(uint64_t n) +{ + return n ? raw_ctz(n) : 64; +} + +/* Returns the number of leading 0-bits in 'n', or 32 if 'n' is 0. */ +static inline int +clz32(uint32_t n) +{ + return n ? raw_clz64(n) - 32 : 32; +} + +/* Returns the number of leading 0-bits in 'n', or 64 if 'n' is 0. */ +static inline int +clz64(uint64_t n) +{ + return n ? raw_clz64(n) : 64; +} + +/* Given a word 'n', calculates floor(log_2('n')). This is equivalent + * to finding the bit position of the most significant one bit in 'n'. It is + * an error to call this function with 'n' == 0. */ +static inline int +log_2_floor(uint64_t n) +{ + return 63 - raw_clz64(n); +} + +/* Given a word 'n', calculates ceil(log_2('n')). It is an error to + * call this function with 'n' == 0. */ +static inline int +log_2_ceil(uint64_t n) +{ + return log_2_floor(n) + !is_pow2(n); +} + +/* unsigned int count_1bits(uint64_t x): + * + * Returns the number of 1-bits in 'x', between 0 and 64 inclusive. */ +#if UINTPTR_MAX == UINT64_MAX +static inline unsigned int +count_1bits(uint64_t x) +{ +#if __GNUC__ >= 4 && __POPCNT__ + return __builtin_popcountll(x); +#else + /* This portable implementation is the fastest one we know of for 64 + * bits, and about 3x faster than GCC 4.7 __builtin_popcountll(). */ + const uint64_t h55 = UINT64_C(0x5555555555555555); + const uint64_t h33 = UINT64_C(0x3333333333333333); + const uint64_t h0F = UINT64_C(0x0F0F0F0F0F0F0F0F); + const uint64_t h01 = UINT64_C(0x0101010101010101); + x -= (x >> 1) & h55; /* Count of each 2 bits in-place. */ + x = (x & h33) + ((x >> 2) & h33); /* Count of each 4 bits in-place. */ + x = (x + (x >> 4)) & h0F; /* Count of each 8 bits in-place. */ + return (x * h01) >> 56; /* Sum of all bytes. */ +#endif +} +#else /* Not 64-bit. */ +#if __GNUC__ >= 4 && __POPCNT__ +static inline unsigned int +count_1bits_32__(uint32_t x) +{ + return __builtin_popcount(x); +} +#else +#define NEED_COUNT_1BITS_8 1 +extern const uint8_t count_1bits_8[256]; +static inline unsigned int +count_1bits_32__(uint32_t x) +{ + /* This portable implementation is the fastest one we know of for 32 bits, + * and faster than GCC __builtin_popcount(). */ + return (count_1bits_8[x & 0xff] + + count_1bits_8[(x >> 8) & 0xff] + + count_1bits_8[(x >> 16) & 0xff] + + count_1bits_8[x >> 24]); +} +#endif +static inline unsigned int +count_1bits(uint64_t x) +{ + return count_1bits_32__(x) + count_1bits_32__(x >> 32); +} +#endif + +/* Returns the rightmost 1-bit in 'x' (e.g. 01011000 => 00001000), or 0 if 'x' + * is 0. */ +static inline uintmax_t +rightmost_1bit(uintmax_t x) +{ + return x & -x; +} + +/* Returns 'x' with its rightmost 1-bit changed to a zero (e.g. 01011000 => + * 01010000), or 0 if 'x' is 0. */ +static inline uintmax_t +zero_rightmost_1bit(uintmax_t x) +{ + return x & (x - 1); +} + +/* Returns the index of the rightmost 1-bit in 'x' (e.g. 01011000 => 3), or an + * undefined value if 'x' is 0. */ +static inline int +rightmost_1bit_idx(uint64_t x) +{ + return ctz64(x); +} + +/* Returns the index of the leftmost 1-bit in 'x' (e.g. 01011000 => 6), or an + * undefined value if 'x' is 0. */ +static inline uint32_t +leftmost_1bit_idx(uint64_t x) +{ + return log_2_floor(x); +} + +/* Return a ovs_be32 prefix in network byte order with 'plen' highest bits set. + * Shift with 32 is undefined behavior, but we rather use 64-bit shift than + * compare. */ +static inline ovs_be32 be32_prefix_mask(int plen) +{ + return htonl((uint64_t)UINT32_MAX << (32 - plen)); +} + +bool is_all_zeros(const void *, size_t); +bool is_all_ones(const void *, size_t); +void bitwise_copy(const void *src, unsigned int src_len, unsigned int src_ofs, + void *dst, unsigned int dst_len, unsigned int dst_ofs, + unsigned int n_bits); +void bitwise_zero(void *dst_, unsigned int dst_len, unsigned dst_ofs, + unsigned int n_bits); +void bitwise_one(void *dst_, unsigned int dst_len, unsigned dst_ofs, + unsigned int n_bits); +bool bitwise_is_all_zeros(const void *, unsigned int len, unsigned int ofs, + unsigned int n_bits); +unsigned int bitwise_scan(const void *, unsigned int len, + bool target, unsigned int start, unsigned int end); +int bitwise_rscan(const void *, unsigned int len, bool target, + int start, int end); +void bitwise_put(uint64_t value, + void *dst, unsigned int dst_len, unsigned int dst_ofs, + unsigned int n_bits); +uint64_t bitwise_get(const void *src, unsigned int src_len, + unsigned int src_ofs, unsigned int n_bits); +bool bitwise_get_bit(const void *src, unsigned int len, unsigned int ofs); +void bitwise_put0(void *dst, unsigned int len, unsigned int ofs); +void bitwise_put1(void *dst, unsigned int len, unsigned int ofs); +void bitwise_put_bit(void *dst, unsigned int len, unsigned int ofs, bool); +void bitwise_toggle_bit(void *dst, unsigned int len, unsigned int ofs); + +/* Returns non-zero if the parameters have equal value. */ +static inline int +ovs_u128_equals(const ovs_u128 *a, const ovs_u128 *b) +{ + return (a->u64.hi == b->u64.hi) && (a->u64.lo == b->u64.lo); +} + +/* Returns true if 'val' is 0. */ +static inline bool +ovs_u128_is_zero(const ovs_u128 *val) +{ + return !(val->u64.hi || val->u64.lo); +} + +/* Returns true if 'val' is all ones. */ +static inline bool +ovs_u128_is_ones(const ovs_u128 *val) +{ + return ovs_u128_equals(val, &OVS_U128_MAX); +} + +/* Returns non-zero if the parameters have equal value. */ +static inline int +ovs_be128_equals(const ovs_be128 *a, const ovs_be128 *b) +{ + return (a->be64.hi == b->be64.hi) && (a->be64.lo == b->be64.lo); +} + +/* Returns true if 'val' is 0. */ +static inline bool +ovs_be128_is_zero(const ovs_be128 *val) +{ + return !(val->be64.hi || val->be64.lo); +} + +static inline ovs_u128 +ovs_u128_and(const ovs_u128 a, const ovs_u128 b) +{ + ovs_u128 dst; + + dst.u64.hi = a.u64.hi & b.u64.hi; + dst.u64.lo = a.u64.lo & b.u64.lo; + + return dst; +} + +void xsleep(unsigned int seconds); + +#ifdef _WIN32 + +char *ovs_format_message(int error); +char *ovs_lasterror_to_string(void); +int ftruncate(int fd, off_t length); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* util.h */ --- /dev/null +++ ovs/lib/compiler.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. + * + * 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 COMPILER_H +#define COMPILER_H 1 + +#include "openvswitch/compiler.h" + +#if __GNUC__ && !__CHECKER__ +#define STRFTIME_FORMAT(FMT) __attribute__((__format__(__strftime__, FMT, 0))) +#define MALLOC_LIKE __attribute__((__malloc__)) +#define ALWAYS_INLINE __attribute__((always_inline)) +#define SENTINEL(N) __attribute__((sentinel(N))) +#else +#define STRFTIME_FORMAT(FMT) +#define MALLOC_LIKE +#define ALWAYS_INLINE +#define SENTINEL(N) +#endif + +/* Output a message (not an error) while compiling without failing the + * compilation process */ +#if HAVE_PRAGMA_MESSAGE +#define DO_PRAGMA(x) _Pragma(#x) +#define BUILD_MESSAGE(x) \ + DO_PRAGMA(message(x)) +#else +#define BUILD_MESSAGE(x) +#endif + +#endif /* compiler.h */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor