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(ip_prefix_t * a)
532 int preflen = ip_prefix_len(a);
538 ip = &ip_prefix_addr (a);
539 switch (ip_addr_version (ip))
547 ip4 = &ip_addr_v4 (ip);
548 mask = pow2_mask (preflen) << (32 - preflen);
549 mask = clib_host_to_net_u32 (mask);
550 ip4->data_u32 &= mask;
558 ip6 = &ip_addr_v6 (ip);
559 memset(mask_6, 0, sizeof(mask_6));
564 for (j = 0; j < i0; j++)
571 m[i0] = clib_host_to_net_u32 (pow2_mask(i1) << (32 - i1));
574 ip6->as_u64[0] &= mask_6[0];
575 ip6->as_u64[1] &= mask_6[1];
584 ip_prefix_cast (gid_address_t * a)
586 return &gid_address_ippref(a);
590 ip_prefix_size_to_write (void * pref)
592 ip_prefix_t *a = (ip_prefix_t *) pref;
593 return ip_address_size_to_write (&ip_prefix_addr (a));
597 ip_prefix_write (u8 * p, void * gid)
599 gid_address_t * g = gid;
600 ip_prefix_t *a = &gid_address_ippref (g);
602 switch (ip_prefix_version (a))
605 return ip4_address_put (p, &ip_prefix_v4 (a));
608 return ip6_address_put (p, &ip_prefix_v6 (a));
615 ip_prefix_length (void *a)
617 return ip_prefix_len((ip_prefix_t *) a);
621 ip_prefix_copy (void * dst , void * src)
623 clib_memcpy (dst, src, sizeof (ip_prefix_t));
627 mac_copy (void * dst , void * src)
629 clib_memcpy (dst, src, 6);
633 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
637 ip_prefix_normalize (p1);
638 ip_prefix_normalize (p2);
640 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
643 if (ip_prefix_len(p1) < ip_prefix_len(p2))
649 if (ip_prefix_len(p1) > ip_prefix_len(p2))
657 no_addr_copy (void * dst, void * src)
663 vni_copy (void * dst, void * src)
668 clib_memcpy (vd, vs, sizeof (vd[0]));
669 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
670 gid_address_copy (vni_gid (vd), vni_gid (vs));
674 lcaf_copy (void * dst , void * src)
676 lcaf_t * lcaf_dst = dst;
677 lcaf_t * lcaf_src = src;
679 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
680 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
684 lcaf_length (void *a)
696 lcaf_cast (gid_address_t * a)
698 return &gid_address_lcaf (a);
702 mac_cast (gid_address_t * a)
704 return &gid_address_mac (a);
708 no_addr_length (void * a)
714 vni_length (void * a)
717 return (sizeof (u32) /* VNI size */
718 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
722 lcaf_write (u8 * p, void * a)
726 u8 type = lcaf_type (lcaf);
727 lcaf_hdr_t _h, *h = &_h;
729 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
730 size += sizeof (u16);
731 memset (h, 0, sizeof (h[0]));
732 LCAF_TYPE (h) = type;
733 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
734 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
736 clib_memcpy (p + size, h, sizeof (h[0]));
737 size += sizeof (h[0]);
738 len = (*lcaf_write_fcts[type])(p + size, lcaf);
747 mac_write (u8 * p, void * a)
749 *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
750 clib_memcpy(p + sizeof (u16), a, 6);
751 return mac_size_to_write (a);
755 vni_write (u8 * p, void * a)
757 lcaf_hdr_t _h, *h = &_h;
758 gid_address_t * g = a;
761 /* put lcaf header */
762 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
763 size += sizeof (u16);
764 memset (h, 0, sizeof (h[0]));
765 LCAF_TYPE (h) = LCAF_INSTANCE_ID;
766 u16 lcaf_len = sizeof (u32) /* Instance ID size */
767 + gid_address_size_to_put_no_vni (g);
768 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
769 LCAF_RES2 (h) = gid_address_vni_mask (g);
772 clib_memcpy (p + size, h, sizeof (h[0]));
773 size += sizeof (h[0]);
775 u32 * afip = (u32 *)(p + size);
776 afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
777 size += sizeof (u32);
779 /* write the actual address */
780 len = gid_address_put_no_vni (p + size, g);
789 no_addr_write (u8 * p, void * a)
791 /* do nothing; return AFI field size */
796 no_addr_size_to_write (void * a)
798 return sizeof (u16); /* AFI field length */
802 vni_size_to_write (void * a)
804 gid_address_t * g = a;
805 return (sizeof (u32) /* vni size */
806 + sizeof (u16) /* LCAF AFI field size */
807 + sizeof (lcaf_hdr_t)
808 + gid_address_size_to_put_no_vni (g));
812 lcaf_size_to_write (void * a)
814 lcaf_t * lcaf = (lcaf_t *) a;
816 u8 type = lcaf_type (lcaf);
818 size += sizeof (u16); /* AFI size */
820 len = (*lcaf_size_to_write_fcts[type])(lcaf);
828 mac_size_to_write (void * a)
830 return sizeof (u16) + 6;
834 gid_address_len (gid_address_t *a)
836 gid_address_type_t type = gid_address_type (a);
837 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
841 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
843 gid_address_type_t type = gid_address_type (gid);
844 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
848 gid_address_put (u8 * b, gid_address_t * gid)
850 if (0 != gid_address_vni (gid))
851 return vni_write (b, gid);
853 return gid_address_put_no_vni (b, gid);
857 gid_address_size_to_put_no_vni (gid_address_t * gid)
859 gid_address_type_t type = gid_address_type (gid);
860 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
864 gid_address_size_to_put (gid_address_t * gid)
866 if (0 != gid_address_vni (gid))
867 return vni_size_to_write (gid);
869 return gid_address_size_to_put_no_vni (gid);
873 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
875 return (*cast_fcts[type])(gid);
879 gid_address_copy(gid_address_t * dst, gid_address_t * src)
881 gid_address_type_t type = gid_address_type(src);
882 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
883 gid_address_type(dst) = type;
884 gid_address_vni(dst) = gid_address_vni(src);
885 gid_address_vni_mask(dst) = gid_address_vni_mask(src);
889 mac_parse (u8 * offset, gid_address_t * a)
892 offset += sizeof (u16);
894 memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
895 return (sizeof (u16) + sizeof (gid_address_mac (a)));
899 gid_address_parse (u8 * offset, gid_address_t *a)
907 /* NOTE: since gid_adress_parse may be called by vni_parse, we can't 0
908 * the gid address here */
909 afi = clib_net_to_host_u16 (*((u16 *) offset));
913 case LISP_AFI_NO_ADDR:
915 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
918 len = ip_address_parse (offset, afi, &gid_address_ip(a));
919 gid_address_type(a) = GID_ADDR_IP_PREFIX;
920 /* this should be modified outside if needed*/
921 gid_address_ippref_len(a) = 32;
924 len = ip_address_parse (offset, afi, &gid_address_ip(a));
925 gid_address_type(a) = GID_ADDR_IP_PREFIX;
926 /* this should be modified outside if needed*/
927 gid_address_ippref_len(a) = 128;
930 gid_address_type(a) = GID_ADDR_LCAF;
931 len = lcaf_parse (offset, a);
934 len = mac_parse (offset, a);
935 gid_address_type(a) = GID_ADDR_MAC;
938 clib_warning("LISP AFI %d not supported!", afi);
945 no_addr_cmp (void * a1, void * a2)
951 vni_cmp (void * a1, void * a2)
956 if (vni_mask_len (v1) != vni_mask_len (v2))
958 if (vni_vni (v1) != vni_vni (v2))
960 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
963 /* Compare two gid_address_t.
965 * -1: If they are from different afi
966 * 0: Both address are the same
967 * 1: Addr1 is bigger than addr2
968 * 2: Addr2 is bigger than addr1
971 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
973 lcaf_t * lcaf1, * lcaf2;
977 if (gid_address_type(a1) != gid_address_type(a2))
979 if (gid_address_vni(a1) != gid_address_vni(a2))
981 if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
984 switch (gid_address_type(a1))
986 case GID_ADDR_NO_ADDRESS:
992 case GID_ADDR_IP_PREFIX:
993 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
996 lcaf1 = &gid_address_lcaf (a1);
997 lcaf2 = &gid_address_lcaf (a2);
998 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
999 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
1002 cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
1003 sizeof (gid_address_mac (a1)));
1014 locator_parse (void * b, locator_t * loc)
1017 u8 status = 1; /* locator up */
1021 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
1024 len = gid_address_parse (LOC_ADDR(h), &loc->address);
1028 loc->state = status;
1030 loc->priority = LOC_PRIORITY(h);
1031 loc->weight = LOC_WEIGHT(h);
1032 loc->mpriority = LOC_MPRIORITY(h);
1033 loc->mweight = LOC_MWEIGHT(h);
1035 return sizeof(locator_hdr_t) + len;
1039 locator_copy (locator_t * dst, locator_t * src)
1041 /* TODO if gid become more complex, this will need to be changed! */
1042 clib_memcpy (dst, src, sizeof(*dst));
1044 gid_address_copy (&dst->address, &src->address);
1048 locator_cmp (locator_t * l1, locator_t * l2)
1051 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
1054 if (l1->priority != l2->priority)
1056 if (l1->weight != l2->weight)
1058 if (l1->mpriority != l2->mpriority)
1060 if (l1->mweight != l2->mweight)
1066 locator_free (locator_t * l)
1069 gid_address_free (&l->address);