Since uuid functions may not be available everywhere, implement uuid functions in DPDK. These are based off the FreeBSD source of libc, without the annoying DCE style function signature.
Signed-off-by: Stephen Hemminger <sthem...@microsoft.com> --- lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_uuid.c | 112 ++++++++++++++++++++ lib/librte_eal/common/include/rte_uuid.h | 129 +++++++++++++++++++++++ lib/librte_eal/common/meson.build | 2 + lib/librte_eal/linuxapp/eal/Makefile | 1 + 6 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eal/common/eal_common_uuid.c create mode 100644 lib/librte_eal/common/include/rte_uuid.h diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile index 3fd33f1e4318..13eafca61243 100644 --- a/lib/librte_eal/bsdapp/eal/Makefile +++ b/lib/librte_eal/bsdapp/eal/Makefile @@ -58,6 +58,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_proc.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_fbarray.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_uuid.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_malloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_elem.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_heap.c diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile index 48f870f24bef..68a680bcb934 100644 --- a/lib/librte_eal/common/Makefile +++ b/lib/librte_eal/common/Makefile @@ -16,7 +16,7 @@ INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h rte_keepalive.h rte_time.h INC += rte_service.h rte_service_component.h INC += rte_bitmap.h rte_vfio.h rte_hypervisor.h rte_test.h -INC += rte_reciprocal.h rte_fbarray.h +INC += rte_reciprocal.h rte_fbarray.h rte_uuid.h GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h GENERIC_INC += rte_spinlock.h rte_memcpy.h rte_cpuflags.h rte_rwlock.h diff --git a/lib/librte_eal/common/eal_common_uuid.c b/lib/librte_eal/common/eal_common_uuid.c new file mode 100644 index 000000000000..1d73a5c4f33c --- /dev/null +++ b/lib/librte_eal/common/eal_common_uuid.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2002,2005 Marcel Moolenaar + * Copyright (c) 2002 Hiten Mahesh Pandya + * All rights reserved. + */ + +#include <stdio.h> +#include <string.h> + +#include <rte_uuid.h> + +static void rte_uuid_create_nil(rte_uuid_t *u) +{ + memset(u, '\0', sizeof(*u)); +} + +/* A macro used to improve the readability of uuid_compare(). */ +#define DIFF_RETURN(a, b, field) do { \ + if ((a)->field != (b)->field) \ + return (((a)->field < (b)->field) ? -1 : 1); \ +} while (0) + +/* + * rte_uuid_compare() - compare two UUIDs. + * + * NOTE: Either UUID can be NULL, meaning a nil UUID. nil UUIDs are smaller + * than any non-nil UUID. + */ +int +rte_uuid_compare(const rte_uuid_t *a, const rte_uuid_t *b) +{ + /* Deal with NULL or equal pointers. */ + if (a == b) + return 0; + + if (a == NULL) + return rte_uuid_is_nil(b) ? 0 : -1; + + if (b == NULL) + return rte_uuid_is_nil(a) ? 0 : 1; + + /* We have to compare the hard way. */ + DIFF_RETURN(a, b, time_low); + DIFF_RETURN(a, b, time_mid); + DIFF_RETURN(a, b, time_hi_and_version); + DIFF_RETURN(a, b, clock_seq_hi_and_reserved); + DIFF_RETURN(a, b, clock_seq_low); + + return memcmp(a->node, b->node, sizeof(a->node)); +} + +int +rte_uuid_from_string(const char *s, rte_uuid_t *u) +{ + int n; + + /* Short-circuit 2 special cases: NULL pointer and empty string. */ + if (s == NULL || *s == '\0') { + rte_uuid_create_nil(u); + return 0; + } + + /* The UUID string representation has a fixed length. */ + if (strlen(s) != 36) + return -1; + + /* + * We only work with "new" UUIDs. New UUIDs have the form: + * 01234567-89ab-cdef-0123-456789abcdef + * The so called "old" UUIDs, which we don't support, have the form: + * 0123456789ab.cd.ef.01.23.45.67.89.ab + */ + if (s[8] != '-') + return -1; + + n = sscanf(s, + "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", + &u->time_low, &u->time_mid, &u->time_hi_and_version, + &u->clock_seq_hi_and_reserved, &u->clock_seq_low, &u->node[0], + &u->node[1], &u->node[2], &u->node[3], &u->node[4], &u->node[5]); + + /* Make sure we have all conversions. */ + if (n != 11) + return -1; + + /* We have a successful scan. Check semantics... */ + n = u->clock_seq_hi_and_reserved; + if ((n & 0x80) != 0x00 && /* variant 0? */ + (n & 0xc0) != 0x80 && /* variant 1? */ + (n & 0xe0) != 0xc0) { /* variant 2? */ + return -1; + } else { + return 0; + } +} + +void +rte_uuid_to_string(const rte_uuid_t *u, char *out, size_t len) +{ + static rte_uuid_t nil; + + if (u == NULL) + u = &nil; + + snprintf(out, len, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + u->time_low, u->time_mid, u->time_hi_and_version, + u->clock_seq_hi_and_reserved, u->clock_seq_low, u->node[0], + u->node[1], u->node[2], u->node[3], u->node[4], u->node[5]); + +} diff --git a/lib/librte_eal/common/include/rte_uuid.h b/lib/librte_eal/common/include/rte_uuid.h new file mode 100644 index 000000000000..ba49b006d3e3 --- /dev/null +++ b/lib/librte_eal/common/include/rte_uuid.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2002,2005 Marcel Moolenaar + * Copyright (c) 2002 Hiten Mahesh Pandya + * All rights reserved. + */ + +/** + * @file + * + * UUID related functions originally from BSD + */ + +#ifndef _RTE_UUID_H_ +#define _RTE_UUID_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stdbool.h> + +#define RTE_UUID_NODE_LEN 6 + +/** + * Struct describing a Universal Unique Identifer + */ +struct rte_uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[RTE_UUID_NODE_LEN]; +}; +typedef struct rte_uuid rte_uuid_t; + +/** + * Helper for defining UUID values for id tables. + */ +#define RTE_UUID_INIT(a, b, c, d, e) { \ + .time_low = (a), \ + .time_mid = (b), \ + .clock_seq_hi_and_reserved = ((d) >> 8 & 0xff), \ + .clock_seq_low = (d) & 0xff, \ + .node = { (e) >> 24 & 0xff, (e) >> 16 & 0xff, \ + (e) >> 8 & 0xff, (e) & 0xff } \ + } + +/** + * Test if UUID is all zeros. + * + * @param u + * The uuid to check. + * @return + * true if uuid is NULL value, false otherwise + */ +static inline bool rte_uuid_is_nil(const rte_uuid_t *u) +{ + const uint32_t *p; + + if (!u) + return true; + + /* + * Pick the largest type that has equivalent alignment constraints + * as an UUID and use it to test if the UUID consists of all zeroes. + */ + p = (const uint32_t *)u; + return (p[0] | p[1] | p[2] | p[3]) == 0; +} + +/** + * Copy a UUID + * + * @param dst + * Pointer to the destination UUID + * @param src + * Pointer to the source UUID + */ +static inline void rte_uuid_copy(rte_uuid_t *dst, const rte_uuid_t *src) +{ + *dst = *src; +} + +/** + * Compare two UUID's + * + * @param a + * Pointer to a UUID to compare + * @param b + * Pointer to a UUID to compare + * @return + * returns an integer less than, equal to, or greater than zero if UUID a is + * is less than, equal, or greater than UUID b. + */ +int rte_uuid_compare(const rte_uuid_t *a, const rte_uuid_t *b); + +/** + * Extract UUID from string + * + * @param in + * Pointer to string of characters to convert + * @param string + * Destination UUID + * @return + * Returns 0 on succes, and -1 if string is not a valid UUID. + */ +int rte_uuid_from_string(const char *in, rte_uuid_t *dst); + +/** + * Convert UUID to string + * + * @param u + * Pointer to UUID to format + * @param out + * Resulting string buffer + * @param len + * Sizeof the available string buffer + */ +#define RTE_UUID_STRLEN (36 + 1) +void rte_uuid_to_string(const rte_uuid_t *u, char *out, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_UUID_H */ diff --git a/lib/librte_eal/common/meson.build b/lib/librte_eal/common/meson.build index 8a3dcfee091b..e184e4d7413d 100644 --- a/lib/librte_eal/common/meson.build +++ b/lib/librte_eal/common/meson.build @@ -25,6 +25,7 @@ common_sources = files( 'eal_common_tailqs.c', 'eal_common_thread.c', 'eal_common_timer.c', + 'eal_common_uuid.c', 'malloc_elem.c', 'malloc_heap.c', 'malloc_mp.c', @@ -75,6 +76,7 @@ common_headers = files( 'include/rte_string_fns.h', 'include/rte_tailq.h', 'include/rte_time.h', + 'include/rte_uuid.h', 'include/rte_version.h') # special case install the generic headers, since they go in a subdir diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile index 3719ec9d7d53..927a80fec907 100644 --- a/lib/librte_eal/linuxapp/eal/Makefile +++ b/lib/librte_eal/linuxapp/eal/Makefile @@ -66,6 +66,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_proc.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_fbarray.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_uuid.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_malloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_elem.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_heap.c -- 2.17.0