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)
196 gid_address_t * a = va_arg(*args, gid_address_t *);
200 memset (&ippref, 0, sizeof (ippref));
201 memset (a, 0, sizeof (a[0]));
203 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
205 if (unformat (input, "%U", unformat_ip_prefix, &ippref))
207 clib_memcpy (&gid_address_ippref(a), &ippref, sizeof (ippref));
208 gid_address_type(a) = GID_ADDR_IP_PREFIX;
210 else if (unformat (input, "%U", unformat_mac_address, mac))
212 clib_memcpy (gid_address_mac(a), mac, sizeof (mac));
213 gid_address_type(a) = GID_ADDR_MAC;
215 else if (unformat (input, "[%d]", &vni))
216 gid_address_vni(a) = vni;
224 ip_address_size (ip_address_t * a)
226 switch (ip_addr_version (a))
229 return sizeof(ip4_address_t);
232 return sizeof(ip6_address_t);
239 ip_version_to_size (u8 ver)
244 return sizeof(ip4_address_t);
247 return sizeof(ip6_address_t);
254 ip_version_to_max_plen (u8 ver)
268 always_inline lisp_afi_e
269 ip_version_to_iana_afi (u16 version)
284 ip_iana_afi_to_version (lisp_afi_e afi)
299 ip_address_size_to_write (ip_address_t * a)
301 return ip_address_size (a) + sizeof (u16);
305 ip_address_iana_afi(ip_address_t *a)
307 return ip_version_to_iana_afi(ip_addr_version(a));
311 ip_address_max_len (u8 version)
313 return version == IP4 ? 32 : 128;
317 ip4_address_size_to_put ()
319 // return sizeof(u16) + sizeof (ip4_address_t);
324 ip6_address_size_to_put ()
326 //return sizeof(u16) + sizeof (ip6_address_t);
331 ip4_address_put (u8 * b, ip4_address_t * a)
333 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
334 u8 *p = b + sizeof (u16);
335 clib_memcpy (p, a, sizeof(*a));
336 return ip4_address_size_to_put();
340 ip6_address_put (u8 * b, ip6_address_t * a)
342 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
343 u8 *p = b + sizeof (u16);
344 clib_memcpy (p, a, sizeof(*a));
345 return ip6_address_size_to_put();
349 ip_address_put (u8 * b, ip_address_t * a)
351 u32 len = ip_address_size (a);
352 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
353 u8 * p = b + sizeof (u16);
354 clib_memcpy (p, &ip_addr_addr (a), len);
355 return (len + sizeof (u16));
359 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
361 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
362 u8 size = ip_version_to_size (ip_addr_version(dst));
363 clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
364 return(sizeof(u16) + size);
368 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
370 lcaf_hdr_t * lh = offset;
371 lcaf->type = lh->type;
373 /* this is a bit of hack: since the LCAF Instance ID is the
374 only message that uses reserved2 field, we can set it here.
375 If any LCAF format starts using reserved2 field as well this needs
376 to be moved elsewhere */
377 lcaf_vni_len (lcaf) = lh->reserved2;
379 return sizeof (lh[0]);
383 vni_parse (u8 * p, void * a)
386 gid_address_t * g = a;
389 gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p);
390 size += sizeof (u32);
391 gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
393 /* nested LCAFs are not supported - it is expected that nested AFI type is
395 size += gid_address_parse (p + size, g);
400 no_addr_parse (u8 * p, void * a)
407 lcaf_parse (void * offset, gid_address_t *addr)
410 offset += sizeof (u16);
411 lcaf_t * lcaf = &gid_address_lcaf (addr);
413 u32 size = lcaf_hdr_parse (offset, lcaf);
414 u8 type = lcaf_type (lcaf);
416 if (!lcaf_parse_fcts[type])
418 clib_warning ("Unsupported LCAF type: %u", type);
421 size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
422 return sizeof (u16) + size;
429 gid_address_free (vni_gid (v));
430 clib_mem_free (vni_gid (v));
434 no_addr_free (void * a)
440 gid_address_free (gid_address_t *a)
442 if (gid_address_type (a) != GID_ADDR_LCAF)
445 lcaf_t * lcaf = &gid_address_lcaf (a);
446 u8 lcaf_type = lcaf_type (lcaf);
447 (*lcaf_free_fcts[lcaf_type])(lcaf);
451 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
454 if (ip_addr_version (ip1) != ip_addr_version(ip2))
456 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
467 ip_address_copy (ip_address_t * dst , ip_address_t * src)
469 clib_memcpy (dst, src, sizeof (ip_address_t));
473 ip_address_copy_addr (void * dst , ip_address_t * src)
475 clib_memcpy (dst, src, ip_address_size(src));
479 ip_address_set(ip_address_t * dst, void * src, u8 version)
481 clib_memcpy(dst, src, ip_version_to_size(version));
482 ip_addr_version(dst) = version;
486 ip_prefix_cast (gid_address_t * a)
488 return &gid_address_ippref(a);
492 ip_prefix_size_to_write (void * pref)
494 ip_prefix_t *a = (ip_prefix_t *) pref;
495 return ip_address_size_to_write (&ip_prefix_addr (a));
499 ip_prefix_write (u8 * p, void * gid)
501 gid_address_t * g = gid;
502 ip_prefix_t *a = &gid_address_ippref (g);
504 switch (ip_prefix_version (a))
507 return ip4_address_put (p, &ip_prefix_v4 (a));
510 return ip6_address_put (p, &ip_prefix_v6 (a));
517 ip_prefix_length (void *a)
519 return ip_prefix_len((ip_prefix_t *) a);
523 ip_prefix_copy (void * dst , void * src)
525 clib_memcpy (dst, src, sizeof (ip_prefix_t));
529 mac_copy (void * dst , void * src)
531 clib_memcpy (dst, src, 6);
535 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
538 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
541 if (ip_prefix_len(p1) < ip_prefix_len(p2))
547 if (ip_prefix_len(p1) > ip_prefix_len(p2))
555 no_addr_copy (void * dst, void * src)
561 vni_copy (void * dst, void * src)
566 clib_memcpy (vd, vs, sizeof (vd[0]));
567 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
568 gid_address_copy (vni_gid (vd), vni_gid (vs));
572 lcaf_copy (void * dst , void * src)
574 lcaf_t * lcaf_dst = dst;
575 lcaf_t * lcaf_src = src;
577 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
578 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
582 lcaf_length (void *a)
594 lcaf_cast (gid_address_t * a)
596 return &gid_address_lcaf (a);
600 mac_cast (gid_address_t * a)
602 return &gid_address_mac (a);
606 no_addr_length (void * a)
612 vni_length (void * a)
615 return (sizeof (u32) /* VNI size */
616 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
620 lcaf_write (u8 * p, void * a)
624 u8 type = lcaf_type (lcaf);
625 lcaf_hdr_t _h, *h = &_h;
627 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
628 size += sizeof (u16);
629 memset (h, 0, sizeof (h[0]));
630 LCAF_TYPE (h) = type;
631 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
632 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
634 clib_memcpy (p + size, h, sizeof (h[0]));
635 size += sizeof (h[0]);
636 len = (*lcaf_write_fcts[type])(p + size, lcaf);
645 mac_write (u8 * p, void * a)
647 *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
648 clib_memcpy(p + sizeof (u16), a, 6);
649 return mac_size_to_write (a);
653 vni_write (u8 * p, void * a)
655 lcaf_hdr_t _h, *h = &_h;
656 gid_address_t * g = a;
659 /* put lcaf header */
660 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
661 size += sizeof (u16);
662 memset (h, 0, sizeof (h[0]));
663 LCAF_TYPE (h) = LCAF_INSTANCE_ID;
664 u16 lcaf_len = sizeof (u32) /* Instance ID size */
665 + gid_address_size_to_put_no_vni (g);
666 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
667 LCAF_RES2 (h) = gid_address_vni_mask (g);
670 clib_memcpy (p + size, h, sizeof (h[0]));
671 size += sizeof (h[0]);
673 u32 * afip = (u32 *)(p + size);
674 afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
675 size += sizeof (u32);
677 /* write the actual address */
678 len = gid_address_put_no_vni (p + size, g);
687 no_addr_write (u8 * p, void * a)
689 /* do nothing; return AFI field size */
694 no_addr_size_to_write (void * a)
696 return sizeof (u16); /* AFI field length */
700 vni_size_to_write (void * a)
702 gid_address_t * g = a;
703 return (sizeof (u32) /* vni size */
704 + sizeof (u16) /* LCAF AFI field size */
705 + sizeof (lcaf_hdr_t)
706 + gid_address_size_to_put_no_vni (g));
710 lcaf_size_to_write (void * a)
712 lcaf_t * lcaf = (lcaf_t *) a;
714 u8 type = lcaf_type (lcaf);
716 size += sizeof (u16); /* AFI size */
718 len = (*lcaf_size_to_write_fcts[type])(lcaf);
726 mac_size_to_write (void * a)
728 return sizeof (u16) + 6;
732 gid_address_len (gid_address_t *a)
734 gid_address_type_t type = gid_address_type (a);
735 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
739 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
741 gid_address_type_t type = gid_address_type (gid);
742 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
746 gid_address_put (u8 * b, gid_address_t * gid)
748 if (0 != gid_address_vni (gid))
749 return vni_write (b, gid);
751 return gid_address_put_no_vni (b, gid);
755 gid_address_size_to_put_no_vni (gid_address_t * gid)
757 gid_address_type_t type = gid_address_type (gid);
758 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
762 gid_address_size_to_put (gid_address_t * gid)
764 if (0 != gid_address_vni (gid))
765 return vni_size_to_write (gid);
767 return gid_address_size_to_put_no_vni (gid);
771 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
773 return (*cast_fcts[type])(gid);
777 gid_address_copy(gid_address_t * dst, gid_address_t * src)
779 gid_address_type_t type = gid_address_type(src);
780 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
781 gid_address_type(dst) = type;
782 gid_address_vni(dst) = gid_address_vni(src);
783 gid_address_vni_mask(dst) = gid_address_vni_mask(src);
787 mac_parse (u8 * offset, gid_address_t * a)
790 offset += sizeof (u16);
792 memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
793 return (sizeof (u16) + sizeof (gid_address_mac (a)));
797 gid_address_parse (u8 * offset, gid_address_t *a)
805 /* NOTE: since gid_adress_parse may be called by vni_parse, we can't 0
806 * the gid address here */
807 afi = clib_net_to_host_u16 (*((u16 *) offset));
811 case LISP_AFI_NO_ADDR:
813 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
816 len = ip_address_parse (offset, afi, &gid_address_ip(a));
817 gid_address_type(a) = GID_ADDR_IP_PREFIX;
818 /* this should be modified outside if needed*/
819 gid_address_ippref_len(a) = 32;
822 len = ip_address_parse (offset, afi, &gid_address_ip(a));
823 gid_address_type(a) = GID_ADDR_IP_PREFIX;
824 /* this should be modified outside if needed*/
825 gid_address_ippref_len(a) = 128;
828 gid_address_type(a) = GID_ADDR_LCAF;
829 len = lcaf_parse (offset, a);
832 len = mac_parse (offset, a);
833 gid_address_type(a) = GID_ADDR_MAC;
836 clib_warning("LISP AFI %d not supported!", afi);
843 no_addr_cmp (void * a1, void * a2)
849 vni_cmp (void * a1, void * a2)
854 if (vni_mask_len (v1) != vni_mask_len (v2))
856 if (vni_vni (v1) != vni_vni (v2))
858 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
861 /* Compare two gid_address_t.
863 * -1: If they are from different afi
864 * 0: Both address are the same
865 * 1: Addr1 is bigger than addr2
866 * 2: Addr2 is bigger than addr1
869 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
871 lcaf_t * lcaf1, * lcaf2;
875 if (gid_address_type(a1) != gid_address_type(a2))
877 if (gid_address_vni(a1) != gid_address_vni(a2))
879 if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
882 switch (gid_address_type(a1))
884 case GID_ADDR_NO_ADDRESS:
890 case GID_ADDR_IP_PREFIX:
891 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
894 lcaf1 = &gid_address_lcaf (a1);
895 lcaf2 = &gid_address_lcaf (a2);
896 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
897 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
900 cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
901 sizeof (gid_address_mac (a1)));
912 locator_parse (void * b, locator_t * loc)
915 u8 status = 1; /* locator up */
919 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
922 len = gid_address_parse (LOC_ADDR(h), &loc->address);
928 loc->priority = LOC_PRIORITY(h);
929 loc->weight = LOC_WEIGHT(h);
930 loc->mpriority = LOC_MPRIORITY(h);
931 loc->mweight = LOC_MWEIGHT(h);
933 return sizeof(locator_hdr_t) + len;
937 locator_copy (locator_t * dst, locator_t * src)
939 /* TODO if gid become more complex, this will need to be changed! */
940 clib_memcpy (dst, src, sizeof(*dst));
942 gid_address_copy (&dst->address, &src->address);
946 locator_cmp (locator_t * l1, locator_t * l2)
949 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
952 if (l1->priority != l2->priority)
954 if (l1->weight != l2->weight)
956 if (l1->mpriority != l2->mpriority)
958 if (l1->mweight != l2->mweight)
964 locator_free (locator_t * l)
967 gid_address_free (&l->address);