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