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 format_gid_address (u8 * s, va_list * args)
156 gid_address_t * a = va_arg(*args, gid_address_t *);
157 u8 type = gid_address_type(a);
160 case GID_ADDR_IP_PREFIX:
161 return format (s, "[%d] %U", gid_address_vni(a), format_ip_prefix,
162 &gid_address_ippref(a));
163 case GID_ADDR_SRC_DST:
164 return format (s, "[%d] %U|%U", gid_address_vni(a),
165 format_ip_prefix, &gid_address_sd_source_pref(a),
166 format_ip_prefix, &gid_address_sd_dest_pref(a));
168 clib_warning("Can't format gid type %d", type);
174 unformat_gid_address (unformat_input_t * input, va_list * args)
176 gid_address_t * a = va_arg(*args, gid_address_t *);
177 if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a)))
178 gid_address_type(a) = GID_ADDR_IP_PREFIX;
185 ip_address_size (ip_address_t * a)
187 switch (ip_addr_version (a))
190 return sizeof(ip4_address_t);
193 return sizeof(ip6_address_t);
200 ip_version_to_size (u8 ver)
205 return sizeof(ip4_address_t);
208 return sizeof(ip6_address_t);
215 ip_version_to_max_plen (u8 ver)
229 always_inline lisp_afi_e
230 ip_version_to_iana_afi (u16 version)
245 ip_iana_afi_to_version (lisp_afi_e afi)
260 ip_address_size_to_write (ip_address_t * a)
262 return ip_address_size (a) + sizeof (u16);
266 ip_address_iana_afi(ip_address_t *a)
268 return ip_version_to_iana_afi(ip_addr_version(a));
272 ip_address_max_len (u8 version)
274 return version == IP4 ? 32 : 128;
278 ip4_address_size_to_put ()
280 // return sizeof(u16) + sizeof (ip4_address_t);
285 ip6_address_size_to_put ()
287 //return sizeof(u16) + sizeof (ip6_address_t);
292 ip4_address_put (u8 * b, ip4_address_t * a)
294 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
295 u8 *p = b + sizeof (u16);
296 clib_memcpy (p, a, sizeof(*a));
297 return ip4_address_size_to_put();
301 ip6_address_put (u8 * b, ip6_address_t * a)
303 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
304 u8 *p = b + sizeof (u16);
305 clib_memcpy (p, a, sizeof(*a));
306 return ip6_address_size_to_put();
310 ip_address_put (u8 * b, ip_address_t * a)
312 u32 len = ip_address_size (a);
313 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
314 u8 * p = b + sizeof (u16);
315 clib_memcpy (p, &ip_addr_addr (a), len);
316 return (len + sizeof (u16));
320 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
322 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
323 u8 size = ip_version_to_size (ip_addr_version(dst));
324 clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
325 return(sizeof(u16) + size);
329 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
331 lcaf_hdr_t * lh = offset;
332 lcaf->type = lh->type;
334 /* this is a bit of hack: since the LCAF Instance ID is the
335 only message that uses reserved2 field, we can set it here.
336 If any LCAF format starts using reserved2 field as well this needs
337 to be moved elsewhere */
338 lcaf_vni_len (lcaf) = lh->reserved2;
340 return sizeof (lh[0]);
344 vni_parse (u8 * p, void * a)
347 gid_address_t * g = a;
350 gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p);
351 size += sizeof (u32);
352 gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
354 /* nested LCAFs are not supported - it is expected that nested AFI type is
356 size += gid_address_parse (p + size, g);
361 no_addr_parse (u8 * p, void * a)
368 lcaf_parse (void * offset, gid_address_t *addr)
371 offset += sizeof (u16);
372 lcaf_t * lcaf = &gid_address_lcaf (addr);
374 u32 size = lcaf_hdr_parse (offset, lcaf);
375 u8 type = lcaf_type (lcaf);
377 if (!lcaf_parse_fcts[type])
379 clib_warning ("Unsupported LCAF type: %u", type);
382 size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
383 return sizeof (u16) + size;
390 gid_address_free (vni_gid (v));
391 clib_mem_free (vni_gid (v));
395 no_addr_free (void * a)
401 gid_address_free (gid_address_t *a)
403 if (gid_address_type (a) != GID_ADDR_LCAF)
406 lcaf_t * lcaf = &gid_address_lcaf (a);
407 u8 lcaf_type = lcaf_type (lcaf);
408 (*lcaf_free_fcts[lcaf_type])(lcaf);
412 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
415 if (ip_addr_version (ip1) != ip_addr_version(ip2))
417 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
428 ip_address_copy (ip_address_t * dst , ip_address_t * src)
430 clib_memcpy (dst, src, sizeof (ip_address_t));
434 ip_address_copy_addr (void * dst , ip_address_t * src)
436 clib_memcpy (dst, src, ip_address_size(src));
440 ip_address_set(ip_address_t * dst, void * src, u8 version)
442 clib_memcpy(dst, src, ip_version_to_size(version));
443 ip_addr_version(dst) = version;
447 ip_prefix_cast (gid_address_t * a)
449 return &gid_address_ippref(a);
453 ip_prefix_size_to_write (void * pref)
455 ip_prefix_t *a = (ip_prefix_t *) pref;
456 return ip_address_size_to_write (&ip_prefix_addr (a));
460 ip_prefix_write (u8 * p, void * gid)
462 gid_address_t * g = gid;
463 ip_prefix_t *a = &gid_address_ippref (g);
465 switch (ip_prefix_version (a))
468 return ip4_address_put (p, &ip_prefix_v4 (a));
471 return ip6_address_put (p, &ip_prefix_v6 (a));
478 ip_prefix_length (void *a)
480 return ip_prefix_len((ip_prefix_t *) a);
484 ip_prefix_copy (void * dst , void * src)
486 clib_memcpy (dst, src, sizeof (ip_prefix_t));
490 mac_copy (void * dst , void * src)
492 clib_memcpy (dst, src, 6);
496 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
499 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
502 if (ip_prefix_len(p1) < ip_prefix_len(p2))
508 if (ip_prefix_len(p1) > ip_prefix_len(p2))
516 no_addr_copy (void * dst, void * src)
522 vni_copy (void * dst, void * src)
527 clib_memcpy (vd, vs, sizeof (vd[0]));
528 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
529 gid_address_copy (vni_gid (vd), vni_gid (vs));
533 lcaf_copy (void * dst , void * src)
535 lcaf_t * lcaf_dst = dst;
536 lcaf_t * lcaf_src = src;
538 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
539 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
543 lcaf_length (void *a)
555 lcaf_cast (gid_address_t * a)
557 return &gid_address_lcaf (a);
561 mac_cast (gid_address_t * a)
563 return &gid_address_mac (a);
567 no_addr_length (void * a)
573 vni_length (void * a)
576 return (sizeof (u32) /* VNI size */
577 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
581 lcaf_write (u8 * p, void * a)
585 u8 type = lcaf_type (lcaf);
586 lcaf_hdr_t _h, *h = &_h;
588 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
589 size += sizeof (u16);
590 memset (h, 0, sizeof (h[0]));
591 LCAF_TYPE (h) = type;
592 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
593 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
595 clib_memcpy (p + size, h, sizeof (h[0]));
596 size += sizeof (h[0]);
597 len = (*lcaf_write_fcts[type])(p + size, lcaf);
606 mac_write (u8 * p, void * a)
608 *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
609 clib_memcpy(p + sizeof (u16), a, 6);
610 return mac_size_to_write (a);
614 vni_write (u8 * p, void * a)
616 lcaf_hdr_t _h, *h = &_h;
617 gid_address_t * g = a;
620 /* put lcaf header */
621 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
622 size += sizeof (u16);
623 memset (h, 0, sizeof (h[0]));
624 LCAF_TYPE (h) = LCAF_INSTANCE_ID;
625 u16 lcaf_len = sizeof (u32) /* Instance ID size */
626 + gid_address_size_to_put_no_vni (g);
627 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
628 LCAF_RES2 (h) = gid_address_vni_mask (g);
631 clib_memcpy (p + size, h, sizeof (h[0]));
632 size += sizeof (h[0]);
634 u32 * afip = (u32 *)(p + size);
635 afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
636 size += sizeof (u32);
638 /* write the actual address */
639 len = gid_address_put_no_vni (p + size, g);
648 no_addr_write (u8 * p, void * a)
650 /* do nothing; return AFI field size */
655 no_addr_size_to_write (void * a)
657 return sizeof (u16); /* AFI field length */
661 vni_size_to_write (void * a)
663 gid_address_t * g = a;
664 return (sizeof (u32) /* vni size */
665 + sizeof (u16) /* LCAF AFI field size */
666 + sizeof (lcaf_hdr_t)
667 + gid_address_size_to_put_no_vni (g));
671 lcaf_size_to_write (void * a)
673 lcaf_t * lcaf = (lcaf_t *) a;
675 u8 type = lcaf_type (lcaf);
677 size += sizeof (u16); /* AFI size */
679 len = (*lcaf_size_to_write_fcts[type])(lcaf);
687 mac_size_to_write (void * a)
689 return sizeof (u16) + 6;
693 gid_address_len (gid_address_t *a)
695 gid_address_type_t type = gid_address_type (a);
696 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
700 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
702 gid_address_type_t type = gid_address_type (gid);
703 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
707 gid_address_put (u8 * b, gid_address_t * gid)
709 if (0 != gid_address_vni (gid))
710 return vni_write (b, gid);
712 return gid_address_put_no_vni (b, gid);
716 gid_address_size_to_put_no_vni (gid_address_t * gid)
718 gid_address_type_t type = gid_address_type (gid);
719 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
723 gid_address_size_to_put (gid_address_t * gid)
725 if (0 != gid_address_vni (gid))
726 return vni_size_to_write (gid);
728 return gid_address_size_to_put_no_vni (gid);
732 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
734 return (*cast_fcts[type])(gid);
738 gid_address_copy(gid_address_t * dst, gid_address_t * src)
740 gid_address_type_t type = gid_address_type(src);
741 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
742 gid_address_type(dst) = type;
743 gid_address_vni(dst) = gid_address_vni(src);
744 gid_address_vni_mask(dst) = gid_address_vni_mask(src);
748 mac_parse (u8 * offset, gid_address_t * a)
751 offset += sizeof (u16);
753 memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
754 return (sizeof (u16) + sizeof (gid_address_mac (a)));
758 gid_address_parse (u8 * offset, gid_address_t *a)
766 afi = clib_net_to_host_u16 (*((u16 *) offset));
770 case LISP_AFI_NO_ADDR:
772 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
775 len = ip_address_parse (offset, afi, &gid_address_ip(a));
776 gid_address_type(a) = GID_ADDR_IP_PREFIX;
777 /* this should be modified outside if needed*/
778 gid_address_ippref_len(a) = 32;
781 len = ip_address_parse (offset, afi, &gid_address_ip(a));
782 gid_address_type(a) = GID_ADDR_IP_PREFIX;
783 /* this should be modified outside if needed*/
784 gid_address_ippref_len(a) = 128;
787 gid_address_type(a) = GID_ADDR_LCAF;
788 len = lcaf_parse (offset, a);
791 len = mac_parse (offset, a);
792 gid_address_type(a) = GID_ADDR_MAC;
795 clib_warning("LISP AFI %d not supported!", afi);
802 no_addr_cmp (void * a1, void * a2)
808 vni_cmp (void * a1, void * a2)
813 if (vni_mask_len (v1) != vni_mask_len (v2))
815 if (vni_vni (v1) != vni_vni (v2))
817 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
820 /* Compare two gid_address_t.
822 * -1: If they are from different afi
823 * 0: Both address are the same
824 * 1: Addr1 is bigger than addr2
825 * 2: Addr2 is bigger than addr1
828 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
830 lcaf_t * lcaf1, * lcaf2;
834 if (gid_address_type(a1) != gid_address_type(a2))
836 if (gid_address_vni(a1) != gid_address_vni(a2))
838 if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
841 switch (gid_address_type(a1))
843 case GID_ADDR_NO_ADDRESS:
849 case GID_ADDR_IP_PREFIX:
850 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
853 lcaf1 = &gid_address_lcaf (a1);
854 lcaf2 = &gid_address_lcaf (a2);
855 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
856 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
859 cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
860 sizeof (gid_address_mac (a1)));
871 locator_parse (void * b, locator_t * loc)
874 u8 status = 1; /* locator up */
878 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
881 len = gid_address_parse (LOC_ADDR(h), &loc->address);
887 loc->priority = LOC_PRIORITY(h);
888 loc->weight = LOC_WEIGHT(h);
889 loc->mpriority = LOC_MPRIORITY(h);
890 loc->mweight = LOC_MWEIGHT(h);
892 return sizeof(locator_hdr_t) + len;
896 locator_copy (locator_t * dst, locator_t * src)
898 /* TODO if gid become more complex, this will need to be changed! */
899 clib_memcpy (dst, src, sizeof(*dst));
901 gid_address_copy (&dst->address, &src->address);
905 locator_cmp (locator_t * l1, locator_t * l2)
908 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
911 if (l1->priority != l2->priority)
913 if (l1->weight != l2->weight)
915 if (l1->mpriority != l2->mpriority)
917 if (l1->mweight != l2->mweight)
923 locator_free (locator_t * l)
926 gid_address_free (&l->address);