fi_provider(3)

πŸ’… fi_provider(3) β€” the Libfabric manual page, but make it make sense πŸ¦‹

okay bestie, so this is a page from the Libfabric programmer's manual β€” it's the provider-side API, the backstage pass stuff ✨ β€” and it is a lot, but we're gonna get through it together. grab a strawberry drink πŸ“ and let's go.


✨ NAME ✨

fi_prov_ini β€” the external provider entry point (like, the front door of a provider, no cap πŸšͺ)

fi_param_define / fi_param_get β€” register and retrieve environment variables with the libfabric core πŸ”§

fi_log_enabled / fi_log_ready / fi_log β€” control and output debug logging information πŸ“

fi_open / fi_import / fi_close β€” open and import a named library object πŸ“¦

fi_import_log β€” import new logging callbacks πŸͺ΅


🌸 SYNOPSIS 🌸

#include <rdma/fabric.h>
#include <rdma/prov/fi_prov.h>

struct fi_provider* fi_prov_ini(void);

int fi_param_define(const struct fi_provider *provider, const char *param_name,
    enum fi_param_type type, const char *help_string_fmt, ...);

int fi_param_get_str(struct fi_provider *provider, const char *param_name,
    char **value);

int fi_param_get_int(struct fi_provider *provider, const char *param_name,
    int *value);

int fi_param_get_bool(struct fi_provider *provider, const char *param_name,
    int *value);

int fi_param_get_size_t(struct fi_provider *provider, const char *param_name,
    size_t *value);

#include <rdma/fabric.h>
#include <rdma/prov/fi_prov.h>
#include <rdma/prov/fi_log.h>

int fi_log_enabled(const struct fi_provider *prov, enum fi_log_level level,
    enum fi_log_subsys subsys);

int fi_log_ready(const struct fi_provider *prov, enum fi_log_level level,
    enum fi_log_subsys subsys, uint64_t *showtime);

void fi_log(const struct fi_provider *prov, enum fi_log_level level,
    enum fi_log_subsys subsys, const char *func, int line,
    const char *fmt, ...);

#include <rdma/fabric.h>

int fi_open(uint32_t version, const char *name, void *attr,
    size_t attr_len, uint64_t flags, struct fid **fid, void *context);

static inline int fi_import(uint32_t version, const char *name, void *attr,
                size_t attr_len, uint64_t flags, struct fid *fid,
                void *context);

int fi_close(struct fid *fid);

#include <rdma/fabric.h>
#include <rdma/fi_ext.h>

static inline int fi_import_log(uint32_t version, uint64_t flags,
                struct fid_logging *log_fid);

πŸŽ€ ARGUMENTS πŸŽ€

  • provider β€” a reference to the provider. the provider in question. that one 🫢
  • version β€” the API version the application is requesting.
  • name β€” the well-known name of the library object you wanna open.
  • attr β€” optional attributes of the object to open.
  • attr_len β€” the size of any attribute structure passed to fi_open. should be 0 if no attributes are given, bestie, don't be out here lying about your struct size 😭
  • fid β€” the returned fabric identifier for the opened object.

πŸ¦‹ DESCRIPTION πŸ¦‹

so a fabric provider implements the application-facing software interfaces you need to actually reach network-specific protocols, drivers, and hardware. the interfaces and structures defined by this man page are exported by the libfabric library β€” BUT they're targeted at provider implementations, not at most applications using them directly. it's giving "for internal use only" energy πŸ’…

Integrated providers are the ones built directly into the libfabric library itself. External providers get loaded dynamically by libfabric at initialization time. external providers must live in a standard library path, or in the libfabric library search path as specified by an environment variable. also β€” non-negotiable β€” external providers must be named with the suffix -fi.so at the end of the name. like, that's the whole dress code πŸ‘‘

Named objects are special purpose resources that applications can access directly. they may be used to enhance or modify the behavior of the library core. for the deets, see the fi_open call below πŸ‘‡

🌈 fi_prov_ini

this entry point must be defined by external providers, periodt. on loading, libfabric will invoke fi_prov_ini() to retrieve the provider's fi_provider structure. any additional interactions between the libfabric core and the provider go through the interfaces defined by that struct. mutuals only 🀝

🌈 fi_param_define

defines a configuration parameter for use by a specified provider. the help_string and param_name arguments must be non-NULL β€” and help_string must additionally be non-empty, no slacking 🚫. they're copied internally, so you may free them after calling fi_param_define. ugh, so considerate πŸ’–

🌈 fi_param_get

gets the value of a configuration parameter that was previously defined using fi_param_define(). the value comes from the environment variable name of the form FI__, all converted to upper case. (yes, that's the pattern, exactly as written, don't @ me)

here's the vibe check on return values:

  • if the parameter was previously defined and the user set a value β†’ FI_SUCCESS is returned and (*value) points to the retrieved value ✨
  • if the parameter name was previously defined, but the user did not set a value β†’ -FI_ENODATA is returned and the value of (*value) is unchanged πŸ™ˆ
  • if the parameter name was not previously defined via fi_param_define() β†’ -FI_ENOENT is returned and the value of (*value) is unchanged πŸ’€
  • if the value in the environment is not valid for the parameter type β†’ -FI_EINVAL is returned and the value of (*value) is unchanged 🚩

🌈 fi_log_enabled / fi_log_ready / fi_log

these functions control debug and informational logging output πŸ“Š. providers typically access these functions through the FI_LOG and related macros in fi_log.h and do not call these functions directly. so like, don't come for them directly, go through the macros, iykyk 🧚

🌈 fi_open

open a library resource using a well-known name. this feature gives applications and providers a mechanism that can be used to modify or enhance core library services and behavior. the details are specific based on the requested object name. most applications will not need this level of control β€” it's main character energy for providers only πŸ‘‘

the library API version known to the application should be provided through the version parameter. the use of attributes is object dependent. if required, attributes should be provided through the attr parameter, with attr_len set to the size of the referenced attribute structure. here's the list of published names, plus what service or resource each one corresponds to:

  • mr_cache β€” the mr_cache object references the internal memory registration cache used by the different providers. more info on the cache lives in the fi_mr(3) man page πŸ—‚οΈ
  • logging β€” the logging object references the internal logging subsystem used by the different providers. once opened, custom logging callbacks may be installed. can be opened only once, and only the last import is used if imported multiple times. one (1) opening, that's the rule 🚨

🌈 fi_import

this helper function is a combination of fi_open and fi_import_fid. it may be used to import a fabric object created and owned by the libfabric user. this lets the upper level libraries or the application override or define low-level libfabric behavior. so powerful, honestly 🫢

🌈 fi_import_log

helper function to override the low-level libfabric's logging system with new callback functions πŸͺ΅βœ¨

struct fi_ops_log {
    size_t size;
    int (*enabled)(const struct fi_provider *prov, enum fi_log_level level,
               enum fi_log_subsys subsys, uint64_t flags);
    int (*ready)(const struct fi_provider *prov, enum fi_log_level level,
             enum fi_log_subsys subsys, uint64_t flags, uint64_t *showtime);
    void (*log)(const struct fi_provider *prov, enum fi_log_level level,
            enum fi_log_subsys subsys, const char *func, int line,
            const char *msg);
};

struct fid_logging {
    struct fid          fid;
    struct fi_ops_log   *ops;
};

πŸ‘‘ PROVIDER INTERFACE πŸ‘‘

the fi_provider structure defines entry points for the libfabric core to use to access the provider. every other call into a provider goes through function pointers associated with allocated objects. indirect kings πŸ‘‘

struct fi_provider {
    uint32_t version;
    uint32_t fi_version;
    struct fi_context context;
    const char *name;
    int (*getinfo)(uint32_t version, const char *node, const char *service,
            uint64_t flags, const struct fi_info *hints,
            struct fi_info **info);
    int (*fabric)(struct fi_fabric_attr *attr, struct fid_fabric **fabric,
            void *context);
    void    (*cleanup)(void);
};

πŸ’œ version

the provider version. for providers integrated with the library, this is often the same as the library version. twinning! πŸ‘―

πŸ’œ fi_version

the library interface version that the provider was implemented against. the provider's fi_version must be greater than or equal to an application's requested API version for the application to use the provider πŸ”₯. it is a provider's responsibility to support older versions of the API if it wishes to support legacy applications. for integrated providers


⭐ RETURN VALUE ⭐

returns FI_SUCCESS on success πŸŽ‰. on error, a negative value corresponding to fabric errno is returned. fabric errno values are defined in rdma/fi_errno.h.


πŸ” SEE ALSO πŸ”

fabric(7), fi_getinfo(3) fi_mr(3),


πŸ’€ AUTHORS πŸ’€

OpenFabrics.


okay that's the whole page, you ate that fr fr πŸ“βœ¨ signing off β€” this was Libfabric v2.5.1, dated 2024-12-10, from the Libfabric Programmer's Manual. mwah, go touch some grass, then go read fabric(7) πŸ’œπŸ¦‹

πŸ“¦ where this page comes from