Imported from openpmix/openpmix (
src/mca/pnet/nvd/AGENTS.md). Install upstream withnpx skills add openpmix/openpmix --skill nvd. Copyright stays with the author.
AGENTS.md: The PNET nvd Component
nvd is the pnet component for Mellanox / NVIDIA fabric and
networking support. Read the framework AGENTS.md first;
this file covers only what is specific to nvd. It is a near-copy of
opa retargeted at NVIDIA/Mellanox NICs. It builds
in a stock configure and runs on any host whose topology shows a Mellanox
or NVIDIA InfiniBand controller; it was hardwired off in its
configure.m4 until recently (see Building).
Files
| File | Contents |
|---|---|
pnet_nvd.h |
Component struct type + PMIX_PNET_NVD_BLOB / inventory key #defines. |
pnet_nvd_component.c |
Component struct, component_register, component_open (hwloc gate), component_query (priority 10). |
pnet_nvd.c |
The module: allocate / setup_local_network / setup_fork / collect_inventory / deliver_inventory. |
There is deliberately no configure.m4 — see Building.
When it is selected
Selection is a two-step gate mirroring opa:
component_openprobes hwloc twice viapmix_hwloc_check_vendor— first for Mellanox vendor0x15b3, then (on failure) for NVIDIA vendor0x10de— both against PCI class0x207. It opens only if a matching device is found. Themymatch[]table inpnet_nvd.cholds the same two pairs, andsetup_forkandcollect_inventoryboth work from it, so what the component opens for and what it claims cannot drift apart.component_queryreturnspmix_pnet_nvd_moduleat priority 10.
component_open returns whatever pmix_hwloc_check_vendor gave it, and
only PMIX_ERR_NOT_AVAILABLE is the MCA's "silently ignore me" cue — the
helper's other two failures (PMIX_ERR_BAD_PARAM for no topology,
PMIX_ERR_TAKE_NEXT_OPTION for one that did not come from hwloc) would be
reported as a component that failed to open. Neither is reachable as the
server stands: PMIx_server_init runs pmix_hwloc_setup_topology, and
fails outright if it cannot, before it opens this framework.
The module
pmix_pnet_module_t pmix_pnet_nvd_module = {
.name = "nvd",
.allocate = allocate,
.setup_local_network = setup_local_network,
.setup_fork = setup_fork,
.collect_inventory = collect_inventory,
.deliver_inventory = deliver_inventory
};
The signatures match the current framework interface (unlike tcp and
simptest).
What the functions do
-
allocate— likeopa's but envar-only (no security key). It readsPMIX_SETUP_APP_ENVARS/PMIX_SETUP_APP_ALL, harvests envars withpmix_util_harvest_envarsusing the component'sinclude/excludeglobs (default include"UCX_*,HCOLL_*,UCC_*,SHARP_*,NCCL_*"— the UCX/HCOLL/UCC/SHARP/NCCL stacks), packs each asPMIX_ENVAR, wraps the buffer in apmix_kval_tkeyedPMIX_PNET_NVD_BLOB, compresses it, and appends toilist. -
setup_local_network— findsPMIX_PNET_NVD_BLOB, decompresses if needed, unpacks thePMIX_ENVARstream, and appends each tons->envarsfor fork-time injection. (Unlikeopait does not special-case any transport key.) Two things about it are easy to get wrong and are covered bytest/unit/pnet_envar_blob.c; see Gotchas. -
collect_inventory— askspmix_hwloc_check_vendorfor eachmymatch[]pair whether the node carries one of our NICs. It does not yet add anything to the inventory list — the "add this to the inventory" step is a comment — and it answersPMIX_SUCCESSeither way; see Gotchas for why it must. -
setup_fork— names the NICs this one process was mapped against to the libraries that will use them. It askspmix_pnet_base_get_assigned_devices()for the process's devices filtered by the same PCI(vendor, class)pairscomponent_openprobed for, then writes:Variable Value Why that form NCCL_IB_HCAmlx5_0NCCL matches an HCA by name, so the selector goes in as it stands UCX_NET_DEVICESmlx5_0:*UCX names a device port and matches each entry as a glob, so this is "this card, whatever ports it has" without PMIx having to pick one. The :is load-bearing:mlx5_1*would also matchmlx5_10on a node with enough cardsBoth are overwritten if already set: a process mapped against a device made the more specific request, and the names come from the topology as this daemon sees it, so where an RM has already narrowed what the node presents they are a subset of what is visible. A process that was not mapped against one of our NICs is left alone (the helper returns
PMIX_ERR_TAKE_NEXT_OPTION, which the base treats as "nothing to say"). -
deliver_inventory— a stub returningPMIX_SUCCESS.
Building
nvd ships no configure.m4 and builds unconditionally; the MCA
machinery configures a component with no configure.m4 by itself. Keep it
that way. It links nothing and needs no SDK — it reads info attributes
hwloc already recorded and sets environment variables — and whether it has
work to do is a property of the machine the daemon runs on, which only
component_open can know. It previously carried an
AS_IF([test "yes" = "no"], …) gate justified by "no real
NVIDIA-transport detection exists yet", which asked that question at build
time on a host that is routinely not the run host; the one visible
consequence of dropping the file is that configure's summary no longer
prints a Transports / NVIDIA line.
Gotchas
- The unpack loop's terminating status is not a failure. The envar
stream carries no count, so
setup_local_networkunpacks until the buffer runs out and the loop can only end onPMIX_ERR_UNPACK_READ_PAST_END_OF_BUFFER. That has to be turned back intoPMIX_SUCCESSbefore returning: the base treats anything other thanSUCCESS/NOT_AVAILABLE/TAKE_NEXT_OPTIONas a hard error, which stops the fan-out to every pnet component behind us and failsPMIx_server_setup_local_supportfor the whole job.opahas always done this;nvddid not, so the only job it let launch was one whose blob it never found. pmix_compress.decompress()writes nothing when it fails, and the failure is not exotic. A node that built no compression component still receives compressed blobs from a lead server that did, and the base's stub decompressor simply returnsfalse— as does a real one fed a damaged blob. It leaves the output pointer untouched, so its return value must be checked before the result is read or freed. Decline the blob rather than continuing.bktmust never be destructed.PMIX_LOAD_BUFFER_NON_DESTRUCTparks a borrowed pointer in the buffer — either the info's own byte object or the block the decompressor allocated, which this function frees itself. Destructing the buffer would free it a second time.allocatehands the payload over exactly once.PMIX_UNLOAD_BUFFERtransfers the packed bytes to apmix_byte_object_twithout freeing anything, so when compression succeeds — and thepmix_kval_ttherefore owns the compressed copy — the uncompressed block has to be freed by hand.pgpu/{nvd,intel}andpnet/opaall do this.collect_inventoryreports presence but not contents. It confirms a matching NIC exists but does not populate inventory; treat inventory support as unfinished.- Any error out of
collect_inventoryaborts the whole fan-out. Unlikeallocate/setup_fork, the base has no decline convention there: itPMIX_ERROR_LOGs a non-SUCCESSreturn and stops, so the other components' inventory never gets collected. This is why "no matching NIC" answersPMIX_SUCCESShere rather thanTAKE_NEXT_OPTION. ThePMIX_ERR_NOT_SUPPORTEDguard on a non-hwloc topology is defensive only —component_openalready ranpmix_hwloc_check_vendor, which applies the same source check and must have passed for this module to be active at all. - The envar-glob defaults are the interface to the comms stacks.
UCX_*,HCOLL_*,UCC_*,SHARP_*,NCCL_*are what get forwarded to compute nodes; changing them changes which runtime settings propagate.