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);
20 static u16 fid_addr_size_to_write (fid_address_t * a);
22 u32 mac_parse (u8 * offset, u8 * a);
24 typedef u16 (*size_to_write_fct) (void *);
25 typedef void *(*cast_fct) (gid_address_t *);
26 typedef u16 (*serdes_fct) (u8 *, void *);
27 typedef u8 (*addr_len_fct) (void *);
28 typedef void (*copy_fct) (void *, void *);
29 typedef void (*free_fct) (void *);
30 typedef int (*cmp_fct) (void *, void *);
32 size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
33 { ip_prefix_size_to_write, lcaf_size_to_write, mac_size_to_write,
34 sd_size_to_write, nsh_size_to_write, 0 /* arp */ , no_addr_size_to_write
37 serdes_fct write_fcts[GID_ADDR_TYPES] =
38 { ip_prefix_write, lcaf_write, mac_write, sd_write, nsh_write, 0 /* arp */ ,
42 cast_fct cast_fcts[GID_ADDR_TYPES] =
43 { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast, nsh_cast, 0 /* arp */ ,
47 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
48 { ip_prefix_length, lcaf_length, mac_length, sd_length, nsh_length,
49 0 /* arp */ , no_addr_length
52 copy_fct copy_fcts[GID_ADDR_TYPES] =
53 { ip_prefix_copy, lcaf_copy, mac_copy, sd_copy, nsh_copy, 0 /* arp */ ,
57 #define foreach_lcaf_type \
77 #define _(cond, name) \
78 u16 name ## _write (u8 * p, void * a); \
79 u16 name ## _parse (u8 * p, void * a); \
80 u16 name ## _size_to_write (void * a); \
81 void name ## _free (void * a); \
82 void name ## _copy (void * dst, void * src); \
83 u8 name ## _length (void * a); \
84 int name ## _cmp (void *, void *);
87 #define CONCAT(a,b) a##_##b
88 #define IF(c, t, e) CONCAT(IF, c)(t, e)
91 #define EXPAND_FCN(cond, fcn) \
93 cmp_fct lcaf_cmp_fcts[LCAF_TYPES] =
95 #define _(cond, name) \
96 EXPAND_FCN(cond, name##_cmp),
101 addr_len_fct lcaf_body_length_fcts[LCAF_TYPES] = {
102 #define _(cond, name) \
103 EXPAND_FCN(cond, name##_length),
108 copy_fct lcaf_copy_fcts[LCAF_TYPES] = {
109 #define _(cond, name) \
110 EXPAND_FCN(cond, name##_copy),
115 free_fct lcaf_free_fcts[LCAF_TYPES] = {
116 #define _(cond, name) \
117 EXPAND_FCN(cond, name##_free),
122 size_to_write_fct lcaf_size_to_write_fcts[LCAF_TYPES] = {
123 #define _(cond, name) \
124 EXPAND_FCN(cond, name##_size_to_write),
129 serdes_fct lcaf_write_fcts[LCAF_TYPES] = {
130 #define _(cond, name) \
131 EXPAND_FCN(cond, name##_write),
136 serdes_fct lcaf_parse_fcts[LCAF_TYPES] = {
137 #define _(cond, name) \
138 EXPAND_FCN(cond, name##_parse),
144 format_ip_address (u8 * s, va_list * args)
146 ip_address_t *a = va_arg (*args, ip_address_t *);
147 u8 ver = ip_addr_version (a);
150 return format (s, "%U", format_ip4_address, &ip_addr_v4 (a));
154 return format (s, "%U", format_ip6_address, &ip_addr_v6 (a));
158 clib_warning ("Can't format IP version %d!", ver);
164 unformat_ip_address (unformat_input_t * input, va_list * args)
166 ip_address_t *a = va_arg (*args, ip_address_t *);
168 clib_memset (a, 0, sizeof (*a));
169 if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (a)))
170 ip_addr_version (a) = IP4;
171 else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6 (a)))
172 ip_addr_version (a) = IP6;
179 format_ip_prefix (u8 * s, va_list * args)
181 ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
182 return format (s, "%U/%d", format_ip_address, &ip_prefix_addr (a),
187 unformat_ip_prefix (unformat_input_t * input, va_list * args)
189 ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
190 if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr (a),
193 if ((ip_prefix_version (a) == IP4 && 32 < ip_prefix_len (a)) ||
194 (ip_prefix_version (a) == IP6 && 128 < ip_prefix_length (a)))
196 clib_warning ("Prefix length to big: %d!", ip_prefix_len (a));
199 ip_prefix_normalize (a);
207 unformat_nsh_address (unformat_input_t * input, va_list * args)
209 nsh_t *a = va_arg (*args, nsh_t *);
210 return unformat (input, "SPI:%d SI:%d", &a->spi, &a->si);
214 format_nsh_address (u8 * s, va_list * args)
216 nsh_t *a = va_arg (*args, nsh_t *);
217 return format (s, "SPI:%d SI:%d", a->spi, a->si);
221 format_fid_nsh_address (u8 * s, va_list * args)
223 u32 *a = va_arg (*args, u32 *);
224 return format (s, "SPI:%d SI:%d", *a >> 8, *a & 0xff);
228 format_fid_address (u8 * s, va_list * args)
230 fid_address_t *a = va_arg (*args, fid_address_t *);
232 switch (fid_addr_type (a))
234 case FID_ADDR_IP_PREF:
235 return format (s, "%U", format_ip_prefix, &fid_addr_ippref (a));
237 return format (s, "%U", format_mac_address, &fid_addr_mac (a));
239 return format (s, "%U", format_fid_nsh_address, &fid_addr_nsh (a));
242 clib_warning ("Can't format fid address type %d!", fid_addr_type (a));
249 format_gid_address (u8 * s, va_list * args)
251 gid_address_t *a = va_arg (*args, gid_address_t *);
252 u8 type = gid_address_type (a);
255 case GID_ADDR_IP_PREFIX:
256 return format (s, "[%d] %U", gid_address_vni (a), format_ip_prefix,
257 &gid_address_ippref (a));
258 case GID_ADDR_SRC_DST:
259 return format (s, "[%d] %U|%U", gid_address_vni (a),
260 format_fid_address, &gid_address_sd_src (a),
261 format_fid_address, &gid_address_sd_dst (a));
263 return format (s, "[%d] %U", gid_address_vni (a), format_mac_address,
264 &gid_address_mac (a));
267 return format (s, "[%d, %U]", gid_address_arp_ndp_bd (a),
268 format_ip_address, &gid_address_arp_ndp_ip (a));
270 return format (s, "%U", format_nsh_address, &gid_address_nsh (a));
273 clib_warning ("Can't format gid type %d", type);
280 unformat_fid_address (unformat_input_t * i, va_list * args)
282 fid_address_t *a = va_arg (*args, fid_address_t *);
287 if (unformat (i, "%U", unformat_ip_prefix, &ippref))
289 fid_addr_type (a) = FID_ADDR_IP_PREF;
290 ip_prefix_copy (&fid_addr_ippref (a), &ippref);
292 else if (unformat (i, "%U", unformat_mac_address, mac))
294 fid_addr_type (a) = FID_ADDR_MAC;
295 mac_copy (fid_addr_mac (a), mac);
297 else if (unformat (i, "%U", unformat_nsh_address, &nsh))
299 fid_addr_type (a) = FID_ADDR_NSH;
300 nsh_copy (&fid_addr_nsh (a), &nsh);
309 unformat_hmac_key_id (unformat_input_t * input, va_list * args)
311 u32 *key_id = va_arg (*args, u32 *);
314 if (unformat (input, "%s", &s))
316 if (!strcmp ((char *) s, "sha1"))
317 key_id[0] = HMAC_SHA_1_96;
318 else if (!strcmp ((char *) s, "sha256"))
319 key_id[0] = HMAC_SHA_256_128;
322 clib_warning ("invalid key_id: '%s'", s);
323 key_id[0] = HMAC_NO_KEY;
334 unformat_gid_address (unformat_input_t * input, va_list * args)
336 gid_address_t *a = va_arg (*args, gid_address_t *);
339 fid_address_t sim1, sim2;
342 clib_memset (&ippref, 0, sizeof (ippref));
343 clib_memset (&sim1, 0, sizeof (sim1));
344 clib_memset (&sim2, 0, sizeof (sim2));
346 if (unformat (input, "%U|%U", unformat_fid_address, &sim1,
347 unformat_fid_address, &sim2))
349 gid_address_sd_src (a) = sim1;
350 gid_address_sd_dst (a) = sim2;
351 gid_address_type (a) = GID_ADDR_SRC_DST;
353 else if (unformat (input, "%U", unformat_ip_prefix, &ippref))
355 ip_prefix_copy (&gid_address_ippref (a), &ippref);
356 gid_address_type (a) = GID_ADDR_IP_PREFIX;
358 else if (unformat (input, "%U", unformat_mac_address, mac))
360 mac_copy (gid_address_mac (a), mac);
361 gid_address_type (a) = GID_ADDR_MAC;
363 else if (unformat (input, "%U", unformat_nsh_address, &nsh))
365 nsh_copy (&gid_address_nsh (a), &nsh);
366 gid_address_type (a) = GID_ADDR_NSH;
375 unformat_negative_mapping_action (unformat_input_t * input, va_list * args)
377 u32 *action = va_arg (*args, u32 *);
380 if (unformat (input, "%s", &s))
382 if (!strcmp ((char *) s, "no-action"))
383 action[0] = LISP_NO_ACTION;
384 else if (!strcmp ((char *) s, "natively-forward"))
385 action[0] = LISP_FORWARD_NATIVE;
386 else if (!strcmp ((char *) s, "send-map-request"))
387 action[0] = LISP_SEND_MAP_REQUEST;
388 else if (!strcmp ((char *) s, "drop"))
389 action[0] = LISP_DROP;
392 clib_warning ("invalid action: '%s'", s);
393 action[0] = LISP_DROP;
404 format_hmac_key_id (u8 * s, va_list * args)
406 lisp_key_type_t key_id = va_arg (*args, lisp_key_type_t);
411 return format (0, "sha1");
412 case HMAC_SHA_256_128:
413 return format (0, "sha256");
422 format_negative_mapping_action (u8 * s, va_list * args)
424 lisp_action_e action = va_arg (*args, lisp_action_e);
429 s = format (s, "no-action");
431 case LISP_FORWARD_NATIVE:
432 s = format (s, "natively-forward");
434 case LISP_SEND_MAP_REQUEST:
435 s = format (s, "send-map-request");
439 s = format (s, "drop");
446 ip_address_size (const ip_address_t * a)
448 switch (ip_addr_version (a))
451 return sizeof (ip4_address_t);
454 return sizeof (ip6_address_t);
461 ip_version_to_size (u8 ver)
466 return sizeof (ip4_address_t);
469 return sizeof (ip6_address_t);
476 ip_version_to_max_plen (u8 ver)
490 always_inline lisp_afi_e
491 ip_version_to_iana_afi (u16 version)
506 ip_iana_afi_to_version (lisp_afi_e afi)
521 ip_address_size_to_write (ip_address_t * a)
523 return ip_address_size (a) + sizeof (u16);
527 ip_address_iana_afi (ip_address_t * a)
529 return ip_version_to_iana_afi (ip_addr_version (a));
533 ip_address_max_len (u8 version)
535 return version == IP4 ? 32 : 128;
539 ip4_address_size_to_put ()
541 // return sizeof(u16) + sizeof (ip4_address_t);
546 ip6_address_size_to_put ()
548 //return sizeof(u16) + sizeof (ip6_address_t);
553 ip4_address_put (u8 * b, ip4_address_t * a)
555 *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (IP4));
556 u8 *p = b + sizeof (u16);
557 clib_memcpy (p, a, sizeof (*a));
558 return ip4_address_size_to_put ();
562 ip6_address_put (u8 * b, ip6_address_t * a)
564 *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (IP6));
565 u8 *p = b + sizeof (u16);
566 clib_memcpy (p, a, sizeof (*a));
567 return ip6_address_size_to_put ();
571 ip_address_put (u8 * b, ip_address_t * a)
573 u32 len = ip_address_size (a);
574 *(u16 *) b = clib_host_to_net_u16 (ip_address_iana_afi (a));
575 u8 *p = b + sizeof (u16);
576 clib_memcpy (p, &ip_addr_addr (a), len);
577 return (len + sizeof (u16));
581 ip_address_parse (void *offset, u16 iana_afi, ip_address_t * dst)
583 ip_addr_version (dst) = ip_iana_afi_to_version (iana_afi);
584 u8 size = ip_version_to_size (ip_addr_version (dst));
585 clib_memcpy (&ip_addr_addr (dst), offset + sizeof (u16), size);
586 return (sizeof (u16) + size);
590 gid_to_dp_address (gid_address_t * g, dp_address_t * d)
592 switch (gid_address_type (g))
594 case GID_ADDR_SRC_DST:
595 switch (gid_address_sd_dst_type (g))
597 case FID_ADDR_IP_PREF:
598 ip_prefix_copy (&d->ippref, &gid_address_sd_dst_ippref (g));
599 d->type = FID_ADDR_IP_PREF;
602 mac_copy (&d->mac, &gid_address_sd_dst_mac (g));
603 d->type = FID_ADDR_MAC;
606 clib_warning ("Source/Dest address type %d not supported!",
607 gid_address_sd_dst_type (g));
611 case GID_ADDR_IP_PREFIX:
612 ip_prefix_copy (&d->ippref, &gid_address_ippref (g));
613 d->type = FID_ADDR_IP_PREF;
616 mac_copy (&d->mac, &gid_address_mac (g));
617 d->type = FID_ADDR_MAC;
621 d->nsh = gid_address_nsh (g).spi << 8 | gid_address_nsh (g).si;
622 d->type = FID_ADDR_NSH;
628 lcaf_hdr_parse (void *offset, lcaf_t * lcaf)
630 lcaf_hdr_t *lh = offset;
631 lcaf->type = lh->type;
633 /* this is a bit of hack: since the LCAF Instance ID is the
634 only message that uses reserved2 field, we can set it here.
635 If any LCAF format starts using reserved2 field as well this needs
636 to be moved elsewhere */
637 lcaf_vni_len (lcaf) = lh->reserved2;
639 return sizeof (lh[0]);
643 iana_afi_to_fid_addr_type (u16 type)
649 return FID_ADDR_IP_PREF;
658 fid_addr_parse (u8 * p, fid_address_t * a)
660 u16 afi = clib_net_to_host_u16 (*(u16 *) p);
661 fid_addr_type (a) = iana_afi_to_fid_addr_type (afi);
662 ip_address_t *ip_addr = &ip_prefix_addr (&fid_addr_ippref (a));
664 switch (fid_addr_type (a))
667 return mac_parse (p, fid_addr_mac (a));
669 case FID_ADDR_IP_PREF:
670 return ip_address_parse (p, afi, ip_addr);
678 #define INC(dst, exp) \
681 if ((u16)~0 == _sum) \
693 nsh_parse (u8 * p, void *a)
695 lcaf_spi_hdr_t *h = (lcaf_spi_hdr_t *) p;
696 gid_address_t *g = a;
698 gid_address_type (g) = GID_ADDR_NSH;
699 gid_address_nsh_spi (g) = clib_net_to_host_u32 (LCAF_SPI_SI (h)) >> 8;
700 gid_address_nsh_si (g) = (u8) clib_net_to_host_u32 (LCAF_SPI_SI (h));
702 return sizeof (lcaf_spi_hdr_t);
706 nsh_cmp (void *a1, void *a2)
711 if (n1->spi != n2->spi)
713 if (n1->si != n2->si)
719 sd_parse (u8 * p, void *a)
721 lcaf_src_dst_hdr_t *sd_hdr;
722 gid_address_t *g = a;
724 fid_address_t *src = &gid_address_sd_src (g);
725 fid_address_t *dst = &gid_address_sd_dst (g);
727 gid_address_type (g) = GID_ADDR_SRC_DST;
729 sd_hdr = (lcaf_src_dst_hdr_t *) (p + size);
730 size += sizeof (sd_hdr[0]);
732 INC (size, fid_addr_parse (p + size, src));
733 INC (size, fid_addr_parse (p + size, dst));
735 if (fid_addr_type (src) == FID_ADDR_IP_PREF)
737 ip_prefix_t *ippref = &fid_addr_ippref (src);
738 ip_prefix_len (ippref) = LCAF_SD_SRC_ML (sd_hdr);
740 if (fid_addr_type (dst) == FID_ADDR_IP_PREF)
742 ip_prefix_t *ippref = &fid_addr_ippref (dst);
743 ip_prefix_len (ippref) = LCAF_SD_DST_ML (sd_hdr);
749 try_parse_src_dst_lcaf (u8 * p, gid_address_t * a)
752 u16 size = sizeof (u16); /* skip AFI */
754 size += lcaf_hdr_parse (p + size, &lcaf);
756 if (LCAF_SOURCE_DEST != lcaf_type (&lcaf))
759 INC (size, sd_parse (p + size, a));
764 vni_parse (u8 * p, void *a)
767 gid_address_t *g = a;
770 gid_address_vni (g) = clib_net_to_host_u32 (*(u32 *) p);
771 size += sizeof (u32);
772 gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
774 /* nested LCAFs are not supported except of src/dst with vni - to handle
775 * such case look at the next AFI and process src/dest LCAF separately */
776 u16 afi = clib_net_to_host_u16 (*((u16 *) (p + size)));
777 if (LISP_AFI_LCAF == afi)
779 INC (size, try_parse_src_dst_lcaf (p + size, g));
782 INC (size, gid_address_parse (p + size, g));
788 no_addr_parse (u8 * p, void *a)
795 lcaf_parse (void *offset, gid_address_t * addr)
798 offset += sizeof (u16);
799 lcaf_t *lcaf = &gid_address_lcaf (addr);
801 u32 size = lcaf_hdr_parse (offset, lcaf);
802 u8 type = lcaf_type (lcaf);
804 if (!lcaf_parse_fcts[type])
806 clib_warning ("Unsupported LCAF type: %u", type);
809 INC (size, (*lcaf_parse_fcts[type]) (offset + size, lcaf));
810 return sizeof (u16) + size;
817 gid_address_free (vni_gid (v));
818 clib_mem_free (vni_gid (v));
822 no_addr_free (void *a)
834 gid_address_free (gid_address_t * a)
836 if (gid_address_type (a) != GID_ADDR_LCAF)
839 lcaf_t *lcaf = &gid_address_lcaf (a);
840 u8 lcaf_type = lcaf_type (lcaf);
841 (*lcaf_free_fcts[lcaf_type]) (lcaf);
845 gid_address_from_ip (gid_address_t * g, ip_address_t * ip)
847 clib_memset (g, 0, sizeof (g[0]));
848 ip_address_set (&gid_address_ip (g), ip, ip_addr_version (ip));
849 gid_address_ippref_len (g) = 32;
853 ip_address_cmp (const ip_address_t * ip1, const ip_address_t * ip2)
856 if (ip_addr_version (ip1) != ip_addr_version (ip2))
859 memcmp (&ip_addr_addr (ip1), &ip_addr_addr (ip2), ip_address_size (ip1));
870 ip_address_copy (ip_address_t * dst, const ip_address_t * src)
872 if (IP4 == ip_addr_version (src))
874 /* don't copy any garbage from the union */
875 clib_memset (dst, 0, sizeof (*dst));
876 dst->ip.v4 = src->ip.v4;
881 clib_memcpy (dst, src, sizeof (ip_address_t));
886 ip_address_copy_addr (void *dst, const ip_address_t * src)
888 clib_memcpy (dst, src, ip_address_size (src));
892 ip_address_set (ip_address_t * dst, const void *src, u8 version)
894 clib_memcpy (dst, src, ip_version_to_size (version));
895 ip_addr_version (dst) = version;
899 ip_address_to_46 (const ip_address_t * addr,
900 ip46_address_t * a, fib_protocol_t * proto)
902 *proto = (IP4 == ip_addr_version (addr) ?
903 FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
906 case FIB_PROTOCOL_IP4:
907 ip46_address_set_ip4 (a, &addr->ip.v4);
909 case FIB_PROTOCOL_IP6:
910 a->ip6 = addr->ip.v6;
919 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
930 mask = pow2_mask (preflen) << (32 - preflen);
931 mask = clib_host_to_net_u32 (mask);
932 ip4->data_u32 &= mask;
936 ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
944 clib_memset (mask_6, 0, sizeof (mask_6));
953 m = (u32 *) & mask_6[0];
955 for (j = 0; j < i0; j++)
962 m[i0] = clib_host_to_net_u32 (pow2_mask (i1) << (32 - i1));
965 for (j = 0; j < sizeof (mask_6); j++)
967 ip6->as_u8[j] &= mask_6[j];
972 ip_prefix_normalize (ip_prefix_t * a)
974 u8 preflen = ip_prefix_len (a);
976 switch (ip_prefix_version (a))
979 ip_prefix_normalize_ip4 (&ip_prefix_v4 (a), preflen);
983 ip_prefix_normalize_ip6 (&ip_prefix_v6 (a), preflen);
992 ip_prefix_cast (gid_address_t * a)
994 return &gid_address_ippref (a);
998 ip_prefix_size_to_write (void *pref)
1000 ip_prefix_t *a = (ip_prefix_t *) pref;
1001 return ip_address_size_to_write (&ip_prefix_addr (a));
1005 ip_prefix_write (u8 * p, void *gid)
1007 gid_address_t *g = gid;
1008 ip_prefix_t *a = &gid_address_ippref (g);
1010 switch (ip_prefix_version (a))
1013 return ip4_address_put (p, &ip_prefix_v4 (a));
1016 return ip6_address_put (p, &ip_prefix_v6 (a));
1023 ip_prefix_length (void *a)
1025 return ip_prefix_len ((ip_prefix_t *) a);
1029 ip_prefix_copy (void *dst, void *src)
1031 clib_memcpy (dst, src, sizeof (ip_prefix_t));
1035 mac_copy (void *dst, void *src)
1037 clib_memcpy (dst, src, 6);
1041 sd_copy (void *dst, void *src)
1043 clib_memcpy (dst, src, sizeof (source_dest_t));
1047 nsh_copy (void *dst, void *src)
1049 clib_memcpy (dst, src, sizeof (nsh_t));
1053 ip_prefix_cmp (ip_prefix_t * p1, ip_prefix_t * p2)
1057 ip_prefix_normalize (p1);
1058 ip_prefix_normalize (p2);
1060 cmp = ip_address_cmp (&ip_prefix_addr (p1), &ip_prefix_addr (p2));
1063 if (ip_prefix_len (p1) < ip_prefix_len (p2))
1069 if (ip_prefix_len (p1) > ip_prefix_len (p2))
1077 no_addr_copy (void *dst, void *src)
1083 vni_copy (void *dst, void *src)
1088 clib_memcpy (vd, vs, sizeof (vd[0]));
1089 vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t));
1090 gid_address_copy (vni_gid (vd), vni_gid (vs));
1094 lcaf_copy (void *dst, void *src)
1096 lcaf_t *lcaf_dst = dst;
1097 lcaf_t *lcaf_src = src;
1099 lcaf_type (lcaf_dst) = lcaf_type (lcaf_src);
1100 (*lcaf_copy_fcts[lcaf_type (lcaf_src)]) (dst, src);
1104 lcaf_length (void *a)
1110 mac_length (void *a)
1122 nsh_length (void *a)
1128 lcaf_cast (gid_address_t * a)
1130 return &gid_address_lcaf (a);
1134 mac_cast (gid_address_t * a)
1136 return &gid_address_mac (a);
1140 no_addr_cast (gid_address_t * a)
1146 sd_cast (gid_address_t * a)
1148 return &gid_address_sd (a);
1152 nsh_cast (gid_address_t * a)
1154 return &gid_address_nsh (a);
1158 no_addr_length (void *a)
1164 vni_length (void *a)
1167 return (sizeof (u32) /* VNI size */
1168 + gid_address_size_to_put (vni_gid (v)) /* vni body size */ );
1172 lcaf_write (u8 * p, void *a)
1176 u8 type = lcaf_type (lcaf);
1177 lcaf_hdr_t _h, *h = &_h;
1179 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1180 size += sizeof (u16);
1181 clib_memset (h, 0, sizeof (h[0]));
1182 LCAF_TYPE (h) = type;
1183 u16 lcaf_len = (*lcaf_body_length_fcts[type]) (lcaf);
1184 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1186 clib_memcpy (p + size, h, sizeof (h[0]));
1187 size += sizeof (h[0]);
1188 len = (*lcaf_write_fcts[type]) (p + size, lcaf);
1190 if ((u16) ~ 0 == len)
1197 mac_write (u8 * p, void *a)
1199 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_MAC);
1200 clib_memcpy (p + sizeof (u16), a, 6);
1201 return mac_size_to_write (a);
1205 fid_addr_write (u8 * p, fid_address_t * a)
1207 switch (fid_addr_type (a))
1209 case FID_ADDR_IP_PREF:
1210 return ip_prefix_write (p, &fid_addr_ippref (a));
1213 return mac_write (p, &fid_addr_mac (a));
1222 fid_address_length (fid_address_t * a)
1224 switch (fid_addr_type (a))
1226 case FID_ADDR_IP_PREF:
1227 return ip_prefix_length (&fid_addr_ippref (a));
1237 sd_write (u8 * p, void *a)
1239 source_dest_t *sd = a;
1241 lcaf_hdr_t _h, *h = &_h;
1242 lcaf_src_dst_hdr_t sd_hdr;
1244 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1245 size += sizeof (u16);
1246 clib_memset (h, 0, sizeof (h[0]));
1247 LCAF_TYPE (h) = LCAF_SOURCE_DEST;
1248 u16 lcaf_len = sizeof (lcaf_src_dst_hdr_t)
1249 + fid_addr_size_to_write (&sd_src (sd))
1250 + fid_addr_size_to_write (&sd_dst (sd));
1251 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1253 clib_memcpy (p + size, h, sizeof (h[0]));
1254 size += sizeof (h[0]);
1256 clib_memset (&sd_hdr, 0, sizeof (sd_hdr));
1257 LCAF_SD_SRC_ML (&sd_hdr) = fid_address_length (&sd_src (sd));
1258 LCAF_SD_DST_ML (&sd_hdr) = fid_address_length (&sd_dst (sd));
1259 clib_memcpy (p + size, &sd_hdr, sizeof (sd_hdr));
1260 size += sizeof (sd_hdr);
1262 u16 len = fid_addr_write (p + size, &sd_src (sd));
1263 if ((u16) ~ 0 == len)
1267 len = fid_addr_write (p + size, &sd_dst (sd));
1268 if ((u16) ~ 0 == len)
1276 nsh_write (u8 * p, void *a)
1280 gid_address_t *g = a;
1283 ASSERT (gid_address_type (g) == GID_ADDR_NSH);
1285 clib_memset (&lcaf, 0, sizeof (lcaf));
1286 clib_memset (&spi, 0, sizeof (spi));
1288 LCAF_TYPE (&lcaf) = LCAF_NSH;
1289 LCAF_LENGTH (&lcaf) = clib_host_to_net_u16 (sizeof (lcaf_spi_hdr_t));
1291 u32 s = clib_host_to_net_u32 (gid_address_nsh_spi (g) << 8 |
1292 gid_address_nsh_si (g));
1293 LCAF_SPI_SI (&spi) = s;
1295 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1296 size += sizeof (u16);
1298 clib_memcpy (p + size, &lcaf, sizeof (lcaf));
1299 size += sizeof (lcaf);
1301 clib_memcpy (p + size, &spi, sizeof (spi));
1302 size += sizeof (spi);
1308 vni_write (u8 * p, void *a)
1310 lcaf_hdr_t _h, *h = &_h;
1311 gid_address_t *g = a;
1314 /* put lcaf header */
1315 *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
1316 size += sizeof (u16);
1317 clib_memset (h, 0, sizeof (h[0]));
1318 LCAF_TYPE (h) = LCAF_INSTANCE_ID;
1319 u16 lcaf_len = sizeof (u32) /* Instance ID size */
1320 + gid_address_size_to_put_no_vni (g);
1321 LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
1322 LCAF_RES2 (h) = gid_address_vni_mask (g);
1324 /* put vni header */
1325 clib_memcpy (p + size, h, sizeof (h[0]));
1326 size += sizeof (h[0]);
1328 u32 *afip = (u32 *) (p + size);
1329 afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
1330 size += sizeof (u32);
1332 if (GID_ADDR_SRC_DST == gid_address_type (g))
1333 /* write src/dst LCAF */
1335 len = sd_write (p + size, g);
1336 if ((u16) ~ 0 == len)
1340 /* write the actual address */
1341 len = gid_address_put_no_vni (p + size, g);
1343 if ((u16) ~ 0 == len)
1350 no_addr_write (u8 * p, void *a)
1352 /* do nothing; return AFI field size */
1353 return sizeof (u16);
1357 no_addr_size_to_write (void *a)
1359 return sizeof (u16); /* AFI field length */
1363 fid_addr_size_to_write (fid_address_t * a)
1365 switch (fid_addr_type (a))
1367 case FID_ADDR_IP_PREF:
1368 return ip_prefix_size_to_write (a);
1371 return mac_size_to_write (a);
1380 vni_size_to_write (void *a)
1382 gid_address_t *g = a;
1384 u16 lcaf_size = sizeof (u32) + sizeof (u16) /* LCAF AFI field size */
1385 + sizeof (lcaf_hdr_t);
1387 if (gid_address_type (g) == GID_ADDR_SRC_DST)
1388 /* special case where nested LCAF is supported */
1389 return lcaf_size + sd_size_to_write (g);
1391 return lcaf_size + gid_address_size_to_put_no_vni (g);
1395 lcaf_size_to_write (void *a)
1397 lcaf_t *lcaf = (lcaf_t *) a;
1399 u8 type = lcaf_type (lcaf);
1401 size += sizeof (u16); /* AFI size */
1403 len = (*lcaf_size_to_write_fcts[type]) (lcaf);
1411 sd_size_to_write (void *a)
1413 source_dest_t *sd = a;
1415 + sizeof (lcaf_hdr_t)
1416 + sizeof (lcaf_src_dst_hdr_t)
1417 + fid_addr_size_to_write (&sd_src (sd))
1418 + fid_addr_size_to_write (&sd_dst (sd));
1422 mac_size_to_write (void *a)
1424 return sizeof (u16) + 6;
1428 nsh_size_to_write (void *a)
1430 return sizeof (u16) + sizeof (lcaf_hdr_t) + sizeof (lcaf_spi_hdr_t);
1434 gid_address_len (gid_address_t * a)
1436 gid_address_type_t type = gid_address_type (a);
1437 return (*addr_len_fcts[type]) ((*cast_fcts[type]) (a));
1441 gid_address_put_no_vni (u8 * b, gid_address_t * gid)
1443 gid_address_type_t type = gid_address_type (gid);
1444 return (*write_fcts[type]) (b, (*cast_fcts[type]) (gid));
1448 gid_address_put (u8 * b, gid_address_t * gid)
1450 if (0 != gid_address_vni (gid))
1451 return vni_write (b, gid);
1453 return gid_address_put_no_vni (b, gid);
1457 gid_address_size_to_put_no_vni (gid_address_t * gid)
1459 gid_address_type_t type = gid_address_type (gid);
1460 return (*size_to_write_fcts[type]) ((*cast_fcts[type]) (gid));
1464 gid_address_size_to_put (gid_address_t * gid)
1466 if (0 != gid_address_vni (gid))
1467 return vni_size_to_write (gid);
1469 return gid_address_size_to_put_no_vni (gid);
1473 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
1475 return (*cast_fcts[type]) (gid);
1479 gid_address_copy (gid_address_t * dst, gid_address_t * src)
1481 gid_address_type_t type = gid_address_type (src);
1482 (*copy_fcts[type]) ((*cast_fcts[type]) (dst), (*cast_fcts[type]) (src));
1483 gid_address_type (dst) = type;
1484 gid_address_vni (dst) = gid_address_vni (src);
1485 gid_address_vni_mask (dst) = gid_address_vni_mask (src);
1489 mac_parse (u8 * offset, u8 * a)
1491 /* skip AFI field */
1492 offset += sizeof (u16);
1494 clib_memcpy (a, offset, 6);
1495 return sizeof (u16) + 6;
1499 gid_address_parse (u8 * offset, gid_address_t * a)
1506 /* NOTE: since gid_address_parse may be called by vni_parse, we can't 0
1507 * the gid address here */
1508 afi = clib_net_to_host_u16 (*((u16 *) offset));
1512 case LISP_AFI_NO_ADDR:
1514 gid_address_type (a) = GID_ADDR_NO_ADDRESS;
1517 len = ip_address_parse (offset, afi, &gid_address_ip (a));
1518 gid_address_type (a) = GID_ADDR_IP_PREFIX;
1519 /* this should be modified outside if needed */
1520 gid_address_ippref_len (a) = 32;
1523 len = ip_address_parse (offset, afi, &gid_address_ip (a));
1524 gid_address_type (a) = GID_ADDR_IP_PREFIX;
1525 /* this should be modified outside if needed */
1526 gid_address_ippref_len (a) = 128;
1529 gid_address_type (a) = GID_ADDR_LCAF;
1530 len = lcaf_parse (offset, a);
1533 len = mac_parse (offset, gid_address_mac (a));
1534 gid_address_type (a) = GID_ADDR_MAC;
1537 clib_warning ("LISP AFI %d not supported!", afi);
1540 return (len == (u16) ~ 0) ? ~0 : len;
1544 gid_address_ip_set (gid_address_t * dst, void *src, u8 version)
1546 gid_address_ippref_len (dst) = ip_address_max_len (version);
1547 ip_address_set (&gid_address_ip (dst), src, version);
1551 no_addr_cmp (void *a1, void *a2)
1557 vni_cmp (void *a1, void *a2)
1562 if (vni_mask_len (v1) != vni_mask_len (v2))
1564 if (vni_vni (v1) != vni_vni (v2))
1566 return gid_address_cmp (vni_gid (v1), vni_gid (v2));
1570 mac_cmp (void *a1, void *a2)
1572 return memcmp (a1, a2, 6);
1576 fid_addr_cmp (fid_address_t * a1, fid_address_t * a2)
1578 if (fid_addr_type (a1) != fid_addr_type (a2))
1581 switch (fid_addr_type (a1))
1583 case FID_ADDR_IP_PREF:
1584 return ip_prefix_cmp (&fid_addr_ippref (a1), &fid_addr_ippref (a2));
1587 return mac_cmp (fid_addr_mac (a1), fid_addr_mac (a2));
1596 sd_cmp (void *a1, void *a2)
1598 source_dest_t *sd1 = a1;
1599 source_dest_t *sd2 = a2;
1601 if (fid_addr_cmp (&sd_dst (sd1), &sd_dst (sd2)))
1603 if (fid_addr_cmp (&sd_src (sd1), &sd_src (sd2)))
1608 /* Compare two gid_address_t.
1610 * -1: If they are from different afi
1611 * 0: Both address are the same
1612 * 1: Addr1 is bigger than addr2
1613 * 2: Addr2 is bigger than addr1
1616 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
1618 lcaf_t *lcaf1, *lcaf2;
1622 if (gid_address_type (a1) != gid_address_type (a2))
1624 if (gid_address_vni (a1) != gid_address_vni (a2))
1627 /* TODO vni mask is not supported, disable comparing for now
1628 if (gid_address_vni_mask (a1) != gid_address_vni_mask (a2))
1632 switch (gid_address_type (a1))
1634 case GID_ADDR_NO_ADDRESS:
1640 case GID_ADDR_IP_PREFIX:
1642 ip_prefix_cmp (&gid_address_ippref (a1), &gid_address_ippref (a2));
1645 lcaf1 = &gid_address_lcaf (a1);
1646 lcaf2 = &gid_address_lcaf (a2);
1647 if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
1648 cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)]) (lcaf1, lcaf2);
1651 cmp = mac_cmp (gid_address_mac (a1), gid_address_mac (a2));
1654 case GID_ADDR_SRC_DST:
1655 cmp = sd_cmp (&gid_address_sd (a1), &gid_address_sd (a2));
1658 cmp = nsh_cmp (&gid_address_nsh (a1), &gid_address_nsh (a2));
1668 locator_parse (void *b, locator_t * loc)
1671 u8 status = 1; /* locator up */
1675 if (!LOC_REACHABLE (h) && LOC_LOCAL (h))
1678 len = gid_address_parse (LOC_ADDR (h), &loc->address);
1682 loc->state = status;
1684 loc->priority = LOC_PRIORITY (h);
1685 loc->weight = LOC_WEIGHT (h);
1686 loc->mpriority = LOC_MPRIORITY (h);
1687 loc->mweight = LOC_MWEIGHT (h);
1689 return sizeof (locator_hdr_t) + len;
1693 locator_copy (locator_t * dst, locator_t * src)
1695 /* TODO if gid become more complex, this will need to be changed! */
1696 clib_memcpy (dst, src, sizeof (*dst));
1698 gid_address_copy (&dst->address, &src->address);
1702 locator_cmp (locator_t * l1, locator_t * l2)
1705 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
1708 if (l1->priority != l2->priority)
1710 if (l1->weight != l2->weight)
1712 if (l1->mpriority != l2->mpriority)
1714 if (l1->mweight != l2->mweight)
1720 locator_free (locator_t * l)
1723 gid_address_free (&l->address);
1727 build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst)
1729 clib_memset (sd, 0, sizeof (*sd));
1730 gid_address_type (sd) = GID_ADDR_SRC_DST;
1731 gid_address_vni (sd) = gid_address_vni (dst);
1732 gid_address_vni_mask (sd) = gid_address_vni_mask (dst);
1734 switch (gid_address_type (dst))
1736 case GID_ADDR_IP_PREFIX:
1737 gid_address_sd_src_type (sd) = FID_ADDR_IP_PREF;
1738 gid_address_sd_dst_type (sd) = FID_ADDR_IP_PREF;
1739 ip_prefix_copy (&gid_address_sd_src_ippref (sd),
1740 &gid_address_ippref (src));
1741 ip_prefix_copy (&gid_address_sd_dst_ippref (sd),
1742 &gid_address_ippref (dst));
1745 gid_address_sd_src_type (sd) = FID_ADDR_MAC;
1746 gid_address_sd_dst_type (sd) = FID_ADDR_MAC;
1747 mac_copy (gid_address_sd_src_mac (sd), gid_address_mac (src));
1748 mac_copy (gid_address_sd_dst_mac (sd), gid_address_mac (dst));
1751 clib_warning ("Unsupported gid type %d while conversion!",
1752 gid_address_type (dst));
1758 * fd.io coding-style-patch-verification: ON
1761 * eval: (c-set-style "gnu")