Add Overlay Network Engine API
[vpp.git] / src / 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 static u16 fid_addr_size_to_write (fid_address_t * a);
21
22 u32 mac_parse (u8 * offset, u8 * a);
23
24 typedef u16 (*size_to_write_fct) (void *);
25 typedef void *(*cast_fct) (gid_address_t *);
26 typedef u16 (*serdes_fct) (u8 *, void *);
27 typedef u8 (*addr_len_fct) (void *);
28 typedef void (*copy_fct) (void *, void *);
29 typedef void (*free_fct) (void *);
30 typedef int (*cmp_fct) (void *, void *);
31
32 size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
33   { ip_prefix_size_to_write, lcaf_size_to_write, mac_size_to_write,
34   sd_size_to_write, nsh_size_to_write
35 };
36 serdes_fct write_fcts[GID_ADDR_TYPES] =
37   { ip_prefix_write, lcaf_write, mac_write, sd_write, nsh_write };
38 cast_fct cast_fcts[GID_ADDR_TYPES] =
39   { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast, nsh_cast };
40 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
41   { ip_prefix_length, lcaf_length, mac_length, sd_length, nsh_length };
42 copy_fct copy_fcts[GID_ADDR_TYPES] =
43   { ip_prefix_copy, lcaf_copy, mac_copy, sd_copy, nsh_copy };
44
45 #define foreach_lcaf_type \
46   _(1, no_addr)      \
47   _(0, NULL)         \
48   _(1, vni)          \
49   _(0, NULL)         \
50   _(0, NULL)         \
51   _(0, NULL)         \
52   _(0, NULL)         \
53   _(0, NULL)         \
54   _(0, NULL)         \
55   _(0, NULL)         \
56   _(0, NULL)         \
57   _(0, NULL)         \
58   _(1, sd)
59
60 #define _(cond, name)                             \
61   u16 name ## _write (u8 * p, void * a);          \
62   u16 name ## _parse (u8 * p, void * a);          \
63   u16 name ## _size_to_write (void * a);          \
64   void name ## _free (void * a);                  \
65   void name ## _copy (void * dst, void * src);    \
66   u8 name ## _length (void * a);                  \
67   int name ## _cmp (void *, void *);
68 foreach_lcaf_type
69 #undef _
70 #define CONCAT(a,b) a##_##b
71 #define IF(c, t, e) CONCAT(IF, c)(t, e)
72 #define IF_0(t, e) e
73 #define IF_1(t, e) t
74 #define EXPAND_FCN(cond, fcn)                           \
75   IF(cond, fcn, NULL)
76   cmp_fct lcaf_cmp_fcts[LCAF_TYPES] =
77 {
78 #define _(cond, name)                                   \
79     EXPAND_FCN(cond, name##_cmp),
80   foreach_lcaf_type
81 #undef _
82 };
83
84 addr_len_fct lcaf_body_length_fcts[LCAF_TYPES] = {
85 #define _(cond, name)                                   \
86     EXPAND_FCN(cond, name##_length),
87   foreach_lcaf_type
88 #undef _
89 };
90
91 copy_fct lcaf_copy_fcts[LCAF_TYPES] = {
92 #define _(cond, name)                                   \
93     EXPAND_FCN(cond, name##_copy),
94   foreach_lcaf_type
95 #undef _
96 };
97
98 free_fct lcaf_free_fcts[LCAF_TYPES] = {
99 #define _(cond, name)                                   \
100     EXPAND_FCN(cond, name##_free),
101   foreach_lcaf_type
102 #undef _
103 };
104
105 size_to_write_fct lcaf_size_to_write_fcts[LCAF_TYPES] = {
106 #define _(cond, name)                                   \
107     EXPAND_FCN(cond, name##_size_to_write),
108   foreach_lcaf_type
109 #undef _
110 };
111
112 serdes_fct lcaf_write_fcts[LCAF_TYPES] = {
113 #define _(cond, name)                                   \
114     EXPAND_FCN(cond, name##_write),
115   foreach_lcaf_type
116 #undef _
117 };
118
119 serdes_fct lcaf_parse_fcts[LCAF_TYPES] = {
120 #define _(cond, name)                                   \
121     EXPAND_FCN(cond, name##_parse),
122   foreach_lcaf_type
123 #undef _
124 };
125
126 u8 *
127 format_ip_address (u8 * s, va_list * args)
128 {
129   ip_address_t *a = va_arg (*args, ip_address_t *);
130   u8 ver = ip_addr_version (a);
131   if (ver == IP4)
132     {
133       return format (s, "%U", format_ip4_address, &ip_addr_v4 (a));
134     }
135   else if (ver == IP6)
136     {
137       return format (s, "%U", format_ip6_address, &ip_addr_v6 (a));
138     }
139   else
140     {
141       clib_warning ("Can't format IP version %d!", ver);
142       return 0;
143     }
144 }
145
146 uword
147 unformat_ip_address (unformat_input_t * input, va_list * args)
148 {
149   ip_address_t *a = va_arg (*args, ip_address_t *);
150
151   memset (a, 0, sizeof (*a));
152   if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (a)))
153     ip_addr_version (a) = IP4;
154   else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6 (a)))
155     ip_addr_version (a) = IP6;
156   else
157     return 0;
158   return 1;
159 }
160
161 u8 *
162 format_ip_prefix (u8 * s, va_list * args)
163 {
164   ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
165   return format (s, "%U/%d", format_ip_address, &ip_prefix_addr (a),
166                  ip_prefix_len (a));
167 }
168
169 uword
170 unformat_ip_prefix (unformat_input_t * input, va_list * args)
171 {
172   ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
173   if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr (a),
174                 &ip_prefix_len (a)))
175     {
176       if ((ip_prefix_version (a) == IP4 && 32 < ip_prefix_len (a)) ||
177           (ip_prefix_version (a) == IP6 && 128 < ip_prefix_length (a)))
178         {
179           clib_warning ("Prefix length to big: %d!", ip_prefix_len (a));
180           return 0;
181         }
182       ip_prefix_normalize (a);
183     }
184   else
185     return 0;
186   return 1;
187 }
188
189 uword
190 unformat_mac_address (unformat_input_t * input, va_list * args)
191 {
192   u8 *a = va_arg (*args, u8 *);
193   return unformat (input, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3],
194                    &a[4], &a[5]);
195 }
196
197 u8 *
198 format_mac_address (u8 * s, va_list * args)
199 {
200   u8 *a = va_arg (*args, u8 *);
201   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
202                  a[0], a[1], a[2], a[3], a[4], a[5]);
203 }
204
205 uword
206 unformat_nsh_address (unformat_input_t * input, va_list * args)
207 {
208   nsh_t *a = va_arg (*args, nsh_t *);
209   return unformat (input, "SPI:%d SI:%d", &a->spi, &a->si);
210 }
211
212 u8 *
213 format_nsh_address (u8 * s, va_list * args)
214 {
215   nsh_t *a = va_arg (*args, nsh_t *);
216   return format (s, "SPI:%d SI:%d", a->spi, a->si);
217 }
218
219 u8 *
220 format_fid_address (u8 * s, va_list * args)
221 {
222   fid_address_t *a = va_arg (*args, fid_address_t *);
223
224   switch (fid_addr_type (a))
225     {
226     case FID_ADDR_IP_PREF:
227       return format (s, "%U", format_ip_prefix, &fid_addr_ippref (a));
228     case FID_ADDR_MAC:
229       return format (s, "%U", format_mac_address, &fid_addr_mac (a));
230     case FID_ADDR_NSH:
231       return format (s, "%U", format_nsh_address, &fid_addr_nsh (a));
232
233     default:
234       clib_warning ("Can't format fid address type %d!", fid_addr_type (a));
235       return 0;
236     }
237   return 0;
238 }
239
240 u8 *
241 format_gid_address (u8 * s, va_list * args)
242 {
243   gid_address_t *a = va_arg (*args, gid_address_t *);
244   u8 type = gid_address_type (a);
245   switch (type)
246     {
247     case GID_ADDR_IP_PREFIX:
248       return format (s, "[%d] %U", gid_address_vni (a), format_ip_prefix,
249                      &gid_address_ippref (a));
250     case GID_ADDR_SRC_DST:
251       return format (s, "[%d] %U|%U", gid_address_vni (a),
252                      format_fid_address, &gid_address_sd_src (a),
253                      format_fid_address, &gid_address_sd_dst (a));
254     case GID_ADDR_MAC:
255       return format (s, "[%d] %U", gid_address_vni (a), format_mac_address,
256                      &gid_address_mac (a));
257     case GID_ADDR_NSH:
258       return format (s, "%U", format_nsh_address, &gid_address_nsh (a));
259     default:
260       clib_warning ("Can't format gid type %d", type);
261       return 0;
262     }
263   return 0;
264 }
265
266 uword
267 unformat_fid_address (unformat_input_t * i, va_list * args)
268 {
269   fid_address_t *a = va_arg (*args, fid_address_t *);
270   ip_prefix_t ippref;
271   u8 mac[6] = { 0 };
272   nsh_t nsh;
273
274   if (unformat (i, "%U", unformat_ip_prefix, &ippref))
275     {
276       fid_addr_type (a) = FID_ADDR_IP_PREF;
277       ip_prefix_copy (&fid_addr_ippref (a), &ippref);
278     }
279   else if (unformat (i, "%U", unformat_mac_address, mac))
280     {
281       fid_addr_type (a) = FID_ADDR_MAC;
282       mac_copy (fid_addr_mac (a), mac);
283     }
284   else if (unformat (i, "%U", unformat_nsh_address, &nsh))
285     {
286       fid_addr_type (a) = FID_ADDR_NSH;
287       nsh_copy (&fid_addr_nsh (a), mac);
288     }
289   else
290     return 0;
291
292   return 1;
293 }
294
295 uword
296 unformat_hmac_key_id (unformat_input_t * input, va_list * args)
297 {
298   u32 *key_id = va_arg (*args, u32 *);
299   u8 *s = 0;
300
301   if (unformat (input, "%s", &s))
302     {
303       if (!strcmp ((char *) s, "sha1"))
304         key_id[0] = HMAC_SHA_1_96;
305       else if (!strcmp ((char *) s, "sha256"))
306         key_id[0] = HMAC_SHA_256_128;
307       else
308         {
309           clib_warning ("invalid key_id: '%s'", s);
310           key_id[0] = HMAC_NO_KEY;
311         }
312     }
313   else
314     return 0;
315
316   vec_free (s);
317   return 1;
318 }
319
320 uword
321 unformat_gid_address (unformat_input_t * input, va_list * args)
322 {
323   gid_address_t *a = va_arg (*args, gid_address_t *);
324   u8 mac[6] = { 0 };
325   ip_prefix_t ippref;
326   fid_address_t sim1, sim2;
327   nsh_t nsh;
328
329   memset (&ippref, 0, sizeof (ippref));
330   memset (&sim1, 0, sizeof (sim1));
331   memset (&sim2, 0, sizeof (sim2));
332
333   if (unformat (input, "%U|%U", unformat_fid_address, &sim1,
334                 unformat_fid_address, &sim2))
335     {
336       gid_address_sd_src (a) = sim1;
337       gid_address_sd_dst (a) = sim2;
338       gid_address_type (a) = GID_ADDR_SRC_DST;
339     }
340   else if (unformat (input, "%U", unformat_ip_prefix, &ippref))
341     {
342       ip_prefix_copy (&gid_address_ippref (a), &ippref);
343       gid_address_type (a) = GID_ADDR_IP_PREFIX;
344     }
345   else if (unformat (input, "%U", unformat_mac_address, mac))
346     {
347       mac_copy (gid_address_mac (a), mac);
348       gid_address_type (a) = GID_ADDR_MAC;
349     }
350   else if (unformat (input, "%U", unformat_nsh_address, &nsh))
351     {
352       nsh_copy (&gid_address_nsh (a), &nsh);
353       gid_address_type (a) = GID_ADDR_NSH;
354     }
355   else
356     return 0;
357
358   return 1;
359 }
360
361 uword
362 unformat_negative_mapping_action (unformat_input_t * input, va_list * args)
363 {
364   u32 *action = va_arg (*args, u32 *);
365   u8 *s = 0;
366
367   if (unformat (input, "%s", &s))
368     {
369       if (!strcmp ((char *) s, "no-action"))
370         action[0] = LISP_NO_ACTION;
371       else if (!strcmp ((char *) s, "natively-forward"))
372         action[0] = LISP_FORWARD_NATIVE;
373       else if (!strcmp ((char *) s, "send-map-request"))
374         action[0] = LISP_SEND_MAP_REQUEST;
375       else if (!strcmp ((char *) s, "drop"))
376         action[0] = LISP_DROP;
377       else
378         {
379           clib_warning ("invalid action: '%s'", s);
380           action[0] = LISP_DROP;
381         }
382     }
383   else
384     return 0;
385
386   vec_free (s);
387   return 1;
388 }
389
390 u8 *
391 format_hmac_key_id (u8 * s, va_list * args)
392 {
393   lisp_key_type_t key_id = va_arg (*args, lisp_key_type_t);
394
395   switch (key_id)
396     {
397     case HMAC_SHA_1_96:
398       return format (0, "sha1");
399     case HMAC_SHA_256_128:
400       return format (0, "sha256");
401     default:
402       return 0;
403     }
404
405   return 0;
406 }
407
408 u8 *
409 format_negative_mapping_action (u8 * s, va_list * args)
410 {
411   lisp_action_e action = va_arg (*args, lisp_action_e);
412
413   switch (action)
414     {
415     case LISP_NO_ACTION:
416       s = format (s, "no-action");
417       break;
418     case LISP_FORWARD_NATIVE:
419       s = format (s, "natively-forward");
420       break;
421     case LISP_SEND_MAP_REQUEST:
422       s = format (s, "send-map-request");
423       break;
424     case LISP_DROP:
425     default:
426       s = format (s, "drop");
427       break;
428     }
429   return (s);
430 }
431
432 u16
433 ip_address_size (const ip_address_t * a)
434 {
435   switch (ip_addr_version (a))
436     {
437     case IP4:
438       return sizeof (ip4_address_t);
439       break;
440     case IP6:
441       return sizeof (ip6_address_t);
442       break;
443     }
444   return 0;
445 }
446
447 u16
448 ip_version_to_size (u8 ver)
449 {
450   switch (ver)
451     {
452     case IP4:
453       return sizeof (ip4_address_t);
454       break;
455     case IP6:
456       return sizeof (ip6_address_t);
457       break;
458     }
459   return 0;
460 }
461
462 u8
463 ip_version_to_max_plen (u8 ver)
464 {
465   switch (ver)
466     {
467     case IP4:
468       return 32;
469       break;
470     case IP6:
471       return 128;
472       break;
473     }
474   return 0;
475 }
476
477 always_inline lisp_afi_e
478 ip_version_to_iana_afi (u16 version)
479 {
480   switch (version)
481     {
482     case IP4:
483       return LISP_AFI_IP;
484     case IP6:
485       return LISP_AFI_IP6;
486     default:
487       return 0;
488     }
489   return 0;
490 }
491
492 always_inline u8
493 ip_iana_afi_to_version (lisp_afi_e afi)
494 {
495   switch (afi)
496     {
497     case LISP_AFI_IP:
498       return IP4;
499     case LISP_AFI_IP6:
500       return IP6;
501     default:
502       return 0;
503     }
504   return 0;
505 }
506
507 u16
508 ip_address_size_to_write (ip_address_t * a)
509 {
510   return ip_address_size (a) + sizeof (u16);
511 }
512
513 u16
514 ip_address_iana_afi (ip_address_t * a)
515 {
516   return ip_version_to_iana_afi (ip_addr_version (a));
517 }
518
519 u8
520 ip_address_max_len (u8 version)
521 {
522   return version == IP4 ? 32 : 128;
523 }
524
525 u16
526 ip4_address_size_to_put ()
527 {
528   // return sizeof(u16) + sizeof (ip4_address_t);
529   return 6;
530 }
531
532 u16
533 ip6_address_size_to_put ()
534 {
535   //return sizeof(u16) + sizeof (ip6_address_t);
536   return 18;
537 }
538
539 u32
540 ip4_address_put (u8 * b, ip4_address_t * a)
541 {
542   *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (IP4));
543   u8 *p = b + sizeof (u16);
544   clib_memcpy (p, a, sizeof (*a));
545   return ip4_address_size_to_put ();
546 }
547
548 u32
549 ip6_address_put (u8 * b, ip6_address_t * a)
550 {
551   *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (IP6));
552   u8 *p = b + sizeof (u16);
553   clib_memcpy (p, a, sizeof (*a));
554   return ip6_address_size_to_put ();
555 }
556
557 u32
558 ip_address_put (u8 * b, ip_address_t * a)
559 {
560   u32 len = ip_address_size (a);
561   *(u16 *) b = clib_host_to_net_u16 (ip_address_iana_afi (a));
562   u8 *p = b + sizeof (u16);
563   clib_memcpy (p, &ip_addr_addr (a), len);
564   return (len + sizeof (u16));
565 }
566
567 u32
568 ip_address_parse (void *offset, u16 iana_afi, ip_address_t * dst)
569 {
570   ip_addr_version (dst) = ip_iana_afi_to_version (iana_afi);
571   u8 size = ip_version_to_size (ip_addr_version (dst));
572   clib_memcpy (&ip_addr_addr (dst), offset + sizeof (u16), size);
573   return (sizeof (u16) + size);
574 }
575
576 u32
577 lcaf_hdr_parse (void *offset, lcaf_t * lcaf)
578 {
579   lcaf_hdr_t *lh = offset;
580   lcaf->type = lh->type;
581
582   /* this is a bit of hack: since the LCAF Instance ID is the
583      only message that uses reserved2 field, we can set it here.
584      If any LCAF format starts using reserved2 field as well this needs
585      to be moved elsewhere */
586   lcaf_vni_len (lcaf) = lh->reserved2;
587
588   return sizeof (lh[0]);
589 }
590
591 static u8
592 iana_afi_to_fid_addr_type (u16 type)
593 {
594   switch (type)
595     {
596     case LISP_AFI_IP:
597     case LISP_AFI_IP6:
598       return FID_ADDR_IP_PREF;
599
600     case LISP_AFI_MAC:
601       return FID_ADDR_MAC;
602     }
603   return ~0;
604 }
605
606 static u16
607 fid_addr_parse (u8 * p, fid_address_t * a)
608 {
609   u16 afi = clib_net_to_host_u16 (*(u16 *) p);
610   fid_addr_type (a) = iana_afi_to_fid_addr_type (afi);
611   ip_address_t *ip_addr = &ip_prefix_addr (&fid_addr_ippref (a));
612
613   switch (fid_addr_type (a))
614     {
615     case FID_ADDR_MAC:
616       return mac_parse (p, fid_addr_mac (a));
617
618     case FID_ADDR_IP_PREF:
619       return ip_address_parse (p, afi, ip_addr);
620
621     case FID_ADDR_NSH:
622       ASSERT (0);
623       break;
624     }
625   return ~0;
626 }
627
628 u16
629 sd_parse (u8 * p, void *a)
630 {
631   lcaf_src_dst_hdr_t *sd_hdr;
632   gid_address_t *g = a;
633   u16 size = 0;
634   fid_address_t *src = &gid_address_sd_src (g);
635   fid_address_t *dst = &gid_address_sd_dst (g);
636
637   gid_address_type (g) = GID_ADDR_SRC_DST;
638
639   sd_hdr = (lcaf_src_dst_hdr_t *) (p + size);
640   size += sizeof (sd_hdr[0]);
641
642   size += fid_addr_parse (p + size, src);
643   size += fid_addr_parse (p + size, dst);
644
645   if (fid_addr_type (src) == FID_ADDR_IP_PREF)
646     {
647       ip_prefix_t *ippref = &fid_addr_ippref (src);
648       ip_prefix_len (ippref) = LCAF_SD_SRC_ML (sd_hdr);
649     }
650   if (fid_addr_type (dst) == FID_ADDR_IP_PREF)
651     {
652       ip_prefix_t *ippref = &fid_addr_ippref (dst);
653       ip_prefix_len (ippref) = LCAF_SD_DST_ML (sd_hdr);
654     }
655   return size;
656 }
657
658 u16
659 try_parse_src_dst_lcaf (u8 * p, gid_address_t * a)
660 {
661   lcaf_t lcaf;
662   u16 size = sizeof (u16);      /* skip AFI */
663
664   size += lcaf_hdr_parse (p + size, &lcaf);
665
666   if (LCAF_SOURCE_DEST != lcaf_type (&lcaf))
667     return ~0;
668
669   size += sd_parse (p + size, a);
670   return size;
671 }
672
673 u16
674 vni_parse (u8 * p, void *a)
675 {
676   lcaf_t *lcaf = a;
677   gid_address_t *g = a;
678   u16 size = 0;
679
680   gid_address_vni (g) = clib_net_to_host_u32 (*(u32 *) p);
681   size += sizeof (u32);
682   gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
683
684   /* nested LCAFs are not supported except of src/dst with vni - to handle
685    * such case look at the next AFI and process src/dest LCAF separately */
686   u16 afi = clib_net_to_host_u16 (*((u16 *) (p + size)));
687   if (LISP_AFI_LCAF == afi)
688     {
689       u16 len = try_parse_src_dst_lcaf (p + size, g);
690       if ((u16) ~ 0 == len)
691         return ~0;
692       size += len;
693     }
694   else
695     size += gid_address_parse (p + size, g);
696
697   return size;
698 }
699
700 u16
701 no_addr_parse (u8 * p, void *a)
702 {
703   /* do nothing */
704   return 0;
705 }
706
707 u32
708 lcaf_parse (void *offset, gid_address_t * addr)
709 {
710   /* skip AFI type */
711   offset += sizeof (u16);
712   lcaf_t *lcaf = &gid_address_lcaf (addr);
713
714   u32 size = lcaf_hdr_parse (offset, lcaf);
715   u8 type = lcaf_type (lcaf);
716
717   if (!lcaf_parse_fcts[type])
718     {
719       clib_warning ("Unsupported LCAF type: %u", type);
720       return ~0;
721     }
722   size += (*lcaf_parse_fcts[type]) (offset + size, lcaf);
723   return sizeof (u16) + size;
724 }
725
726 void
727 vni_free (void *a)
728 {
729   vni_t *v = a;
730   gid_address_free (vni_gid (v));
731   clib_mem_free (vni_gid (v));
732 }
733
734 void
735 no_addr_free (void *a)
736 {
737   /* nothing to do */
738 }
739
740 void
741 sd_free (void *a)
742 {
743   /* nothing */
744 }
745
746 void
747 gid_address_free (gid_address_t * a)
748 {
749   if (gid_address_type (a) != GID_ADDR_LCAF)
750     return;
751
752   lcaf_t *lcaf = &gid_address_lcaf (a);
753   u8 lcaf_type = lcaf_type (lcaf);
754   (*lcaf_free_fcts[lcaf_type]) (lcaf);
755 }
756
757 void
758 gid_address_from_ip (gid_address_t * g, ip_address_t * ip)
759 {
760   memset (g, 0, sizeof (g[0]));
761   ip_address_set (&gid_address_ip (g), ip, ip_addr_version (ip));
762   gid_address_ippref_len (g) = 32;
763 }
764
765 int
766 ip_address_cmp (const ip_address_t * ip1, const ip_address_t * ip2)
767 {
768   int res = 0;
769   if (ip_addr_version (ip1) != ip_addr_version (ip2))
770     return -1;
771   res =
772     memcmp (&ip_addr_addr (ip1), &ip_addr_addr (ip2), ip_address_size (ip1));
773
774   if (res < 0)
775     res = 2;
776   else if (res > 0)
777     res = 1;
778
779   return res;
780 }
781
782 void
783 ip_address_copy (ip_address_t * dst, const ip_address_t * src)
784 {
785   if (IP4 == ip_addr_version (src))
786     {
787       /* don't copy any garbe from the union */
788       memset (dst, 0, sizeof (*dst));
789       dst->ip.v4 = src->ip.v4;
790       dst->version = IP4;
791     }
792   else
793     {
794       clib_memcpy (dst, src, sizeof (ip_address_t));
795     }
796 }
797
798 void
799 ip_address_copy_addr (void *dst, const ip_address_t * src)
800 {
801   clib_memcpy (dst, src, ip_address_size (src));
802 }
803
804 void
805 ip_address_set (ip_address_t * dst, const void *src, u8 version)
806 {
807   clib_memcpy (dst, src, ip_version_to_size (version));
808   ip_addr_version (dst) = version;
809 }
810
811 void
812 ip_address_to_46 (const ip_address_t * addr,
813                   ip46_address_t * a, fib_protocol_t * proto)
814 {
815   *proto = (IP4 == ip_addr_version (addr) ?
816             FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
817   switch (*proto)
818     {
819     case FIB_PROTOCOL_IP4:
820       ip46_address_set_ip4 (a, &addr->ip.v4);
821       break;
822     case FIB_PROTOCOL_IP6:
823       a->ip6 = addr->ip.v6;
824       break;
825     default:
826       ASSERT (0);
827       break;
828     }
829 }
830
831 static void
832 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
833 {
834   u32 mask = ~0;
835
836   ASSERT (ip4);
837
838   if (32 <= preflen)
839     {
840       return;
841     }
842
843   mask = pow2_mask (preflen) << (32 - preflen);
844   mask = clib_host_to_net_u32 (mask);
845   ip4->data_u32 &= mask;
846 }
847
848 static void
849 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
850 {
851   u8 mask_6[16];
852   u32 *m;
853   u8 j, i0, i1;
854
855   ASSERT (ip6);
856
857   memset (mask_6, 0, sizeof (mask_6));
858
859   if (128 <= preflen)
860     {
861       return;
862     }
863
864   i1 = preflen % 32;
865   i0 = preflen / 32;
866   m = (u32 *) & mask_6[0];
867
868   for (j = 0; j < i0; j++)
869     {
870       m[j] = ~0;
871     }
872
873   if (i1)
874     {
875       m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
876     }
877
878   for (j = 0; j < sizeof (mask_6); j++)
879     {
880       ip6->as_u8[j] &= mask_6[j];
881     }
882 }
883
884 void
885 ip_prefix_normalize (ip_prefix_t * a)
886 {
887   u8 preflen = ip_prefix_len (a);
888
889   switch (ip_prefix_version (a))
890     {
891     case IP4:
892       ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
893       break;
894
895     case IP6:
896       ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
897       break;
898
899     default:
900       ASSERT (0);
901     }
902 }
903
904 void *
905 ip_prefix_cast (gid_address_t * a)
906 {
907   return &gid_address_ippref (a);
908 }
909
910 u16
911 ip_prefix_size_to_write (void *pref)
912 {
913   ip_prefix_t *a = (ip_prefix_t *) pref;
914   return ip_address_size_to_write (&ip_prefix_addr (a));
915 }
916
917 u16
918 ip_prefix_write (u8 * p, void *gid)
919 {
920   gid_address_t *g = gid;
921   ip_prefix_t *a = &gid_address_ippref (g);
922
923   switch (ip_prefix_version (a))
924     {
925     case IP4:
926       return ip4_address_put (p, &ip_prefix_v4 (a));
927       break;
928     case IP6:
929       return ip6_address_put (p, &ip_prefix_v6 (a));
930       break;
931     }
932   return 0;
933 }
934
935 u8
936 ip_prefix_length (void *a)
937 {
938   return ip_prefix_len ((ip_prefix_t *) a);
939 }
940
941 void
942 ip_prefix_copy (void *dst, void *src)
943 {
944   clib_memcpy (dst, src, sizeof (ip_prefix_t));
945 }
946
947 void
948 mac_copy (void *dst, void *src)
949 {
950   clib_memcpy (dst, src, 6);
951 }
952
953 void
954 sd_copy (void *dst, void *src)
955 {
956   clib_memcpy (dst, src, sizeof (source_dest_t));
957 }
958
959 void
960 nsh_copy (void *dst, void *src)
961 {
962   clib_memcpy (dst, src, sizeof (nsh_t));
963 }
964
965 int
966 ip_prefix_cmp (ip_prefix_t * p1, ip_prefix_t * p2)
967 {
968   int cmp = 0;
969
970   ip_prefix_normalize (p1);
971   ip_prefix_normalize (p2);
972
973   cmp = ip_address_cmp (&ip_prefix_addr (p1), &ip_prefix_addr (p2));
974   if (cmp == 0)
975     {
976       if (ip_prefix_len (p1) < ip_prefix_len (p2))
977         {
978           cmp = 1;
979         }
980       else
981         {
982           if (ip_prefix_len (p1) > ip_prefix_len (p2))
983             cmp = 2;
984         }
985     }
986   return cmp;
987 }
988
989 void
990 no_addr_copy (void *dst, void *src)
991 {
992   /* nothing to do */
993 }
994
995 void
996 vni_copy (void *dst, void *src)
997 {
998   vni_t *vd = dst;
999   vni_t *vs = src;
1000
1001   clib_memcpy (vd, vs, sizeof (vd[0]));
1002   vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
1003   gid_address_copy (vni_gid (vd), vni_gid (vs));
1004 }
1005
1006 void
1007 lcaf_copy (void *dst, void *src)
1008 {
1009   lcaf_t *lcaf_dst = dst;
1010   lcaf_t *lcaf_src = src;
1011
1012   lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
1013   (*lcaf_copy_fcts[lcaf_type (lcaf_src)]) (dst, src);
1014 }
1015
1016 u8
1017 lcaf_length (void *a)
1018 {
1019   return 0;
1020 }
1021
1022 u8
1023 mac_length (void *a)
1024 {
1025   return 0;
1026 }
1027
1028 u8
1029 sd_length (void *a)
1030 {
1031   return 0;
1032 }
1033
1034 u8
1035 nsh_length (void *a)
1036 {
1037   return 0;
1038 }
1039
1040 void *
1041 lcaf_cast (gid_address_t * a)
1042 {
1043   return &gid_address_lcaf (a);
1044 }
1045
1046 void *
1047 mac_cast (gid_address_t * a)
1048 {
1049   return &gid_address_mac (a);
1050 }
1051
1052 void *
1053 sd_cast (gid_address_t * a)
1054 {
1055   return &gid_address_sd (a);
1056 }
1057
1058 void *
1059 nsh_cast (gid_address_t * a)
1060 {
1061   return &gid_address_nsh (a);
1062 }
1063
1064 u8
1065 no_addr_length (void *a)
1066 {
1067   return 0;
1068 }
1069
1070 u8
1071 vni_length (void *a)
1072 {
1073   vni_t *v = a;
1074   return (sizeof (u32)          /* VNI size */
1075           + gid_address_size_to_put (vni_gid (v)) /* vni body size */ );
1076 }
1077
1078 u16
1079 lcaf_write (u8 * p, void *a)
1080 {
1081   u16 size = 0, len;
1082   lcaf_t *lcaf = a;
1083   u8 type = lcaf_type (lcaf);
1084   lcaf_hdr_t _h, *h = &_h;
1085
1086   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1087   size += sizeof (u16);
1088   memset (h, 0, sizeof (h[0]));
1089   LCAF_TYPE (h) = type;
1090   u16 lcaf_len = (*lcaf_body_length_fcts[type]) (lcaf);
1091   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1092
1093   clib_memcpy (p + size, h, sizeof (h[0]));
1094   size += sizeof (h[0]);
1095   len = (*lcaf_write_fcts[type]) (p + size, lcaf);
1096
1097   if ((u16) ~ 0 == len)
1098     return ~0;
1099
1100   return size + len;
1101 }
1102
1103 u16
1104 mac_write (u8 * p, void *a)
1105 {
1106   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_MAC);
1107   clib_memcpy (p + sizeof (u16), a, 6);
1108   return mac_size_to_write (a);
1109 }
1110
1111 static u16
1112 fid_addr_write (u8 * p, fid_address_t * a)
1113 {
1114   switch (fid_addr_type (a))
1115     {
1116     case FID_ADDR_IP_PREF:
1117       return ip_prefix_write (p, &fid_addr_ippref (a));
1118
1119     case FID_ADDR_MAC:
1120       return mac_write (p, &fid_addr_mac (a));
1121
1122     default:
1123       return ~0;
1124     }
1125   return ~0;
1126 }
1127
1128 static u8
1129 fid_address_length (fid_address_t * a)
1130 {
1131   switch (fid_addr_type (a))
1132     {
1133     case FID_ADDR_IP_PREF:
1134       return ip_prefix_length (&fid_addr_ippref (a));
1135     case FID_ADDR_MAC:
1136       return 0;
1137     case FID_ADDR_NSH:
1138       return 0;
1139     }
1140   return 0;
1141 }
1142
1143 u16
1144 sd_write (u8 * p, void *a)
1145 {
1146   source_dest_t *sd = a;
1147   u16 size = 0;
1148   lcaf_hdr_t _h, *h = &_h;
1149   lcaf_src_dst_hdr_t sd_hdr;
1150
1151   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1152   size += sizeof (u16);
1153   memset (h, 0, sizeof (h[0]));
1154   LCAF_TYPE (h) = LCAF_SOURCE_DEST;
1155   u16 lcaf_len = sizeof (lcaf_src_dst_hdr_t)
1156     + fid_addr_size_to_write (&sd_src (sd))
1157     + fid_addr_size_to_write (&sd_dst (sd));
1158   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1159
1160   clib_memcpy (p + size, h, sizeof (h[0]));
1161   size += sizeof (h[0]);
1162
1163   memset (&sd_hdr, 0, sizeof (sd_hdr));
1164   LCAF_SD_SRC_ML (&sd_hdr) = fid_address_length (&sd_src (sd));
1165   LCAF_SD_DST_ML (&sd_hdr) = fid_address_length (&sd_dst (sd));
1166   clib_memcpy (p + size, &sd_hdr, sizeof (sd_hdr));
1167   size += sizeof (sd_hdr);
1168
1169   u16 len = fid_addr_write (p + size, &sd_src (sd));
1170   if ((u16) ~ 0 == len)
1171     return ~0;
1172   size += len;
1173
1174   len = fid_addr_write (p + size, &sd_dst (sd));
1175   if ((u16) ~ 0 == len)
1176     return ~0;
1177   size += len;
1178
1179   return size;
1180 }
1181
1182 u16
1183 nsh_write (u8 * p, void *a)
1184 {
1185   clib_warning ("not done");
1186   return 0;
1187 }
1188
1189 u16
1190 vni_write (u8 * p, void *a)
1191 {
1192   lcaf_hdr_t _h, *h = &_h;
1193   gid_address_t *g = a;
1194   u16 size = 0, len;
1195
1196   /* put lcaf header */
1197   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1198   size += sizeof (u16);
1199   memset (h, 0, sizeof (h[0]));
1200   LCAF_TYPE (h) = LCAF_INSTANCE_ID;
1201   u16 lcaf_len = sizeof (u32)   /* Instance ID size */
1202     + gid_address_size_to_put_no_vni (g);
1203   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1204   LCAF_RES2 (h) = gid_address_vni_mask (g);
1205
1206   /* put vni header */
1207   clib_memcpy (p + size, h, sizeof (h[0]));
1208   size += sizeof (h[0]);
1209
1210   u32 *afip = (u32 *) (p + size);
1211   afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
1212   size += sizeof (u32);
1213
1214   if (GID_ADDR_SRC_DST == gid_address_type (g))
1215     /* write src/dst LCAF */
1216     {
1217       len = sd_write (p + size, g);
1218       if ((u16) ~ 0 == len)
1219         return ~0;
1220     }
1221   else
1222     /* write the actual address */
1223     len = gid_address_put_no_vni (p + size, g);
1224
1225   if ((u16) ~ 0 == len)
1226     return ~0;
1227
1228   return size + len;
1229 }
1230
1231 u16
1232 no_addr_write (u8 * p, void *a)
1233 {
1234   /* do nothing; return AFI field size */
1235   return sizeof (u16);
1236 }
1237
1238 u16
1239 no_addr_size_to_write (void *a)
1240 {
1241   return sizeof (u16);          /* AFI field length */
1242 }
1243
1244 static u16
1245 fid_addr_size_to_write (fid_address_t * a)
1246 {
1247   switch (fid_addr_type (a))
1248     {
1249     case FID_ADDR_IP_PREF:
1250       return ip_prefix_size_to_write (a);
1251
1252     case FID_ADDR_MAC:
1253       return mac_size_to_write (a);
1254
1255     default:
1256       break;
1257     }
1258   return 0;
1259 }
1260
1261 u16
1262 vni_size_to_write (void *a)
1263 {
1264   gid_address_t *g = a;
1265
1266   u16 lcaf_size = sizeof (u32) + sizeof (u16)   /* LCAF AFI field size */
1267     + sizeof (lcaf_hdr_t);
1268
1269   if (gid_address_type (g) == GID_ADDR_SRC_DST)
1270     /* special case where nested LCAF is supported */
1271     return lcaf_size + sd_size_to_write (g);
1272   else
1273     return lcaf_size + gid_address_size_to_put_no_vni (g);
1274 }
1275
1276 u16
1277 lcaf_size_to_write (void *a)
1278 {
1279   lcaf_t *lcaf = (lcaf_t *) a;
1280   u32 size = 0, len;
1281   u8 type = lcaf_type (lcaf);
1282
1283   size += sizeof (u16);         /* AFI size */
1284
1285   len = (*lcaf_size_to_write_fcts[type]) (lcaf);
1286   if (~0 == len)
1287     return ~0;
1288
1289   return size + len;
1290 }
1291
1292 u16
1293 sd_size_to_write (void *a)
1294 {
1295   source_dest_t *sd = a;
1296   return sizeof (u16)
1297     + sizeof (lcaf_hdr_t)
1298     + sizeof (lcaf_src_dst_hdr_t)
1299     + fid_addr_size_to_write (&sd_src (sd))
1300     + fid_addr_size_to_write (&sd_dst (sd));
1301 }
1302
1303 u16
1304 mac_size_to_write (void *a)
1305 {
1306   return sizeof (u16) + 6;
1307 }
1308
1309 u16
1310 nsh_size_to_write (void *a)
1311 {
1312   return sizeof (u16) + 4;
1313 }
1314
1315 u8
1316 gid_address_len (gid_address_t * a)
1317 {
1318   gid_address_type_t type = gid_address_type (a);
1319   return (*addr_len_fcts[type]) ((*cast_fcts[type]) (a));
1320 }
1321
1322 static u16
1323 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
1324 {
1325   gid_address_type_t type = gid_address_type (gid);
1326   return (*write_fcts[type]) (b, (*cast_fcts[type]) (gid));
1327 }
1328
1329 u16
1330 gid_address_put (u8 * b, gid_address_t * gid)
1331 {
1332   if (0 != gid_address_vni (gid))
1333     return vni_write (b, gid);
1334
1335   return gid_address_put_no_vni (b, gid);
1336 }
1337
1338 static u16
1339 gid_address_size_to_put_no_vni (gid_address_t * gid)
1340 {
1341   gid_address_type_t type = gid_address_type (gid);
1342   return (*size_to_write_fcts[type]) ((*cast_fcts[type]) (gid));
1343 }
1344
1345 u16
1346 gid_address_size_to_put (gid_address_t * gid)
1347 {
1348   if (0 != gid_address_vni (gid))
1349     return vni_size_to_write (gid);
1350
1351   return gid_address_size_to_put_no_vni (gid);
1352 }
1353
1354 void *
1355 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
1356 {
1357   return (*cast_fcts[type]) (gid);
1358 }
1359
1360 void
1361 gid_address_copy (gid_address_t * dst, gid_address_t * src)
1362 {
1363   gid_address_type_t type = gid_address_type (src);
1364   (*copy_fcts[type]) ((*cast_fcts[type]) (dst), (*cast_fcts[type]) (src));
1365   gid_address_type (dst) = type;
1366   gid_address_vni (dst) = gid_address_vni (src);
1367   gid_address_vni_mask (dst) = gid_address_vni_mask (src);
1368 }
1369
1370 u32
1371 mac_parse (u8 * offset, u8 * a)
1372 {
1373   /* skip AFI field */
1374   offset += sizeof (u16);
1375
1376   clib_memcpy (a, offset, 6);
1377   return sizeof (u16) + 6;
1378 }
1379
1380 u32
1381 gid_address_parse (u8 * offset, gid_address_t * a)
1382 {
1383   lisp_afi_e afi;
1384   int len = 0;
1385
1386   if (!a)
1387     return 0;
1388
1389   /* NOTE: since gid_address_parse may be called by vni_parse, we can't 0
1390    * the gid address here */
1391   afi = clib_net_to_host_u16 (*((u16 *) offset));
1392
1393   switch (afi)
1394     {
1395     case LISP_AFI_NO_ADDR:
1396       len = sizeof (u16);
1397       gid_address_type (a) = GID_ADDR_NO_ADDRESS;
1398       break;
1399     case LISP_AFI_IP:
1400       len = ip_address_parse (offset, afi, &gid_address_ip (a));
1401       gid_address_type (a) = GID_ADDR_IP_PREFIX;
1402       /* this should be modified outside if needed */
1403       gid_address_ippref_len (a) = 32;
1404       break;
1405     case LISP_AFI_IP6:
1406       len = ip_address_parse (offset, afi, &gid_address_ip (a));
1407       gid_address_type (a) = GID_ADDR_IP_PREFIX;
1408       /* this should be modified outside if needed */
1409       gid_address_ippref_len (a) = 128;
1410       break;
1411     case LISP_AFI_LCAF:
1412       gid_address_type (a) = GID_ADDR_LCAF;
1413       len = lcaf_parse (offset, a);
1414       break;
1415     case LISP_AFI_MAC:
1416       len = mac_parse (offset, gid_address_mac (a));
1417       gid_address_type (a) = GID_ADDR_MAC;
1418       break;
1419     default:
1420       clib_warning ("LISP AFI %d not supported!", afi);
1421       return ~0;
1422     }
1423   return len;
1424 }
1425
1426 void
1427 gid_address_ip_set (gid_address_t * dst, void *src, u8 version)
1428 {
1429   gid_address_ippref_len (dst) = ip_address_max_len (version);
1430   ip_address_set (&gid_address_ip (dst), src, version);
1431 }
1432
1433 int
1434 no_addr_cmp (void *a1, void *a2)
1435 {
1436   return 0;
1437 }
1438
1439 int
1440 vni_cmp (void *a1, void *a2)
1441 {
1442   vni_t *v1 = a1;
1443   vni_t *v2 = a2;
1444
1445   if (vni_mask_len (v1) != vni_mask_len (v2))
1446     return -1;
1447   if (vni_vni (v1) != vni_vni (v2))
1448     return -1;
1449   return gid_address_cmp (vni_gid (v1), vni_gid (v2));
1450 }
1451
1452 static int
1453 mac_cmp (void *a1, void *a2)
1454 {
1455   return memcmp (a1, a2, 6);
1456 }
1457
1458 static int
1459 fid_addr_cmp (fid_address_t * a1, fid_address_t * a2)
1460 {
1461   if (fid_addr_type (a1) != fid_addr_type (a2))
1462     return -1;
1463
1464   switch (fid_addr_type (a1))
1465     {
1466     case FID_ADDR_IP_PREF:
1467       return ip_prefix_cmp (&fid_addr_ippref (a1), &fid_addr_ippref (a2));
1468
1469     case FID_ADDR_MAC:
1470       return mac_cmp (fid_addr_mac (a1), fid_addr_mac (a2));
1471
1472     default:
1473       return -1;
1474     }
1475   return -1;
1476 }
1477
1478 int
1479 sd_cmp (void *a1, void *a2)
1480 {
1481   source_dest_t *sd1 = a1;
1482   source_dest_t *sd2 = a2;
1483
1484   if (fid_addr_cmp (&sd_dst (sd1), &sd_dst (sd2)))
1485     return -1;
1486   if (fid_addr_cmp (&sd_src (sd1), &sd_src (sd2)))
1487     return -1;
1488   return 0;
1489 }
1490
1491 /* Compare two gid_address_t.
1492  * Returns:
1493  *        -1: If they are from different afi
1494  *             0: Both address are the same
1495  *             1: Addr1 is bigger than addr2
1496  *             2: Addr2 is bigger than addr1
1497  */
1498 int
1499 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
1500 {
1501   lcaf_t *lcaf1, *lcaf2;
1502   int cmp = -1;
1503   if (!a1 || !a2)
1504     return -1;
1505   if (gid_address_type (a1) != gid_address_type (a2))
1506     return -1;
1507   if (gid_address_vni (a1) != gid_address_vni (a2))
1508     return -1;
1509
1510   /* TODO vni mask is not supported, disable comparing for now
1511      if (gid_address_vni_mask (a1) != gid_address_vni_mask (a2))
1512      return -1;
1513    */
1514
1515   switch (gid_address_type (a1))
1516     {
1517     case GID_ADDR_NO_ADDRESS:
1518       if (a1 == a2)
1519         cmp = 0;
1520       else
1521         cmp = 2;
1522       break;
1523     case GID_ADDR_IP_PREFIX:
1524       cmp =
1525         ip_prefix_cmp (&gid_address_ippref (a1), &gid_address_ippref (a2));
1526       break;
1527     case GID_ADDR_LCAF:
1528       lcaf1 = &gid_address_lcaf (a1);
1529       lcaf2 = &gid_address_lcaf (a2);
1530       if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
1531         cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)]) (lcaf1, lcaf2);
1532       break;
1533     case GID_ADDR_MAC:
1534       cmp = mac_cmp (gid_address_mac (a1), gid_address_mac (a2));
1535       break;
1536
1537     case GID_ADDR_SRC_DST:
1538       cmp = sd_cmp (&gid_address_sd (a1), &gid_address_sd (a2));
1539       break;
1540     default:
1541       break;
1542     }
1543
1544   return cmp;
1545 }
1546
1547 u32
1548 locator_parse (void *b, locator_t * loc)
1549 {
1550   locator_hdr_t *h;
1551   u8 status = 1;                /* locator up */
1552   int len;
1553
1554   h = b;
1555   if (!LOC_REACHABLE (h) && LOC_LOCAL (h))
1556     status = 0;
1557
1558   len = gid_address_parse (LOC_ADDR (h), &loc->address);
1559   if (len == ~0)
1560     return len;
1561
1562   loc->state = status;
1563   loc->local = 0;
1564   loc->priority = LOC_PRIORITY (h);
1565   loc->weight = LOC_WEIGHT (h);
1566   loc->mpriority = LOC_MPRIORITY (h);
1567   loc->mweight = LOC_MWEIGHT (h);
1568
1569   return sizeof (locator_hdr_t) + len;
1570 }
1571
1572 void
1573 locator_copy (locator_t * dst, locator_t * src)
1574 {
1575   /* TODO if gid become more complex, this will need to be changed! */
1576   clib_memcpy (dst, src, sizeof (*dst));
1577   if (!src->local)
1578     gid_address_copy (&dst->address, &src->address);
1579 }
1580
1581 u32
1582 locator_cmp (locator_t * l1, locator_t * l2)
1583 {
1584   u32 ret = 0;
1585   if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
1586     return 1;
1587
1588   if (l1->priority != l2->priority)
1589     return 1;
1590   if (l1->weight != l2->weight)
1591     return 1;
1592   if (l1->mpriority != l2->mpriority)
1593     return 1;
1594   if (l1->mweight != l2->mweight)
1595     return 1;
1596   return 0;
1597 }
1598
1599 void
1600 locator_free (locator_t * l)
1601 {
1602   if (!l->local)
1603     gid_address_free (&l->address);
1604 }
1605
1606 void
1607 build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst)
1608 {
1609   memset (sd, 0, sizeof (*sd));
1610   gid_address_type (sd) = GID_ADDR_SRC_DST;
1611   gid_address_vni (sd) = gid_address_vni (dst);
1612   gid_address_vni_mask (sd) = gid_address_vni_mask (dst);
1613
1614   switch (gid_address_type (dst))
1615     {
1616     case GID_ADDR_IP_PREFIX:
1617       gid_address_sd_src_type (sd) = FID_ADDR_IP_PREF;
1618       gid_address_sd_dst_type (sd) = FID_ADDR_IP_PREF;
1619       ip_prefix_copy (&gid_address_sd_src_ippref (sd),
1620                       &gid_address_ippref (src));
1621       ip_prefix_copy (&gid_address_sd_dst_ippref (sd),
1622                       &gid_address_ippref (dst));
1623       break;
1624     case GID_ADDR_MAC:
1625       gid_address_sd_src_type (sd) = FID_ADDR_MAC;
1626       gid_address_sd_dst_type (sd) = FID_ADDR_MAC;
1627       mac_copy (gid_address_sd_src_mac (sd), gid_address_mac (src));
1628       mac_copy (gid_address_sd_dst_mac (sd), gid_address_mac (dst));
1629       break;
1630     default:
1631       clib_warning ("Unsupported gid type %d while conversion!",
1632                     gid_address_type (dst));
1633       break;
1634     }
1635 }
1636
1637 /*
1638  * fd.io coding-style-patch-verification: ON
1639  *
1640  * Local Variables:
1641  * eval: (c-set-style "gnu")
1642  * End:
1643  */