Skip to content

CodeConstruct/nvme-mi-dev

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

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:

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 {:?} to controller {:?}",
                nsid, 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;
        };

        mep.handle_async(&mut subsys, msg, ic, resp).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.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages