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));
214 if (unformat (input, "%U", unformat_ip_prefix, &ippref))
216 ip_prefix_copy (&gid_address_ippref(a), &ippref);
217 gid_address_type(a) = GID_ADDR_IP_PREFIX;
219 else if (unformat (input, "%U", unformat_mac_address, mac))
221 mac_copy (gid_address_mac(a), mac);
222 gid_address_type(a) = GID_ADDR_MAC;
224 else if (unformat (input, "[%d]", &vni))
225 gid_address_vni(a) = vni;
233 unformat_negative_mapping_action (unformat_input_t * input, va_list * args)
235 u32 * action = va_arg(*args, u32 *);
238 if (unformat (input, "%s", &s))
240 if (!strcmp ((char *) s, "no-action"))
241 action[0] = LISP_NO_ACTION;
242 else if (!strcmp ((char *) s, "natively-forward"))
243 action[0] = LISP_FORWARD_NATIVE;
244 else if (!strcmp ((char *) s, "send-map-request"))
245 action[0] = LISP_SEND_MAP_REQUEST;
246 else if (!strcmp ((char *) s, "drop"))
247 action[0] = LISP_DROP;
250 clib_warning("invalid action: '%s'", s);
251 action[0] = LISP_DROP;
262 ip_address_size (ip_address_t * a)
264 switch (ip_addr_version (a))
267 return sizeof(ip4_address_t);
270 return sizeof(ip6_address_t);
277 ip_version_to_size (u8 ver)
282 return sizeof(ip4_address_t);
285 return sizeof(ip6_address_t);
292 ip_version_to_max_plen (u8 ver)
306 always_inline lisp_afi_e
307 ip_version_to_iana_afi (u16 version)
322 ip_iana_afi_to_version (lisp_afi_e afi)
337 ip_address_size_to_write (ip_address_t * a)
339 return ip_address_size (a) + sizeof (u16);
343 ip_address_iana_afi(ip_address_t *a)
345 return ip_version_to_iana_afi(ip_addr_version(a));
349 ip_address_max_len (u8 version)
351 return version == IP4 ? 32 : 128;
355 ip4_address_size_to_put ()
357 // return sizeof(u16) + sizeof (ip4_address_t);
362 ip6_address_size_to_put ()
364 //return sizeof(u16) + sizeof (ip6_address_t);
369 ip4_address_put (u8 * b, ip4_address_t * a)
371 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
372 u8 *p = b + sizeof (u16);
373 clib_memcpy (p, a, sizeof(*a));
374 return ip4_address_size_to_put();
378 ip6_address_put (u8 * b, ip6_address_t * a)
380 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
381 u8 *p = b + sizeof (u16);
382 clib_memcpy (p, a, sizeof(*a));
383 return ip6_address_size_to_put();
387 ip_address_put (u8 * b, ip_address_t * a)
389 u32 len = ip_address_size (a);
390 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
391 u8 * p = b + sizeof (u16);
392 clib_memcpy (p, &ip_addr_addr (a), len);
393 return (len + sizeof (u16));
397 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
399 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
400 u8 size = ip_version_to_size (ip_addr_version(dst));
401 clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
402 return(sizeof(u16) + size);
406 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
408 lcaf_hdr_t * lh = offset;
409 lcaf->type = lh->type;
411 /* this is a bit of hack: since the LCAF Instance ID is the
412 only message that uses reserved2 field, we can set it here.
413 If any LCAF format starts using reserved2 field as well this needs
414 to be moved elsewhere */
415 lcaf_vni_len (lcaf) = lh->reserved2;
417 return sizeof (lh[0]);
421 vni_parse (u8 * p, void * a)
424 gid_address_t * g = a;
427 gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p);
428 size += sizeof (u32);
429 gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
431 /* nested LCAFs are not supported - it is expected that nested AFI type is
433 size += gid_address_parse (p + size, g);
438 no_addr_parse (u8 * p, void * a)
445 lcaf_parse (void * offset, gid_address_t *addr)
448 offset += sizeof (u16);
449 lcaf_t * lcaf = &gid_address_lcaf (addr);
451 u32 size = lcaf_hdr_parse (offset, lcaf);
452 u8 type = lcaf_type (lcaf);
454 if (!lcaf_parse_fcts[type])
456 clib_warning ("Unsupported LCAF type: %u", type);
459 size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
460 return sizeof (u16) + size;
467 gid_address_free (vni_gid (v));
468 clib_mem_free (vni_gid (v));
472 no_addr_free (void * a)
478 gid_address_free (gid_address_t *a)
480 if (gid_address_type (a) != GID_ADDR_LCAF)
483 lcaf_t * lcaf = &gid_address_lcaf (a);
484 u8 lcaf_type = lcaf_type (lcaf);
485 (*lcaf_free_fcts[lcaf_type])(lcaf);
489 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
492 if (ip_addr_version (ip1) != ip_addr_version(ip2))
494 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
505 ip_address_copy (ip_address_t * dst , ip_address_t * src)
507 clib_memcpy (dst, src, sizeof (ip_address_t));
511 ip_address_copy_addr (void * dst , ip_address_t * src)
513 clib_memcpy (dst, src, ip_address_size(src));
517 ip_address_set(ip_address_t * dst, void * src, u8 version)
519 clib_memcpy(dst, src, ip_version_to_size(version));
520 ip_addr_version(dst) = version;
524 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
535 mask = pow2_mask (preflen) << (32 - preflen);
536 mask = clib_host_to_net_u32 (mask);
537 ip4->data_u32 &= mask;
541 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
549 memset (mask_6, 0, sizeof (mask_6));
558 m = (u32 * ) &mask_6[0];
560 for (j = 0; j < i0; j++)
567 m[i0] = clib_host_to_net_u32 (pow2_mask(i1) << (32 - i1));
570 for (j = 0; j < sizeof(mask_6); j++)
572 ip6->as_u8[j] &= mask_6[j];
577 ip_prefix_normalize(ip_prefix_t * a)
579 u8 preflen = ip_prefix_len(a);
581 switch (ip_prefix_version (a))
584 ip_prefix_normalize_ip4(&ip_prefix_v4(a), preflen);
588 ip_prefix_normalize_ip6(&ip_prefix_v6(a), preflen);
597 ip_prefix_cast (gid_address_t * a)
599 return &gid_address_ippref(a);
603 ip_prefix_size_to_write (void * pref)
605 ip_prefix_t *a = (ip_prefix_t *) pref;
606 return ip_address_size_to_write (&ip_prefix_addr (a));
610 ip_prefix_write (u8 * p, void * gid)
612 gid_address_t * g = gid;
613 ip_prefix_t *a = &gid_address_ippref (g);
615 switch (ip_prefix_version (a))
618 return ip4_address_put (p, &ip_prefix_v4 (a));
621 return ip6_address_put (p, &ip_prefix_v6 (a));
628 ip_prefix_length (void *a)
630 return ip_prefix_len((ip_prefix_t *) a);
634 ip_prefix_copy (void * dst , void * src)
636 clib_memcpy (dst, src, sizeof (ip_prefix_t));
640 mac_copy (void * dst , void * src)
642 clib_memcpy (dst, src, 6);
646 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
650 ip_prefix_normalize (p1);
651 ip_prefix_normalize (p2);
653 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
656 if (ip_prefix_len(p1) < ip_prefix_len(p2))
662 if (ip_prefix_len(p1) > ip_prefix_len(p2))
670 no_addr_copy (void * dst, void * src)
676 vni_copy (void * dst, void * src)
681 clib_memcpy (vd, vs, sizeof (vd[0]));
682 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
683 gid_address_copy (vni_gid (vd), vni_gid (vs));
687 lcaf_copy (void * dst , void * src)
689 lcaf_t * lcaf_dst = dst;
690 lcaf_t * lcaf_src = src;
692 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
693 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
697 lcaf_length (void *a)
709 lcaf_cast (gid_address_t * a)
711 return &gid_address_lcaf (a);
715 mac_cast (gid_address_t * a)
717 return &gid_address_mac (a);
721 no_addr_length (void * a)
727 vni_length (void * a)
730 return (sizeof (u32) /* VNI size */
731 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
735 lcaf_write (u8 * p, void * a)
739 u8 type = lcaf_type (lcaf);
740 lcaf_hdr_t _h, *h = &_h;
742 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
743 size += sizeof (u16);
744 memset (h, 0, sizeof (h[0]));
745 LCAF_TYPE (h) = type;
746 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
747 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
749 clib_memcpy (p + size, h, sizeof (h[0]));
750 size += sizeof (h[0]);
751 len = (*lcaf_write_fcts[type])(p + size, lcaf);
760 mac_write (u8 * p, void * a)
762 *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
763 clib_memcpy(p + sizeof (u16), a, 6);
764 return mac_size_to_write (a);
768 vni_write (u8 * p, void * a)
770 lcaf_hdr_t _h, *h = &_h;
771 gid_address_t * g = a;
774 /* put lcaf header */
775 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
776 size += sizeof (u16);
777 memset (h, 0, sizeof (h[0]));
778 LCAF_TYPE (h) = LCAF_INSTANCE_ID;
779 u16 lcaf_len = sizeof (u32) /* Instance ID size */
780 + gid_address_size_to_put_no_vni (g);
781 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
782 LCAF_RES2 (h) = gid_address_vni_mask (g);
785 clib_memcpy (p + size, h, sizeof (h[0]));
786 size += sizeof (h[0]);
788 u32 * afip = (u32 *)(p + size);
789 afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
790 size += sizeof (u32);
792 /* write the actual address */
793 len = gid_address_put_no_vni (p + size, g);
802 no_addr_write (u8 * p, void * a)
804 /* do nothing; return AFI field size */
809 no_addr_size_to_write (void * a)
811 return sizeof (u16); /* AFI field length */
815 vni_size_to_write (void * a)
817 gid_address_t * g = a;
818 return (sizeof (u32) /* vni size */
819 + sizeof (u16) /* LCAF AFI field size */
820 + sizeof (lcaf_hdr_t)
821 + gid_address_size_to_put_no_vni (g));
825 lcaf_size_to_write (void * a)
827 lcaf_t * lcaf = (lcaf_t *) a;
829 u8 type = lcaf_type (lcaf);
831 size += sizeof (u16); /* AFI size */
833 len = (*lcaf_size_to_write_fcts[type])(lcaf);
841 mac_size_to_write (void * a)
843 return sizeof (u16) + 6;
847 gid_address_len (gid_address_t *a)
849 gid_address_type_t type = gid_address_type (a);
850 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
854 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
856 gid_address_type_t type = gid_address_type (gid);
857 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
861 gid_address_put (u8 * b, gid_address_t * gid)
863 if (0 != gid_address_vni (gid))
864 return vni_write (b, gid);
866 return gid_address_put_no_vni (b, gid);
870 gid_address_size_to_put_no_vni (gid_address_t * gid)
872 gid_address_type_t type = gid_address_type (gid);
873 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
877 gid_address_size_to_put (gid_address_t * gid)
879 if (0 != gid_address_vni (gid))
880 return vni_size_to_write (gid);
882 return gid_address_size_to_put_no_vni (gid);
886 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
888 return (*cast_fcts[type])(gid);
892 gid_address_copy(gid_address_t * dst, gid_address_t * src)
894 gid_address_type_t type = gid_address_type(src);
895 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
896 gid_address_type(dst) = type;
897 gid_address_vni(dst) = gid_address_vni(src);
898 gid_address_vni_mask(dst) = gid_address_vni_mask(src);
902 mac_parse (u8 * offset, gid_address_t * a)
905 offset += sizeof (u16);
907 clib_memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
908 return (sizeof (u16) + sizeof (gid_address_mac (a)));
912 gid_address_parse (u8 * offset, gid_address_t *a)
920 /* NOTE: since gid_adress_parse may be called by vni_parse, we can't 0
921 * the gid address here */
922 afi = clib_net_to_host_u16 (*((u16 *) offset));
926 case LISP_AFI_NO_ADDR:
928 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
931 len = ip_address_parse (offset, afi, &gid_address_ip(a));
932 gid_address_type(a) = GID_ADDR_IP_PREFIX;
933 /* this should be modified outside if needed*/
934 gid_address_ippref_len(a) = 32;
937 len = ip_address_parse (offset, afi, &gid_address_ip(a));
938 gid_address_type(a) = GID_ADDR_IP_PREFIX;
939 /* this should be modified outside if needed*/
940 gid_address_ippref_len(a) = 128;
943 gid_address_type(a) = GID_ADDR_LCAF;
944 len = lcaf_parse (offset, a);
947 len = mac_parse (offset, a);
948 gid_address_type(a) = GID_ADDR_MAC;
951 clib_warning("LISP AFI %d not supported!", afi);
958 gid_address_ip_set(gid_address_t * dst, void * src, u8 version)
960 ip_address_set (&gid_address_ip(dst), src, version);
964 no_addr_cmp (void * a1, void * a2)
970 vni_cmp (void * a1, void * a2)
975 if (vni_mask_len (v1) != vni_mask_len (v2))
977 if (vni_vni (v1) != vni_vni (v2))
979 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
982 /* Compare two gid_address_t.
984 * -1: If they are from different afi
985 * 0: Both address are the same
986 * 1: Addr1 is bigger than addr2
987 * 2: Addr2 is bigger than addr1
990 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
992 lcaf_t * lcaf1, * lcaf2;
996 if (gid_address_type(a1) != gid_address_type(a2))
998 if (gid_address_vni(a1) != gid_address_vni(a2))
1000 if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
1003 switch (gid_address_type(a1))
1005 case GID_ADDR_NO_ADDRESS:
1011 case GID_ADDR_IP_PREFIX:
1012 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
1015 lcaf1 = &gid_address_lcaf (a1);
1016 lcaf2 = &gid_address_lcaf (a2);
1017 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
1018 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
1021 cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
1022 sizeof (gid_address_mac (a1)));
1033 locator_parse (void * b, locator_t * loc)
1036 u8 status = 1; /* locator up */
1040 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
1043 len = gid_address_parse (LOC_ADDR(h), &loc->address);
1047 loc->state = status;
1049 loc->priority = LOC_PRIORITY(h);
1050 loc->weight = LOC_WEIGHT(h);
1051 loc->mpriority = LOC_MPRIORITY(h);
1052 loc->mweight = LOC_MWEIGHT(h);
1054 return sizeof(locator_hdr_t) + len;
1058 locator_copy (locator_t * dst, locator_t * src)
1060 /* TODO if gid become more complex, this will need to be changed! */
1061 clib_memcpy (dst, src, sizeof(*dst));
1063 gid_address_copy (&dst->address, &src->address);
1067 locator_cmp (locator_t * l1, locator_t * l2)
1070 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
1073 if (l1->priority != l2->priority)
1075 if (l1->weight != l2->weight)
1077 if (l1->mpriority != l2->mpriority)
1079 if (l1->mweight != l2->mweight)
1085 locator_free (locator_t * l)
1088 gid_address_free (&l->address);