Add MAC address support to LISP map-cache
[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   afi = clib_net_to_host_u16 (*((u16 *) offset));
786
787   switch (afi)
788     {
789     case LISP_AFI_NO_ADDR:
790       len = sizeof(u16);
791       gid_address_type(a) = GID_ADDR_NO_ADDRESS;
792       break;
793     case LISP_AFI_IP:
794       len = ip_address_parse (offset, afi, &gid_address_ip(a));
795       gid_address_type(a) = GID_ADDR_IP_PREFIX;
796       /* this should be modified outside if needed*/
797       gid_address_ippref_len(a) = 32;
798       break;
799     case LISP_AFI_IP6:
800       len = ip_address_parse (offset, afi, &gid_address_ip(a));
801       gid_address_type(a) = GID_ADDR_IP_PREFIX;
802       /* this should be modified outside if needed*/
803       gid_address_ippref_len(a) = 128;
804       break;
805     case LISP_AFI_LCAF:
806       gid_address_type(a) = GID_ADDR_LCAF;
807       len = lcaf_parse (offset, a);
808       break;
809     case LISP_AFI_MAC:
810       len = mac_parse (offset, a);
811       gid_address_type(a) = GID_ADDR_MAC;
812       break;
813     default:
814       clib_warning("LISP AFI %d not supported!", afi);
815       return ~0;
816     }
817   return len;
818 }
819
820 int
821 no_addr_cmp (void * a1, void * a2)
822 {
823   return 0;
824 }
825
826 int
827 vni_cmp (void * a1, void * a2)
828 {
829   vni_t * v1 = a1;
830   vni_t * v2 = a2;
831
832   if (vni_mask_len (v1) != vni_mask_len (v2))
833     return -1;
834   if (vni_vni (v1) != vni_vni (v2))
835     return -1;
836   return gid_address_cmp (vni_gid (v1), vni_gid (v2));
837 }
838
839 /* Compare two gid_address_t.
840  * Returns:
841  *        -1: If they are from different afi
842  *             0: Both address are the same
843  *             1: Addr1 is bigger than addr2
844  *             2: Addr2 is bigger than addr1
845  */
846 int
847 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
848 {
849   lcaf_t * lcaf1, * lcaf2;
850   int cmp = -1;
851   if (!a1 || !a2)
852     return -1;
853   if (gid_address_type(a1) != gid_address_type(a2))
854     return -1;
855   if (gid_address_vni(a1) != gid_address_vni(a2))
856     return -1;
857   if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
858     return -1;
859
860   switch (gid_address_type(a1))
861     {
862     case GID_ADDR_NO_ADDRESS:
863       if (a1 == a2)
864         cmp = 0;
865       else
866         cmp = 2;
867       break;
868     case GID_ADDR_IP_PREFIX:
869       cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
870       break;
871     case GID_ADDR_LCAF:
872       lcaf1 = &gid_address_lcaf (a1);
873       lcaf2 = &gid_address_lcaf (a2);
874       if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
875         cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
876       break;
877     case GID_ADDR_MAC:
878       cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
879                     sizeof (gid_address_mac (a1)));
880       break;
881     default:
882       break;
883     }
884
885   return cmp;
886 }
887
888
889 u32
890 locator_parse (void * b, locator_t * loc)
891 {
892   locator_hdr_t * h;
893   u8 status = 1; /* locator up */
894   int len;
895
896   h = b;
897   if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
898     status = 0;
899
900   len = gid_address_parse (LOC_ADDR(h), &loc->address);
901   if (len == ~0)
902     return len;
903
904   loc->state = status;
905   loc->local = 0;
906   loc->priority = LOC_PRIORITY(h);
907   loc->weight = LOC_WEIGHT(h);
908   loc->mpriority = LOC_MPRIORITY(h);
909   loc->mweight = LOC_MWEIGHT(h);
910
911   return sizeof(locator_hdr_t) + len;
912 }
913
914 void
915 locator_copy (locator_t * dst, locator_t * src)
916 {
917   /* TODO if gid become more complex, this will need to be changed! */
918   clib_memcpy (dst, src, sizeof(*dst));
919   if (!src->local)
920     gid_address_copy (&dst->address, &src->address);
921 }
922
923 u32
924 locator_cmp (locator_t * l1, locator_t * l2)
925 {
926   u32 ret = 0;
927   if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
928     return 1;
929
930   if (l1->priority != l2->priority)
931     return 1;
932   if (l1->weight != l2->weight)
933     return 1;
934   if (l1->mpriority != l2->mpriority)
935     return 1;
936   if (l1->mweight != l2->mweight)
937     return 1;
938   return 0;
939 }
940
941 void
942 locator_free (locator_t * l)
943 {
944   if (!l->local)
945     gid_address_free (&l->address);
946 }