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