udp: fix csum computation when offload disabled
[vpp.git] / src / vat / ip_types.c
1 /*
2  * Copyright (c) 2016 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
16 #include <vnet/ip/ip_types.h>
17 #include <vnet/ip/format.h>
18 #include <vnet/ip/ip.h>
19
20 u8 *
21 format_ip_address (u8 * s, va_list * args)
22 {
23   ip_address_t *a = va_arg (*args, ip_address_t *);
24   u8 ver = ip_addr_version (a);
25   if (ver == AF_IP4)
26     {
27       return format (s, "%U", format_ip4_address, &ip_addr_v4 (a));
28     }
29   else if (ver == AF_IP6)
30     {
31       return format (s, "%U", format_ip6_address, &ip_addr_v6 (a));
32     }
33   else
34     {
35       clib_warning ("Can't format IP version %d!", ver);
36       return 0;
37     }
38 }
39
40 uword
41 unformat_ip_address (unformat_input_t * input, va_list * args)
42 {
43   ip_address_t *a = va_arg (*args, ip_address_t *);
44   ip_address_t tmp, *p_tmp = &tmp;
45
46   clib_memset (p_tmp, 0, sizeof (*p_tmp));
47   if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (p_tmp)))
48     ip_addr_version (p_tmp) = AF_IP4;
49   else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6 (p_tmp)))
50     ip_addr_version (p_tmp) = AF_IP6;
51   else
52     return 0;
53   *a = *p_tmp;
54   return 1;
55 }
56
57 u8 *
58 format_ip_prefix (u8 * s, va_list * args)
59 {
60   ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
61   return format (s, "%U/%d", format_ip_address, &ip_prefix_addr (a),
62                  ip_prefix_len (a));
63 }
64
65 uword
66 unformat_ip_prefix (unformat_input_t * input, va_list * args)
67 {
68   ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
69   /* %d writes more than a u8 */
70   int plen;
71   if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr (a),
72                 &plen))
73     {
74       ip_prefix_len (a) = plen;
75       if ((ip_prefix_version (a) == AF_IP4 && 32 < ip_prefix_len (a)) ||
76           (ip_prefix_version (a) == AF_IP6 && 128 < ip_prefix_len (a)))
77         {
78           clib_warning ("Prefix length to big: %d!", ip_prefix_len (a));
79           return 0;
80         }
81       ip_prefix_normalize (a);
82     }
83   else
84     return 0;
85   return 1;
86 }
87
88 u16
89 ip_address_size (const ip_address_t * a)
90 {
91   switch (ip_addr_version (a))
92     {
93     case AF_IP4:
94       return sizeof (ip4_address_t);
95       break;
96     case AF_IP6:
97       return sizeof (ip6_address_t);
98       break;
99     }
100   return 0;
101 }
102
103 bool
104 ip_address_is_zero (const ip_address_t * ip)
105 {
106   switch (ip_addr_version (ip))
107     {
108     case AF_IP4:
109       return (ip_addr_v4 (ip).as_u32 == 0);
110     case AF_IP6:
111       return (ip_addr_v6 (ip).as_u64[0] == 0 &&
112               ip_addr_v6 (ip).as_u64[1] == 0);
113       break;
114     }
115   return false;
116 }
117
118 int
119 ip_address_cmp (const ip_address_t * ip1, const ip_address_t * ip2)
120 {
121   int res = 0;
122   if (ip_addr_version (ip1) != ip_addr_version (ip2))
123     return -1;
124   res = ip46_address_cmp (&ip_addr_46 (ip1), &ip_addr_46 (ip2));
125
126   if (res < 0)
127     res = 2;
128   else if (res > 0)
129     res = 1;
130
131   return res;
132 }
133
134 void
135 ip_address_copy (ip_address_t * dst, const ip_address_t * src)
136 {
137   if (AF_IP4 == ip_addr_version (src))
138     {
139       /* don't copy any garbage from the union */
140       clib_memset (dst, 0, sizeof (*dst));
141       ip_addr_v4 (dst) = ip_addr_v4 (src);
142       dst->version = AF_IP4;
143     }
144   else
145     {
146       clib_memcpy (dst, src, sizeof (ip_address_t));
147     }
148 }
149
150 u8 *
151 ip_addr_bytes (ip_address_t * ip)
152 {
153   switch (ip->version)
154     {
155     case AF_IP4:
156       return (u8 *) & ip_addr_v4 (ip);
157     case AF_IP6:
158       return (u8 *) & ip_addr_v6 (ip);
159       break;
160     }
161   ASSERT (0);
162   return (NULL);
163 }
164
165 void
166 ip_address_copy_addr (void *dst, const ip_address_t * src)
167 {
168   switch (src->version)
169     {
170     case AF_IP4:
171       clib_memcpy (dst, &ip_addr_v4 (src), ip_address_size (src));
172       break;
173     case AF_IP6:
174       clib_memcpy (dst, &ip_addr_v6 (src), ip_address_size (src));
175       break;
176     }
177 }
178
179 u16
180 ip_version_to_size (ip_address_family_t af)
181 {
182   switch (af)
183     {
184     case AF_IP4:
185       return sizeof (ip4_address_t);
186       break;
187     case AF_IP6:
188       return sizeof (ip6_address_t);
189       break;
190     }
191   return 0;
192 }
193
194 vnet_link_t
195 ip_address_family_to_link_type (ip_address_family_t af)
196 {
197   switch (af)
198     {
199     case AF_IP4:
200       return (VNET_LINK_IP4);
201     case AF_IP6:
202       return (VNET_LINK_IP6);
203     }
204   ASSERT (0);
205   return (VNET_LINK_IP4);
206 }
207
208 void
209 ip_address_set (ip_address_t *dst, const void *src,
210                 ip_address_family_t version)
211 {
212   ip_addr_version (dst) = version;
213
214   switch (version)
215     {
216     case AF_IP4:
217       ip_addr_v4 (dst) = *(ip4_address_t *) src;
218       break;
219     case AF_IP6:
220       ip_addr_v6 (dst) = *(ip6_address_t *) src;
221       break;
222     }
223 }
224
225 fib_protocol_t
226 ip_address_family_to_fib_proto (ip_address_family_t af)
227 {
228   switch (af)
229     {
230     case AF_IP4:
231       return (FIB_PROTOCOL_IP4);
232     case AF_IP6:
233       return (FIB_PROTOCOL_IP6);
234     }
235   ASSERT (0);
236   return (FIB_PROTOCOL_IP4);
237 }
238
239 ip_address_family_t
240 ip_address_family_from_fib_proto (fib_protocol_t fp)
241 {
242   switch (fp)
243     {
244     case FIB_PROTOCOL_IP4:
245       return (AF_IP4);
246     case FIB_PROTOCOL_IP6:
247       return (AF_IP6);
248     case FIB_PROTOCOL_MPLS:
249       ASSERT (0);
250     }
251   return (AF_IP4);
252 }
253
254 fib_protocol_t
255 ip_address_to_46 (const ip_address_t * addr, ip46_address_t * a)
256 {
257   *a = ip_addr_46 (addr);
258   return (ip_address_family_to_fib_proto (ip_addr_version (addr)));
259 }
260
261 void
262 ip_address_from_46 (const ip46_address_t * nh,
263                     fib_protocol_t fproto, ip_address_t * ip)
264 {
265   ip_addr_46 (ip) = *nh;
266   ip_addr_version (ip) = ip_address_family_from_fib_proto (fproto);
267 }
268
269 static void
270 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
271 {
272   u32 mask = ~0;
273
274   ASSERT (ip4);
275
276   if (32 <= preflen)
277     {
278       return;
279     }
280
281   mask = pow2_mask (preflen) << (32 - preflen);
282   mask = clib_host_to_net_u32 (mask);
283   ip4->data_u32 &= mask;
284 }
285
286 static void
287 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
288 {
289   u8 mask_6[16];
290   u32 *m;
291   u8 j, i0, i1;
292
293   ASSERT (ip6);
294
295   clib_memset (mask_6, 0, sizeof (mask_6));
296
297   if (128 <= preflen)
298     {
299       return;
300     }
301
302   i1 = preflen % 32;
303   i0 = preflen / 32;
304   m = (u32 *) & mask_6[0];
305
306   for (j = 0; j < i0; j++)
307     {
308       m[j] = ~0;
309     }
310
311   if (i1)
312     {
313       m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
314     }
315
316   for (j = 0; j < sizeof (mask_6); j++)
317     {
318       ip6->as_u8[j] &= mask_6[j];
319     }
320 }
321
322 void
323 ip_prefix_normalize (ip_prefix_t * a)
324 {
325   u8 preflen = ip_prefix_len (a);
326
327   switch (ip_prefix_version (a))
328     {
329     case AF_IP4:
330       ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
331       break;
332
333     case AF_IP6:
334       ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
335       break;
336
337     default:
338       ASSERT (0);
339     }
340 }
341
342 void
343 ip_prefix_copy (void *dst, void *src)
344 {
345   clib_memcpy (dst, src, sizeof (ip_prefix_t));
346 }
347
348 int
349 ip_prefix_cmp (const ip_prefix_t *ipp1, const ip_prefix_t *ipp2)
350 {
351   ip_prefix_t p1 = *ipp1, p2 = *ipp2;
352   int cmp = 0;
353
354   ip_prefix_normalize (&p1);
355   ip_prefix_normalize (&p2);
356
357   cmp = ip_address_cmp (&ip_prefix_addr (&p1), &ip_prefix_addr (&p2));
358   if (cmp == 0)
359     {
360       if (ip_prefix_len (&p1) < ip_prefix_len (&p2))
361         {
362           cmp = 1;
363         }
364       else
365         {
366           if (ip_prefix_len (&p1) > ip_prefix_len (&p2))
367             cmp = 2;
368         }
369     }
370   return cmp;
371 }
372
373 static bool
374 ip4_prefix_validate (const ip_prefix_t * ip)
375 {
376   ip4_address_t ip4_addr, ip4_mask;
377
378   if (ip_prefix_len (ip) > 32)
379     return (false);
380
381   ip4_addr = ip_prefix_v4 (ip);
382   ip4_preflen_to_mask (ip_prefix_len (ip), &ip4_mask);
383
384   return ((ip4_addr.as_u32 & ip4_mask.as_u32) == ip4_addr.as_u32);
385 }
386
387 static bool
388 ip6_prefix_validate (const ip_prefix_t * ip)
389 {
390   ip6_address_t ip6_addr, ip6_mask;
391
392   if (ip_prefix_len (ip) > 128)
393     return (false);
394
395   ip6_addr = ip_prefix_v6 (ip);
396   ip6_preflen_to_mask (ip_prefix_len (ip), &ip6_mask);
397
398   return (((ip6_addr.as_u64[0] & ip6_mask.as_u64[0]) == ip6_addr.as_u64[0]) &&
399           ((ip6_addr.as_u64[1] & ip6_mask.as_u64[1]) == ip6_addr.as_u64[1]));
400 }
401
402 bool
403 ip_prefix_validate (const ip_prefix_t * ip)
404 {
405   switch (ip_prefix_version (ip))
406     {
407     case AF_IP4:
408       return (ip4_prefix_validate (ip));
409     case AF_IP6:
410       return (ip6_prefix_validate (ip));
411     }
412   ASSERT (0);
413   return (false);
414 }
415
416 void
417 ip4_address_normalize (ip4_address_t * ip4, u8 preflen)
418 {
419   ASSERT (preflen <= 32);
420   if (preflen == 0)
421     ip4->data_u32 = 0;
422   else
423     ip4->data_u32 &= clib_net_to_host_u32 (0xffffffff << (32 - preflen));
424 }
425
426 void
427 ip6_address_normalize (ip6_address_t * ip6, u8 preflen)
428 {
429   ASSERT (preflen <= 128);
430   if (preflen == 0)
431     {
432       ip6->as_u64[0] = 0;
433       ip6->as_u64[1] = 0;
434     }
435   else if (preflen <= 64)
436     {
437       ip6->as_u64[0] &=
438         clib_host_to_net_u64 (0xffffffffffffffffL << (64 - preflen));
439       ip6->as_u64[1] = 0;
440     }
441   else
442     ip6->as_u64[1] &=
443       clib_host_to_net_u64 (0xffffffffffffffffL << (128 - preflen));
444 }
445
446 void
447 ip4_preflen_to_mask (u8 pref_len, ip4_address_t * ip)
448 {
449   if (pref_len == 0)
450     ip->as_u32 = 0;
451   else
452     ip->as_u32 = clib_host_to_net_u32 (~((1 << (32 - pref_len)) - 1));
453 }
454
455 u32
456 ip4_mask_to_preflen (ip4_address_t * mask)
457 {
458   if (mask->as_u32 == 0)
459     return 0;
460   return (32 - log2_first_set (clib_net_to_host_u32 (mask->as_u32)));
461 }
462
463 void
464 ip4_prefix_max_address_host_order (ip4_address_t * ip, u8 plen,
465                                    ip4_address_t * res)
466 {
467   u32 not_mask;
468   not_mask = (1 << (32 - plen)) - 1;
469   res->as_u32 = clib_net_to_host_u32 (ip->as_u32) + not_mask;
470 }
471
472 void
473 ip6_preflen_to_mask (u8 pref_len, ip6_address_t * mask)
474 {
475   if (pref_len == 0)
476     {
477       mask->as_u64[0] = 0;
478       mask->as_u64[1] = 0;
479     }
480   else if (pref_len <= 64)
481     {
482       mask->as_u64[0] =
483         clib_host_to_net_u64 (0xffffffffffffffffL << (64 - pref_len));
484       mask->as_u64[1] = 0;
485     }
486   else
487     {
488       mask->as_u64[0] = 0xffffffffffffffffL;
489       mask->as_u64[1] =
490         clib_host_to_net_u64 (0xffffffffffffffffL << (128 - pref_len));
491     }
492 }
493
494 void
495 ip6_prefix_max_address_host_order (ip6_address_t * ip, u8 plen,
496                                    ip6_address_t * res)
497 {
498   u64 not_mask;
499   if (plen == 0)
500     {
501       res->as_u64[0] = 0xffffffffffffffffL;
502       res->as_u64[1] = 0xffffffffffffffffL;
503     }
504   else if (plen <= 64)
505     {
506       not_mask = ((u64) 1 << (64 - plen)) - 1;
507       res->as_u64[0] = clib_net_to_host_u64 (ip->as_u64[0]) + not_mask;
508       res->as_u64[1] = 0xffffffffffffffffL;
509     }
510   else
511     {
512       not_mask = ((u64) 1 << (128 - plen)) - 1;
513       res->as_u64[1] = clib_net_to_host_u64 (ip->as_u64[1]) + not_mask;
514     }
515 }
516
517 u32
518 ip6_mask_to_preflen (ip6_address_t * mask)
519 {
520   if (mask->as_u64[1] != 0)
521     return 128 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[1]));
522   if (mask->as_u64[0] != 0)
523     return 64 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[0]));
524   return 0;
525 }
526
527 /*
528  * fd.io coding-style-patch-verification: ON
529  *
530  * Local Variables:
531  * eval: (c-set-style "gnu")
532  * End:
533  */