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 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);
21 typedef u16 (*size_to_write_fct)(void *);
22 typedef void * (*cast_fct)(gid_address_t *);
23 typedef u16 (*serdes_fct)(u8 *, void *);
24 typedef u8 (*addr_len_fct)(void *);
25 typedef void (*copy_fct)(void *, void *);
26 typedef void (*free_fct)(void *);
27 typedef int (*cmp_fct)(void *, void *);
29 u16 vni_write (u8 * p, void * a);
30 u16 vni_parse (u8 * p, void * a);
31 u16 vni_size_to_write (void * a);
32 void vni_free (void * a);
33 void vni_copy (void * dst, void * src);
34 u16 vni_length (void * a);
35 int vni_cmp (void *, void *);
37 u16 no_addr_size_to_write (void *);
38 u16 no_addr_write (u8 * p, void * a);
39 u16 no_addr_parse (u8 * p, void * a);
40 void no_addr_free (void * a);
41 void no_addr_copy (void *, void *);
42 u16 no_addr_length (void * a);
43 int no_addr_cmp (void * a1, void * a2);
45 size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
46 { ip_prefix_size_to_write, lcaf_size_to_write, mac_size_to_write };
47 serdes_fct write_fcts[GID_ADDR_TYPES] =
48 { ip_prefix_write, lcaf_write, mac_write };
49 cast_fct cast_fcts[GID_ADDR_TYPES] =
50 { ip_prefix_cast, lcaf_cast, mac_cast };
51 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
52 { ip_prefix_length, lcaf_length, mac_length };
53 copy_fct copy_fcts[GID_ADDR_TYPES] =
54 { ip_prefix_copy, lcaf_copy, mac_copy };
56 cmp_fct lcaf_cmp_fcts[LCAF_TYPES] =
63 size_to_write_fct lcaf_body_length_fcts[LCAF_TYPES] =
70 copy_fct lcaf_copy_fcts[LCAF_TYPES] =
77 free_fct lcaf_free_fcts[LCAF_TYPES] =
84 size_to_write_fct lcaf_size_to_write_fcts[LCAF_TYPES] =
86 no_addr_size_to_write,
91 serdes_fct lcaf_write_fcts[LCAF_TYPES] =
98 serdes_fct lcaf_parse_fcts[LCAF_TYPES] =
106 format_ip_address (u8 * s, va_list * args)
108 ip_address_t * a = va_arg (*args, ip_address_t *);
109 u8 ver = ip_addr_version(a);
112 return format (s, "%U", format_ip4_address, &ip_addr_v4(a));
116 return format (s, "%U", format_ip6_address, &ip_addr_v6(a));
120 clib_warning ("Can't format IP version %d!", ver);
126 unformat_ip_address (unformat_input_t * input, va_list * args)
128 ip_address_t * a = va_arg(*args, ip_address_t *);
129 if (unformat(input, "%U", unformat_ip4_address, &ip_addr_v4(a)))
130 ip_addr_version(a) = IP4;
131 else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6(a)))
132 ip_addr_version(a) = IP6;
139 format_ip_prefix (u8 * s, va_list * args)
141 ip_prefix_t * a = va_arg (*args, ip_prefix_t *);
142 return format (s, "%U/%d", format_ip_address, &ip_prefix_addr(a), ip_prefix_len(a));
146 unformat_ip_prefix (unformat_input_t * input, va_list * args)
148 ip_prefix_t * a = va_arg(*args, ip_prefix_t *);
149 return unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a),
154 unformat_mac_address (unformat_input_t * input, va_list * args)
156 u8 * a = va_arg(*args, u8 *);
157 return unformat (input, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3],
162 format_mac_address (u8 * s, va_list * args)
164 u8 * a = va_arg (*args, u8 *);
165 return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
166 a[0], a[1], a[2], a[3], a[4], a[5]);
170 format_gid_address (u8 * s, va_list * args)
172 gid_address_t * a = va_arg(*args, gid_address_t *);
173 u8 type = gid_address_type(a);
176 case GID_ADDR_IP_PREFIX:
177 return format (s, "[%d] %U", gid_address_vni(a), format_ip_prefix,
178 &gid_address_ippref(a));
179 case GID_ADDR_SRC_DST:
180 return format (s, "[%d] %U|%U", gid_address_vni(a),
181 format_ip_prefix, &gid_address_sd_source_pref(a),
182 format_ip_prefix, &gid_address_sd_dest_pref(a));
184 return format (s, "[%d] %U", gid_address_vni(a), format_mac_address,
185 &gid_address_mac(a));
187 clib_warning("Can't format gid type %d", type);
193 unformat_gid_address (unformat_input_t * input, va_list * args)
195 gid_address_t * a = va_arg(*args, gid_address_t *);
196 if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a)))
197 gid_address_type(a) = GID_ADDR_IP_PREFIX;
204 ip_address_size (ip_address_t * a)
206 switch (ip_addr_version (a))
209 return sizeof(ip4_address_t);
212 return sizeof(ip6_address_t);
219 ip_version_to_size (u8 ver)
224 return sizeof(ip4_address_t);
227 return sizeof(ip6_address_t);
234 ip_version_to_max_plen (u8 ver)
248 always_inline lisp_afi_e
249 ip_version_to_iana_afi (u16 version)
264 ip_iana_afi_to_version (lisp_afi_e afi)
279 ip_address_size_to_write (ip_address_t * a)
281 return ip_address_size (a) + sizeof (u16);
285 ip_address_iana_afi(ip_address_t *a)
287 return ip_version_to_iana_afi(ip_addr_version(a));
291 ip_address_max_len (u8 version)
293 return version == IP4 ? 32 : 128;
297 ip4_address_size_to_put ()
299 // return sizeof(u16) + sizeof (ip4_address_t);
304 ip6_address_size_to_put ()
306 //return sizeof(u16) + sizeof (ip6_address_t);
311 ip4_address_put (u8 * b, ip4_address_t * a)
313 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
314 u8 *p = b + sizeof (u16);
315 clib_memcpy (p, a, sizeof(*a));
316 return ip4_address_size_to_put();
320 ip6_address_put (u8 * b, ip6_address_t * a)
322 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
323 u8 *p = b + sizeof (u16);
324 clib_memcpy (p, a, sizeof(*a));
325 return ip6_address_size_to_put();
329 ip_address_put (u8 * b, ip_address_t * a)
331 u32 len = ip_address_size (a);
332 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
333 u8 * p = b + sizeof (u16);
334 clib_memcpy (p, &ip_addr_addr (a), len);
335 return (len + sizeof (u16));
339 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
341 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
342 u8 size = ip_version_to_size (ip_addr_version(dst));
343 clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
344 return(sizeof(u16) + size);
348 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
350 lcaf_hdr_t * lh = offset;
351 lcaf->type = lh->type;
353 /* this is a bit of hack: since the LCAF Instance ID is the
354 only message that uses reserved2 field, we can set it here.
355 If any LCAF format starts using reserved2 field as well this needs
356 to be moved elsewhere */
357 lcaf_vni_len (lcaf) = lh->reserved2;
359 return sizeof (lh[0]);
363 vni_parse (u8 * p, void * a)
366 gid_address_t * g = a;
369 gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p);
370 size += sizeof (u32);
371 gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
373 /* nested LCAFs are not supported - it is expected that nested AFI type is
375 size += gid_address_parse (p + size, g);
380 no_addr_parse (u8 * p, void * a)
387 lcaf_parse (void * offset, gid_address_t *addr)
390 offset += sizeof (u16);
391 lcaf_t * lcaf = &gid_address_lcaf (addr);
393 u32 size = lcaf_hdr_parse (offset, lcaf);
394 u8 type = lcaf_type (lcaf);
396 if (!lcaf_parse_fcts[type])
398 clib_warning ("Unsupported LCAF type: %u", type);
401 size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
402 return sizeof (u16) + size;
409 gid_address_free (vni_gid (v));
410 clib_mem_free (vni_gid (v));
414 no_addr_free (void * a)
420 gid_address_free (gid_address_t *a)
422 if (gid_address_type (a) != GID_ADDR_LCAF)
425 lcaf_t * lcaf = &gid_address_lcaf (a);
426 u8 lcaf_type = lcaf_type (lcaf);
427 (*lcaf_free_fcts[lcaf_type])(lcaf);
431 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
434 if (ip_addr_version (ip1) != ip_addr_version(ip2))
436 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
447 ip_address_copy (ip_address_t * dst , ip_address_t * src)
449 clib_memcpy (dst, src, sizeof (ip_address_t));
453 ip_address_copy_addr (void * dst , ip_address_t * src)
455 clib_memcpy (dst, src, ip_address_size(src));
459 ip_address_set(ip_address_t * dst, void * src, u8 version)
461 clib_memcpy(dst, src, ip_version_to_size(version));
462 ip_addr_version(dst) = version;
466 ip_prefix_cast (gid_address_t * a)
468 return &gid_address_ippref(a);
472 ip_prefix_size_to_write (void * pref)
474 ip_prefix_t *a = (ip_prefix_t *) pref;
475 return ip_address_size_to_write (&ip_prefix_addr (a));
479 ip_prefix_write (u8 * p, void * gid)
481 gid_address_t * g = gid;
482 ip_prefix_t *a = &gid_address_ippref (g);
484 switch (ip_prefix_version (a))
487 return ip4_address_put (p, &ip_prefix_v4 (a));
490 return ip6_address_put (p, &ip_prefix_v6 (a));
497 ip_prefix_length (void *a)
499 return ip_prefix_len((ip_prefix_t *) a);
503 ip_prefix_copy (void * dst , void * src)
505 clib_memcpy (dst, src, sizeof (ip_prefix_t));
509 mac_copy (void * dst , void * src)
511 clib_memcpy (dst, src, 6);
515 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
518 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
521 if (ip_prefix_len(p1) < ip_prefix_len(p2))
527 if (ip_prefix_len(p1) > ip_prefix_len(p2))
535 no_addr_copy (void * dst, void * src)
541 vni_copy (void * dst, void * src)
546 clib_memcpy (vd, vs, sizeof (vd[0]));
547 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
548 gid_address_copy (vni_gid (vd), vni_gid (vs));
552 lcaf_copy (void * dst , void * src)
554 lcaf_t * lcaf_dst = dst;
555 lcaf_t * lcaf_src = src;
557 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
558 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
562 lcaf_length (void *a)
574 lcaf_cast (gid_address_t * a)
576 return &gid_address_lcaf (a);
580 mac_cast (gid_address_t * a)
582 return &gid_address_mac (a);
586 no_addr_length (void * a)
592 vni_length (void * a)
595 return (sizeof (u32) /* VNI size */
596 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
600 lcaf_write (u8 * p, void * a)
604 u8 type = lcaf_type (lcaf);
605 lcaf_hdr_t _h, *h = &_h;
607 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
608 size += sizeof (u16);
609 memset (h, 0, sizeof (h[0]));
610 LCAF_TYPE (h) = type;
611 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
612 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
614 clib_memcpy (p + size, h, sizeof (h[0]));
615 size += sizeof (h[0]);
616 len = (*lcaf_write_fcts[type])(p + size, lcaf);
625 mac_write (u8 * p, void * a)
627 *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
628 clib_memcpy(p + sizeof (u16), a, 6);
629 return mac_size_to_write (a);
633 vni_write (u8 * p, void * a)
635 lcaf_hdr_t _h, *h = &_h;
636 gid_address_t * g = a;
639 /* put lcaf header */
640 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
641 size += sizeof (u16);
642 memset (h, 0, sizeof (h[0]));
643 LCAF_TYPE (h) = LCAF_INSTANCE_ID;
644 u16 lcaf_len = sizeof (u32) /* Instance ID size */
645 + gid_address_size_to_put_no_vni (g);
646 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
647 LCAF_RES2 (h) = gid_address_vni_mask (g);
650 clib_memcpy (p + size, h, sizeof (h[0]));
651 size += sizeof (h[0]);
653 u32 * afip = (u32 *)(p + size);
654 afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
655 size += sizeof (u32);
657 /* write the actual address */
658 len = gid_address_put_no_vni (p + size, g);
667 no_addr_write (u8 * p, void * a)
669 /* do nothing; return AFI field size */
674 no_addr_size_to_write (void * a)
676 return sizeof (u16); /* AFI field length */
680 vni_size_to_write (void * a)
682 gid_address_t * g = a;
683 return (sizeof (u32) /* vni size */
684 + sizeof (u16) /* LCAF AFI field size */
685 + sizeof (lcaf_hdr_t)
686 + gid_address_size_to_put_no_vni (g));
690 lcaf_size_to_write (void * a)
692 lcaf_t * lcaf = (lcaf_t *) a;
694 u8 type = lcaf_type (lcaf);
696 size += sizeof (u16); /* AFI size */
698 len = (*lcaf_size_to_write_fcts[type])(lcaf);
706 mac_size_to_write (void * a)
708 return sizeof (u16) + 6;
712 gid_address_len (gid_address_t *a)
714 gid_address_type_t type = gid_address_type (a);
715 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
719 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
721 gid_address_type_t type = gid_address_type (gid);
722 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
726 gid_address_put (u8 * b, gid_address_t * gid)
728 if (0 != gid_address_vni (gid))
729 return vni_write (b, gid);
731 return gid_address_put_no_vni (b, gid);
735 gid_address_size_to_put_no_vni (gid_address_t * gid)
737 gid_address_type_t type = gid_address_type (gid);
738 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
742 gid_address_size_to_put (gid_address_t * gid)
744 if (0 != gid_address_vni (gid))
745 return vni_size_to_write (gid);
747 return gid_address_size_to_put_no_vni (gid);
751 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
753 return (*cast_fcts[type])(gid);
757 gid_address_copy(gid_address_t * dst, gid_address_t * src)
759 gid_address_type_t type = gid_address_type(src);
760 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
761 gid_address_type(dst) = type;
762 gid_address_vni(dst) = gid_address_vni(src);
763 gid_address_vni_mask(dst) = gid_address_vni_mask(src);
767 mac_parse (u8 * offset, gid_address_t * a)
770 offset += sizeof (u16);
772 memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
773 return (sizeof (u16) + sizeof (gid_address_mac (a)));
777 gid_address_parse (u8 * offset, gid_address_t *a)
785 /* NOTE: since gid_adress_parse may be called by vni_parse, we can't 0
786 * the gid address here */
787 afi = clib_net_to_host_u16 (*((u16 *) offset));
791 case LISP_AFI_NO_ADDR:
793 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
796 len = ip_address_parse (offset, afi, &gid_address_ip(a));
797 gid_address_type(a) = GID_ADDR_IP_PREFIX;
798 /* this should be modified outside if needed*/
799 gid_address_ippref_len(a) = 32;
802 len = ip_address_parse (offset, afi, &gid_address_ip(a));
803 gid_address_type(a) = GID_ADDR_IP_PREFIX;
804 /* this should be modified outside if needed*/
805 gid_address_ippref_len(a) = 128;
808 gid_address_type(a) = GID_ADDR_LCAF;
809 len = lcaf_parse (offset, a);
812 len = mac_parse (offset, a);
813 gid_address_type(a) = GID_ADDR_MAC;
816 clib_warning("LISP AFI %d not supported!", afi);
823 no_addr_cmp (void * a1, void * a2)
829 vni_cmp (void * a1, void * a2)
834 if (vni_mask_len (v1) != vni_mask_len (v2))
836 if (vni_vni (v1) != vni_vni (v2))
838 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
841 /* Compare two gid_address_t.
843 * -1: If they are from different afi
844 * 0: Both address are the same
845 * 1: Addr1 is bigger than addr2
846 * 2: Addr2 is bigger than addr1
849 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
851 lcaf_t * lcaf1, * lcaf2;
855 if (gid_address_type(a1) != gid_address_type(a2))
857 if (gid_address_vni(a1) != gid_address_vni(a2))
859 if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
862 switch (gid_address_type(a1))
864 case GID_ADDR_NO_ADDRESS:
870 case GID_ADDR_IP_PREFIX:
871 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
874 lcaf1 = &gid_address_lcaf (a1);
875 lcaf2 = &gid_address_lcaf (a2);
876 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
877 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
880 cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
881 sizeof (gid_address_mac (a1)));
892 locator_parse (void * b, locator_t * loc)
895 u8 status = 1; /* locator up */
899 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
902 len = gid_address_parse (LOC_ADDR(h), &loc->address);
908 loc->priority = LOC_PRIORITY(h);
909 loc->weight = LOC_WEIGHT(h);
910 loc->mpriority = LOC_MPRIORITY(h);
911 loc->mweight = LOC_MWEIGHT(h);
913 return sizeof(locator_hdr_t) + len;
917 locator_copy (locator_t * dst, locator_t * src)
919 /* TODO if gid become more complex, this will need to be changed! */
920 clib_memcpy (dst, src, sizeof(*dst));
922 gid_address_copy (&dst->address, &src->address);
926 locator_cmp (locator_t * l1, locator_t * l2)
929 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
932 if (l1->priority != l2->priority)
934 if (l1->weight != l2->weight)
936 if (l1->mpriority != l2->mpriority)
938 if (l1->mweight != l2->mweight)
944 locator_free (locator_t * l)
947 gid_address_free (&l->address);