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 typedef u16 (*size_to_write_fct)(void *);
19 typedef void * (*cast_fct)(gid_address_t *);
20 typedef u16 (*serdes_fct)(u8 *, void *);
21 typedef u8 (*addr_len_fct)(void *);
22 typedef void (*copy_fct)(void *, void *);
23 typedef void (*free_fct)(void *);
24 typedef int (*cmp_fct)(void *, void *);
26 u16 vni_write (u8 * p, void * a);
27 u16 vni_parse (u8 * p, void * a);
28 u16 vni_size_to_write (void * a);
29 void vni_free (void * a);
30 void vni_copy (void * dst, void * src);
31 u16 vni_length (void * a);
32 int vni_cmp (void *, void *);
34 u16 no_addr_size_to_write (void *);
35 u16 no_addr_write (u8 * p, void * a);
36 u16 no_addr_parse (u8 * p, void * a);
37 void no_addr_free (void * a);
38 void no_addr_copy (void *, void *);
39 u16 no_addr_length (void * a);
40 int no_addr_cmp (void * a1, void * a2);
42 size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
43 { ip_prefix_size_to_write, lcaf_size_to_write, mac_size_to_write };
44 serdes_fct write_fcts[GID_ADDR_TYPES] =
45 { ip_prefix_write, lcaf_write, mac_write };
46 cast_fct cast_fcts[GID_ADDR_TYPES] =
47 { ip_prefix_cast, lcaf_cast, mac_cast };
48 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
49 { ip_prefix_length, lcaf_length, mac_length };
50 copy_fct copy_fcts[GID_ADDR_TYPES] =
51 { ip_prefix_copy, lcaf_copy, mac_copy };
53 cmp_fct lcaf_cmp_fcts[LCAF_TYPES] =
60 size_to_write_fct lcaf_body_length_fcts[LCAF_TYPES] =
67 copy_fct lcaf_copy_fcts[LCAF_TYPES] =
74 free_fct lcaf_free_fcts[LCAF_TYPES] =
81 size_to_write_fct lcaf_size_to_write_fcts[LCAF_TYPES] =
83 no_addr_size_to_write,
88 serdes_fct lcaf_write_fcts[LCAF_TYPES] =
95 serdes_fct lcaf_parse_fcts[LCAF_TYPES] =
103 format_ip_address (u8 * s, va_list * args)
105 ip_address_t * a = va_arg (*args, ip_address_t *);
106 u8 ver = ip_addr_version(a);
109 return format (s, "%U", format_ip4_address, &ip_addr_v4(a));
113 return format (s, "%U", format_ip6_address, &ip_addr_v6(a));
117 clib_warning ("Can't format IP version %d!", ver);
123 unformat_ip_address (unformat_input_t * input, va_list * args)
125 ip_address_t * a = va_arg(*args, ip_address_t *);
126 if (unformat(input, "%U", unformat_ip4_address, &ip_addr_v4(a)))
127 ip_addr_version(a) = IP4;
128 else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6(a)))
129 ip_addr_version(a) = IP6;
136 format_ip_prefix (u8 * s, va_list * args)
138 ip_prefix_t * a = va_arg (*args, ip_prefix_t *);
139 return format (s, "%U/%d", format_ip_address, &ip_prefix_addr(a), ip_prefix_len(a));
143 unformat_ip_prefix (unformat_input_t * input, va_list * args)
145 ip_prefix_t * a = va_arg(*args, ip_prefix_t *);
146 return unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a),
151 format_gid_address (u8 * s, va_list * args)
153 gid_address_t * a = va_arg(*args, gid_address_t *);
154 u8 type = gid_address_type(a);
157 case GID_ADDR_IP_PREFIX:
158 return format (s, "%U", format_ip_prefix, &gid_address_ippref(a));
160 clib_warning("Can't format gid type %d", type);
166 unformat_gid_address (unformat_input_t * input, va_list * args)
168 gid_address_t * a = va_arg(*args, gid_address_t *);
169 if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a)))
170 gid_address_type(a) = GID_ADDR_IP_PREFIX;
177 ip_address_size (ip_address_t * a)
179 switch (ip_addr_version (a))
182 return sizeof(ip4_address_t);
185 return sizeof(ip6_address_t);
192 ip_version_to_size (u8 ver)
197 return sizeof(ip4_address_t);
200 return sizeof(ip6_address_t);
207 ip_version_to_max_plen (u8 ver)
221 always_inline lisp_afi_e
222 ip_version_to_iana_afi (u16 version)
237 ip_iana_afi_to_version (lisp_afi_e afi)
252 ip_address_size_to_write (ip_address_t * a)
254 return ip_address_size (a) + sizeof (u16);
258 ip_address_iana_afi(ip_address_t *a)
260 return ip_version_to_iana_afi(ip_addr_version(a));
264 ip_address_max_len (u8 version)
266 return version == IP4 ? 32 : 128;
270 ip4_address_size_to_put ()
272 // return sizeof(u16) + sizeof (ip4_address_t);
277 ip6_address_size_to_put ()
279 //return sizeof(u16) + sizeof (ip6_address_t);
284 ip4_address_put (u8 * b, ip4_address_t * a)
286 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
287 u8 *p = b + sizeof (u16);
288 clib_memcpy (p, a, sizeof(*a));
289 return ip4_address_size_to_put();
293 ip6_address_put (u8 * b, ip6_address_t * a)
295 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
296 u8 *p = b + sizeof (u16);
297 clib_memcpy (p, a, sizeof(*a));
298 return ip6_address_size_to_put();
302 ip_address_put (u8 * b, ip_address_t * a)
304 u32 len = ip_address_size (a);
305 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
306 u8 * p = b + sizeof (u16);
307 clib_memcpy (p, &ip_addr_addr (a), len);
308 return (len + sizeof (u16));
312 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
314 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
315 u8 size = ip_version_to_size (ip_addr_version(dst));
316 clib_memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
317 return(sizeof(u16) + size);
321 lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
323 lcaf_hdr_t * lh = offset;
324 lcaf->type = lh->type;
326 /* this is a bit of hack: since the LCAF Instance ID is the
327 only message that uses reserved2 field, we can set it here.
328 If any LCAF format starts using reserved2 field as well this needs
329 to be moved elsewhere */
330 lcaf_vni_len (lcaf) = lh->reserved2;
332 return sizeof (lh[0]);
336 vni_parse (u8 * p, void * a)
340 vni_vni (v) = clib_net_to_host_u32 ( *(u32 *) p);
341 size += sizeof (u32);
343 vni_gid (v) = clib_mem_alloc (sizeof (gid_address_t));
344 gid_address_t * gid = vni_gid (v);
345 memset (gid, 0, sizeof (gid[0]));
347 size += gid_address_parse (p + size, gid);
352 no_addr_parse (u8 * p, void * a)
359 lcaf_parse (void * offset, gid_address_t *addr)
362 offset += sizeof (u16);
363 lcaf_t * lcaf = &gid_address_lcaf (addr);
365 u32 size = lcaf_hdr_parse (offset, lcaf);
366 u8 type = lcaf_type (lcaf);
368 if (!lcaf_parse_fcts[type])
370 clib_warning ("Unsupported LCAF type: %u", type);
373 size += (*lcaf_parse_fcts[type])(offset + size, lcaf);
374 return sizeof (u16) + size;
381 gid_address_free (vni_gid (v));
382 clib_mem_free (vni_gid (v));
386 no_addr_free (void * a)
392 gid_address_free (gid_address_t *a)
394 if (gid_address_type (a) != GID_ADDR_LCAF)
397 lcaf_t * lcaf = &gid_address_lcaf (a);
398 u8 lcaf_type = lcaf_type (lcaf);
399 (*lcaf_free_fcts[lcaf_type])(lcaf);
403 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
406 if (ip_addr_version (ip1) != ip_addr_version(ip2))
408 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
419 ip_address_copy (ip_address_t * dst , ip_address_t * src)
421 clib_memcpy (dst, src, sizeof (ip_address_t));
425 ip_address_copy_addr (void * dst , ip_address_t * src)
427 clib_memcpy (dst, src, ip_address_size(src));
431 ip_address_set(ip_address_t * dst, void * src, u8 version)
433 clib_memcpy(dst, src, ip_version_to_size(version));
434 ip_addr_version(dst) = version;
438 ip_prefix_cast (gid_address_t * a)
440 return &gid_address_ippref(a);
444 ip_prefix_size_to_write (void * pref)
446 ip_prefix_t *a = (ip_prefix_t *) pref;
447 return ip_address_size_to_write (&ip_prefix_addr (a));
451 ip_prefix_write (u8 * p, void * pref)
453 ip_prefix_t *a = (ip_prefix_t *) pref;
454 switch (ip_prefix_version (a))
457 return ip4_address_put (p, &ip_prefix_v4 (a));
460 return ip6_address_put (p, &ip_prefix_v6 (a));
467 ip_prefix_length (void *a)
469 return ip_prefix_len((ip_prefix_t *) a);
473 ip_prefix_copy (void * dst , void * src)
475 clib_memcpy (dst, src, sizeof (ip_prefix_t));
479 mac_copy (void * dst , void * src)
481 clib_memcpy (dst, src, 6);
485 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
488 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
491 if (ip_prefix_len(p1) < ip_prefix_len(p2))
497 if (ip_prefix_len(p1) > ip_prefix_len(p2))
505 no_addr_copy (void * dst, void * src)
511 vni_copy (void * dst, void * src)
516 clib_memcpy (vd, vs, sizeof (vd[0]));
517 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
518 gid_address_copy (vni_gid (vd), vni_gid (vs));
522 lcaf_copy (void * dst , void * src)
524 lcaf_t * lcaf_dst = dst;
525 lcaf_t * lcaf_src = src;
527 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
528 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
532 lcaf_length (void *a)
544 lcaf_cast (gid_address_t * a)
546 return &gid_address_lcaf (a);
550 mac_cast (gid_address_t * a)
552 return &gid_address_mac (a);
556 no_addr_length (void * a)
562 vni_length (void * a)
565 return (sizeof (u32) /* VNI size */
566 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
570 lcaf_write (u8 * p, void * a)
574 u8 type = lcaf_type (lcaf);
575 lcaf_hdr_t _h, *h = &_h;
577 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
578 size += sizeof (u16);
579 memset (h, 0, sizeof (h[0]));
580 LCAF_TYPE (h) = type;
581 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
582 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
584 if (LCAF_INSTANCE_ID == type)
585 LCAF_RES2 (h) = lcaf_vni_len(lcaf);
587 clib_memcpy (p + size, h, sizeof (h[0]));
588 size += sizeof (h[0]);
589 len = (*lcaf_write_fcts[type])(p + size, lcaf);
598 mac_write (u8 * p, void * a)
600 *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
601 clib_memcpy(p + sizeof (u16), a, 6);
602 return mac_size_to_write (a);
606 vni_write (u8 * p, void * a)
611 *(u32 *)p = clib_host_to_net_u32 (vni_vni (v));
612 size += sizeof (u32);
613 len = gid_address_put (p + size, vni_gid (v));
622 no_addr_write (u8 * p, void * a)
624 /* do nothing; return AFI field size */
629 no_addr_size_to_write (void * a)
631 return sizeof (u16); /* AFI field length */
635 vni_size_to_write (void * a)
638 u16 size = sizeof (vni_vni (v));
640 gid_address_t * gid = vni_gid (v);
641 return (size + sizeof (lcaf_hdr_t)
642 + gid_address_size_to_put (gid));
646 lcaf_size_to_write (void * a)
648 lcaf_t * lcaf = (lcaf_t *) a;
650 u8 type = lcaf_type (lcaf);
652 size += sizeof (u16); /* AFI size */
654 len = (*lcaf_size_to_write_fcts[type])(lcaf);
662 mac_size_to_write (void * a)
664 return sizeof (u16) + 6;
668 gid_address_len (gid_address_t *a)
670 gid_address_type_t type = gid_address_type (a);
671 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
675 gid_address_put (u8 * b, gid_address_t * gid)
677 gid_address_type_t type = gid_address_type (gid);
678 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
682 gid_address_size_to_put (gid_address_t * gid)
684 gid_address_type_t type = gid_address_type (gid);
685 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
689 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
691 return (*cast_fcts[type])(gid);
695 gid_address_copy(gid_address_t * dst, gid_address_t * src)
697 gid_address_type_t type = gid_address_type(src);
698 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
699 gid_address_type(dst) = type;
703 mac_parse (u8 * offset, gid_address_t * a)
706 offset += sizeof (u16);
708 memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
709 return (sizeof (u16) + sizeof (gid_address_mac (a)));
713 gid_address_parse (u8 * offset, gid_address_t *a)
721 afi = clib_net_to_host_u16 (*((u16 *) offset));
725 case LISP_AFI_NO_ADDR:
727 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
730 len = ip_address_parse (offset, afi, &gid_address_ip(a));
731 gid_address_type(a) = GID_ADDR_IP_PREFIX;
732 /* this should be modified outside if needed*/
733 gid_address_ippref_len(a) = 32;
736 len = ip_address_parse (offset, afi, &gid_address_ip(a));
737 gid_address_type(a) = GID_ADDR_IP_PREFIX;
738 /* this should be modified outside if needed*/
739 gid_address_ippref_len(a) = 128;
742 len = lcaf_parse (offset, a);
743 gid_address_type(a) = GID_ADDR_LCAF;
746 len = mac_parse (offset, a);
747 gid_address_type(a) = GID_ADDR_MAC;
750 clib_warning("LISP AFI %d not supported!", afi);
757 no_addr_cmp (void * a1, void * a2)
763 vni_cmp (void * a1, void * a2)
768 if (vni_mask_len (v1) != vni_mask_len (v2))
770 if (vni_vni (v1) != vni_vni (v2))
772 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
775 /* Compare two gid_address_t.
777 * -1: If they are from different afi
778 * 0: Both address are the same
779 * 1: Addr1 is bigger than addr2
780 * 2: Addr2 is bigger than addr1
783 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
785 lcaf_t * lcaf1, * lcaf2;
789 if (gid_address_type(a1) != gid_address_type(a2))
792 switch (gid_address_type(a1))
794 case GID_ADDR_NO_ADDRESS:
800 case GID_ADDR_IP_PREFIX:
801 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
804 lcaf1 = &gid_address_lcaf (a1);
805 lcaf2 = &gid_address_lcaf (a2);
806 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
807 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
810 cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
811 sizeof (gid_address_mac (a1)));
822 locator_parse (void * b, locator_t * loc)
825 u8 status = 1; /* locator up */
829 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
832 len = gid_address_parse (LOC_ADDR(h), &loc->address);
838 loc->priority = LOC_PRIORITY(h);
839 loc->weight = LOC_WEIGHT(h);
840 loc->mpriority = LOC_MPRIORITY(h);
841 loc->mweight = LOC_MWEIGHT(h);
843 return sizeof(locator_hdr_t) + len;
847 locator_copy (locator_t * dst, locator_t * src)
849 /* TODO if gid become more complex, this will need to be changed! */
850 clib_memcpy (dst, src, sizeof(*dst));
852 gid_address_copy (&dst->address, &src->address);
856 locator_cmp (locator_t * l1, locator_t * l2)
859 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
862 if (l1->priority != l2->priority)
864 if (l1->weight != l2->weight)
866 if (l1->mpriority != l2->mpriority)
868 if (l1->mweight != l2->mweight)
874 locator_free (locator_t * l)
877 gid_address_free (&l->address);