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