LISP statistics
[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 void
577 gid_to_dp_address (gid_address_t * g, dp_address_t * d)
578 {
579   switch (gid_address_type (g))
580     {
581     case GID_ADDR_SRC_DST:
582       switch (gid_address_sd_dst_type (g))
583         {
584         case FID_ADDR_IP_PREF:
585           ip_prefix_copy (&d->ippref, &gid_address_sd_dst_ippref (g));
586           d->type = FID_ADDR_IP_PREF;
587           break;
588         case FID_ADDR_MAC:
589           mac_copy (&d->mac, &gid_address_sd_dst_mac (g));
590           d->type = FID_ADDR_MAC;
591           break;
592         default:
593           clib_warning ("Source/Dest address type %d not supported!",
594                         gid_address_sd_dst_type (g));
595           break;
596         }
597       break;
598     case GID_ADDR_IP_PREFIX:
599       ip_prefix_copy (&d->ippref, &gid_address_ippref (g));
600       d->type = FID_ADDR_IP_PREF;
601       break;
602     case GID_ADDR_MAC:
603       mac_copy (&d->mac, &gid_address_mac (g));
604       d->type = FID_ADDR_MAC;
605       break;
606     case GID_ADDR_NSH:
607     default:
608       d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si;
609       d->type = FID_ADDR_NSH;
610       break;
611     }
612 }
613
614 u32
615 lcaf_hdr_parse (void *offset, lcaf_t * lcaf)
616 {
617   lcaf_hdr_t *lh = offset;
618   lcaf->type = lh->type;
619
620   /* this is a bit of hack: since the LCAF Instance ID is the
621      only message that uses reserved2 field, we can set it here.
622      If any LCAF format starts using reserved2 field as well this needs
623      to be moved elsewhere */
624   lcaf_vni_len (lcaf) = lh->reserved2;
625
626   return sizeof (lh[0]);
627 }
628
629 static u8
630 iana_afi_to_fid_addr_type (u16 type)
631 {
632   switch (type)
633     {
634     case LISP_AFI_IP:
635     case LISP_AFI_IP6:
636       return FID_ADDR_IP_PREF;
637
638     case LISP_AFI_MAC:
639       return FID_ADDR_MAC;
640     }
641   return ~0;
642 }
643
644 static u16
645 fid_addr_parse (u8 * p, fid_address_t * a)
646 {
647   u16 afi = clib_net_to_host_u16 (*(u16 *) p);
648   fid_addr_type (a) = iana_afi_to_fid_addr_type (afi);
649   ip_address_t *ip_addr = &ip_prefix_addr (&fid_addr_ippref (a));
650
651   switch (fid_addr_type (a))
652     {
653     case FID_ADDR_MAC:
654       return mac_parse (p, fid_addr_mac (a));
655
656     case FID_ADDR_IP_PREF:
657       return ip_address_parse (p, afi, ip_addr);
658
659     case FID_ADDR_NSH:
660       ASSERT (0);
661       break;
662     }
663   return ~0;
664 }
665
666 u16
667 sd_parse (u8 * p, void *a)
668 {
669   lcaf_src_dst_hdr_t *sd_hdr;
670   gid_address_t *g = a;
671   u16 size = 0;
672   fid_address_t *src = &gid_address_sd_src (g);
673   fid_address_t *dst = &gid_address_sd_dst (g);
674
675   gid_address_type (g) = GID_ADDR_SRC_DST;
676
677   sd_hdr = (lcaf_src_dst_hdr_t *) (p + size);
678   size += sizeof (sd_hdr[0]);
679
680   size += fid_addr_parse (p + size, src);
681   size += fid_addr_parse (p + size, dst);
682
683   if (fid_addr_type (src) == FID_ADDR_IP_PREF)
684     {
685       ip_prefix_t *ippref = &fid_addr_ippref (src);
686       ip_prefix_len (ippref) = LCAF_SD_SRC_ML (sd_hdr);
687     }
688   if (fid_addr_type (dst) == FID_ADDR_IP_PREF)
689     {
690       ip_prefix_t *ippref = &fid_addr_ippref (dst);
691       ip_prefix_len (ippref) = LCAF_SD_DST_ML (sd_hdr);
692     }
693   return size;
694 }
695
696 u16
697 try_parse_src_dst_lcaf (u8 * p, gid_address_t * a)
698 {
699   lcaf_t lcaf;
700   u16 size = sizeof (u16);      /* skip AFI */
701
702   size += lcaf_hdr_parse (p + size, &lcaf);
703
704   if (LCAF_SOURCE_DEST != lcaf_type (&lcaf))
705     return ~0;
706
707   size += sd_parse (p + size, a);
708   return size;
709 }
710
711 u16
712 vni_parse (u8 * p, void *a)
713 {
714   lcaf_t *lcaf = a;
715   gid_address_t *g = a;
716   u16 size = 0;
717
718   gid_address_vni (g) = clib_net_to_host_u32 (*(u32 *) p);
719   size += sizeof (u32);
720   gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
721
722   /* nested LCAFs are not supported except of src/dst with vni - to handle
723    * such case look at the next AFI and process src/dest LCAF separately */
724   u16 afi = clib_net_to_host_u16 (*((u16 *) (p + size)));
725   if (LISP_AFI_LCAF == afi)
726     {
727       u16 len = try_parse_src_dst_lcaf (p + size, g);
728       if ((u16) ~ 0 == len)
729         return ~0;
730       size += len;
731     }
732   else
733     size += gid_address_parse (p + size, g);
734
735   return size;
736 }
737
738 u16
739 no_addr_parse (u8 * p, void *a)
740 {
741   /* do nothing */
742   return 0;
743 }
744
745 u32
746 lcaf_parse (void *offset, gid_address_t * addr)
747 {
748   /* skip AFI type */
749   offset += sizeof (u16);
750   lcaf_t *lcaf = &gid_address_lcaf (addr);
751
752   u32 size = lcaf_hdr_parse (offset, lcaf);
753   u8 type = lcaf_type (lcaf);
754
755   if (!lcaf_parse_fcts[type])
756     {
757       clib_warning ("Unsupported LCAF type: %u", type);
758       return ~0;
759     }
760   size += (*lcaf_parse_fcts[type]) (offset + size, lcaf);
761   return sizeof (u16) + size;
762 }
763
764 void
765 vni_free (void *a)
766 {
767   vni_t *v = a;
768   gid_address_free (vni_gid (v));
769   clib_mem_free (vni_gid (v));
770 }
771
772 void
773 no_addr_free (void *a)
774 {
775   /* nothing to do */
776 }
777
778 void
779 sd_free (void *a)
780 {
781   /* nothing */
782 }
783
784 void
785 gid_address_free (gid_address_t * a)
786 {
787   if (gid_address_type (a) != GID_ADDR_LCAF)
788     return;
789
790   lcaf_t *lcaf = &gid_address_lcaf (a);
791   u8 lcaf_type = lcaf_type (lcaf);
792   (*lcaf_free_fcts[lcaf_type]) (lcaf);
793 }
794
795 void
796 gid_address_from_ip (gid_address_t * g, ip_address_t * ip)
797 {
798   memset (g, 0, sizeof (g[0]));
799   ip_address_set (&gid_address_ip (g), ip, ip_addr_version (ip));
800   gid_address_ippref_len (g) = 32;
801 }
802
803 int
804 ip_address_cmp (const ip_address_t * ip1, const ip_address_t * ip2)
805 {
806   int res = 0;
807   if (ip_addr_version (ip1) != ip_addr_version (ip2))
808     return -1;
809   res =
810     memcmp (&ip_addr_addr (ip1), &ip_addr_addr (ip2), ip_address_size (ip1));
811
812   if (res < 0)
813     res = 2;
814   else if (res > 0)
815     res = 1;
816
817   return res;
818 }
819
820 void
821 ip_address_copy (ip_address_t * dst, const ip_address_t * src)
822 {
823   if (IP4 == ip_addr_version (src))
824     {
825       /* don't copy any garbe from the union */
826       memset (dst, 0, sizeof (*dst));
827       dst->ip.v4 = src->ip.v4;
828       dst->version = IP4;
829     }
830   else
831     {
832       clib_memcpy (dst, src, sizeof (ip_address_t));
833     }
834 }
835
836 void
837 ip_address_copy_addr (void *dst, const ip_address_t * src)
838 {
839   clib_memcpy (dst, src, ip_address_size (src));
840 }
841
842 void
843 ip_address_set (ip_address_t * dst, const void *src, u8 version)
844 {
845   clib_memcpy (dst, src, ip_version_to_size (version));
846   ip_addr_version (dst) = version;
847 }
848
849 void
850 ip_address_to_46 (const ip_address_t * addr,
851                   ip46_address_t * a, fib_protocol_t * proto)
852 {
853   *proto = (IP4 == ip_addr_version (addr) ?
854             FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
855   switch (*proto)
856     {
857     case FIB_PROTOCOL_IP4:
858       ip46_address_set_ip4 (a, &addr->ip.v4);
859       break;
860     case FIB_PROTOCOL_IP6:
861       a->ip6 = addr->ip.v6;
862       break;
863     default:
864       ASSERT (0);
865       break;
866     }
867 }
868
869 static void
870 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
871 {
872   u32 mask = ~0;
873
874   ASSERT (ip4);
875
876   if (32 <= preflen)
877     {
878       return;
879     }
880
881   mask = pow2_mask (preflen) << (32 - preflen);
882   mask = clib_host_to_net_u32 (mask);
883   ip4->data_u32 &= mask;
884 }
885
886 static void
887 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
888 {
889   u8 mask_6[16];
890   u32 *m;
891   u8 j, i0, i1;
892
893   ASSERT (ip6);
894
895   memset (mask_6, 0, sizeof (mask_6));
896
897   if (128 <= preflen)
898     {
899       return;
900     }
901
902   i1 = preflen % 32;
903   i0 = preflen / 32;
904   m = (u32 *) & mask_6[0];
905
906   for (j = 0; j < i0; j++)
907     {
908       m[j] = ~0;
909     }
910
911   if (i1)
912     {
913       m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
914     }
915
916   for (j = 0; j < sizeof (mask_6); j++)
917     {
918       ip6->as_u8[j] &= mask_6[j];
919     }
920 }
921
922 void
923 ip_prefix_normalize (ip_prefix_t * a)
924 {
925   u8 preflen = ip_prefix_len (a);
926
927   switch (ip_prefix_version (a))
928     {
929     case IP4:
930       ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
931       break;
932
933     case IP6:
934       ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
935       break;
936
937     default:
938       ASSERT (0);
939     }
940 }
941
942 void *
943 ip_prefix_cast (gid_address_t * a)
944 {
945   return &gid_address_ippref (a);
946 }
947
948 u16
949 ip_prefix_size_to_write (void *pref)
950 {
951   ip_prefix_t *a = (ip_prefix_t *) pref;
952   return ip_address_size_to_write (&ip_prefix_addr (a));
953 }
954
955 u16
956 ip_prefix_write (u8 * p, void *gid)
957 {
958   gid_address_t *g = gid;
959   ip_prefix_t *a = &gid_address_ippref (g);
960
961   switch (ip_prefix_version (a))
962     {
963     case IP4:
964       return ip4_address_put (p, &ip_prefix_v4 (a));
965       break;
966     case IP6:
967       return ip6_address_put (p, &ip_prefix_v6 (a));
968       break;
969     }
970   return 0;
971 }
972
973 u8
974 ip_prefix_length (void *a)
975 {
976   return ip_prefix_len ((ip_prefix_t *) a);
977 }
978
979 void
980 ip_prefix_copy (void *dst, void *src)
981 {
982   clib_memcpy (dst, src, sizeof (ip_prefix_t));
983 }
984
985 void
986 mac_copy (void *dst, void *src)
987 {
988   clib_memcpy (dst, src, 6);
989 }
990
991 void
992 sd_copy (void *dst, void *src)
993 {
994   clib_memcpy (dst, src, sizeof (source_dest_t));
995 }
996
997 void
998 nsh_copy (void *dst, void *src)
999 {
1000   clib_memcpy (dst, src, sizeof (nsh_t));
1001 }
1002
1003 int
1004 ip_prefix_cmp (ip_prefix_t * p1, ip_prefix_t * p2)
1005 {
1006   int cmp = 0;
1007
1008   ip_prefix_normalize (p1);
1009   ip_prefix_normalize (p2);
1010
1011   cmp = ip_address_cmp (&ip_prefix_addr (p1), &ip_prefix_addr (p2));
1012   if (cmp == 0)
1013     {
1014       if (ip_prefix_len (p1) < ip_prefix_len (p2))
1015         {
1016           cmp = 1;
1017         }
1018       else
1019         {
1020           if (ip_prefix_len (p1) > ip_prefix_len (p2))
1021             cmp = 2;
1022         }
1023     }
1024   return cmp;
1025 }
1026
1027 void
1028 no_addr_copy (void *dst, void *src)
1029 {
1030   /* nothing to do */
1031 }
1032
1033 void
1034 vni_copy (void *dst, void *src)
1035 {
1036   vni_t *vd = dst;
1037   vni_t *vs = src;
1038
1039   clib_memcpy (vd, vs, sizeof (vd[0]));
1040   vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
1041   gid_address_copy (vni_gid (vd), vni_gid (vs));
1042 }
1043
1044 void
1045 lcaf_copy (void *dst, void *src)
1046 {
1047   lcaf_t *lcaf_dst = dst;
1048   lcaf_t *lcaf_src = src;
1049
1050   lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
1051   (*lcaf_copy_fcts[lcaf_type (lcaf_src)]) (dst, src);
1052 }
1053
1054 u8
1055 lcaf_length (void *a)
1056 {
1057   return 0;
1058 }
1059
1060 u8
1061 mac_length (void *a)
1062 {
1063   return 0;
1064 }
1065
1066 u8
1067 sd_length (void *a)
1068 {
1069   return 0;
1070 }
1071
1072 u8
1073 nsh_length (void *a)
1074 {
1075   return 0;
1076 }
1077
1078 void *
1079 lcaf_cast (gid_address_t * a)
1080 {
1081   return &gid_address_lcaf (a);
1082 }
1083
1084 void *
1085 mac_cast (gid_address_t * a)
1086 {
1087   return &gid_address_mac (a);
1088 }
1089
1090 void *
1091 sd_cast (gid_address_t * a)
1092 {
1093   return &gid_address_sd (a);
1094 }
1095
1096 void *
1097 nsh_cast (gid_address_t * a)
1098 {
1099   return &gid_address_nsh (a);
1100 }
1101
1102 u8
1103 no_addr_length (void *a)
1104 {
1105   return 0;
1106 }
1107
1108 u8
1109 vni_length (void *a)
1110 {
1111   vni_t *v = a;
1112   return (sizeof (u32)          /* VNI size */
1113           + gid_address_size_to_put (vni_gid (v)) /* vni body size */ );
1114 }
1115
1116 u16
1117 lcaf_write (u8 * p, void *a)
1118 {
1119   u16 size = 0, len;
1120   lcaf_t *lcaf = a;
1121   u8 type = lcaf_type (lcaf);
1122   lcaf_hdr_t _h, *h = &_h;
1123
1124   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1125   size += sizeof (u16);
1126   memset (h, 0, sizeof (h[0]));
1127   LCAF_TYPE (h) = type;
1128   u16 lcaf_len = (*lcaf_body_length_fcts[type]) (lcaf);
1129   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1130
1131   clib_memcpy (p + size, h, sizeof (h[0]));
1132   size += sizeof (h[0]);
1133   len = (*lcaf_write_fcts[type]) (p + size, lcaf);
1134
1135   if ((u16) ~ 0 == len)
1136     return ~0;
1137
1138   return size + len;
1139 }
1140
1141 u16
1142 mac_write (u8 * p, void *a)
1143 {
1144   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_MAC);
1145   clib_memcpy (p + sizeof (u16), a, 6);
1146   return mac_size_to_write (a);
1147 }
1148
1149 static u16
1150 fid_addr_write (u8 * p, fid_address_t * a)
1151 {
1152   switch (fid_addr_type (a))
1153     {
1154     case FID_ADDR_IP_PREF:
1155       return ip_prefix_write (p, &fid_addr_ippref (a));
1156
1157     case FID_ADDR_MAC:
1158       return mac_write (p, &fid_addr_mac (a));
1159
1160     default:
1161       return ~0;
1162     }
1163   return ~0;
1164 }
1165
1166 static u8
1167 fid_address_length (fid_address_t * a)
1168 {
1169   switch (fid_addr_type (a))
1170     {
1171     case FID_ADDR_IP_PREF:
1172       return ip_prefix_length (&fid_addr_ippref (a));
1173     case FID_ADDR_MAC:
1174       return 0;
1175     case FID_ADDR_NSH:
1176       return 0;
1177     }
1178   return 0;
1179 }
1180
1181 u16
1182 sd_write (u8 * p, void *a)
1183 {
1184   source_dest_t *sd = a;
1185   u16 size = 0;
1186   lcaf_hdr_t _h, *h = &_h;
1187   lcaf_src_dst_hdr_t sd_hdr;
1188
1189   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1190   size += sizeof (u16);
1191   memset (h, 0, sizeof (h[0]));
1192   LCAF_TYPE (h) = LCAF_SOURCE_DEST;
1193   u16 lcaf_len = sizeof (lcaf_src_dst_hdr_t)
1194     + fid_addr_size_to_write (&sd_src (sd))
1195     + fid_addr_size_to_write (&sd_dst (sd));
1196   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1197
1198   clib_memcpy (p + size, h, sizeof (h[0]));
1199   size += sizeof (h[0]);
1200
1201   memset (&sd_hdr, 0, sizeof (sd_hdr));
1202   LCAF_SD_SRC_ML (&sd_hdr) = fid_address_length (&sd_src (sd));
1203   LCAF_SD_DST_ML (&sd_hdr) = fid_address_length (&sd_dst (sd));
1204   clib_memcpy (p + size, &sd_hdr, sizeof (sd_hdr));
1205   size += sizeof (sd_hdr);
1206
1207   u16 len = fid_addr_write (p + size, &sd_src (sd));
1208   if ((u16) ~ 0 == len)
1209     return ~0;
1210   size += len;
1211
1212   len = fid_addr_write (p + size, &sd_dst (sd));
1213   if ((u16) ~ 0 == len)
1214     return ~0;
1215   size += len;
1216
1217   return size;
1218 }
1219
1220 u16
1221 nsh_write (u8 * p, void *a)
1222 {
1223   clib_warning ("not done");
1224   return 0;
1225 }
1226
1227 u16
1228 vni_write (u8 * p, void *a)
1229 {
1230   lcaf_hdr_t _h, *h = &_h;
1231   gid_address_t *g = a;
1232   u16 size = 0, len;
1233
1234   /* put lcaf header */
1235   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1236   size += sizeof (u16);
1237   memset (h, 0, sizeof (h[0]));
1238   LCAF_TYPE (h) = LCAF_INSTANCE_ID;
1239   u16 lcaf_len = sizeof (u32)   /* Instance ID size */
1240     + gid_address_size_to_put_no_vni (g);
1241   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1242   LCAF_RES2 (h) = gid_address_vni_mask (g);
1243
1244   /* put vni header */
1245   clib_memcpy (p + size, h, sizeof (h[0]));
1246   size += sizeof (h[0]);
1247
1248   u32 *afip = (u32 *) (p + size);
1249   afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
1250   size += sizeof (u32);
1251
1252   if (GID_ADDR_SRC_DST == gid_address_type (g))
1253     /* write src/dst LCAF */
1254     {
1255       len = sd_write (p + size, g);
1256       if ((u16) ~ 0 == len)
1257         return ~0;
1258     }
1259   else
1260     /* write the actual address */
1261     len = gid_address_put_no_vni (p + size, g);
1262
1263   if ((u16) ~ 0 == len)
1264     return ~0;
1265
1266   return size + len;
1267 }
1268
1269 u16
1270 no_addr_write (u8 * p, void *a)
1271 {
1272   /* do nothing; return AFI field size */
1273   return sizeof (u16);
1274 }
1275
1276 u16
1277 no_addr_size_to_write (void *a)
1278 {
1279   return sizeof (u16);          /* AFI field length */
1280 }
1281
1282 static u16
1283 fid_addr_size_to_write (fid_address_t * a)
1284 {
1285   switch (fid_addr_type (a))
1286     {
1287     case FID_ADDR_IP_PREF:
1288       return ip_prefix_size_to_write (a);
1289
1290     case FID_ADDR_MAC:
1291       return mac_size_to_write (a);
1292
1293     default:
1294       break;
1295     }
1296   return 0;
1297 }
1298
1299 u16
1300 vni_size_to_write (void *a)
1301 {
1302   gid_address_t *g = a;
1303
1304   u16 lcaf_size = sizeof (u32) + sizeof (u16)   /* LCAF AFI field size */
1305     + sizeof (lcaf_hdr_t);
1306
1307   if (gid_address_type (g) == GID_ADDR_SRC_DST)
1308     /* special case where nested LCAF is supported */
1309     return lcaf_size + sd_size_to_write (g);
1310   else
1311     return lcaf_size + gid_address_size_to_put_no_vni (g);
1312 }
1313
1314 u16
1315 lcaf_size_to_write (void *a)
1316 {
1317   lcaf_t *lcaf = (lcaf_t *) a;
1318   u32 size = 0, len;
1319   u8 type = lcaf_type (lcaf);
1320
1321   size += sizeof (u16);         /* AFI size */
1322
1323   len = (*lcaf_size_to_write_fcts[type]) (lcaf);
1324   if (~0 == len)
1325     return ~0;
1326
1327   return size + len;
1328 }
1329
1330 u16
1331 sd_size_to_write (void *a)
1332 {
1333   source_dest_t *sd = a;
1334   return sizeof (u16)
1335     + sizeof (lcaf_hdr_t)
1336     + sizeof (lcaf_src_dst_hdr_t)
1337     + fid_addr_size_to_write (&sd_src (sd))
1338     + fid_addr_size_to_write (&sd_dst (sd));
1339 }
1340
1341 u16
1342 mac_size_to_write (void *a)
1343 {
1344   return sizeof (u16) + 6;
1345 }
1346
1347 u16
1348 nsh_size_to_write (void *a)
1349 {
1350   return sizeof (u16) + 4;
1351 }
1352
1353 u8
1354 gid_address_len (gid_address_t * a)
1355 {
1356   gid_address_type_t type = gid_address_type (a);
1357   return (*addr_len_fcts[type]) ((*cast_fcts[type]) (a));
1358 }
1359
1360 static u16
1361 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
1362 {
1363   gid_address_type_t type = gid_address_type (gid);
1364   return (*write_fcts[type]) (b, (*cast_fcts[type]) (gid));
1365 }
1366
1367 u16
1368 gid_address_put (u8 * b, gid_address_t * gid)
1369 {
1370   if (0 != gid_address_vni (gid))
1371     return vni_write (b, gid);
1372
1373   return gid_address_put_no_vni (b, gid);
1374 }
1375
1376 static u16
1377 gid_address_size_to_put_no_vni (gid_address_t * gid)
1378 {
1379   gid_address_type_t type = gid_address_type (gid);
1380   return (*size_to_write_fcts[type]) ((*cast_fcts[type]) (gid));
1381 }
1382
1383 u16
1384 gid_address_size_to_put (gid_address_t * gid)
1385 {
1386   if (0 != gid_address_vni (gid))
1387     return vni_size_to_write (gid);
1388
1389   return gid_address_size_to_put_no_vni (gid);
1390 }
1391
1392 void *
1393 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
1394 {
1395   return (*cast_fcts[type]) (gid);
1396 }
1397
1398 void
1399 gid_address_copy (gid_address_t * dst, gid_address_t * src)
1400 {
1401   gid_address_type_t type = gid_address_type (src);
1402   (*copy_fcts[type]) ((*cast_fcts[type]) (dst), (*cast_fcts[type]) (src));
1403   gid_address_type (dst) = type;
1404   gid_address_vni (dst) = gid_address_vni (src);
1405   gid_address_vni_mask (dst) = gid_address_vni_mask (src);
1406 }
1407
1408 u32
1409 mac_parse (u8 * offset, u8 * a)
1410 {
1411   /* skip AFI field */
1412   offset += sizeof (u16);
1413
1414   clib_memcpy (a, offset, 6);
1415   return sizeof (u16) + 6;
1416 }
1417
1418 u32
1419 gid_address_parse (u8 * offset, gid_address_t * a)
1420 {
1421   lisp_afi_e afi;
1422   int len = 0;
1423
1424   if (!a)
1425     return 0;
1426
1427   /* NOTE: since gid_address_parse may be called by vni_parse, we can't 0
1428    * the gid address here */
1429   afi = clib_net_to_host_u16 (*((u16 *) offset));
1430
1431   switch (afi)
1432     {
1433     case LISP_AFI_NO_ADDR:
1434       len = sizeof (u16);
1435       gid_address_type (a) = GID_ADDR_NO_ADDRESS;
1436       break;
1437     case LISP_AFI_IP:
1438       len = ip_address_parse (offset, afi, &gid_address_ip (a));
1439       gid_address_type (a) = GID_ADDR_IP_PREFIX;
1440       /* this should be modified outside if needed */
1441       gid_address_ippref_len (a) = 32;
1442       break;
1443     case LISP_AFI_IP6:
1444       len = ip_address_parse (offset, afi, &gid_address_ip (a));
1445       gid_address_type (a) = GID_ADDR_IP_PREFIX;
1446       /* this should be modified outside if needed */
1447       gid_address_ippref_len (a) = 128;
1448       break;
1449     case LISP_AFI_LCAF:
1450       gid_address_type (a) = GID_ADDR_LCAF;
1451       len = lcaf_parse (offset, a);
1452       break;
1453     case LISP_AFI_MAC:
1454       len = mac_parse (offset, gid_address_mac (a));
1455       gid_address_type (a) = GID_ADDR_MAC;
1456       break;
1457     default:
1458       clib_warning ("LISP AFI %d not supported!", afi);
1459       return ~0;
1460     }
1461   return len;
1462 }
1463
1464 void
1465 gid_address_ip_set (gid_address_t * dst, void *src, u8 version)
1466 {
1467   gid_address_ippref_len (dst) = ip_address_max_len (version);
1468   ip_address_set (&gid_address_ip (dst), src, version);
1469 }
1470
1471 int
1472 no_addr_cmp (void *a1, void *a2)
1473 {
1474   return 0;
1475 }
1476
1477 int
1478 vni_cmp (void *a1, void *a2)
1479 {
1480   vni_t *v1 = a1;
1481   vni_t *v2 = a2;
1482
1483   if (vni_mask_len (v1) != vni_mask_len (v2))
1484     return -1;
1485   if (vni_vni (v1) != vni_vni (v2))
1486     return -1;
1487   return gid_address_cmp (vni_gid (v1), vni_gid (v2));
1488 }
1489
1490 static int
1491 mac_cmp (void *a1, void *a2)
1492 {
1493   return memcmp (a1, a2, 6);
1494 }
1495
1496 static int
1497 fid_addr_cmp (fid_address_t * a1, fid_address_t * a2)
1498 {
1499   if (fid_addr_type (a1) != fid_addr_type (a2))
1500     return -1;
1501
1502   switch (fid_addr_type (a1))
1503     {
1504     case FID_ADDR_IP_PREF:
1505       return ip_prefix_cmp (&fid_addr_ippref (a1), &fid_addr_ippref (a2));
1506
1507     case FID_ADDR_MAC:
1508       return mac_cmp (fid_addr_mac (a1), fid_addr_mac (a2));
1509
1510     default:
1511       return -1;
1512     }
1513   return -1;
1514 }
1515
1516 int
1517 sd_cmp (void *a1, void *a2)
1518 {
1519   source_dest_t *sd1 = a1;
1520   source_dest_t *sd2 = a2;
1521
1522   if (fid_addr_cmp (&sd_dst (sd1), &sd_dst (sd2)))
1523     return -1;
1524   if (fid_addr_cmp (&sd_src (sd1), &sd_src (sd2)))
1525     return -1;
1526   return 0;
1527 }
1528
1529 /* Compare two gid_address_t.
1530  * Returns:
1531  *        -1: If they are from different afi
1532  *             0: Both address are the same
1533  *             1: Addr1 is bigger than addr2
1534  *             2: Addr2 is bigger than addr1
1535  */
1536 int
1537 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
1538 {
1539   lcaf_t *lcaf1, *lcaf2;
1540   int cmp = -1;
1541   if (!a1 || !a2)
1542     return -1;
1543   if (gid_address_type (a1) != gid_address_type (a2))
1544     return -1;
1545   if (gid_address_vni (a1) != gid_address_vni (a2))
1546     return -1;
1547
1548   /* TODO vni mask is not supported, disable comparing for now
1549      if (gid_address_vni_mask (a1) != gid_address_vni_mask (a2))
1550      return -1;
1551    */
1552
1553   switch (gid_address_type (a1))
1554     {
1555     case GID_ADDR_NO_ADDRESS:
1556       if (a1 == a2)
1557         cmp = 0;
1558       else
1559         cmp = 2;
1560       break;
1561     case GID_ADDR_IP_PREFIX:
1562       cmp =
1563         ip_prefix_cmp (&gid_address_ippref (a1), &gid_address_ippref (a2));
1564       break;
1565     case GID_ADDR_LCAF:
1566       lcaf1 = &gid_address_lcaf (a1);
1567       lcaf2 = &gid_address_lcaf (a2);
1568       if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
1569         cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)]) (lcaf1, lcaf2);
1570       break;
1571     case GID_ADDR_MAC:
1572       cmp = mac_cmp (gid_address_mac (a1), gid_address_mac (a2));
1573       break;
1574
1575     case GID_ADDR_SRC_DST:
1576       cmp = sd_cmp (&gid_address_sd (a1), &gid_address_sd (a2));
1577       break;
1578     default:
1579       break;
1580     }
1581
1582   return cmp;
1583 }
1584
1585 u32
1586 locator_parse (void *b, locator_t * loc)
1587 {
1588   locator_hdr_t *h;
1589   u8 status = 1;                /* locator up */
1590   int len;
1591
1592   h = b;
1593   if (!LOC_REACHABLE (h) && LOC_LOCAL (h))
1594     status = 0;
1595
1596   len = gid_address_parse (LOC_ADDR (h), &loc->address);
1597   if (len == ~0)
1598     return len;
1599
1600   loc->state = status;
1601   loc->local = 0;
1602   loc->priority = LOC_PRIORITY (h);
1603   loc->weight = LOC_WEIGHT (h);
1604   loc->mpriority = LOC_MPRIORITY (h);
1605   loc->mweight = LOC_MWEIGHT (h);
1606
1607   return sizeof (locator_hdr_t) + len;
1608 }
1609
1610 void
1611 locator_copy (locator_t * dst, locator_t * src)
1612 {
1613   /* TODO if gid become more complex, this will need to be changed! */
1614   clib_memcpy (dst, src, sizeof (*dst));
1615   if (!src->local)
1616     gid_address_copy (&dst->address, &src->address);
1617 }
1618
1619 u32
1620 locator_cmp (locator_t * l1, locator_t * l2)
1621 {
1622   u32 ret = 0;
1623   if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
1624     return 1;
1625
1626   if (l1->priority != l2->priority)
1627     return 1;
1628   if (l1->weight != l2->weight)
1629     return 1;
1630   if (l1->mpriority != l2->mpriority)
1631     return 1;
1632   if (l1->mweight != l2->mweight)
1633     return 1;
1634   return 0;
1635 }
1636
1637 void
1638 locator_free (locator_t * l)
1639 {
1640   if (!l->local)
1641     gid_address_free (&l->address);
1642 }
1643
1644 void
1645 build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst)
1646 {
1647   memset (sd, 0, sizeof (*sd));
1648   gid_address_type (sd) = GID_ADDR_SRC_DST;
1649   gid_address_vni (sd) = gid_address_vni (dst);
1650   gid_address_vni_mask (sd) = gid_address_vni_mask (dst);
1651
1652   switch (gid_address_type (dst))
1653     {
1654     case GID_ADDR_IP_PREFIX:
1655       gid_address_sd_src_type (sd) = FID_ADDR_IP_PREF;
1656       gid_address_sd_dst_type (sd) = FID_ADDR_IP_PREF;
1657       ip_prefix_copy (&gid_address_sd_src_ippref (sd),
1658                       &gid_address_ippref (src));
1659       ip_prefix_copy (&gid_address_sd_dst_ippref (sd),
1660                       &gid_address_ippref (dst));
1661       break;
1662     case GID_ADDR_MAC:
1663       gid_address_sd_src_type (sd) = FID_ADDR_MAC;
1664       gid_address_sd_dst_type (sd) = FID_ADDR_MAC;
1665       mac_copy (gid_address_sd_src_mac (sd), gid_address_mac (src));
1666       mac_copy (gid_address_sd_dst_mac (sd), gid_address_mac (dst));
1667       break;
1668     default:
1669       clib_warning ("Unsupported gid type %d while conversion!",
1670                     gid_address_type (dst));
1671       break;
1672     }
1673 }
1674
1675 /*
1676  * fd.io coding-style-patch-verification: ON
1677  *
1678  * Local Variables:
1679  * eval: (c-set-style "gnu")
1680  * End:
1681  */