aboutsummaryrefslogtreecommitdiffstats
path: root/lib/src/name.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/src/name.c')
-rw-r--r--lib/src/name.c741
1 files changed, 339 insertions, 402 deletions
diff --git a/lib/src/name.c b/lib/src/name.c
index 54b2a76aa..f363eea90 100644
--- a/lib/src/name.c
+++ b/lib/src/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,533 +19,470 @@
*/
#ifndef _WIN32
-#include <arpa/inet.h> // inet_ptin
+#include <arpa/inet.h> // inet_ptin
#endif
#include <errno.h>
#include <stdio.h>
-#include <stdlib.h> // strtoul
-#include <string.h> // memcpy
+#include <stdlib.h> // strtoul
+#include <string.h> // memcpy
#include <hicn/common.h>
#include <hicn/error.h>
#include <hicn/name.h>
+#include <hicn/util/sstrncpy.h>
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#if ! HICN_VPP_PLUGIN
int
-hicn_name_create (const char *ip_address, u32 id, hicn_name_t * name)
+hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name)
{
int af, rc;
- af = get_addr_family (ip_address);
-
- switch (af)
- {
- case AF_INET:
- if (name->type == HNT_UNSPEC)
- {
- name->type = HNT_CONTIGUOUS_V4;
- }
- name->len = IPV4_ADDR_LEN;
- break;
- case AF_INET6:
- if (name->type == HNT_UNSPEC)
- {
- name->type = HNT_CONTIGUOUS_V6;
- }
- name->len = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
+ memset (name, 0, sizeof (hicn_name_t));
- if ((name->type != HNT_CONTIGUOUS_V4) && (name->type != HNT_CONTIGUOUS_V6))
- {
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+ af = get_addr_family (ip_address);
+ int v4 = (af == AF_INET);
+ u8 *dst = (u8 *) (v4 * (intptr_t) (name->prefix.v4.as_u8) +
+ (1 - v4) * (intptr_t) (name->prefix.v6.as_u8));
+ rc = inet_pton (af, ip_address, dst);
- rc = inet_pton (af, ip_address, name->buffer);
- if (rc <= 0)
+ if (rc != 1)
{
return HICN_LIB_ERROR_UNKNOWN_ADDRESS;
}
- *(u32 *) (name->buffer + name->len) = id;
+
+ name->suffix = id;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_create_from_ip_prefix (const ip_prefix_t * prefix, u32 id,
- hicn_name_t * name)
+hicn_name_create_from_ip_address (const hicn_ip_address_t ip_address,
+ u32 suffix, hicn_name_t *name)
{
- switch (prefix->family)
- {
- case AF_INET:
- name->type = HNT_CONTIGUOUS_V4;
- memcpy (name->buffer, prefix->address.v4.buffer,
- ip_address_len(prefix->family));
- name->len = IPV4_ADDR_LEN;
- break;
- case AF_INET6:
- name->type = HNT_CONTIGUOUS_V6;
- memcpy (name->buffer, prefix->address.v6.buffer,
- ip_address_len(prefix->family));
- name->len = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
-
- *(u32 *) (name->buffer + name->len) = id;
+ name->prefix = ip_address;
+ name->suffix = suffix;
return HICN_LIB_ERROR_NONE;
}
-u8
-hicn_name_get_length (const hicn_name_t * name)
+int
+hicn_name_create_from_ip_prefix (const hicn_ip_prefix_t *prefix, u32 id,
+ hicn_name_t *name)
{
- return name->len;
+ name->prefix = prefix->address;
+ name->suffix = id;
+
+ return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_compare (const hicn_name_t * name_1, const hicn_name_t * name_2,
- bool consider_segment)
+hicn_name_compare (const hicn_name_t *name_1, const hicn_name_t *name_2,
+ bool consider_segment)
{
- hicn_name_t *name1 = (hicn_name_t *) name_1;
- hicn_name_t *name2 = (hicn_name_t *) name_2;
+ int ret;
+ ret = memcmp (&name_1->prefix.v6.buffer, &name_2->prefix.v6.buffer,
+ sizeof (name_1->prefix.v6));
- if ((name1->type == HNT_CONTIGUOUS_V4 && name2->type == HNT_CONTIGUOUS_V6)
- || (name1->type == HNT_CONTIGUOUS_V6
- && name2->type == HNT_CONTIGUOUS_V4))
- {
- return -1;
- }
+ if (consider_segment)
+ ret |= !(name_1->suffix == name_2->suffix);
- if ((name1->type == HNT_IOV_V4 && name2->type == HNT_IOV_V6) ||
- (name1->type == HNT_IOV_V6 && name2->type == HNT_IOV_V4))
- {
- return -1;
- }
+ return ret;
+}
- if ((name1->type == HNT_IOV_V4 && name2->type == HNT_CONTIGUOUS_V6) ||
- (name1->type == HNT_IOV_V6 && name2->type == HNT_CONTIGUOUS_V4))
- {
- return -1;
- }
+uint32_t
+_hicn_name_get_hash (const hicn_name_t *name, bool consider_suffix)
+{
+ uint32_t hash = hash32 (&name->prefix, sizeof (name->prefix));
- if (name1->type == HNT_UNSPEC || name2->type == HNT_UNSPEC)
- {
- return -1;
- }
+ if (consider_suffix)
+ hash = cumulative_hash32 (&name->suffix, sizeof (name->suffix), hash);
- size_t len1 = 0, len2 = 0;
+ return hash;
+}
- u8 *buffer11, *buffer12, *buffer21, *buffer22;
+int
+hicn_name_empty (hicn_name_t *name)
+{
+ return _is_unspec (name);
+}
- switch (name1->type)
- {
- case HNT_CONTIGUOUS_V4:
- buffer11 = name1->buffer;
- buffer12 = name1->buffer + IPV4_ADDR_LEN;
- len1 = IPV4_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V6:
- buffer11 = name1->buffer;
- buffer12 = name1->buffer + IPV6_ADDR_LEN;
- len1 = IPV6_ADDR_LEN;
- break;
- case HNT_IOV_V4:
- buffer11 = name1->iov.buffers[0].iov_base;
- buffer12 = name1->iov.buffers[1].iov_base;
- len1 = IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- buffer11 = name1->iov.buffers[0].iov_base;
- buffer12 = name1->iov.buffers[1].iov_base;
- len1 = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+int
+hicn_name_copy (hicn_name_t *dst, const hicn_name_t *src)
+{
+ *dst = *src;
+ return HICN_LIB_ERROR_NONE;
+}
- switch (name2->type)
- {
- case HNT_CONTIGUOUS_V4:
- buffer21 = name2->buffer;
- buffer22 = name2->buffer + IPV4_ADDR_LEN;
- len2 = IPV4_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V6:
- buffer21 = name2->buffer;
- buffer22 = name2->buffer + IPV6_ADDR_LEN;
- len2 = IPV6_ADDR_LEN;
- break;
- case HNT_IOV_V4:
- buffer21 = name2->iov.buffers[0].iov_base;
- buffer22 = name2->iov.buffers[1].iov_base;
- len2 = IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- buffer21 = name2->iov.buffers[0].iov_base;
- buffer22 = name2->iov.buffers[1].iov_base;
- len2 = IPV6_ADDR_LEN;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+int
+hicn_name_copy_prefix_to_destination (u8 *dst, const hicn_name_t *name)
+{
+ int v4 = _is_inet4 (name);
+ const u8 *src = (u8 *) (v4 * (intptr_t) (name->prefix.v4.as_u8) +
+ (1 - v4) * (intptr_t) (name->prefix.v6.as_u8));
+ size_t size = v4 * IPV4_ADDR_LEN + (1 - v4) * IPV6_ADDR_LEN;
+ memcpy (dst, src, size);
- // Sanity check
- if (len1 != len2)
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ return HICN_LIB_ERROR_NONE;
+}
- int ret1 = memcmp ((u8 *) buffer11, (u8 *) buffer21, len1);
+int
+hicn_name_set_suffix (hicn_name_t *name, hicn_name_suffix_t suffix)
+{
+ name->suffix = suffix;
+ return HICN_LIB_ERROR_NONE;
+}
- if (!consider_segment)
+int
+hicn_name_to_sockaddr_address (const hicn_name_t *name,
+ struct sockaddr *ip_address)
+{
+ struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) ip_address;
+ struct sockaddr_in *tmp4 = (struct sockaddr_in *) ip_address;
+
+ assert (!_is_unspec (name));
+
+ if (_is_inet4 (name))
+ {
+ tmp4->sin_family = AF_INET;
+ tmp4->sin_port = DUMMY_PORT;
+ memcpy (&tmp4->sin_addr, &name->prefix.v4, IPV4_ADDR_LEN);
+ }
+ else
{
- return ret1;
+ tmp6->sin6_family = AF_INET6;
+ tmp6->sin6_scope_id = 0;
+ tmp6->sin6_port = DUMMY_PORT;
+ memcpy (&tmp6->sin6_addr, &name->prefix.v6, IPV6_ADDR_LEN);
}
- int ret2 = memcmp ((u8 *) buffer12, (u8 *) buffer22, HICN_SEGMENT_LEN);
-
- return ret1 || ret2;
+ return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix)
+hicn_name_to_hicn_ip_prefix (const hicn_name_t *name, hicn_ip_prefix_t *prefix)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V4:
- *hash = hash32 (name->buffer, consider_suffix ? HICN_V4_NAME_LEN : HICN_V4_PREFIX_LEN);
- break;
- case HNT_CONTIGUOUS_V6:
- *hash = hash32 (name->buffer, consider_suffix ? HICN_V6_NAME_LEN : HICN_V6_PREFIX_LEN);
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- *hash =
- hash32 (name->iov.buffers[0].iov_base, name->iov.buffers[0].iov_len);
- if (consider_suffix)
- {
- *hash = cumulative_hash32 (name->iov.buffers[1].iov_base,
- name->iov.buffers[1].iov_len, *hash);
- }
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
-
+ int family, rc;
+ rc = hicn_name_get_family (name, &family);
+ if (rc)
+ return rc;
+
+ prefix->family = family;
+ prefix->address.v6.as_u64[0] = name->prefix.v6.as_u64[0];
+ prefix->address.v6.as_u64[1] = name->prefix.v6.as_u64[1];
+ prefix->len = 128;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_empty (hicn_name_t * name)
+hicn_name_get_seq_number (const hicn_name_t *name, u32 *seq_number)
{
- return name->type == HNT_UNSPEC ? 1 : 0;
+ *seq_number = name->suffix;
+ return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_copy (hicn_name_t * dst, const hicn_name_t * src)
+hicn_name_ntop (const hicn_name_t *src, char *dst, size_t len)
{
- switch (src->type)
+ int offset;
+ const char *rc = NULL;
+ int v4 = _is_inet4 (src);
+ const u8 *addr = (u8 *) (v4 * (intptr_t) src->prefix.v4.as_u8 +
+ (1 - v4) * (intptr_t) src->prefix.v6.as_u8);
+ int family = v4 * AF_INET + (1 - v4) * AF_INET6;
+ rc = inet_ntop (family, addr, dst, (socklen_t) len);
+
+ if (!rc)
{
- case HNT_CONTIGUOUS_V4:
- case HNT_CONTIGUOUS_V6:
- *dst = *src;
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- dst->type =
- src->type == HNT_IOV_V4 ? HNT_CONTIGUOUS_V4 : HNT_CONTIGUOUS_V6;
- memcpy (dst->buffer, src->iov.buffers[0].iov_base,
- src->iov.buffers[0].iov_len);
- memcpy (dst->buffer + src->iov.buffers[0].iov_len,
- src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len);
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ return HICN_LIB_ERROR_UNSPECIFIED;
}
+ offset = (int) strnlen_s (dst, len);
+ dst[offset] = '|';
+
+ snprintf (dst + offset + 1, len - offset - 1, "%lu",
+ (unsigned long) (src->suffix));
+
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_copy_to_destination (u8 * dst, const hicn_name_t * src,
- bool copy_suffix)
+hicn_name_pton (const char *src, hicn_name_t *dst)
{
- size_t length;
+ return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+}
- switch (src->type)
- {
- case HNT_CONTIGUOUS_V4:
- if (copy_suffix)
- {
- length = HICN_V4_NAME_LEN;
- }
- else
- {
- length = IPV4_ADDR_LEN;
- }
- memcpy (dst, src->buffer, length);
- break;
- case HNT_CONTIGUOUS_V6:
- if (copy_suffix)
- {
- length = HICN_V6_NAME_LEN;
- }
- else
- {
- length = IPV6_ADDR_LEN;
- }
- memcpy (dst, src->buffer, length);
- break;
- case HNT_IOV_V4:
- case HNT_IOV_V6:
- memcpy (dst, src->iov.buffers[0].iov_base, src->iov.buffers[0].iov_len);
- if (copy_suffix)
- {
- memcpy (dst + src->iov.buffers[0].iov_len,
- src->iov.buffers[1].iov_base, src->iov.buffers[1].iov_len);
- }
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
+int
+hicn_name_get_family (const hicn_name_t *name, int *family)
+{
+ assert (!_is_unspec (name));
+ int v4 = _is_inet4 (name);
+ *family = v4 * AF_INET + (1 - v4) * AF_INET6;
return HICN_LIB_ERROR_NONE;
}
+bool
+hicn_name_is_v4 (const hicn_name_t *name)
+{
+ return _is_inet4 (name);
+}
+
int
-hicn_name_set_seq_number (hicn_name_t * name, u32 seq_number)
+hicn_name_snprintf (char *s, size_t size, const hicn_name_t *name)
{
- u8 *sequence_number = NULL;
+ int n, rc;
+ n = hicn_ip_address_snprintf (s, size, &name->prefix);
+ if (n < 0 || n >= size)
+ return n;
+ rc = snprintf (s + n, size - n, "|%d", name->suffix);
+ if (rc < 0)
+ return rc;
+ return rc + n;
+}
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- sequence_number = name->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- sequence_number = name->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- case HNT_IOV_V4:
- sequence_number = name->iov.buffers[1].iov_base;
- break;
- case HNT_UNSPEC:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+int
+hicn_name_no_suffix_snprintf (char *s, size_t size, const hicn_name_t *name)
+{
+ return hicn_ip_address_snprintf (s, size, &name->prefix);
+}
- if (sequence_number)
- {
- *(u32 *) sequence_number = seq_number;
- }
- else
- {
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+int
+hicn_prefix_create_from_ip_prefix (const hicn_ip_prefix_t *hicn_ip_prefix,
+ hicn_prefix_t *prefix)
+{
+ if (hicn_ip_prefix->family != AF_INET && hicn_ip_prefix->family != AF_INET6)
+ return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
+ prefix->name = hicn_ip_prefix->address;
+ prefix->len = (u8) (hicn_ip_prefix->len);
return HICN_LIB_ERROR_NONE;
}
int
-hicn_name_to_sockaddr_address (const hicn_name_t * name,
- struct sockaddr *ip_address)
+hicn_name_cmp (const hicn_name_t *n1, const hicn_name_t *n2)
{
- struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) ip_address;
- struct sockaddr_in *tmp4 = (struct sockaddr_in *) ip_address;
-
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- tmp6->sin6_family = AF_INET6;
- tmp6->sin6_scope_id = 0;
- tmp6->sin6_port = DUMMY_PORT;
- memcpy (&tmp6->sin6_addr, name->buffer, IPV6_ADDR_LEN);
- break;
- case HNT_IOV_V6:
- tmp6->sin6_family = AF_INET6;
- tmp6->sin6_scope_id = 0;
- tmp6->sin6_port = DUMMY_PORT;
- memcpy (&tmp6->sin6_addr, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- break;
- case HNT_CONTIGUOUS_V4:
- tmp4->sin_family = AF_INET;
- tmp4->sin_port = DUMMY_PORT;
- memcpy (&tmp4->sin_addr, name->buffer, IPV4_ADDR_LEN);
- break;
- case HNT_IOV_V4:
- tmp4->sin_family = AF_INET;
- tmp4->sin_port = DUMMY_PORT;
- memcpy (&tmp4->sin_addr, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ int rc = hicn_ip_address_cmp (&n1->prefix, &n2->prefix);
+ if (rc != 0)
+ return rc;
+ return n2->suffix - n1->suffix;
+}
- return HICN_LIB_ERROR_NONE;
+bool
+hicn_name_equals (const hicn_name_t *n1, const hicn_name_t *n2)
+{
+ return (hicn_name_cmp (n1, n2) == 0);
}
int
-hicn_name_to_ip_prefix (const hicn_name_t * name, ip_prefix_t * prefix)
+hicn_prefix_create_from_ip_address_len (const hicn_ip_address_t *ip_address,
+ uint8_t len, hicn_prefix_t *prefix)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- memcpy (&prefix->address.v6.buffer, name->buffer, IPV6_ADDR_LEN);
- prefix->family = AF_INET6;
- break;
- case HNT_IOV_V6:
- memcpy (&prefix->address.v6.buffer, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- prefix->family = AF_INET6;
- break;
- case HNT_CONTIGUOUS_V4:
- memcpy (&prefix->address.v4.buffer, name->buffer, IPV4_ADDR_LEN);
- prefix->family = AF_INET;
- break;
- case HNT_IOV_V4:
- memcpy (&prefix->address.v4.buffer, name->iov.buffers[0].iov_base,
- name->iov.buffers[0].iov_len);
- prefix->family = AF_INET;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ prefix->name = *ip_address;
+ prefix->len = len;
return HICN_LIB_ERROR_NONE;
}
+hicn_prefix_t *
+hicn_prefix_dup (const hicn_prefix_t *prefix)
+{
+ hicn_prefix_t *copy = malloc (sizeof (hicn_prefix_t));
+ if (!copy)
+ goto ERR_MALLOC;
+ if (hicn_prefix_copy (copy, prefix) < 0)
+ goto ERR_COPY;
+ return copy;
+
+ERR_COPY:
+ free (copy);
+ERR_MALLOC:
+ return NULL;
+}
+
int
-hicn_name_get_seq_number (const hicn_name_t * name, u32 * seq_number)
+hicn_prefix_copy (hicn_prefix_t *dst, const hicn_prefix_t *src)
{
- const u8 *sequence_number = NULL;
+ dst->name = src->name;
+ dst->len = src->len;
+ return 0;
+}
- switch (name->type)
+bool
+hicn_prefix_is_v4 (const hicn_prefix_t *prefix)
+{
+ return hicn_ip_address_is_v4 (&prefix->name);
+}
+
+/*
+ * The ip address is in network byte order (big endian, msb last) in
+ * hicn_{prefix,name}_t, as in ip_address_t which builds upon struct in*_addr,
+ * But the bits are in host order... so we cannot use builtin functions to get
+ * the position of the first 1 unless we swap bytes as was done previously,
+ * which is costly and non-essential.
+ *
+ *
+ * Example:
+ *
+ * bits | 127 .. 120 | ... | 8 9 10 11 12 13 14 15 | 0 .. 7 |
+ * diff | | ... | 1 0 1 0 0 0 0 0 | |
+ * ^
+ * bit of interest ----------------+
+ */
+
+uint64_t
+_log2_nbo (uint64_t val)
+{
+ assert (val != 0); /* There is at least 1 bit set (network byte order) */
+
+ uint64_t result = 0;
+
+ /* Search for the first 1, starting from left */
+
+ /* The first 32 bits of val are 0 */
+ if (!(val & 0x00000000FFFFFFFF))
{
- case HNT_CONTIGUOUS_V6:
- sequence_number = name->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- sequence_number = name->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- case HNT_IOV_V4:
- sequence_number = name->iov.buffers[1].iov_base;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
+ val = val >> 32;
+ result = result | 32;
}
- if (sequence_number)
+ if (!(val & 0x0000FFFF))
{
- *seq_number = *(u32 *) sequence_number;
+ val = val >> 16;
+ result = result | 16;
}
- else
+
+ if (!(val & 0x00FF))
{
- return HICN_LIB_ERROR_UNEXPECTED;
+ val = val >> 8;
+ result = result | 8;
}
- return HICN_LIB_ERROR_NONE;
+ /* Val now contains the byte with at last 1 bit set (host bit order) */
+ if (val & 0xF0)
+ val = val >> 4;
+ else
+ result = result | 4;
+
+ if (val & 0xC)
+ val = val >> 2;
+ else
+ result = result | 2;
+
+ if (val & 0x2)
+ val = val >> 1;
+ else
+ result = result | 1;
+
+ return result;
}
-int
-hicn_name_ntop (const hicn_name_t * src, char *dst, size_t len)
+uint32_t
+hicn_prefix_lpm (const hicn_prefix_t *p1, const hicn_prefix_t *p2)
{
- int offset;
- const char *rc;
- void *seg_number = NULL;
-
- switch (src->type)
+ uint32_t prefix_len = 0;
+ /* Test each block of 64 bits as a whole */
+ for (unsigned i = 0; i < 2; i++)
{
- case HNT_CONTIGUOUS_V6:
- rc = inet_ntop (AF_INET6, src->buffer, dst, (socklen_t)len);
- seg_number = (u8 *) src->buffer + IPV6_ADDR_LEN;
- break;
- case HNT_CONTIGUOUS_V4:
- rc = inet_ntop (AF_INET, src->buffer, dst, (socklen_t)len);
- seg_number = (u8 *) src->buffer + IPV4_ADDR_LEN;
- break;
- case HNT_IOV_V6:
- rc = inet_ntop (AF_INET6, src->iov.buffers[0].iov_base, dst, (socklen_t)len);
- seg_number = src->iov.buffers[1].iov_base;
- break;
- case HNT_IOV_V4:
- rc = inet_ntop (AF_INET, src->iov.buffers[0].iov_base, dst, (socklen_t)len);
- seg_number = src->iov.buffers[1].iov_base;
- break;
- default:
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
- }
- if (!rc)
- {
- goto ERR;
+ /* Check for differences in the two u64 */
+ uint64_t diff = p1->name.v6.as_u64[i] ^ p2->name.v6.as_u64[i];
+ if (diff)
+ {
+ /*
+ * As the ip_address_t mimics in*_addr and has network byte order
+ * (and host bit order, we cannot directly use 64-bit operations:
+ */
+ prefix_len += _log2_nbo (diff);
+ break;
+ }
+ prefix_len += 8 * sizeof (uint64_t);
}
- offset = (int) strlen (dst);
- dst[offset] = '|';
-
- sprintf (dst + offset + 1, "%lu", (unsigned long) (*(u32 *) seg_number));
-
- return HICN_LIB_ERROR_NONE;
+ /* Bound the returned prefix length by the length of all input */
+ return MIN (prefix_len,
+ MIN (hicn_prefix_get_len (p1), hicn_prefix_get_len (p2)));
+}
-ERR:
- return HICN_LIB_ERROR_UNSPECIFIED;
+void
+hicn_prefix_clear (hicn_prefix_t *prefix, uint8_t start_from)
+{
+ uint8_t *buffer = prefix->name.v6.as_u8;
+
+ /* Compute the offset of the byte from which to clear the name... */
+ uint8_t offset = start_from / 8;
+ if (hicn_prefix_is_v4 (prefix))
+ offset += IP_ADDRESS_V4_OFFSET_LEN; /* Ignore padding */
+ /* ... and the position of the first bit to clear */
+ uint8_t pos = start_from % 8;
+
+ /* Mask to clear specific bits at offset...
+ * pos 7 6 5 4 3 2 1 0 (eg. start_from = 19, pos = 3)
+ * mask 0 0 0 0 0 1 1 1 (= 1<<pos - 1)
+ * */
+ uint8_t mask = 0xFF ^ ((1 << (8 - pos)) - 1);
+ buffer[offset] &= mask;
+
+ /* ... then fully clear remaining bytes */
+ for (uint8_t i = offset + 1; i < HICN_PREFIX_MAX_LEN; i++)
+ buffer[i] = 0;
}
-int
-hicn_name_pton (const char *src, hicn_name_t * dst)
+void
+hicn_prefix_truncate (hicn_prefix_t *prefix, uint8_t len)
{
- return HICN_LIB_ERROR_NOT_IMPLEMENTED;
+ hicn_prefix_clear (prefix, len);
+ prefix->len = len;
}
int
-hicn_name_get_family (const hicn_name_t * name, int *family)
+hicn_prefix_cmp (const hicn_prefix_t *p1, const hicn_prefix_t *p2)
{
- switch (name->type)
- {
- case HNT_CONTIGUOUS_V6:
- case HNT_IOV_V6:
- *family = AF_INET6;
- break;
- case HNT_CONTIGUOUS_V4:
- case HNT_IOV_V4:
- *family = AF_INET;
- break;
- default:
- return HICN_LIB_ERROR_UNEXPECTED;
- }
+ if (p1->len != p2->len)
+ return p2->len - p1->len;
+ return hicn_ip_address_cmp (&p1->name, &p2->name);
+}
- return HICN_LIB_ERROR_NONE;
+bool
+hicn_prefix_equals (const hicn_prefix_t *p1, const hicn_prefix_t *p2)
+{
+ return hicn_prefix_cmp (p1, p2) == 0;
}
int
-hicn_prefix_create_from_ip_prefix (const ip_prefix_t * ip_prefix,
- hicn_prefix_t * prefix)
+hicn_prefix_snprintf (char *s, size_t size, const hicn_prefix_t *prefix)
{
- switch (ip_prefix->family)
- {
- case AF_INET:
- prefix->name.ip4.as_u32 = ip_prefix->address.v4.as_u32;
- break;
- case AF_INET6:
- prefix->name.ip6.as_u64[0] = ip_prefix->address.v6.as_u64[0];
- prefix->name.ip6.as_u64[1] = ip_prefix->address.v6.as_u64[1];
- break;
- default:
- return HICN_LIB_ERROR_INVALID_IP_ADDRESS;
- }
- prefix->len = (u8) (ip_prefix->len);
+ hicn_ip_prefix_t ip_prefix = { .family =
+ hicn_ip_address_get_family (&prefix->name),
+ .address = prefix->name,
+ .len = prefix->len };
+ return hicn_ip_prefix_snprintf (s, size, &ip_prefix);
+}
- return HICN_LIB_ERROR_NONE;
+uint8_t
+_hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos)
+{
+ const hicn_ip_address_t *address = hicn_prefix_get_ip_address (prefix);
+ return hicn_ip_address_get_bit (address, pos);
}
-#endif /* ! HICN_VPP_PLUGIN */
+uint8_t
+hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos)
+{
+ assert (pos <= hicn_prefix_get_len (prefix));
+ return _hicn_prefix_get_bit (prefix, pos);
+}
+int
+hicn_prefix_get_ip_prefix (const hicn_prefix_t *prefix,
+ hicn_ip_prefix_t *ip_prefix)
+{
+ *ip_prefix =
+ (hicn_ip_prefix_t){ .family = hicn_ip_address_get_family (&prefix->name),
+ .address = prefix->name,
+ .len = prefix->len };
+ return HICN_LIB_ERROR_NONE;
+}
/*
* fd.io coding-style-patch-verification: ON