Hybrid ICN (hICN) plugin  v21.06-rc0-4-g18fa668
common.h
1 /*
2  * Copyright (c) 2017-2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
33 #ifndef HICN_COMMON_H
34 #define HICN_COMMON_H
35 
36 #include <stdint.h>
37 #include <assert.h>
38 
39 /* Concise type definitions */
40 
41 typedef uint64_t u64;
42 typedef uint32_t u32;
43 typedef uint16_t u16;
44 typedef uint8_t u8;
45 
46 /*
47  * Code annotations
48  *
49  * NOTE: these are defined by default in VPP.
50  */
51 
52 #ifndef HICN_VPP_PLUGIN
53 
54 #define PREDICT_FALSE(x) (x)
55 #define PREDICT_TRUE(x) (x)
56 #define always_inline static inline
57 #define static_always_inline static inline
58 #define STRUCT_SIZE_OF(type, member) sizeof(((type *)0)->member)
59 #define ASSERT
60 
61 #define STATIC_ASSERT(x)
62 
63 /* Architecture-dependent uword size */
64 #if INTPTR_MAX == INT64_MAX
65 #define log2_uword_bits 6
66 #elif INTPTR_MAX == INT32_MAX
67 #define log2_uword_bits 5
68 #else
69 #error "Impossible to detect architecture"
70 #endif
71 
72 #define uword_bits (1 << log2_uword_bits)
73 
74 /* Word types. */
75 #if uword_bits == 64
76 /* 64 bit word machines. */
77 typedef u64 uword;
78 #else
79 /* 32 bit word machines. */
80 typedef u32 uword;
81 #endif
82 
83 typedef uword ip_csum_t;
84 
85 #endif /* ! HICN_VPP_PLUGIN */
86 
87 /*
88  * Windows compilers do not support named initilizers when .h files are included
89  * inside C++ files. For readability, we either use the following macro, or
90  * duplicate some code, with the intent of preserving those safeguards for
91  * non-Windows platforms.
92  */
93 #ifndef _WIN32
94 #define ATTR_INIT(key, value) .key = value
95 #else
96 #define ATTR_INIT(key, value) value
97 #endif
98 
99 #ifdef _WIN32
100  /* Endianness detection for Windows platforms */
101 #define __ORDER_LITTLE_ENDIAN__ 0x41424344UL
102 #define __ORDER_BIG_ENDIAN__ 0x44434241UL
103 #define __BYTE_ORDER__ ('ABCD')
104 
105  /* Windows compatibility headers */
106 #define WIN32_LEAN_AND_MEAN
107 #ifndef NOMINMAX
108 #define NOMINMAX
109 #endif
110 #include <windows.h>
111 #include <winsock2.h>
112 #include <ws2ipdef.h>
113 #include <Ws2tcpip.h>
114 #include <In6addr.h>
115 
116 #define strdup _strdup
117 #define __attribute__(A)
118 
119 #ifndef IOVEC
120 #define IOVEC
121 #define UIO_MAXIOV 16
122 #define IOV_MAX UIO_MAXIOV
123 struct iovec
124 {
125  void *iov_base;
126  size_t iov_len;
127 };
128 #endif
129 #endif
130 
131 /*
132  * Portable attribute packed.
133  */
134 #ifndef _WIN32
135 #define PACKED( __Declaration__ ) __Declaration__ __attribute__((__packed__))
136 #else
137 #define PACKED( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )
138 #endif
139 
140 
141 /*
142  * IP address types
143  */
144 
145 #ifdef HICN_VPP_PLUGIN
146 
147 #include <vnet/ip/ip4_packet.h> // ip4_address_t
148 #include <vnet/ip/ip6_packet.h> // ip6_address_t
149 
150 #if __GNUC__ >= 9
151 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
152 #endif
153 
154 #include <vnet/ip/ip46_address.h>
155 
156 #if __GNUC__ >= 9
157 #pragma GCC diagnostic pop
158 #endif
159 
160 #else
161 
162 
163 #ifndef _WIN32
164 #include <netinet/in.h>
165 #endif
166 
167 typedef union
168 {
169  u32 as_u32;
170  struct in_addr as_inaddr;
171 } ip4_address_t;
172 
173 typedef union
174 {
175  u64 as_u64[2];
176  u32 as_u32[4];
177  u8 as_u8[16];
178  struct in6_addr as_in6addr;
179 } ip6_address_t;
180 
181 typedef union
182 {
183  struct
184  {
185  u32 pad[3];
186  ip4_address_t ip4;
187  };
188  ip6_address_t ip6;
190 
191 #define ip46_address_is_ip4(ip46) (((ip46)->pad[0] | (ip46)->pad[1] | (ip46)->pad[2]) == 0)
192 
193 #endif /* ! HICN_VPP_PLUGIN */
194 
200 int get_addr_family (const char *ip_address);
201 
202 /*
203  * Checksum computation
204  *
205  * NOTE: VPP provides efficient (incremental) checksum computations
206  * that we reuse, and provide alternative implementation otherwise.
207  */
208 
209 #ifndef HICN_VPP_PLUGIN
210 
211 /*
212  * Checksum update (incremental and non-incremental)
213  *
214  * Those functions are already defined in VPP in vnet/ip/ip_packet.h, and we
215  * borrow this code here.
216  */
217 
218 static_always_inline u16
219 ip_csum_fold (ip_csum_t c)
220 {
221  /* Reduce to 16 bits. */
222 #if uword_bits == 64
223  c = (c & (ip_csum_t) 0xffffffff) + (c >> (ip_csum_t) 32);
224  c = (c & 0xffff) + (c >> 16);
225 #endif
226 
227  c = (c & 0xffff) + (c >> 16);
228  c = (c & 0xffff) + (c >> 16);
229 
230  return (u16)c;
231 }
232 
233 static_always_inline ip_csum_t
234 ip_csum_with_carry (ip_csum_t sum, ip_csum_t x)
235 {
236  ip_csum_t t = sum + x;
237  return t + (t < x);
238 }
239 
240 /* Update checksum changing field at even byte offset from x -> 0. */
241 static_always_inline ip_csum_t
242 ip_csum_add_even (ip_csum_t c, ip_csum_t x)
243 {
244  ip_csum_t d;
245 
246  d = c - x;
247 
248  /* Fold in carry from high bit. */
249  d -= d > c;
250 
251  return d;
252 }
253 
254 /* Update checksum changing field at even byte offset from 0 -> x. */
255 static_always_inline ip_csum_t
256 ip_csum_sub_even (ip_csum_t c, ip_csum_t x)
257 {
258  return ip_csum_with_carry (c, x);
259 }
260 
261 u32 cumulative_hash32 (const void *data, size_t len, u32 lastValue);
262 u32 hash32 (const void *data, size_t len);
263 u64 cumulative_hash64 (const void *data, size_t len, u64 lastValue);
264 u64 hash64 (const void *data, size_t len);
265 void hicn_packet_dump (const uint8_t * buffer, size_t len);
266 
267 #endif /* ! HICN_VPP_PLUGIN */
268 
276 always_inline u16
277 csum (const void *addr, size_t size, u16 init)
278 {
279  u32 sum = init;
280  const u16 *bytes = (u16 *) addr;
281 
282  while (size > 1)
283  {
284  sum += *bytes++;
285  size -= sizeof (u16);
286  }
287  if (size)
288  {
289  sum += *(const u8 *) bytes;
290  }
291  sum = (sum >> 16) + (sum & 0xffff);
292  sum += (sum >> 16);
293 
294  return (u16) ~ sum;
295 }
296 
297 /*
298  * Useful aliases
299  */
300 
301 /* Symmetry with IPPROTO_ICMPV6 */
302 #define IPPROTO_ICMPV4 IPPROTO_ICMP
303 
304 /*
305  * Query IP version from packet (either 4 or 6)
306  * (version is located as same offsets in both protocol headers)
307  */
308 #define HICN_IP_VERSION(packet) ((hicn_header_t *)packet)->v4.ip.version
309 
310 /*
311  * ntohll / htonll allows byte swapping for 64 bits integers
312  */
313 #ifndef htonll
314 #define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
315 #endif
316 
317 #ifndef ntohll
318 #define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
319 #endif
320 
321 #endif /* HICN_COMMON_H */
322 
323 /*
324  * fd.io coding-style-patch-verification: ON
325  *
326  * Local Variables:
327  * eval: (c-set-style "gnu")
328  * End:
329  */
ip6_address_t
Definition: common.h:173
ip4_address_t
Definition: common.h:167
iovec
Definition: windows_utils.h:33
ip46_address_t
Definition: common.h:181