04b8462e4fcbecb69bcfb85961db6b3b228b800f
[vpp.git] / vnet / vnet / lisp-cp / lisp_types.c
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vnet/lisp-cp/lisp_types.h>
17
18 static u16 gid_address_put_no_vni (u8 * b, gid_address_t * gid);
19 static u16 gid_address_size_to_put_no_vni (gid_address_t * gid);
20 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 u8 *
206 format_fid_address (u8 * s, va_list * args)
207 {
208   fid_address_t *a = va_arg (*args, fid_address_t *);
209
210   switch (fid_addr_type (a))
211     {
212     case FID_ADDR_IP_PREF:
213       return format (s, "%U", format_ip_prefix, &fid_addr_ippref (a));
214
215     case FID_ADDR_MAC:
216       return format (s, "%U", format_mac_address, &fid_addr_mac (a));
217
218     default:
219       clib_warning ("Can't format fid address type %d!", fid_addr_type (a));
220       return 0;
221     }
222   return 0;
223 }
224
225 u8 *
226 format_gid_address (u8 * s, va_list * args)
227 {
228   gid_address_t *a = va_arg (*args, gid_address_t *);
229   u8 type = gid_address_type (a);
230   switch (type)
231     {
232     case GID_ADDR_IP_PREFIX:
233       return format (s, "[%d] %U", gid_address_vni (a), format_ip_prefix,
234                      &gid_address_ippref (a));
235     case GID_ADDR_SRC_DST:
236       return format (s, "[%d] %U|%U", gid_address_vni (a),
237                      format_fid_address, &gid_address_sd_src (a),
238                      format_fid_address, &gid_address_sd_dst (a));
239     case GID_ADDR_MAC:
240       return format (s, "[%d] %U", gid_address_vni (a), format_mac_address,
241                      &gid_address_mac (a));
242     default:
243       clib_warning ("Can't format gid type %d", type);
244       return 0;
245     }
246   return 0;
247 }
248
249 uword
250 unformat_fid_address (unformat_input_t * i, va_list * args)
251 {
252   fid_address_t *a = va_arg (*args, fid_address_t *);
253   ip_prefix_t ippref;
254   u8 mac[6] = { 0 };
255
256   if (unformat (i, "%U", unformat_ip_prefix, &ippref))
257     {
258       fid_addr_type (a) = FID_ADDR_IP_PREF;
259       ip_prefix_copy (&fid_addr_ippref (a), &ippref);
260     }
261   else if (unformat (i, "%U", unformat_mac_address, mac))
262     {
263       fid_addr_type (a) = FID_ADDR_MAC;
264       mac_copy (fid_addr_mac (a), mac);
265     }
266   else
267     return 0;
268
269   return 1;
270 }
271
272 uword
273 unformat_gid_address (unformat_input_t * input, va_list * args)
274 {
275   gid_address_t *a = va_arg (*args, gid_address_t *);
276   u8 mac[6] = { 0 };
277   ip_prefix_t ippref;
278   fid_address_t sim1, sim2;
279
280   memset (&ippref, 0, sizeof (ippref));
281   memset (&sim1, 0, sizeof (sim1));
282   memset (&sim2, 0, sizeof (sim2));
283
284   if (unformat (input, "%U|%U", unformat_fid_address, &sim1,
285                 unformat_fid_address, &sim2))
286     {
287       gid_address_sd_src (a) = sim1;
288       gid_address_sd_dst (a) = sim2;
289       gid_address_type (a) = GID_ADDR_SRC_DST;
290     }
291   else if (unformat (input, "%U", unformat_ip_prefix, &ippref))
292     {
293       ip_prefix_copy (&gid_address_ippref (a), &ippref);
294       gid_address_type (a) = GID_ADDR_IP_PREFIX;
295     }
296   else if (unformat (input, "%U", unformat_mac_address, mac))
297     {
298       mac_copy (gid_address_mac (a), mac);
299       gid_address_type (a) = GID_ADDR_MAC;
300     }
301   else
302     return 0;
303
304   return 1;
305 }
306
307 uword
308 unformat_negative_mapping_action (unformat_input_t * input, va_list * args)
309 {
310   u32 *action = va_arg (*args, u32 *);
311   u8 *s = 0;
312
313   if (unformat (input, "%s", &s))
314     {
315       if (!strcmp ((char *) s, "no-action"))
316         action[0] = LISP_NO_ACTION;
317       else if (!strcmp ((char *) s, "natively-forward"))
318         action[0] = LISP_FORWARD_NATIVE;
319       else if (!strcmp ((char *) s, "send-map-request"))
320         action[0] = LISP_SEND_MAP_REQUEST;
321       else if (!strcmp ((char *) s, "drop"))
322         action[0] = LISP_DROP;
323       else
324         {
325           clib_warning ("invalid action: '%s'", s);
326           action[0] = LISP_DROP;
327         }
328     }
329   else
330     return 0;
331
332   vec_free (s);
333   return 1;
334 }
335
336 u8 *
337 format_negative_mapping_action (u8 * s, va_list * args)
338 {
339   lisp_action_e action = va_arg (*args, lisp_action_e);
340
341   switch (action)
342     {
343     case LISP_NO_ACTION:
344       s = format (s, "no-action");
345       break;
346     case LISP_FORWARD_NATIVE:
347       s = format (s, "natively-forward");
348       break;
349     case LISP_SEND_MAP_REQUEST:
350       s = format (s, "send-map-request");
351       break;
352     case LISP_DROP:
353     default:
354       s = format (s, "drop");
355       break;
356     }
357   return (s);
358 }
359
360 u16
361 ip_address_size (const ip_address_t * a)
362 {
363   switch (ip_addr_version (a))
364     {
365     case IP4:
366       return sizeof (ip4_address_t);
367       break;
368     case IP6:
369       return sizeof (ip6_address_t);
370       break;
371     }
372   return 0;
373 }
374
375 u16
376 ip_version_to_size (u8 ver)
377 {
378   switch (ver)
379     {
380     case IP4:
381       return sizeof (ip4_address_t);
382       break;
383     case IP6:
384       return sizeof (ip6_address_t);
385       break;
386     }
387   return 0;
388 }
389
390 u8
391 ip_version_to_max_plen (u8 ver)
392 {
393   switch (ver)
394     {
395     case IP4:
396       return 32;
397       break;
398     case IP6:
399       return 128;
400       break;
401     }
402   return 0;
403 }
404
405 always_inline lisp_afi_e
406 ip_version_to_iana_afi (u16 version)
407 {
408   switch (version)
409     {
410     case IP4:
411       return LISP_AFI_IP;
412     case IP6:
413       return LISP_AFI_IP6;
414     default:
415       return 0;
416     }
417   return 0;
418 }
419
420 always_inline u8
421 ip_iana_afi_to_version (lisp_afi_e afi)
422 {
423   switch (afi)
424     {
425     case LISP_AFI_IP:
426       return IP4;
427     case LISP_AFI_IP6:
428       return IP6;
429     default:
430       return 0;
431     }
432   return 0;
433 }
434
435 u16
436 ip_address_size_to_write (ip_address_t * a)
437 {
438   return ip_address_size (a) + sizeof (u16);
439 }
440
441 u16
442 ip_address_iana_afi (ip_address_t * a)
443 {
444   return ip_version_to_iana_afi (ip_addr_version (a));
445 }
446
447 u8
448 ip_address_max_len (u8 version)
449 {
450   return version == IP4 ? 32 : 128;
451 }
452
453 u16
454 ip4_address_size_to_put ()
455 {
456   // return sizeof(u16) + sizeof (ip4_address_t);
457   return 6;
458 }
459
460 u16
461 ip6_address_size_to_put ()
462 {
463   //return sizeof(u16) + sizeof (ip6_address_t);
464   return 18;
465 }
466
467 u32
468 ip4_address_put (u8 * b, ip4_address_t * a)
469 {
470   *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (IP4));
471   u8 *p = b + sizeof (u16);
472   clib_memcpy (p, a, sizeof (*a));
473   return ip4_address_size_to_put ();
474 }
475
476 u32
477 ip6_address_put (u8 * b, ip6_address_t * a)
478 {
479   *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (IP6));
480   u8 *p = b + sizeof (u16);
481   clib_memcpy (p, a, sizeof (*a));
482   return ip6_address_size_to_put ();
483 }
484
485 u32
486 ip_address_put (u8 * b, ip_address_t * a)
487 {
488   u32 len = ip_address_size (a);
489   *(u16 *) b = clib_host_to_net_u16 (ip_address_iana_afi (a));
490   u8 *p = b + sizeof (u16);
491   clib_memcpy (p, &ip_addr_addr (a), len);
492   return (len + sizeof (u16));
493 }
494
495 u32
496 ip_address_parse (void *offset, u16 iana_afi, ip_address_t * dst)
497 {
498   ip_addr_version (dst) = ip_iana_afi_to_version (iana_afi);
499   u8 size = ip_version_to_size (ip_addr_version (dst));
500   clib_memcpy (&ip_addr_addr (dst), offset + sizeof (u16), size);
501   return (sizeof (u16) + size);
502 }
503
504 u32
505 lcaf_hdr_parse (void *offset, lcaf_t * lcaf)
506 {
507   lcaf_hdr_t *lh = offset;
508   lcaf->type = lh->type;
509
510   /* this is a bit of hack: since the LCAF Instance ID is the
511      only message that uses reserved2 field, we can set it here.
512      If any LCAF format starts using reserved2 field as well this needs
513      to be moved elsewhere */
514   lcaf_vni_len (lcaf) = lh->reserved2;
515
516   return sizeof (lh[0]);
517 }
518
519 static u8
520 iana_afi_to_fid_addr_type (u16 type)
521 {
522   switch (type)
523     {
524     case LISP_AFI_IP:
525     case LISP_AFI_IP6:
526       return FID_ADDR_IP_PREF;
527
528     case LISP_AFI_MAC:
529       return FID_ADDR_MAC;
530     }
531   return ~0;
532 }
533
534 static u16
535 fid_addr_parse (u8 * p, fid_address_t * a)
536 {
537   u16 afi = clib_net_to_host_u16 (*(u16 *) p);
538   fid_addr_type (a) = iana_afi_to_fid_addr_type (afi);
539   ip_address_t *ip_addr = &ip_prefix_addr (&fid_addr_ippref (a));
540
541   switch (fid_addr_type (a))
542     {
543     case FID_ADDR_MAC:
544       return mac_parse (p, fid_addr_mac (a));
545
546     case FID_ADDR_IP_PREF:
547       return ip_address_parse (p, afi, ip_addr);
548     }
549   return ~0;
550 }
551
552 u16
553 sd_parse (u8 * p, void *a)
554 {
555   lcaf_src_dst_hdr_t *sd_hdr;
556   gid_address_t *g = a;
557   u16 size = 0;
558   fid_address_t *src = &gid_address_sd_src (g);
559   fid_address_t *dst = &gid_address_sd_dst (g);
560
561   gid_address_type (g) = GID_ADDR_SRC_DST;
562
563   sd_hdr = (lcaf_src_dst_hdr_t *) (p + size);
564   size += sizeof (sd_hdr[0]);
565
566   size += fid_addr_parse (p + size, src);
567   size += fid_addr_parse (p + size, dst);
568
569   if (fid_addr_type (src) == FID_ADDR_IP_PREF)
570     {
571       ip_prefix_t *ippref = &fid_addr_ippref (src);
572       ip_prefix_len (ippref) = LCAF_SD_SRC_ML (sd_hdr);
573     }
574   if (fid_addr_type (dst) == FID_ADDR_IP_PREF)
575     {
576       ip_prefix_t *ippref = &fid_addr_ippref (dst);
577       ip_prefix_len (ippref) = LCAF_SD_DST_ML (sd_hdr);
578     }
579   return size;
580 }
581
582 u16
583 try_parse_src_dst_lcaf (u8 * p, gid_address_t * a)
584 {
585   lcaf_t lcaf;
586   u16 size = sizeof (u16);      /* skip AFI */
587
588   size += lcaf_hdr_parse (p + size, &lcaf);
589
590   if (LCAF_SOURCE_DEST != lcaf_type (&lcaf))
591     return ~0;
592
593   size += sd_parse (p + size, a);
594   return size;
595 }
596
597 u16
598 vni_parse (u8 * p, void *a)
599 {
600   lcaf_t *lcaf = a;
601   gid_address_t *g = a;
602   u16 size = 0;
603
604   gid_address_vni (g) = clib_net_to_host_u32 (*(u32 *) p);
605   size += sizeof (u32);
606   gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
607
608   /* nested LCAFs are not supported except of src/dst with vni - to handle
609    * such case look at the next AFI and process src/dest LCAF separately */
610   u16 afi = clib_net_to_host_u16 (*((u16 *) (p + size)));
611   if (LISP_AFI_LCAF == afi)
612     {
613       u16 len = try_parse_src_dst_lcaf (p + size, g);
614       if ((u16) ~ 0 == len)
615         return ~0;
616       size += len;
617     }
618   else
619     size += gid_address_parse (p + size, g);
620
621   return size;
622 }
623
624 u16
625 no_addr_parse (u8 * p, void *a)
626 {
627   /* do nothing */
628   return 0;
629 }
630
631 u32
632 lcaf_parse (void *offset, gid_address_t * addr)
633 {
634   /* skip AFI type */
635   offset += sizeof (u16);
636   lcaf_t *lcaf = &gid_address_lcaf (addr);
637
638   u32 size = lcaf_hdr_parse (offset, lcaf);
639   u8 type = lcaf_type (lcaf);
640
641   if (!lcaf_parse_fcts[type])
642     {
643       clib_warning ("Unsupported LCAF type: %u", type);
644       return ~0;
645     }
646   size += (*lcaf_parse_fcts[type]) (offset + size, lcaf);
647   return sizeof (u16) + size;
648 }
649
650 void
651 vni_free (void *a)
652 {
653   vni_t *v = a;
654   gid_address_free (vni_gid (v));
655   clib_mem_free (vni_gid (v));
656 }
657
658 void
659 no_addr_free (void *a)
660 {
661   /* nothing to do */
662 }
663
664 void
665 sd_free (void *a)
666 {
667   /* nothing */
668 }
669
670 void
671 gid_address_free (gid_address_t * a)
672 {
673   if (gid_address_type (a) != GID_ADDR_LCAF)
674     return;
675
676   lcaf_t *lcaf = &gid_address_lcaf (a);
677   u8 lcaf_type = lcaf_type (lcaf);
678   (*lcaf_free_fcts[lcaf_type]) (lcaf);
679 }
680
681 int
682 ip_address_cmp (const ip_address_t * ip1, const ip_address_t * ip2)
683 {
684   int res = 0;
685   if (ip_addr_version (ip1) != ip_addr_version (ip2))
686     return -1;
687   res =
688     memcmp (&ip_addr_addr (ip1), &ip_addr_addr (ip2), ip_address_size (ip1));
689
690   if (res < 0)
691     res = 2;
692   else if (res > 0)
693     res = 1;
694
695   return res;
696 }
697
698 void
699 ip_address_copy (ip_address_t * dst, const ip_address_t * src)
700 {
701   if (IP4 == ip_addr_version (src))
702     {
703       /* don't copy any garbe from the union */
704       memset (dst, 0, sizeof (*dst));
705       dst->ip.v4 = src->ip.v4;
706       dst->version = IP4;
707     }
708   else
709     {
710       clib_memcpy (dst, src, sizeof (ip_address_t));
711     }
712 }
713
714 void
715 ip_address_copy_addr (void *dst, const ip_address_t * src)
716 {
717   clib_memcpy (dst, src, ip_address_size (src));
718 }
719
720 void
721 ip_address_set (ip_address_t * dst, const void *src, u8 version)
722 {
723   clib_memcpy (dst, src, ip_version_to_size (version));
724   ip_addr_version (dst) = version;
725 }
726
727 void
728 ip_address_to_46 (const ip_address_t * addr,
729                   ip46_address_t * a, fib_protocol_t * proto)
730 {
731   *proto = (IP4 == ip_addr_version (addr) ?
732             FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
733   switch (*proto)
734     {
735     case FIB_PROTOCOL_IP4:
736       ip46_address_set_ip4 (a, &addr->ip.v4);
737       break;
738     case FIB_PROTOCOL_IP6:
739       a->ip6 = addr->ip.v6;
740       break;
741     default:
742       ASSERT (0);
743       break;
744     }
745 }
746
747 static void
748 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
749 {
750   u32 mask = ~0;
751
752   ASSERT (ip4);
753
754   if (32 <= preflen)
755     {
756       return;
757     }
758
759   mask = pow2_mask (preflen) << (32 - preflen);
760   mask = clib_host_to_net_u32 (mask);
761   ip4->data_u32 &= mask;
762 }
763
764 static void
765 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
766 {
767   u8 mask_6[16];
768   u32 *m;
769   u8 j, i0, i1;
770
771   ASSERT (ip6);
772
773   memset (mask_6, 0, sizeof (mask_6));
774
775   if (128 <= preflen)
776     {
777       return;
778     }
779
780   i1 = preflen % 32;
781   i0 = preflen / 32;
782   m = (u32 *) & mask_6[0];
783
784   for (j = 0; j < i0; j++)
785     {
786       m[j] = ~0;
787     }
788
789   if (i1)
790     {
791       m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
792     }
793
794   for (j = 0; j < sizeof (mask_6); j++)
795     {
796       ip6->as_u8[j] &= mask_6[j];
797     }
798 }
799
800 void
801 ip_prefix_normalize (ip_prefix_t * a)
802 {
803   u8 preflen = ip_prefix_len (a);
804
805   switch (ip_prefix_version (a))
806     {
807     case IP4:
808       ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
809       break;
810
811     case IP6:
812       ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
813       break;
814
815     default:
816       ASSERT (0);
817     }
818 }
819
820 void *
821 ip_prefix_cast (gid_address_t * a)
822 {
823   return &gid_address_ippref (a);
824 }
825
826 u16
827 ip_prefix_size_to_write (void *pref)
828 {
829   ip_prefix_t *a = (ip_prefix_t *) pref;
830   return ip_address_size_to_write (&ip_prefix_addr (a));
831 }
832
833 u16
834 ip_prefix_write (u8 * p, void *gid)
835 {
836   gid_address_t *g = gid;
837   ip_prefix_t *a = &gid_address_ippref (g);
838
839   switch (ip_prefix_version (a))
840     {
841     case IP4:
842       return ip4_address_put (p, &ip_prefix_v4 (a));
843       break;
844     case IP6:
845       return ip6_address_put (p, &ip_prefix_v6 (a));
846       break;
847     }
848   return 0;
849 }
850
851 u8
852 ip_prefix_length (void *a)
853 {
854   return ip_prefix_len ((ip_prefix_t *) a);
855 }
856
857 void
858 ip_prefix_copy (void *dst, void *src)
859 {
860   clib_memcpy (dst, src, sizeof (ip_prefix_t));
861 }
862
863 void
864 mac_copy (void *dst, void *src)
865 {
866   clib_memcpy (dst, src, 6);
867 }
868
869 void
870 sd_copy (void *dst, void *src)
871 {
872   clib_memcpy (dst, src, sizeof (source_dest_t));
873 }
874
875 int
876 ip_prefix_cmp (ip_prefix_t * p1, ip_prefix_t * p2)
877 {
878   int cmp = 0;
879
880   ip_prefix_normalize (p1);
881   ip_prefix_normalize (p2);
882
883   cmp = ip_address_cmp (&ip_prefix_addr (p1), &ip_prefix_addr (p2));
884   if (cmp == 0)
885     {
886       if (ip_prefix_len (p1) < ip_prefix_len (p2))
887         {
888           cmp = 1;
889         }
890       else
891         {
892           if (ip_prefix_len (p1) > ip_prefix_len (p2))
893             cmp = 2;
894         }
895     }
896   return cmp;
897 }
898
899 void
900 no_addr_copy (void *dst, void *src)
901 {
902   /* nothing to do */
903 }
904
905 void
906 vni_copy (void *dst, void *src)
907 {
908   vni_t *vd = dst;
909   vni_t *vs = src;
910
911   clib_memcpy (vd, vs, sizeof (vd[0]));
912   vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
913   gid_address_copy (vni_gid (vd), vni_gid (vs));
914 }
915
916 void
917 lcaf_copy (void *dst, void *src)
918 {
919   lcaf_t *lcaf_dst = dst;
920   lcaf_t *lcaf_src = src;
921
922   lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
923   (*lcaf_copy_fcts[lcaf_type (lcaf_src)]) (dst, src);
924 }
925
926 u8
927 lcaf_length (void *a)
928 {
929   return 0;
930 }
931
932 u8
933 mac_length (void *a)
934 {
935   return 0;
936 }
937
938 u8
939 sd_length (void *a)
940 {
941   return 0;
942 }
943
944 void *
945 lcaf_cast (gid_address_t * a)
946 {
947   return &gid_address_lcaf (a);
948 }
949
950 void *
951 mac_cast (gid_address_t * a)
952 {
953   return &gid_address_mac (a);
954 }
955
956 void *
957 sd_cast (gid_address_t * a)
958 {
959   return &gid_address_sd (a);
960 }
961
962 u8
963 no_addr_length (void *a)
964 {
965   return 0;
966 }
967
968 u8
969 vni_length (void *a)
970 {
971   vni_t *v = a;
972   return (sizeof (u32)          /* VNI size */
973           + gid_address_size_to_put (vni_gid (v)) /* vni body size */ );
974 }
975
976 u16
977 lcaf_write (u8 * p, void *a)
978 {
979   u16 size = 0, len;
980   lcaf_t *lcaf = a;
981   u8 type = lcaf_type (lcaf);
982   lcaf_hdr_t _h, *h = &_h;
983
984   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
985   size += sizeof (u16);
986   memset (h, 0, sizeof (h[0]));
987   LCAF_TYPE (h) = type;
988   u16 lcaf_len = (*lcaf_body_length_fcts[type]) (lcaf);
989   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
990
991   clib_memcpy (p + size, h, sizeof (h[0]));
992   size += sizeof (h[0]);
993   len = (*lcaf_write_fcts[type]) (p + size, lcaf);
994
995   if ((u16) ~ 0 == len)
996     return ~0;
997
998   return size + len;
999 }
1000
1001 u16
1002 mac_write (u8 * p, void *a)
1003 {
1004   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_MAC);
1005   clib_memcpy (p + sizeof (u16), a, 6);
1006   return mac_size_to_write (a);
1007 }
1008
1009 static u16
1010 fid_addr_write (u8 * p, fid_address_t * a)
1011 {
1012   switch (fid_addr_type (a))
1013     {
1014     case FID_ADDR_IP_PREF:
1015       return ip_prefix_write (p, &fid_addr_ippref (a));
1016
1017     case FID_ADDR_MAC:
1018       return mac_write (p, &fid_addr_mac (a));
1019
1020     default:
1021       return ~0;
1022     }
1023   return ~0;
1024 }
1025
1026 static u8
1027 fid_address_length (fid_address_t * a)
1028 {
1029   switch (fid_addr_type (a))
1030     {
1031     case FID_ADDR_IP_PREF:
1032       return ip_prefix_length (&fid_addr_ippref (a));
1033     case FID_ADDR_MAC:
1034       return 0;
1035     }
1036   return 0;
1037 }
1038
1039 u16
1040 sd_write (u8 * p, void *a)
1041 {
1042   source_dest_t *sd = a;
1043   u16 size = 0;
1044   lcaf_hdr_t _h, *h = &_h;
1045   lcaf_src_dst_hdr_t sd_hdr;
1046
1047   *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1048   size += sizeof (u16);
1049   memset (h, 0, sizeof (h[0]));
1050   LCAF_TYPE (h) = LCAF_SOURCE_DEST;
1051   u16 lcaf_len = 4 + sizeof (lcaf_src_dst_hdr_t)
1052     + fid_addr_size_to_write (&sd_src (sd))
1053     + fid_addr_size_to_write (&sd_dst (sd));
1054   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1055
1056   clib_memcpy (p + size, h, sizeof (h[0]));
1057   size += sizeof (h[0]);
1058
1059   memset (&sd_hdr, 0, sizeof (sd_hdr));
1060   LCAF_SD_SRC_ML (&sd_hdr) = fid_address_length (&sd_src (sd));
1061   LCAF_SD_DST_ML (&sd_hdr) = fid_address_length (&sd_dst (sd));
1062   clib_memcpy (p + size, &sd_hdr, sizeof (sd_hdr));
1063   size += sizeof (sd_hdr);
1064
1065   u16 len = fid_addr_write (p + size, &sd_src (sd));
1066   if ((u16) ~ 0 == len)
1067     return ~0;
1068   size += len;
1069
1070   len = fid_addr_write (p + size, &sd_dst (sd));
1071   if ((u16) ~ 0 == len)
1072     return ~0;
1073   size += len;
1074
1075   return size;
1076 }
1077
1078 u16
1079 vni_write (u8 * p, void *a)
1080 {
1081   lcaf_hdr_t _h, *h = &_h;
1082   gid_address_t *g = a;
1083   u16 size = 0, len;
1084
1085   /* put lcaf header */
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) = LCAF_INSTANCE_ID;
1090   u16 lcaf_len = sizeof (u32)   /* Instance ID size */
1091     + gid_address_size_to_put_no_vni (g);
1092   LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1093   LCAF_RES2 (h) = gid_address_vni_mask (g);
1094
1095   /* put vni header */
1096   clib_memcpy (p + size, h, sizeof (h[0]));
1097   size += sizeof (h[0]);
1098
1099   u32 *afip = (u32 *) (p + size);
1100   afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
1101   size += sizeof (u32);
1102
1103   if (GID_ADDR_SRC_DST == gid_address_type (g))
1104     /* write src/dst LCAF */
1105     {
1106       len = sd_write (p + size, g);
1107       if ((u16) ~ 0 == len)
1108         return ~0;
1109     }
1110   else
1111     /* write the actual address */
1112     len = gid_address_put_no_vni (p + size, g);
1113
1114   if ((u16) ~ 0 == len)
1115     return ~0;
1116
1117   return size + len;
1118 }
1119
1120 u16
1121 no_addr_write (u8 * p, void *a)
1122 {
1123   /* do nothing; return AFI field size */
1124   return sizeof (u16);
1125 }
1126
1127 u16
1128 no_addr_size_to_write (void *a)
1129 {
1130   return sizeof (u16);          /* AFI field length */
1131 }
1132
1133 static u16
1134 fid_addr_size_to_write (fid_address_t * a)
1135 {
1136   switch (fid_addr_type (a))
1137     {
1138     case FID_ADDR_IP_PREF:
1139       return ip_prefix_size_to_write (a);
1140
1141     case FID_ADDR_MAC:
1142       return mac_size_to_write (a);
1143
1144     default:
1145       break;
1146     }
1147   return 0;
1148 }
1149
1150 u16
1151 vni_size_to_write (void *a)
1152 {
1153   gid_address_t *g = a;
1154
1155   u16 lcaf_size = sizeof (u32) + sizeof (u16)   /* LCAF AFI field size */
1156     + sizeof (lcaf_hdr_t);
1157
1158   if (gid_address_type (g) == GID_ADDR_SRC_DST)
1159     /* special case where nested LCAF is supported */
1160     return lcaf_size + sd_size_to_write (g);
1161   else
1162     return lcaf_size + gid_address_size_to_put_no_vni (g);
1163 }
1164
1165 u16
1166 lcaf_size_to_write (void *a)
1167 {
1168   lcaf_t *lcaf = (lcaf_t *) a;
1169   u32 size = 0, len;
1170   u8 type = lcaf_type (lcaf);
1171
1172   size += sizeof (u16);         /* AFI size */
1173
1174   len = (*lcaf_size_to_write_fcts[type]) (lcaf);
1175   if (~0 == len)
1176     return ~0;
1177
1178   return size + len;
1179 }
1180
1181 u16
1182 sd_size_to_write (void *a)
1183 {
1184   source_dest_t *sd = a;
1185   return sizeof (u16)
1186     + sizeof (lcaf_hdr_t)
1187     + sizeof (lcaf_src_dst_hdr_t)
1188     + fid_addr_size_to_write (&sd_src (sd))
1189     + fid_addr_size_to_write (&sd_dst (sd));
1190 }
1191
1192 u16
1193 mac_size_to_write (void *a)
1194 {
1195   return sizeof (u16) + 6;
1196 }
1197
1198 u8
1199 gid_address_len (gid_address_t * a)
1200 {
1201   gid_address_type_t type = gid_address_type (a);
1202   return (*addr_len_fcts[type]) ((*cast_fcts[type]) (a));
1203 }
1204
1205 static u16
1206 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
1207 {
1208   gid_address_type_t type = gid_address_type (gid);
1209   return (*write_fcts[type]) (b, (*cast_fcts[type]) (gid));
1210 }
1211
1212 u16
1213 gid_address_put (u8 * b, gid_address_t * gid)
1214 {
1215   if (0 != gid_address_vni (gid))
1216     return vni_write (b, gid);
1217
1218   return gid_address_put_no_vni (b, gid);
1219 }
1220
1221 static u16
1222 gid_address_size_to_put_no_vni (gid_address_t * gid)
1223 {
1224   gid_address_type_t type = gid_address_type (gid);
1225   return (*size_to_write_fcts[type]) ((*cast_fcts[type]) (gid));
1226 }
1227
1228 u16
1229 gid_address_size_to_put (gid_address_t * gid)
1230 {
1231   if (0 != gid_address_vni (gid))
1232     return vni_size_to_write (gid);
1233
1234   return gid_address_size_to_put_no_vni (gid);
1235 }
1236
1237 void *
1238 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
1239 {
1240   return (*cast_fcts[type]) (gid);
1241 }
1242
1243 void
1244 gid_address_copy (gid_address_t * dst, gid_address_t * src)
1245 {
1246   gid_address_type_t type = gid_address_type (src);
1247   (*copy_fcts[type]) ((*cast_fcts[type]) (dst), (*cast_fcts[type]) (src));
1248   gid_address_type (dst) = type;
1249   gid_address_vni (dst) = gid_address_vni (src);
1250   gid_address_vni_mask (dst) = gid_address_vni_mask (src);
1251 }
1252
1253 u32
1254 mac_parse (u8 * offset, u8 * a)
1255 {
1256   /* skip AFI field */
1257   offset += sizeof (u16);
1258
1259   clib_memcpy (a, offset, 6);
1260   return sizeof (u16) + 6;
1261 }
1262
1263 u32
1264 gid_address_parse (u8 * offset, gid_address_t * a)
1265 {
1266   lisp_afi_e afi;
1267   int len = 0;
1268
1269   if (!a)
1270     return 0;
1271
1272   /* NOTE: since gid_address_parse may be called by vni_parse, we can't 0
1273    * the gid address here */
1274   afi = clib_net_to_host_u16 (*((u16 *) offset));
1275
1276   switch (afi)
1277     {
1278     case LISP_AFI_NO_ADDR:
1279       len = sizeof (u16);
1280       gid_address_type (a) = GID_ADDR_NO_ADDRESS;
1281       break;
1282     case LISP_AFI_IP:
1283       len = ip_address_parse (offset, afi, &gid_address_ip (a));
1284       gid_address_type (a) = GID_ADDR_IP_PREFIX;
1285       /* this should be modified outside if needed */
1286       gid_address_ippref_len (a) = 32;
1287       break;
1288     case LISP_AFI_IP6:
1289       len = ip_address_parse (offset, afi, &gid_address_ip (a));
1290       gid_address_type (a) = GID_ADDR_IP_PREFIX;
1291       /* this should be modified outside if needed */
1292       gid_address_ippref_len (a) = 128;
1293       break;
1294     case LISP_AFI_LCAF:
1295       gid_address_type (a) = GID_ADDR_LCAF;
1296       len = lcaf_parse (offset, a);
1297       break;
1298     case LISP_AFI_MAC:
1299       len = mac_parse (offset, gid_address_mac (a));
1300       gid_address_type (a) = GID_ADDR_MAC;
1301       break;
1302     default:
1303       clib_warning ("LISP AFI %d not supported!", afi);
1304       return ~0;
1305     }
1306   return len;
1307 }
1308
1309 void
1310 gid_address_ip_set (gid_address_t * dst, void *src, u8 version)
1311 {
1312   gid_address_ippref_len (dst) = ip_address_max_len (version);
1313   ip_address_set (&gid_address_ip (dst), src, version);
1314 }
1315
1316 int
1317 no_addr_cmp (void *a1, void *a2)
1318 {
1319   return 0;
1320 }
1321
1322 int
1323 vni_cmp (void *a1, void *a2)
1324 {
1325   vni_t *v1 = a1;
1326   vni_t *v2 = a2;
1327
1328   if (vni_mask_len (v1) != vni_mask_len (v2))
1329     return -1;
1330   if (vni_vni (v1) != vni_vni (v2))
1331     return -1;
1332   return gid_address_cmp (vni_gid (v1), vni_gid (v2));
1333 }
1334
1335 static int
1336 mac_cmp (void *a1, void *a2)
1337 {
1338   return memcmp (a1, a2, 6);
1339 }
1340
1341 static int
1342 fid_addr_cmp (fid_address_t * a1, fid_address_t * a2)
1343 {
1344   if (fid_addr_type (a1) != fid_addr_type (a2))
1345     return -1;
1346
1347   switch (fid_addr_type (a1))
1348     {
1349     case FID_ADDR_IP_PREF:
1350       return ip_prefix_cmp (&fid_addr_ippref (a1), &fid_addr_ippref (a2));
1351
1352     case FID_ADDR_MAC:
1353       return mac_cmp (fid_addr_mac (a1), fid_addr_mac (a2));
1354
1355     default:
1356       return -1;
1357     }
1358   return -1;
1359 }
1360
1361 int
1362 sd_cmp (void *a1, void *a2)
1363 {
1364   source_dest_t *sd1 = a1;
1365   source_dest_t *sd2 = a2;
1366
1367   if (fid_addr_cmp (&sd_dst (sd1), &sd_dst (sd2)))
1368     return -1;
1369   if (fid_addr_cmp (&sd_src (sd1), &sd_src (sd2)))
1370     return -1;
1371   return 0;
1372 }
1373
1374 /* Compare two gid_address_t.
1375  * Returns:
1376  *        -1: If they are from different afi
1377  *             0: Both address are the same
1378  *             1: Addr1 is bigger than addr2
1379  *             2: Addr2 is bigger than addr1
1380  */
1381 int
1382 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
1383 {
1384   lcaf_t *lcaf1, *lcaf2;
1385   int cmp = -1;
1386   if (!a1 || !a2)
1387     return -1;
1388   if (gid_address_type (a1) != gid_address_type (a2))
1389     return -1;
1390   if (gid_address_vni (a1) != gid_address_vni (a2))
1391     return -1;
1392   if (gid_address_vni_mask (a1) != gid_address_vni_mask (a2))
1393     return -1;
1394
1395   switch (gid_address_type (a1))
1396     {
1397     case GID_ADDR_NO_ADDRESS:
1398       if (a1 == a2)
1399         cmp = 0;
1400       else
1401         cmp = 2;
1402       break;
1403     case GID_ADDR_IP_PREFIX:
1404       cmp =
1405         ip_prefix_cmp (&gid_address_ippref (a1), &gid_address_ippref (a2));
1406       break;
1407     case GID_ADDR_LCAF:
1408       lcaf1 = &gid_address_lcaf (a1);
1409       lcaf2 = &gid_address_lcaf (a2);
1410       if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
1411         cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)]) (lcaf1, lcaf2);
1412       break;
1413     case GID_ADDR_MAC:
1414       cmp = mac_cmp (gid_address_mac (a1), gid_address_mac (a2));
1415       break;
1416
1417     case GID_ADDR_SRC_DST:
1418       cmp = sd_cmp (&gid_address_sd (a1), &gid_address_sd (a2));
1419       break;
1420     default:
1421       break;
1422     }
1423
1424   return cmp;
1425 }
1426
1427 u32
1428 locator_parse (void *b, locator_t * loc)
1429 {
1430   locator_hdr_t *h;
1431   u8 status = 1;                /* locator up */
1432   int len;
1433
1434   h = b;
1435   if (!LOC_REACHABLE (h) && LOC_LOCAL (h))
1436     status = 0;
1437
1438   len = gid_address_parse (LOC_ADDR (h), &loc->address);
1439   if (len == ~0)
1440     return len;
1441
1442   loc->state = status;
1443   loc->local = 0;
1444   loc->priority = LOC_PRIORITY (h);
1445   loc->weight = LOC_WEIGHT (h);
1446   loc->mpriority = LOC_MPRIORITY (h);
1447   loc->mweight = LOC_MWEIGHT (h);
1448
1449   return sizeof (locator_hdr_t) + len;
1450 }
1451
1452 void
1453 locator_copy (locator_t * dst, locator_t * src)
1454 {
1455   /* TODO if gid become more complex, this will need to be changed! */
1456   clib_memcpy (dst, src, sizeof (*dst));
1457   if (!src->local)
1458     gid_address_copy (&dst->address, &src->address);
1459 }
1460
1461 u32
1462 locator_cmp (locator_t * l1, locator_t * l2)
1463 {
1464   u32 ret = 0;
1465   if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
1466     return 1;
1467
1468   if (l1->priority != l2->priority)
1469     return 1;
1470   if (l1->weight != l2->weight)
1471     return 1;
1472   if (l1->mpriority != l2->mpriority)
1473     return 1;
1474   if (l1->mweight != l2->mweight)
1475     return 1;
1476   return 0;
1477 }
1478
1479 void
1480 locator_free (locator_t * l)
1481 {
1482   if (!l->local)
1483     gid_address_free (&l->address);
1484 }
1485
1486 void
1487 build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst)
1488 {
1489   memset (sd, 0, sizeof (*sd));
1490   gid_address_type (sd) = GID_ADDR_SRC_DST;
1491   gid_address_vni (sd) = gid_address_vni (dst);
1492   gid_address_vni_mask (sd) = gid_address_vni_mask (dst);
1493
1494   switch (gid_address_type (dst))
1495     {
1496     case GID_ADDR_IP_PREFIX:
1497       gid_address_sd_src_type (sd) = FID_ADDR_IP_PREF;
1498       gid_address_sd_dst_type (sd) = FID_ADDR_IP_PREF;
1499       ip_prefix_copy (&gid_address_sd_src_ippref (sd),
1500                       &gid_address_ippref (src));
1501       ip_prefix_copy (&gid_address_sd_dst_ippref (sd),
1502                       &gid_address_ippref (dst));
1503       break;
1504     case GID_ADDR_MAC:
1505       gid_address_sd_src_type (sd) = FID_ADDR_MAC;
1506       gid_address_sd_dst_type (sd) = FID_ADDR_MAC;
1507       mac_copy (gid_address_sd_src_mac (sd), gid_address_mac (src));
1508       mac_copy (gid_address_sd_dst_mac (sd), gid_address_mac (dst));
1509       break;
1510     default:
1511       clib_warning ("Unsupported gid type %d while conversion!",
1512                     gid_address_type (dst));
1513       break;
1514     }
1515 }
1516
1517 /*
1518  * fd.io coding-style-patch-verification: ON
1519  *
1520  * Local Variables:
1521  * eval: (c-set-style "gnu")
1522  * End:
1523  */