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 if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a),
152 if ((ip_prefix_version(a) == IP4 && 32 < ip_prefix_len(a)) ||
153 (ip_prefix_version(a) == IP6 && 128 < ip_prefix_length(a)))
155 clib_warning("Prefix length to big: %d!", ip_prefix_len(a));
158 ip_prefix_normalize(a);
166 unformat_mac_address (unformat_input_t * input, va_list * args)
168 u8 * a = va_arg(*args, u8 *);
169 return unformat (input, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3],
174 format_mac_address (u8 * s, va_list * args)
176 u8 * a = va_arg (*args, u8 *);
177 return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
178 a[0], a[1], a[2], a[3], a[4], a[5]);
182 format_gid_address (u8 * s, va_list * args)
184 gid_address_t * a = va_arg(*args, gid_address_t *);
185 u8 type = gid_address_type(a);
188 case GID_ADDR_IP_PREFIX:
189 return format (s, "[%d] %U", gid_address_vni(a), format_ip_prefix,
190 &gid_address_ippref(a));
191 case GID_ADDR_SRC_DST:
192 return format (s, "[%d] %U|%U", gid_address_vni(a),
193 format_ip_prefix, &gid_address_sd_source_pref(a),
194 format_ip_prefix, &gid_address_sd_dest_pref(a));
196 return format (s, "[%d] %U", gid_address_vni(a), format_mac_address,
197 &gid_address_mac(a));
199 clib_warning("Can't format gid type %d", type);
205 unformat_gid_address (unformat_input_t * input, va_list * args)
208 gid_address_t * a = va_arg(*args, gid_address_t *);
212 memset (&ippref, 0, sizeof (ippref));
213 memset(a, 0, sizeof(a[0]));
215 if (unformat (input, "%U", unformat_ip_prefix, &ippref))
217 clib_memcpy (&gid_address_ippref(a), &ippref, sizeof(ippref));
218 gid_address_type(a) = GID_ADDR_IP_PREFIX;
220 else if (unformat (input, "%U", unformat_mac_address, mac))
222 clib_memcpy (gid_address_mac(a), mac, sizeof(mac));
223 gid_address_type(a) = GID_ADDR_MAC;
225 else if (unformat (input, "[%d]", &vni))
226 gid_address_vni(a) = vni;
234 unformat_negative_mapping_action (unformat_input_t * input, va_list * args)
236 u32 * action = va_arg(*args, u32 *);
239 if (unformat (input, "%s", &s))
241 int len = vec_len(s);
242 clib_warning ("len = %d", len);
243 if (!strcmp ((char *) s, "no-action"))
244 action[0] = ACTION_NONE;
245 if (!strcmp ((char *) s, "natively-forward"))
246 action[0] = ACTION_NATIVELY_FORWARDED;
247 if (!strcmp ((char *) s, "send-map-request"))
248 action[0] = ACTION_SEND_MAP_REQUEST;
249 else if (!strcmp ((char *) s, "drop"))
250 action[0] = ACTION_DROP;
253 clib_warning("invalid action: '%s'", s);
254 action[0] = ACTION_DROP;
265 ip_address_size (ip_address_t * a)
267 switch (ip_addr_version (a))
270 return sizeof(ip4_address_t);
273 return sizeof(ip6_address_t);
280 ip_version_to_size (u8 ver)
285 return sizeof(ip4_address_t);
288 return sizeof(ip6_address_t);
295 ip_version_to_max_plen (u8 ver)
309 always_inline lisp_afi_e
310 ip_version_to_iana_afi (u16 version)
325 ip_iana_afi_to_version (lisp_afi_e afi)
340 ip_address_size_to_write (ip_address_t * a)
342 return ip_address_size (a) + sizeof (u16);
346 ip_address_iana_afi(ip_address_t *a)
348 return ip_version_to_iana_afi(ip_addr_version(a));
352 ip_address_max_len (u8 version)
354 return version == IP4 ? 32 : 128;
358 ip4_address_size_to_put ()
360 // return sizeof(u16) + sizeof (ip4_address_t);
365 ip6_address_size_to_put ()
367 //return sizeof(u16) + sizeof (ip6_address_t);
372 ip4_address_put (u8 * b, ip4_address_t * a)
374 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
375 u8 *p = b + sizeof (u16);
376 clib_memcpy (p, a, sizeof(*a));
377 return ip4_address_size_to_put();
381 ip6_address_put (u8 * b, ip6_address_t * a)
383 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
384 u8 *p = b + sizeof (u16);
385 clib_memcpy (p, a, sizeof(*a));
386 return ip6_address_size_to_put();
390 ip_address_put (u8 * b, ip_address_t * a)
392 u32 len = ip_address_size (a);
393 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
394 u8 * p = b + sizeof (u16);
395 clib_memcpy (p, &ip_addr_addr (a), len);
396 return (len + sizeof (u16));
400 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
402 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
403 u8 size = ip_version_to_size (ip_addr_version(dst));
404 clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
405 return(sizeof(u16) + size);
409 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
411 lcaf_hdr_t * lh = offset;
412 lcaf->type = lh->type;
414 /* this is a bit of hack: since the LCAF Instance ID is the
415 only message that uses reserved2 field, we can set it here.
416 If any LCAF format starts using reserved2 field as well this needs
417 to be moved elsewhere */
418 lcaf_vni_len (lcaf) = lh->reserved2;
420 return sizeof (lh[0]);
424 vni_parse (u8 * p, void * a)
427 gid_address_t * g = a;
430 gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p);
431 size += sizeof (u32);
432 gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
434 /* nested LCAFs are not supported - it is expected that nested AFI type is
436 size += gid_address_parse (p + size, g);
441 no_addr_parse (u8 * p, void * a)
448 lcaf_parse (void * offset, gid_address_t *addr)
451 offset += sizeof (u16);
452 lcaf_t * lcaf = &gid_address_lcaf (addr);
454 u32 size = lcaf_hdr_parse (offset, lcaf);
455 u8 type = lcaf_type (lcaf);
457 if (!lcaf_parse_fcts[type])
459 clib_warning ("Unsupported LCAF type: %u", type);
462 size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
463 return sizeof (u16) + size;
470 gid_address_free (vni_gid (v));
471 clib_mem_free (vni_gid (v));
475 no_addr_free (void * a)
481 gid_address_free (gid_address_t *a)
483 if (gid_address_type (a) != GID_ADDR_LCAF)
486 lcaf_t * lcaf = &gid_address_lcaf (a);
487 u8 lcaf_type = lcaf_type (lcaf);
488 (*lcaf_free_fcts[lcaf_type])(lcaf);
492 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
495 if (ip_addr_version (ip1) != ip_addr_version(ip2))
497 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
508 ip_address_copy (ip_address_t * dst , ip_address_t * src)
510 clib_memcpy (dst, src, sizeof (ip_address_t));
514 ip_address_copy_addr (void * dst , ip_address_t * src)
516 clib_memcpy (dst, src, ip_address_size(src));
520 ip_address_set(ip_address_t * dst, void * src, u8 version)
522 clib_memcpy(dst, src, ip_version_to_size(version));
523 ip_addr_version(dst) = version;
527 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
538 mask = pow2_mask (preflen) << (32 - preflen);
539 mask = clib_host_to_net_u32 (mask);
540 ip4->data_u32 &= mask;
544 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
552 memset (mask_6, 0, sizeof (mask_6));
561 m = (u32 * ) &mask_6[0];
563 for (j = 0; j < i0; j++)
570 m[i0] = clib_host_to_net_u32 (pow2_mask(i1) << (32 - i1));
573 for (j = 0; j < sizeof(mask_6); j++)
575 ip6->as_u8[j] &= mask_6[j];
580 ip_prefix_normalize(ip_prefix_t * a)
582 u8 preflen = ip_prefix_len(a);
584 switch (ip_prefix_version (a))
587 ip_prefix_normalize_ip4(&ip_prefix_v4(a), preflen);
591 ip_prefix_normalize_ip6(&ip_prefix_v6(a), preflen);
600 ip_prefix_cast (gid_address_t * a)
602 return &gid_address_ippref(a);
606 ip_prefix_size_to_write (void * pref)
608 ip_prefix_t *a = (ip_prefix_t *) pref;
609 return ip_address_size_to_write (&ip_prefix_addr (a));
613 ip_prefix_write (u8 * p, void * gid)
615 gid_address_t * g = gid;
616 ip_prefix_t *a = &gid_address_ippref (g);
618 switch (ip_prefix_version (a))
621 return ip4_address_put (p, &ip_prefix_v4 (a));
624 return ip6_address_put (p, &ip_prefix_v6 (a));
631 ip_prefix_length (void *a)
633 return ip_prefix_len((ip_prefix_t *) a);
637 ip_prefix_copy (void * dst , void * src)
639 clib_memcpy (dst, src, sizeof (ip_prefix_t));
643 mac_copy (void * dst , void * src)
645 clib_memcpy (dst, src, 6);
649 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
653 ip_prefix_normalize (p1);
654 ip_prefix_normalize (p2);
656 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
659 if (ip_prefix_len(p1) < ip_prefix_len(p2))
665 if (ip_prefix_len(p1) > ip_prefix_len(p2))
673 no_addr_copy (void * dst, void * src)
679 vni_copy (void * dst, void * src)
684 clib_memcpy (vd, vs, sizeof (vd[0]));
685 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
686 gid_address_copy (vni_gid (vd), vni_gid (vs));
690 lcaf_copy (void * dst , void * src)
692 lcaf_t * lcaf_dst = dst;
693 lcaf_t * lcaf_src = src;
695 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
696 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
700 lcaf_length (void *a)
712 lcaf_cast (gid_address_t * a)
714 return &gid_address_lcaf (a);
718 mac_cast (gid_address_t * a)
720 return &gid_address_mac (a);
724 no_addr_length (void * a)
730 vni_length (void * a)
733 return (sizeof (u32) /* VNI size */
734 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
738 lcaf_write (u8 * p, void * a)
742 u8 type = lcaf_type (lcaf);
743 lcaf_hdr_t _h, *h = &_h;
745 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
746 size += sizeof (u16);
747 memset (h, 0, sizeof (h[0]));
748 LCAF_TYPE (h) = type;
749 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
750 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
752 clib_memcpy (p + size, h, sizeof (h[0]));
753 size += sizeof (h[0]);
754 len = (*lcaf_write_fcts[type])(p + size, lcaf);
763 mac_write (u8 * p, void * a)
765 *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
766 clib_memcpy(p + sizeof (u16), a, 6);
767 return mac_size_to_write (a);
771 vni_write (u8 * p, void * a)
773 lcaf_hdr_t _h, *h = &_h;
774 gid_address_t * g = a;
777 /* put lcaf header */
778 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
779 size += sizeof (u16);
780 memset (h, 0, sizeof (h[0]));
781 LCAF_TYPE (h) = LCAF_INSTANCE_ID;
782 u16 lcaf_len = sizeof (u32) /* Instance ID size */
783 + gid_address_size_to_put_no_vni (g);
784 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
785 LCAF_RES2 (h) = gid_address_vni_mask (g);
788 clib_memcpy (p + size, h, sizeof (h[0]));
789 size += sizeof (h[0]);
791 u32 * afip = (u32 *)(p + size);
792 afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
793 size += sizeof (u32);
795 /* write the actual address */
796 len = gid_address_put_no_vni (p + size, g);
805 no_addr_write (u8 * p, void * a)
807 /* do nothing; return AFI field size */
812 no_addr_size_to_write (void * a)
814 return sizeof (u16); /* AFI field length */
818 vni_size_to_write (void * a)
820 gid_address_t * g = a;
821 return (sizeof (u32) /* vni size */
822 + sizeof (u16) /* LCAF AFI field size */
823 + sizeof (lcaf_hdr_t)
824 + gid_address_size_to_put_no_vni (g));
828 lcaf_size_to_write (void * a)
830 lcaf_t * lcaf = (lcaf_t *) a;
832 u8 type = lcaf_type (lcaf);
834 size += sizeof (u16); /* AFI size */
836 len = (*lcaf_size_to_write_fcts[type])(lcaf);
844 mac_size_to_write (void * a)
846 return sizeof (u16) + 6;
850 gid_address_len (gid_address_t *a)
852 gid_address_type_t type = gid_address_type (a);
853 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
857 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
859 gid_address_type_t type = gid_address_type (gid);
860 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
864 gid_address_put (u8 * b, gid_address_t * gid)
866 if (0 != gid_address_vni (gid))
867 return vni_write (b, gid);
869 return gid_address_put_no_vni (b, gid);
873 gid_address_size_to_put_no_vni (gid_address_t * gid)
875 gid_address_type_t type = gid_address_type (gid);
876 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
880 gid_address_size_to_put (gid_address_t * gid)
882 if (0 != gid_address_vni (gid))
883 return vni_size_to_write (gid);
885 return gid_address_size_to_put_no_vni (gid);
889 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
891 return (*cast_fcts[type])(gid);
895 gid_address_copy(gid_address_t * dst, gid_address_t * src)
897 gid_address_type_t type = gid_address_type(src);
898 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
899 gid_address_type(dst) = type;
900 gid_address_vni(dst) = gid_address_vni(src);
901 gid_address_vni_mask(dst) = gid_address_vni_mask(src);
905 mac_parse (u8 * offset, gid_address_t * a)
908 offset += sizeof (u16);
910 memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
911 return (sizeof (u16) + sizeof (gid_address_mac (a)));
915 gid_address_parse (u8 * offset, gid_address_t *a)
923 /* NOTE: since gid_adress_parse may be called by vni_parse, we can't 0
924 * the gid address here */
925 afi = clib_net_to_host_u16 (*((u16 *) offset));
929 case LISP_AFI_NO_ADDR:
931 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
934 len = ip_address_parse (offset, afi, &gid_address_ip(a));
935 gid_address_type(a) = GID_ADDR_IP_PREFIX;
936 /* this should be modified outside if needed*/
937 gid_address_ippref_len(a) = 32;
940 len = ip_address_parse (offset, afi, &gid_address_ip(a));
941 gid_address_type(a) = GID_ADDR_IP_PREFIX;
942 /* this should be modified outside if needed*/
943 gid_address_ippref_len(a) = 128;
946 gid_address_type(a) = GID_ADDR_LCAF;
947 len = lcaf_parse (offset, a);
950 len = mac_parse (offset, a);
951 gid_address_type(a) = GID_ADDR_MAC;
954 clib_warning("LISP AFI %d not supported!", afi);
961 no_addr_cmp (void * a1, void * a2)
967 vni_cmp (void * a1, void * a2)
972 if (vni_mask_len (v1) != vni_mask_len (v2))
974 if (vni_vni (v1) != vni_vni (v2))
976 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
979 /* Compare two gid_address_t.
981 * -1: If they are from different afi
982 * 0: Both address are the same
983 * 1: Addr1 is bigger than addr2
984 * 2: Addr2 is bigger than addr1
987 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
989 lcaf_t * lcaf1, * lcaf2;
993 if (gid_address_type(a1) != gid_address_type(a2))
995 if (gid_address_vni(a1) != gid_address_vni(a2))
997 if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
1000 switch (gid_address_type(a1))
1002 case GID_ADDR_NO_ADDRESS:
1008 case GID_ADDR_IP_PREFIX:
1009 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
1012 lcaf1 = &gid_address_lcaf (a1);
1013 lcaf2 = &gid_address_lcaf (a2);
1014 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
1015 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
1018 cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
1019 sizeof (gid_address_mac (a1)));
1030 locator_parse (void * b, locator_t * loc)
1033 u8 status = 1; /* locator up */
1037 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
1040 len = gid_address_parse (LOC_ADDR(h), &loc->address);
1044 loc->state = status;
1046 loc->priority = LOC_PRIORITY(h);
1047 loc->weight = LOC_WEIGHT(h);
1048 loc->mpriority = LOC_MPRIORITY(h);
1049 loc->mweight = LOC_MWEIGHT(h);
1051 return sizeof(locator_hdr_t) + len;
1055 locator_copy (locator_t * dst, locator_t * src)
1057 /* TODO if gid become more complex, this will need to be changed! */
1058 clib_memcpy (dst, src, sizeof(*dst));
1060 gid_address_copy (&dst->address, &src->address);
1064 locator_cmp (locator_t * l1, locator_t * l2)
1067 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
1070 if (l1->priority != l2->priority)
1072 if (l1->weight != l2->weight)
1074 if (l1->mpriority != l2->mpriority)
1076 if (l1->mweight != l2->mweight)
1082 locator_free (locator_t * l)
1085 gid_address_free (&l->address);