]> git.proxmox.com Git - mirror_ovs.git/blob - include/openvswitch/types.h
unaligned: Introduce helpers for 32-bit aligned 128-bit integers.
[mirror_ovs.git] / include / openvswitch / types.h
1 /*
2 * Copyright (c) 2010, 2011, 2013, 2014, 2016, 2017 Nicira, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef OPENVSWITCH_TYPES_H
18 #define OPENVSWITCH_TYPES_H 1
19
20 #include <sys/types.h>
21 #include <stdint.h>
22 #include "openvswitch/compiler.h"
23
24 #ifdef __CHECKER__
25 #define OVS_BITWISE __attribute__((bitwise))
26 #define OVS_FORCE __attribute__((force))
27 #else
28 #define OVS_BITWISE
29 #define OVS_FORCE
30 #endif
31
32 /* The ovs_be<N> types indicate that an object is in big-endian, not
33 * native-endian, byte order. They are otherwise equivalent to uint<N>_t. */
34 typedef uint16_t OVS_BITWISE ovs_be16;
35 typedef uint32_t OVS_BITWISE ovs_be32;
36 typedef uint64_t OVS_BITWISE ovs_be64;
37
38 #define OVS_BE16_MAX ((OVS_FORCE ovs_be16) 0xffff)
39 #define OVS_BE32_MAX ((OVS_FORCE ovs_be32) 0xffffffff)
40 #define OVS_BE64_MAX ((OVS_FORCE ovs_be64) 0xffffffffffffffffULL)
41 \f
42 /* These types help with a few funny situations:
43 *
44 * - The Ethernet header is 14 bytes long, which misaligns everything after
45 * that. One can put 2 "shim" bytes before the Ethernet header, but this
46 * helps only if there is exactly one Ethernet header. If there are two,
47 * as with GRE and VXLAN (and if the inner header doesn't use this
48 * trick--GRE and VXLAN don't) then you have the choice of aligning the
49 * inner data or the outer data. So it seems better to treat 32-bit fields
50 * in protocol headers as aligned only on 16-bit boundaries.
51 *
52 * - ARP headers contain misaligned 32-bit fields.
53 *
54 * - Netlink and OpenFlow contain 64-bit values that are only guaranteed to
55 * be aligned on 32-bit boundaries.
56 *
57 * lib/unaligned.h has helper functions for accessing these. */
58
59 /* A 32-bit value, in host byte order, that is only aligned on a 16-bit
60 * boundary. */
61 typedef struct {
62 #ifdef WORDS_BIGENDIAN
63 uint16_t hi, lo;
64 #else
65 uint16_t lo, hi;
66 #endif
67 } ovs_16aligned_u32;
68
69 /* A 32-bit value, in network byte order, that is only aligned on a 16-bit
70 * boundary. */
71 typedef struct {
72 ovs_be16 hi, lo;
73 } ovs_16aligned_be32;
74
75 /* A 64-bit value, in host byte order, that is only aligned on a 32-bit
76 * boundary. */
77 typedef struct {
78 #ifdef WORDS_BIGENDIAN
79 uint32_t hi, lo;
80 #else
81 uint32_t lo, hi;
82 #endif
83 } ovs_32aligned_u64;
84
85 /* A 128-bit value, in host byte order, that is only aligned on a 32-bit
86 * boundary. */
87 typedef struct {
88 uint32_t u32[4];
89 } ovs_32aligned_u128;
90
91 /* A 128-bit value, in network byte order, that is only aligned on a 32-bit
92 * boundary. */
93 typedef struct {
94 ovs_be32 be32[4];
95 } ovs_32aligned_be128;
96
97 typedef union {
98 uint32_t u32[4];
99 struct {
100 #ifdef WORDS_BIGENDIAN
101 uint64_t hi, lo;
102 #else
103 uint64_t lo, hi;
104 #endif
105 } u64;
106 } ovs_u128;
107
108 typedef union {
109 ovs_be32 be32[4];
110 struct {
111 ovs_be64 hi, lo;
112 } be64;
113 } ovs_be128;
114
115 /* MSVC2015 doesn't support designated initializers when compiling C++,
116 * and doesn't support ternary operators with non-designated initializers.
117 * So we use these static definitions rather than using initializer macros. */
118 static const ovs_u128 OVS_U128_ZERO = { { 0, 0, 0, 0 } };
119 static const ovs_u128 OVS_U128_MAX = { { UINT32_MAX, UINT32_MAX,
120 UINT32_MAX, UINT32_MAX } };
121 static const ovs_be128 OVS_BE128_MAX OVS_UNUSED = { { OVS_BE32_MAX, OVS_BE32_MAX,
122 OVS_BE32_MAX, OVS_BE32_MAX } };
123 static const ovs_u128 OVS_U128_MIN OVS_UNUSED = { {0, 0, 0, 0} };
124 static const ovs_u128 OVS_BE128_MIN OVS_UNUSED = { {0, 0, 0, 0} };
125
126 #define OVS_U128_ZERO OVS_U128_MIN
127
128 /* A 64-bit value, in network byte order, that is only aligned on a 32-bit
129 * boundary. */
130 typedef struct {
131 ovs_be32 hi, lo;
132 } ovs_32aligned_be64;
133
134 /* Port numbers
135 * ------------
136 *
137 * None of these types are directly interchangeable, hence the OVS_BITWISE
138 * annotation.
139 *
140 * ofp_port_t is an OpenFlow 1.0 port number. It uses a 16-bit range, even
141 * though it is a 32-bit type. This allows it to be overlaid on an odp_port_t
142 * for a few situations where this is useful, e.g. in union flow_in_port.
143 *
144 * ofp11_port_t is an OpenFlow-1.1 port number.
145 *
146 * odp_port_t is a port number within a datapath (e.g. see lib/dpif.h).
147 */
148 typedef uint32_t OVS_BITWISE ofp_port_t;
149 typedef uint32_t OVS_BITWISE odp_port_t;
150 typedef uint32_t OVS_BITWISE ofp11_port_t;
151
152 /* Macro functions that cast int types to ofp/odp/ofp11 types. */
153 #define OFP_PORT_C(X) ((OVS_FORCE ofp_port_t) (X))
154 #define ODP_PORT_C(X) ((OVS_FORCE odp_port_t) (X))
155 #define OFP11_PORT_C(X) ((OVS_FORCE ofp11_port_t) (X))
156
157 /* Using this struct instead of a bare array makes an ethernet address field
158 * assignable. The size of the array is also part of the type, so it is easier
159 * to deal with. */
160 struct eth_addr {
161 union {
162 uint8_t ea[6];
163 ovs_be16 be16[3];
164 };
165 };
166
167 /* Similar to struct eth_addr, for EUI-64 addresses. */
168 struct eth_addr64 {
169 union {
170 uint8_t ea64[8];
171 ovs_be16 be16[4];
172 };
173 };
174
175 #endif /* openvswitch/types.h */