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