7a41c866b9c08d22f812e158a6ec23a3f52adeed
[vpp.git] / vnet / vnet / lisp-cp / lisp_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/lisp-cp/lisp_types.h>
17
18 typedef u16 (*size_to_write_fct)(void *);
19 typedef void * (*cast_fct)(gid_address_t *);
20 typedef u16 (*serdes_fct)(u8 *, void *);
21 typedef u8 (*addr_len_fct)(void *);
22 typedef void (*copy_fct)(void *, void *);
23 typedef void (*free_fct)(void *);
24 typedef int (*cmp_fct)(void *, void *);
25
26 u16 vni_write (u8 * p, void * a);
27 u16 vni_parse (u8 * p, void * a);
28 u16 vni_size_to_write (void * a);
29 void vni_free (void * a);
30 void vni_copy (void * dst, void * src);
31 u16 vni_length (void * a);
32 int vni_cmp (void *, void *);
33
34 u16 no_addr_size_to_write (void *);
35 u16 no_addr_write (u8 * p, void * a);
36 u16 no_addr_parse (u8 * p, void * a);
37 void no_addr_free (void * a);
38 void no_addr_copy (void *, void *);
39 u16 no_addr_length (void * a);
40 int no_addr_cmp (void * a1, void * a2);
41
42 size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
43   { ip_prefix_size_to_write, lcaf_size_to_write };
44 serdes_fct write_fcts[GID_ADDR_TYPES] =
45   { ip_prefix_write, lcaf_write };
46 cast_fct cast_fcts[GID_ADDR_TYPES] =
47   { ip_prefix_cast, lcaf_cast };
48 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
49   { ip_prefix_length, lcaf_prefix_length };
50 copy_fct copy_fcts[GID_ADDR_TYPES] =
51   { ip_prefix_copy, lcaf_copy };
52
53 cmp_fct lcaf_cmp_fcts[LCAF_TYPES] =
54   {
55     no_addr_cmp,
56     NULL,
57     vni_cmp
58   };
59
60 size_to_write_fct lcaf_body_length_fcts[LCAF_TYPES] =
61   {
62     no_addr_length,
63     NULL,
64     vni_length
65   };
66
67 copy_fct lcaf_copy_fcts[LCAF_TYPES] =
68   {
69     no_addr_copy,
70     NULL,
71     vni_copy
72   };
73
74 free_fct lcaf_free_fcts[LCAF_TYPES] =
75   {
76     no_addr_free,
77     NULL,
78     vni_free
79   };
80
81 size_to_write_fct lcaf_size_to_write_fcts[LCAF_TYPES] =
82   {
83     no_addr_size_to_write,
84     NULL,
85     vni_size_to_write
86   };
87
88 serdes_fct lcaf_write_fcts[LCAF_TYPES] =
89   {
90     no_addr_write,
91     NULL,
92     vni_write
93   };
94
95 serdes_fct lcaf_parse_fcts[LCAF_TYPES] =
96   {
97     no_addr_parse,
98     NULL,
99     vni_parse
100   };
101
102 u8 *
103 format_ip_address (u8 * s, va_list * args)
104 {
105   ip_address_t * a = va_arg (*args, ip_address_t *);
106   u8 ver = ip_addr_version(a);
107   if (ver == IP4)
108     {
109       return format (s, "%U", format_ip4_address, &ip_addr_v4(a));
110     }
111   else if (ver == IP6)
112     {
113       return format (s, "%U", format_ip6_address, &ip_addr_v6(a));
114     }
115   else
116     {
117       clib_warning ("Can't format IP version %d!", ver);
118       return 0;
119     }
120 }
121
122 uword
123 unformat_ip_address (unformat_input_t * input, va_list * args)
124 {
125   ip_address_t * a = va_arg(*args, ip_address_t *);
126   if (unformat(input, "%U", unformat_ip4_address, &ip_addr_v4(a)))
127     ip_addr_version(a) = IP4;
128   else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6(a)))
129     ip_addr_version(a) = IP6;
130   else
131     return 0;
132   return 1;
133 }
134
135 u8 *
136 format_ip_prefix (u8 * s, va_list * args)
137 {
138   ip_prefix_t * a = va_arg (*args, ip_prefix_t *);
139   return format (s, "%U/%d", format_ip_address, &ip_prefix_addr(a), ip_prefix_len(a));
140 }
141
142 uword
143 unformat_ip_prefix (unformat_input_t * input, va_list * args)
144 {
145   ip_prefix_t * a = va_arg(*args, ip_prefix_t *);
146   return unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a),
147                    &ip_prefix_len(a));
148 }
149
150 u8 *
151 format_gid_address (u8 * s, va_list * args)
152 {
153   gid_address_t * a = va_arg(*args, gid_address_t *);
154   u8 type = gid_address_type(a);
155   switch (type)
156     {
157     case GID_ADDR_IP_PREFIX:
158       return format (s, "%U", format_ip_prefix, &gid_address_ippref(a));
159     default:
160       clib_warning("Can't format gid type %d", type);
161       return 0;
162     }
163 }
164
165 uword
166 unformat_gid_address (unformat_input_t * input, va_list * args)
167 {
168   gid_address_t * a = va_arg(*args, gid_address_t *);
169   if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a)))
170     gid_address_type(a) = GID_ADDR_IP_PREFIX;
171   else
172     return 0;
173   return 1;
174 }
175
176 u16
177 ip_address_size (ip_address_t * a)
178 {
179   switch (ip_addr_version (a))
180   {
181     case IP4:
182       return sizeof(ip4_address_t);
183       break;
184     case IP6:
185       return sizeof(ip6_address_t);
186       break;
187   }
188   return 0;
189 }
190
191 u16
192 ip_version_to_size (u8 ver)
193 {
194   switch (ver)
195   {
196     case IP4:
197       return sizeof(ip4_address_t);
198       break;
199     case IP6:
200       return sizeof(ip6_address_t);
201       break;
202   }
203   return 0;
204 }
205
206 u8
207 ip_version_to_max_plen (u8 ver)
208 {
209   switch (ver)
210   {
211     case IP4:
212       return 32;
213       break;
214     case IP6:
215       return 128;
216       break;
217   }
218   return 0;
219 }
220
221 always_inline lisp_afi_e
222 ip_version_to_iana_afi (u16 version)
223 {
224   switch (version)
225     {
226     case IP4:
227       return LISP_AFI_IP;
228     case IP6:
229       return LISP_AFI_IP6;
230     default:
231       return 0;
232     }
233   return 0;
234 }
235
236 always_inline u8
237 ip_iana_afi_to_version (lisp_afi_e afi)
238 {
239   switch (afi)
240     {
241     case LISP_AFI_IP:
242       return IP4;
243     case LISP_AFI_IP6:
244       return IP6;
245     default:
246       return 0;
247     }
248   return 0;
249 }
250
251 u16
252 ip_address_size_to_write (ip_address_t * a)
253 {
254   return ip_address_size (a) + sizeof (u16);
255 }
256
257 u16
258 ip_address_iana_afi(ip_address_t *a)
259 {
260     return ip_version_to_iana_afi(ip_addr_version(a));
261 }
262
263 u8
264 ip_address_max_len (u8 version)
265 {
266   return version == IP4 ? 32 : 128;
267 }
268
269 u16
270 ip4_address_size_to_put ()
271 {
272   // return sizeof(u16) + sizeof (ip4_address_t);
273   return 6;
274 }
275
276 u16
277 ip6_address_size_to_put ()
278 {
279   //return sizeof(u16) + sizeof (ip6_address_t);
280   return 18;
281 }
282
283 u32
284 ip4_address_put (u8 * b, ip4_address_t * a)
285 {
286   *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
287   u8 *p = b + sizeof (u16);
288   clib_memcpy (p, a, sizeof(*a));
289   return ip4_address_size_to_put();
290 }
291
292 u32
293 ip6_address_put (u8 * b, ip6_address_t * a)
294 {
295   *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
296   u8 *p = b + sizeof (u16);
297   clib_memcpy (p, a, sizeof(*a));
298   return ip6_address_size_to_put();
299 }
300
301 u32
302 ip_address_put (u8 * b, ip_address_t * a)
303 {
304   u32 len = ip_address_size (a);
305   *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
306   u8 * p = b + sizeof (u16);
307   clib_memcpy (p, &ip_addr_addr (a), len);
308   return (len + sizeof (u16));
309 }
310
311 u32
312 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
313 {
314   ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
315   u8 size = ip_version_to_size (ip_addr_version(dst));
316   clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
317   return(sizeof(u16) + size);
318 }
319
320 u32
321 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
322 {
323   lcaf_hdr_t * lh = offset;
324   lcaf->type = lh->type;
325
326   /* this is a bit of hack: since the LCAF Instance ID is the
327     only message that uses reserved2 field, we can set it here.
328     If any LCAF format starts using reserved2 field as well this needs
329     to be moved elsewhere */
330   lcaf_vni_len (lcaf) = lh->reserved2;
331
332   return sizeof (lh[0]);
333 }
334
335 u16
336 vni_parse (u8 * p, void * a)
337 {
338   vni_t * v = a;
339   u16 size = 0;
340   vni_vni (v) = clib_net_to_host_u32 ( *(u32 *) p);
341   size += sizeof (u32);
342
343   vni_gid (v) = clib_mem_alloc (sizeof (gid_address_t));
344   gid_address_t * gid = vni_gid (v);
345   memset (gid, 0, sizeof (gid[0]));
346
347   size += gid_address_parse (p + size, gid);
348   return size;
349 }
350
351 u16
352 no_addr_parse (u8 * p, void * a)
353 {
354   /* do nothing */
355   return 0;
356 }
357
358 u32
359 lcaf_parse (void * offset, gid_address_t *addr)
360 {
361   /* skip AFI type */
362   offset += sizeof (u16);
363   lcaf_t * lcaf = &gid_address_lcaf (addr);
364
365   u32 size = lcaf_hdr_parse (offset, lcaf);
366   u8 type = lcaf_type (lcaf);
367
368   if (!lcaf_parse_fcts[type])
369     {
370       clib_warning ("Unsupported LCAF type: %u", type);
371       return ~0;
372     }
373   size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
374   return sizeof (u16) + size;
375 }
376
377 void
378 vni_free (void * a)
379 {
380   vni_t * v = a;
381   gid_address_free (vni_gid (v));
382   clib_mem_free (vni_gid (v));
383 }
384
385 void
386 no_addr_free (void * a)
387 {
388   /* nothing to do */
389 }
390
391 void
392 gid_address_free (gid_address_t *a)
393 {
394   if (gid_address_type (a) != GID_ADDR_LCAF)
395     return;
396
397   lcaf_t * lcaf = &gid_address_lcaf (a);
398   u8 lcaf_type = lcaf_type (lcaf);
399   (*lcaf_free_fcts[lcaf_type])(lcaf);
400 }
401
402 int
403 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
404 {
405   int res = 0;
406   if (ip_addr_version (ip1) != ip_addr_version(ip2))
407     return -1;
408   res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
409
410   if (res < 0)
411     res = 2;
412   else if (res > 0)
413     res = 1;
414
415   return res;
416 }
417
418 void
419 ip_address_copy (ip_address_t * dst , ip_address_t * src)
420 {
421   clib_memcpy (dst, src, sizeof (ip_address_t));
422 }
423
424 void
425 ip_address_copy_addr (void * dst , ip_address_t * src)
426 {
427   clib_memcpy (dst, src, ip_address_size(src));
428 }
429
430 void
431 ip_address_set(ip_address_t * dst, void * src, u8 version)
432 {
433   clib_memcpy(dst, src, ip_version_to_size(version));
434   ip_addr_version(dst) = version;
435 }
436
437 void *
438 ip_prefix_cast (gid_address_t * a)
439 {
440   return &gid_address_ippref(a);
441 }
442
443 u16
444 ip_prefix_size_to_write (void * pref)
445 {
446   ip_prefix_t *a = (ip_prefix_t *) pref;
447   return ip_address_size_to_write (&ip_prefix_addr (a));
448 }
449
450 u16
451 ip_prefix_write (u8 * p, void * pref)
452 {
453   ip_prefix_t *a = (ip_prefix_t *) pref;
454   switch (ip_prefix_version (a))
455   {
456     case IP4:
457       return ip4_address_put (p, &ip_prefix_v4 (a));
458       break;
459     case IP6:
460       return ip6_address_put (p, &ip_prefix_v6 (a));
461       break;
462   }
463   return 0;
464 }
465
466 u8
467 ip_prefix_length (void *a)
468 {
469   return ip_prefix_len((ip_prefix_t *) a);
470 }
471
472 void
473 ip_prefix_copy (void * dst , void * src)
474 {
475   clib_memcpy (dst, src, sizeof (ip_prefix_t));
476 }
477
478 int
479 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
480 {
481   int cmp = 0;
482   cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
483   if (cmp == 0)
484   {
485     if (ip_prefix_len(p1) < ip_prefix_len(p2))
486     {
487       cmp = 1;
488     }
489     else
490     {
491       if (ip_prefix_len(p1) > ip_prefix_len(p2))
492         cmp = 2;
493     }
494   }
495   return cmp;
496 }
497
498 void
499 no_addr_copy (void * dst, void * src)
500 {
501   /* nothing to do */
502 }
503
504 void
505 vni_copy (void * dst, void * src)
506 {
507   vni_t * vd = dst;
508   vni_t * vs = src;
509
510   clib_memcpy (vd, vs, sizeof (vd[0]));
511   vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
512   gid_address_copy (vni_gid (vd), vni_gid (vs));
513 }
514
515 void
516 lcaf_copy (void * dst , void * src)
517 {
518   lcaf_t * lcaf_dst = dst;
519   lcaf_t * lcaf_src = src;
520
521   lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
522   (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
523 }
524
525 u8
526 lcaf_prefix_length (void *a)
527 {
528   return 0;
529 }
530
531 void *
532 lcaf_cast (gid_address_t * a)
533 {
534   return &gid_address_lcaf (a);
535 }
536
537 u16
538 no_addr_length (void * a)
539 {
540   return 0;
541 }
542
543 u16
544 vni_length (void * a)
545 {
546   vni_t * v = a;
547   return (sizeof (u32) /* VNI size */
548    + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
549 }
550
551 u16
552 lcaf_write (u8 * p, void * a)
553 {
554   u16 size = 0, len;
555   lcaf_t * lcaf = a;
556   u8 type = lcaf_type (lcaf);
557   lcaf_hdr_t _h, *h = &_h;
558
559   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
560   size += sizeof (u16);
561   memset (h, 0, sizeof (h[0]));
562   LCAF_TYPE (h) = type;
563   u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
564   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
565
566   if (LCAF_INSTANCE_ID == type)
567     LCAF_RES2 (h) = lcaf_vni_len(lcaf);
568
569   clib_memcpy (p + size, h, sizeof (h[0]));
570   size += sizeof (h[0]);
571   len = (*lcaf_write_fcts[type])(p + size, lcaf);
572
573   if ((u16)~0 == len)
574     return ~0;
575
576   return size + len;
577 }
578
579 u16
580 vni_write (u8 * p, void * a)
581 {
582   vni_t * v = a;
583   u16 size = 0, len;
584
585   *(u32 *)p = clib_host_to_net_u32 (vni_vni (v));
586   size += sizeof (u32);
587   len = gid_address_put (p + size, vni_gid (v));
588
589   if ((u16)~0 == len)
590     return ~0;
591
592   return size + len;
593 }
594
595 u16
596 no_addr_write (u8 * p, void * a)
597 {
598   /* do nothing; return AFI field size */
599   return sizeof (u16);
600 }
601
602 u16
603 no_addr_size_to_write (void * a)
604 {
605   return sizeof (u16); /* AFI field length */
606 }
607
608 u16
609 vni_size_to_write (void * a)
610 {
611   vni_t * v =  a;
612   u16 size = sizeof (vni_vni (v));
613
614   gid_address_t * gid = vni_gid (v);
615   return (size + sizeof (lcaf_hdr_t)
616     + gid_address_size_to_put (gid));
617 }
618
619 u16
620 lcaf_size_to_write (void * a)
621 {
622   lcaf_t * lcaf = (lcaf_t *) a;
623   u32 size = 0, len;
624   u8 type = lcaf_type (lcaf);
625
626   size += sizeof (u16); /* AFI size */
627
628   len = (*lcaf_size_to_write_fcts[type])(lcaf);
629   if (~0 == len)
630     return ~0;
631
632   return size + len;
633 }
634
635 u8
636 gid_address_len (gid_address_t *a)
637 {
638   gid_address_type_t type = gid_address_type (a);
639   return (*addr_len_fcts[type])((*cast_fcts[type])(a));
640 }
641
642 u16
643 gid_address_put (u8 * b, gid_address_t * gid)
644 {
645   gid_address_type_t type = gid_address_type (gid);
646   return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
647 }
648
649 u16
650 gid_address_size_to_put (gid_address_t * gid)
651 {
652   gid_address_type_t type = gid_address_type (gid);
653   return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
654 }
655
656 void *
657 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
658 {
659   return (*cast_fcts[type])(gid);
660 }
661
662 void
663 gid_address_copy(gid_address_t * dst, gid_address_t * src)
664 {
665   gid_address_type_t type = gid_address_type(src);
666   (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
667   gid_address_type(dst) = type;
668 }
669
670 u32
671 gid_address_parse (u8 * offset, gid_address_t *a)
672 {
673   lisp_afi_e afi;
674   int len = 0;
675
676   if (!a)
677     return 0;
678
679   afi = clib_net_to_host_u16 (*((u16 *) offset));
680
681   switch (afi)
682     {
683     case LISP_AFI_NO_ADDR:
684       len = sizeof(u16);
685       gid_address_type(a) = GID_ADDR_NO_ADDRESS;
686       break;
687     case LISP_AFI_IP:
688       len = ip_address_parse (offset, afi, &gid_address_ip(a));
689       gid_address_type(a) = GID_ADDR_IP_PREFIX;
690       /* this should be modified outside if needed*/
691       gid_address_ippref_len(a) = 32;
692       break;
693     case LISP_AFI_IP6:
694       len = ip_address_parse (offset, afi, &gid_address_ip(a));
695       gid_address_type(a) = GID_ADDR_IP_PREFIX;
696       /* this should be modified outside if needed*/
697       gid_address_ippref_len(a) = 128;
698       break;
699     case LISP_AFI_LCAF:
700       len = lcaf_parse (offset, a);
701       gid_address_type(a) = GID_ADDR_LCAF;
702       break;
703     default:
704       clib_warning("LISP AFI %d not supported!", afi);
705       return ~0;
706     }
707   return len;
708 }
709
710 int
711 no_addr_cmp (void * a1, void * a2)
712 {
713   return 0;
714 }
715
716 int
717 vni_cmp (void * a1, void * a2)
718 {
719   vni_t * v1 = a1;
720   vni_t * v2 = a2;
721
722   if (vni_mask_len (v1) != vni_mask_len (v2))
723     return -1;
724   if (vni_vni (v1) != vni_vni (v2))
725     return -1;
726   return gid_address_cmp (vni_gid (v1), vni_gid (v2));
727 }
728
729 /* Compare two gid_address_t.
730  * Returns:
731  *        -1: If they are from different afi
732  *             0: Both address are the same
733  *             1: Addr1 is bigger than addr2
734  *             2: Addr2 is bigger than addr1
735  */
736 int
737 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
738 {
739   lcaf_t * lcaf1, * lcaf2;
740   int cmp = -1;
741   if (!a1 || !a2)
742     return -1;
743   if (gid_address_type(a1) != gid_address_type(a2))
744     return -1;
745
746   switch (gid_address_type(a1))
747     {
748     case GID_ADDR_NO_ADDRESS:
749       if (a1 == a2)
750         cmp = 0;
751       else
752         cmp = 2;
753       break;
754     case GID_ADDR_IP_PREFIX:
755       cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
756       break;
757     case GID_ADDR_LCAF:
758       lcaf1 = &gid_address_lcaf (a1);
759       lcaf2 = &gid_address_lcaf (a2);
760       if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
761         cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
762       break;
763     default:
764       break;
765     }
766
767   return cmp;
768 }
769
770
771 u32
772 locator_parse (void * b, locator_t * loc)
773 {
774   locator_hdr_t * h;
775   u8 status = 1; /* locator up */
776   int len;
777
778   h = b;
779   if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
780     status = 0;
781
782   len = gid_address_parse (LOC_ADDR(h), &loc->address);
783   if (len == ~0)
784     return len;
785
786   loc->state = status;
787   loc->local = 0;
788   loc->priority = LOC_PRIORITY(h);
789   loc->weight = LOC_WEIGHT(h);
790   loc->mpriority = LOC_MPRIORITY(h);
791   loc->mweight = LOC_MWEIGHT(h);
792
793   return sizeof(locator_hdr_t) + len;
794 }
795
796 void
797 locator_copy (locator_t * dst, locator_t * src)
798 {
799   /* TODO if gid become more complex, this will need to be changed! */
800   clib_memcpy (dst, src, sizeof(*dst));
801   if (!src->local)
802     gid_address_copy (&dst->address, &src->address);
803 }
804
805 u32
806 locator_cmp (locator_t * l1, locator_t * l2)
807 {
808   u32 ret = 0;
809   if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
810     return 1;
811
812   if (l1->priority != l2->priority)
813     return 1;
814   if (l1->weight != l2->weight)
815     return 1;
816   if (l1->mpriority != l2->mpriority)
817     return 1;
818   if (l1->mweight != l2->mweight)
819     return 1;
820   return 0;
821 }
822
823 void
824 locator_free (locator_t * l)
825 {
826   if (!l->local)
827     gid_address_free (&l->address);
828 }