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 };
44 serdes_fct write_fcts[GID_ADDR_TYPES] =
45 { ip_prefix_write, lcaf_write };
46 cast_fct cast_fcts[GID_ADDR_TYPES] =
47 { ip_prefix_cast, lcaf_cast };
48 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
49 { ip_prefix_length, lcaf_prefix_length };
50 copy_fct copy_fcts[GID_ADDR_TYPES] =
51 { ip_prefix_copy, lcaf_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 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
482 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
485 if (ip_prefix_len(p1) < ip_prefix_len(p2))
491 if (ip_prefix_len(p1) > ip_prefix_len(p2))
499 no_addr_copy (void * dst, void * src)
505 vni_copy (void * dst, void * src)
510 clib_memcpy (vd, vs, sizeof (vd[0]));
511 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
512 gid_address_copy (vni_gid (vd), vni_gid (vs));
516 lcaf_copy (void * dst , void * src)
518 lcaf_t * lcaf_dst = dst;
519 lcaf_t * lcaf_src = src;
521 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
522 (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src);
526 lcaf_prefix_length (void *a)
532 lcaf_cast (gid_address_t * a)
534 return &gid_address_lcaf (a);
538 no_addr_length (void * a)
544 vni_length (void * a)
547 return (sizeof (u32) /* VNI size */
548 + gid_address_size_to_put (vni_gid (v)) /* vni body size*/);
552 lcaf_write (u8 * p, void * a)
556 u8 type = lcaf_type (lcaf);
557 lcaf_hdr_t _h, *h = &_h;
559 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
560 size += sizeof (u16);
561 memset (h, 0, sizeof (h[0]));
562 LCAF_TYPE (h) = type;
563 u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
564 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
566 if (LCAF_INSTANCE_ID == type)
567 LCAF_RES2 (h) = lcaf_vni_len(lcaf);
569 clib_memcpy (p + size, h, sizeof (h[0]));
570 size += sizeof (h[0]);
571 len = (*lcaf_write_fcts[type])(p + size, lcaf);
580 vni_write (u8 * p, void * a)
585 *(u32 *)p = clib_host_to_net_u32 (vni_vni (v));
586 size += sizeof (u32);
587 len = gid_address_put (p + size, vni_gid (v));
596 no_addr_write (u8 * p, void * a)
598 /* do nothing; return AFI field size */
603 no_addr_size_to_write (void * a)
605 return sizeof (u16); /* AFI field length */
609 vni_size_to_write (void * a)
612 u16 size = sizeof (vni_vni (v));
614 gid_address_t * gid = vni_gid (v);
615 return (size + sizeof (lcaf_hdr_t)
616 + gid_address_size_to_put (gid));
620 lcaf_size_to_write (void * a)
622 lcaf_t * lcaf = (lcaf_t *) a;
624 u8 type = lcaf_type (lcaf);
626 size += sizeof (u16); /* AFI size */
628 len = (*lcaf_size_to_write_fcts[type])(lcaf);
636 gid_address_len (gid_address_t *a)
638 gid_address_type_t type = gid_address_type (a);
639 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
643 gid_address_put (u8 * b, gid_address_t * gid)
645 gid_address_type_t type = gid_address_type (gid);
646 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
650 gid_address_size_to_put (gid_address_t * gid)
652 gid_address_type_t type = gid_address_type (gid);
653 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
657 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
659 return (*cast_fcts[type])(gid);
663 gid_address_copy(gid_address_t * dst, gid_address_t * src)
665 gid_address_type_t type = gid_address_type(src);
666 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
667 gid_address_type(dst) = type;
671 gid_address_parse (u8 * offset, gid_address_t *a)
679 afi = clib_net_to_host_u16 (*((u16 *) offset));
683 case LISP_AFI_NO_ADDR:
685 gid_address_type(a) = GID_ADDR_NO_ADDRESS;
688 len = ip_address_parse (offset, afi, &gid_address_ip(a));
689 gid_address_type(a) = GID_ADDR_IP_PREFIX;
690 /* this should be modified outside if needed*/
691 gid_address_ippref_len(a) = 32;
694 len = ip_address_parse (offset, afi, &gid_address_ip(a));
695 gid_address_type(a) = GID_ADDR_IP_PREFIX;
696 /* this should be modified outside if needed*/
697 gid_address_ippref_len(a) = 128;
700 len = lcaf_parse (offset, a);
701 gid_address_type(a) = GID_ADDR_LCAF;
704 clib_warning("LISP AFI %d not supported!", afi);
711 no_addr_cmp (void * a1, void * a2)
717 vni_cmp (void * a1, void * a2)
722 if (vni_mask_len (v1) != vni_mask_len (v2))
724 if (vni_vni (v1) != vni_vni (v2))
726 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
729 /* Compare two gid_address_t.
731 * -1: If they are from different afi
732 * 0: Both address are the same
733 * 1: Addr1 is bigger than addr2
734 * 2: Addr2 is bigger than addr1
737 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
739 lcaf_t * lcaf1, * lcaf2;
743 if (gid_address_type(a1) != gid_address_type(a2))
746 switch (gid_address_type(a1))
748 case GID_ADDR_NO_ADDRESS:
754 case GID_ADDR_IP_PREFIX:
755 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
758 lcaf1 = &gid_address_lcaf (a1);
759 lcaf2 = &gid_address_lcaf (a2);
760 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
761 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
772 locator_parse (void * b, locator_t * loc)
775 u8 status = 1; /* locator up */
779 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
782 len = gid_address_parse (LOC_ADDR(h), &loc->address);
788 loc->priority = LOC_PRIORITY(h);
789 loc->weight = LOC_WEIGHT(h);
790 loc->mpriority = LOC_MPRIORITY(h);
791 loc->mweight = LOC_MWEIGHT(h);
793 return sizeof(locator_hdr_t) + len;
797 locator_copy (locator_t * dst, locator_t * src)
799 /* TODO if gid become more complex, this will need to be changed! */
800 clib_memcpy (dst, src, sizeof(*dst));
802 gid_address_copy (&dst->address, &src->address);
806 locator_cmp (locator_t * l1, locator_t * l2)
809 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
812 if (l1->priority != l2->priority)
814 if (l1->weight != l2->weight)
816 if (l1->mpriority != l2->mpriority)
818 if (l1->mweight != l2->mweight)
824 locator_free (locator_t * l)
827 gid_address_free (&l->address);