openflow build environment setup
This commit is contained in:
269
openflow/include/openvswitch/compiler.h
Normal file
269
openflow/include/openvswitch/compiler.h
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 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 OPENVSWITCH_COMPILER_H
|
||||
#define OPENVSWITCH_COMPILER_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
#ifndef __has_extension
|
||||
#define __has_extension(x) 0
|
||||
#endif
|
||||
|
||||
/* To make OVS_NO_RETURN portable across gcc/clang and MSVC, it should be
|
||||
* added at the beginning of the function declaration. */
|
||||
#if __GNUC__ && !__CHECKER__
|
||||
#define OVS_NO_RETURN __attribute__((__noreturn__))
|
||||
#elif _MSC_VER
|
||||
#define OVS_NO_RETURN __declspec(noreturn)
|
||||
#else
|
||||
#define OVS_NO_RETURN
|
||||
#endif
|
||||
|
||||
#if __GNUC__ && !__CHECKER__
|
||||
#define OVS_UNUSED __attribute__((__unused__))
|
||||
#define OVS_PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1)))
|
||||
#define OVS_SCANF_FORMAT(FMT, ARG1) __attribute__((__format__(scanf, FMT, ARG1)))
|
||||
#define OVS_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
|
||||
#define OVS_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1)
|
||||
#define OVS_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0)
|
||||
#else
|
||||
#define OVS_UNUSED
|
||||
#define OVS_PRINTF_FORMAT(FMT, ARG1)
|
||||
#define OVS_SCANF_FORMAT(FMT, ARG1)
|
||||
#define OVS_WARN_UNUSED_RESULT
|
||||
#define OVS_LIKELY(CONDITION) (!!(CONDITION))
|
||||
#define OVS_UNLIKELY(CONDITION) (!!(CONDITION))
|
||||
#endif
|
||||
|
||||
#if __has_feature(c_thread_safety_attributes)
|
||||
/* "clang" annotations for thread safety check.
|
||||
*
|
||||
* OVS_LOCKABLE indicates that the struct contains mutex element
|
||||
* which can be locked by functions like ovs_mutex_lock().
|
||||
*
|
||||
* Below, the word MUTEX stands for the name of an object with an OVS_LOCKABLE
|
||||
* struct type. It can also be a comma-separated list of multiple structs,
|
||||
* e.g. to require a function to hold multiple locks while invoked.
|
||||
*
|
||||
*
|
||||
* On a variable:
|
||||
*
|
||||
* - OVS_GUARDED indicates that the variable may only be accessed some mutex
|
||||
* is held.
|
||||
*
|
||||
* - OVS_GUARDED_BY(MUTEX) indicates that the variable may only be accessed
|
||||
* while the specific MUTEX is held.
|
||||
*
|
||||
*
|
||||
* On a variable A of mutex type:
|
||||
*
|
||||
* - OVS_ACQ_BEFORE(B), where B is a mutex or a comma-separated list of
|
||||
* mutexes, declare that if both A and B are acquired at the same time,
|
||||
* then A must be acquired before B. That is, B nests inside A.
|
||||
*
|
||||
* - OVS_ACQ_AFTER(B) is the opposite of OVS_ACQ_BEFORE(B), that is, it
|
||||
* declares that A nests inside B.
|
||||
*
|
||||
*
|
||||
* On a function, the following attributes apply to mutexes:
|
||||
*
|
||||
* - OVS_ACQUIRES(MUTEX) indicate that the function must be called without
|
||||
* holding MUTEX and that it returns holding MUTEX.
|
||||
*
|
||||
* - OVS_RELEASES(MUTEX) indicates that the function may only be called with
|
||||
* MUTEX held and that it returns with MUTEX released. It can be used for
|
||||
* all types of MUTEX.
|
||||
*
|
||||
* - OVS_TRY_LOCK(RETVAL, MUTEX) indicate that the function will try to
|
||||
* acquire MUTEX. RETVAL is an integer or boolean value specifying the
|
||||
* return value of a successful lock acquisition.
|
||||
*
|
||||
* - OVS_REQUIRES(MUTEX) indicate that the function may only be called with
|
||||
* MUTEX held and that the function does not release MUTEX.
|
||||
*
|
||||
* - OVS_EXCLUDED(MUTEX) indicates that the function may only be called when
|
||||
* MUTEX is not held.
|
||||
*
|
||||
*
|
||||
* The following variants, with the same syntax, apply to reader-writer locks:
|
||||
*
|
||||
* mutex rwlock, for reading rwlock, for writing
|
||||
* ------------------- ------------------- -------------------
|
||||
* OVS_ACQUIRES OVS_ACQ_RDLOCK OVS_ACQ_WRLOCK
|
||||
* OVS_RELEASES OVS_RELEASES OVS_RELEASES
|
||||
* OVS_TRY_LOCK OVS_TRY_RDLOCK OVS_TRY_WRLOCK
|
||||
* OVS_REQUIRES OVS_REQ_RDLOCK OVS_REQ_WRLOCK
|
||||
* OVS_EXCLUDED OVS_EXCLUDED OVS_EXCLUDED
|
||||
*/
|
||||
#define OVS_LOCKABLE __attribute__((lockable))
|
||||
#define OVS_REQ_RDLOCK(...) __attribute__((shared_locks_required(__VA_ARGS__)))
|
||||
#define OVS_ACQ_RDLOCK(...) __attribute__((shared_lock_function(__VA_ARGS__)))
|
||||
#define OVS_REQ_WRLOCK(...) \
|
||||
__attribute__((exclusive_locks_required(__VA_ARGS__)))
|
||||
#define OVS_ACQ_WRLOCK(...) \
|
||||
__attribute__((exclusive_lock_function(__VA_ARGS__)))
|
||||
#define OVS_REQUIRES(...) \
|
||||
__attribute__((exclusive_locks_required(__VA_ARGS__)))
|
||||
#define OVS_ACQUIRES(...) \
|
||||
__attribute__((exclusive_lock_function(__VA_ARGS__)))
|
||||
#define OVS_TRY_WRLOCK(RETVAL, ...) \
|
||||
__attribute__((exclusive_trylock_function(RETVAL, __VA_ARGS__)))
|
||||
#define OVS_TRY_RDLOCK(RETVAL, ...) \
|
||||
__attribute__((shared_trylock_function(RETVAL, __VA_ARGS__)))
|
||||
#define OVS_TRY_LOCK(RETVAL, ...) \
|
||||
__attribute__((exclusive_trylock_function(RETVAL, __VA_ARGS__)))
|
||||
#define OVS_GUARDED __attribute__((guarded_var))
|
||||
#define OVS_GUARDED_BY(...) __attribute__((guarded_by(__VA_ARGS__)))
|
||||
#define OVS_RELEASES(...) __attribute__((unlock_function(__VA_ARGS__)))
|
||||
#define OVS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
|
||||
#define OVS_ACQ_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
|
||||
#define OVS_ACQ_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
|
||||
#define OVS_NO_THREAD_SAFETY_ANALYSIS \
|
||||
__attribute__((no_thread_safety_analysis))
|
||||
#else /* not Clang */
|
||||
#define OVS_LOCKABLE
|
||||
#define OVS_REQ_RDLOCK(...)
|
||||
#define OVS_ACQ_RDLOCK(...)
|
||||
#define OVS_REQ_WRLOCK(...)
|
||||
#define OVS_ACQ_WRLOCK(...)
|
||||
#define OVS_REQUIRES(...)
|
||||
#define OVS_ACQUIRES(...)
|
||||
#define OVS_TRY_WRLOCK(...)
|
||||
#define OVS_TRY_RDLOCK(...)
|
||||
#define OVS_TRY_LOCK(...)
|
||||
#define OVS_GUARDED
|
||||
#define OVS_GUARDED_BY(...)
|
||||
#define OVS_EXCLUDED(...)
|
||||
#define OVS_RELEASES(...)
|
||||
#define OVS_ACQ_BEFORE(...)
|
||||
#define OVS_ACQ_AFTER(...)
|
||||
#define OVS_NO_THREAD_SAFETY_ANALYSIS
|
||||
#endif
|
||||
|
||||
/* ISO C says that a C implementation may choose any integer type for an enum
|
||||
* that is sufficient to hold all of its values. Common ABIs (such as the
|
||||
* System V ABI used on i386 GNU/Linux) always use a full-sized "int", even
|
||||
* when a smaller type would suffice.
|
||||
*
|
||||
* In GNU C, "enum __attribute__((packed)) name { ... }" defines 'name' as an
|
||||
* enum compatible with a type that is no bigger than necessary. This is the
|
||||
* intended use of OVS_PACKED_ENUM.
|
||||
*
|
||||
* OVS_PACKED_ENUM is intended for use only as a space optimization, since it
|
||||
* only works with GCC. That means that it must not be used in wire protocols
|
||||
* or otherwise exposed outside of a single process. */
|
||||
#if __GNUC__ && !__CHECKER__
|
||||
#define OVS_PACKED_ENUM __attribute__((__packed__))
|
||||
#define HAVE_PACKED_ENUM
|
||||
#else
|
||||
#define OVS_PACKED_ENUM
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define OVS_PACKED(DECL) DECL __attribute__((__packed__))
|
||||
#else
|
||||
#define OVS_PACKED(DECL) __pragma(pack(push, 1)) DECL __pragma(pack(pop))
|
||||
#endif
|
||||
|
||||
/* OVS_ALIGNED_STRUCT may be used to define a structure whose instances should
|
||||
* aligned on an N-byte boundary. This:
|
||||
* OVS_ALIGNED_STRUCT(64, mystruct) { ... };
|
||||
* is equivalent to the following except that it specifies 64-byte alignment:
|
||||
* struct mystruct { ... };
|
||||
*
|
||||
* OVS_ALIGNED_VAR defines a variable aligned on an N-byte boundary. For
|
||||
* example,
|
||||
* OVS_ALIGNED_VAR(64) int x;
|
||||
* defines a "int" variable that is aligned on a 64-byte boundary.
|
||||
*/
|
||||
#ifndef _MSC_VER
|
||||
#define OVS_ALIGNED_STRUCT(N, TAG) struct __attribute__((aligned(N))) TAG
|
||||
#define OVS_ALIGNED_VAR(N) __attribute__((aligned(N)))
|
||||
#else
|
||||
#define OVS_ALIGNED_STRUCT(N, TAG) __declspec(align(N)) struct TAG
|
||||
#define OVS_ALIGNED_VAR(N) __declspec(align(N))
|
||||
#endif
|
||||
|
||||
/* Supplies code to be run at startup time before invoking main().
|
||||
* Use as:
|
||||
*
|
||||
* OVS_CONSTRUCTOR(my_constructor) {
|
||||
* ...some code...
|
||||
* }
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#define CCALL __cdecl
|
||||
#pragma section(".CRT$XCU",read)
|
||||
#define OVS_CONSTRUCTOR(f) \
|
||||
static void __cdecl f(void); \
|
||||
__declspec(allocate(".CRT$XCU")) static void (__cdecl*f##_)(void) = f; \
|
||||
static void __cdecl f(void)
|
||||
#else
|
||||
#define OVS_CONSTRUCTOR(f) \
|
||||
static void f(void) __attribute__((constructor)); \
|
||||
static void f(void)
|
||||
#endif
|
||||
|
||||
/* OVS_PREFETCH() can be used to instruct the CPU to fetch the cache
|
||||
* line containing the given address to a CPU cache.
|
||||
* OVS_PREFETCH_WRITE() should be used when the memory is going to be
|
||||
* written to. Depending on the target CPU, this can generate the same
|
||||
* instruction as OVS_PREFETCH(), or bring the data into the cache in an
|
||||
* exclusive state. */
|
||||
#if __GNUC__
|
||||
#define OVS_PREFETCH(addr) __builtin_prefetch((addr))
|
||||
#define OVS_PREFETCH_WRITE(addr) __builtin_prefetch((addr), 1)
|
||||
#else
|
||||
#define OVS_PREFETCH(addr)
|
||||
#define OVS_PREFETCH_WRITE(addr)
|
||||
#endif
|
||||
|
||||
/* Build assertions. */
|
||||
#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
|
||||
|
||||
|
||||
#endif /* compiler.h */
|
||||
93
openflow/include/openvswitch/dynamic-string.h
Normal file
93
openflow/include/openvswitch/dynamic-string.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016 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 OPENVSWITCH_DYNAMIC_STRING_H
|
||||
#define OPENVSWITCH_DYNAMIC_STRING_H 1
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "openvswitch/compiler.h"
|
||||
|
||||
/* A "dynamic string", that is, a buffer that can be used to construct a
|
||||
* string across a series of operations that extend or modify it.
|
||||
*
|
||||
* The 'string' member does not always point to a null-terminated string.
|
||||
* Initially it is NULL, and even when it is nonnull, some operations do not
|
||||
* ensure that it is null-terminated. Use ds_cstr() to ensure that memory is
|
||||
* allocated for the string and that it is null-terminated. */
|
||||
struct ds {
|
||||
char *string; /* Null-terminated string. */
|
||||
size_t length; /* Bytes used, not including null terminator. */
|
||||
size_t allocated; /* Bytes allocated, not including null terminator. */
|
||||
};
|
||||
|
||||
#define DS_EMPTY_INITIALIZER { NULL, 0, 0 }
|
||||
|
||||
void ds_init(struct ds *);
|
||||
void ds_clear(struct ds *);
|
||||
void ds_truncate(struct ds *, size_t new_length);
|
||||
void ds_reserve(struct ds *, size_t min_length);
|
||||
char *ds_put_uninit(struct ds *, size_t n);
|
||||
static inline void ds_put_char(struct ds *, char);
|
||||
void ds_put_utf8(struct ds *, int uc);
|
||||
void ds_put_char_multiple(struct ds *, char, size_t n);
|
||||
void ds_put_buffer(struct ds *, const char *, size_t n);
|
||||
void ds_put_cstr(struct ds *, const char *);
|
||||
void ds_put_and_free_cstr(struct ds *, char *);
|
||||
void ds_put_format(struct ds *, const char *, ...) OVS_PRINTF_FORMAT(2, 3);
|
||||
void ds_put_format_valist(struct ds *, const char *, va_list)
|
||||
OVS_PRINTF_FORMAT(2, 0);
|
||||
void ds_put_printable(struct ds *, const char *, size_t);
|
||||
void ds_put_hex(struct ds *ds, const void *buf, size_t size);
|
||||
void ds_put_hex_dump(struct ds *ds, const void *buf_, size_t size,
|
||||
uintptr_t ofs, bool ascii);
|
||||
int ds_get_line(struct ds *, FILE *);
|
||||
int ds_get_preprocessed_line(struct ds *, FILE *, int *line_number);
|
||||
int ds_get_test_line(struct ds *, FILE *);
|
||||
|
||||
void ds_put_strftime_msec(struct ds *, const char *format, long long int when,
|
||||
bool utc);
|
||||
char *xastrftime_msec(const char *format, long long int when, bool utc);
|
||||
|
||||
char *ds_cstr(struct ds *);
|
||||
const char *ds_cstr_ro(const struct ds *);
|
||||
char *ds_steal_cstr(struct ds *);
|
||||
void ds_destroy(struct ds *);
|
||||
void ds_swap(struct ds *, struct ds *);
|
||||
|
||||
int ds_last(const struct ds *);
|
||||
bool ds_chomp(struct ds *, int c);
|
||||
void ds_clone(struct ds *, struct ds *);
|
||||
|
||||
/* Inline functions. */
|
||||
|
||||
void ds_put_char__(struct ds *, char);
|
||||
|
||||
static inline void
|
||||
ds_put_char(struct ds *ds, char c)
|
||||
{
|
||||
if (ds->length < ds->allocated) {
|
||||
ds->string[ds->length++] = c;
|
||||
ds->string[ds->length] = '\0';
|
||||
} else {
|
||||
ds_put_char__(ds, c);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* dynamic-string.h */
|
||||
204
openflow/include/openvswitch/flow.h
Normal file
204
openflow/include/openvswitch/flow.h
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 OPENVSWITCH_FLOW_H
|
||||
#define OPENVSWITCH_FLOW_H 1
|
||||
|
||||
#include "openflow/nicira-ext.h"
|
||||
#include "openvswitch/packets.h"
|
||||
#include "openvswitch/util.h"
|
||||
|
||||
/* This sequence number should be incremented whenever anything involving flows
|
||||
* or the wildcarding of flows changes. This will cause build assertion
|
||||
* failures in places which likely need to be updated. */
|
||||
#define FLOW_WC_SEQ 36
|
||||
|
||||
/* Number of Open vSwitch extension 32-bit registers. */
|
||||
#define FLOW_N_REGS 16
|
||||
BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
|
||||
BUILD_ASSERT_DECL(FLOW_N_REGS % 4 == 0); /* Handle xxregs. */
|
||||
|
||||
/* Number of OpenFlow 1.5+ 64-bit registers.
|
||||
*
|
||||
* Each of these overlays a pair of Open vSwitch 32-bit registers, so there
|
||||
* are half as many of them.*/
|
||||
#define FLOW_N_XREGS (FLOW_N_REGS / 2)
|
||||
|
||||
/* Number of 128-bit registers.
|
||||
*
|
||||
* Each of these overlays four Open vSwitch 32-bit registers, so there
|
||||
* are a quarter as many of them.*/
|
||||
#define FLOW_N_XXREGS (FLOW_N_REGS / 4)
|
||||
|
||||
/* Used for struct flow's dl_type member for frames that have no Ethernet
|
||||
* type, that is, pure 802.2 frames. */
|
||||
#define FLOW_DL_TYPE_NONE 0x5ff
|
||||
|
||||
/* Fragment bits, used for IPv4 and IPv6, always zero for non-IP flows. */
|
||||
#define FLOW_NW_FRAG_ANY (1 << 0) /* Set for any IP frag. */
|
||||
#define FLOW_NW_FRAG_LATER (1 << 1) /* Set for IP frag with nonzero offset. */
|
||||
#define FLOW_NW_FRAG_MASK (FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER)
|
||||
|
||||
BUILD_ASSERT_DECL(FLOW_NW_FRAG_ANY == NX_IP_FRAG_ANY);
|
||||
BUILD_ASSERT_DECL(FLOW_NW_FRAG_LATER == NX_IP_FRAG_LATER);
|
||||
|
||||
BUILD_ASSERT_DECL(FLOW_TNL_F_OAM == NX_TUN_FLAG_OAM);
|
||||
|
||||
const char *flow_tun_flag_to_string(uint32_t flags);
|
||||
|
||||
/* Maximum number of supported MPLS labels. */
|
||||
#define FLOW_MAX_MPLS_LABELS 3
|
||||
|
||||
/*
|
||||
* A flow in the network.
|
||||
*
|
||||
* Must be initialized to all zeros to make any compiler-induced padding
|
||||
* zeroed. Helps also in keeping unused fields (such as mutually exclusive
|
||||
* IPv4 and IPv6 addresses) zeroed out.
|
||||
*
|
||||
* The meaning of 'in_port' is context-dependent. In most cases, it is a
|
||||
* 16-bit OpenFlow 1.0 port number. In the software datapath interface (dpif)
|
||||
* layer and its implementations (e.g. dpif-netlink, dpif-netdev), it is
|
||||
* instead a 32-bit datapath port number.
|
||||
*
|
||||
* The fields are organized in four segments to facilitate staged lookup, where
|
||||
* lower layer fields are first used to determine if the later fields need to
|
||||
* be looked at. This enables better wildcarding for datapath flows.
|
||||
*
|
||||
* NOTE: Order of the fields is significant, any change in the order must be
|
||||
* reflected in miniflow_extract()!
|
||||
*/
|
||||
struct flow {
|
||||
/* Metadata */
|
||||
struct flow_tnl tunnel; /* Encapsulating tunnel parameters. */
|
||||
ovs_be64 metadata; /* OpenFlow Metadata. */
|
||||
uint32_t regs[FLOW_N_REGS]; /* Registers. */
|
||||
uint32_t skb_priority; /* Packet priority for QoS. */
|
||||
uint32_t pkt_mark; /* Packet mark. */
|
||||
uint32_t dp_hash; /* Datapath computed hash value. The exact
|
||||
* computation is opaque to the user space. */
|
||||
union flow_in_port in_port; /* Input port.*/
|
||||
uint32_t recirc_id; /* Must be exact match. */
|
||||
uint16_t ct_state; /* Connection tracking state. */
|
||||
uint16_t ct_zone; /* Connection tracking zone. */
|
||||
uint32_t ct_mark; /* Connection mark.*/
|
||||
uint8_t pad1[4]; /* Pad to 64 bits. */
|
||||
ovs_u128 ct_label; /* Connection label. */
|
||||
uint32_t conj_id; /* Conjunction ID. */
|
||||
ofp_port_t actset_output; /* Output port in action set. */
|
||||
|
||||
/* L2, Order the same as in the Ethernet header! (64-bit aligned) */
|
||||
struct eth_addr dl_dst; /* Ethernet destination address. */
|
||||
struct eth_addr dl_src; /* Ethernet source address. */
|
||||
ovs_be16 dl_type; /* Ethernet frame type. */
|
||||
ovs_be16 vlan_tci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */
|
||||
ovs_be32 mpls_lse[ROUND_UP(FLOW_MAX_MPLS_LABELS, 2)]; /* MPLS label stack
|
||||
(with padding). */
|
||||
/* L3 (64-bit aligned) */
|
||||
ovs_be32 nw_src; /* IPv4 source address or ARP SPA. */
|
||||
ovs_be32 nw_dst; /* IPv4 destination address or ARP TPA. */
|
||||
struct in6_addr ipv6_src; /* IPv6 source address. */
|
||||
struct in6_addr ipv6_dst; /* IPv6 destination address. */
|
||||
ovs_be32 ipv6_label; /* IPv6 flow label. */
|
||||
uint8_t nw_frag; /* FLOW_FRAG_* flags. */
|
||||
uint8_t nw_tos; /* IP ToS (including DSCP and ECN). */
|
||||
uint8_t nw_ttl; /* IP TTL/Hop Limit. */
|
||||
uint8_t nw_proto; /* IP protocol or low 8 bits of ARP opcode. */
|
||||
struct in6_addr nd_target; /* IPv6 neighbor discovery (ND) target. */
|
||||
struct eth_addr arp_sha; /* ARP/ND source hardware address. */
|
||||
struct eth_addr arp_tha; /* ARP/ND target hardware address. */
|
||||
ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */
|
||||
ovs_be16 pad3; /* Pad to 64 bits. */
|
||||
|
||||
/* L4 (64-bit aligned) */
|
||||
ovs_be16 tp_src; /* TCP/UDP/SCTP source port/ICMP type. */
|
||||
ovs_be16 tp_dst; /* TCP/UDP/SCTP destination port/ICMP code. */
|
||||
ovs_be32 igmp_group_ip4; /* IGMP group IPv4 address.
|
||||
* Keep last for BUILD_ASSERT_DECL below. */
|
||||
};
|
||||
BUILD_ASSERT_DECL(sizeof(struct flow) % sizeof(uint64_t) == 0);
|
||||
BUILD_ASSERT_DECL(sizeof(struct flow_tnl) % sizeof(uint64_t) == 0);
|
||||
|
||||
#define FLOW_U64S (sizeof(struct flow) / sizeof(uint64_t))
|
||||
|
||||
/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
|
||||
BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t)
|
||||
== sizeof(struct flow_tnl) + 248
|
||||
&& FLOW_WC_SEQ == 36);
|
||||
|
||||
/* Incremental points at which flow classification may be performed in
|
||||
* segments.
|
||||
* This is located here since this is dependent on the structure of the
|
||||
* struct flow defined above:
|
||||
* Each offset must be on a distinct, successive U64 boundary strictly
|
||||
* within the struct flow. */
|
||||
enum {
|
||||
FLOW_SEGMENT_1_ENDS_AT = offsetof(struct flow, dl_dst),
|
||||
FLOW_SEGMENT_2_ENDS_AT = offsetof(struct flow, nw_src),
|
||||
FLOW_SEGMENT_3_ENDS_AT = offsetof(struct flow, tp_src),
|
||||
};
|
||||
BUILD_ASSERT_DECL(FLOW_SEGMENT_1_ENDS_AT % sizeof(uint64_t) == 0);
|
||||
BUILD_ASSERT_DECL(FLOW_SEGMENT_2_ENDS_AT % sizeof(uint64_t) == 0);
|
||||
BUILD_ASSERT_DECL(FLOW_SEGMENT_3_ENDS_AT % sizeof(uint64_t) == 0);
|
||||
BUILD_ASSERT_DECL( 0 < FLOW_SEGMENT_1_ENDS_AT);
|
||||
BUILD_ASSERT_DECL(FLOW_SEGMENT_1_ENDS_AT < FLOW_SEGMENT_2_ENDS_AT);
|
||||
BUILD_ASSERT_DECL(FLOW_SEGMENT_2_ENDS_AT < FLOW_SEGMENT_3_ENDS_AT);
|
||||
BUILD_ASSERT_DECL(FLOW_SEGMENT_3_ENDS_AT < sizeof(struct flow));
|
||||
|
||||
/* Wildcards for a flow.
|
||||
*
|
||||
* A 1-bit in each bit in 'masks' indicates that the corresponding bit of
|
||||
* the flow is significant (must match). A 0-bit indicates that the
|
||||
* corresponding bit of the flow is wildcarded (need not match). */
|
||||
struct flow_wildcards {
|
||||
struct flow masks;
|
||||
};
|
||||
|
||||
#define WC_MASK_FIELD(WC, FIELD) \
|
||||
memset(&(WC)->masks.FIELD, 0xff, sizeof (WC)->masks.FIELD)
|
||||
#define WC_MASK_FIELD_MASK(WC, FIELD, MASK) \
|
||||
((WC)->masks.FIELD |= (MASK))
|
||||
#define WC_UNMASK_FIELD(WC, FIELD) \
|
||||
memset(&(WC)->masks.FIELD, 0, sizeof (WC)->masks.FIELD)
|
||||
|
||||
void flow_wildcards_init_catchall(struct flow_wildcards *);
|
||||
|
||||
void flow_wildcards_init_for_packet(struct flow_wildcards *,
|
||||
const struct flow *);
|
||||
|
||||
void flow_wildcards_clear_non_packet_fields(struct flow_wildcards *);
|
||||
|
||||
bool flow_wildcards_is_catchall(const struct flow_wildcards *);
|
||||
|
||||
void flow_wildcards_set_reg_mask(struct flow_wildcards *,
|
||||
int idx, uint32_t mask);
|
||||
void flow_wildcards_set_xreg_mask(struct flow_wildcards *,
|
||||
int idx, uint64_t mask);
|
||||
void flow_wildcards_set_xxreg_mask(struct flow_wildcards *,
|
||||
int idx, ovs_u128 mask);
|
||||
|
||||
void flow_wildcards_and(struct flow_wildcards *dst,
|
||||
const struct flow_wildcards *src1,
|
||||
const struct flow_wildcards *src2);
|
||||
void flow_wildcards_or(struct flow_wildcards *dst,
|
||||
const struct flow_wildcards *src1,
|
||||
const struct flow_wildcards *src2);
|
||||
bool flow_wildcards_has_extra(const struct flow_wildcards *,
|
||||
const struct flow_wildcards *);
|
||||
uint32_t flow_wildcards_hash(const struct flow_wildcards *, uint32_t basis);
|
||||
bool flow_wildcards_equal(const struct flow_wildcards *,
|
||||
const struct flow_wildcards *);
|
||||
|
||||
#endif /* flow.h */
|
||||
63
openflow/include/openvswitch/geneve.h
Normal file
63
openflow/include/openvswitch/geneve.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 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 OPENVSWITCH_GENEVE_H
|
||||
#define OPENVSWITCH_GENEVE_H 1
|
||||
|
||||
#include "openvswitch/types.h"
|
||||
|
||||
#define TLV_MAX_OPT_SIZE 124
|
||||
#define TLV_TOT_OPT_SIZE 252
|
||||
|
||||
#define GENEVE_CRIT_OPT_TYPE (1 << 7)
|
||||
|
||||
struct geneve_opt {
|
||||
ovs_be16 opt_class;
|
||||
uint8_t type;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
uint8_t r1:1;
|
||||
uint8_t r2:1;
|
||||
uint8_t r3:1;
|
||||
uint8_t length:5;
|
||||
#else
|
||||
uint8_t length:5;
|
||||
uint8_t r3:1;
|
||||
uint8_t r2:1;
|
||||
uint8_t r1:1;
|
||||
#endif
|
||||
/* Option data */
|
||||
};
|
||||
|
||||
struct genevehdr {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
uint8_t ver:2;
|
||||
uint8_t opt_len:6;
|
||||
uint8_t oam:1;
|
||||
uint8_t critical:1;
|
||||
uint8_t rsvd1:6;
|
||||
#else
|
||||
uint8_t opt_len:6;
|
||||
uint8_t ver:2;
|
||||
uint8_t rsvd1:6;
|
||||
uint8_t critical:1;
|
||||
uint8_t oam:1;
|
||||
#endif
|
||||
ovs_be16 proto_type;
|
||||
ovs_16aligned_be32 vni;
|
||||
struct geneve_opt options[];
|
||||
};
|
||||
|
||||
#endif /* geneve.h */
|
||||
407
openflow/include/openvswitch/hmap.h
Normal file
407
openflow/include/openvswitch/hmap.h
Normal file
@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016 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 "openvswitch/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 'N' nodes
|
||||
* linked together starting at 'NODE'. The hmap only has a single chain of
|
||||
* hmap_nodes, so 'N' should be small. */
|
||||
#define HMAP_CONST(HMAP, N, NODE) { \
|
||||
CONST_CAST(struct hmap_node **, &(HMAP)->one), NODE, 0, N }
|
||||
|
||||
/* 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.
|
||||
*
|
||||
* The *_INIT variants of these macros additionally evaluate the expressions
|
||||
* supplied following the HMAP argument once during the loop initialization.
|
||||
* This makes it possible for data structures that wrap around hmaps to insert
|
||||
* additional initialization into their iteration macros without having to
|
||||
* completely rewrite them. In particular, it can be a good idea to insert
|
||||
* BUILD_ASSERT_TYPE checks for map and node types that wrap hmap, since
|
||||
* otherwise it is possible for clients to accidentally confuse two derived
|
||||
* data structures that happen to use the same member names for struct hmap and
|
||||
* struct hmap_node. */
|
||||
|
||||
/* Iterates through every node in HMAP. */
|
||||
#define HMAP_FOR_EACH(NODE, MEMBER, HMAP) \
|
||||
HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, (void) 0)
|
||||
#define HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, ...) \
|
||||
for (INIT_CONTAINER(NODE, hmap_first(HMAP), MEMBER), __VA_ARGS__; \
|
||||
(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) \
|
||||
HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, (void) 0)
|
||||
#define HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, ...) \
|
||||
for (INIT_CONTAINER(NODE, hmap_first(HMAP), MEMBER), __VA_ARGS__; \
|
||||
((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) \
|
||||
HMAP_FOR_EACH_CONTINUE_INIT(NODE, MEMBER, HMAP, (void) 0)
|
||||
#define HMAP_FOR_EACH_CONTINUE_INIT(NODE, MEMBER, HMAP, ...) \
|
||||
for (ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER), \
|
||||
__VA_ARGS__; \
|
||||
(NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \
|
||||
ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER))
|
||||
|
||||
static inline struct hmap_node *
|
||||
hmap_pop_helper__(struct hmap *hmap, size_t *bucket) {
|
||||
|
||||
for (; *bucket <= hmap->mask; (*bucket)++) {
|
||||
struct hmap_node *node = hmap->buckets[*bucket];
|
||||
|
||||
if (node) {
|
||||
hmap_remove(hmap, node);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define HMAP_FOR_EACH_POP(NODE, MEMBER, HMAP) \
|
||||
for (size_t bucket__ = 0; \
|
||||
INIT_CONTAINER(NODE, hmap_pop_helper__(HMAP, &bucket__), MEMBER), \
|
||||
(NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL);)
|
||||
|
||||
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_position {
|
||||
unsigned int bucket;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
struct hmap_node *hmap_at_position(const struct hmap *,
|
||||
struct hmap_position *);
|
||||
|
||||
/* 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 */
|
||||
143
openflow/include/openvswitch/json.h
Normal file
143
openflow/include/openvswitch/json.h
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include "openvswitch/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;
|
||||
size_t count;
|
||||
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_deep_clone(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 */
|
||||
304
openflow/include/openvswitch/list.h
Normal file
304
openflow/include/openvswitch/list.h
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2013, 2015, 2016 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 OPENVSWITCH_LIST_H
|
||||
#define OPENVSWITCH_LIST_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <openvswitch/types.h>
|
||||
#include <openvswitch/util.h>
|
||||
|
||||
/* Doubly linked list head or element. */
|
||||
struct ovs_list {
|
||||
struct ovs_list *prev; /* Previous list element. */
|
||||
struct ovs_list *next; /* Next list element. */
|
||||
};
|
||||
|
||||
#define OVS_LIST_INITIALIZER(LIST) { LIST, LIST }
|
||||
|
||||
/* "struct ovs_list" with pointers that will (probably) cause segfaults if
|
||||
* dereferenced and, better yet, show up clearly in a debugger.
|
||||
|
||||
* MSVC2015 doesn't support designated initializers when compiling C++,
|
||||
* and doesn't support ternary operators with non-designated initializers.
|
||||
* So we use these static definitions rather than using initializer macros. */
|
||||
static const struct ovs_list OVS_LIST_POISON =
|
||||
{ (struct ovs_list *) (UINTPTR_MAX / 0xf * 0xc),
|
||||
(struct ovs_list *) (UINTPTR_MAX / 0xf * 0xc) };
|
||||
|
||||
static inline void ovs_list_init(struct ovs_list *);
|
||||
static inline void ovs_list_poison(struct ovs_list *);
|
||||
|
||||
/* List insertion. */
|
||||
static inline void ovs_list_insert(struct ovs_list *, struct ovs_list *);
|
||||
static inline void ovs_list_splice(struct ovs_list *before, struct ovs_list *first,
|
||||
struct ovs_list *last);
|
||||
static inline void ovs_list_push_front(struct ovs_list *, struct ovs_list *);
|
||||
static inline void ovs_list_push_back(struct ovs_list *, struct ovs_list *);
|
||||
static inline void ovs_list_replace(struct ovs_list *, const struct ovs_list *);
|
||||
static inline void ovs_list_moved(struct ovs_list *, const struct ovs_list *orig);
|
||||
static inline void ovs_list_move(struct ovs_list *dst, struct ovs_list *src);
|
||||
|
||||
/* List removal. */
|
||||
static inline struct ovs_list *ovs_list_remove(struct ovs_list *);
|
||||
static inline struct ovs_list *ovs_list_pop_front(struct ovs_list *);
|
||||
static inline struct ovs_list *ovs_list_pop_back(struct ovs_list *);
|
||||
|
||||
/* List elements. */
|
||||
static inline struct ovs_list *ovs_list_front(const struct ovs_list *);
|
||||
static inline struct ovs_list *ovs_list_back(const struct ovs_list *);
|
||||
|
||||
/* List properties. */
|
||||
static inline size_t ovs_list_size(const struct ovs_list *);
|
||||
static inline bool ovs_list_is_empty(const struct ovs_list *);
|
||||
static inline bool ovs_list_is_singleton(const struct ovs_list *);
|
||||
static inline bool ovs_list_is_short(const struct ovs_list *);
|
||||
|
||||
#define LIST_FOR_EACH(ITER, MEMBER, LIST) \
|
||||
for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER); \
|
||||
&(ITER)->MEMBER != (LIST); \
|
||||
ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER))
|
||||
#define LIST_FOR_EACH_CONTINUE(ITER, MEMBER, LIST) \
|
||||
for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER); \
|
||||
&(ITER)->MEMBER != (LIST); \
|
||||
ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER))
|
||||
#define LIST_FOR_EACH_REVERSE(ITER, MEMBER, LIST) \
|
||||
for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER); \
|
||||
&(ITER)->MEMBER != (LIST); \
|
||||
ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
|
||||
#define LIST_FOR_EACH_REVERSE_SAFE(ITER, PREV, MEMBER, LIST) \
|
||||
for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER); \
|
||||
(&(ITER)->MEMBER != (LIST) \
|
||||
? INIT_CONTAINER(PREV, (ITER)->MEMBER.prev, MEMBER), 1 \
|
||||
: 0); \
|
||||
(ITER) = (PREV))
|
||||
#define LIST_FOR_EACH_REVERSE_CONTINUE(ITER, MEMBER, LIST) \
|
||||
for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER); \
|
||||
&(ITER)->MEMBER != (LIST); \
|
||||
ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
|
||||
#define LIST_FOR_EACH_SAFE(ITER, NEXT, MEMBER, LIST) \
|
||||
for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER); \
|
||||
(&(ITER)->MEMBER != (LIST) \
|
||||
? INIT_CONTAINER(NEXT, (ITER)->MEMBER.next, MEMBER), 1 \
|
||||
: 0); \
|
||||
(ITER) = (NEXT))
|
||||
#define LIST_FOR_EACH_POP(ITER, MEMBER, LIST) \
|
||||
while (!ovs_list_is_empty(LIST) \
|
||||
&& (INIT_CONTAINER(ITER, ovs_list_pop_front(LIST), MEMBER), 1))
|
||||
|
||||
/* Inline implementations. */
|
||||
|
||||
/* Initializes 'list' as an empty list. */
|
||||
static inline void
|
||||
ovs_list_init(struct ovs_list *list)
|
||||
{
|
||||
list->next = list->prev = list;
|
||||
}
|
||||
|
||||
/* Initializes 'list' with pointers that will (probably) cause segfaults if
|
||||
* dereferenced and, better yet, show up clearly in a debugger. */
|
||||
static inline void
|
||||
ovs_list_poison(struct ovs_list *list)
|
||||
{
|
||||
*list = OVS_LIST_POISON;
|
||||
}
|
||||
|
||||
/* Inserts 'elem' just before 'before'. */
|
||||
static inline void
|
||||
ovs_list_insert(struct ovs_list *before, struct ovs_list *elem)
|
||||
{
|
||||
elem->prev = before->prev;
|
||||
elem->next = before;
|
||||
before->prev->next = elem;
|
||||
before->prev = elem;
|
||||
}
|
||||
|
||||
/* Removes elements 'first' though 'last' (exclusive) from their current list,
|
||||
then inserts them just before 'before'. */
|
||||
static inline void
|
||||
ovs_list_splice(struct ovs_list *before, struct ovs_list *first, struct ovs_list *last)
|
||||
{
|
||||
if (first == last) {
|
||||
return;
|
||||
}
|
||||
last = last->prev;
|
||||
|
||||
/* Cleanly remove 'first'...'last' from its current list. */
|
||||
first->prev->next = last->next;
|
||||
last->next->prev = first->prev;
|
||||
|
||||
/* Splice 'first'...'last' into new list. */
|
||||
first->prev = before->prev;
|
||||
last->next = before;
|
||||
before->prev->next = first;
|
||||
before->prev = last;
|
||||
}
|
||||
|
||||
/* Inserts 'elem' at the beginning of 'list', so that it becomes the front in
|
||||
'list'. */
|
||||
static inline void
|
||||
ovs_list_push_front(struct ovs_list *list, struct ovs_list *elem)
|
||||
{
|
||||
ovs_list_insert(list->next, elem);
|
||||
}
|
||||
|
||||
/* Inserts 'elem' at the end of 'list', so that it becomes the back in
|
||||
* 'list'. */
|
||||
static inline void
|
||||
ovs_list_push_back(struct ovs_list *list, struct ovs_list *elem)
|
||||
{
|
||||
ovs_list_insert(list, elem);
|
||||
}
|
||||
|
||||
/* Puts 'elem' in the position currently occupied by 'position'.
|
||||
* Afterward, 'position' is not part of a list. */
|
||||
static inline void
|
||||
ovs_list_replace(struct ovs_list *element, const struct ovs_list *position)
|
||||
{
|
||||
element->next = position->next;
|
||||
element->next->prev = element;
|
||||
element->prev = position->prev;
|
||||
element->prev->next = element;
|
||||
}
|
||||
|
||||
/* Adjusts pointers around 'list' to compensate for 'list' having been moved
|
||||
* around in memory (e.g. as a consequence of realloc()), with original
|
||||
* location 'orig'.
|
||||
*
|
||||
* ('orig' likely points to freed memory, but this function does not
|
||||
* dereference 'orig', it only compares it to 'list'. In a very pedantic
|
||||
* language lawyer sense, this still yields undefined behavior, but it works
|
||||
* with actual compilers.) */
|
||||
static inline void
|
||||
ovs_list_moved(struct ovs_list *list, const struct ovs_list *orig)
|
||||
{
|
||||
if (list->next == orig) {
|
||||
ovs_list_init(list);
|
||||
} else {
|
||||
list->prev->next = list->next->prev = list;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes 'dst' with the contents of 'src', compensating for moving it
|
||||
* around in memory. The effect is that, if 'src' was the head of a list, now
|
||||
* 'dst' is the head of a list containing the same elements. */
|
||||
static inline void
|
||||
ovs_list_move(struct ovs_list *dst, struct ovs_list *src)
|
||||
{
|
||||
*dst = *src;
|
||||
ovs_list_moved(dst, src);
|
||||
}
|
||||
|
||||
/* Removes 'elem' from its list and returns the element that followed it.
|
||||
Undefined behavior if 'elem' is not in a list. */
|
||||
static inline struct ovs_list *
|
||||
ovs_list_remove(struct ovs_list *elem)
|
||||
{
|
||||
elem->prev->next = elem->next;
|
||||
elem->next->prev = elem->prev;
|
||||
return elem->next;
|
||||
}
|
||||
|
||||
/* Removes the front element from 'list' and returns it. Undefined behavior if
|
||||
'list' is empty before removal. */
|
||||
static inline struct ovs_list *
|
||||
ovs_list_pop_front(struct ovs_list *list)
|
||||
{
|
||||
struct ovs_list *front = list->next;
|
||||
|
||||
ovs_list_remove(front);
|
||||
return front;
|
||||
}
|
||||
|
||||
/* Removes the back element from 'list' and returns it.
|
||||
Undefined behavior if 'list' is empty before removal. */
|
||||
static inline struct ovs_list *
|
||||
ovs_list_pop_back(struct ovs_list *list)
|
||||
{
|
||||
struct ovs_list *back = list->prev;
|
||||
|
||||
ovs_list_remove(back);
|
||||
return back;
|
||||
}
|
||||
|
||||
/* Returns the front element in 'list_'.
|
||||
Undefined behavior if 'list_' is empty. */
|
||||
static inline struct ovs_list *
|
||||
ovs_list_front(const struct ovs_list *list_)
|
||||
{
|
||||
struct ovs_list *list = CONST_CAST(struct ovs_list *, list_);
|
||||
|
||||
ovs_assert(!ovs_list_is_empty(list));
|
||||
|
||||
return list->next;
|
||||
}
|
||||
|
||||
/* Returns the back element in 'list_'.
|
||||
Undefined behavior if 'list_' is empty. */
|
||||
static inline struct ovs_list *
|
||||
ovs_list_back(const struct ovs_list *list_)
|
||||
{
|
||||
struct ovs_list *list = CONST_CAST(struct ovs_list *, list_);
|
||||
|
||||
ovs_assert(!ovs_list_is_empty(list));
|
||||
|
||||
return list->prev;
|
||||
}
|
||||
|
||||
/* Returns the number of elements in 'list'.
|
||||
Runs in O(n) in the number of elements. */
|
||||
static inline size_t
|
||||
ovs_list_size(const struct ovs_list *list)
|
||||
{
|
||||
const struct ovs_list *e;
|
||||
size_t cnt = 0;
|
||||
|
||||
for (e = list->next; e != list; e = e->next) {
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Returns true if 'list' is empty, false otherwise. */
|
||||
static inline bool
|
||||
ovs_list_is_empty(const struct ovs_list *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
||||
|
||||
/* Returns true if 'list' has exactly 1 element, false otherwise. */
|
||||
static inline bool
|
||||
ovs_list_is_singleton(const struct ovs_list *list)
|
||||
{
|
||||
return ovs_list_is_short(list) && !ovs_list_is_empty(list);
|
||||
}
|
||||
|
||||
/* Returns true if 'list' has 0 or 1 elements, false otherwise. */
|
||||
static inline bool
|
||||
ovs_list_is_short(const struct ovs_list *list)
|
||||
{
|
||||
return list->next == list->prev;
|
||||
}
|
||||
|
||||
/* Transplant a list into another, and resets the origin list */
|
||||
static inline void
|
||||
ovs_list_push_back_all(struct ovs_list *dst, struct ovs_list *src)
|
||||
{
|
||||
ovs_list_splice(dst, src->next, src);
|
||||
}
|
||||
|
||||
#endif /* list.h */
|
||||
218
openflow/include/openvswitch/match.h
Normal file
218
openflow/include/openvswitch/match.h
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 OPENVSWITCH_MATCH_H
|
||||
#define OPENVSWITCH_MATCH_H 1
|
||||
|
||||
#include "openvswitch/flow.h"
|
||||
#include "openvswitch/packets.h"
|
||||
#include "openvswitch/tun-metadata.h"
|
||||
|
||||
struct ds;
|
||||
|
||||
/* A flow classification match.
|
||||
*
|
||||
* Use one of the match_*() functions to initialize a "struct match".
|
||||
*
|
||||
* The match_*() functions below maintain the following important invariant.
|
||||
* If a bit or a field is wildcarded in 'wc', then the corresponding bit or
|
||||
* field in 'flow' is set to all-0-bits. (The match_zero_wildcarded_fields()
|
||||
* function can be used to restore this invariant after adding wildcards.) */
|
||||
struct match {
|
||||
struct flow flow;
|
||||
struct flow_wildcards wc;
|
||||
struct tun_metadata_allocation tun_md;
|
||||
};
|
||||
|
||||
/* Initializer for a "struct match" that matches every packet. */
|
||||
#define MATCH_CATCHALL_INITIALIZER { .flow = { .dl_type = 0 } }
|
||||
|
||||
void match_init(struct match *,
|
||||
const struct flow *, const struct flow_wildcards *);
|
||||
void match_wc_init(struct match *match, const struct flow *flow);
|
||||
void match_init_catchall(struct match *);
|
||||
|
||||
void match_zero_wildcarded_fields(struct match *);
|
||||
|
||||
void match_set_dp_hash(struct match *, uint32_t value);
|
||||
void match_set_dp_hash_masked(struct match *, uint32_t value, uint32_t mask);
|
||||
|
||||
void match_set_recirc_id(struct match *, uint32_t value);
|
||||
|
||||
void match_set_conj_id(struct match *, uint32_t value);
|
||||
|
||||
void match_set_reg(struct match *, unsigned int reg_idx, uint32_t value);
|
||||
void match_set_reg_masked(struct match *, unsigned int reg_idx,
|
||||
uint32_t value, uint32_t mask);
|
||||
void match_set_xreg(struct match *, unsigned int xreg_idx, uint64_t value);
|
||||
void match_set_xreg_masked(struct match *, unsigned int xreg_idx,
|
||||
uint64_t value, uint64_t mask);
|
||||
void match_set_xxreg(struct match *, unsigned int xxreg_idx, ovs_u128 value);
|
||||
void match_set_xxreg_masked(struct match *, unsigned int xxreg_idx,
|
||||
ovs_u128 value, ovs_u128 mask);
|
||||
void match_set_actset_output(struct match *, ofp_port_t actset_output);
|
||||
void match_set_metadata(struct match *, ovs_be64 metadata);
|
||||
void match_set_metadata_masked(struct match *,
|
||||
ovs_be64 metadata, ovs_be64 mask);
|
||||
void match_set_tun_id(struct match *, ovs_be64 tun_id);
|
||||
void match_set_tun_id_masked(struct match *, ovs_be64 tun_id, ovs_be64 mask);
|
||||
void match_set_tun_src(struct match *match, ovs_be32 src);
|
||||
void match_set_tun_src_masked(struct match *match, ovs_be32 src, ovs_be32 mask);
|
||||
void match_set_tun_dst(struct match *match, ovs_be32 dst);
|
||||
void match_set_tun_dst_masked(struct match *match, ovs_be32 dst, ovs_be32 mask);
|
||||
void match_set_tun_ipv6_src(struct match *, const struct in6_addr *);
|
||||
void match_set_tun_ipv6_src_masked(struct match *, const struct in6_addr *,
|
||||
const struct in6_addr *);
|
||||
void match_set_tun_ipv6_dst(struct match *, const struct in6_addr *);
|
||||
void match_set_tun_ipv6_dst_masked(struct match *, const struct in6_addr *,
|
||||
const struct in6_addr *);
|
||||
void match_set_tun_ttl(struct match *match, uint8_t ttl);
|
||||
void match_set_tun_ttl_masked(struct match *match, uint8_t ttl, uint8_t mask);
|
||||
void match_set_tun_tos(struct match *match, uint8_t tos);
|
||||
void match_set_tun_tos_masked(struct match *match, uint8_t tos, uint8_t mask);
|
||||
void match_set_tun_flags(struct match *match, uint16_t flags);
|
||||
void match_set_tun_flags_masked(struct match *match, uint16_t flags, uint16_t mask);
|
||||
void match_set_tun_gbp_id_masked(struct match *match, ovs_be16 gbp_id, ovs_be16 mask);
|
||||
void match_set_tun_gbp_id(struct match *match, ovs_be16 gbp_id);
|
||||
void match_set_tun_gbp_flags_masked(struct match *match, uint8_t flags, uint8_t mask);
|
||||
void match_set_tun_gbp_flags(struct match *match, uint8_t flags);
|
||||
void match_set_in_port(struct match *, ofp_port_t ofp_port);
|
||||
void match_set_pkt_mark(struct match *, uint32_t pkt_mark);
|
||||
void match_set_pkt_mark_masked(struct match *, uint32_t pkt_mark, uint32_t mask);
|
||||
void match_set_ct_state(struct match *, uint32_t ct_state);
|
||||
void match_set_ct_state_masked(struct match *, uint32_t ct_state, uint32_t mask);
|
||||
void match_set_ct_zone(struct match *, uint16_t ct_zone);
|
||||
void match_set_ct_mark(struct match *, uint32_t ct_mark);
|
||||
void match_set_ct_mark_masked(struct match *, uint32_t ct_mark, uint32_t mask);
|
||||
void match_set_ct_label(struct match *, ovs_u128 ct_label);
|
||||
void match_set_ct_label_masked(struct match *, ovs_u128 ct_label, ovs_u128 mask);
|
||||
void match_set_skb_priority(struct match *, uint32_t skb_priority);
|
||||
void match_set_dl_type(struct match *, ovs_be16);
|
||||
void match_set_dl_src(struct match *, const struct eth_addr );
|
||||
void match_set_dl_src_masked(struct match *, const struct eth_addr dl_src,
|
||||
const struct eth_addr mask);
|
||||
void match_set_dl_dst(struct match *, const struct eth_addr);
|
||||
void match_set_dl_dst_masked(struct match *, const struct eth_addr dl_dst,
|
||||
const struct eth_addr mask);
|
||||
void match_set_dl_tci(struct match *, ovs_be16 tci);
|
||||
void match_set_dl_tci_masked(struct match *, ovs_be16 tci, ovs_be16 mask);
|
||||
void match_set_any_vid(struct match *);
|
||||
void match_set_dl_vlan(struct match *, ovs_be16);
|
||||
void match_set_vlan_vid(struct match *, ovs_be16);
|
||||
void match_set_vlan_vid_masked(struct match *, ovs_be16 vid, ovs_be16 mask);
|
||||
void match_set_any_pcp(struct match *);
|
||||
void match_set_dl_vlan_pcp(struct match *, uint8_t);
|
||||
void match_set_any_mpls_lse(struct match *, int idx);
|
||||
void match_set_mpls_lse(struct match *, int idx, ovs_be32);
|
||||
void match_set_any_mpls_label(struct match *, int idx);
|
||||
void match_set_mpls_label(struct match *, int idx, ovs_be32);
|
||||
void match_set_any_mpls_tc(struct match *, int idx);
|
||||
void match_set_mpls_tc(struct match *, int idx, uint8_t);
|
||||
void match_set_any_mpls_bos(struct match *, int idx);
|
||||
void match_set_mpls_bos(struct match *, int idx, uint8_t);
|
||||
void match_set_any_mpls_ttl(struct match *, int idx);
|
||||
void match_set_mpls_ttl(struct match *, int idx, uint8_t);
|
||||
void match_set_tp_src(struct match *, ovs_be16);
|
||||
void match_set_mpls_lse(struct match *, int idx, ovs_be32 lse);
|
||||
void match_set_tp_src_masked(struct match *, ovs_be16 port, ovs_be16 mask);
|
||||
void match_set_tp_dst(struct match *, ovs_be16);
|
||||
void match_set_tp_dst_masked(struct match *, ovs_be16 port, ovs_be16 mask);
|
||||
void match_set_tcp_flags(struct match *, ovs_be16);
|
||||
void match_set_tcp_flags_masked(struct match *, ovs_be16 flags, ovs_be16 mask);
|
||||
void match_set_nw_proto(struct match *, uint8_t);
|
||||
void match_set_nw_src(struct match *, ovs_be32);
|
||||
void match_set_nw_src_masked(struct match *, ovs_be32 ip, ovs_be32 mask);
|
||||
void match_set_nw_dst(struct match *, ovs_be32);
|
||||
void match_set_nw_dst_masked(struct match *, ovs_be32 ip, ovs_be32 mask);
|
||||
void match_set_nw_dscp(struct match *, uint8_t);
|
||||
void match_set_nw_ecn(struct match *, uint8_t);
|
||||
void match_set_nw_ttl(struct match *, uint8_t);
|
||||
void match_set_nw_frag(struct match *, uint8_t nw_frag);
|
||||
void match_set_nw_frag_masked(struct match *, uint8_t nw_frag, uint8_t mask);
|
||||
void match_set_icmp_type(struct match *, uint8_t);
|
||||
void match_set_icmp_code(struct match *, uint8_t);
|
||||
void match_set_arp_sha(struct match *, const struct eth_addr);
|
||||
void match_set_arp_sha_masked(struct match *,
|
||||
const struct eth_addr arp_sha,
|
||||
const struct eth_addr mask);
|
||||
void match_set_arp_tha(struct match *, const struct eth_addr);
|
||||
void match_set_arp_tha_masked(struct match *,
|
||||
const struct eth_addr arp_tha,
|
||||
const struct eth_addr mask);
|
||||
void match_set_ipv6_src(struct match *, const struct in6_addr *);
|
||||
void match_set_ipv6_src_masked(struct match *, const struct in6_addr *,
|
||||
const struct in6_addr *);
|
||||
void match_set_ipv6_dst(struct match *, const struct in6_addr *);
|
||||
void match_set_ipv6_dst_masked(struct match *, const struct in6_addr *,
|
||||
const struct in6_addr *);
|
||||
void match_set_ipv6_label(struct match *, ovs_be32);
|
||||
void match_set_ipv6_label_masked(struct match *, ovs_be32, ovs_be32);
|
||||
void match_set_nd_target(struct match *, const struct in6_addr *);
|
||||
void match_set_nd_target_masked(struct match *, const struct in6_addr *,
|
||||
const struct in6_addr *);
|
||||
|
||||
bool match_equal(const struct match *, const struct match *);
|
||||
uint32_t match_hash(const struct match *, uint32_t basis);
|
||||
|
||||
void match_init_hidden_fields(struct match *);
|
||||
bool match_has_default_hidden_fields(const struct match *);
|
||||
|
||||
void match_format(const struct match *, struct ds *, int priority);
|
||||
char *match_to_string(const struct match *, int priority);
|
||||
void match_print(const struct match *);
|
||||
|
||||
/* Compressed match. */
|
||||
|
||||
/* A sparse representation of a "struct match".
|
||||
*
|
||||
* 'flows' is used for allocating both 'flow' and 'mask' with one
|
||||
* miniflow_alloc() call.
|
||||
*
|
||||
* There are two invariants:
|
||||
*
|
||||
* - The same invariant as "struct match", that is, a 1-bit in the 'flow'
|
||||
* must correspond to a 1-bit in 'mask'.
|
||||
*
|
||||
* - 'flow' and 'mask' have the same 'map'. This implies that 'flow' and
|
||||
* 'mask' have the same part of "struct flow" at the same offset into
|
||||
* 'values', which makes minimatch_matches_flow() faster.
|
||||
*/
|
||||
struct minimatch {
|
||||
union {
|
||||
struct {
|
||||
struct miniflow *flow;
|
||||
struct minimask *mask;
|
||||
};
|
||||
struct miniflow *flows[2];
|
||||
};
|
||||
};
|
||||
|
||||
void minimatch_init(struct minimatch *, const struct match *);
|
||||
void minimatch_clone(struct minimatch *, const struct minimatch *);
|
||||
void minimatch_move(struct minimatch *dst, struct minimatch *src);
|
||||
void minimatch_destroy(struct minimatch *);
|
||||
|
||||
void minimatch_expand(const struct minimatch *, struct match *);
|
||||
|
||||
bool minimatch_equal(const struct minimatch *a, const struct minimatch *b);
|
||||
|
||||
bool minimatch_matches_flow(const struct minimatch *, const struct flow *);
|
||||
|
||||
void minimatch_format(const struct minimatch *, const struct tun_table *,
|
||||
struct ds *, int priority);
|
||||
char *minimatch_to_string(const struct minimatch *, int priority);
|
||||
|
||||
#endif /* match.h */
|
||||
1977
openflow/include/openvswitch/meta-flow.h
Normal file
1977
openflow/include/openvswitch/meta-flow.h
Normal file
File diff suppressed because it is too large
Load Diff
114
openflow/include/openvswitch/netdev.h
Normal file
114
openflow/include/openvswitch/netdev.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 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 OPENVSWITCH_NETDEV_H
|
||||
#define OPENVSWITCH_NETDEV_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct netdev;
|
||||
|
||||
/* Network device statistics.
|
||||
*
|
||||
* Values of unsupported statistics are set to all-1-bits (UINT64_MAX). */
|
||||
struct netdev_stats {
|
||||
uint64_t rx_packets; /* Total packets received. */
|
||||
uint64_t tx_packets; /* Total packets transmitted. */
|
||||
uint64_t rx_bytes; /* Total bytes received. */
|
||||
uint64_t tx_bytes; /* Total bytes transmitted. */
|
||||
uint64_t rx_errors; /* Bad packets received. */
|
||||
uint64_t tx_errors; /* Packet transmit problems. */
|
||||
uint64_t rx_dropped; /* No buffer space. */
|
||||
uint64_t tx_dropped; /* No buffer space. */
|
||||
uint64_t multicast; /* Multicast packets received. */
|
||||
uint64_t collisions;
|
||||
|
||||
/* Detailed receive errors. */
|
||||
uint64_t rx_length_errors;
|
||||
uint64_t rx_over_errors; /* Receiver ring buff overflow. */
|
||||
uint64_t rx_crc_errors; /* Recved pkt with crc error. */
|
||||
uint64_t rx_frame_errors; /* Recv'd frame alignment error. */
|
||||
uint64_t rx_fifo_errors; /* Recv'r fifo overrun . */
|
||||
uint64_t rx_missed_errors; /* Receiver missed packet. */
|
||||
|
||||
/* Detailed transmit errors. */
|
||||
uint64_t tx_aborted_errors;
|
||||
uint64_t tx_carrier_errors;
|
||||
uint64_t tx_fifo_errors;
|
||||
uint64_t tx_heartbeat_errors;
|
||||
uint64_t tx_window_errors;
|
||||
|
||||
/* Extended statistics based on RFC2819. */
|
||||
uint64_t rx_1_to_64_packets;
|
||||
uint64_t rx_65_to_127_packets;
|
||||
uint64_t rx_128_to_255_packets;
|
||||
uint64_t rx_256_to_511_packets;
|
||||
uint64_t rx_512_to_1023_packets;
|
||||
uint64_t rx_1024_to_1522_packets;
|
||||
uint64_t rx_1523_to_max_packets;
|
||||
|
||||
uint64_t tx_1_to_64_packets;
|
||||
uint64_t tx_65_to_127_packets;
|
||||
uint64_t tx_128_to_255_packets;
|
||||
uint64_t tx_256_to_511_packets;
|
||||
uint64_t tx_512_to_1023_packets;
|
||||
uint64_t tx_1024_to_1522_packets;
|
||||
uint64_t tx_1523_to_max_packets;
|
||||
|
||||
uint64_t tx_multicast_packets;
|
||||
|
||||
uint64_t rx_broadcast_packets;
|
||||
uint64_t tx_broadcast_packets;
|
||||
|
||||
uint64_t rx_undersized_errors;
|
||||
uint64_t rx_oversize_errors;
|
||||
uint64_t rx_fragmented_errors;
|
||||
uint64_t rx_jabber_errors;
|
||||
};
|
||||
|
||||
/* Features. */
|
||||
enum netdev_features {
|
||||
NETDEV_F_10MB_HD = 1 << 0, /* 10 Mb half-duplex rate support. */
|
||||
NETDEV_F_10MB_FD = 1 << 1, /* 10 Mb full-duplex rate support. */
|
||||
NETDEV_F_100MB_HD = 1 << 2, /* 100 Mb half-duplex rate support. */
|
||||
NETDEV_F_100MB_FD = 1 << 3, /* 100 Mb full-duplex rate support. */
|
||||
NETDEV_F_1GB_HD = 1 << 4, /* 1 Gb half-duplex rate support. */
|
||||
NETDEV_F_1GB_FD = 1 << 5, /* 1 Gb full-duplex rate support. */
|
||||
NETDEV_F_10GB_FD = 1 << 6, /* 10 Gb full-duplex rate support. */
|
||||
NETDEV_F_40GB_FD = 1 << 7, /* 40 Gb full-duplex rate support. */
|
||||
NETDEV_F_100GB_FD = 1 << 8, /* 100 Gb full-duplex rate support. */
|
||||
NETDEV_F_1TB_FD = 1 << 9, /* 1 Tb full-duplex rate support. */
|
||||
NETDEV_F_OTHER = 1 << 10, /* Other rate, not in the list. */
|
||||
NETDEV_F_COPPER = 1 << 11, /* Copper medium. */
|
||||
NETDEV_F_FIBER = 1 << 12, /* Fiber medium. */
|
||||
NETDEV_F_AUTONEG = 1 << 13, /* Auto-negotiation. */
|
||||
NETDEV_F_PAUSE = 1 << 14, /* Pause. */
|
||||
NETDEV_F_PAUSE_ASYM = 1 << 15, /* Asymmetric pause. */
|
||||
};
|
||||
|
||||
int netdev_get_features(const struct netdev *,
|
||||
enum netdev_features *current,
|
||||
enum netdev_features *advertised,
|
||||
enum netdev_features *supported,
|
||||
enum netdev_features *peer);
|
||||
uint64_t netdev_features_to_bps(enum netdev_features features,
|
||||
uint64_t default_bps);
|
||||
bool netdev_features_is_full_duplex(enum netdev_features features);
|
||||
int netdev_set_advertisements(struct netdev *, enum netdev_features advertise);
|
||||
|
||||
#endif /* netdev.h */
|
||||
1160
openflow/include/openvswitch/ofp-actions.h
Normal file
1160
openflow/include/openvswitch/ofp-actions.h
Normal file
File diff suppressed because it is too large
Load Diff
819
openflow/include/openvswitch/ofp-errors.h
Normal file
819
openflow/include/openvswitch/ofp-errors.h
Normal file
@ -0,0 +1,819 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2017 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 OPENVSWITCH_OFP_ERRORS_H
|
||||
#define OPENVSWITCH_OFP_ERRORS_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "openflow/openflow.h"
|
||||
|
||||
struct ds;
|
||||
struct ofpbuf;
|
||||
|
||||
/* Error codes.
|
||||
*
|
||||
* We embed system errno values and OpenFlow standard and vendor extension
|
||||
* error codes into the positive range of "int":
|
||||
*
|
||||
* - Errno values are assumed to use the range 1 through 2**30 - 1.
|
||||
*
|
||||
* (C and POSIX say that errno values are positive. We assume that they
|
||||
* are less than 2**29. They are actually less than 65536 on at least
|
||||
* Linux, FreeBSD, OpenBSD, and Windows.)
|
||||
*
|
||||
* - OpenFlow standard and vendor extension error codes use the range
|
||||
* starting at 2**30 (OFPERR_OFS).
|
||||
*
|
||||
* Zero and negative values are not used.
|
||||
*/
|
||||
|
||||
#define OFPERR_OFS (1 << 30)
|
||||
|
||||
/* OpenFlow error codes
|
||||
* --------------------
|
||||
*
|
||||
* The comments below are parsed by the extract-ofp-errors program at build
|
||||
* time and used to determine the mapping between "enum ofperr" constants and
|
||||
* error type/code values used in the OpenFlow protocol:
|
||||
*
|
||||
* - The first part of each comment specifies the vendor, OpenFlow versions,
|
||||
* type, and sometimes a code for each protocol that supports the error:
|
||||
*
|
||||
* # The vendor is OF for standard OpenFlow error codes. Otherwise it
|
||||
* is one of the *_VENDOR_ID codes defined in openflow-common.h.
|
||||
*
|
||||
* # The version can specify a specific OpenFlow version, a version
|
||||
* range delimited by "-", or an open-ended range with "+".
|
||||
*
|
||||
* # Standard OpenFlow errors have both a type and a code. Extension
|
||||
* errors generally have only a type, no code. There is one
|
||||
* exception: Nicira extension (NX) errors for OpenFlow 1.0 and 1.1
|
||||
* have both a type and a code. (This means that the version
|
||||
* specification for NX errors may not include version 1.0 or 1.1 (or
|
||||
* both) along with version 1.2 or later, because the requirements
|
||||
* for those versions are different.)
|
||||
*
|
||||
* - Additional text is a human-readable description of the meaning of each
|
||||
* error, used to explain the error to the user. Any text enclosed in
|
||||
* square brackets is omitted; this can be used to explain rationale for
|
||||
* choice of error codes in the case where this is desirable.
|
||||
*
|
||||
*
|
||||
* Expected duplications
|
||||
* ---------------------
|
||||
*
|
||||
* Occasionally, in one version of OpenFlow a single named error can indicate
|
||||
* two or more distinct errors, then a later version of OpenFlow splits those
|
||||
* meanings into different error codes. When that happens, both errors are
|
||||
* assigned the same value in the earlier version. That is ordinarily a
|
||||
* mistake, so the build system reports an error. When that happens, add the
|
||||
* error message to the list of "Expected duplications" below to suppress the
|
||||
* error. In such a case, the named error defined earlier is how OVS
|
||||
* interprets the earlier, merged form of the error.
|
||||
*
|
||||
* For example, OpenFlow 1.1 defined (3,5) as OFPBIC_UNSUP_EXP_INST, then
|
||||
* OpenFlow 1.2 broke this error into OFPBIC_BAD_EXPERIMENTER as (3,5) and
|
||||
* OFPBIC_BAD_EXT_TYPE as (3,6). To allow the OVS code to report just a single
|
||||
* error code, instead of protocol version dependent errors, this list of
|
||||
* errors only lists the latter two errors, giving both of them the same code
|
||||
* (3,5) for OpenFlow 1.1. Then, when OVS serializes either error into
|
||||
* OpenFlow 1.1, it uses the same code (3,5). In the other direction, when OVS
|
||||
* deserializes (3,5) from OpenFlow 1.1, it translates it into
|
||||
* OFPBIC_BAD_EXPERIMENTER (because its definition precedes that of
|
||||
* OFPBIC_BAD_EXT_TYPE below). See the "encoding OFPBIC_* experimenter errors"
|
||||
* and "decoding OFPBIC_* experimenter errors" tests in tests/ofp-errors.at for
|
||||
* full details.
|
||||
*/
|
||||
enum ofperr {
|
||||
/* Expected duplications. */
|
||||
|
||||
/* Expected: 0x0,3,5 in OF1.1 means both OFPBIC_BAD_EXPERIMENTER and
|
||||
* OFPBIC_BAD_EXP_TYPE. */
|
||||
|
||||
/* Expected: 0x0,1,5 in OF1.0 means both OFPBRC_EPERM and
|
||||
* OFPBRC_IS_SLAVE. */
|
||||
|
||||
/* Expected: 0x0,1,5 in OF1.1 means both OFPBRC_EPERM and
|
||||
* OFPBRC_IS_SLAVE. */
|
||||
|
||||
/* ## ------------------ ## */
|
||||
/* ## OFPET_HELLO_FAILED ## */
|
||||
/* ## ------------------ ## */
|
||||
|
||||
/* OF1.0+(0,0). No compatible version. */
|
||||
OFPERR_OFPHFC_INCOMPATIBLE = OFPERR_OFS,
|
||||
|
||||
/* OF1.0+(0,1). Permissions error. */
|
||||
OFPERR_OFPHFC_EPERM,
|
||||
|
||||
/* ## ----------------- ## */
|
||||
/* ## OFPET_BAD_REQUEST ## */
|
||||
/* ## ----------------- ## */
|
||||
|
||||
/* OF1.0+(1,0). ofp_header.version not supported. */
|
||||
OFPERR_OFPBRC_BAD_VERSION,
|
||||
|
||||
/* OF1.0+(1,1). ofp_header.type not supported. */
|
||||
OFPERR_OFPBRC_BAD_TYPE,
|
||||
|
||||
/* OF1.0+(1,2). ofp_stats_msg.type not supported. */
|
||||
OFPERR_OFPBRC_BAD_STAT,
|
||||
|
||||
/* OF1.0+(1,3). Vendor not supported (in ofp_vendor_header or
|
||||
* ofp_stats_msg). */
|
||||
OFPERR_OFPBRC_BAD_VENDOR,
|
||||
|
||||
/* OF1.0+(1,4). Vendor subtype not supported. */
|
||||
OFPERR_OFPBRC_BAD_SUBTYPE,
|
||||
|
||||
/* OF1.0+(1,5). Permissions error. */
|
||||
OFPERR_OFPBRC_EPERM,
|
||||
|
||||
/* OF1.0+(1,6). Wrong request length for type. */
|
||||
OFPERR_OFPBRC_BAD_LEN,
|
||||
|
||||
/* OF1.0+(1,7). Specified buffer has already been used. */
|
||||
OFPERR_OFPBRC_BUFFER_EMPTY,
|
||||
|
||||
/* OF1.0+(1,8). Specified buffer does not exist. */
|
||||
OFPERR_OFPBRC_BUFFER_UNKNOWN,
|
||||
|
||||
/* NX1.0(1,512), OF1.1+(1,9). Specified table-id invalid or does not exist.
|
||||
* [ A non-standard error (1,512), formerly OFPERR_NXBRC_BAD_TABLE_ID,
|
||||
* is used for OpenFlow 1.0 as there seems to be no appropriate error
|
||||
* code defined the specification. ] */
|
||||
OFPERR_OFPBRC_BAD_TABLE_ID,
|
||||
|
||||
/* OF1.0-1.1(1,5), OF1.2+(1,10). Denied because controller is slave. */
|
||||
OFPERR_OFPBRC_IS_SLAVE,
|
||||
|
||||
/* NX1.0-1.1(1,514), OF1.2+(1,11). Invalid port. [ A non-standard error
|
||||
* (1,514), formerly OFPERR_NXBRC_BAD_IN_PORT is used for OpenFlow 1.0 and
|
||||
* 1.1 as there seems to be no appropriate error code defined the
|
||||
* specifications. ] */
|
||||
OFPERR_OFPBRC_BAD_PORT,
|
||||
|
||||
/* OF1.2+(1,12). Invalid packet in packet-out. */
|
||||
OFPERR_OFPBRC_BAD_PACKET,
|
||||
|
||||
/* OF1.3+(1,13). Multipart request overflowed the assigned buffer. */
|
||||
OFPERR_OFPBRC_MULTIPART_BUFFER_OVERFLOW,
|
||||
|
||||
/* NX1.0-1.1(1,256), NX1.2+(2). Invalid NXM flow match. */
|
||||
OFPERR_NXBRC_NXM_INVALID,
|
||||
|
||||
/* NX1.0-1.1(1,257), NX1.2+(3). The nxm_type, or nxm_type taken in
|
||||
* combination with nxm_hasmask or nxm_length or both, is invalid or not
|
||||
* implemented. */
|
||||
OFPERR_NXBRC_NXM_BAD_TYPE,
|
||||
|
||||
/* NX1.0-1.1(1,515), NX1.2+(4). Must-be-zero field had nonzero value. */
|
||||
OFPERR_NXBRC_MUST_BE_ZERO,
|
||||
|
||||
/* NX1.0-1.1(1,516), NX1.2+(5). The reason in an ofp_port_status message
|
||||
* is not valid. */
|
||||
OFPERR_NXBRC_BAD_REASON,
|
||||
|
||||
/* NX1.0-1.1(1,520), NX1.2+(9). The 'event' in an NXST_FLOW_MONITOR reply
|
||||
* does not specify one of the NXFME_ABBREV, NXFME_ADD, NXFME_DELETE, or
|
||||
* NXFME_MODIFY. */
|
||||
OFPERR_NXBRC_FM_BAD_EVENT,
|
||||
|
||||
/* NX1.0-1.1(1,521), NX1.2+(10). The error that occurred cannot be
|
||||
* represented in this OpenFlow version. */
|
||||
OFPERR_NXBRC_UNENCODABLE_ERROR,
|
||||
|
||||
/* ## ---------------- ## */
|
||||
/* ## OFPET_BAD_ACTION ## */
|
||||
/* ## ---------------- ## */
|
||||
|
||||
/* OF1.0+(2,0). Unknown action type. */
|
||||
OFPERR_OFPBAC_BAD_TYPE,
|
||||
|
||||
/* OF1.0+(2,1). Length problem in actions. */
|
||||
OFPERR_OFPBAC_BAD_LEN,
|
||||
|
||||
/* OF1.0+(2,2). Unknown experimenter id specified. */
|
||||
OFPERR_OFPBAC_BAD_VENDOR,
|
||||
|
||||
/* OF1.0+(2,3). Unknown action type for experimenter id. */
|
||||
OFPERR_OFPBAC_BAD_VENDOR_TYPE,
|
||||
|
||||
/* OF1.0+(2,4). Problem validating output port. */
|
||||
OFPERR_OFPBAC_BAD_OUT_PORT,
|
||||
|
||||
/* OF1.0+(2,5). Bad action argument. */
|
||||
OFPERR_OFPBAC_BAD_ARGUMENT,
|
||||
|
||||
/* OF1.0+(2,6). Permissions error. */
|
||||
OFPERR_OFPBAC_EPERM,
|
||||
|
||||
/* OF1.0+(2,7). Can't handle this many actions. */
|
||||
OFPERR_OFPBAC_TOO_MANY,
|
||||
|
||||
/* OF1.0+(2,8). Problem validating output queue. */
|
||||
OFPERR_OFPBAC_BAD_QUEUE,
|
||||
|
||||
/* OF1.1+(2,9). Invalid group id in forward action. */
|
||||
OFPERR_OFPBAC_BAD_OUT_GROUP,
|
||||
|
||||
/* NX1.0(1,522), OF1.1+(2,10). Action can't apply for this match or a
|
||||
* prerequisite for use of this field is unmet. */
|
||||
OFPERR_OFPBAC_MATCH_INCONSISTENT,
|
||||
|
||||
/* OF1.1+(2,11). Action order is unsupported for the action list in an
|
||||
* Apply-Actions instruction */
|
||||
OFPERR_OFPBAC_UNSUPPORTED_ORDER,
|
||||
|
||||
/* OF1.1+(2,12). Actions uses an unsupported tag/encap. */
|
||||
OFPERR_OFPBAC_BAD_TAG,
|
||||
|
||||
/* NX1.0-1.1(1,523), OF1.2+(2,13). Action uses unknown or unsupported OXM
|
||||
* or NXM field. */
|
||||
OFPERR_OFPBAC_BAD_SET_TYPE,
|
||||
|
||||
/* NX1.0-1.1(1,524), OF1.2+(2,14). Action references past the end of an
|
||||
* OXM or NXM field, or uses a length of zero. */
|
||||
OFPERR_OFPBAC_BAD_SET_LEN,
|
||||
|
||||
/* NX1.0-1.1(1,525), OF1.2+(2,15). Action sets a field to an invalid or
|
||||
* unsupported value, or modifies a read-only field. */
|
||||
OFPERR_OFPBAC_BAD_SET_ARGUMENT,
|
||||
|
||||
/* ONF1.3-1.4(4250), OF1.5+(2,16). Field in Set-Field action has Has-Mask
|
||||
* bit set to 1. */
|
||||
OFPERR_OFPBAC_BAD_SET_MASK,
|
||||
|
||||
/* NX1.0-1.1(2,256), NX1.2+(11). Must-be-zero action argument had nonzero
|
||||
* value. */
|
||||
OFPERR_NXBAC_MUST_BE_ZERO,
|
||||
|
||||
/* NX1.0-1.1(2,526), NX1.2+(15). Conjunction action must be only action
|
||||
* present. conjunction(id, k/n) must satisfy 1 <= k <= n and 2 <= n <=
|
||||
* 64. */
|
||||
OFPERR_NXBAC_BAD_CONJUNCTION,
|
||||
|
||||
/* ## --------------------- ## */
|
||||
/* ## OFPET_BAD_INSTRUCTION ## */
|
||||
/* ## --------------------- ## */
|
||||
|
||||
/* OF1.1+(3,0). Unknown instruction. */
|
||||
OFPERR_OFPBIC_UNKNOWN_INST,
|
||||
|
||||
/* NX1.0(2,257), OF1.1+(3,1). Switch or table does not support the
|
||||
* instruction. */
|
||||
OFPERR_OFPBIC_UNSUP_INST,
|
||||
|
||||
/* OF1.1+(3,2). Invalid Table-ID specified. */
|
||||
OFPERR_OFPBIC_BAD_TABLE_ID,
|
||||
|
||||
/* OF1.1+(3,3). Metadata value unsupported by datapath. */
|
||||
OFPERR_OFPBIC_UNSUP_METADATA,
|
||||
|
||||
/* OF1.1+(3,4). Metadata mask value unsupported by datapath. */
|
||||
OFPERR_OFPBIC_UNSUP_METADATA_MASK,
|
||||
|
||||
/* OF1.1+(3,5). Unknown experimenter id specified. */
|
||||
OFPERR_OFPBIC_BAD_EXPERIMENTER,
|
||||
|
||||
/* OF1.1(3,5), OF1.2+(3,6). Unknown instruction for experimenter id. */
|
||||
OFPERR_OFPBIC_BAD_EXP_TYPE,
|
||||
|
||||
/* OF1.2+(3,7). Length problem in instructions. */
|
||||
OFPERR_OFPBIC_BAD_LEN,
|
||||
|
||||
/* OF1.2+(3,8). Permissions error. */
|
||||
OFPERR_OFPBIC_EPERM,
|
||||
|
||||
/* NX1.1(3,256), ONF1.2-1.3(2600), OF1.4+(3,9). Duplicate instruction. */
|
||||
OFPERR_OFPBIC_DUP_INST,
|
||||
|
||||
/* ## --------------- ## */
|
||||
/* ## OFPET_BAD_MATCH ## */
|
||||
/* ## --------------- ## */
|
||||
|
||||
/* OF1.1+(4,0). Unsupported match type specified by the match */
|
||||
OFPERR_OFPBMC_BAD_TYPE,
|
||||
|
||||
/* OF1.1+(4,1). Length problem in match. */
|
||||
OFPERR_OFPBMC_BAD_LEN,
|
||||
|
||||
/* OF1.1+(4,2). Match uses an unsupported tag/encap. */
|
||||
OFPERR_OFPBMC_BAD_TAG,
|
||||
|
||||
/* OF1.1+(4,3). Unsupported datalink addr mask - switch does not support
|
||||
* arbitrary datalink address mask. */
|
||||
OFPERR_OFPBMC_BAD_DL_ADDR_MASK,
|
||||
|
||||
/* OF1.1+(4,4). Unsupported network addr mask - switch does not support
|
||||
* arbitrary network address mask. */
|
||||
OFPERR_OFPBMC_BAD_NW_ADDR_MASK,
|
||||
|
||||
/* NX1.0(1,262), OF1.1+(4,5). Unsupported wildcard specified in the
|
||||
* match. */
|
||||
OFPERR_OFPBMC_BAD_WILDCARDS,
|
||||
|
||||
/* NX1.0(0,263), OF1.1+(4,6). Unsupported field in the match. */
|
||||
OFPERR_OFPBMC_BAD_FIELD,
|
||||
|
||||
/* NX1.0(1,258), OF1.1+(4,7). Unsupported value in a match
|
||||
* field. */
|
||||
OFPERR_OFPBMC_BAD_VALUE,
|
||||
|
||||
/* NX1.0-1.1(1,259), OF1.2+(4,8). Unsupported mask specified in the match,
|
||||
* field is not dl-address or nw-address. */
|
||||
OFPERR_OFPBMC_BAD_MASK,
|
||||
|
||||
/* NX1.0-1.1(1,260), OF1.2+(4,9). A prerequisite was not met. */
|
||||
OFPERR_OFPBMC_BAD_PREREQ,
|
||||
|
||||
/* NX1.0-1.1(1,261), OF1.2+(4,10). A field type was duplicated. */
|
||||
OFPERR_OFPBMC_DUP_FIELD,
|
||||
|
||||
/* OF1.2+(4,11). Permissions error. */
|
||||
OFPERR_OFPBMC_EPERM,
|
||||
|
||||
/* ## --------------------- ## */
|
||||
/* ## OFPET_FLOW_MOD_FAILED ## */
|
||||
/* ## --------------------- ## */
|
||||
|
||||
/* OF1.1+(5,0). Unspecified error. */
|
||||
OFPERR_OFPFMFC_UNKNOWN,
|
||||
|
||||
/* OF1.0(3,0), OF1.1+(5,1). Flow not added because of full table(s). */
|
||||
OFPERR_OFPFMFC_TABLE_FULL,
|
||||
|
||||
/* OF1.1+(5,2). Table does not exist */
|
||||
OFPERR_OFPFMFC_BAD_TABLE_ID,
|
||||
|
||||
/* OF1.0(3,1), OF1.1+(5,3). Attempted to add overlapping flow with
|
||||
* CHECK_OVERLAP flag set. */
|
||||
OFPERR_OFPFMFC_OVERLAP,
|
||||
|
||||
/* OF1.0(3,2), OF1.1+(5,4). Permissions error. */
|
||||
OFPERR_OFPFMFC_EPERM,
|
||||
|
||||
/* OF1.1+(5,5). Flow not added because of unsupported idle/hard
|
||||
* timeout. */
|
||||
OFPERR_OFPFMFC_BAD_TIMEOUT,
|
||||
|
||||
/* OF1.0(3,3). Flow not added because of non-zero idle/hard timeout. */
|
||||
OFPERR_OFPFMFC_BAD_EMERG_TIMEOUT,
|
||||
|
||||
/* OF1.0(3,4), OF1.1+(5,6). Unsupported or unknown command. */
|
||||
OFPERR_OFPFMFC_BAD_COMMAND,
|
||||
|
||||
/* NX1.0(3,258), NX1.1(5,258), OF1.2+(5,7). Unsupported or unknown
|
||||
* flags. */
|
||||
OFPERR_OFPFMFC_BAD_FLAGS,
|
||||
|
||||
/* OF1.0(3,5). Unsupported action list - cannot process in the order
|
||||
* specified. */
|
||||
OFPERR_OFPFMFC_UNSUPPORTED,
|
||||
|
||||
/* NX1.0-1.1(5,256), NX1.2+(12). Generic hardware error. */
|
||||
OFPERR_NXFMFC_HARDWARE,
|
||||
|
||||
/* NX1.0-1.1(5,257), NX1.2+(13). A nonexistent table ID was specified in
|
||||
* the "command" field of struct ofp_flow_mod, when the
|
||||
* nxt_flow_mod_table_id extension is enabled. */
|
||||
OFPERR_NXFMFC_BAD_TABLE_ID,
|
||||
|
||||
/* NX1.0-1.1(1,536), NX1.2+(37). Attempted to add a flow with an invalid
|
||||
* variable length meta-flow field. */
|
||||
OFPERR_NXFMFC_INVALID_TLV_FIELD,
|
||||
|
||||
/* ## ---------------------- ## */
|
||||
/* ## OFPET_GROUP_MOD_FAILED ## */
|
||||
/* ## ---------------------- ## */
|
||||
|
||||
/* OF1.1+(6,0). Group not added because a group ADD attempted to replace
|
||||
* an already-present group. */
|
||||
OFPERR_OFPGMFC_GROUP_EXISTS,
|
||||
|
||||
/* OF1.1+(6,1). Group not added because Group specified is invalid. */
|
||||
OFPERR_OFPGMFC_INVALID_GROUP,
|
||||
|
||||
/* OF1.1+(6,2). Switch does not support unequal load sharing with select
|
||||
* groups. */
|
||||
OFPERR_OFPGMFC_WEIGHT_UNSUPPORTED,
|
||||
|
||||
/* OF1.1+(6,3). The group table is full. */
|
||||
OFPERR_OFPGMFC_OUT_OF_GROUPS,
|
||||
|
||||
/* OF1.1+(6,4). The maximum number of action buckets for a group has been
|
||||
* exceeded. */
|
||||
OFPERR_OFPGMFC_OUT_OF_BUCKETS,
|
||||
|
||||
/* OF1.1+(6,5). Switch does not support groups that forward to groups. */
|
||||
OFPERR_OFPGMFC_CHAINING_UNSUPPORTED,
|
||||
|
||||
/* OF1.1+(6,6). This group cannot watch the watch_port or watch_group
|
||||
* specified. */
|
||||
OFPERR_OFPGMFC_WATCH_UNSUPPORTED,
|
||||
|
||||
/* OF1.1+(6,7). Group entry would cause a loop. */
|
||||
OFPERR_OFPGMFC_LOOP,
|
||||
|
||||
/* OF1.1+(6,8). Group not modified because a group MODIFY attempted to
|
||||
* modify a non-existent group. */
|
||||
OFPERR_OFPGMFC_UNKNOWN_GROUP,
|
||||
|
||||
/* OF1.2+(6,9). Group not deleted because another
|
||||
group is forwarding to it. */
|
||||
OFPERR_OFPGMFC_CHAINED_GROUP,
|
||||
|
||||
/* OF1.2+(6,10). Unsupported or unknown group type. */
|
||||
OFPERR_OFPGMFC_BAD_TYPE,
|
||||
|
||||
/* OF1.2+(6,11). Unsupported or unknown command. */
|
||||
OFPERR_OFPGMFC_BAD_COMMAND,
|
||||
|
||||
/* OF1.2+(6,12). Error in bucket. */
|
||||
OFPERR_OFPGMFC_BAD_BUCKET,
|
||||
|
||||
/* OF1.2+(6,13). Error in watch port/group. */
|
||||
OFPERR_OFPGMFC_BAD_WATCH,
|
||||
|
||||
/* OF1.2+(6,14). Permissions error. */
|
||||
OFPERR_OFPGMFC_EPERM,
|
||||
|
||||
/* OF1.5+(6,15). Invalid bucket identifier used in
|
||||
* INSERT BUCKET or REMOVE BUCKET command. */
|
||||
OFPERR_OFPGMFC_UNKNOWN_BUCKET,
|
||||
|
||||
/* OF1.5+(6,16). Can't insert bucket because a bucket
|
||||
* already exist with that bucket-id. */
|
||||
OFPERR_OFPGMFC_BUCKET_EXISTS,
|
||||
|
||||
/* ## --------------------- ## */
|
||||
/* ## OFPET_PORT_MOD_FAILED ## */
|
||||
/* ## --------------------- ## */
|
||||
|
||||
/* OF1.0(4,0), OF1.1+(7,0). Specified port does not exist. */
|
||||
OFPERR_OFPPMFC_BAD_PORT,
|
||||
|
||||
/* OF1.0(4,1), OF1.1+(7,1). Specified hardware address does not match the
|
||||
* port number. */
|
||||
OFPERR_OFPPMFC_BAD_HW_ADDR,
|
||||
|
||||
/* OF1.1+(7,2). Specified config is invalid. */
|
||||
OFPERR_OFPPMFC_BAD_CONFIG,
|
||||
|
||||
/* OF1.1+(7,3). Specified advertise is invalid. */
|
||||
OFPERR_OFPPMFC_BAD_ADVERTISE,
|
||||
|
||||
/* OF1.2+(7,4). Permissions error. */
|
||||
OFPERR_OFPPMFC_EPERM,
|
||||
|
||||
/* ## ---------------------- ## */
|
||||
/* ## OFPET_TABLE_MOD_FAILED ## */
|
||||
/* ## ---------------------- ## */
|
||||
|
||||
/* OF1.1+(8,0). Specified table does not exist. */
|
||||
OFPERR_OFPTMFC_BAD_TABLE,
|
||||
|
||||
/* OF1.1+(8,1). Specified config is invalid. */
|
||||
OFPERR_OFPTMFC_BAD_CONFIG,
|
||||
|
||||
/* OF1.2+(8,2). Permissions error. */
|
||||
OFPERR_OFPTMFC_EPERM,
|
||||
|
||||
/* ## --------------------- ## */
|
||||
/* ## OFPET_QUEUE_OP_FAILED ## */
|
||||
/* ## --------------------- ## */
|
||||
|
||||
/* OF1.0(5,0), OF1.1+(9,0). Invalid port (or port does not exist). */
|
||||
OFPERR_OFPQOFC_BAD_PORT,
|
||||
|
||||
/* OF1.0(5,1), OF1.1+(9,1). Queue does not exist. */
|
||||
OFPERR_OFPQOFC_BAD_QUEUE,
|
||||
|
||||
/* OF1.0(5,2), OF1.1+(9,2). Permissions error. */
|
||||
OFPERR_OFPQOFC_EPERM,
|
||||
|
||||
/* NX1.4+(23). System error retrieving queue details. */
|
||||
OFPERR_NXQOFC_QUEUE_ERROR,
|
||||
|
||||
/* ## -------------------------- ## */
|
||||
/* ## OFPET_SWITCH_CONFIG_FAILED ## */
|
||||
/* ## -------------------------- ## */
|
||||
|
||||
/* OF1.1+(10,0). Specified flags is invalid. */
|
||||
OFPERR_OFPSCFC_BAD_FLAGS,
|
||||
|
||||
/* OF1.1+(10,1). Specified len is invalid. */
|
||||
OFPERR_OFPSCFC_BAD_LEN,
|
||||
|
||||
/* OF1.2+(10,2). Permissions error. */
|
||||
OFPERR_OFPSCFC_EPERM,
|
||||
|
||||
/* ## ------------------------- ## */
|
||||
/* ## OFPET_ROLE_REQUEST_FAILED ## */
|
||||
/* ## ------------------------- ## */
|
||||
|
||||
/* OF1.2+(11,0). Stale Message: old generation_id. */
|
||||
OFPERR_OFPRRFC_STALE,
|
||||
|
||||
/* OF1.2+(11,1). Controller role change unsupported. */
|
||||
OFPERR_OFPRRFC_UNSUP,
|
||||
|
||||
/* NX1.0-1.1(1,513), OF1.2+(11,2). Invalid role. */
|
||||
OFPERR_OFPRRFC_BAD_ROLE,
|
||||
|
||||
/* ## ---------------------- ## */
|
||||
/* ## OFPET_METER_MOD_FAILED ## */
|
||||
/* ## ---------------------- ## */
|
||||
|
||||
/* OF1.3+(12,0). Unspecified error. */
|
||||
OFPERR_OFPMMFC_UNKNOWN,
|
||||
|
||||
/* OF1.3+(12,1). Meter not added because a Meter ADD attempted to
|
||||
* replace an existing Meter. */
|
||||
OFPERR_OFPMMFC_METER_EXISTS,
|
||||
|
||||
/* OF1.3+(12,2). Meter not added because Meter specified is invalid. */
|
||||
OFPERR_OFPMMFC_INVALID_METER,
|
||||
|
||||
/* OF1.3+(12,3). Meter not modified because a Meter MODIFY attempted
|
||||
* to modify a non-existent Meter. */
|
||||
OFPERR_OFPMMFC_UNKNOWN_METER,
|
||||
|
||||
/* OF1.3+(12,4). Unsupported or unknown command. */
|
||||
OFPERR_OFPMMFC_BAD_COMMAND,
|
||||
|
||||
/* OF1.3+(12,5). Flag configuration unsupported. */
|
||||
OFPERR_OFPMMFC_BAD_FLAGS,
|
||||
|
||||
/* OF1.3+(12,6). Rate unsupported. */
|
||||
OFPERR_OFPMMFC_BAD_RATE,
|
||||
|
||||
/* OF1.3+(12,7). Burst size unsupported. */
|
||||
OFPERR_OFPMMFC_BAD_BURST,
|
||||
|
||||
/* OF1.3+(12,8). Band unsupported. */
|
||||
OFPERR_OFPMMFC_BAD_BAND,
|
||||
|
||||
/* OF1.3+(12,9). Band value unsupported. */
|
||||
OFPERR_OFPMMFC_BAD_BAND_VALUE,
|
||||
|
||||
/* OF1.3+(12,10). No more meters available. */
|
||||
OFPERR_OFPMMFC_OUT_OF_METERS,
|
||||
|
||||
/* OF1.3+(12,11). The maximum number of properties for a meter has
|
||||
* been exceeded. */
|
||||
OFPERR_OFPMMFC_OUT_OF_BANDS,
|
||||
|
||||
/* ## --------------------------- ## */
|
||||
/* ## OFPET_TABLE_FEATURES_FAILED ## */
|
||||
/* ## --------------------------- ## */
|
||||
|
||||
/* OF1.3+(13,0). Specified table does not exist. */
|
||||
OFPERR_OFPTFFC_BAD_TABLE,
|
||||
|
||||
/* OF1.3+(13,1). Invalid metadata mask. */
|
||||
OFPERR_OFPTFFC_BAD_METADATA,
|
||||
|
||||
/* OF1.3+(13,5). Permissions error. */
|
||||
OFPERR_OFPTFFC_EPERM,
|
||||
|
||||
/* ## ------------------ ## */
|
||||
/* ## OFPET_BAD_PROPERTY ## */
|
||||
/* ## ------------------ ## */
|
||||
|
||||
/* NX1.0-1.1(13,2), NX1.2(25), OF1.3(13,2), OF1.4+(14,0). Unknown property
|
||||
* type.
|
||||
*
|
||||
* [Known as OFPTFFC_BAD_TYPE in OF1.3.] */
|
||||
OFPERR_OFPBPC_BAD_TYPE,
|
||||
|
||||
/* NX1.0-1.1(13,3), NX1.2(26), OF1.3(13,3), OF1.4+(14,1). Length problem
|
||||
* in property.
|
||||
*
|
||||
* [Known as OFPTFFC_BAD_LEN in OF1.3.] */
|
||||
OFPERR_OFPBPC_BAD_LEN,
|
||||
|
||||
/* NX1.0-1.1(13,4), NX1.2(27), OF1.3(13,4), OF1.4+(14,2). Unsupported
|
||||
* property value.
|
||||
*
|
||||
* [Known as OFPTFFC_BAD_ARGUMENT in OF1.3.] */
|
||||
OFPERR_OFPBPC_BAD_VALUE,
|
||||
|
||||
/* NX1.0-1.1(14,3), NX1.2(28), ONF1.3(4443), OF1.4+(14,3). Can't handle
|
||||
* this many properties. */
|
||||
OFPERR_OFPBPC_TOO_MANY,
|
||||
|
||||
/* NX1.0-1.1(14,4), NX1.2(29), ONF1.3(4444), OF1.4+(14,4). A property type
|
||||
* was duplicated. */
|
||||
OFPERR_OFPBPC_DUP_TYPE,
|
||||
|
||||
/* NX1.0-1.1(14,5), NX1.2(30), ONF1.3(4445), OF1.4+(14,5). Unknown
|
||||
* experimenter id specified. */
|
||||
OFPERR_OFPBPC_BAD_EXPERIMENTER,
|
||||
|
||||
/* NX1.0-1.1(14,6), NX1.2(31), ONF1.3(4446), OF1.4+(14,6). Unknown
|
||||
* exp_type for experimenter id. */
|
||||
OFPERR_OFPBPC_BAD_EXP_TYPE,
|
||||
|
||||
/* NX1.0-1.1(14,7), NX1.2(32), ONF1.3(4447), OF1.4+(14,7). Unknown value
|
||||
* for experimenter id. */
|
||||
OFPERR_OFPBPC_BAD_EXP_VALUE,
|
||||
|
||||
/* NX1.0-1.1(14,8), NX1.2(33), ONF1.3(4448), OF1.4+(14,8). Permissions
|
||||
* error. */
|
||||
OFPERR_OFPBPC_EPERM,
|
||||
|
||||
/* ## -------------------------- ## */
|
||||
/* ## OFPET_ASYNC_CONFIG_FAILED ## */
|
||||
/* ## -------------------------- ## */
|
||||
|
||||
/* OF1.4+(15,0). One mask is invalid. */
|
||||
OFPERR_OFPACFC_INVALID,
|
||||
|
||||
/* OF1.4+(15,1). Requested configuration not supported. */
|
||||
OFPERR_OFPACFC_UNSUPPORTED,
|
||||
|
||||
/* OF1.4+(15,2). Permissions error. */
|
||||
OFPERR_OFPACFC_EPERM,
|
||||
|
||||
/* ## -------------------- ## */
|
||||
/* ## OFPET_BUNDLE_FAILED ## */
|
||||
/* ## -------------------- ## */
|
||||
|
||||
/* ONF1.3(2300), OF1.4+(17,0). Unspecified error. */
|
||||
OFPERR_OFPBFC_UNKNOWN,
|
||||
|
||||
/* ONF1.3(2301), OF1.4+(17,1). Permissions error. */
|
||||
OFPERR_OFPBFC_EPERM,
|
||||
|
||||
/* ONF1.3(2302), OF1.4+(17,2). Bundle ID doesn't exist. */
|
||||
OFPERR_OFPBFC_BAD_ID,
|
||||
|
||||
/* ONF1.3(2303), OF1.4+(17,3). Bundle ID already exists. */
|
||||
OFPERR_OFPBFC_BUNDLE_EXIST,
|
||||
|
||||
/* ONF1.3(2304), OF1.4+(17,4). Bundle ID is closed. */
|
||||
OFPERR_OFPBFC_BUNDLE_CLOSED,
|
||||
|
||||
/* ONF1.3(2305), OF1.4+(17,5). Too many bundle IDs. */
|
||||
OFPERR_OFPBFC_OUT_OF_BUNDLES,
|
||||
|
||||
/* ONF1.3(2306), OF1.4+(17,6). Unsupported of unknown message control
|
||||
* type. */
|
||||
OFPERR_OFPBFC_BAD_TYPE,
|
||||
|
||||
/* ONF1.3(2307), OF1.4+(17,7). Unsupported, unknown, or inconsistent
|
||||
* flags. */
|
||||
OFPERR_OFPBFC_BAD_FLAGS,
|
||||
|
||||
/* ONF1.3(2308), OF1.4+(17,8). Length problem in included message. */
|
||||
OFPERR_OFPBFC_MSG_BAD_LEN,
|
||||
|
||||
/* ONF1.3(2309), OF1.4+(17,9). Inconsistent or duplicate XID. */
|
||||
OFPERR_OFPBFC_MSG_BAD_XID,
|
||||
|
||||
/* ONF1.3(2310), OF1.4+(17,10). Unsupported message in this bundle. */
|
||||
OFPERR_OFPBFC_MSG_UNSUP,
|
||||
|
||||
/* ONF1.3(2311), OF1.4+(17,11). Unsupported message combination in this
|
||||
* bundle. */
|
||||
OFPERR_OFPBFC_MSG_CONFLICT,
|
||||
|
||||
/* ONF1.3(2312), OF1.4+(17,12). Cant handle this many messages in
|
||||
* bundle. */
|
||||
OFPERR_OFPBFC_MSG_TOO_MANY,
|
||||
|
||||
/* ONF1.3(2313), OF1.4+(17,13). One message in bundle failed. */
|
||||
OFPERR_OFPBFC_MSG_FAILED,
|
||||
|
||||
/* ONF1.3(2314), OF1.4+(17,14). Bundle is taking too long. */
|
||||
OFPERR_OFPBFC_TIMEOUT,
|
||||
|
||||
/* ONF1.3(2315), OF1.4+(17,15). Bundle is locking the resource. */
|
||||
OFPERR_OFPBFC_BUNDLE_IN_PROGRESS,
|
||||
|
||||
/* NX1.4-1.5(22), OF1.6+(17,19). In an OFPT_BUNDLE_ADD_MESSAGE, the
|
||||
* OpenFlow version in the inner and outer messages differ. */
|
||||
OFPERR_OFPBFC_BAD_VERSION,
|
||||
|
||||
/* ## ------------------------- ## */
|
||||
/* ## OFPET_FLOW_MONITOR_FAILED ## */
|
||||
/* ## ------------------------- ## */
|
||||
|
||||
/* OF1.4+(16,0). Unspecified error. */
|
||||
OFPERR_OFPMOFC_UNKNOWN,
|
||||
|
||||
/* NX1.0-1.1(1,517), NX1.2-1.3(6), OF1.4+(16,1). Monitor not added
|
||||
* because a Monitor ADD attempted to replace an existing Monitor. */
|
||||
OFPERR_OFPMOFC_MONITOR_EXISTS,
|
||||
|
||||
/* OF1.4+(16,2). Monitor not added because
|
||||
* Monitor specified is invalid. */
|
||||
OFPERR_OFPMOFC_INVALID_MONITOR,
|
||||
|
||||
/* NX1.0-1.1(1,519), NX1.2-1.3(8), OF1.4+(16,3). Monitor not modified
|
||||
* because a Monitor MODIFY attempted to modify a non-existent Monitor. */
|
||||
OFPERR_OFPMOFC_UNKNOWN_MONITOR,
|
||||
|
||||
/* OF1.4+(16,4). Unsupported or unknown command. */
|
||||
OFPERR_OFPMOFC_BAD_COMMAND,
|
||||
|
||||
/* NX1.0-1.1(1,518), NX1.2-1.3(7), OF1.4+(16,5). Flag configuration
|
||||
* unsupported. */
|
||||
OFPERR_OFPMOFC_BAD_FLAGS,
|
||||
|
||||
/* OF1.4+(16,6). Specified table does not exist. */
|
||||
OFPERR_OFPMOFC_BAD_TABLE_ID,
|
||||
|
||||
/* OF1.4+(16,7). Error in output port/group. */
|
||||
OFPERR_OFPMOFC_BAD_OUT,
|
||||
|
||||
/* ## ----------------------------- ## */
|
||||
/* ## OFPET_TLV_TABLE_MOD_FAILED ## */
|
||||
/* ## ----------------------------- ## */
|
||||
|
||||
/* NX1.0-1.1(1,527), NX1.2+(16). The TLV table mod command is not
|
||||
* recognized as a valid operation. */
|
||||
OFPERR_NXTTMFC_BAD_COMMAND,
|
||||
|
||||
/* NX1.0-1.1(1,528), NX1.2+(17). The option length is not a valid
|
||||
* option size for TLVs. */
|
||||
OFPERR_NXTTMFC_BAD_OPT_LEN,
|
||||
|
||||
/* NX1.0-1.1(1,529), NX1.2+(18). The field index is out of range for
|
||||
* the supported NX_TUN_METADATA<n> match. */
|
||||
OFPERR_NXTTMFC_BAD_FIELD_IDX,
|
||||
|
||||
/* NX1.0-1.1(1,530), NX1.2+(19). The total set of configured options
|
||||
* exceeds the maximum supported by the switch. */
|
||||
OFPERR_NXTTMFC_TABLE_FULL,
|
||||
|
||||
/* NX1.0-1.1(1,531), NX1.2+(20). The controller issued an NXTTMC_ADD
|
||||
* command for a field index that is already mapped. */
|
||||
OFPERR_NXTTMFC_ALREADY_MAPPED,
|
||||
|
||||
/* NX1.0-1.1(1,532), NX1.2+(21). The option TLV that is attempting
|
||||
* to be mapped is the same as one assigned to a different field. */
|
||||
OFPERR_NXTTMFC_DUP_ENTRY,
|
||||
|
||||
/* ## ---------- ## */
|
||||
/* ## NXT_RESUME ## */
|
||||
/* ## ---------- ## */
|
||||
|
||||
/* NX1.0-1.1(1,533), NX1.2+(34). This datapath doesn't support
|
||||
* NXT_RESUME. */
|
||||
OFPERR_NXR_NOT_SUPPORTED,
|
||||
|
||||
/* NX1.0-1.1(1,534), NX1.2+(35). Continuation is stale: Open vSwitch
|
||||
* process has been restarted or bridge has been destroyed since
|
||||
* continuation was generated, or continuation was not generated by this
|
||||
* Open vSwitch instance. */
|
||||
OFPERR_NXR_STALE,
|
||||
|
||||
/* ## ---------- ## */
|
||||
/* ## NXT_STATS ## */
|
||||
/* ## ---------- ## */
|
||||
|
||||
/* NX1.0-1.1(1,535), NX1.2+(36). Protocol is not configured on this
|
||||
* Open vSwitch instance. */
|
||||
OFPERR_NXST_NOT_CONFIGURED,
|
||||
};
|
||||
|
||||
const char *ofperr_domain_get_name(enum ofp_version);
|
||||
|
||||
bool ofperr_is_valid(enum ofperr);
|
||||
|
||||
enum ofperr ofperr_from_name(const char *);
|
||||
|
||||
enum ofperr ofperr_decode_msg(const struct ofp_header *,
|
||||
struct ofpbuf *payload);
|
||||
struct ofpbuf *ofperr_encode_reply(enum ofperr, const struct ofp_header *);
|
||||
struct ofpbuf *ofperr_encode_hello(enum ofperr, enum ofp_version ofp_version,
|
||||
const char *);
|
||||
int ofperr_get_vendor(enum ofperr, enum ofp_version);
|
||||
int ofperr_get_type(enum ofperr, enum ofp_version);
|
||||
int ofperr_get_code(enum ofperr, enum ofp_version);
|
||||
|
||||
const char *ofperr_get_name(enum ofperr);
|
||||
const char *ofperr_get_description(enum ofperr);
|
||||
|
||||
void ofperr_format(struct ds *, enum ofperr);
|
||||
const char *ofperr_to_string(enum ofperr);
|
||||
|
||||
#endif /* ofp-errors.h */
|
||||
771
openflow/include/openvswitch/ofp-msgs.h
Normal file
771
openflow/include/openvswitch/ofp-msgs.h
Normal file
@ -0,0 +1,771 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016 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 OPENVSWITCH_OFP_MSGS_H
|
||||
#define OPENVSWITCH_OFP_MSGS_H 1
|
||||
|
||||
/* OpenFlow message headers abstraction.
|
||||
*
|
||||
* OpenFlow headers are unnecessarily complicated:
|
||||
*
|
||||
* - Some messages with the same meaning were renumbered between 1.0 and 1.1.
|
||||
*
|
||||
* - "Statistics" (aka multipart) messages have a different format from other
|
||||
* messages.
|
||||
*
|
||||
* - The 1.0 header for statistics messages is an odd number of 32-bit words
|
||||
* long, leaving 64-bit quantities in the body misaligned. The 1.1 header
|
||||
* for statistics added a padding word to fix this misalignment, although
|
||||
* many statistic message bodies did not change.
|
||||
*
|
||||
* - Vendor-defined messages have an additional header but no standard way to
|
||||
* distinguish individual types of message within a given vendor.
|
||||
*
|
||||
* This file attempts to abstract out the differences between the various forms
|
||||
* of headers.
|
||||
*/
|
||||
|
||||
#include "openvswitch/ofp-errors.h"
|
||||
#include "openvswitch/types.h"
|
||||
|
||||
struct ovs_list;
|
||||
|
||||
/* Raw identifiers for OpenFlow messages.
|
||||
*
|
||||
* Some OpenFlow messages with similar meanings have multiple variants across
|
||||
* OpenFlow versions or vendor extensions. Each variant has a different
|
||||
* OFPRAW_* enumeration constant. More specifically, if two messages have
|
||||
* different types, different numbers, or different arguments, then they must
|
||||
* have different OFPRAW_* values.
|
||||
*
|
||||
* The comments here must follow a stylized form because the "extract-ofp-msgs"
|
||||
* program parses them at build time to generate data tables. The syntax of
|
||||
* each comment is:
|
||||
*
|
||||
* type versions (number): arguments.
|
||||
*
|
||||
* where the syntax of each part is:
|
||||
*
|
||||
* - type: One of the following:
|
||||
*
|
||||
* * OFPT: standard OpenFlow message.
|
||||
* * OFPST: standard OpenFlow statistics or multipart message.
|
||||
* * NXT: Nicira extension message.
|
||||
* * NXST: Nicira extension statistics or multipart message.
|
||||
* * ONFT: Open Networking Foundation extension message.
|
||||
* * ONFST: Open Networking Foundation multipart message.
|
||||
*
|
||||
* As new vendors implement extensions it will make sense to expand the
|
||||
* dictionary of possible types.
|
||||
*
|
||||
* - versions: The OpenFlow version or versions in which this message is
|
||||
* supported, e.g. "1.0" or "1.1" or "1.0+".
|
||||
*
|
||||
* - number:
|
||||
* For OFPT, the 'type' in struct ofp_header.
|
||||
* For OFPST, the 'type' in struct ofp_stats_msg or ofp11_stats_msg.
|
||||
* For NXT or ONFT, the 'subtype' in struct ofp_vendor_header.
|
||||
* For NXST or ONFST, the 'subtype' in an appropriate vendor stats
|
||||
* struct.
|
||||
*
|
||||
* - arguments: The types of data that follow the OpenFlow headers (the
|
||||
* message "body"). This can be "void" if the message has no body.
|
||||
* Otherwise, it should be a comma-separated sequence of C types. The
|
||||
* last type in the sequence can end with [] if the body ends in a
|
||||
* variable-length sequence.
|
||||
*
|
||||
* The arguments are used to validate the lengths of messages when a
|
||||
* header is parsed. Any message whose length isn't valid as a length of
|
||||
* the specified types will be rejected with OFPERR_OFPBRC_BAD_LEN.
|
||||
*
|
||||
* A few OpenFlow messages, such as OFPT_PACKET_IN, intentionally end with
|
||||
* only part of a structure, up to some specified member. The syntax "up
|
||||
* to <member>" indicates this, e.g. "struct ofp11_packet_in up to data".
|
||||
*/
|
||||
enum ofpraw {
|
||||
/* Immutable standard messages.
|
||||
*
|
||||
* The OpenFlow standard promises to preserve these messages and their numbers
|
||||
* in future versions, so we mark them as <all>, which covers every OpenFlow
|
||||
* version numbered 0x01...0xff, rather than as OF1.0+, which covers only
|
||||
* OpenFlow versions that we otherwise implement.
|
||||
*
|
||||
* Without <all> here, then we would fail to decode "hello" messages that
|
||||
* announce a version higher than we understand, even though there still could
|
||||
* be a version in common with the peer that we do understand. The <all>
|
||||
* keyword is less useful for the other messages, because our OpenFlow channels
|
||||
* accept only OpenFlow messages with a previously negotiated version.
|
||||
*/
|
||||
|
||||
/* OFPT <all> (0): uint8_t[]. */
|
||||
OFPRAW_OFPT_HELLO,
|
||||
|
||||
/* OFPT <all> (1): struct ofp_error_msg, uint8_t[]. */
|
||||
OFPRAW_OFPT_ERROR,
|
||||
|
||||
/* OFPT <all> (2): uint8_t[]. */
|
||||
OFPRAW_OFPT_ECHO_REQUEST,
|
||||
|
||||
/* OFPT <all> (3): uint8_t[]. */
|
||||
OFPRAW_OFPT_ECHO_REPLY,
|
||||
|
||||
/* Other standard messages.
|
||||
*
|
||||
* The meanings of these messages can (and often do) change from one version
|
||||
* of OpenFlow to another. */
|
||||
|
||||
/* OFPT 1.0+ (5): void. */
|
||||
OFPRAW_OFPT_FEATURES_REQUEST,
|
||||
|
||||
/* OFPT 1.0 (6): struct ofp_switch_features, struct ofp10_phy_port[]. */
|
||||
OFPRAW_OFPT10_FEATURES_REPLY,
|
||||
/* OFPT 1.1-1.2 (6): struct ofp_switch_features, struct ofp11_port[]. */
|
||||
OFPRAW_OFPT11_FEATURES_REPLY,
|
||||
/* OFPT 1.3+ (6): struct ofp_switch_features. */
|
||||
OFPRAW_OFPT13_FEATURES_REPLY,
|
||||
|
||||
/* OFPT 1.0+ (7): void. */
|
||||
OFPRAW_OFPT_GET_CONFIG_REQUEST,
|
||||
|
||||
/* OFPT 1.0+ (8): struct ofp_switch_config. */
|
||||
OFPRAW_OFPT_GET_CONFIG_REPLY,
|
||||
|
||||
/* OFPT 1.0+ (9): struct ofp_switch_config. */
|
||||
OFPRAW_OFPT_SET_CONFIG,
|
||||
|
||||
/* OFPT 1.0 (10): struct ofp10_packet_in up to data, uint8_t[]. */
|
||||
OFPRAW_OFPT10_PACKET_IN,
|
||||
/* OFPT 1.1 (10): struct ofp11_packet_in, uint8_t[]. */
|
||||
OFPRAW_OFPT11_PACKET_IN,
|
||||
/* OFPT 1.2 (10): struct ofp12_packet_in, uint8_t[]. */
|
||||
OFPRAW_OFPT12_PACKET_IN,
|
||||
/* OFPT 1.3+ (10): struct ofp12_packet_in, ovs_be64, uint8_t[]. */
|
||||
OFPRAW_OFPT13_PACKET_IN,
|
||||
/* NXT 1.0+ (17): struct nx_packet_in, uint8_t[]. */
|
||||
OFPRAW_NXT_PACKET_IN,
|
||||
/* NXT 1.0+ (30): uint8_t[8][]. */
|
||||
OFPRAW_NXT_PACKET_IN2,
|
||||
|
||||
/* OFPT 1.0 (11): struct ofp10_flow_removed. */
|
||||
OFPRAW_OFPT10_FLOW_REMOVED,
|
||||
/* OFPT 1.1+ (11): struct ofp11_flow_removed, uint8_t[8][]. */
|
||||
OFPRAW_OFPT11_FLOW_REMOVED,
|
||||
/* NXT 1.0+ (14): struct nx_flow_removed, uint8_t[8][]. */
|
||||
OFPRAW_NXT_FLOW_REMOVED,
|
||||
|
||||
/* OFPT 1.0 (12): struct ofp_port_status, struct ofp10_phy_port. */
|
||||
OFPRAW_OFPT10_PORT_STATUS,
|
||||
/* OFPT 1.1-1.3 (12): struct ofp_port_status, struct ofp11_port. */
|
||||
OFPRAW_OFPT11_PORT_STATUS,
|
||||
/* OFPT 1.4+ (12): struct ofp_port_status, struct ofp14_port, uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_PORT_STATUS,
|
||||
|
||||
/* OFPT 1.0 (13): struct ofp10_packet_out, uint8_t[]. */
|
||||
OFPRAW_OFPT10_PACKET_OUT,
|
||||
/* OFPT 1.1+ (13): struct ofp11_packet_out, uint8_t[]. */
|
||||
OFPRAW_OFPT11_PACKET_OUT,
|
||||
|
||||
/* OFPT 1.0 (14): struct ofp10_flow_mod, uint8_t[8][]. */
|
||||
OFPRAW_OFPT10_FLOW_MOD,
|
||||
/* OFPT 1.1+ (14): struct ofp11_flow_mod, struct ofp11_instruction[]. */
|
||||
OFPRAW_OFPT11_FLOW_MOD,
|
||||
/* NXT 1.0+ (13): struct nx_flow_mod, uint8_t[8][]. */
|
||||
OFPRAW_NXT_FLOW_MOD,
|
||||
|
||||
/* OFPT 1.1-1.4 (15): struct ofp11_group_mod, uint8_t[8][]. */
|
||||
OFPRAW_OFPT11_GROUP_MOD,
|
||||
/* OFPT 1.5+ (15): struct ofp15_group_mod, uint8_t[8][]. */
|
||||
OFPRAW_OFPT15_GROUP_MOD,
|
||||
|
||||
/* OFPT 1.0 (15): struct ofp10_port_mod. */
|
||||
OFPRAW_OFPT10_PORT_MOD,
|
||||
/* OFPT 1.1-1.3 (16): struct ofp11_port_mod. */
|
||||
OFPRAW_OFPT11_PORT_MOD,
|
||||
/* OFPT 1.4+ (16): struct ofp14_port_mod, uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_PORT_MOD,
|
||||
|
||||
/* OFPT 1.1-1.3 (17): struct ofp11_table_mod. */
|
||||
OFPRAW_OFPT11_TABLE_MOD,
|
||||
/* OFPT 1.4+ (17): struct ofp14_table_mod, uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_TABLE_MOD,
|
||||
|
||||
/* OFPT 1.0 (18): void. */
|
||||
OFPRAW_OFPT10_BARRIER_REQUEST,
|
||||
/* OFPT 1.1+ (20): void. */
|
||||
OFPRAW_OFPT11_BARRIER_REQUEST,
|
||||
|
||||
/* OFPT 1.0 (19): void. */
|
||||
OFPRAW_OFPT10_BARRIER_REPLY,
|
||||
/* OFPT 1.1+ (21): void. */
|
||||
OFPRAW_OFPT11_BARRIER_REPLY,
|
||||
|
||||
/* OFPT 1.0 (20): struct ofp10_queue_get_config_request. */
|
||||
OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST,
|
||||
/* OFPT 1.1-1.3 (22): struct ofp11_queue_get_config_request. */
|
||||
OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST,
|
||||
|
||||
/* OFPT 1.0 (21): struct ofp10_queue_get_config_reply, uint8_t[8][]. */
|
||||
OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY,
|
||||
/* OFPT 1.1-1.3 (23): struct ofp11_queue_get_config_reply, uint8_t[8][]. */
|
||||
OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY,
|
||||
|
||||
/* OFPT 1.2+ (24): struct ofp12_role_request. */
|
||||
OFPRAW_OFPT12_ROLE_REQUEST,
|
||||
/* NXT 1.0+ (10): struct nx_role_request. */
|
||||
OFPRAW_NXT_ROLE_REQUEST,
|
||||
|
||||
/* OFPT 1.2+ (25): struct ofp12_role_request. */
|
||||
OFPRAW_OFPT12_ROLE_REPLY,
|
||||
/* NXT 1.0+ (11): struct nx_role_request. */
|
||||
OFPRAW_NXT_ROLE_REPLY,
|
||||
|
||||
/* OFPT 1.3 (26): void. */
|
||||
OFPRAW_OFPT13_GET_ASYNC_REQUEST,
|
||||
/* OFPT 1.4+ (26): void. */
|
||||
OFPRAW_OFPT14_GET_ASYNC_REQUEST,
|
||||
/* OFPT 1.3 (27): struct ofp13_async_config. */
|
||||
OFPRAW_OFPT13_GET_ASYNC_REPLY,
|
||||
/* OFPT 1.4+ (27): uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_GET_ASYNC_REPLY,
|
||||
/* OFPT 1.3 (28): struct ofp13_async_config. */
|
||||
OFPRAW_OFPT13_SET_ASYNC,
|
||||
/* NXT 1.0+ (19): struct nx_async_config. */
|
||||
OFPRAW_NXT_SET_ASYNC_CONFIG,
|
||||
/* NXT 1.0-1.3 (27): uint8_t[8][]. */
|
||||
OFPRAW_NXT_SET_ASYNC_CONFIG2,
|
||||
/* OFPT 1.4+ (28): uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_SET_ASYNC,
|
||||
|
||||
/* OFPT 1.3+ (29): struct ofp13_meter_mod, uint8_t[8][]. */
|
||||
OFPRAW_OFPT13_METER_MOD,
|
||||
|
||||
/* OFPT 1.4+ (30): struct ofp14_role_status, uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_ROLE_STATUS,
|
||||
|
||||
/* OFPT 1.4+ (31): struct ofp14_table_status, uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_TABLE_STATUS,
|
||||
|
||||
/* OFPT 1.4+ (32): struct ofp14_requestforward, uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_REQUESTFORWARD,
|
||||
|
||||
/* OFPT 1.4+ (33): struct ofp14_bundle_ctrl_msg, uint8_t[8][]. */
|
||||
OFPRAW_OFPT14_BUNDLE_CONTROL,
|
||||
/* ONFT 1.3 (2300): struct ofp14_bundle_ctrl_msg, uint8_t[8][]. */
|
||||
OFPRAW_ONFT13_BUNDLE_CONTROL,
|
||||
|
||||
/* OFPT 1.4+ (34): struct ofp14_bundle_ctrl_msg, uint8_t[]. */
|
||||
OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE,
|
||||
/* ONFT 1.3 (2301): struct ofp14_bundle_ctrl_msg, uint8_t[]. */
|
||||
OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE,
|
||||
|
||||
/* Standard statistics. */
|
||||
|
||||
/* OFPST 1.0+ (0): void. */
|
||||
OFPRAW_OFPST_DESC_REQUEST,
|
||||
|
||||
/* OFPST 1.0+ (0): struct ofp_desc_stats. */
|
||||
OFPRAW_OFPST_DESC_REPLY,
|
||||
|
||||
/* OFPST 1.0 (1): struct ofp10_flow_stats_request. */
|
||||
OFPRAW_OFPST10_FLOW_REQUEST,
|
||||
/* OFPST 1.1+ (1): struct ofp11_flow_stats_request, uint8_t[8][]. */
|
||||
OFPRAW_OFPST11_FLOW_REQUEST,
|
||||
/* NXST 1.0 (0): struct nx_flow_stats_request, uint8_t[8][]. */
|
||||
OFPRAW_NXST_FLOW_REQUEST,
|
||||
|
||||
/* OFPST 1.0 (1): uint8_t[]. */
|
||||
OFPRAW_OFPST10_FLOW_REPLY,
|
||||
/* OFPST 1.1-1.2 (1): uint8_t[]. */
|
||||
OFPRAW_OFPST11_FLOW_REPLY,
|
||||
/* OFPST 1.3+ (1): uint8_t[]. */
|
||||
OFPRAW_OFPST13_FLOW_REPLY,
|
||||
/* NXST 1.0 (0): uint8_t[]. */
|
||||
OFPRAW_NXST_FLOW_REPLY,
|
||||
|
||||
/* OFPST 1.0 (2): struct ofp10_flow_stats_request. */
|
||||
OFPRAW_OFPST10_AGGREGATE_REQUEST,
|
||||
/* OFPST 1.1+ (2): struct ofp11_flow_stats_request, uint8_t[8][]. */
|
||||
OFPRAW_OFPST11_AGGREGATE_REQUEST,
|
||||
/* NXST 1.0 (1): struct nx_flow_stats_request, uint8_t[8][]. */
|
||||
OFPRAW_NXST_AGGREGATE_REQUEST,
|
||||
|
||||
/* OFPST 1.0+ (2): struct ofp_aggregate_stats_reply. */
|
||||
OFPRAW_OFPST_AGGREGATE_REPLY,
|
||||
/* NXST 1.0 (1): struct ofp_aggregate_stats_reply. */
|
||||
OFPRAW_NXST_AGGREGATE_REPLY,
|
||||
|
||||
/* OFPST 1.0+ (3): void. */
|
||||
OFPRAW_OFPST_TABLE_REQUEST,
|
||||
|
||||
/* OFPST 1.0 (3): struct ofp10_table_stats[]. */
|
||||
OFPRAW_OFPST10_TABLE_REPLY,
|
||||
/* OFPST 1.1 (3): struct ofp11_table_stats[]. */
|
||||
OFPRAW_OFPST11_TABLE_REPLY,
|
||||
/* OFPST 1.2 (3): struct ofp12_table_stats[]. */
|
||||
OFPRAW_OFPST12_TABLE_REPLY,
|
||||
/* OFPST 1.3+ (3): struct ofp13_table_stats[]. */
|
||||
OFPRAW_OFPST13_TABLE_REPLY,
|
||||
|
||||
/* OFPST 1.0 (4): struct ofp10_port_stats_request. */
|
||||
OFPRAW_OFPST10_PORT_REQUEST,
|
||||
/* OFPST 1.1+ (4): struct ofp11_port_stats_request. */
|
||||
OFPRAW_OFPST11_PORT_REQUEST,
|
||||
|
||||
/* OFPST 1.0 (4): struct ofp10_port_stats[]. */
|
||||
OFPRAW_OFPST10_PORT_REPLY,
|
||||
/* OFPST 1.1-1.2 (4): struct ofp11_port_stats[]. */
|
||||
OFPRAW_OFPST11_PORT_REPLY,
|
||||
/* OFPST 1.3 (4): struct ofp13_port_stats[]. */
|
||||
OFPRAW_OFPST13_PORT_REPLY,
|
||||
/* OFPST 1.4+ (4): uint8_t[8][]. */
|
||||
OFPRAW_OFPST14_PORT_REPLY,
|
||||
|
||||
/* OFPST 1.0 (5): struct ofp10_queue_stats_request. */
|
||||
OFPRAW_OFPST10_QUEUE_REQUEST,
|
||||
/* OFPST 1.1+ (5): struct ofp11_queue_stats_request. */
|
||||
OFPRAW_OFPST11_QUEUE_REQUEST,
|
||||
|
||||
/* OFPST 1.0 (5): struct ofp10_queue_stats[]. */
|
||||
OFPRAW_OFPST10_QUEUE_REPLY,
|
||||
/* OFPST 1.1-1.2 (5): struct ofp11_queue_stats[]. */
|
||||
OFPRAW_OFPST11_QUEUE_REPLY,
|
||||
/* OFPST 1.3 (5): struct ofp13_queue_stats[]. */
|
||||
OFPRAW_OFPST13_QUEUE_REPLY,
|
||||
/* OFPST 1.4+ (5): uint8_t[8][]. */
|
||||
OFPRAW_OFPST14_QUEUE_REPLY,
|
||||
|
||||
/* OFPST 1.1+ (6): struct ofp11_group_stats_request. */
|
||||
OFPRAW_OFPST11_GROUP_REQUEST,
|
||||
|
||||
/* OFPST 1.1-1.2 (6): uint8_t[8][]. */
|
||||
OFPRAW_OFPST11_GROUP_REPLY,
|
||||
/* OFPST 1.3+ (6): uint8_t[8][]. */
|
||||
OFPRAW_OFPST13_GROUP_REPLY,
|
||||
|
||||
/* OFPST 1.1-1.4 (7): void. */
|
||||
OFPRAW_OFPST11_GROUP_DESC_REQUEST,
|
||||
/* OFPST 1.5+ (7): struct ofp15_group_desc_request. */
|
||||
OFPRAW_OFPST15_GROUP_DESC_REQUEST,
|
||||
|
||||
/* OFPST 1.1+ (7): uint8_t[8][]. */
|
||||
OFPRAW_OFPST11_GROUP_DESC_REPLY,
|
||||
|
||||
/* OFPST 1.2+ (8): void. */
|
||||
OFPRAW_OFPST12_GROUP_FEATURES_REQUEST,
|
||||
|
||||
/* OFPST 1.2+ (8): struct ofp12_group_features_stats. */
|
||||
OFPRAW_OFPST12_GROUP_FEATURES_REPLY,
|
||||
|
||||
/* OFPST 1.3+ (9): struct ofp13_meter_multipart_request. */
|
||||
OFPRAW_OFPST13_METER_REQUEST,
|
||||
|
||||
/* OFPST 1.3+ (9): uint8_t[8][]. */
|
||||
OFPRAW_OFPST13_METER_REPLY,
|
||||
|
||||
/* OFPST 1.3+ (10): struct ofp13_meter_multipart_request. */
|
||||
OFPRAW_OFPST13_METER_CONFIG_REQUEST,
|
||||
|
||||
/* OFPST 1.3+ (10): uint8_t[8][]. */
|
||||
OFPRAW_OFPST13_METER_CONFIG_REPLY,
|
||||
|
||||
/* OFPST 1.3+ (11): void. */
|
||||
OFPRAW_OFPST13_METER_FEATURES_REQUEST,
|
||||
|
||||
/* OFPST 1.3+ (11): struct ofp13_meter_features. */
|
||||
OFPRAW_OFPST13_METER_FEATURES_REPLY,
|
||||
|
||||
/* OFPST 1.3+ (12): void. */
|
||||
OFPRAW_OFPST13_TABLE_FEATURES_REQUEST,
|
||||
|
||||
/* OFPST 1.3+ (12): struct ofp13_table_features, uint8_t[8][]. */
|
||||
OFPRAW_OFPST13_TABLE_FEATURES_REPLY,
|
||||
|
||||
/* OFPST 1.4+ (14): void. */
|
||||
OFPRAW_OFPST14_TABLE_DESC_REQUEST,
|
||||
|
||||
/* OFPST 1.4+ (14): struct ofp14_table_desc, uint8_t[8][]. */
|
||||
OFPRAW_OFPST14_TABLE_DESC_REPLY,
|
||||
|
||||
/* OFPST 1.0-1.4 (13): void. */
|
||||
OFPRAW_OFPST10_PORT_DESC_REQUEST,
|
||||
/* OFPST 1.5+ (13): struct ofp15_port_desc_request. */
|
||||
OFPRAW_OFPST15_PORT_DESC_REQUEST,
|
||||
|
||||
/* OFPST 1.0 (13): struct ofp10_phy_port[]. */
|
||||
OFPRAW_OFPST10_PORT_DESC_REPLY,
|
||||
/* OFPST 1.1-1.3 (13): struct ofp11_port[]. */
|
||||
OFPRAW_OFPST11_PORT_DESC_REPLY,
|
||||
/* OFPST 1.4+ (13): uint8_t[8][]. */
|
||||
OFPRAW_OFPST14_PORT_DESC_REPLY,
|
||||
|
||||
/* OFPST 1.4+ (15): struct ofp14_queue_desc_request. */
|
||||
OFPRAW_OFPST14_QUEUE_DESC_REQUEST,
|
||||
/* OFPST 1.4+ (15): uint8_t[8][]. */
|
||||
OFPRAW_OFPST14_QUEUE_DESC_REPLY,
|
||||
|
||||
/* OFPST 1.4+ (16): uint8_t[8][]. */
|
||||
OFPRAW_OFPST14_FLOW_MONITOR_REQUEST,
|
||||
/* NXST 1.0 (2): uint8_t[8][]. */
|
||||
OFPRAW_NXST_FLOW_MONITOR_REQUEST,
|
||||
|
||||
/* OFPST 1.4+ (16): uint8_t[8][]. */
|
||||
OFPRAW_OFPST14_FLOW_MONITOR_REPLY,
|
||||
/* NXST 1.0 (2): uint8_t[8][]. */
|
||||
OFPRAW_NXST_FLOW_MONITOR_REPLY,
|
||||
|
||||
/* Nicira extension messages.
|
||||
*
|
||||
* Nicira extensions that correspond to standard OpenFlow messages are listed
|
||||
* alongside the standard versions above. */
|
||||
|
||||
/* NXT 1.0 (12): struct nx_set_flow_format. */
|
||||
OFPRAW_NXT_SET_FLOW_FORMAT,
|
||||
|
||||
/* NXT 1.0+ (15): struct nx_flow_mod_table_id. */
|
||||
OFPRAW_NXT_FLOW_MOD_TABLE_ID,
|
||||
|
||||
/* NXT 1.0+ (16): struct nx_set_packet_in_format. */
|
||||
OFPRAW_NXT_SET_PACKET_IN_FORMAT,
|
||||
|
||||
/* NXT 1.0+ (18): void. */
|
||||
OFPRAW_NXT_FLOW_AGE,
|
||||
|
||||
/* NXT 1.0+ (20): struct nx_controller_id. */
|
||||
OFPRAW_NXT_SET_CONTROLLER_ID,
|
||||
|
||||
/* NXT 1.0+ (21): struct nx_flow_monitor_cancel. */
|
||||
OFPRAW_NXT_FLOW_MONITOR_CANCEL,
|
||||
|
||||
/* NXT 1.0+ (22): void. */
|
||||
OFPRAW_NXT_FLOW_MONITOR_PAUSED,
|
||||
|
||||
/* NXT 1.0+ (23): void. */
|
||||
OFPRAW_NXT_FLOW_MONITOR_RESUMED,
|
||||
|
||||
/* NXT 1.0+ (24): struct nx_tlv_table_mod, struct nx_tlv_map[]. */
|
||||
OFPRAW_NXT_TLV_TABLE_MOD,
|
||||
|
||||
/* NXT 1.0+ (25): void. */
|
||||
OFPRAW_NXT_TLV_TABLE_REQUEST,
|
||||
|
||||
/* NXT 1.0+ (26): struct nx_tlv_table_reply, struct nx_tlv_map[]. */
|
||||
OFPRAW_NXT_TLV_TABLE_REPLY,
|
||||
|
||||
/* NXT 1.0+ (28): uint8_t[8][]. */
|
||||
OFPRAW_NXT_RESUME,
|
||||
|
||||
/* NXT 1.0+ (29): struct nx_zone_id. */
|
||||
OFPRAW_NXT_CT_FLUSH_ZONE,
|
||||
|
||||
/* NXST 1.0+ (3): void. */
|
||||
OFPRAW_NXST_IPFIX_BRIDGE_REQUEST,
|
||||
|
||||
/* NXST 1.0+ (3): struct nx_ipfix_stats_reply. */
|
||||
OFPRAW_NXST_IPFIX_BRIDGE_REPLY,
|
||||
|
||||
/* NXST 1.0+ (4): void. */
|
||||
OFPRAW_NXST_IPFIX_FLOW_REQUEST,
|
||||
|
||||
/* NXST 1.0+ (4): struct nx_ipfix_stats_reply[]. */
|
||||
OFPRAW_NXST_IPFIX_FLOW_REPLY,
|
||||
};
|
||||
|
||||
/* Decoding messages into OFPRAW_* values. */
|
||||
enum ofperr ofpraw_decode(enum ofpraw *, const struct ofp_header *);
|
||||
enum ofpraw ofpraw_decode_assert(const struct ofp_header *);
|
||||
enum ofperr ofpraw_pull(enum ofpraw *, struct ofpbuf *);
|
||||
enum ofpraw ofpraw_pull_assert(struct ofpbuf *);
|
||||
|
||||
enum ofperr ofpraw_decode_partial(enum ofpraw *,
|
||||
const struct ofp_header *, size_t length);
|
||||
|
||||
/* Encoding messages using OFPRAW_* values. */
|
||||
struct ofpbuf *ofpraw_alloc(enum ofpraw, uint8_t ofp_version,
|
||||
size_t extra_tailroom);
|
||||
struct ofpbuf *ofpraw_alloc_xid(enum ofpraw, uint8_t ofp_version,
|
||||
ovs_be32 xid, size_t extra_tailroom);
|
||||
struct ofpbuf *ofpraw_alloc_reply(enum ofpraw,
|
||||
const struct ofp_header *request,
|
||||
size_t extra_tailroom);
|
||||
struct ofpbuf *ofpraw_alloc_stats_reply(const struct ofp_header *request,
|
||||
size_t extra_tailroom);
|
||||
|
||||
void ofpraw_put(enum ofpraw, uint8_t ofp_version, struct ofpbuf *);
|
||||
void ofpraw_put_xid(enum ofpraw, uint8_t ofp_version, ovs_be32 xid,
|
||||
struct ofpbuf *);
|
||||
void ofpraw_put_reply(enum ofpraw, const struct ofp_header *request,
|
||||
struct ofpbuf *);
|
||||
void ofpraw_put_stats_reply(const struct ofp_header *request, struct ofpbuf *);
|
||||
|
||||
/* Information about OFPRAW_* values. */
|
||||
const char *ofpraw_get_name(enum ofpraw);
|
||||
enum ofpraw ofpraw_stats_request_to_reply(enum ofpraw, uint8_t version);
|
||||
|
||||
/* Semantic identifiers for OpenFlow messages.
|
||||
*
|
||||
* Each OFPTYPE_* enumeration constant represents one or more concrete format
|
||||
* of OpenFlow message. When two variants of a message have essentially the
|
||||
* same meaning, they are assigned a single OFPTYPE_* value.
|
||||
*
|
||||
* The comments here must follow a stylized form because the "extract-ofp-msgs"
|
||||
* program parses them at build time to generate data tables. The format is
|
||||
* simply to list each OFPRAW_* enumeration constant for a given OFPTYPE_*,
|
||||
* each followed by a period. */
|
||||
enum ofptype {
|
||||
/* Immutable messages. */
|
||||
OFPTYPE_HELLO, /* OFPRAW_OFPT_HELLO. */
|
||||
OFPTYPE_ERROR, /* OFPRAW_OFPT_ERROR. */
|
||||
OFPTYPE_ECHO_REQUEST, /* OFPRAW_OFPT_ECHO_REQUEST. */
|
||||
OFPTYPE_ECHO_REPLY, /* OFPRAW_OFPT_ECHO_REPLY. */
|
||||
|
||||
/* Switch configuration messages. */
|
||||
OFPTYPE_FEATURES_REQUEST, /* OFPRAW_OFPT_FEATURES_REQUEST. */
|
||||
OFPTYPE_FEATURES_REPLY, /* OFPRAW_OFPT10_FEATURES_REPLY.
|
||||
* OFPRAW_OFPT11_FEATURES_REPLY.
|
||||
* OFPRAW_OFPT13_FEATURES_REPLY. */
|
||||
OFPTYPE_GET_CONFIG_REQUEST, /* OFPRAW_OFPT_GET_CONFIG_REQUEST. */
|
||||
OFPTYPE_GET_CONFIG_REPLY, /* OFPRAW_OFPT_GET_CONFIG_REPLY. */
|
||||
OFPTYPE_SET_CONFIG, /* OFPRAW_OFPT_SET_CONFIG. */
|
||||
|
||||
/* Asynchronous messages. */
|
||||
OFPTYPE_PACKET_IN, /* OFPRAW_OFPT10_PACKET_IN.
|
||||
* OFPRAW_OFPT11_PACKET_IN.
|
||||
* OFPRAW_OFPT12_PACKET_IN.
|
||||
* OFPRAW_OFPT13_PACKET_IN.
|
||||
* OFPRAW_NXT_PACKET_IN2.
|
||||
* OFPRAW_NXT_PACKET_IN. */
|
||||
OFPTYPE_FLOW_REMOVED, /* OFPRAW_OFPT10_FLOW_REMOVED.
|
||||
* OFPRAW_OFPT11_FLOW_REMOVED.
|
||||
* OFPRAW_NXT_FLOW_REMOVED. */
|
||||
OFPTYPE_PORT_STATUS, /* OFPRAW_OFPT10_PORT_STATUS.
|
||||
* OFPRAW_OFPT11_PORT_STATUS.
|
||||
* OFPRAW_OFPT14_PORT_STATUS. */
|
||||
|
||||
/* Controller command messages. */
|
||||
OFPTYPE_PACKET_OUT, /* OFPRAW_OFPT10_PACKET_OUT.
|
||||
* OFPRAW_OFPT11_PACKET_OUT. */
|
||||
OFPTYPE_FLOW_MOD, /* OFPRAW_OFPT10_FLOW_MOD.
|
||||
* OFPRAW_OFPT11_FLOW_MOD.
|
||||
* OFPRAW_NXT_FLOW_MOD. */
|
||||
OFPTYPE_GROUP_MOD, /* OFPRAW_OFPT11_GROUP_MOD.
|
||||
* OFPRAW_OFPT15_GROUP_MOD. */
|
||||
OFPTYPE_PORT_MOD, /* OFPRAW_OFPT10_PORT_MOD.
|
||||
* OFPRAW_OFPT11_PORT_MOD.
|
||||
* OFPRAW_OFPT14_PORT_MOD. */
|
||||
OFPTYPE_TABLE_MOD, /* OFPRAW_OFPT11_TABLE_MOD.
|
||||
* OFPRAW_OFPT14_TABLE_MOD. */
|
||||
|
||||
/* Barrier messages. */
|
||||
OFPTYPE_BARRIER_REQUEST, /* OFPRAW_OFPT10_BARRIER_REQUEST.
|
||||
* OFPRAW_OFPT11_BARRIER_REQUEST. */
|
||||
OFPTYPE_BARRIER_REPLY, /* OFPRAW_OFPT10_BARRIER_REPLY.
|
||||
* OFPRAW_OFPT11_BARRIER_REPLY. */
|
||||
|
||||
/* Queue Configuration messages. */
|
||||
OFPTYPE_QUEUE_GET_CONFIG_REQUEST, /* OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST.
|
||||
* OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST.
|
||||
* OFPRAW_OFPST14_QUEUE_DESC_REQUEST. */
|
||||
OFPTYPE_QUEUE_GET_CONFIG_REPLY, /* OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY.
|
||||
* OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY.
|
||||
* OFPRAW_OFPST14_QUEUE_DESC_REPLY. */
|
||||
|
||||
/* Controller role change request messages. */
|
||||
OFPTYPE_ROLE_REQUEST, /* OFPRAW_OFPT12_ROLE_REQUEST.
|
||||
* OFPRAW_NXT_ROLE_REQUEST. */
|
||||
OFPTYPE_ROLE_REPLY, /* OFPRAW_OFPT12_ROLE_REPLY.
|
||||
* OFPRAW_NXT_ROLE_REPLY. */
|
||||
|
||||
/* Asynchronous message configuration. */
|
||||
OFPTYPE_GET_ASYNC_REQUEST, /* OFPRAW_OFPT13_GET_ASYNC_REQUEST.
|
||||
* OFPRAW_OFPT14_GET_ASYNC_REQUEST. */
|
||||
OFPTYPE_GET_ASYNC_REPLY, /* OFPRAW_OFPT13_GET_ASYNC_REPLY.
|
||||
* OFPRAW_OFPT14_GET_ASYNC_REPLY. */
|
||||
OFPTYPE_SET_ASYNC_CONFIG, /* OFPRAW_NXT_SET_ASYNC_CONFIG.
|
||||
* OFPRAW_NXT_SET_ASYNC_CONFIG2.
|
||||
* OFPRAW_OFPT13_SET_ASYNC.
|
||||
* OFPRAW_OFPT14_SET_ASYNC. */
|
||||
|
||||
/* Meters and rate limiters configuration messages. */
|
||||
OFPTYPE_METER_MOD, /* OFPRAW_OFPT13_METER_MOD. */
|
||||
|
||||
/* Controller role change event messages. */
|
||||
OFPTYPE_ROLE_STATUS, /* OFPRAW_OFPT14_ROLE_STATUS. */
|
||||
|
||||
/* Request forwarding by the switch. */
|
||||
OFPTYPE_REQUESTFORWARD, /* OFPRAW_OFPT14_REQUESTFORWARD. */
|
||||
|
||||
/* Asynchronous messages. */
|
||||
OFPTYPE_TABLE_STATUS, /* OFPRAW_OFPT14_TABLE_STATUS. */
|
||||
|
||||
OFPTYPE_BUNDLE_CONTROL, /* OFPRAW_OFPT14_BUNDLE_CONTROL.
|
||||
* OFPRAW_ONFT13_BUNDLE_CONTROL. */
|
||||
|
||||
OFPTYPE_BUNDLE_ADD_MESSAGE, /* OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE.
|
||||
* OFPRAW_ONFT13_BUNDLE_ADD_MESSAGE. */
|
||||
|
||||
/* Statistics. */
|
||||
OFPTYPE_DESC_STATS_REQUEST, /* OFPRAW_OFPST_DESC_REQUEST. */
|
||||
OFPTYPE_DESC_STATS_REPLY, /* OFPRAW_OFPST_DESC_REPLY. */
|
||||
OFPTYPE_FLOW_STATS_REQUEST, /* OFPRAW_OFPST10_FLOW_REQUEST.
|
||||
* OFPRAW_OFPST11_FLOW_REQUEST.
|
||||
* OFPRAW_NXST_FLOW_REQUEST. */
|
||||
OFPTYPE_FLOW_STATS_REPLY, /* OFPRAW_OFPST10_FLOW_REPLY.
|
||||
* OFPRAW_OFPST11_FLOW_REPLY.
|
||||
* OFPRAW_OFPST13_FLOW_REPLY.
|
||||
* OFPRAW_NXST_FLOW_REPLY. */
|
||||
OFPTYPE_AGGREGATE_STATS_REQUEST, /* OFPRAW_OFPST10_AGGREGATE_REQUEST.
|
||||
* OFPRAW_OFPST11_AGGREGATE_REQUEST.
|
||||
* OFPRAW_NXST_AGGREGATE_REQUEST. */
|
||||
OFPTYPE_AGGREGATE_STATS_REPLY, /* OFPRAW_OFPST_AGGREGATE_REPLY.
|
||||
* OFPRAW_NXST_AGGREGATE_REPLY. */
|
||||
OFPTYPE_TABLE_STATS_REQUEST, /* OFPRAW_OFPST_TABLE_REQUEST. */
|
||||
OFPTYPE_TABLE_STATS_REPLY, /* OFPRAW_OFPST10_TABLE_REPLY.
|
||||
* OFPRAW_OFPST11_TABLE_REPLY.
|
||||
* OFPRAW_OFPST12_TABLE_REPLY.
|
||||
* OFPRAW_OFPST13_TABLE_REPLY. */
|
||||
OFPTYPE_PORT_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_REQUEST.
|
||||
* OFPRAW_OFPST11_PORT_REQUEST. */
|
||||
OFPTYPE_PORT_STATS_REPLY, /* OFPRAW_OFPST10_PORT_REPLY.
|
||||
* OFPRAW_OFPST11_PORT_REPLY.
|
||||
* OFPRAW_OFPST13_PORT_REPLY.
|
||||
* OFPRAW_OFPST14_PORT_REPLY. */
|
||||
OFPTYPE_QUEUE_STATS_REQUEST, /* OFPRAW_OFPST10_QUEUE_REQUEST.
|
||||
* OFPRAW_OFPST11_QUEUE_REQUEST. */
|
||||
OFPTYPE_QUEUE_STATS_REPLY, /* OFPRAW_OFPST10_QUEUE_REPLY.
|
||||
* OFPRAW_OFPST11_QUEUE_REPLY.
|
||||
* OFPRAW_OFPST13_QUEUE_REPLY.
|
||||
* OFPRAW_OFPST14_QUEUE_REPLY. */
|
||||
|
||||
OFPTYPE_GROUP_STATS_REQUEST, /* OFPRAW_OFPST11_GROUP_REQUEST. */
|
||||
|
||||
OFPTYPE_GROUP_STATS_REPLY, /* OFPRAW_OFPST11_GROUP_REPLY.
|
||||
* OFPRAW_OFPST13_GROUP_REPLY. */
|
||||
|
||||
OFPTYPE_GROUP_DESC_STATS_REQUEST, /* OFPRAW_OFPST11_GROUP_DESC_REQUEST.
|
||||
* OFPRAW_OFPST15_GROUP_DESC_REQUEST. */
|
||||
|
||||
OFPTYPE_GROUP_DESC_STATS_REPLY, /* OFPRAW_OFPST11_GROUP_DESC_REPLY. */
|
||||
|
||||
OFPTYPE_GROUP_FEATURES_STATS_REQUEST, /* OFPRAW_OFPST12_GROUP_FEATURES_REQUEST. */
|
||||
|
||||
OFPTYPE_GROUP_FEATURES_STATS_REPLY, /* OFPRAW_OFPST12_GROUP_FEATURES_REPLY. */
|
||||
|
||||
OFPTYPE_METER_STATS_REQUEST, /* OFPRAW_OFPST13_METER_REQUEST. */
|
||||
|
||||
OFPTYPE_METER_STATS_REPLY, /* OFPRAW_OFPST13_METER_REPLY. */
|
||||
|
||||
OFPTYPE_METER_CONFIG_STATS_REQUEST, /* OFPRAW_OFPST13_METER_CONFIG_REQUEST. */
|
||||
|
||||
OFPTYPE_METER_CONFIG_STATS_REPLY, /* OFPRAW_OFPST13_METER_CONFIG_REPLY. */
|
||||
|
||||
OFPTYPE_METER_FEATURES_STATS_REQUEST, /* OFPRAW_OFPST13_METER_FEATURES_REQUEST. */
|
||||
|
||||
OFPTYPE_METER_FEATURES_STATS_REPLY, /* OFPRAW_OFPST13_METER_FEATURES_REPLY. */
|
||||
|
||||
OFPTYPE_TABLE_FEATURES_STATS_REQUEST, /* OFPRAW_OFPST13_TABLE_FEATURES_REQUEST. */
|
||||
|
||||
OFPTYPE_TABLE_FEATURES_STATS_REPLY, /* OFPRAW_OFPST13_TABLE_FEATURES_REPLY. */
|
||||
|
||||
OFPTYPE_TABLE_DESC_REQUEST, /* OFPRAW_OFPST14_TABLE_DESC_REQUEST. */
|
||||
|
||||
OFPTYPE_TABLE_DESC_REPLY, /* OFPRAW_OFPST14_TABLE_DESC_REPLY. */
|
||||
|
||||
OFPTYPE_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_DESC_REQUEST.
|
||||
* OFPRAW_OFPST15_PORT_DESC_REQUEST. */
|
||||
|
||||
OFPTYPE_PORT_DESC_STATS_REPLY, /* OFPRAW_OFPST10_PORT_DESC_REPLY.
|
||||
* OFPRAW_OFPST11_PORT_DESC_REPLY.
|
||||
* OFPRAW_OFPST14_PORT_DESC_REPLY. */
|
||||
|
||||
OFPTYPE_FLOW_MONITOR_STATS_REQUEST, /* OFPRAW_OFPST14_FLOW_MONITOR_REQUEST.
|
||||
* OFPRAW_NXST_FLOW_MONITOR_REQUEST. */
|
||||
OFPTYPE_FLOW_MONITOR_STATS_REPLY, /* OFPRAW_OFPST14_FLOW_MONITOR_REPLY.
|
||||
* OFPRAW_NXST_FLOW_MONITOR_REPLY. */
|
||||
|
||||
/* Nicira extensions. */
|
||||
OFPTYPE_SET_FLOW_FORMAT, /* OFPRAW_NXT_SET_FLOW_FORMAT. */
|
||||
OFPTYPE_FLOW_MOD_TABLE_ID, /* OFPRAW_NXT_FLOW_MOD_TABLE_ID. */
|
||||
OFPTYPE_SET_PACKET_IN_FORMAT, /* OFPRAW_NXT_SET_PACKET_IN_FORMAT. */
|
||||
OFPTYPE_FLOW_AGE, /* OFPRAW_NXT_FLOW_AGE. */
|
||||
OFPTYPE_SET_CONTROLLER_ID, /* OFPRAW_NXT_SET_CONTROLLER_ID. */
|
||||
OFPTYPE_NXT_TLV_TABLE_MOD, /* OFPRAW_NXT_TLV_TABLE_MOD. */
|
||||
OFPTYPE_NXT_TLV_TABLE_REQUEST, /* OFPRAW_NXT_TLV_TABLE_REQUEST. */
|
||||
OFPTYPE_NXT_TLV_TABLE_REPLY, /* OFPRAW_NXT_TLV_TABLE_REPLY. */
|
||||
OFPTYPE_NXT_RESUME, /* OFPRAW_NXT_RESUME. */
|
||||
OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST, /* OFPRAW_NXST_IPFIX_BRIDGE_REQUEST */
|
||||
OFPTYPE_IPFIX_BRIDGE_STATS_REPLY, /* OFPRAW_NXST_IPFIX_BRIDGE_REPLY */
|
||||
OFPTYPE_IPFIX_FLOW_STATS_REQUEST, /* OFPRAW_NXST_IPFIX_FLOW_REQUEST */
|
||||
OFPTYPE_IPFIX_FLOW_STATS_REPLY, /* OFPRAW_NXST_IPFIX_FLOW_REPLY */
|
||||
OFPTYPE_CT_FLUSH_ZONE, /* OFPRAW_NXT_CT_FLUSH_ZONE. */
|
||||
|
||||
/* Flow monitor extension. */
|
||||
OFPTYPE_FLOW_MONITOR_CANCEL, /* OFPRAW_NXT_FLOW_MONITOR_CANCEL. */
|
||||
OFPTYPE_FLOW_MONITOR_PAUSED, /* OFPRAW_NXT_FLOW_MONITOR_PAUSED. */
|
||||
OFPTYPE_FLOW_MONITOR_RESUMED, /* OFPRAW_NXT_FLOW_MONITOR_RESUMED. */
|
||||
};
|
||||
|
||||
/* Decoding messages into OFPTYPE_* values. */
|
||||
enum ofperr ofptype_decode(enum ofptype *, const struct ofp_header *);
|
||||
enum ofperr ofptype_pull(enum ofptype *, struct ofpbuf *);
|
||||
enum ofptype ofptype_from_ofpraw(enum ofpraw);
|
||||
|
||||
/* Information about OFTYPE_* values. */
|
||||
const char *ofptype_get_name(enum ofptype);
|
||||
|
||||
/* OpenFlow message properties. */
|
||||
void ofpmsg_update_length(struct ofpbuf *);
|
||||
const void *ofpmsg_body(const struct ofp_header *);
|
||||
bool ofpmsg_is_stat_request(const struct ofp_header *);
|
||||
|
||||
/* Multipart messages (aka "statistics").
|
||||
*
|
||||
* Individual OpenFlow messages are limited to 64 kB in size, but some messages
|
||||
* need to be longer. Therefore, multipart messages allow a longer message to
|
||||
* be divided into multiple parts at some convenient boundary. For example,
|
||||
* limiting the response to a "flow dump" request to 64 kB would unreasonably
|
||||
* limit the maximum number of flows in an OpenFlow switch, so a "flow dump" is
|
||||
* expressed as a multipart request/reply pair, with the reply broken into
|
||||
* pieces between flows.
|
||||
*
|
||||
* Multipart messages always consist of a request/reply pair.
|
||||
*
|
||||
* In OpenFlow 1.0, 1.1, and 1.2, requests must always fit in a single message,
|
||||
* that is, only a multipart reply may have more than one part. OpenFlow 1.3
|
||||
* adds one multipart request. This code does not yet support multipart
|
||||
* requests. */
|
||||
|
||||
/* Encoding multipart replies.
|
||||
*
|
||||
* These functions are useful for multipart replies that might really require
|
||||
* more than one message. A multipart message that is known in advance to fit
|
||||
* within 64 kB doesn't need any special treatment, so you might as well use
|
||||
* the ofpraw_alloc_*() functions.
|
||||
*
|
||||
* These functions work with a "struct ovs_list" of "struct ofpbuf"s, each of
|
||||
* which represents one part of a multipart message. */
|
||||
void ofpmp_init(struct ovs_list *, const struct ofp_header *request);
|
||||
struct ofpbuf *ofpmp_reserve(struct ovs_list *, size_t len);
|
||||
void *ofpmp_append(struct ovs_list *, size_t len);
|
||||
void ofpmp_postappend(struct ovs_list *, size_t start_ofs);
|
||||
|
||||
enum ofp_version ofpmp_version(struct ovs_list *);
|
||||
enum ofpraw ofpmp_decode_raw(struct ovs_list *);
|
||||
|
||||
/* Decoding multipart replies. */
|
||||
uint16_t ofpmp_flags(const struct ofp_header *);
|
||||
bool ofpmp_more(const struct ofp_header *);
|
||||
|
||||
#endif /* ofp-msgs.h */
|
||||
118
openflow/include/openvswitch/ofp-parse.h
Normal file
118
openflow/include/openvswitch/ofp-parse.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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.
|
||||
*/
|
||||
|
||||
/* OpenFlow protocol string to flow parser. */
|
||||
|
||||
#ifndef OPENVSWITCH_OFP_PARSE_H
|
||||
#define OPENVSWITCH_OFP_PARSE_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "openvswitch/compiler.h"
|
||||
#include "openvswitch/types.h"
|
||||
|
||||
struct flow;
|
||||
struct ofpbuf;
|
||||
struct ofputil_flow_mod;
|
||||
struct ofputil_packet_out;
|
||||
struct ofputil_flow_monitor_request;
|
||||
struct ofputil_flow_stats_request;
|
||||
struct ofputil_group_mod;
|
||||
struct ofputil_meter_mod;
|
||||
struct ofputil_table_mod;
|
||||
struct ofputil_bundle_msg;
|
||||
struct ofputil_tlv_table_mod;
|
||||
struct simap;
|
||||
enum ofputil_protocol;
|
||||
|
||||
char *parse_ofp_str(struct ofputil_flow_mod *, int command, const char *str_,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_flow_mod_str(struct ofputil_flow_mod *, const char *string,
|
||||
int command,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_packet_out_str(struct ofputil_packet_out *po, const char *str_,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_table_mod(struct ofputil_table_mod *,
|
||||
const char *table_id, const char *flow_miss_handling,
|
||||
uint32_t *usable_versions)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_flow_mod_file(const char *file_name, int command,
|
||||
struct ofputil_flow_mod **fms, size_t *n_fms,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *,
|
||||
bool aggregate, const char *string,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_exact_flow(struct flow *flow, struct flow_wildcards *wc,
|
||||
const struct tun_table *tun_table, const char *s,
|
||||
const struct simap *portno_names);
|
||||
|
||||
char *parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string,
|
||||
int command,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_flow_monitor_request(struct ofputil_flow_monitor_request *,
|
||||
const char *,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_group_mod_file(const char *file_name, int command,
|
||||
struct ofputil_group_mod **gms, size_t *n_gms,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_group_mod_str(struct ofputil_group_mod *, int command,
|
||||
const char *string,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_bundle_file(const char *file_name,
|
||||
struct ofputil_bundle_msg **, size_t *n_bms,
|
||||
enum ofputil_protocol *)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_tlv_table_mod_str(struct ofputil_tlv_table_mod *,
|
||||
uint16_t command, const char *string,
|
||||
enum ofputil_protocol *usable_protocols)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
char *str_to_u8(const char *str, const char *name, uint8_t *valuep)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
char *str_to_u16(const char *str, const char *name, uint16_t *valuep)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
char *str_to_u32(const char *str, uint32_t *valuep) OVS_WARN_UNUSED_RESULT;
|
||||
char *str_to_u64(const char *str, uint64_t *valuep) OVS_WARN_UNUSED_RESULT;
|
||||
char *str_to_be64(const char *str, ovs_be64 *valuep) OVS_WARN_UNUSED_RESULT;
|
||||
char *str_to_mac(const char *str, struct eth_addr *mac) OVS_WARN_UNUSED_RESULT;
|
||||
char *str_to_ip(const char *str, ovs_be32 *ip) OVS_WARN_UNUSED_RESULT;
|
||||
char *str_to_connhelper(const char *str, uint16_t *alg) OVS_WARN_UNUSED_RESULT;
|
||||
char *parse_ofp_table_vacancy(struct ofputil_table_mod *,
|
||||
const char *flow_miss_handling)
|
||||
OVS_WARN_UNUSED_RESULT;
|
||||
|
||||
#endif /* ofp-parse.h */
|
||||
58
openflow/include/openvswitch/ofp-print.h
Normal file
58
openflow/include/openvswitch/ofp-print.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2011, 2012, 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.
|
||||
*/
|
||||
|
||||
/* OpenFlow protocol pretty-printer. */
|
||||
|
||||
#ifndef OPENVSWITCH_OFP_PRINT_H
|
||||
#define OPENVSWITCH_OFP_PRINT_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct ds;
|
||||
struct ofp10_match;
|
||||
struct ofp_flow_mod;
|
||||
struct ofp_header;
|
||||
struct ofputil_flow_stats;
|
||||
struct ofputil_table_features;
|
||||
struct ofputil_table_stats;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ofp_print(FILE *, const void *, size_t, int verbosity);
|
||||
void ofp_print_packet(FILE *stream, const void *data, size_t len);
|
||||
|
||||
void ofp10_match_print(struct ds *, const struct ofp10_match *, int verbosity);
|
||||
|
||||
char *ofp_to_string(const void *, size_t, int verbosity);
|
||||
char *ofp10_match_to_string(const struct ofp10_match *, int verbosity);
|
||||
char *ofp_packet_to_string(const void *data, size_t len);
|
||||
|
||||
void ofp_print_flow_stats(struct ds *, struct ofputil_flow_stats *);
|
||||
void ofp_print_version(const struct ofp_header *, struct ds *);
|
||||
void ofp_print_table_features(
|
||||
struct ds *, const struct ofputil_table_features *features,
|
||||
const struct ofputil_table_features *prev_features,
|
||||
const struct ofputil_table_stats *stats,
|
||||
const struct ofputil_table_stats *prev_stats);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ofp-print.h */
|
||||
138
openflow/include/openvswitch/ofp-prop.h
Normal file
138
openflow/include/openvswitch/ofp-prop.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, 2016 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 OPENVSWITCH_OFP_PROP_H
|
||||
#define OPENVSWITCH_OFP_PROP_H 1
|
||||
|
||||
/* OpenFlow 1.3+ property support
|
||||
* ==============================
|
||||
*
|
||||
* Several OpenFlow 1.3+ messages use type-length-value (TLV) properties that
|
||||
* take the common form shown by "struct ofp_prop_header". This module
|
||||
* provides support for serializing and deserializing properties in this
|
||||
* format.
|
||||
*
|
||||
*
|
||||
* Property types
|
||||
* --------------
|
||||
*
|
||||
* This module uses uint64_t values to identify property types
|
||||
*
|
||||
* - OpenFlow assigns 16-bit type values to its own standardized
|
||||
* properties. ofpprop uses these values directly in uint64_t.
|
||||
*
|
||||
* The 16-bit value 0xffff (and for some kinds of properties 0xfffe) is
|
||||
* reserved as a kind of escape to introduce an "experimenter" property
|
||||
* (see below).
|
||||
*
|
||||
* - Vendor-specific "experimenter" properties have a 32-bit "experimenter
|
||||
* ID" (generally an Ethernet OUI) and a 32-bit experimenter-defined
|
||||
* "exp_type". ofpprop encodes these with the experimenter ID in the
|
||||
* high 32 bits and exp_type in the low 32 bits. (All existing
|
||||
* experimenter IDs are nonzero, so this is unambiguous.) Use
|
||||
* OFPPROP_EXP to encode these property types.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "openvswitch/ofp-errors.h"
|
||||
#include "openvswitch/types.h"
|
||||
|
||||
struct ofpbuf;
|
||||
struct uuid;
|
||||
struct vlog_module;
|
||||
|
||||
/* Given an OpenFlow experimenter ID (e.g. NX_VENDOR_ID) 'exp_id' and type
|
||||
* 'exp_type', yields the code that ofpprop_pull() would use to identify the
|
||||
* given experimenter property. */
|
||||
#define OFPPROP_EXP(EXP_ID, EXP_TYPE) \
|
||||
(((uint64_t) (EXP_ID) << 32) | (EXP_TYPE))
|
||||
|
||||
/* Returns true if 'type' represents an experimenter property type,
|
||||
* false if it represents a standard property type.*/
|
||||
static inline bool
|
||||
ofpprop_is_experimenter(uint64_t type)
|
||||
{
|
||||
return type > UINT16_MAX;
|
||||
}
|
||||
|
||||
/* Deserializing properties. */
|
||||
enum ofperr ofpprop_pull__(struct ofpbuf *msg, struct ofpbuf *property,
|
||||
unsigned int alignment, unsigned int min_exp,
|
||||
uint64_t *typep);
|
||||
enum ofperr ofpprop_pull(struct ofpbuf *msg, struct ofpbuf *property,
|
||||
uint64_t *typep);
|
||||
|
||||
enum ofperr ofpprop_parse_be16(const struct ofpbuf *, ovs_be16 *value);
|
||||
enum ofperr ofpprop_parse_be32(const struct ofpbuf *, ovs_be32 *value);
|
||||
enum ofperr ofpprop_parse_be64(const struct ofpbuf *, ovs_be64 *value);
|
||||
enum ofperr ofpprop_parse_u8(const struct ofpbuf *, uint8_t *value);
|
||||
enum ofperr ofpprop_parse_u16(const struct ofpbuf *, uint16_t *value);
|
||||
enum ofperr ofpprop_parse_u32(const struct ofpbuf *, uint32_t *value);
|
||||
enum ofperr ofpprop_parse_u64(const struct ofpbuf *, uint64_t *value);
|
||||
enum ofperr ofpprop_parse_uuid(const struct ofpbuf *, struct uuid *);
|
||||
enum ofperr ofpprop_parse_nested(const struct ofpbuf *, struct ofpbuf *);
|
||||
|
||||
/* Serializing properties. */
|
||||
void ofpprop_put(struct ofpbuf *, uint64_t type,
|
||||
const void *value, size_t len);
|
||||
void *ofpprop_put_zeros(struct ofpbuf *, uint64_t type, size_t len);
|
||||
void ofpprop_put_be16(struct ofpbuf *, uint64_t type, ovs_be16 value);
|
||||
void ofpprop_put_be32(struct ofpbuf *, uint64_t type, ovs_be32 value);
|
||||
void ofpprop_put_be64(struct ofpbuf *, uint64_t type, ovs_be64 value);
|
||||
void ofpprop_put_u8(struct ofpbuf *, uint64_t type, uint8_t value);
|
||||
void ofpprop_put_u16(struct ofpbuf *, uint64_t type, uint16_t value);
|
||||
void ofpprop_put_u32(struct ofpbuf *, uint64_t type, uint32_t value);
|
||||
void ofpprop_put_u64(struct ofpbuf *, uint64_t type, uint64_t value);
|
||||
void ofpprop_put_bitmap(struct ofpbuf *, uint64_t type, uint64_t bitmap);
|
||||
void ofpprop_put_flag(struct ofpbuf *, uint64_t type);
|
||||
void ofpprop_put_uuid(struct ofpbuf *, uint64_t type, const struct uuid *);
|
||||
void ofpprop_put_nested(struct ofpbuf *, uint64_t type, const struct ofpbuf *);
|
||||
|
||||
size_t ofpprop_start(struct ofpbuf *, uint64_t type);
|
||||
void ofpprop_end(struct ofpbuf *, size_t start_ofs);
|
||||
|
||||
size_t ofpprop_start_nested(struct ofpbuf *, uint64_t type);
|
||||
|
||||
/* Logging errors while deserializing properties.
|
||||
*
|
||||
* The attitude that a piece of code should take when it deserializes an
|
||||
* unknown property type depends on the code in question:
|
||||
*
|
||||
* - In a "loose" context (with LOOSE set to true), that is, where the code
|
||||
* is parsing the property to find out about the state or the capabilities
|
||||
* of some piece of the system, generally an unknown property type is not
|
||||
* a big deal, because it only means that there is additional information
|
||||
* that the receiver does not understand.
|
||||
*
|
||||
* - In a "strict" context (with LOOSE set to false), that is, where the
|
||||
* code is parsing the property to change the state or configuration of a
|
||||
* part of the system, generally an unknown property type is an error,
|
||||
* because it means that the receiver is being asked to configure the
|
||||
* system in some way it doesn't understand.
|
||||
*
|
||||
* Given LOOSE, this macro automatically logs chooses an appropriate log
|
||||
* level. */
|
||||
#define OFPPROP_LOG(RL, LOOSE, ...) \
|
||||
VLOG_RL(RL, (LOOSE) ? VLL_DBG : VLL_WARN, __VA_ARGS__)
|
||||
|
||||
enum ofperr ofpprop_unknown(struct vlog_module *, bool loose, const char *msg,
|
||||
uint64_t type);
|
||||
#define OFPPROP_UNKNOWN(LOOSE, MSG, TYPE) \
|
||||
ofpprop_unknown(&this_module, LOOSE, MSG, TYPE)
|
||||
|
||||
#endif /* ofp-prop.h */
|
||||
1467
openflow/include/openvswitch/ofp-util.h
Normal file
1467
openflow/include/openvswitch/ofp-util.h
Normal file
File diff suppressed because it is too large
Load Diff
277
openflow/include/openvswitch/ofpbuf.h
Normal file
277
openflow/include/openvswitch/ofpbuf.h
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016 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 OPENVSWITCH_OFPBUF_H
|
||||
#define OPENVSWITCH_OFPBUF_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "openvswitch/dynamic-string.h"
|
||||
#include "openvswitch/list.h"
|
||||
#include "openvswitch/util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum OVS_PACKED_ENUM ofpbuf_source {
|
||||
OFPBUF_MALLOC, /* Obtained via malloc(). */
|
||||
OFPBUF_STACK, /* Un-movable stack space or static buffer. */
|
||||
OFPBUF_STUB, /* Starts on stack, may expand into heap. */
|
||||
};
|
||||
|
||||
/* Buffer for holding arbitrary data. An ofpbuf is automatically reallocated
|
||||
* as necessary if it grows too large for the available memory.
|
||||
*
|
||||
* 'header' and 'msg' conventions:
|
||||
*
|
||||
* OpenFlow messages: 'header' points to the start of the OpenFlow
|
||||
* header, while 'msg' is the OpenFlow msg body.
|
||||
* When parsing, the 'data' will move past these, as data is being
|
||||
* pulled from the OpenFlow message.
|
||||
*
|
||||
* Caution: buffer manipulation of 'struct ofpbuf' must always update
|
||||
* the 'header' and 'msg' pointers.
|
||||
*
|
||||
*
|
||||
* Actions: When encoding OVS action lists, the 'header' is used
|
||||
* as a pointer to the beginning of the current action (see ofpact_put()).
|
||||
*
|
||||
* rconn: Reuses 'header' as a private pointer while queuing.
|
||||
*/
|
||||
struct ofpbuf {
|
||||
void *base; /* First byte of allocated space. */
|
||||
void *data; /* First byte actually in use. */
|
||||
uint32_t size; /* Number of bytes in use. */
|
||||
uint32_t allocated; /* Number of bytes allocated. */
|
||||
|
||||
void *header; /* OpenFlow header. */
|
||||
void *msg; /* message's body */
|
||||
struct ovs_list list_node; /* Private list element for use by owner. */
|
||||
enum ofpbuf_source source; /* Source of memory allocated as 'base'. */
|
||||
};
|
||||
|
||||
/* An initializer for a struct ofpbuf that will be initially empty and uses the
|
||||
* space in STUB (which should be an array) as a stub. This is the initializer
|
||||
* form of ofpbuf_use_stub().
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* uint64_t stub[1024 / 8]; // 1 kB stub properly aligned for 64-bit data.
|
||||
* struct ofpbuf ofpbuf = OFPBUF_STUB_INITIALIZER(stub);
|
||||
*/
|
||||
#define OFPBUF_STUB_INITIALIZER(STUB) { \
|
||||
.base = (STUB), \
|
||||
.data = (STUB), \
|
||||
.size = 0, \
|
||||
.allocated = sizeof (STUB), \
|
||||
.header = NULL, \
|
||||
.msg = NULL, \
|
||||
.list_node = OVS_LIST_POISON, \
|
||||
.source = OFPBUF_STUB, \
|
||||
}
|
||||
|
||||
/* An initializer for a struct ofpbuf whose data starts at DATA and continues
|
||||
* for SIZE bytes. This is appropriate for an ofpbuf that will be used to
|
||||
* inspect existing data, without moving it around or reallocating it, and
|
||||
* generally without modifying it at all. This is the initializer form of
|
||||
* ofpbuf_use_const().
|
||||
*/
|
||||
static inline struct ofpbuf
|
||||
ofpbuf_const_initializer(const void *data, size_t size)
|
||||
{
|
||||
return (struct ofpbuf) {
|
||||
.base = CONST_CAST(void *, data),
|
||||
.data = CONST_CAST(void *, data),
|
||||
.size = size,
|
||||
.allocated = size,
|
||||
.header = NULL,
|
||||
.msg = NULL,
|
||||
.list_node = OVS_LIST_POISON,
|
||||
.source = OFPBUF_STACK,
|
||||
};
|
||||
}
|
||||
|
||||
void ofpbuf_use_ds(struct ofpbuf *, const struct ds *);
|
||||
void ofpbuf_use_stack(struct ofpbuf *, void *, size_t);
|
||||
void ofpbuf_use_stub(struct ofpbuf *, void *, size_t);
|
||||
void ofpbuf_use_const(struct ofpbuf *, const void *, size_t);
|
||||
|
||||
void ofpbuf_init(struct ofpbuf *, size_t);
|
||||
void ofpbuf_uninit(struct ofpbuf *);
|
||||
void ofpbuf_reinit(struct ofpbuf *, size_t);
|
||||
|
||||
struct ofpbuf *ofpbuf_new(size_t);
|
||||
struct ofpbuf *ofpbuf_new_with_headroom(size_t, size_t headroom);
|
||||
struct ofpbuf *ofpbuf_clone(const struct ofpbuf *);
|
||||
struct ofpbuf *ofpbuf_clone_with_headroom(const struct ofpbuf *,
|
||||
size_t headroom);
|
||||
struct ofpbuf *ofpbuf_clone_data(const void *, size_t);
|
||||
struct ofpbuf *ofpbuf_clone_data_with_headroom(const void *, size_t,
|
||||
size_t headroom);
|
||||
static inline void ofpbuf_delete(struct ofpbuf *);
|
||||
|
||||
static inline void *ofpbuf_at(const struct ofpbuf *, size_t offset,
|
||||
size_t size);
|
||||
static inline void *ofpbuf_at_assert(const struct ofpbuf *, size_t offset,
|
||||
size_t size);
|
||||
static inline void *ofpbuf_tail(const struct ofpbuf *);
|
||||
static inline void *ofpbuf_end(const struct ofpbuf *);
|
||||
|
||||
void *ofpbuf_put_uninit(struct ofpbuf *, size_t);
|
||||
void *ofpbuf_put_zeros(struct ofpbuf *, size_t);
|
||||
void *ofpbuf_put(struct ofpbuf *, const void *, size_t);
|
||||
char *ofpbuf_put_hex(struct ofpbuf *, const char *s, size_t *n);
|
||||
void ofpbuf_reserve(struct ofpbuf *, size_t);
|
||||
void *ofpbuf_push_uninit(struct ofpbuf *b, size_t);
|
||||
void *ofpbuf_push_zeros(struct ofpbuf *, size_t);
|
||||
void *ofpbuf_push(struct ofpbuf *b, const void *, size_t);
|
||||
|
||||
static inline size_t ofpbuf_headroom(const struct ofpbuf *);
|
||||
static inline size_t ofpbuf_tailroom(const struct ofpbuf *);
|
||||
static inline size_t ofpbuf_msgsize(const struct ofpbuf *);
|
||||
void ofpbuf_prealloc_headroom(struct ofpbuf *, size_t);
|
||||
void ofpbuf_prealloc_tailroom(struct ofpbuf *, size_t);
|
||||
void ofpbuf_trim(struct ofpbuf *);
|
||||
void ofpbuf_padto(struct ofpbuf *, size_t);
|
||||
void ofpbuf_shift(struct ofpbuf *, int);
|
||||
|
||||
static inline void ofpbuf_clear(struct ofpbuf *);
|
||||
static inline void *ofpbuf_pull(struct ofpbuf *, size_t);
|
||||
static inline void *ofpbuf_try_pull(struct ofpbuf *, size_t);
|
||||
|
||||
void *ofpbuf_steal_data(struct ofpbuf *);
|
||||
|
||||
char *ofpbuf_to_string(const struct ofpbuf *, size_t maxbytes);
|
||||
static inline struct ofpbuf *ofpbuf_from_list(const struct ovs_list *);
|
||||
void ofpbuf_list_delete(struct ovs_list *);
|
||||
static inline bool ofpbuf_equal(const struct ofpbuf *, const struct ofpbuf *);
|
||||
|
||||
|
||||
/* Frees memory that 'b' points to, as well as 'b' itself. */
|
||||
static inline void ofpbuf_delete(struct ofpbuf *b)
|
||||
{
|
||||
if (b) {
|
||||
ofpbuf_uninit(b);
|
||||
free(b);
|
||||
}
|
||||
}
|
||||
|
||||
/* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
|
||||
* byte 'offset'. Otherwise, returns a null pointer. */
|
||||
static inline void *ofpbuf_at(const struct ofpbuf *b, size_t offset,
|
||||
size_t size)
|
||||
{
|
||||
return offset + size <= b->size ? (char *) b->data + offset : NULL;
|
||||
}
|
||||
|
||||
/* Returns a pointer to byte 'offset' in 'b', which must contain at least
|
||||
* 'offset + size' bytes of data. */
|
||||
static inline void *ofpbuf_at_assert(const struct ofpbuf *b, size_t offset,
|
||||
size_t size)
|
||||
{
|
||||
ovs_assert(offset + size <= b->size);
|
||||
return ((char *) b->data) + offset;
|
||||
}
|
||||
|
||||
/* Returns a pointer to byte following the last byte of data in use in 'b'. */
|
||||
static inline void *ofpbuf_tail(const struct ofpbuf *b)
|
||||
{
|
||||
return (char *) b->data + b->size;
|
||||
}
|
||||
|
||||
/* Returns a pointer to byte following the last byte allocated for use (but
|
||||
* not necessarily in use) in 'b'. */
|
||||
static inline void *ofpbuf_end(const struct ofpbuf *b)
|
||||
{
|
||||
return (char *) b->base + b->allocated;
|
||||
}
|
||||
|
||||
/* Returns the number of bytes of headroom in 'b', that is, the number of bytes
|
||||
* of unused space in ofpbuf 'b' before the data that is in use. (Most
|
||||
* commonly, the data in a ofpbuf is at its beginning, and thus the ofpbuf's
|
||||
* headroom is 0.) */
|
||||
static inline size_t ofpbuf_headroom(const struct ofpbuf *b)
|
||||
{
|
||||
return (char*)b->data - (char*)b->base;
|
||||
}
|
||||
|
||||
/* Returns the number of bytes that may be appended to the tail end of ofpbuf
|
||||
* 'b' before the ofpbuf must be reallocated. */
|
||||
static inline size_t ofpbuf_tailroom(const struct ofpbuf *b)
|
||||
{
|
||||
return (char*)ofpbuf_end(b) - (char*)ofpbuf_tail(b);
|
||||
}
|
||||
|
||||
/* Returns the number of bytes from 'b->header' to 'b->msg', that is, the
|
||||
* length of 'b''s header. */
|
||||
static inline size_t
|
||||
ofpbuf_headersize(const struct ofpbuf *b)
|
||||
{
|
||||
return (char *)b->msg - (char *)b->header;
|
||||
}
|
||||
|
||||
/* Returns the number of bytes from 'b->msg' to 'b->data + b->size', that is,
|
||||
* the length of the used space in 'b' starting from 'msg'. */
|
||||
static inline size_t
|
||||
ofpbuf_msgsize(const struct ofpbuf *b)
|
||||
{
|
||||
return (char *)ofpbuf_tail(b) - (char *)b->msg;
|
||||
}
|
||||
|
||||
/* Clears any data from 'b'. */
|
||||
static inline void ofpbuf_clear(struct ofpbuf *b)
|
||||
{
|
||||
b->data = b->base;
|
||||
b->size = 0;
|
||||
}
|
||||
|
||||
/* Removes 'size' bytes from the head end of 'b', which must contain at least
|
||||
* 'size' bytes of data. Returns the first byte of data removed. */
|
||||
static inline void *ofpbuf_pull(struct ofpbuf *b, size_t size)
|
||||
{
|
||||
void *data = b->data;
|
||||
b->data = (char*)b->data + size;
|
||||
b->size = b->size - size;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* If 'b' has at least 'size' bytes of data, removes that many bytes from the
|
||||
* head end of 'b' and returns the first byte removed. Otherwise, returns a
|
||||
* null pointer without modifying 'b'. */
|
||||
static inline void *ofpbuf_try_pull(struct ofpbuf *b, size_t size)
|
||||
{
|
||||
return b->size >= size ? ofpbuf_pull(b, size) : NULL;
|
||||
}
|
||||
|
||||
static inline struct ofpbuf *ofpbuf_from_list(const struct ovs_list *list)
|
||||
{
|
||||
return CONTAINER_OF(list, struct ofpbuf, list_node);
|
||||
}
|
||||
|
||||
static inline bool ofpbuf_equal(const struct ofpbuf *a, const struct ofpbuf *b)
|
||||
{
|
||||
return a->size == b->size &&
|
||||
memcmp(a->data, b->data, a->size) == 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ofpbuf.h */
|
||||
64
openflow/include/openvswitch/packets.h
Normal file
64
openflow/include/openvswitch/packets.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 OPENVSWITCH_PACKETS_H
|
||||
#define OPENVSWITCH_PACKETS_H 1
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include "openvswitch/tun-metadata.h"
|
||||
|
||||
/* Tunnel information used in flow key and metadata. */
|
||||
struct flow_tnl {
|
||||
ovs_be32 ip_dst;
|
||||
struct in6_addr ipv6_dst;
|
||||
ovs_be32 ip_src;
|
||||
struct in6_addr ipv6_src;
|
||||
ovs_be64 tun_id;
|
||||
uint16_t flags;
|
||||
uint8_t ip_tos;
|
||||
uint8_t ip_ttl;
|
||||
ovs_be16 tp_src;
|
||||
ovs_be16 tp_dst;
|
||||
ovs_be16 gbp_id;
|
||||
uint8_t gbp_flags;
|
||||
uint8_t pad1[5]; /* Pad to 64 bits. */
|
||||
struct tun_metadata metadata;
|
||||
};
|
||||
|
||||
/* Some flags are exposed through OpenFlow while others are used only
|
||||
* internally. */
|
||||
|
||||
/* Public flags */
|
||||
#define FLOW_TNL_F_OAM (1 << 0)
|
||||
|
||||
#define FLOW_TNL_PUB_F_MASK ((1 << 1) - 1)
|
||||
|
||||
/* Private flags */
|
||||
#define FLOW_TNL_F_DONT_FRAGMENT (1 << 1)
|
||||
#define FLOW_TNL_F_CSUM (1 << 2)
|
||||
#define FLOW_TNL_F_KEY (1 << 3)
|
||||
|
||||
#define FLOW_TNL_F_MASK ((1 << 4) - 1)
|
||||
|
||||
/* Unfortunately, a "struct flow" sometimes has to handle OpenFlow port
|
||||
* numbers and other times datapath (dpif) port numbers. This union allows
|
||||
* access to both. */
|
||||
union flow_in_port {
|
||||
odp_port_t odp_port;
|
||||
ofp_port_t ofp_port;
|
||||
};
|
||||
|
||||
#endif /* packets.h */
|
||||
81
openflow/include/openvswitch/shash.h
Normal file
81
openflow/include/openvswitch/shash.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011, 2016 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 "openvswitch/hmap.h"
|
||||
#include "openvswitch/util.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_INIT (SHASH_NODE, node, &(SHASH)->map, \
|
||||
BUILD_ASSERT_TYPE(SHASH_NODE, struct shash_node *), \
|
||||
BUILD_ASSERT_TYPE(SHASH, struct shash *))
|
||||
|
||||
#define SHASH_FOR_EACH_SAFE(SHASH_NODE, NEXT, SHASH) \
|
||||
HMAP_FOR_EACH_SAFE_INIT ( \
|
||||
SHASH_NODE, NEXT, node, &(SHASH)->map, \
|
||||
BUILD_ASSERT_TYPE(SHASH_NODE, struct shash_node *), \
|
||||
BUILD_ASSERT_TYPE(NEXT, struct shash_node *), \
|
||||
BUILD_ASSERT_TYPE(SHASH, struct shash *))
|
||||
|
||||
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 */
|
||||
137
openflow/include/openvswitch/thread.h
Normal file
137
openflow/include/openvswitch/thread.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 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 OPENVSWITCH_THREAD_H
|
||||
#define OPENVSWITCH_THREAD_H 1
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include "openvswitch/compiler.h"
|
||||
|
||||
/* Mutex. */
|
||||
struct OVS_LOCKABLE ovs_mutex {
|
||||
pthread_mutex_t lock;
|
||||
const char *where; /* NULL if and only if uninitialized. */
|
||||
};
|
||||
|
||||
/* "struct ovs_mutex" initializer. */
|
||||
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
|
||||
#define OVS_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, \
|
||||
"<unlocked>" }
|
||||
#else
|
||||
#define OVS_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, "<unlocked>" }
|
||||
#endif
|
||||
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
#define OVS_ADAPTIVE_MUTEX_INITIALIZER \
|
||||
{ PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, "<unlocked>" }
|
||||
#else
|
||||
#define OVS_ADAPTIVE_MUTEX_INITIALIZER OVS_MUTEX_INITIALIZER
|
||||
#endif
|
||||
|
||||
/* ovs_mutex functions analogous to pthread_mutex_*() functions.
|
||||
*
|
||||
* Most of these functions abort the process with an error message on any
|
||||
* error. ovs_mutex_trylock() is an exception: it passes through a 0 or EBUSY
|
||||
* return value to the caller and aborts on any other error. */
|
||||
void ovs_mutex_init(const struct ovs_mutex *);
|
||||
void ovs_mutex_init_recursive(const struct ovs_mutex *);
|
||||
void ovs_mutex_init_adaptive(const struct ovs_mutex *);
|
||||
void ovs_mutex_destroy(const struct ovs_mutex *);
|
||||
void ovs_mutex_unlock(const struct ovs_mutex *mutex) OVS_RELEASES(mutex);
|
||||
void ovs_mutex_lock_at(const struct ovs_mutex *mutex, const char *where)
|
||||
OVS_ACQUIRES(mutex);
|
||||
#define ovs_mutex_lock(mutex) \
|
||||
ovs_mutex_lock_at(mutex, OVS_SOURCE_LOCATOR)
|
||||
|
||||
int ovs_mutex_trylock_at(const struct ovs_mutex *mutex, const char *where)
|
||||
OVS_TRY_LOCK(0, mutex);
|
||||
#define ovs_mutex_trylock(mutex) \
|
||||
ovs_mutex_trylock_at(mutex, OVS_SOURCE_LOCATOR)
|
||||
|
||||
void ovs_mutex_cond_wait(pthread_cond_t *, const struct ovs_mutex *);
|
||||
|
||||
/* Convenient once-only execution.
|
||||
*
|
||||
*
|
||||
* Problem
|
||||
* =======
|
||||
*
|
||||
* POSIX provides pthread_once_t and pthread_once() as primitives for running a
|
||||
* set of code only once per process execution. They are used like this:
|
||||
*
|
||||
* static void run_once(void) { ...initialization... }
|
||||
* static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
* ...
|
||||
* pthread_once(&once, run_once);
|
||||
*
|
||||
* pthread_once() does not allow passing any parameters to the initialization
|
||||
* function, which is often inconvenient, because it means that the function
|
||||
* can only access data declared at file scope.
|
||||
*
|
||||
*
|
||||
* Solution
|
||||
* ========
|
||||
*
|
||||
* Use ovsthread_once, like this, instead:
|
||||
*
|
||||
* static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
|
||||
*
|
||||
* if (ovsthread_once_start(&once)) {
|
||||
* ...initialization...
|
||||
* ovsthread_once_done(&once);
|
||||
* }
|
||||
*/
|
||||
|
||||
struct ovsthread_once {
|
||||
bool done; /* Non-atomic, false negatives possible. */
|
||||
struct ovs_mutex mutex;
|
||||
};
|
||||
|
||||
#define OVSTHREAD_ONCE_INITIALIZER \
|
||||
{ \
|
||||
false, \
|
||||
OVS_MUTEX_INITIALIZER, \
|
||||
}
|
||||
|
||||
static inline bool ovsthread_once_start(struct ovsthread_once *once)
|
||||
OVS_TRY_LOCK(true, once->mutex);
|
||||
void ovsthread_once_done(struct ovsthread_once *once)
|
||||
OVS_RELEASES(once->mutex);
|
||||
|
||||
bool ovsthread_once_start__(struct ovsthread_once *once)
|
||||
OVS_TRY_LOCK(true, once->mutex);
|
||||
|
||||
/* Returns true if this is the first call to ovsthread_once_start() for
|
||||
* 'once'. In this case, the caller should perform whatever initialization
|
||||
* actions it needs to do, then call ovsthread_once_done() for 'once'.
|
||||
*
|
||||
* Returns false if this is not the first call to ovsthread_once_start() for
|
||||
* 'once'. In this case, the call will not return until after
|
||||
* ovsthread_once_done() has been called. */
|
||||
static inline bool
|
||||
ovsthread_once_start(struct ovsthread_once *once)
|
||||
{
|
||||
/* We may be reading 'done' at the same time as the first thread
|
||||
* is writing on it, or we can be using a stale copy of it. The
|
||||
* worst that can happen is that we call ovsthread_once_start__()
|
||||
* once when strictly not necessary. */
|
||||
return OVS_UNLIKELY(!once->done && ovsthread_once_start__(once));
|
||||
}
|
||||
|
||||
#endif /* ovs-thread.h */
|
||||
45
openflow/include/openvswitch/token-bucket.h
Normal file
45
openflow/include/openvswitch/token-bucket.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 OPENVSWITCH_TOKEN_BUCKET_H
|
||||
#define OPENVSWITCH_TOKEN_BUCKET_H 1
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct token_bucket {
|
||||
/* Configuration settings. */
|
||||
unsigned int rate; /* Tokens added per millisecond. */
|
||||
unsigned int burst; /* Max cumulative tokens credit. */
|
||||
|
||||
/* Current status. */
|
||||
unsigned int tokens; /* Current number of tokens. */
|
||||
long long int last_fill; /* Last time tokens added. */
|
||||
};
|
||||
|
||||
#define TOKEN_BUCKET_INIT(RATE, BURST) { RATE, BURST, 0, LLONG_MIN }
|
||||
|
||||
void token_bucket_init(struct token_bucket *,
|
||||
unsigned int rate, unsigned int burst);
|
||||
void token_bucket_set(struct token_bucket *,
|
||||
unsigned int rate, unsigned int burst);
|
||||
bool token_bucket_withdraw(struct token_bucket *, unsigned int n);
|
||||
void token_bucket_wait_at(struct token_bucket *, unsigned int n,
|
||||
const char *where);
|
||||
#define token_bucket_wait(bucket, n) \
|
||||
token_bucket_wait_at(bucket, n, OVS_SOURCE_LOCATOR)
|
||||
|
||||
#endif /* token-bucket.h */
|
||||
101
openflow/include/openvswitch/tun-metadata.h
Normal file
101
openflow/include/openvswitch/tun-metadata.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 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 OPENVSWITCH_TUN_METADATA_H
|
||||
#define OPENVSWITCH_TUN_METADATA_H 1
|
||||
|
||||
#include "openvswitch/geneve.h"
|
||||
|
||||
#define TUN_METADATA_NUM_OPTS 64
|
||||
#define TUN_METADATA_TOT_OPT_SIZE 256
|
||||
|
||||
/* Tunnel option data, plus metadata to aid in their interpretation.
|
||||
*
|
||||
* The option data exists in two forms and is interpreted differently depending
|
||||
* on whether FLOW_TNL_F_UDPIF is set in struct flow_tnl flags:
|
||||
*
|
||||
* When FLOW_TNL_F_UDPIF is set, the tunnel metadata is in "userspace datapath
|
||||
* format". This is typically used for fast-path packet processing to avoid
|
||||
* the cost of translating options and in situations where we need to maintain
|
||||
* tunnel metadata exactly as it came in. In this case 'opts.gnv' is raw
|
||||
* packet data from the tunnel header and 'present.len' indicates the length
|
||||
* of the data stored there. In these situations, 'tab' is NULL.
|
||||
*
|
||||
* In all other cases, we are doing flow-based processing (such as during
|
||||
* upcalls). FLOW_TNL_F_UDPIF is not set and options are reordered into
|
||||
* pre-allocated locations. 'present.map' is indexed by type, that is, by the
|
||||
* <i> in TUN_METADATA<i>, so that e.g. TUN_METADATA5 is present if
|
||||
* 'present.map & (1ULL << 5)' is nonzero. The actual data for TUN_METADATA5,
|
||||
* if present, might be anywhere in 'opts.u8' (not necessarily even contiguous),
|
||||
* and finding it requires referring to 'tab', if set, or the global metadata
|
||||
* table. */
|
||||
struct tun_metadata {
|
||||
union { /* Valid members of 'opts'. When 'opts' is sorted into known types,
|
||||
* 'map' is used. When 'opts' is raw packet data, 'len' is used. */
|
||||
uint64_t map; /* 1-bit for each present TLV. */
|
||||
uint8_t len; /* Length of data in 'opts'. */
|
||||
} present;
|
||||
const struct tun_table *tab; /* Types & lengths for 'opts' and 'opt_map'. */
|
||||
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
uint8_t pad[4]; /* Pad to 64-bit boundary. */
|
||||
#endif
|
||||
|
||||
union {
|
||||
uint8_t u8[TUN_METADATA_TOT_OPT_SIZE]; /* Values from tunnel TLVs. */
|
||||
struct geneve_opt gnv[TLV_TOT_OPT_SIZE / sizeof(struct geneve_opt)];
|
||||
} opts;
|
||||
};
|
||||
BUILD_ASSERT_DECL(offsetof(struct tun_metadata, opts) % 8 == 0);
|
||||
BUILD_ASSERT_DECL(sizeof(((struct tun_metadata *)0)->present.map) * 8 >=
|
||||
TUN_METADATA_NUM_OPTS);
|
||||
|
||||
/* The location of an option can be stored either as a single offset/len
|
||||
* pair (hopefully) or if the address space is fragmented then it is a
|
||||
* linked list of these blocks. */
|
||||
struct tun_metadata_loc_chain {
|
||||
struct tun_metadata_loc_chain *next;
|
||||
int offset; /* In bytes, from start of 'opts', multiple of 4. */
|
||||
int len; /* In bytes, multiple of 4. */
|
||||
};
|
||||
|
||||
struct tun_metadata_loc {
|
||||
int len; /* Sum of 'len' over elements in chain. */
|
||||
struct tun_metadata_loc_chain c;
|
||||
};
|
||||
|
||||
/* Bookkeeping information to keep track of an option that was allocated
|
||||
* inside struct match. */
|
||||
struct tun_metadata_match_entry {
|
||||
struct tun_metadata_loc loc; /* Allocated position. */
|
||||
bool masked; /* Source value had a mask. Otherwise we can't tell if the
|
||||
* entire field was exact matched or only the portion that
|
||||
* is the same size as the value. */
|
||||
};
|
||||
|
||||
/* Allocation of options inside struct match. This is important if we don't
|
||||
* have access to an allocation table - either because there isn't one
|
||||
* (ovs-ofctl) or if we need to keep the allocation outside of packet
|
||||
* processing context (Packet-In). These structures never have dynamically
|
||||
* allocated memory because the address space is never fragmented. */
|
||||
struct tun_metadata_allocation {
|
||||
struct tun_metadata_match_entry entry[TUN_METADATA_NUM_OPTS];
|
||||
int alloc_offset; /* Byte offset into 'opts', multiple of 4. */
|
||||
bool valid; /* Set to true after any allocation occurs. */
|
||||
};
|
||||
|
||||
|
||||
#endif /* tun-metadata.h */
|
||||
55
openflow/include/openvswitch/type-props.h
Normal file
55
openflow/include/openvswitch/type-props.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, 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 OPENVSWITCH_TYPE_PROPS_H
|
||||
#define OPENVSWITCH_TYPE_PROPS_H 1
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* True if TYPE is _Bool, false otherwise. */
|
||||
#define TYPE_IS_BOOL(TYPE) ((TYPE) 1 == (TYPE) 2)
|
||||
|
||||
/* True if TYPE is an integer type (including _Bool), false if it is a
|
||||
* floating-point type. */
|
||||
#define TYPE_IS_INTEGER(TYPE) ((TYPE) 1.5 == (TYPE) 1)
|
||||
|
||||
/* True if TYPE is a signed integer or floating point type, otherwise false. */
|
||||
#define TYPE_IS_SIGNED(TYPE) ((TYPE) 1 > (TYPE) -1)
|
||||
|
||||
/* The number of value bits in an signed or unsigned integer TYPE:
|
||||
*
|
||||
* - _Bool has 1 value bit.
|
||||
*
|
||||
* - An N-bit unsigned integer type has N value bits.
|
||||
*
|
||||
* - An N-bit signed integer type has N-1 value bits.
|
||||
*/
|
||||
#define TYPE_VALUE_BITS(TYPE) \
|
||||
(TYPE_IS_BOOL(TYPE) ? 1 : sizeof(TYPE) * CHAR_BIT - TYPE_IS_SIGNED(TYPE))
|
||||
|
||||
/* The minimum or maximum value of a signed or unsigned integer TYPE. */
|
||||
#define TYPE_MINIMUM(TYPE) (TYPE_IS_SIGNED(TYPE) ? -TYPE_MAXIMUM(TYPE) - 1 : 0)
|
||||
#define TYPE_MAXIMUM(TYPE) \
|
||||
((((TYPE)1 << (TYPE_VALUE_BITS(TYPE) - 1)) - 1) * 2 + 1)
|
||||
|
||||
/* Number of decimal digits required to format an integer of the given TYPE.
|
||||
* Includes space for a sign, if TYPE is signed, but not for a null
|
||||
* terminator.
|
||||
*
|
||||
* The value is an overestimate. */
|
||||
#define INT_STRLEN(TYPE) (TYPE_IS_SIGNED(TYPE) + TYPE_VALUE_BITS(TYPE) / 3 + 1)
|
||||
|
||||
#endif /* type-props.h */
|
||||
155
openflow/include/openvswitch/types.h
Normal file
155
openflow/include/openvswitch/types.h
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, 2013, 2014, 2016 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 OPENVSWITCH_TYPES_H
|
||||
#define OPENVSWITCH_TYPES_H 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include "openvswitch/compiler.h"
|
||||
|
||||
#ifdef __CHECKER__
|
||||
#define OVS_BITWISE __attribute__((bitwise))
|
||||
#define OVS_FORCE __attribute__((force))
|
||||
#else
|
||||
#define OVS_BITWISE
|
||||
#define OVS_FORCE
|
||||
#endif
|
||||
|
||||
/* The ovs_be<N> types indicate that an object is in big-endian, not
|
||||
* native-endian, byte order. They are otherwise equivalent to uint<N>_t. */
|
||||
typedef uint16_t OVS_BITWISE ovs_be16;
|
||||
typedef uint32_t OVS_BITWISE ovs_be32;
|
||||
typedef uint64_t OVS_BITWISE ovs_be64;
|
||||
|
||||
#define OVS_BE16_MAX ((OVS_FORCE ovs_be16) 0xffff)
|
||||
#define OVS_BE32_MAX ((OVS_FORCE ovs_be32) 0xffffffff)
|
||||
#define OVS_BE64_MAX ((OVS_FORCE ovs_be64) 0xffffffffffffffffULL)
|
||||
|
||||
/* These types help with a few funny situations:
|
||||
*
|
||||
* - The Ethernet header is 14 bytes long, which misaligns everything after
|
||||
* that. One can put 2 "shim" bytes before the Ethernet header, but this
|
||||
* helps only if there is exactly one Ethernet header. If there are two,
|
||||
* as with GRE and VXLAN (and if the inner header doesn't use this
|
||||
* trick--GRE and VXLAN don't) then you have the choice of aligning the
|
||||
* inner data or the outer data. So it seems better to treat 32-bit fields
|
||||
* in protocol headers as aligned only on 16-bit boundaries.
|
||||
*
|
||||
* - ARP headers contain misaligned 32-bit fields.
|
||||
*
|
||||
* - Netlink and OpenFlow contain 64-bit values that are only guaranteed to
|
||||
* be aligned on 32-bit boundaries.
|
||||
*
|
||||
* lib/unaligned.h has helper functions for accessing these. */
|
||||
|
||||
/* A 32-bit value, in host byte order, that is only aligned on a 16-bit
|
||||
* boundary. */
|
||||
typedef struct {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
uint16_t hi, lo;
|
||||
#else
|
||||
uint16_t lo, hi;
|
||||
#endif
|
||||
} ovs_16aligned_u32;
|
||||
|
||||
/* A 32-bit value, in network byte order, that is only aligned on a 16-bit
|
||||
* boundary. */
|
||||
typedef struct {
|
||||
ovs_be16 hi, lo;
|
||||
} ovs_16aligned_be32;
|
||||
|
||||
/* A 64-bit value, in host byte order, that is only aligned on a 32-bit
|
||||
* boundary. */
|
||||
typedef struct {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
uint32_t hi, lo;
|
||||
#else
|
||||
uint32_t lo, hi;
|
||||
#endif
|
||||
} ovs_32aligned_u64;
|
||||
|
||||
typedef union {
|
||||
uint32_t u32[4];
|
||||
struct {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
uint64_t hi, lo;
|
||||
#else
|
||||
uint64_t lo, hi;
|
||||
#endif
|
||||
} u64;
|
||||
} ovs_u128;
|
||||
|
||||
typedef union {
|
||||
ovs_be32 be32[4];
|
||||
struct {
|
||||
ovs_be64 hi, lo;
|
||||
} be64;
|
||||
} ovs_be128;
|
||||
|
||||
/* MSVC2015 doesn't support designated initializers when compiling C++,
|
||||
* and doesn't support ternary operators with non-designated initializers.
|
||||
* So we use these static definitions rather than using initializer macros. */
|
||||
static const ovs_u128 OVS_U128_ZERO = { { 0, 0, 0, 0 } };
|
||||
static const ovs_u128 OVS_U128_MAX = { { UINT32_MAX, UINT32_MAX,
|
||||
UINT32_MAX, UINT32_MAX } };
|
||||
static const ovs_be128 OVS_BE128_MAX OVS_UNUSED = { { OVS_BE32_MAX, OVS_BE32_MAX,
|
||||
OVS_BE32_MAX, OVS_BE32_MAX } };
|
||||
static const ovs_u128 OVS_U128_MIN OVS_UNUSED = { {0, 0, 0, 0} };
|
||||
static const ovs_u128 OVS_BE128_MIN OVS_UNUSED = { {0, 0, 0, 0} };
|
||||
|
||||
#define OVS_U128_ZERO OVS_U128_MIN
|
||||
|
||||
/* A 64-bit value, in network byte order, that is only aligned on a 32-bit
|
||||
* boundary. */
|
||||
typedef struct {
|
||||
ovs_be32 hi, lo;
|
||||
} ovs_32aligned_be64;
|
||||
|
||||
/* Port numbers
|
||||
* ------------
|
||||
*
|
||||
* None of these types are directly interchangeable, hence the OVS_BITWISE
|
||||
* annotation.
|
||||
*
|
||||
* ofp_port_t is an OpenFlow 1.0 port number. It uses a 16-bit range, even
|
||||
* though it is a 32-bit type. This allows it to be overlaid on an odp_port_t
|
||||
* for a few situations where this is useful, e.g. in union flow_in_port.
|
||||
*
|
||||
* ofp11_port_t is an OpenFlow-1.1 port number.
|
||||
*
|
||||
* odp_port_t is a port number within a datapath (e.g. see lib/dpif.h).
|
||||
*/
|
||||
typedef uint32_t OVS_BITWISE ofp_port_t;
|
||||
typedef uint32_t OVS_BITWISE odp_port_t;
|
||||
typedef uint32_t OVS_BITWISE ofp11_port_t;
|
||||
|
||||
/* Macro functions that cast int types to ofp/odp/ofp11 types. */
|
||||
#define OFP_PORT_C(X) ((OVS_FORCE ofp_port_t) (X))
|
||||
#define ODP_PORT_C(X) ((OVS_FORCE odp_port_t) (X))
|
||||
#define OFP11_PORT_C(X) ((OVS_FORCE ofp11_port_t) (X))
|
||||
|
||||
/* Using this struct instead of a bare array makes an ethernet address field
|
||||
* assignable. The size of the array is also part of the type, so it is easier
|
||||
* to deal with. */
|
||||
struct eth_addr {
|
||||
union {
|
||||
uint8_t ea[6];
|
||||
ovs_be16 be16[3];
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* openvswitch/types.h */
|
||||
218
openflow/include/openvswitch/util.h
Normal file
218
openflow/include/openvswitch/util.h
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017 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 OPENVSWITCH_UTIL_H
|
||||
#define OPENVSWITCH_UTIL_H 1
|
||||
|
||||
#include <openvswitch/compiler.h>
|
||||
#include <openvswitch/version.h>
|
||||
#include <openvswitch/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ovs_set_program_name(const char *name, const char *version);
|
||||
|
||||
const char *ovs_get_program_name(void);
|
||||
const char *ovs_get_program_version(void);
|
||||
|
||||
/* Expands to a string that looks like "<file>:<line>", e.g. "tmp.c:10".
|
||||
*
|
||||
* See http://c-faq.com/ansi/stringize.html for an explanation of OVS_STRINGIZE
|
||||
* and OVS_STRINGIZE2. */
|
||||
#define OVS_SOURCE_LOCATOR __FILE__ ":" OVS_STRINGIZE(__LINE__)
|
||||
#define OVS_STRINGIZE(ARG) OVS_STRINGIZE2(ARG)
|
||||
#define OVS_STRINGIZE2(ARG) #ARG
|
||||
|
||||
/* Saturating multiplication of "unsigned int"s: overflow yields UINT_MAX. */
|
||||
#define OVS_SAT_MUL(X, Y) \
|
||||
((Y) == 0 ? 0 \
|
||||
: (X) <= UINT_MAX / (Y) ? (unsigned int) (X) * (unsigned int) (Y) \
|
||||
: UINT_MAX)
|
||||
|
||||
/* 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 *);
|
||||
|
||||
/* This is a void expression that issues a compiler error if POINTER cannot be
|
||||
* compared for equality with the given pointer TYPE. This generally means
|
||||
* that POINTER is a qualified or unqualified TYPE. However,
|
||||
* BUILD_ASSERT_TYPE(POINTER, void *) will accept any pointer to object type,
|
||||
* because any pointer to object can be compared for equality with "void *".
|
||||
*
|
||||
* POINTER can be any expression. The use of "sizeof" ensures that the
|
||||
* expression is not actually evaluated, so that any side effects of the
|
||||
* expression do not occur.
|
||||
*
|
||||
* 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 BUILD_ASSERT_TYPE(POINTER, TYPE) \
|
||||
((void) sizeof ((int) ((POINTER) == (TYPE) (POINTER))))
|
||||
|
||||
/* Casts 'pointer' to 'type' and issues a compiler warning if the cast changes
|
||||
* anything other than an outermost "const" or "volatile" qualifier. */
|
||||
#define CONST_CAST(TYPE, POINTER) \
|
||||
(BUILD_ASSERT_TYPE(POINTER, TYPE), \
|
||||
(TYPE) (POINTER))
|
||||
|
||||
/* 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))
|
||||
|
||||
/* Yields the offset of the end of MEMBER within STRUCT. */
|
||||
#define OFFSETOFEND(STRUCT, MEMBER) \
|
||||
(offsetof(STRUCT, MEMBER) + MEMBER_SIZEOF(STRUCT, 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))
|
||||
|
||||
/* 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)))
|
||||
|
||||
/* Expands to an anonymous union that contains:
|
||||
*
|
||||
* - MEMBERS in a nested anonymous struct.
|
||||
*
|
||||
* - An array as large as MEMBERS plus padding to a multiple of UNIT bytes.
|
||||
*
|
||||
* The effect is to pad MEMBERS to a multiple of UNIT bytes.
|
||||
*
|
||||
* For example, the struct below is 8 bytes long, with 6 bytes of padding:
|
||||
*
|
||||
* struct padded_struct {
|
||||
* PADDED_MEMBERS(8, uint8_t x; uint8_t y;);
|
||||
* };
|
||||
*/
|
||||
#define PADDED_MEMBERS(UNIT, MEMBERS) \
|
||||
union { \
|
||||
struct { MEMBERS }; \
|
||||
uint8_t pad[ROUND_UP(sizeof(struct { MEMBERS }), UNIT)]; \
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
/* Macros for sizing bitmaps */
|
||||
#define BITMAP_ULONG_BITS (sizeof(unsigned long) * CHAR_BIT)
|
||||
#define BITMAP_N_LONGS(N_BITS) DIV_ROUND_UP(N_BITS, BITMAP_ULONG_BITS)
|
||||
|
||||
/* 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))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
35
openflow/include/openvswitch/uuid.h
Normal file
35
openflow/include/openvswitch/uuid.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright (c) 2008, 2009, 2010 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 OPENVSWITCH_UUID_H
|
||||
#define OPENVSWITCH_UUID_H 1
|
||||
|
||||
#include "openvswitch/util.h"
|
||||
|
||||
#define UUID_BIT 128 /* Number of bits in a UUID. */
|
||||
#define UUID_OCTET (UUID_BIT / 8) /* Number of bytes in a UUID. */
|
||||
|
||||
/* A Universally Unique IDentifier (UUID) compliant with RFC 4122.
|
||||
*
|
||||
* Each of the parts is stored in host byte order, but the parts themselves are
|
||||
* ordered from left to right. That is, (parts[0] >> 24) is the first 8 bits
|
||||
* of the UUID when output in the standard form, and (parts[3] & 0xff) is the
|
||||
* final 8 bits. */
|
||||
struct uuid {
|
||||
uint32_t parts[4];
|
||||
};
|
||||
BUILD_ASSERT_DECL(sizeof(struct uuid) == UUID_OCTET);
|
||||
|
||||
#endif /* uuid.h */
|
||||
114
openflow/include/openvswitch/vconn.h
Normal file
114
openflow/include/openvswitch/vconn.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2016 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 OPENVSWITCH_VCONN_H
|
||||
#define OPENVSWITCH_VCONN_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "openvswitch/list.h"
|
||||
#include "openvswitch/types.h"
|
||||
#include "openvswitch/ofp-util.h"
|
||||
#include "openflow/openflow.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ofpbuf;
|
||||
struct pvconn;
|
||||
struct pvconn_class;
|
||||
struct vconn;
|
||||
struct vconn_class;
|
||||
|
||||
void vconn_usage(bool active, bool passive, bool bootstrap);
|
||||
|
||||
/* Active vconns: virtual connections to OpenFlow devices. */
|
||||
int vconn_verify_name(const char *name);
|
||||
int vconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp,
|
||||
struct vconn **vconnp);
|
||||
void vconn_close(struct vconn *);
|
||||
const char *vconn_get_name(const struct vconn *);
|
||||
|
||||
uint32_t vconn_get_allowed_versions(const struct vconn *vconn);
|
||||
void vconn_set_allowed_versions(struct vconn *vconn,
|
||||
uint32_t allowed_versions);
|
||||
int vconn_get_version(const struct vconn *);
|
||||
void vconn_set_recv_any_version(struct vconn *);
|
||||
|
||||
int vconn_connect(struct vconn *);
|
||||
int vconn_recv(struct vconn *, struct ofpbuf **);
|
||||
int vconn_send(struct vconn *, struct ofpbuf *);
|
||||
int vconn_recv_xid(struct vconn *, ovs_be32 xid, struct ofpbuf **);
|
||||
int vconn_transact(struct vconn *, struct ofpbuf *, struct ofpbuf **);
|
||||
int vconn_transact_noreply(struct vconn *, struct ofpbuf *, struct ofpbuf **);
|
||||
int vconn_transact_multiple_noreply(struct vconn *, struct ovs_list *requests,
|
||||
struct ofpbuf **replyp);
|
||||
|
||||
int vconn_dump_flows(struct vconn *, const struct ofputil_flow_stats_request *,
|
||||
enum ofputil_protocol,
|
||||
struct ofputil_flow_stats **fsesp, size_t *n_fsesp);
|
||||
|
||||
/* Bundle errors must be free()d by the caller. */
|
||||
struct vconn_bundle_error {
|
||||
struct ovs_list list_node;
|
||||
|
||||
/* OpenFlow header and some of the message contents for error reporting. */
|
||||
union {
|
||||
struct ofp_header ofp_msg;
|
||||
uint8_t ofp_msg_data[64];
|
||||
};
|
||||
};
|
||||
|
||||
/* Bundle errors must be free()d by the caller. */
|
||||
int vconn_bundle_transact(struct vconn *, struct ovs_list *requests,
|
||||
uint16_t bundle_flags,
|
||||
struct ovs_list *errors);
|
||||
|
||||
void vconn_run(struct vconn *);
|
||||
void vconn_run_wait(struct vconn *);
|
||||
|
||||
int vconn_get_status(const struct vconn *);
|
||||
|
||||
int vconn_open_block(const char *name, uint32_t allowed_versions, uint8_t dscp,
|
||||
struct vconn **);
|
||||
int vconn_connect_block(struct vconn *);
|
||||
int vconn_send_block(struct vconn *, struct ofpbuf *);
|
||||
int vconn_recv_block(struct vconn *, struct ofpbuf **);
|
||||
|
||||
enum vconn_wait_type {
|
||||
WAIT_CONNECT,
|
||||
WAIT_RECV,
|
||||
WAIT_SEND
|
||||
};
|
||||
void vconn_wait(struct vconn *, enum vconn_wait_type);
|
||||
void vconn_connect_wait(struct vconn *);
|
||||
void vconn_recv_wait(struct vconn *);
|
||||
void vconn_send_wait(struct vconn *);
|
||||
|
||||
/* Passive vconns: virtual listeners for incoming OpenFlow connections. */
|
||||
int pvconn_verify_name(const char *name);
|
||||
int pvconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp,
|
||||
struct pvconn **pvconnp);
|
||||
const char *pvconn_get_name(const struct pvconn *);
|
||||
void pvconn_close(struct pvconn *);
|
||||
int pvconn_accept(struct pvconn *, struct vconn **);
|
||||
void pvconn_wait(struct pvconn *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* vconn.h */
|
||||
28
openflow/include/openvswitch/version.h
Normal file
28
openflow/include/openvswitch/version.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Nicira, Inc.
|
||||
* Copyright (c) 2014 Cisco Systems, 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 OPENVSWITCH_VERSION_H
|
||||
#define OPENVSWITCH_VERSION_H 1
|
||||
|
||||
#define OVS_PACKAGE_STRING "openvswitch 2.7.0"
|
||||
#define OVS_PACKAGE_VERSION "2.7.0"
|
||||
|
||||
#define OVS_LIB_VERSION 1
|
||||
#define OVS_LIB_REVISION 0
|
||||
#define OVS_LIB_AGE 0
|
||||
|
||||
#endif /* openvswitch/version.h */
|
||||
300
openflow/include/openvswitch/vlog.h
Normal file
300
openflow/include/openvswitch/vlog.h
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2016 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 OPENVSWITCH_VLOG_H
|
||||
#define OPENVSWITCH_VLOG_H 1
|
||||
|
||||
/* Logging.
|
||||
*
|
||||
*
|
||||
* Thread-safety
|
||||
* =============
|
||||
*
|
||||
* Fully thread safe.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <openvswitch/compiler.h>
|
||||
#include <openvswitch/list.h>
|
||||
#include <openvswitch/thread.h>
|
||||
#include <openvswitch/token-bucket.h>
|
||||
#include <openvswitch/util.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Logging severity levels.
|
||||
*
|
||||
* ovs-appctl(8) defines each of the log levels. */
|
||||
#define VLOG_LEVELS \
|
||||
VLOG_LEVEL(OFF, LOG_ALERT, 1) \
|
||||
VLOG_LEVEL(EMER, LOG_ALERT, 1) \
|
||||
VLOG_LEVEL(ERR, LOG_ERR, 3) \
|
||||
VLOG_LEVEL(WARN, LOG_WARNING, 4) \
|
||||
VLOG_LEVEL(INFO, LOG_NOTICE, 5) \
|
||||
VLOG_LEVEL(DBG, LOG_DEBUG, 7)
|
||||
enum vlog_level {
|
||||
#define VLOG_LEVEL(NAME, SYSLOG_LEVEL, RFC5424_LEVEL) VLL_##NAME,
|
||||
VLOG_LEVELS
|
||||
#undef VLOG_LEVEL
|
||||
VLL_N_LEVELS
|
||||
};
|
||||
|
||||
const char *vlog_get_level_name(enum vlog_level);
|
||||
enum vlog_level vlog_get_level_val(const char *name);
|
||||
|
||||
/* Destinations that we can log to. */
|
||||
#define VLOG_DESTINATIONS \
|
||||
VLOG_DESTINATION(SYSLOG, "ovs|%05N|%c%T|%p|%m") \
|
||||
VLOG_DESTINATION(CONSOLE, "%D{%Y-%m-%dT%H:%M:%SZ}|%05N|%c%T|%p|%m") \
|
||||
VLOG_DESTINATION(FILE, "%D{%Y-%m-%dT%H:%M:%S.###Z}|%05N|%c%T|%p|%m")
|
||||
enum vlog_destination {
|
||||
#define VLOG_DESTINATION(NAME, PATTERN) VLF_##NAME,
|
||||
VLOG_DESTINATIONS
|
||||
#undef VLOG_DESTINATION
|
||||
VLF_N_DESTINATIONS,
|
||||
VLF_ANY_DESTINATION = -1
|
||||
};
|
||||
|
||||
const char *vlog_get_destination_name(enum vlog_destination);
|
||||
enum vlog_destination vlog_get_destination_val(const char *name);
|
||||
|
||||
/* A log module. */
|
||||
struct vlog_module {
|
||||
struct ovs_list list;
|
||||
const char *name; /* User-visible name. */
|
||||
int levels[VLF_N_DESTINATIONS]; /* Minimum log level for each
|
||||
destination. */
|
||||
int min_level; /* Minimum log level for any destination. */
|
||||
bool honor_rate_limits; /* Set false to ignore rate limits. */
|
||||
};
|
||||
|
||||
void vlog_insert_module(struct ovs_list *);
|
||||
|
||||
const char *vlog_get_module_name(const struct vlog_module *);
|
||||
struct vlog_module *vlog_module_from_name(const char *name);
|
||||
|
||||
/* Rate-limiter for log messages. */
|
||||
struct vlog_rate_limit {
|
||||
struct token_bucket token_bucket;
|
||||
time_t first_dropped; /* Time first message was dropped. */
|
||||
time_t last_dropped; /* Time of most recent message drop. */
|
||||
unsigned int n_dropped; /* Number of messages dropped. */
|
||||
struct ovs_mutex mutex; /* Mutual exclusion for rate limit. */
|
||||
};
|
||||
|
||||
/* Number of tokens to emit a message. We add 'rate' tokens per millisecond,
|
||||
* thus 60,000 tokens are required to emit one message per minute. */
|
||||
#define VLOG_MSG_TOKENS (60 * 1000)
|
||||
|
||||
/* Initializer for a struct vlog_rate_limit, to set up a maximum rate of RATE
|
||||
* messages per minute and a maximum burst size of BURST messages. */
|
||||
#define VLOG_RATE_LIMIT_INIT(RATE, BURST) \
|
||||
{ \
|
||||
TOKEN_BUCKET_INIT(RATE, OVS_SAT_MUL(BURST, VLOG_MSG_TOKENS)), \
|
||||
0, /* first_dropped */ \
|
||||
0, /* last_dropped */ \
|
||||
0, /* n_dropped */ \
|
||||
OVS_MUTEX_INITIALIZER /* mutex */ \
|
||||
}
|
||||
|
||||
/* Configuring how each module logs messages. */
|
||||
enum vlog_level vlog_get_level(const struct vlog_module *,
|
||||
enum vlog_destination);
|
||||
void vlog_set_levels(struct vlog_module *,
|
||||
enum vlog_destination, enum vlog_level);
|
||||
char *vlog_set_levels_from_string(const char *) OVS_WARN_UNUSED_RESULT;
|
||||
void vlog_set_levels_from_string_assert(const char *);
|
||||
char *vlog_get_levels(void);
|
||||
char *vlog_get_patterns(void);
|
||||
bool vlog_is_enabled(const struct vlog_module *, enum vlog_level);
|
||||
bool vlog_should_drop(const struct vlog_module *, enum vlog_level,
|
||||
struct vlog_rate_limit *);
|
||||
void vlog_set_verbosity(const char *arg);
|
||||
|
||||
/* Configuring log destinations. */
|
||||
void vlog_set_pattern(enum vlog_destination, const char *pattern);
|
||||
int vlog_set_log_file(const char *file_name);
|
||||
int vlog_reopen_log_file(void);
|
||||
#ifndef _WIN32
|
||||
void vlog_change_owner_unix(uid_t, gid_t);
|
||||
#endif
|
||||
|
||||
/* Configure method how vlog should send messages to syslog server. */
|
||||
void vlog_set_syslog_method(const char *method);
|
||||
|
||||
/* Configure syslog target. */
|
||||
void vlog_set_syslog_target(const char *target);
|
||||
|
||||
/* Initialization. */
|
||||
void vlog_init(void);
|
||||
void vlog_enable_async(void);
|
||||
|
||||
/* Functions for actual logging. */
|
||||
void vlog(const struct vlog_module *, enum vlog_level, const char *format, ...)
|
||||
OVS_PRINTF_FORMAT (3, 4);
|
||||
void vlog_valist(const struct vlog_module *, enum vlog_level,
|
||||
const char *, va_list)
|
||||
OVS_PRINTF_FORMAT (3, 0);
|
||||
|
||||
OVS_NO_RETURN void vlog_fatal(const struct vlog_module *, const char *format, ...)
|
||||
OVS_PRINTF_FORMAT (2, 3);
|
||||
OVS_NO_RETURN void vlog_fatal_valist(const struct vlog_module *,
|
||||
const char *format, va_list)
|
||||
OVS_PRINTF_FORMAT (2, 0);
|
||||
|
||||
OVS_NO_RETURN void vlog_abort(const struct vlog_module *, const char *format, ...)
|
||||
OVS_PRINTF_FORMAT (2, 3);
|
||||
OVS_NO_RETURN void vlog_abort_valist(const struct vlog_module *,
|
||||
const char *format, va_list)
|
||||
OVS_PRINTF_FORMAT (2, 0);
|
||||
|
||||
void vlog_rate_limit(const struct vlog_module *, enum vlog_level,
|
||||
struct vlog_rate_limit *, const char *, ...)
|
||||
OVS_PRINTF_FORMAT (4, 5);
|
||||
|
||||
/* Defines a logging module whose name is MODULE, which should generally be
|
||||
* roughly the name of the source file, and makes it the module used by the
|
||||
* logging convenience macros defined below. */
|
||||
#define VLOG_DEFINE_THIS_MODULE(MODULE) \
|
||||
static struct vlog_module this_module = { \
|
||||
OVS_LIST_INITIALIZER(&this_module.list), \
|
||||
#MODULE, /* name */ \
|
||||
{ VLL_INFO, VLL_INFO, VLL_INFO }, /* levels */ \
|
||||
VLL_INFO, /* min_level */ \
|
||||
true /* honor_rate_limits */ \
|
||||
}; \
|
||||
OVS_CONSTRUCTOR(init_this_module_##MODULE) { \
|
||||
vlog_insert_module(&this_module.list); \
|
||||
} \
|
||||
\
|
||||
/* Prevent duplicate module names, via linker error. \
|
||||
* The extra "extern" declaration makes sparse happy. */ \
|
||||
extern struct vlog_module *VLM_##MODULE; \
|
||||
struct vlog_module *VLM_##MODULE = &this_module;
|
||||
|
||||
/* Macros for the current module as set up by VLOG_DEFINE_THIS_MODULE.
|
||||
* These are usually what you want to use.
|
||||
*
|
||||
* Guaranteed to preserve errno.
|
||||
*/
|
||||
#define VLOG_FATAL(...) vlog_fatal(&this_module, __VA_ARGS__)
|
||||
#define VLOG_ABORT(...) vlog_abort(&this_module, __VA_ARGS__)
|
||||
#define VLOG_EMER(...) VLOG(VLL_EMER, __VA_ARGS__)
|
||||
#define VLOG_ERR(...) VLOG(VLL_ERR, __VA_ARGS__)
|
||||
#define VLOG_WARN(...) VLOG(VLL_WARN, __VA_ARGS__)
|
||||
#define VLOG_INFO(...) VLOG(VLL_INFO, __VA_ARGS__)
|
||||
#define VLOG_DBG(...) VLOG(VLL_DBG, __VA_ARGS__)
|
||||
|
||||
/* More convenience macros, for testing whether a given level is enabled. When
|
||||
* constructing a log message is expensive, this enables it to be skipped. */
|
||||
#define VLOG_IS_ERR_ENABLED() vlog_is_enabled(&this_module, VLL_ERR)
|
||||
#define VLOG_IS_WARN_ENABLED() vlog_is_enabled(&this_module, VLL_WARN)
|
||||
#define VLOG_IS_INFO_ENABLED() vlog_is_enabled(&this_module, VLL_INFO)
|
||||
#define VLOG_IS_DBG_ENABLED() vlog_is_enabled(&this_module, VLL_DBG)
|
||||
|
||||
/* Convenience macros for rate-limiting.
|
||||
* Guaranteed to preserve errno.
|
||||
*/
|
||||
#define VLOG_ERR_RL(RL, ...) VLOG_RL(RL, VLL_ERR, __VA_ARGS__)
|
||||
#define VLOG_WARN_RL(RL, ...) VLOG_RL(RL, VLL_WARN, __VA_ARGS__)
|
||||
#define VLOG_INFO_RL(RL, ...) VLOG_RL(RL, VLL_INFO, __VA_ARGS__)
|
||||
#define VLOG_DBG_RL(RL, ...) VLOG_RL(RL, VLL_DBG, __VA_ARGS__)
|
||||
|
||||
/* Convenience macros to additionally store log message in buffer
|
||||
* Caller is responsible for freeing *ERRP afterwards */
|
||||
#define VLOG_ERR_BUF(ERRP, ...) VLOG_ERRP(ERRP, VLL_ERR, __VA_ARGS__)
|
||||
#define VLOG_WARN_BUF(ERRP, ...) VLOG_ERRP(ERRP, VLL_WARN, __VA_ARGS__)
|
||||
|
||||
#define VLOG_DROP_ERR(RL) vlog_should_drop(&this_module, VLL_ERR, RL)
|
||||
#define VLOG_DROP_WARN(RL) vlog_should_drop(&this_module, VLL_WARN, RL)
|
||||
#define VLOG_DROP_INFO(RL) vlog_should_drop(&this_module, VLL_INFO, RL)
|
||||
#define VLOG_DROP_DBG(RL) vlog_should_drop(&this_module, VLL_DBG, RL)
|
||||
|
||||
/* Macros for logging at most once per execution. */
|
||||
#define VLOG_ERR_ONCE(...) VLOG_ONCE(VLL_ERR, __VA_ARGS__)
|
||||
#define VLOG_WARN_ONCE(...) VLOG_ONCE(VLL_WARN, __VA_ARGS__)
|
||||
#define VLOG_INFO_ONCE(...) VLOG_ONCE(VLL_INFO, __VA_ARGS__)
|
||||
#define VLOG_DBG_ONCE(...) VLOG_ONCE(VLL_DBG, __VA_ARGS__)
|
||||
|
||||
/* Command line processing. */
|
||||
#define VLOG_OPTION_ENUMS \
|
||||
OPT_LOG_FILE, \
|
||||
OPT_SYSLOG_IMPL, \
|
||||
OPT_SYSLOG_TARGET
|
||||
|
||||
#define VLOG_LONG_OPTIONS \
|
||||
{"verbose", optional_argument, NULL, 'v'}, \
|
||||
{"log-file", optional_argument, NULL, OPT_LOG_FILE}, \
|
||||
{"syslog-method", required_argument, NULL, OPT_SYSLOG_IMPL}, \
|
||||
{"syslog-target", required_argument, NULL, OPT_SYSLOG_TARGET}
|
||||
|
||||
#define VLOG_OPTION_HANDLERS \
|
||||
case 'v': \
|
||||
vlog_set_verbosity(optarg); \
|
||||
break; \
|
||||
case OPT_LOG_FILE: \
|
||||
vlog_set_log_file(optarg); \
|
||||
break; \
|
||||
case OPT_SYSLOG_IMPL: \
|
||||
vlog_set_syslog_method(optarg); \
|
||||
break; \
|
||||
case OPT_SYSLOG_TARGET: \
|
||||
vlog_set_syslog_target(optarg); \
|
||||
break;
|
||||
|
||||
void vlog_usage(void);
|
||||
|
||||
/* Implementation details. */
|
||||
#define VLOG(LEVEL, ...) \
|
||||
do { \
|
||||
enum vlog_level level__ = LEVEL; \
|
||||
if (this_module.min_level >= level__) { \
|
||||
vlog(&this_module, level__, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define VLOG_RL(RL, LEVEL, ...) \
|
||||
do { \
|
||||
enum vlog_level level__ = LEVEL; \
|
||||
if (this_module.min_level >= level__) { \
|
||||
vlog_rate_limit(&this_module, level__, RL, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define VLOG_ONCE(LEVEL, ...) \
|
||||
do { \
|
||||
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; \
|
||||
if (ovsthread_once_start(&once)) { \
|
||||
vlog(&this_module, LEVEL, __VA_ARGS__); \
|
||||
ovsthread_once_done(&once); \
|
||||
} \
|
||||
} while (0)
|
||||
#define VLOG_ERRP(ERRP, LEVEL, ...) \
|
||||
do { \
|
||||
VLOG(LEVEL, __VA_ARGS__); \
|
||||
if (ERRP) { \
|
||||
*(ERRP) = xasprintf(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* vlog.h */
|
||||
Reference in New Issue
Block a user