323cf4d456cc4dfd97095e4b185c16d6de12f622
[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_to_prefix (const ip_address_t *addr, ip_prefix_t *prefix)
292 {
293   prefix->len = (addr->version == AF_IP4 ? 32 : 128);
294   clib_memcpy (&prefix->addr, addr, sizeof (prefix->addr));
295 }
296
297 void
298 ip_address_increment (ip_address_t * ip)
299 {
300   ip46_address_increment ((ip_addr_version (ip) == AF_IP4 ?
301                            IP46_TYPE_IP4 : IP46_TYPE_IP6), &ip_addr_46 (ip));
302 }
303
304 void
305 ip_address_reset (ip_address_t * ip)
306 {
307   clib_memset (ip, 0, sizeof (*ip));
308 }
309
310 static void
311 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
312 {
313   u32 mask = ~0;
314
315   ASSERT (ip4);
316
317   if (32 <= preflen)
318     {
319       return;
320     }
321
322   mask = pow2_mask (preflen) << (32 - preflen);
323   mask = clib_host_to_net_u32 (mask);
324   ip4->data_u32 &= mask;
325 }
326
327 static void
328 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
329 {
330   u8 mask_6[16];
331   u32 *m;
332   u8 j, i0, i1;
333
334   ASSERT (ip6);
335
336   clib_memset (mask_6, 0, sizeof (mask_6));
337
338   if (128 <= preflen)
339     {
340       return;
341     }
342
343   i1 = preflen % 32;
344   i0 = preflen / 32;
345   m = (u32 *) & mask_6[0];
346
347   for (j = 0; j < i0; j++)
348     {
349       m[j] = ~0;
350     }
351
352   if (i1)
353     {
354       m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
355     }
356
357   for (j = 0; j < sizeof (mask_6); j++)
358     {
359       ip6->as_u8[j] &= mask_6[j];
360     }
361 }
362
363 void
364 ip_prefix_normalize (ip_prefix_t * a)
365 {
366   u8 preflen = ip_prefix_len (a);
367
368   switch (ip_prefix_version (a))
369     {
370     case AF_IP4:
371       ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
372       break;
373
374     case AF_IP6:
375       ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
376       break;
377
378     default:
379       ASSERT (0);
380     }
381 }
382
383 void
384 ip_prefix_copy (void *dst, void *src)
385 {
386   clib_memcpy (dst, src, sizeof (ip_prefix_t));
387 }
388
389 int
390 ip_prefix_cmp (const ip_prefix_t *ipp1, const ip_prefix_t *ipp2)
391 {
392   ip_prefix_t p1 = *ipp1, p2 = *ipp2;
393   int cmp = 0;
394
395   ip_prefix_normalize (&p1);
396   ip_prefix_normalize (&p2);
397
398   cmp = ip_address_cmp (&ip_prefix_addr (&p1), &ip_prefix_addr (&p2));
399   if (cmp == 0)
400     {
401       if (ip_prefix_len (&p1) < ip_prefix_len (&p2))
402         {
403           cmp = 1;
404         }
405       else
406         {
407           if (ip_prefix_len (&p1) > ip_prefix_len (&p2))
408             cmp = 2;
409         }
410     }
411   return cmp;
412 }
413
414 /**
415  * convert from a LISP to a FIB prefix
416  */
417 void
418 ip_prefix_to_fib_prefix (const ip_prefix_t * ip_prefix,
419                          fib_prefix_t * fib_prefix)
420 {
421   ip_address_to_fib_prefix (&ip_prefix->addr, fib_prefix);
422   fib_prefix->fp_len = ip_prefix->len;
423 }
424
425 static bool
426 ip4_prefix_validate (const ip_prefix_t * ip)
427 {
428   ip4_address_t ip4_addr, ip4_mask;
429
430   if (ip_prefix_len (ip) > 32)
431     return (false);
432
433   ip4_addr = ip_prefix_v4 (ip);
434   ip4_preflen_to_mask (ip_prefix_len (ip), &ip4_mask);
435
436   return ((ip4_addr.as_u32 & ip4_mask.as_u32) == ip4_addr.as_u32);
437 }
438
439 static bool
440 ip6_prefix_validate (const ip_prefix_t * ip)
441 {
442   ip6_address_t ip6_addr, ip6_mask;
443
444   if (ip_prefix_len (ip) > 128)
445     return (false);
446
447   ip6_addr = ip_prefix_v6 (ip);
448   ip6_preflen_to_mask (ip_prefix_len (ip), &ip6_mask);
449
450   return (((ip6_addr.as_u64[0] & ip6_mask.as_u64[0]) == ip6_addr.as_u64[0]) &&
451           ((ip6_addr.as_u64[1] & ip6_mask.as_u64[1]) == ip6_addr.as_u64[1]));
452 }
453
454 bool
455 ip_prefix_validate (const ip_prefix_t * ip)
456 {
457   switch (ip_prefix_version (ip))
458     {
459     case AF_IP4:
460       return (ip4_prefix_validate (ip));
461     case AF_IP6:
462       return (ip6_prefix_validate (ip));
463     }
464   ASSERT (0);
465   return (false);
466 }
467
468 void
469 ip4_address_normalize (ip4_address_t * ip4, u8 preflen)
470 {
471   ASSERT (preflen <= 32);
472   if (preflen == 0)
473     ip4->data_u32 = 0;
474   else
475     ip4->data_u32 &= clib_net_to_host_u32 (0xffffffff << (32 - preflen));
476 }
477
478 void
479 ip6_address_normalize (ip6_address_t * ip6, u8 preflen)
480 {
481   ASSERT (preflen <= 128);
482   if (preflen == 0)
483     {
484       ip6->as_u64[0] = 0;
485       ip6->as_u64[1] = 0;
486     }
487   else if (preflen <= 64)
488     {
489       ip6->as_u64[0] &=
490         clib_host_to_net_u64 (0xffffffffffffffffL << (64 - preflen));
491       ip6->as_u64[1] = 0;
492     }
493   else
494     ip6->as_u64[1] &=
495       clib_host_to_net_u64 (0xffffffffffffffffL << (128 - preflen));
496 }
497
498 void
499 ip4_preflen_to_mask (u8 pref_len, ip4_address_t * ip)
500 {
501   if (pref_len == 0)
502     ip->as_u32 = 0;
503   else
504     ip->as_u32 = clib_host_to_net_u32 (~((1 << (32 - pref_len)) - 1));
505 }
506
507 u32
508 ip4_mask_to_preflen (ip4_address_t * mask)
509 {
510   if (mask->as_u32 == 0)
511     return 0;
512   return (32 - log2_first_set (clib_net_to_host_u32 (mask->as_u32)));
513 }
514
515 void
516 ip4_prefix_max_address_host_order (ip4_address_t * ip, u8 plen,
517                                    ip4_address_t * res)
518 {
519   u32 not_mask;
520   not_mask = (1 << (32 - plen)) - 1;
521   res->as_u32 = clib_net_to_host_u32 (ip->as_u32) + not_mask;
522 }
523
524 void
525 ip6_preflen_to_mask (u8 pref_len, ip6_address_t * mask)
526 {
527   if (pref_len == 0)
528     {
529       mask->as_u64[0] = 0;
530       mask->as_u64[1] = 0;
531     }
532   else if (pref_len <= 64)
533     {
534       mask->as_u64[0] =
535         clib_host_to_net_u64 (0xffffffffffffffffL << (64 - pref_len));
536       mask->as_u64[1] = 0;
537     }
538   else
539     {
540       mask->as_u64[0] = 0xffffffffffffffffL;
541       mask->as_u64[1] =
542         clib_host_to_net_u64 (0xffffffffffffffffL << (128 - pref_len));
543     }
544 }
545
546 void
547 ip6_prefix_max_address_host_order (ip6_address_t * ip, u8 plen,
548                                    ip6_address_t * res)
549 {
550   u64 not_mask;
551   if (plen == 0)
552     {
553       res->as_u64[0] = 0xffffffffffffffffL;
554       res->as_u64[1] = 0xffffffffffffffffL;
555     }
556   else if (plen <= 64)
557     {
558       not_mask = ((u64) 1 << (64 - plen)) - 1;
559       res->as_u64[0] = clib_net_to_host_u64 (ip->as_u64[0]) + not_mask;
560       res->as_u64[1] = 0xffffffffffffffffL;
561     }
562   else
563     {
564       not_mask = ((u64) 1 << (128 - plen)) - 1;
565       res->as_u64[1] = clib_net_to_host_u64 (ip->as_u64[1]) + not_mask;
566     }
567 }
568
569 u32
570 ip6_mask_to_preflen (ip6_address_t * mask)
571 {
572   if (mask->as_u64[1] != 0)
573     return 128 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[1]));
574   if (mask->as_u64[0] != 0)
575     return 64 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[0]));
576   return 0;
577 }
578
579 /*
580  * fd.io coding-style-patch-verification: ON
581  *
582  * Local Variables:
583  * eval: (c-set-style "gnu")
584  * End:
585  */