ipsec: Support MPLS over IPSec[46] interface
[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
207 void
208 ip_address_set (ip_address_t * dst, const void *src, u8 version)
209 {
210   ip_addr_version (dst) = version;
211
212   switch (version)
213     {
214     case AF_IP4:
215       ip_addr_v4 (dst) = *(ip4_address_t *) src;
216       break;
217     case AF_IP6:
218       ip_addr_v6 (dst) = *(ip6_address_t *) src;
219       break;
220     }
221 }
222
223 fib_protocol_t
224 ip_address_family_to_fib_proto (ip_address_family_t af)
225 {
226   switch (af)
227     {
228     case AF_IP4:
229       return (FIB_PROTOCOL_IP4);
230     case AF_IP6:
231       return (FIB_PROTOCOL_IP6);
232     }
233   ASSERT (0);
234   return (FIB_PROTOCOL_IP4);
235 }
236
237 ip_address_family_t
238 ip_address_family_from_fib_proto (fib_protocol_t fp)
239 {
240   switch (fp)
241     {
242     case FIB_PROTOCOL_IP4:
243       return (AF_IP4);
244     case FIB_PROTOCOL_IP6:
245       return (AF_IP6);
246     case FIB_PROTOCOL_MPLS:
247       ASSERT (0);
248     }
249   return (AF_IP4);
250 }
251
252 fib_protocol_t
253 ip_address_to_46 (const ip_address_t * addr, ip46_address_t * a)
254 {
255   *a = ip_addr_46 (addr);
256   return (ip_address_family_to_fib_proto (ip_addr_version (addr)));
257 }
258
259 void
260 ip_address_from_46 (const ip46_address_t * nh,
261                     fib_protocol_t fproto, ip_address_t * ip)
262 {
263   ip_addr_46 (ip) = *nh;
264   ip_addr_version (ip) = ip_address_family_from_fib_proto (fproto);
265 }
266
267 /**
268  * convert from a IP address to a FIB prefix
269  */
270 void
271 ip_address_to_fib_prefix (const ip_address_t * addr, fib_prefix_t * prefix)
272 {
273   if (addr->version == AF_IP4)
274     {
275       prefix->fp_len = 32;
276       prefix->fp_proto = FIB_PROTOCOL_IP4;
277       clib_memset (&prefix->fp_addr.pad, 0, sizeof (prefix->fp_addr.pad));
278       memcpy (&prefix->fp_addr.ip4, &addr->ip.ip4,
279               sizeof (prefix->fp_addr.ip4));
280     }
281   else
282     {
283       prefix->fp_len = 128;
284       prefix->fp_proto = FIB_PROTOCOL_IP6;
285       memcpy (&prefix->fp_addr.ip6, &addr->ip.ip6,
286               sizeof (prefix->fp_addr.ip6));
287     }
288   prefix->___fp___pad = 0;
289 }
290
291 void
292 ip_address_increment (ip_address_t * ip)
293 {
294   ip46_address_increment ((ip_addr_version (ip) == AF_IP4 ?
295                            IP46_TYPE_IP4 : IP46_TYPE_IP6), &ip_addr_46 (ip));
296 }
297
298 void
299 ip_address_reset (ip_address_t * ip)
300 {
301   clib_memset (ip, 0, sizeof (*ip));
302 }
303
304 static void
305 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
306 {
307   u32 mask = ~0;
308
309   ASSERT (ip4);
310
311   if (32 <= preflen)
312     {
313       return;
314     }
315
316   mask = pow2_mask (preflen) << (32 - preflen);
317   mask = clib_host_to_net_u32 (mask);
318   ip4->data_u32 &= mask;
319 }
320
321 static void
322 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
323 {
324   u8 mask_6[16];
325   u32 *m;
326   u8 j, i0, i1;
327
328   ASSERT (ip6);
329
330   clib_memset (mask_6, 0, sizeof (mask_6));
331
332   if (128 <= preflen)
333     {
334       return;
335     }
336
337   i1 = preflen % 32;
338   i0 = preflen / 32;
339   m = (u32 *) & mask_6[0];
340
341   for (j = 0; j < i0; j++)
342     {
343       m[j] = ~0;
344     }
345
346   if (i1)
347     {
348       m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
349     }
350
351   for (j = 0; j < sizeof (mask_6); j++)
352     {
353       ip6->as_u8[j] &= mask_6[j];
354     }
355 }
356
357 void
358 ip_prefix_normalize (ip_prefix_t * a)
359 {
360   u8 preflen = ip_prefix_len (a);
361
362   switch (ip_prefix_version (a))
363     {
364     case AF_IP4:
365       ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
366       break;
367
368     case AF_IP6:
369       ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
370       break;
371
372     default:
373       ASSERT (0);
374     }
375 }
376
377 void
378 ip_prefix_copy (void *dst, void *src)
379 {
380   clib_memcpy (dst, src, sizeof (ip_prefix_t));
381 }
382
383 int
384 ip_prefix_cmp (ip_prefix_t * p1, ip_prefix_t * p2)
385 {
386   int cmp = 0;
387
388   ip_prefix_normalize (p1);
389   ip_prefix_normalize (p2);
390
391   cmp = ip_address_cmp (&ip_prefix_addr (p1), &ip_prefix_addr (p2));
392   if (cmp == 0)
393     {
394       if (ip_prefix_len (p1) < ip_prefix_len (p2))
395         {
396           cmp = 1;
397         }
398       else
399         {
400           if (ip_prefix_len (p1) > ip_prefix_len (p2))
401             cmp = 2;
402         }
403     }
404   return cmp;
405 }
406
407 /**
408  * convert from a LISP to a FIB prefix
409  */
410 void
411 ip_prefix_to_fib_prefix (const ip_prefix_t * ip_prefix,
412                          fib_prefix_t * fib_prefix)
413 {
414   ip_address_to_fib_prefix (&ip_prefix->addr, fib_prefix);
415   fib_prefix->fp_len = ip_prefix->len;
416 }
417
418 static bool
419 ip4_prefix_validate (const ip_prefix_t * ip)
420 {
421   ip4_address_t ip4_addr, ip4_mask;
422
423   if (ip_prefix_len (ip) > 32)
424     return (false);
425
426   ip4_addr = ip_prefix_v4 (ip);
427   ip4_preflen_to_mask (ip_prefix_len (ip), &ip4_mask);
428
429   return ((ip4_addr.as_u32 & ip4_mask.as_u32) == ip4_addr.as_u32);
430 }
431
432 static bool
433 ip6_prefix_validate (const ip_prefix_t * ip)
434 {
435   ip6_address_t ip6_addr, ip6_mask;
436
437   if (ip_prefix_len (ip) > 128)
438     return (false);
439
440   ip6_addr = ip_prefix_v6 (ip);
441   ip6_preflen_to_mask (ip_prefix_len (ip), &ip6_mask);
442
443   return (((ip6_addr.as_u64[0] & ip6_mask.as_u64[0]) == ip6_addr.as_u64[0]) &&
444           ((ip6_addr.as_u64[1] & ip6_mask.as_u64[1]) == ip6_addr.as_u64[1]));
445 }
446
447 bool
448 ip_prefix_validate (const ip_prefix_t * ip)
449 {
450   switch (ip_prefix_version (ip))
451     {
452     case AF_IP4:
453       return (ip4_prefix_validate (ip));
454     case AF_IP6:
455       return (ip6_prefix_validate (ip));
456     }
457   ASSERT (0);
458   return (false);
459 }
460
461 void
462 ip4_address_normalize (ip4_address_t * ip4, u8 preflen)
463 {
464   ASSERT (preflen <= 32);
465   if (preflen == 0)
466     ip4->data_u32 = 0;
467   else
468     ip4->data_u32 &= clib_net_to_host_u32 (0xffffffff << (32 - preflen));
469 }
470
471 void
472 ip6_address_normalize (ip6_address_t * ip6, u8 preflen)
473 {
474   ASSERT (preflen <= 128);
475   if (preflen == 0)
476     {
477       ip6->as_u64[0] = 0;
478       ip6->as_u64[1] = 0;
479     }
480   else if (preflen <= 64)
481     {
482       ip6->as_u64[0] &=
483         clib_host_to_net_u64 (0xffffffffffffffffL << (64 - preflen));
484       ip6->as_u64[1] = 0;
485     }
486   else
487     ip6->as_u64[1] &=
488       clib_host_to_net_u64 (0xffffffffffffffffL << (128 - preflen));
489 }
490
491 void
492 ip4_preflen_to_mask (u8 pref_len, ip4_address_t * ip)
493 {
494   if (pref_len == 0)
495     ip->as_u32 = 0;
496   else
497     ip->as_u32 = clib_host_to_net_u32 (~((1 << (32 - pref_len)) - 1));
498 }
499
500 u32
501 ip4_mask_to_preflen (ip4_address_t * mask)
502 {
503   if (mask->as_u32 == 0)
504     return 0;
505   return (32 - log2_first_set (clib_net_to_host_u32 (mask->as_u32)));
506 }
507
508 void
509 ip4_prefix_max_address_host_order (ip4_address_t * ip, u8 plen,
510                                    ip4_address_t * res)
511 {
512   u32 not_mask;
513   not_mask = (1 << (32 - plen)) - 1;
514   res->as_u32 = clib_net_to_host_u32 (ip->as_u32) + not_mask;
515 }
516
517 void
518 ip6_preflen_to_mask (u8 pref_len, ip6_address_t * mask)
519 {
520   if (pref_len == 0)
521     {
522       mask->as_u64[0] = 0;
523       mask->as_u64[1] = 0;
524     }
525   else if (pref_len <= 64)
526     {
527       mask->as_u64[0] =
528         clib_host_to_net_u64 (0xffffffffffffffffL << (64 - pref_len));
529       mask->as_u64[1] = 0;
530     }
531   else
532     {
533       mask->as_u64[0] = 0xffffffffffffffffL;
534       mask->as_u64[1] =
535         clib_host_to_net_u64 (0xffffffffffffffffL << (128 - pref_len));
536     }
537 }
538
539 void
540 ip6_prefix_max_address_host_order (ip6_address_t * ip, u8 plen,
541                                    ip6_address_t * res)
542 {
543   u64 not_mask;
544   if (plen == 0)
545     {
546       res->as_u64[0] = 0xffffffffffffffffL;
547       res->as_u64[1] = 0xffffffffffffffffL;
548     }
549   else if (plen <= 64)
550     {
551       not_mask = ((u64) 1 << (64 - plen)) - 1;
552       res->as_u64[0] = clib_net_to_host_u64 (ip->as_u64[0]) + not_mask;
553       res->as_u64[1] = 0xffffffffffffffffL;
554     }
555   else
556     {
557       not_mask = ((u64) 1 << (128 - plen)) - 1;
558       res->as_u64[1] = clib_net_to_host_u64 (ip->as_u64[1]) + not_mask;
559     }
560 }
561
562 u32
563 ip6_mask_to_preflen (ip6_address_t * mask)
564 {
565   if (mask->as_u64[1] != 0)
566     return 128 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[1]));
567   if (mask->as_u64[0] != 0)
568     return 64 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[0]));
569   return 0;
570 }
571
572 /*
573  * fd.io coding-style-patch-verification: ON
574  *
575  * Local Variables:
576  * eval: (c-set-style "gnu")
577  * End:
578  */