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