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 (*write_fct)(u8 *, void *);
21 typedef u8 (*addr_len_fct)(void *);
22 typedef void (*copy_fct)(void *, void *);
24 size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
25 { ip_prefix_size_to_write };
26 write_fct write_fcts[GID_ADDR_TYPES] =
28 cast_fct cast_fcts[GID_ADDR_TYPES] =
30 addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
32 copy_fct copy_fcts[GID_ADDR_TYPES] =
36 format_ip_address (u8 * s, va_list * args)
38 ip_address_t * a = va_arg (*args, ip_address_t *);
39 u8 ver = ip_addr_version(a);
42 return format (s, "%U", format_ip4_address, &ip_addr_v4(a));
46 return format (s, "%U", format_ip6_address, &ip_addr_v6(a));
50 clib_warning ("Can't format IP version %d!", ver);
56 unformat_ip_address (unformat_input_t * input, va_list * args)
58 ip_address_t * a = va_arg(*args, ip_address_t *);
59 if (unformat(input, "%U", unformat_ip4_address, &ip_addr_v4(a)))
60 ip_addr_version(a) = IP4;
61 else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6(a)))
62 ip_addr_version(a) = IP6;
69 format_ip_prefix (u8 * s, va_list * args)
71 ip_prefix_t * a = va_arg (*args, ip_prefix_t *);
72 return format (s, "%U/%d", format_ip_address, &ip_prefix_addr(a), ip_prefix_len(a));
76 unformat_ip_prefix (unformat_input_t * input, va_list * args)
78 ip_prefix_t * a = va_arg(*args, ip_prefix_t *);
79 return unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a),
84 format_gid_address (u8 * s, va_list * args)
86 gid_address_t * a = va_arg(*args, gid_address_t *);
87 u8 type = gid_address_type(a);
91 return format (s, "%U", format_ip_prefix, &gid_address_ippref(a));
93 clib_warning("Can't format gid type %d", type);
99 unformat_gid_address (unformat_input_t * input, va_list * args)
101 gid_address_t * a = va_arg(*args, gid_address_t *);
102 if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a)))
103 gid_address_type(a) = IP_PREFIX;
110 ip_address_size (ip_address_t * a)
112 switch (ip_addr_version (a))
115 return sizeof(ip4_address_t);
118 return sizeof(ip6_address_t);
125 ip_version_to_size (u8 ver)
130 return sizeof(ip4_address_t);
133 return sizeof(ip6_address_t);
140 ip_version_to_max_plen (u8 ver)
154 always_inline lisp_afi_e
155 ip_version_to_iana_afi (u16 version)
170 ip_iana_afi_to_version (lisp_afi_e afi)
185 ip_address_size_to_write (ip_address_t * a)
187 return ip_address_size (a) + sizeof (u16);
191 ip_address_iana_afi(ip_address_t *a)
193 return ip_version_to_iana_afi(ip_addr_version(a));
197 ip_address_max_len (u8 version)
199 return version == IP4 ? 32 : 128;
203 ip4_address_size_to_put ()
205 // return sizeof(u16) + sizeof (ip4_address_t);
210 ip6_address_size_to_put ()
212 //return sizeof(u16) + sizeof (ip6_address_t);
217 ip4_address_put (u8 * b, ip4_address_t * a)
219 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP4));
220 u8 *p = b + sizeof (u16);
221 memcpy (p, a, sizeof(*a));
222 return ip4_address_size_to_put();
226 ip6_address_put (u8 * b, ip6_address_t * a)
228 *(u16 *)b = clib_host_to_net_u16(ip_version_to_iana_afi(IP6));
229 u8 *p = b + sizeof (u16);
230 memcpy (p, a, sizeof(*a));
231 return ip6_address_size_to_put();
235 ip_address_put (u8 * b, ip_address_t * a)
237 u32 len = ip_address_size (a);
238 *(u16 *) b = clib_host_to_net_u16(ip_address_iana_afi (a));
239 u8 * p = b + sizeof (u16);
240 memcpy (p, &ip_addr_addr (a), len);
241 return (len + sizeof (u16));
245 ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst)
247 ip_addr_version(dst) = ip_iana_afi_to_version (iana_afi);
248 u8 size = ip_version_to_size (ip_addr_version(dst));
249 memcpy (&ip_addr_addr(dst), offset + sizeof(u16), size);
250 return(sizeof(u16) + size);
254 ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2)
257 if (ip_addr_version (ip1) != ip_addr_version(ip2))
259 res = memcmp (&ip_addr_addr(ip1), &ip_addr_addr(ip2), ip_address_size (ip1));
270 ip_prefix_cast (gid_address_t * a)
272 return &gid_address_ippref(a);
276 ip_prefix_size_to_write (void * pref)
278 ip_prefix_t *a = (ip_prefix_t *) pref;
279 return ip_address_size_to_write (&ip_prefix_addr (a));
283 ip_prefix_write (u8 * p, void * pref)
285 ip_prefix_t *a = (ip_prefix_t *) pref;
286 switch (ip_prefix_version (a))
289 return ip4_address_put (p, &ip_prefix_v4 (a));
292 return ip6_address_put (p, &ip_prefix_v6 (a));
299 ip_prefix_length (void *a)
301 return ip_prefix_len((ip_prefix_t *) a);
305 ip_prefix_copy (void * dst , void * src)
307 memcpy (dst, src, sizeof (ip_prefix_t));
311 ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
314 cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
316 cmp = ip_prefix_len(p1) < ip_prefix_len(p2) ? 1 : 2; /* XXX ? */
321 gid_address_len (gid_address_t *a)
323 gid_address_type_t type = gid_address_type (a);
324 return (*addr_len_fcts[type])((*cast_fcts[type])(a));
328 gid_address_put (u8 * b, gid_address_t * gid)
330 gid_address_type_t type = gid_address_type (gid);
331 return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
335 gid_address_size_to_put (gid_address_t * gid)
337 gid_address_type_t type = gid_address_type (gid);
338 return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
342 gid_address_cast (gid_address_t * gid, gid_address_type_t type)
344 return (*cast_fcts[type])(gid);
348 gid_address_copy(gid_address_t * dst, gid_address_t * src)
350 gid_address_type_t type = gid_address_type(src);
351 (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
352 gid_address_type(dst) = type;
356 gid_address_parse (u8 * offset, gid_address_t *a)
364 afi = clib_net_to_host_u16 (*((u16 *) offset));
368 case LISP_AFI_NO_ADDR:
370 gid_address_type(a) = NO_ADDRESS;
373 len = ip_address_parse (offset, afi, &gid_address_ip(a));
374 gid_address_type(a) = IP_PREFIX;
375 /* this should be modified outside if needed*/
376 gid_address_ippref_len(a) = 32;
379 len = ip_address_parse (offset, afi, &gid_address_ip(a));
380 gid_address_type(a) = IP_PREFIX;
381 /* this should be modified outside if needed*/
382 gid_address_ippref_len(a) = 128;
386 clib_warning("LISP AFI %d not supported!", afi);
392 /* Compare two gid_address_t.
394 * -1: If they are from different afi
395 * 0: Both address are the same
396 * 1: Addr1 is bigger than addr2
397 * 2: Addr2 is bigger than addr1
400 gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
405 if (gid_address_type(a1) != gid_address_type(a2))
408 switch (gid_address_type(a1))
417 cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2));
428 locator_parse (void * b, locator_t * loc)
431 u8 status = 1; /* locator up */
435 if (!LOC_REACHABLE(h) && LOC_LOCAL(h))
438 len = gid_address_parse (LOC_ADDR(h), &loc->address);
444 loc->priority = LOC_PRIORITY(h);
445 loc->weight = LOC_WEIGHT(h);
446 loc->mpriority = LOC_MPRIORITY(h);
447 loc->mweight = LOC_MWEIGHT(h);
449 return sizeof(locator_hdr_t) + len;
453 locator_copy (locator_t * dst, locator_t * src)
455 /* TODO if gid become more complex, this will need to be changed! */
456 memcpy (dst, src, sizeof(*dst));
460 locator_cmp (locator_t * l1, locator_t * l2)
463 if ((ret = gid_address_cmp (&l1->address, &l2->address)) != 0)
466 if (l1->priority != l2->priority)
468 if (l1->weight != l2->weight)
470 if (l1->mpriority != l2->mpriority)
472 if (l1->mweight != l2->mweight)