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));
164 clib_warning("Can't format gid type %d", type);
170 unformat_gid_address (unformat_input_t * input, va_list * args)
172 gid_address_t * a = va_arg(*args, gid_address_t *);
173 if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a)))
174 gid_address_type(a) = GID_ADDR_IP_PREFIX;
181 ip_address_size (ip_address_t * a)
183 switch (ip_addr_version (a))
186 return sizeof(ip4_address_t);
189 return sizeof(ip6_address_t);
196 ip_version_to_size (u8 ver)
201 return sizeof(ip4_address_t);
204 return sizeof(ip6_address_t);
211 ip_version_to_max_plen (u8 ver)
225 always_inline lisp_afi_e
226 ip_version_to_iana_afi (u16 version)
241 ip_iana_afi_to_version (lisp_afi_e afi)
256 ip_address_size_to_write (ip_address_t * a)
258 return ip_address_size (a) + sizeof (u16);
262 ip_address_iana_afi(ip_address_t *a)
264 return ip_version_to_iana_afi(ip_addr_version(a));
268 ip_address_max_len (u8 version)
270 return version == IP4 ? 32 : 128;
274 ip4_address_size_to_put ()
276 // return sizeof(u16) + sizeof (ip4_address_t);
281 ip6_address_size_to_put ()
283 //return sizeof(u16) + sizeof (ip6_address_t);
288 ip4_address_put (u8 * b, ip4_address_t * a)
290 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
291 u8 *p = b + sizeof (u16);
292 clib_memcpy (p, a, sizeof(*a));
293 return ip4_address_size_to_put();
297 ip6_address_put (u8 * b, ip6_address_t * a)
299 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
300 u8 *p = b + sizeof (u16);
301 clib_memcpy (p, a, sizeof(*a));
302 return ip6_address_size_to_put();
306 ip_address_put (u8 * b, ip_address_t * a)
308 u32 len = ip_address_size (a);
309 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
310 u8 * p = b + sizeof (u16);
311 clib_memcpy (p, &ip_addr_addr (a), len);
312 return (len + sizeof (u16));
316 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
318 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
319 u8 size = ip_version_to_size (ip_addr_version(dst));
320 clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
321 return(sizeof(u16) + size);
325 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
327 lcaf_hdr_t * lh = offset;
328 lcaf->type = lh->type;
330 /* this is a bit of hack: since the LCAF Instance ID is the
331 only message that uses reserved2 field, we can set it here.
332 If any LCAF format starts using reserved2 field as well this needs
333 to be moved elsewhere */
334 lcaf_vni_len (lcaf) = lh->reserved2;
336 return sizeof (lh[0]);
340 vni_parse (u8 * p, void * a)
343 gid_address_t * g = a;
346 gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p);
347 size += sizeof (u32);
348 gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
350 /* nested LCAFs are not supported - it is expected that nested AFI type is
352 size += gid_address_parse (p + size, g);
357 no_addr_parse (u8 * p, void * a)
364 lcaf_parse (void * offset, gid_address_t *addr)
367 offset += sizeof (u16);
368 lcaf_t * lcaf = &gid_address_lcaf (addr);
370 u32 size = lcaf_hdr_parse (offset, lcaf);
371 u8 type = lcaf_type (lcaf);
373 if (!lcaf_parse_fcts[type])
375 clib_warning ("Unsupported LCAF type: %u", type);
378 size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
379 return sizeof (u16) + size;
386 gid_address_free (vni_gid (v));
387 clib_mem_free (vni_gid (v));
391 no_addr_free (void * a)
397 gid_address_free (gid_address_t *a)
399 if (gid_address_type (a) != GID_ADDR_LCAF)
402 lcaf_t * lcaf = &gid_address_lcaf (a);
403 u8 lcaf_type = lcaf_type (lcaf);
404 (*lcaf_free_fcts[lcaf_type])(lcaf);
408 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
411 if (ip_addr_version (ip1) != ip_addr_version(ip2))
413 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
424 ip_address_copy (ip_address_t * dst , ip_address_t * src)
426 clib_memcpy (dst, src, sizeof (ip_address_t));
430 ip_address_copy_addr (void * dst , ip_address_t * src)
432 clib_memcpy (dst, src, ip_address_size(src));
436 ip_address_set(ip_address_t * dst, void * src, u8 version)
438 clib_memcpy(dst, src, ip_version_to_size(version));
439 ip_addr_version(dst) = version;
443 ip_prefix_cast (gid_address_t * a)
445 return &gid_address_ippref(a);
449 ip_prefix_size_to_write (void * pref)
451 ip_prefix_t *a = (ip_prefix_t *) pref;
452 return ip_address_size_to_write (&ip_prefix_addr (a));
456 ip_prefix_write (u8 * p, void * gid)
458 gid_address_t * g = gid;
459 ip_prefix_t *a = &gid_address_ippref (g);
461 switch (ip_prefix_version (a))
464 return ip4_address_put (p, &ip_prefix_v4 (a));
467 return ip6_address_put (p, &ip_prefix_v6 (a));
474 ip_prefix_length (void *a)
476 return ip_prefix_len((ip_prefix_t *) a);
480 ip_prefix_copy (void * dst , void * src)
482 clib_memcpy (dst, src, sizeof (ip_prefix_t));
486 mac_copy (void * dst , void * src)
488 clib_memcpy (dst, src, 6);
492 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
495 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
498 if (ip_prefix_len(p1) < ip_prefix_len(p2))
504 if (ip_prefix_len(p1) > ip_prefix_len(p2))
512 no_addr_copy (void * dst, void * src)
518 vni_copy (void * dst, void * src)
523 clib_memcpy (vd, vs, sizeof (vd[0]));
524 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
525 gid_address_copy (vni_gid (vd), vni_gid (vs));
529 lcaf_copy (void * dst , void * src)
531 lcaf_t * lcaf_dst = dst;
532 lcaf_t * lcaf_src = src;
534 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
535 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
539 lcaf_length (void *a)
551 lcaf_cast (gid_address_t * a)
553 return &gid_address_lcaf (a);
557 mac_cast (gid_address_t * a)
559 return &gid_address_mac (a);
563 no_addr_length (void * a)
569 vni_length (void * a)
572 return (sizeof (u32) /* VNI size */
573 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
577 lcaf_write (u8 * p, void * a)
581 u8 type = lcaf_type (lcaf);
582 lcaf_hdr_t _h, *h = &_h;
584 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
585 size += sizeof (u16);
586 memset (h, 0, sizeof (h[0]));
587 LCAF_TYPE (h) = type;
588 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
589 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
591 clib_memcpy (p + size, h, sizeof (h[0]));
592 size += sizeof (h[0]);
593 len = (*lcaf_write_fcts[type])(p + size, lcaf);
602 mac_write (u8 * p, void * a)
604 *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
605 clib_memcpy(p + sizeof (u16), a, 6);
606 return mac_size_to_write (a);
610 vni_write (u8 * p, void * a)
612 lcaf_hdr_t _h, *h = &_h;
613 gid_address_t * g = a;
616 /* put lcaf header */
617 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
618 size += sizeof (u16);
619 memset (h, 0, sizeof (h[0]));
620 LCAF_TYPE (h) = LCAF_INSTANCE_ID;
621 u16 lcaf_len = sizeof (u32) /* Instance ID size */
622 + gid_address_size_to_put_no_vni (g);
623 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
624 LCAF_RES2 (h) = gid_address_vni_mask (g);
627 clib_memcpy (p + size, h, sizeof (h[0]));
628 size += sizeof (h[0]);
630 u32 * afip = (u32 *)(p + size);
631 afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
632 size += sizeof (u32);
634 /* write the actual address */
635 len = gid_address_put_no_vni (p + size, g);
644 no_addr_write (u8 * p, void * a)
646 /* do nothing; return AFI field size */
651 no_addr_size_to_write (void * a)
653 return sizeof (u16); /* AFI field length */
657 vni_size_to_write (void * a)
659 gid_address_t * g = a;
660 return (sizeof (u32) /* vni size */
661 + sizeof (u16) /* LCAF AFI field size */
662 + sizeof (lcaf_hdr_t)
663 + gid_address_size_to_put_no_vni (g));
667 lcaf_size_to_write (void * a)
669 lcaf_t * lcaf = (lcaf_t *) a;
671 u8 type = lcaf_type (lcaf);
673 size += sizeof (u16); /* AFI size */
675 len = (*lcaf_size_to_write_fcts[type])(lcaf);
683 mac_size_to_write (void * a)
685 return sizeof (u16) + 6;
689 gid_address_len (gid_address_t *a)
691 gid_address_type_t type = gid_address_type (a);
692 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
696 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
698 gid_address_type_t type = gid_address_type (gid);
699 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
703 gid_address_put (u8 * b, gid_address_t * gid)
705 if (0 != gid_address_vni (gid))
706 return vni_write (b, gid);
708 return gid_address_put_no_vni (b, gid);
712 gid_address_size_to_put_no_vni (gid_address_t * gid)
714 gid_address_type_t type = gid_address_type (gid);
715 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
719 gid_address_size_to_put (gid_address_t * gid)
721 if (0 != gid_address_vni (gid))
722 return vni_size_to_write (gid);
724 return gid_address_size_to_put_no_vni (gid);
728 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
730 return (*cast_fcts[type])(gid);
734 gid_address_copy(gid_address_t * dst, gid_address_t * src)
736 gid_address_type_t type = gid_address_type(src);
737 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
738 gid_address_type(dst) = type;
739 gid_address_vni(dst) = gid_address_vni(src);
740 gid_address_vni_mask(dst) = gid_address_vni_mask(src);
744 mac_parse (u8 * offset, gid_address_t * a)
747 offset += sizeof (u16);
749 memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
750 return (sizeof (u16) + sizeof (gid_address_mac (a)));
754 gid_address_parse (u8 * offset, gid_address_t *a)
762 afi = clib_net_to_host_u16 (*((u16 *) offset));
766 case LISP_AFI_NO_ADDR:
768 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
771 len = ip_address_parse (offset, afi, &gid_address_ip(a));
772 gid_address_type(a) = GID_ADDR_IP_PREFIX;
773 /* this should be modified outside if needed*/
774 gid_address_ippref_len(a) = 32;
777 len = ip_address_parse (offset, afi, &gid_address_ip(a));
778 gid_address_type(a) = GID_ADDR_IP_PREFIX;
779 /* this should be modified outside if needed*/
780 gid_address_ippref_len(a) = 128;
783 gid_address_type(a) = GID_ADDR_LCAF;
784 len = lcaf_parse (offset, a);
787 len = mac_parse (offset, a);
788 gid_address_type(a) = GID_ADDR_MAC;
791 clib_warning("LISP AFI %d not supported!", afi);
798 no_addr_cmp (void * a1, void * a2)
804 vni_cmp (void * a1, void * a2)
809 if (vni_mask_len (v1) != vni_mask_len (v2))
811 if (vni_vni (v1) != vni_vni (v2))
813 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
816 /* Compare two gid_address_t.
818 * -1: If they are from different afi
819 * 0: Both address are the same
820 * 1: Addr1 is bigger than addr2
821 * 2: Addr2 is bigger than addr1
824 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
826 lcaf_t * lcaf1, * lcaf2;
830 if (gid_address_type(a1) != gid_address_type(a2))
832 if (gid_address_vni(a1) != gid_address_vni(a2))
834 if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
837 switch (gid_address_type(a1))
839 case GID_ADDR_NO_ADDRESS:
845 case GID_ADDR_IP_PREFIX:
846 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
849 lcaf1 = &gid_address_lcaf (a1);
850 lcaf2 = &gid_address_lcaf (a2);
851 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
852 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
855 cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
856 sizeof (gid_address_mac (a1)));
867 locator_parse (void * b, locator_t * loc)
870 u8 status = 1; /* locator up */
874 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
877 len = gid_address_parse (LOC_ADDR(h), &loc->address);
883 loc->priority = LOC_PRIORITY(h);
884 loc->weight = LOC_WEIGHT(h);
885 loc->mpriority = LOC_MPRIORITY(h);
886 loc->mweight = LOC_MWEIGHT(h);
888 return sizeof(locator_hdr_t) + len;
892 locator_copy (locator_t * dst, locator_t * src)
894 /* TODO if gid become more complex, this will need to be changed! */
895 clib_memcpy (dst, src, sizeof(*dst));
897 gid_address_copy (&dst->address, &src->address);
901 locator_cmp (locator_t * l1, locator_t * l2)
904 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
907 if (l1->priority != l2->priority)
909 if (l1->weight != l2->weight)
911 if (l1->mpriority != l2->mpriority)
913 if (l1->mweight != l2->mweight)
919 locator_free (locator_t * l)
922 gid_address_free (&l->address);