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