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