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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/lisp-cp/lisp_types.h>
18 typedef u16 (*size_to_write_fct)(void *);
19 typedef void * (*cast_fct)(gid_address_t *);
20 typedef u16 (*serdes_fct)(u8 *, void *);
21 typedef u8 (*addr_len_fct)(void *);
22 typedef void (*copy_fct)(void *, void *);
23 typedef void (*free_fct)(void *);
24 typedef int (*cmp_fct)(void *, void *);
26 u16 vni_write (u8 * p, void * a);
27 u16 vni_parse (u8 * p, void * a);
28 u16 vni_size_to_write (void * a);
29 void vni_free (void * a);
30 void vni_copy (void * dst, void * src);
31 u16 vni_length (void * a);
32 int vni_cmp (void *, void *);
34 u16 no_addr_size_to_write (void *);
35 u16 no_addr_write (u8 * p, void * a);
36 u16 no_addr_parse (u8 * p, void * a);
37 void no_addr_free (void * a);
38 void no_addr_copy (void *, void *);
39 u16 no_addr_length (void * a);
40 int no_addr_cmp (void * a1, void * a2);
42 size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
43 { ip_prefix_size_to_write, lcaf_size_to_write };
44 serdes_fct write_fcts[GID_ADDR_TYPES] =
45 { ip_prefix_write, lcaf_write };
46 cast_fct cast_fcts[GID_ADDR_TYPES] =
47 { ip_prefix_cast, lcaf_cast };
48 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
49 { ip_prefix_length, lcaf_prefix_length };
50 copy_fct copy_fcts[GID_ADDR_TYPES] =
51 { ip_prefix_copy, lcaf_copy };
53 cmp_fct lcaf_cmp_fcts[LCAF_TYPES] =
60 size_to_write_fct lcaf_body_length_fcts[LCAF_TYPES] =
67 copy_fct lcaf_copy_fcts[LCAF_TYPES] =
74 free_fct lcaf_free_fcts[LCAF_TYPES] =
81 size_to_write_fct lcaf_size_to_write_fcts[LCAF_TYPES] =
83 no_addr_size_to_write,
88 serdes_fct lcaf_write_fcts[LCAF_TYPES] =
95 serdes_fct lcaf_parse_fcts[LCAF_TYPES] =
103 format_ip_address (u8 * s, va_list * args)
105 ip_address_t * a = va_arg (*args, ip_address_t *);
106 u8 ver = ip_addr_version(a);
109 return format (s, "%U", format_ip4_address, &ip_addr_v4(a));
113 return format (s, "%U", format_ip6_address, &ip_addr_v6(a));
117 clib_warning ("Can't format IP version %d!", ver);
123 unformat_ip_address (unformat_input_t * input, va_list * args)
125 ip_address_t * a = va_arg(*args, ip_address_t *);
126 if (unformat(input, "%U", unformat_ip4_address, &ip_addr_v4(a)))
127 ip_addr_version(a) = IP4;
128 else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6(a)))
129 ip_addr_version(a) = IP6;
136 format_ip_prefix (u8 * s, va_list * args)
138 ip_prefix_t * a = va_arg (*args, ip_prefix_t *);
139 return format (s, "%U/%d", format_ip_address, &ip_prefix_addr(a), ip_prefix_len(a));
143 unformat_ip_prefix (unformat_input_t * input, va_list * args)
145 ip_prefix_t * a = va_arg(*args, ip_prefix_t *);
146 return unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a),
151 format_gid_address (u8 * s, va_list * args)
153 gid_address_t * a = va_arg(*args, gid_address_t *);
154 u8 type = gid_address_type(a);
157 case GID_ADDR_IP_PREFIX:
158 return format (s, "%U", format_ip_prefix, &gid_address_ippref(a));
160 clib_warning("Can't format gid type %d", type);
166 unformat_gid_address (unformat_input_t * input, va_list * args)
168 gid_address_t * a = va_arg(*args, gid_address_t *);
169 if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a)))
170 gid_address_type(a) = GID_ADDR_IP_PREFIX;
177 ip_address_size (ip_address_t * a)
179 switch (ip_addr_version (a))
182 return sizeof(ip4_address_t);
185 return sizeof(ip6_address_t);
192 ip_version_to_size (u8 ver)
197 return sizeof(ip4_address_t);
200 return sizeof(ip6_address_t);
207 ip_version_to_max_plen (u8 ver)
221 always_inline lisp_afi_e
222 ip_version_to_iana_afi (u16 version)
237 ip_iana_afi_to_version (lisp_afi_e afi)
252 ip_address_size_to_write (ip_address_t * a)
254 return ip_address_size (a) + sizeof (u16);
258 ip_address_iana_afi(ip_address_t *a)
260 return ip_version_to_iana_afi(ip_addr_version(a));
264 ip_address_max_len (u8 version)
266 return version == IP4 ? 32 : 128;
270 ip4_address_size_to_put ()
272 // return sizeof(u16) + sizeof (ip4_address_t);
277 ip6_address_size_to_put ()
279 //return sizeof(u16) + sizeof (ip6_address_t);
284 ip4_address_put (u8 * b, ip4_address_t * a)
286 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
287 u8 *p = b + sizeof (u16);
288 clib_memcpy (p, a, sizeof(*a));
289 return ip4_address_size_to_put();
293 ip6_address_put (u8 * b, ip6_address_t * a)
295 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
296 u8 *p = b + sizeof (u16);
297 clib_memcpy (p, a, sizeof(*a));
298 return ip6_address_size_to_put();
302 ip_address_put (u8 * b, ip_address_t * a)
304 u32 len = ip_address_size (a);
305 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
306 u8 * p = b + sizeof (u16);
307 clib_memcpy (p, &ip_addr_addr (a), len);
308 return (len + sizeof (u16));
312 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
314 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
315 u8 size = ip_version_to_size (ip_addr_version(dst));
316 clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
317 return(sizeof(u16) + size);
321 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
323 lcaf_hdr_t * lh = offset;
324 lcaf->type = lh->type;
326 /* this is a bit of hack: since the LCAF Instance ID is the
327 only message that uses reserved2 field, we can set it here.
328 If any LCAF format starts using reserved2 field as well this needs
329 to be moved elsewhere */
330 lcaf_vni_len (lcaf) = lh->reserved2;
332 return sizeof (lh[0]);
336 vni_parse (u8 * p, void * a)
340 vni_vni (v) = clib_net_to_host_u32 ( *(u32 *) p);
341 size += sizeof (u32);
343 vni_gid (v) = clib_mem_alloc (sizeof (gid_address_t));
344 gid_address_t * gid = vni_gid (v);
345 memset (gid, 0, sizeof (gid[0]));
347 size += gid_address_parse (p + size, gid);
352 no_addr_parse (u8 * p, void * a)
359 lcaf_parse (void * offset, gid_address_t *addr)
362 offset += sizeof (u16);
363 lcaf_t * lcaf = &gid_address_lcaf (addr);
365 u32 size = lcaf_hdr_parse (offset, lcaf);
366 u8 type = lcaf_type (lcaf);
368 if (!lcaf_parse_fcts[type])
370 clib_warning ("Unsupported LCAF type: %u", type);
373 size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
374 return sizeof (u16) + size;
381 gid_address_free (vni_gid (v));
382 clib_mem_free (vni_gid (v));
386 no_addr_free (void * a)
392 gid_address_free (gid_address_t *a)
394 if (gid_address_type (a) != GID_ADDR_LCAF)
397 lcaf_t * lcaf = &gid_address_lcaf (a);
398 u8 lcaf_type = lcaf_type (lcaf);
399 (*lcaf_free_fcts[lcaf_type])(lcaf);
403 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
406 if (ip_addr_version (ip1) != ip_addr_version(ip2))
408 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
419 ip_address_copy (ip_address_t * dst , ip_address_t * src)
421 clib_memcpy (dst, src, sizeof (ip_address_t));
425 ip_address_copy_addr (void * dst , ip_address_t * src)
427 clib_memcpy (dst, src, ip_address_size(src));
431 ip_prefix_cast (gid_address_t * a)
433 return &gid_address_ippref(a);
437 ip_prefix_size_to_write (void * pref)
439 ip_prefix_t *a = (ip_prefix_t *) pref;
440 return ip_address_size_to_write (&ip_prefix_addr (a));
444 ip_prefix_write (u8 * p, void * pref)
446 ip_prefix_t *a = (ip_prefix_t *) pref;
447 switch (ip_prefix_version (a))
450 return ip4_address_put (p, &ip_prefix_v4 (a));
453 return ip6_address_put (p, &ip_prefix_v6 (a));
460 ip_prefix_length (void *a)
462 return ip_prefix_len((ip_prefix_t *) a);
466 ip_prefix_copy (void * dst , void * src)
468 clib_memcpy (dst, src, sizeof (ip_prefix_t));
472 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
475 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
478 if (ip_prefix_len(p1) < ip_prefix_len(p2))
484 if (ip_prefix_len(p1) > ip_prefix_len(p2))
492 no_addr_copy (void * dst, void * src)
498 vni_copy (void * dst, void * src)
503 clib_memcpy (vd, vs, sizeof (vd[0]));
504 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
505 gid_address_copy (vni_gid (vd), vni_gid (vs));
509 lcaf_copy (void * dst , void * src)
511 lcaf_t * lcaf_dst = dst;
512 lcaf_t * lcaf_src = src;
514 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
515 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
519 lcaf_prefix_length (void *a)
525 lcaf_cast (gid_address_t * a)
527 return &gid_address_lcaf (a);
531 no_addr_length (void * a)
537 vni_length (void * a)
540 return (sizeof (u32) /* VNI size */
541 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
545 lcaf_write (u8 * p, void * a)
549 u8 type = lcaf_type (lcaf);
550 lcaf_hdr_t _h, *h = &_h;
552 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
553 size += sizeof (u16);
554 memset (h, 0, sizeof (h[0]));
555 LCAF_TYPE (h) = type;
556 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
557 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
559 if (LCAF_INSTANCE_ID == type)
560 LCAF_RES2 (h) = lcaf_vni_len(lcaf);
562 clib_memcpy (p + size, h, sizeof (h[0]));
563 size += sizeof (h[0]);
564 len = (*lcaf_write_fcts[type])(p + size, lcaf);
573 vni_write (u8 * p, void * a)
578 *(u32 *)p = clib_host_to_net_u32 (vni_vni (v));
579 size += sizeof (u32);
580 len = gid_address_put (p + size, vni_gid (v));
589 no_addr_write (u8 * p, void * a)
591 /* do nothing; return AFI field size */
596 no_addr_size_to_write (void * a)
598 return sizeof (u16); /* AFI field length */
602 vni_size_to_write (void * a)
605 u16 size = sizeof (vni_vni (v));
607 gid_address_t * gid = vni_gid (v);
608 return (size + sizeof (lcaf_hdr_t)
609 + gid_address_size_to_put (gid));
613 lcaf_size_to_write (void * a)
615 lcaf_t * lcaf = (lcaf_t *) a;
617 u8 type = lcaf_type (lcaf);
619 size += sizeof (u16); /* AFI size */
621 len = (*lcaf_size_to_write_fcts[type])(lcaf);
629 gid_address_len (gid_address_t *a)
631 gid_address_type_t type = gid_address_type (a);
632 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
636 gid_address_put (u8 * b, gid_address_t * gid)
638 gid_address_type_t type = gid_address_type (gid);
639 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
643 gid_address_size_to_put (gid_address_t * gid)
645 gid_address_type_t type = gid_address_type (gid);
646 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
650 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
652 return (*cast_fcts[type])(gid);
656 gid_address_copy(gid_address_t * dst, gid_address_t * src)
658 gid_address_type_t type = gid_address_type(src);
659 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
660 gid_address_type(dst) = type;
664 gid_address_parse (u8 * offset, gid_address_t *a)
672 afi = clib_net_to_host_u16 (*((u16 *) offset));
676 case LISP_AFI_NO_ADDR:
678 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
681 len = ip_address_parse (offset, afi, &gid_address_ip(a));
682 gid_address_type(a) = GID_ADDR_IP_PREFIX;
683 /* this should be modified outside if needed*/
684 gid_address_ippref_len(a) = 32;
687 len = ip_address_parse (offset, afi, &gid_address_ip(a));
688 gid_address_type(a) = GID_ADDR_IP_PREFIX;
689 /* this should be modified outside if needed*/
690 gid_address_ippref_len(a) = 128;
693 len = lcaf_parse (offset, a);
694 gid_address_type(a) = GID_ADDR_LCAF;
697 clib_warning("LISP AFI %d not supported!", afi);
704 no_addr_cmp (void * a1, void * a2)
710 vni_cmp (void * a1, void * a2)
715 if (vni_mask_len (v1) != vni_mask_len (v2))
717 if (vni_vni (v1) != vni_vni (v2))
719 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
722 /* Compare two gid_address_t.
724 * -1: If they are from different afi
725 * 0: Both address are the same
726 * 1: Addr1 is bigger than addr2
727 * 2: Addr2 is bigger than addr1
730 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
732 lcaf_t * lcaf1, * lcaf2;
736 if (gid_address_type(a1) != gid_address_type(a2))
739 switch (gid_address_type(a1))
741 case GID_ADDR_NO_ADDRESS:
747 case GID_ADDR_IP_PREFIX:
748 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
751 lcaf1 = &gid_address_lcaf (a1);
752 lcaf2 = &gid_address_lcaf (a2);
753 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
754 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
765 locator_parse (void * b, locator_t * loc)
768 u8 status = 1; /* locator up */
772 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
775 len = gid_address_parse (LOC_ADDR(h), &loc->address);
781 loc->priority = LOC_PRIORITY(h);
782 loc->weight = LOC_WEIGHT(h);
783 loc->mpriority = LOC_MPRIORITY(h);
784 loc->mweight = LOC_MWEIGHT(h);
786 return sizeof(locator_hdr_t) + len;
790 locator_copy (locator_t * dst, locator_t * src)
792 /* TODO if gid become more complex, this will need to be changed! */
793 clib_memcpy (dst, src, sizeof(*dst));
795 gid_address_copy (&dst->address, &src->address);
799 locator_cmp (locator_t * l1, locator_t * l2)
802 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
805 if (l1->priority != l2->priority)
807 if (l1->weight != l2->weight)
809 if (l1->mpriority != l2->mpriority)
811 if (l1->mweight != l2->mweight)
817 locator_free (locator_t * l)
820 gid_address_free (&l->address);