openflow build environment setup

This commit is contained in:
2025-11-11 16:45:43 +08:00
parent be0a7ad9b3
commit 50ecb9a23f
2767 changed files with 62766 additions and 649828 deletions

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

File diff suppressed because it is too large Load Diff

View 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 */

File diff suppressed because it is too large Load Diff

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

File diff suppressed because it is too large Load Diff

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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

View 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 */

View 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 */

View 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 */

View 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 */