diff options
Diffstat (limited to 'src/nvme/util.h')
-rw-r--r-- | src/nvme/util.h | 714 |
1 files changed, 714 insertions, 0 deletions
diff --git a/src/nvme/util.h b/src/nvme/util.h new file mode 100644 index 0000000..517c696 --- /dev/null +++ b/src/nvme/util.h @@ -0,0 +1,714 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * This file is part of libnvme. + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: Keith Busch <keith.busch@wdc.com> + * Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> + */ +#ifndef _LIBNVME_UTIL_H +#define _LIBNVME_UTIL_H + +#include <ifaddrs.h> + +#include "types.h" + +/** + * DOC: util.h + * + * libnvme utility functions + */ + +/** + * enum nvme_connect_err - nvme connect error codes + * @ENVME_CONNECT_RESOLVE: failed to resolve host + * @ENVME_CONNECT_ADDRFAM: unrecognized address family + * @ENVME_CONNECT_TRADDR: failed to get traddr + * @ENVME_CONNECT_TARG: need a transport (-t) argument + * @ENVME_CONNECT_AARG: need a address (-a) argument + * @ENVME_CONNECT_OPEN: failed to open nvme-fabrics device + * @ENVME_CONNECT_WRITE: failed to write to nvme-fabrics device + * @ENVME_CONNECT_READ: failed to read from nvme-fabrics device + * @ENVME_CONNECT_PARSE: failed to parse ctrl info + * @ENVME_CONNECT_INVAL_TR: invalid transport type + * @ENVME_CONNECT_LOOKUP_SUBSYS_NAME: failed to lookup subsystem name + * @ENVME_CONNECT_LOOKUP_SUBSYS: failed to lookup subsystem + * @ENVME_CONNECT_ALREADY: the connect attempt failed, already connected + * @ENVME_CONNECT_INVAL: invalid arguments/configuration + * @ENVME_CONNECT_ADDRINUSE: hostnqn already in use + * @ENVME_CONNECT_NODEV: invalid interface + * @ENVME_CONNECT_OPNOTSUPP: not supported + * @ENVME_CONNECT_CONNREFUSED: connection refused + * @ENVME_CONNECT_ADDRNOTAVAIL: cannot assign requested address + * @ENVME_CONNECT_IGNORED: connect attempt is ignored due to configuration + */ +enum nvme_connect_err { + ENVME_CONNECT_RESOLVE = 1000, + ENVME_CONNECT_ADDRFAM, + ENVME_CONNECT_TRADDR, + ENVME_CONNECT_TARG, + ENVME_CONNECT_AARG, + ENVME_CONNECT_OPEN, + ENVME_CONNECT_WRITE, + ENVME_CONNECT_READ, + ENVME_CONNECT_PARSE, + ENVME_CONNECT_INVAL_TR, + ENVME_CONNECT_LOOKUP_SUBSYS_NAME, + ENVME_CONNECT_LOOKUP_SUBSYS, + ENVME_CONNECT_ALREADY, + ENVME_CONNECT_INVAL, + ENVME_CONNECT_ADDRINUSE, + ENVME_CONNECT_NODEV, + ENVME_CONNECT_OPNOTSUPP, + ENVME_CONNECT_CONNREFUSED, + ENVME_CONNECT_ADDRNOTAVAIL, + ENVME_CONNECT_IGNORED, +}; + +/** + * nvme_status_to_errno() - Converts nvme return status to errno + * @status: Return status from an nvme passthrough command + * @fabrics: Set to true if &status is to a fabrics target. + * + * Return: An errno representing the nvme status if it is an nvme status field, + * or unchanged status is < 0 since errno is already set. + */ +__u8 nvme_status_to_errno(int status, bool fabrics); + +/** + * nvme_status_to_string() - Returns string describing nvme return status. + * @status: Return status from an nvme passthrough command + * @fabrics: Set to true if &status is to a fabrics target. + * + * Return: String representation of the nvme status if it is an nvme status field, + * or a standard errno string if status is < 0. + */ +const char *nvme_status_to_string(int status, bool fabrics); + +/** + * nvme_errno_to_string() - Returns string describing nvme connect failures + * @err: Returned error code from nvme_add_ctrl() + * + * Return: String representation of the nvme connect error codes + */ +const char *nvme_errno_to_string(int err); + +/** + * nvme_init_ctrl_list() - Initialize an nvme_ctrl_list structure from an array. + * @cntlist: The controller list structure to initialize + * @num_ctrls: The number of controllers in the array, &ctrlist. + * @ctrlist: An array of controller identifiers in CPU native endian. + * + * This is intended to be used with any command that takes a controller list + * argument. See nvme_ns_attach_ctrls() and nvme_ns_detach(). + */ +void nvme_init_ctrl_list(struct nvme_ctrl_list *cntlist, __u16 num_ctrls, + __u16 *ctrlist); + +/** + * nvme_init_dsm_range() - Constructs a data set range structure + * @dsm: DSM range array + * @ctx_attrs: Array of context attributes + * @llbas: Array of length in logical blocks + * @slbas: Array of starting logical blocks + * @nr_ranges: The size of the dsm arrays + * + * Each array must be the same size of size 'nr_ranges'. This is intended to be + * used with constructing a payload for nvme_dsm(). + * + * Return: The nvme command status if a response was received or -errno + * otherwise. + */ +void nvme_init_dsm_range(struct nvme_dsm_range *dsm, __u32 *ctx_attrs, + __u32 *llbas, __u64 *slbas, __u16 nr_ranges); + +/** + * nvme_init_copy_range() - Constructs a copy range structure + * @copy: Copy range array + * @nlbs: Number of logical blocks + * @slbas: Starting LBA + * @eilbrts: Expected initial logical block reference tag + * @elbatms: Expected logical block application tag mask + * @elbats: Expected logical block application tag + * @nr: Number of descriptors to construct + */ +void nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs, + __u64 *slbas, __u32 *eilbrts, __u32 *elbatms, + __u32 *elbats, __u16 nr); + +/** + * nvme_init_copy_range_f1() - Constructs a copy range f1 structure + * @copy: Copy range array + * @nlbs: Number of logical blocks + * @slbas: Starting LBA + * @eilbrts: Expected initial logical block reference tag + * @elbatms: Expected logical block application tag mask + * @elbats: Expected logical block application tag + * @nr: Number of descriptors to construct + */ +void nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs, + __u64 *slbas, __u64 *eilbrts, __u32 *elbatms, + __u32 *elbats, __u16 nr); + +/** + * nvme_init_copy_range_f2() - Constructs a copy range f2 structure + * @copy: Copy range array + * @snsids: Source namespace identifier + * @nlbs: Number of logical blocks + * @slbas: Starting LBA + * @sopts: Source options + * @eilbrts: Expected initial logical block reference tag + * @elbatms: Expected logical block application tag mask + * @elbats: Expected logical block application tag + * @nr: Number of descriptors to construct + */ +void nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy, __u32 *snsids, + __u16 *nlbs, __u64 *slbas, __u16 *sopts, + __u32 *eilbrts, __u32 *elbatms, __u32 *elbats, + __u16 nr); + +/** + * nvme_init_copy_range_f3() - Constructs a copy range f3 structure + * @copy: Copy range array + * @snsids: Source namespace identifier + * @nlbs: Number of logical blocks + * @slbas: Starting LBA + * @sopts: Source options + * @eilbrts: Expected initial logical block reference tag + * @elbatms: Expected logical block application tag mask + * @elbats: Expected logical block application tag + * @nr: Number of descriptors to construct + */ +void nvme_init_copy_range_f3(struct nvme_copy_range_f3 *copy, __u32 *snsids, + __u16 *nlbs, __u64 *slbas, __u16 *sopts, + __u64 *eilbrts, __u32 *elbatms, __u32 *elbats, + __u16 nr); + +/** + * nvme_get_feature_length() - Retreive the command payload length for a + * specific feature identifier + * @fid: Feature identifier, see &enum nvme_features_id. + * @cdw11: The cdw11 value may affect the transfer (only known fid is + * %NVME_FEAT_FID_HOST_ID) + * @len: On success, set to this features payload length in bytes. + * + * Return: 0 on success, -1 with errno set to EINVAL if the function did not + * recognize &fid. + */ +int nvme_get_feature_length(int fid, __u32 cdw11, __u32 *len); + +/** + * nvme_get_feature_length2() - Retreive the command payload length for a + * specific feature identifier + * @fid: Feature identifier, see &enum nvme_features_id. + * @cdw11: The cdw11 value may affect the transfer (only known fid is + * %NVME_FEAT_FID_HOST_ID) + * @dir: Data transfer direction: false - host to controller, true - + * controller to host may affect the transfer (only known fid is + * %NVME_FEAT_FID_HOST_MEM_BUF). + * @len: On success, set to this features payload length in bytes. + * + * Return: 0 on success, -1 with errno set to EINVAL if the function did not + * recognize &fid. + */ +int nvme_get_feature_length2(int fid, __u32 cdw11, enum nvme_data_tfr dir, + __u32 *len); + +/** + * nvme_get_directive_receive_length() - Get directive receive length + * @dtype: Directive type, see &enum nvme_directive_dtype + * @doper: Directive receive operation, see &enum nvme_directive_receive_doper + * @len: On success, set to this directives payload length in bytes. + * + * Return: 0 on success, -1 with errno set to EINVAL if the function did not + * recognize &dtype or &doper. + */ +int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, + enum nvme_directive_receive_doper doper, __u32 *len); + +#define NVME_FEAT_ARB_BURST(v) NVME_GET(v, FEAT_ARBITRATION_BURST) +#define NVME_FEAT_ARB_LPW(v) NVME_GET(v, FEAT_ARBITRATION_LPW) +#define NVME_FEAT_ARB_MPW(v) NVME_GET(v, FEAT_ARBITRATION_MPW) +#define NVME_FEAT_ARB_HPW(v) NVME_GET(v, FEAT_ARBITRATION_HPW) + +static inline void nvme_feature_decode_arbitration(__u32 value, __u8 *ab, + __u8 *lpw, __u8 *mpw, + __u8 *hpw) +{ + *ab = NVME_FEAT_ARB_BURST(value); + *lpw = NVME_FEAT_ARB_LPW(value); + *mpw = NVME_FEAT_ARB_MPW(value); + *hpw = NVME_FEAT_ARB_HPW(value); +}; + +#define NVME_FEAT_PM_PS(v) NVME_GET(v, FEAT_PWRMGMT_PS) +#define NVME_FEAT_PM_WH(v) NVME_GET(v, FEAT_PWRMGMT_WH) + +static inline void nvme_feature_decode_power_mgmt(__u32 value, __u8 *ps, + __u8 *wh) +{ + *ps = NVME_FEAT_PM_PS(value); + *wh = NVME_FEAT_PM_WH(value); +} + +#define NVME_FEAT_LBAR_NR(v) NVME_GET(v, FEAT_LBAR_NR) + +static inline void nvme_feature_decode_lba_range(__u32 value, __u8 *num) +{ + *num = NVME_FEAT_LBAR_NR(value); +} + +#define NVME_FEAT_TT_TMPTH(v) NVME_GET(v, FEAT_TT_TMPTH) +#define NVME_FEAT_TT_TMPSEL(v) NVME_GET(v, FEAT_TT_TMPSEL) +#define NVME_FEAT_TT_THSEL(v) NVME_GET(v, FEAT_TT_THSEL) + +static inline void nvme_feature_decode_temp_threshold(__u32 value, __u16 *tmpth, + __u8 *tmpsel, __u8 *thsel) +{ + *tmpth = NVME_FEAT_TT_TMPTH(value); + *tmpsel = NVME_FEAT_TT_TMPSEL(value); + *thsel = NVME_FEAT_TT_THSEL(value); +} + +#define NVME_FEAT_ER_TLER(v) NVME_GET(v, FEAT_ERROR_RECOVERY_TLER) +#define NVME_FEAT_ER_DULBE(v) NVME_GET(v, FEAT_ERROR_RECOVERY_DULBE) + +static inline void nvme_feature_decode_error_recovery(__u32 value, __u16 *tler, + bool *dulbe) +{ + *tler = NVME_FEAT_ER_TLER(value); + *dulbe = NVME_FEAT_ER_DULBE(value); +} + +#define NVME_FEAT_VWC_WCE(v) NVME_GET(v, FEAT_VWC_WCE) + +static inline void nvme_feature_decode_volatile_write_cache(__u32 value, + bool *wce) +{ + *wce = NVME_FEAT_VWC_WCE(value); +} + +#define NVME_FEAT_NRQS_NSQR(v) NVME_GET(v, FEAT_NRQS_NSQR) +#define NVME_FEAT_NRQS_NCQR(v) NVME_GET(v, FEAT_NRQS_NCQR) + +static inline void nvme_feature_decode_number_of_queues(__u32 value, + __u16 *nsqr, + __u16 *ncqr) +{ + *nsqr = NVME_FEAT_NRQS_NSQR(value); + *ncqr = NVME_FEAT_NRQS_NCQR(value); +} + +#define NVME_FEAT_IRQC_THR(v) NVME_GET(v, FEAT_IRQC_THR) +#define NVME_FEAT_IRQC_TIME(v) NVME_GET(v, FEAT_IRQC_TIME) + +static inline void nvme_feature_decode_interrupt_coalescing(__u32 value, + __u8 *thr, + __u8 *time) +{ + *thr = NVME_FEAT_IRQC_THR(value); + *time = NVME_FEAT_IRQC_TIME(value); +} + +#define NVME_FEAT_ICFG_IV(v) NVME_GET(v, FEAT_ICFG_IV) +#define NVME_FEAT_ICFG_CD(v) NVME_GET(v, FEAT_ICFG_CD) + +static inline void nvme_feature_decode_interrupt_config(__u32 value, __u16 *iv, + bool *cd) +{ + *iv = NVME_FEAT_ICFG_IV(value); + *cd = NVME_FEAT_ICFG_CD(value); +} + +#define NVME_FEAT_WA_DN(v) NVME_GET(v, FEAT_WA_DN) + +static inline void nvme_feature_decode_write_atomicity(__u32 value, bool *dn) +{ + *dn = NVME_FEAT_WA_DN(value); +} + +#define NVME_FEAT_AE_SMART(v) NVME_GET(v, FEAT_AE_SMART) +#define NVME_FEAT_AE_NAN(v) NVME_GET(v, FEAT_AE_NAN) +#define NVME_FEAT_AE_FW(v) NVME_GET(v, FEAT_AE_FW) +#define NVME_FEAT_AE_TELEM(v) NVME_GET(v, FEAT_AE_TELEM) +#define NVME_FEAT_AE_ANA(v) NVME_GET(v, FEAT_AE_ANA) +#define NVME_FEAT_AE_PLA(v) NVME_GET(v, FEAT_AE_PLA) +#define NVME_FEAT_AE_LBAS(v) NVME_GET(v, FEAT_AE_LBAS) +#define NVME_FEAT_AE_EGA(v) NVME_GET(v, FEAT_AE_EGA) + +static inline void nvme_feature_decode_async_event_config(__u32 value, + __u8 *smart, bool *nan, bool *fw, bool *telem, + bool *ana, bool *pla, bool *lbas, bool *ega) +{ + *smart = NVME_FEAT_AE_SMART(value); + *nan = NVME_FEAT_AE_NAN(value); + *fw = NVME_FEAT_AE_FW(value); + *telem = NVME_FEAT_AE_TELEM(value); + *ana = NVME_FEAT_AE_ANA(value); + *pla = NVME_FEAT_AE_PLA(value); + *lbas = NVME_FEAT_AE_LBAS(value); + *ega = NVME_FEAT_AE_EGA(value); +} + +#define NVME_FEAT_APST_APSTE(v) NVME_GET(v, FEAT_APST_APSTE) + +static inline void nvme_feature_decode_auto_power_state(__u32 value, + bool *apste) +{ + *apste = NVME_FEAT_APST_APSTE(value); +} + +#define NVME_FEAT_HMEM_EHM(v) NVME_GET(v, FEAT_HMEM_EHM) + +static inline void nvme_feature_decode_host_memory_buffer(__u32 value, bool *ehm) +{ + *ehm = NVME_FEAT_HMEM_EHM(value); +} + +#define NVME_FEAT_HCTM_TMT2(v) NVME_GET(v, FEAT_HCTM_TMT2) +#define NVME_FEAT_HCTM_TMT1(v) NVME_GET(v, FEAT_HCTM_TMT1) + +static inline void nvme_feature_decode_host_thermal_mgmt(__u32 value, + __u16 *tmt2, + __u16 *tmt1) +{ + *tmt2 = NVME_FEAT_HCTM_TMT2(value); + *tmt1 = NVME_FEAT_HCTM_TMT1(value); +} + +#define NVME_FEAT_NOPS_NOPPME(v) NVME_GET(v, FEAT_NOPS_NOPPME) + +static inline void nvme_feature_decode_non_op_power_config(__u32 value, + bool *noppme) +{ + *noppme = NVME_FEAT_NOPS_NOPPME(value); +} + +#define NVME_FEAT_RRL_RRL(v) NVME_GET(v, FEAT_RRL_RRL) + +static inline void nvme_feature_decode_read_recovery_level_config(__u32 value, + __u8 *rrl) +{ + *rrl = NVME_FEAT_RRL_RRL(value); +} + +#define NVME_FEAT_PLM_PLME(v) NVME_GET(v, FEAT_PLM_PLME) + +static inline void nvme_feature_decode_predictable_latency_mode_config(__u32 value, + bool *plme) +{ + *plme = NVME_FEAT_PLM_PLME(value); +} + +#define NVME_FEAT_PLMW_WS(v) NVME_GET(v, FEAT_PLMW_WS) + +static inline void nvme_feature_decode_predictable_latency_mode_window(__u32 value, + __u8 *ws) +{ + *ws = NVME_FEAT_PLMW_WS(value); +} + +#define NVME_FEAT_LBAS_LSIRI(v) NVME_GET(v, FEAT_LBAS_LSIRI) +#define NVME_FEAT_LBAS_LSIPI(v) NVME_GET(v, FEAT_LBAS_LSIPI) + +static inline void nvme_feature_decode_lba_status_attributes(__u32 value, + __u16 *lsiri, + __u16 *lsipi) +{ + *lsiri = NVME_FEAT_LBAS_LSIRI(value); + *lsipi = NVME_FEAT_LBAS_LSIPI(value); +} + +#define NVME_FEAT_SC_NODRM(v) NVME_GET(v, FEAT_SC_NODRM) + +static inline void nvme_feature_decode_sanitize_config(__u32 value, bool *nodrm) +{ + *nodrm = NVME_FEAT_SC_NODRM(value); +} + +#define NVME_FEAT_EG_ENDGID(v) NVME_GET(v, FEAT_EG_ENDGID) +#define NVME_FEAT_EG_EGCW(v) NVME_GET(v, FEAT_EG_EGCW) + +static inline void nvme_feature_decode_endurance_group_event_config(__u32 value, + __u16 *endgid, __u8 *endgcw) +{ + *endgid = NVME_FEAT_EG_ENDGID(value); + *endgcw = NVME_FEAT_EG_EGCW(value); +} + +#define NVME_FEAT_SPM_PBSLC(v) NVME_GET(v, FEAT_SPM_PBSLC) + +static inline void nvme_feature_decode_software_progress_marker(__u32 value, + __u8 *pbslc) +{ + *pbslc = NVME_FEAT_SPM_PBSLC(value); +} + +#define NVME_FEAT_HOSTID_EXHID(v) NVME_GET(v, FEAT_HOSTID_EXHID) + +static inline void nvme_feature_decode_host_identifier(__u32 value, bool *exhid) +{ + *exhid = NVME_FEAT_HOSTID_EXHID(value); +} + +#define NVME_FEAT_RM_REGPRE(v) NVME_GET(v, FEAT_RM_REGPRE) +#define NVME_FEAT_RM_RESREL(v) NVME_GET(v, FEAT_RM_RESREL) +#define NVME_FEAT_RM_RESPRE(v) NVME_GET(v, FEAT_RM_RESPRE) + +static inline void nvme_feature_decode_reservation_notification(__u32 value, + bool *regpre, + bool *resrel, + bool *respre) +{ + *regpre = NVME_FEAT_RM_REGPRE(value); + *resrel = NVME_FEAT_RM_RESREL(value); + *respre = NVME_FEAT_RM_RESPRE(value); +} + +#define NVME_FEAT_RP_PTPL(v) NVME_GET(v, FEAT_RP_PTPL) + +static inline void nvme_feature_decode_reservation_persistance(__u32 value, + bool *ptpl) +{ + *ptpl = NVME_FEAT_RP_PTPL(value); +} + +#define NVME_FEAT_WP_WPS(v) NVME_GET(v, FEAT_WP_WPS) + +static inline void nvme_feature_decode_namespace_write_protect(__u32 value, + __u8 *wps) +{ + *wps = NVME_FEAT_WP_WPS(value); +} + +static inline void nvme_id_ns_flbas_to_lbaf_inuse(__u8 flbas, __u8 *lbaf_inuse) +{ + *lbaf_inuse = ((NVME_FLBAS_HIGHER(flbas) >> 1) | + NVME_FLBAS_LOWER(flbas)); +} + +struct nvme_root; + +char *hostname2traddr(struct nvme_root *r, const char *traddr); + +/** + * get_entity_name - Get Entity Name (ENAME). + * @buffer: The buffer where the ENAME will be saved as an ASCII string. + * @bufsz: The size of @buffer. + * + * Per TP8010, ENAME is defined as the name associated with the host (i.e. + * hostname). + * + * Return: Number of characters copied to @buffer. + */ +size_t get_entity_name(char *buffer, size_t bufsz); + +/** + * get_entity_version - Get Entity Version (EVER). + * @buffer: The buffer where the EVER will be saved as an ASCII string. + * @bufsz: The size of @buffer. + * + * EVER is defined as the operating system name and version as an ASCII + * string. This function reads different files from the file system and + * builds a string as follows: [os type] [os release] [distro release] + * + * E.g. "Linux 5.17.0-rc1 SLES 15.4" + * + * Return: Number of characters copied to @buffer. + */ +size_t get_entity_version(char *buffer, size_t bufsz); + +/** + * kv_strip - Strip blanks from key value string + * @kv: The key-value string to strip + * + * Strip leading/trailing blanks as well as trailing comments from the + * Key=Value string pointed to by @kv. + * + * Return: A pointer to the stripped string. Note that the original string, + * @kv, gets modified. + */ +char *kv_strip(char *kv); + +/** + * kv_keymatch - Look for key in key value string + * @kv: The key=value string to search for the presence of @key + * @key: The key to look for + * + * Look for @key in the Key=Value pair pointed to by @k and return a + * pointer to the Value if @key is found. + * + * Check if @kv starts with @key. If it does then make sure that we + * have a whole-word match on the @key, and if we do, return a pointer + * to the first character of value (i.e. skip leading spaces, tabs, + * and equal sign) + * + * Return: A pointer to the first character of "value" if a match is found. + * NULL otherwise. + */ +char *kv_keymatch(const char *kv, const char *key); + +/** + * startswith - Checks that a string starts with a given prefix. + * @s: The string to check + * @prefix: A string that @s could be starting with + * + * Return: If @s starts with @prefix, then return a pointer within @s at + * the first character after the matched @prefix. NULL otherwise. + */ +char *startswith(const char *s, const char *prefix); + +#define __round_mask(val, mult) ((__typeof__(val))((mult)-1)) + +/** + * round_up - Round a value @val to the next multiple specified by @mult. + * @val: Value to round + * @mult: Multiple to round to. + * + * usage: int x = round_up(13, sizeof(__u32)); // 13 -> 16 + */ +#define round_up(val, mult) ((((val)-1) | __round_mask((val), (mult)))+1) + +/** + * nvmf_exat_len() - Return length rounded up by 4 + * @val_len: Value length + * + * Return the size in bytes, rounded to a multiple of 4 (e.g., size of + * __u32), of the buffer needed to hold the exat value of size + * @val_len. + * + * Return: Length rounded up by 4 + */ +static inline __u16 nvmf_exat_len(size_t val_len) +{ + return (__u16)round_up(val_len, sizeof(__u32)); +} + +/** + * nvmf_exat_size - Return min aligned size to hold value + * @val_len: This is the length of the data to be copied to the "exatval" + * field of a "struct nvmf_ext_attr". + * + * Return the size of the "struct nvmf_ext_attr" needed to hold + * a value of size @val_len. + * + * Return: The size in bytes, rounded to a multiple of 4 (i.e. size of + * __u32), of the "struct nvmf_ext_attr" required to hold a string of + * length @val_len. + */ +static inline __u16 nvmf_exat_size(size_t val_len) +{ + return (__u16)(sizeof(struct nvmf_ext_attr) + nvmf_exat_len(val_len)); +} + +/** + * nvmf_exat_ptr_next - Increment @p to the next element in the array. + * @p: Pointer to an element of an array of "struct nvmf_ext_attr". + * + * Extended attributes are saved to an array of "struct nvmf_ext_attr" + * where each element of the array is of variable size. In order to + * move to the next element in the array one must increment the + * pointer to the current element (@p) by the size of the current + * element. + * + * Return: Pointer to the next element in the array. + */ +struct nvmf_ext_attr *nvmf_exat_ptr_next(struct nvmf_ext_attr *p); + +/** + * enum nvme_version - Selector for version to be returned by @nvme_get_version + * + * @NVME_VERSION_PROJECT: Project release version + * @NVME_VERSION_GIT: Git reference + */ +enum nvme_version { + NVME_VERSION_PROJECT = 0, + NVME_VERSION_GIT = 1, +}; + +/** + * nvme_get_version - Return version libnvme string + * @type: Selects which version type (see @struct nvme_version) + * + * Return: Returns version string for known types or else "n/a" + */ +const char *nvme_get_version(enum nvme_version type); + +#define NVME_UUID_LEN_STRING 37 /* 1b4e28ba-2fa1-11d2-883f-0016d3cca427 + \0 */ +#define NVME_UUID_LEN 16 + +/** + * nvme_uuid_to_string - Return string represenation of encoded UUID + * @uuid: Binary encoded input UUID + * @str: Output string represenation of UUID + * + * Return: Returns error code if type conversion fails. + */ +int nvme_uuid_to_string(unsigned char uuid[NVME_UUID_LEN], char *str); + +/** + * nvme_uuid_from_string - Return encoded UUID represenation of string UUID + * @uuid: Binary encoded input UUID + * @str: Output string represenation of UUID + * + * Return: Returns error code if type conversion fails. + */ +int nvme_uuid_from_string(const char *str, unsigned char uuid[NVME_UUID_LEN]); + +/** + * nvme_uuid_random - Generate random UUID + * @uuid: Generated random UUID + * + * Generate random number according + * https://www.rfc-editor.org/rfc/rfc4122#section-4.4 + * + * Return: Returns error code if generating of random number fails. + */ +int nvme_uuid_random(unsigned char uuid[NVME_UUID_LEN]); + +/** + * nvme_uuid_find - Find UUID position on UUID list + * @uuid_list: UUID list returned by identify UUID + * @uuid: Binary encoded input UUID + * + * Return: The array position where given UUID is present, or -1 on failure with errno set. + */ +int nvme_uuid_find(struct nvme_id_uuid_list *uuid_list, const unsigned char uuid[NVME_UUID_LEN]); + +/** + * nvme_ipaddrs_eq - Check if 2 IP addresses are equal. + * @addr1: IP address (can be IPv4 or IPv6) + * @addr2: IP address (can be IPv4 or IPv6) + * + * Return: true if addr1 == addr2. false otherwise. + */ +bool nvme_ipaddrs_eq(const char *addr1, const char *addr2); + +/** + * nvme_iface_matching_addr - Get interface matching @addr + * @iface_list: Interface list returned by getifaddrs() + * @addr: Address to match + * + * Parse the interface list pointed to by @iface_list looking + * for the interface that has @addr as one of its assigned + * addresses. + * + * Return: The name of the interface that owns @addr or NULL. + */ +const char *nvme_iface_matching_addr(const struct ifaddrs *iface_list, const char *addr); + +/** + * nvme_iface_primary_addr_matches - Check that interface's primary address matches + * @iface_list: Interface list returned by getifaddrs() + * @iface: Interface to match + * @addr: Address to match + * + * Parse the interface list pointed to by @iface_list and looking for + * interface @iface. The get its primary address and check if it matches + * @addr. + * + * Return: true if a match is found, false otherwise. + */ +bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, const char *iface, const char *addr); + +#endif /* _LIBNVME_UTIL_H */ |