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