# nvme-mi-dev **Repository Path**: mirrors_mkj/nvme-mi-dev ## Basic Information - **Project Name**: nvme-mi-dev - **Description**: No description available - **Primary Language**: Unknown - **License**: GPL-3.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-26 - **Last Updated**: 2026-01-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # nvme-mi-dev nvme-mi-dev provides the jigsaw pieces for modelling NVMe devices that can be inspected via NVMe-MI. Initial integrations expose the NVMe-MI endpoint using [mctp-dev](https://github.com/CodeConstruct/mctp-dev/). ## Integration As an example by way of implementation, a test setup that was used for mctp-dev creates two namespaces in a subsystem with one controller, one PCIe port, and one two-wire port. One of the namespaces is attached to the controller: ```rust use nvme_mi_dev::nvme::{ ManagementEndpoint, PciePort, PortType, Subsystem, SubsystemInfo, TwoWirePort, }; async fn nvme_mi<'a>(router: &'a Router<'a>) -> std::io::Result<()> { let mut l = router.listener(mctp::MCTP_TYPE_NVME)?; let mut subsys = Subsystem::new(SubsystemInfo::environment()); let ppid = subsys .add_port(PortType::Pcie(PciePort::new())) .expect("Unable to create PCIe port"); let ctlrid = subsys .add_controller(ppid) .expect("Unable to create controller"); let nsid = subsys .add_namespace(1024) .expect("Unable to create namespace"); subsys .add_namespace(2048) .expect("Unable to create namespace"); subsys .controller_mut(ctlrid) .attach_namespace(nsid) .unwrap_or_else(|_| panic!("Unable to attach namespace {nsid:?} to controller {ctlrid:?}")); let twpid = subsys .add_port(PortType::TwoWire(TwoWirePort::new())) .expect("Unable to create TwoWire port"); let mut mep = ManagementEndpoint::new(twpid); let mut buf = [0u8; 4224]; loop { let Ok((_typ, ic, msg, resp)) = l.recv(&mut buf).await else { debug!("recv() failed"); continue; }; // Disregard command effects for demonstration purposes let effects = async |_| Ok(()); mep.handle_async(&mut subsys, msg, ic, resp, effects).await; } } ``` The public APIs are largely concerned with modelling the device. Details of MI message (de)serialisation are left to the implementation, which will respond to queries based on the properties of the provided model. ## Building As the NVMe specifications largely relate to hardware specifications and implementations, the model needs some input to customise it to the vendor. The following environment variables can be used at build time: - `NVME_MI_DEV_IEEE_OUI` Must be set in the IEEE RA hexadecimal representation, e.g: ``` export NVME_MI_DEV_IEEE_OUI=ac-de-48 ``` - `NVME_MI_DEV_PCI_VID` - `NVME_MI_DEV_PCI_DID` - `NVME_MI_DEV_PCI_SVID` - `NVME_MI_DEV_PCI_SDID` All must be 16-bit values in base-16 representation, e.g: ``` export NVME_MI_DEV_PCI_VID=ffff export NVME_MI_DEV_PCI_DID=ffff export NVME_MI_DEV_PCI_SVID=ffff export NVME_MI_DEV_PCI_SDID=ffff ``` The example values above are provided as defaults if the variables are not exported in the environment. However, they are not valid identifiers: - The `ac-de-48` OUI is allocated as private and used in documentation examples - The `ffff` PCI ID values represent aborted reads Builds using these values must not be distributed.