Basic support for LISP-GPE encapsulated NSH packets
[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
35 };
36 serdes_fct write_fcts[GID_ADDR_TYPES] =
37   { ip_prefix_write, lcaf_write, mac_write, sd_write };
38 cast_fct cast_fcts[GID_ADDR_TYPES] =
39   { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast };
40 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
41   { ip_prefix_length, lcaf_length, mac_length, sd_length };
42 copy_fct copy_fcts[GID_ADDR_TYPES] =
43   { ip_prefix_copy, lcaf_copy, mac_copy, sd_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 nsh_copy (void *dst, void *src)
955 {
956   clib_memcpy (dst, src, sizeof (nsh_t));
957 }
958
959 void
960 sd_copy (void *dst, void *src)
961 {
962   clib_memcpy (dst, src, sizeof (source_dest_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 void *
1035 lcaf_cast (gid_address_t * a)
1036 {
1037   return &gid_address_lcaf (a);
1038 }
1039
1040 void *
1041 mac_cast (gid_address_t * a)
1042 {
1043   return &gid_address_mac (a);
1044 }
1045
1046 void *
1047 sd_cast (gid_address_t * a)
1048 {
1049   return &gid_address_sd (a);
1050 }
1051
1052 u8
1053 no_addr_length (void *a)
1054 {
1055   return 0;
1056 }
1057
1058 u8
1059 vni_length (void *a)
1060 {
1061   vni_t *v = a;
1062   return (sizeof (u32)          /* VNI size */
1063           + gid_address_size_to_put (vni_gid (v)) /* vni body size */ );
1064 }
1065
1066 u16
1067 lcaf_write (u8 * p, void *a)
1068 {
1069   u16 size = 0, len;
1070   lcaf_t *lcaf = a;
1071   u8 type = lcaf_type (lcaf);
1072   lcaf_hdr_t _h, *h = &_h;
1073
1074   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1075   size += sizeof (u16);
1076   memset (h, 0, sizeof (h[0]));
1077   LCAF_TYPE (h) = type;
1078   u16 lcaf_len = (*lcaf_body_length_fcts[type]) (lcaf);
1079   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1080
1081   clib_memcpy (p + size, h, sizeof (h[0]));
1082   size += sizeof (h[0]);
1083   len = (*lcaf_write_fcts[type]) (p + size, lcaf);
1084
1085   if ((u16) ~ 0 == len)
1086     return ~0;
1087
1088   return size + len;
1089 }
1090
1091 u16
1092 mac_write (u8 * p, void *a)
1093 {
1094   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_MAC);
1095   clib_memcpy (p + sizeof (u16), a, 6);
1096   return mac_size_to_write (a);
1097 }
1098
1099 static u16
1100 fid_addr_write (u8 * p, fid_address_t * a)
1101 {
1102   switch (fid_addr_type (a))
1103     {
1104     case FID_ADDR_IP_PREF:
1105       return ip_prefix_write (p, &fid_addr_ippref (a));
1106
1107     case FID_ADDR_MAC:
1108       return mac_write (p, &fid_addr_mac (a));
1109
1110     default:
1111       return ~0;
1112     }
1113   return ~0;
1114 }
1115
1116 static u8
1117 fid_address_length (fid_address_t * a)
1118 {
1119   switch (fid_addr_type (a))
1120     {
1121     case FID_ADDR_IP_PREF:
1122       return ip_prefix_length (&fid_addr_ippref (a));
1123     case FID_ADDR_MAC:
1124       return 0;
1125     case FID_ADDR_NSH:
1126       return 0;
1127     }
1128   return 0;
1129 }
1130
1131 u16
1132 sd_write (u8 * p, void *a)
1133 {
1134   source_dest_t *sd = a;
1135   u16 size = 0;
1136   lcaf_hdr_t _h, *h = &_h;
1137   lcaf_src_dst_hdr_t sd_hdr;
1138
1139   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1140   size += sizeof (u16);
1141   memset (h, 0, sizeof (h[0]));
1142   LCAF_TYPE (h) = LCAF_SOURCE_DEST;
1143   u16 lcaf_len = sizeof (lcaf_src_dst_hdr_t)
1144     + fid_addr_size_to_write (&sd_src (sd))
1145     + fid_addr_size_to_write (&sd_dst (sd));
1146   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1147
1148   clib_memcpy (p + size, h, sizeof (h[0]));
1149   size += sizeof (h[0]);
1150
1151   memset (&sd_hdr, 0, sizeof (sd_hdr));
1152   LCAF_SD_SRC_ML (&sd_hdr) = fid_address_length (&sd_src (sd));
1153   LCAF_SD_DST_ML (&sd_hdr) = fid_address_length (&sd_dst (sd));
1154   clib_memcpy (p + size, &sd_hdr, sizeof (sd_hdr));
1155   size += sizeof (sd_hdr);
1156
1157   u16 len = fid_addr_write (p + size, &sd_src (sd));
1158   if ((u16) ~ 0 == len)
1159     return ~0;
1160   size += len;
1161
1162   len = fid_addr_write (p + size, &sd_dst (sd));
1163   if ((u16) ~ 0 == len)
1164     return ~0;
1165   size += len;
1166
1167   return size;
1168 }
1169
1170 u16
1171 vni_write (u8 * p, void *a)
1172 {
1173   lcaf_hdr_t _h, *h = &_h;
1174   gid_address_t *g = a;
1175   u16 size = 0, len;
1176
1177   /* put lcaf header */
1178   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1179   size += sizeof (u16);
1180   memset (h, 0, sizeof (h[0]));
1181   LCAF_TYPE (h) = LCAF_INSTANCE_ID;
1182   u16 lcaf_len = sizeof (u32)   /* Instance ID size */
1183     + gid_address_size_to_put_no_vni (g);
1184   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1185   LCAF_RES2 (h) = gid_address_vni_mask (g);
1186
1187   /* put vni header */
1188   clib_memcpy (p + size, h, sizeof (h[0]));
1189   size += sizeof (h[0]);
1190
1191   u32 *afip = (u32 *) (p + size);
1192   afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
1193   size += sizeof (u32);
1194
1195   if (GID_ADDR_SRC_DST == gid_address_type (g))
1196     /* write src/dst LCAF */
1197     {
1198       len = sd_write (p + size, g);
1199       if ((u16) ~ 0 == len)
1200         return ~0;
1201     }
1202   else
1203     /* write the actual address */
1204     len = gid_address_put_no_vni (p + size, g);
1205
1206   if ((u16) ~ 0 == len)
1207     return ~0;
1208
1209   return size + len;
1210 }
1211
1212 u16
1213 no_addr_write (u8 * p, void *a)
1214 {
1215   /* do nothing; return AFI field size */
1216   return sizeof (u16);
1217 }
1218
1219 u16
1220 no_addr_size_to_write (void *a)
1221 {
1222   return sizeof (u16);          /* AFI field length */
1223 }
1224
1225 static u16
1226 fid_addr_size_to_write (fid_address_t * a)
1227 {
1228   switch (fid_addr_type (a))
1229     {
1230     case FID_ADDR_IP_PREF:
1231       return ip_prefix_size_to_write (a);
1232
1233     case FID_ADDR_MAC:
1234       return mac_size_to_write (a);
1235
1236     default:
1237       break;
1238     }
1239   return 0;
1240 }
1241
1242 u16
1243 vni_size_to_write (void *a)
1244 {
1245   gid_address_t *g = a;
1246
1247   u16 lcaf_size = sizeof (u32) + sizeof (u16)   /* LCAF AFI field size */
1248     + sizeof (lcaf_hdr_t);
1249
1250   if (gid_address_type (g) == GID_ADDR_SRC_DST)
1251     /* special case where nested LCAF is supported */
1252     return lcaf_size + sd_size_to_write (g);
1253   else
1254     return lcaf_size + gid_address_size_to_put_no_vni (g);
1255 }
1256
1257 u16
1258 lcaf_size_to_write (void *a)
1259 {
1260   lcaf_t *lcaf = (lcaf_t *) a;
1261   u32 size = 0, len;
1262   u8 type = lcaf_type (lcaf);
1263
1264   size += sizeof (u16);         /* AFI size */
1265
1266   len = (*lcaf_size_to_write_fcts[type]) (lcaf);
1267   if (~0 == len)
1268     return ~0;
1269
1270   return size + len;
1271 }
1272
1273 u16
1274 sd_size_to_write (void *a)
1275 {
1276   source_dest_t *sd = a;
1277   return sizeof (u16)
1278     + sizeof (lcaf_hdr_t)
1279     + sizeof (lcaf_src_dst_hdr_t)
1280     + fid_addr_size_to_write (&sd_src (sd))
1281     + fid_addr_size_to_write (&sd_dst (sd));
1282 }
1283
1284 u16
1285 mac_size_to_write (void *a)
1286 {
1287   return sizeof (u16) + 6;
1288 }
1289
1290 u8
1291 gid_address_len (gid_address_t * a)
1292 {
1293   gid_address_type_t type = gid_address_type (a);
1294   return (*addr_len_fcts[type]) ((*cast_fcts[type]) (a));
1295 }
1296
1297 static u16
1298 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
1299 {
1300   gid_address_type_t type = gid_address_type (gid);
1301   return (*write_fcts[type]) (b, (*cast_fcts[type]) (gid));
1302 }
1303
1304 u16
1305 gid_address_put (u8 * b, gid_address_t * gid)
1306 {
1307   if (0 != gid_address_vni (gid))
1308     return vni_write (b, gid);
1309
1310   return gid_address_put_no_vni (b, gid);
1311 }
1312
1313 static u16
1314 gid_address_size_to_put_no_vni (gid_address_t * gid)
1315 {
1316   gid_address_type_t type = gid_address_type (gid);
1317   return (*size_to_write_fcts[type]) ((*cast_fcts[type]) (gid));
1318 }
1319
1320 u16
1321 gid_address_size_to_put (gid_address_t * gid)
1322 {
1323   if (0 != gid_address_vni (gid))
1324     return vni_size_to_write (gid);
1325
1326   return gid_address_size_to_put_no_vni (gid);
1327 }
1328
1329 void *
1330 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
1331 {
1332   return (*cast_fcts[type]) (gid);
1333 }
1334
1335 void
1336 gid_address_copy (gid_address_t * dst, gid_address_t * src)
1337 {
1338   gid_address_type_t type = gid_address_type (src);
1339   (*copy_fcts[type]) ((*cast_fcts[type]) (dst), (*cast_fcts[type]) (src));
1340   gid_address_type (dst) = type;
1341   gid_address_vni (dst) = gid_address_vni (src);
1342   gid_address_vni_mask (dst) = gid_address_vni_mask (src);
1343 }
1344
1345 u32
1346 mac_parse (u8 * offset, u8 * a)
1347 {
1348   /* skip AFI field */
1349   offset += sizeof (u16);
1350
1351   clib_memcpy (a, offset, 6);
1352   return sizeof (u16) + 6;
1353 }
1354
1355 u32
1356 gid_address_parse (u8 * offset, gid_address_t * a)
1357 {
1358   lisp_afi_e afi;
1359   int len = 0;
1360
1361   if (!a)
1362     return 0;
1363
1364   /* NOTE: since gid_address_parse may be called by vni_parse, we can't 0
1365    * the gid address here */
1366   afi = clib_net_to_host_u16 (*((u16 *) offset));
1367
1368   switch (afi)
1369     {
1370     case LISP_AFI_NO_ADDR:
1371       len = sizeof (u16);
1372       gid_address_type (a) = GID_ADDR_NO_ADDRESS;
1373       break;
1374     case LISP_AFI_IP:
1375       len = ip_address_parse (offset, afi, &gid_address_ip (a));
1376       gid_address_type (a) = GID_ADDR_IP_PREFIX;
1377       /* this should be modified outside if needed */
1378       gid_address_ippref_len (a) = 32;
1379       break;
1380     case LISP_AFI_IP6:
1381       len = ip_address_parse (offset, afi, &gid_address_ip (a));
1382       gid_address_type (a) = GID_ADDR_IP_PREFIX;
1383       /* this should be modified outside if needed */
1384       gid_address_ippref_len (a) = 128;
1385       break;
1386     case LISP_AFI_LCAF:
1387       gid_address_type (a) = GID_ADDR_LCAF;
1388       len = lcaf_parse (offset, a);
1389       break;
1390     case LISP_AFI_MAC:
1391       len = mac_parse (offset, gid_address_mac (a));
1392       gid_address_type (a) = GID_ADDR_MAC;
1393       break;
1394     default:
1395       clib_warning ("LISP AFI %d not supported!", afi);
1396       return ~0;
1397     }
1398   return len;
1399 }
1400
1401 void
1402 gid_address_ip_set (gid_address_t * dst, void *src, u8 version)
1403 {
1404   gid_address_ippref_len (dst) = ip_address_max_len (version);
1405   ip_address_set (&gid_address_ip (dst), src, version);
1406 }
1407
1408 int
1409 no_addr_cmp (void *a1, void *a2)
1410 {
1411   return 0;
1412 }
1413
1414 int
1415 vni_cmp (void *a1, void *a2)
1416 {
1417   vni_t *v1 = a1;
1418   vni_t *v2 = a2;
1419
1420   if (vni_mask_len (v1) != vni_mask_len (v2))
1421     return -1;
1422   if (vni_vni (v1) != vni_vni (v2))
1423     return -1;
1424   return gid_address_cmp (vni_gid (v1), vni_gid (v2));
1425 }
1426
1427 static int
1428 mac_cmp (void *a1, void *a2)
1429 {
1430   return memcmp (a1, a2, 6);
1431 }
1432
1433 static int
1434 fid_addr_cmp (fid_address_t * a1, fid_address_t * a2)
1435 {
1436   if (fid_addr_type (a1) != fid_addr_type (a2))
1437     return -1;
1438
1439   switch (fid_addr_type (a1))
1440     {
1441     case FID_ADDR_IP_PREF:
1442       return ip_prefix_cmp (&fid_addr_ippref (a1), &fid_addr_ippref (a2));
1443
1444     case FID_ADDR_MAC:
1445       return mac_cmp (fid_addr_mac (a1), fid_addr_mac (a2));
1446
1447     default:
1448       return -1;
1449     }
1450   return -1;
1451 }
1452
1453 int
1454 sd_cmp (void *a1, void *a2)
1455 {
1456   source_dest_t *sd1 = a1;
1457   source_dest_t *sd2 = a2;
1458
1459   if (fid_addr_cmp (&sd_dst (sd1), &sd_dst (sd2)))
1460     return -1;
1461   if (fid_addr_cmp (&sd_src (sd1), &sd_src (sd2)))
1462     return -1;
1463   return 0;
1464 }
1465
1466 /* Compare two gid_address_t.
1467  * Returns:
1468  *        -1: If they are from different afi
1469  *             0: Both address are the same
1470  *             1: Addr1 is bigger than addr2
1471  *             2: Addr2 is bigger than addr1
1472  */
1473 int
1474 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
1475 {
1476   lcaf_t *lcaf1, *lcaf2;
1477   int cmp = -1;
1478   if (!a1 || !a2)
1479     return -1;
1480   if (gid_address_type (a1) != gid_address_type (a2))
1481     return -1;
1482   if (gid_address_vni (a1) != gid_address_vni (a2))
1483     return -1;
1484
1485   /* TODO vni mask is not supported, disable comparing for now
1486      if (gid_address_vni_mask (a1) != gid_address_vni_mask (a2))
1487      return -1;
1488    */
1489
1490   switch (gid_address_type (a1))
1491     {
1492     case GID_ADDR_NO_ADDRESS:
1493       if (a1 == a2)
1494         cmp = 0;
1495       else
1496         cmp = 2;
1497       break;
1498     case GID_ADDR_IP_PREFIX:
1499       cmp =
1500         ip_prefix_cmp (&gid_address_ippref (a1), &gid_address_ippref (a2));
1501       break;
1502     case GID_ADDR_LCAF:
1503       lcaf1 = &gid_address_lcaf (a1);
1504       lcaf2 = &gid_address_lcaf (a2);
1505       if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
1506         cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)]) (lcaf1, lcaf2);
1507       break;
1508     case GID_ADDR_MAC:
1509       cmp = mac_cmp (gid_address_mac (a1), gid_address_mac (a2));
1510       break;
1511
1512     case GID_ADDR_SRC_DST:
1513       cmp = sd_cmp (&gid_address_sd (a1), &gid_address_sd (a2));
1514       break;
1515     default:
1516       break;
1517     }
1518
1519   return cmp;
1520 }
1521
1522 u32
1523 locator_parse (void *b, locator_t * loc)
1524 {
1525   locator_hdr_t *h;
1526   u8 status = 1;                /* locator up */
1527   int len;
1528
1529   h = b;
1530   if (!LOC_REACHABLE (h) && LOC_LOCAL (h))
1531     status = 0;
1532
1533   len = gid_address_parse (LOC_ADDR (h), &loc->address);
1534   if (len == ~0)
1535     return len;
1536
1537   loc->state = status;
1538   loc->local = 0;
1539   loc->priority = LOC_PRIORITY (h);
1540   loc->weight = LOC_WEIGHT (h);
1541   loc->mpriority = LOC_MPRIORITY (h);
1542   loc->mweight = LOC_MWEIGHT (h);
1543
1544   return sizeof (locator_hdr_t) + len;
1545 }
1546
1547 void
1548 locator_copy (locator_t * dst, locator_t * src)
1549 {
1550   /* TODO if gid become more complex, this will need to be changed! */
1551   clib_memcpy (dst, src, sizeof (*dst));
1552   if (!src->local)
1553     gid_address_copy (&dst->address, &src->address);
1554 }
1555
1556 u32
1557 locator_cmp (locator_t * l1, locator_t * l2)
1558 {
1559   u32 ret = 0;
1560   if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
1561     return 1;
1562
1563   if (l1->priority != l2->priority)
1564     return 1;
1565   if (l1->weight != l2->weight)
1566     return 1;
1567   if (l1->mpriority != l2->mpriority)
1568     return 1;
1569   if (l1->mweight != l2->mweight)
1570     return 1;
1571   return 0;
1572 }
1573
1574 void
1575 locator_free (locator_t * l)
1576 {
1577   if (!l->local)
1578     gid_address_free (&l->address);
1579 }
1580
1581 void
1582 build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst)
1583 {
1584   memset (sd, 0, sizeof (*sd));
1585   gid_address_type (sd) = GID_ADDR_SRC_DST;
1586   gid_address_vni (sd) = gid_address_vni (dst);
1587   gid_address_vni_mask (sd) = gid_address_vni_mask (dst);
1588
1589   switch (gid_address_type (dst))
1590     {
1591     case GID_ADDR_IP_PREFIX:
1592       gid_address_sd_src_type (sd) = FID_ADDR_IP_PREF;
1593       gid_address_sd_dst_type (sd) = FID_ADDR_IP_PREF;
1594       ip_prefix_copy (&gid_address_sd_src_ippref (sd),
1595                       &gid_address_ippref (src));
1596       ip_prefix_copy (&gid_address_sd_dst_ippref (sd),
1597                       &gid_address_ippref (dst));
1598       break;
1599     case GID_ADDR_MAC:
1600       gid_address_sd_src_type (sd) = FID_ADDR_MAC;
1601       gid_address_sd_dst_type (sd) = FID_ADDR_MAC;
1602       mac_copy (gid_address_sd_src_mac (sd), gid_address_mac (src));
1603       mac_copy (gid_address_sd_dst_mac (sd), gid_address_mac (dst));
1604       break;
1605     default:
1606       clib_warning ("Unsupported gid type %d while conversion!",
1607                     gid_address_type (dst));
1608       break;
1609     }
1610 }
1611
1612 /*
1613  * fd.io coding-style-patch-verification: ON
1614  *
1615  * Local Variables:
1616  * eval: (c-set-style "gnu")
1617  * End:
1618  */