Skip to main content

pymctp-exerciser-qemu

QEMU I2C and I3C exerciser support for pymctp.

This package provides exerciser implementations for interfacing with QEMU's I2C and I3C virtual devices to send and receive MCTP packets in virtualized environments.

Installation

pip install pymctp-exerciser-qemu

Requirements

  • pymctp >= 0.1.0
  • crc8 >= 0.1.0
  • QEMU with I2C/I3C device support

Exercisers Included

QemuI2CNetDevSocket

Interfaces with QEMU I2C devices via network sockets.

from pymctp.exerciser import get_exerciser

QemuI2CSocket = get_exerciser('qemu-i2c')
socket = QemuI2CSocket(
    host='localhost',
    port=5555,
    addr=0x20
)

QemuI3CCharDevSocket

Interfaces with QEMU I3C devices via character devices.

from pymctp.exerciser import get_exerciser

QemuI3CSocket = get_exerciser('qemu-i3c')
socket = QemuI3CSocket(
    chardev_path='/tmp/i3c-socket',
    addr=0x20
)

QemuI3CStreamSocket / QemuI2CStreamSocket (TCP "remote target" stream)

Interfaces with QEMU's i3c-target-remote / i2c-target-remote "remote target" devices over a single, bidirectional TCP connection per endpoint. This is different from the netdev/netdev2 transports above, which use a pair of UDP ports (in_port/out_port): the stream transports use one TCP port per endpoint, with QEMU listening as the TCP server and PyMCTP connecting as the client. Every message (data, control, and a connect-time HELLO handshake) is framed the same way on the wire:

[u32 length BE][u8 type][body...]

length counts the bytes of type + body. See stream_framing.py for the codec and qemu_i3c_stream.py / qemu_i2c_stream.py for the per-transport message types.

Use these through pymctp.automaton.manager.EndpointManager.from_config with ConfigTypes.I3CStream ("i3c-stream") / ConfigTypes.I2CStream ("i2c-stream"), rather than instantiating the sockets directly:

from pymctp.automaton.manager import ConfigTypes, EndpointManager

# I3CStreamSocketConfig fields: host, port, name, dump_hex=True,
# dump_packet=False, connect_timeout=5.0, pid=0, bcr=0, dcr=0, mwl=0, mrl=0,
# static_addr=0, auto_configure=True (sends SET_REG + HOT_JOIN on connect
# for any non-zero register field).
hcp0_config = {
    "context": {
        "supported_msg_types": [],  # e.g. MsgTypes.CTRL, MsgTypes.PLDM
        "assigned_eid": 38,
    },
    "config": {
        "type": ConfigTypes.I3CStream,
        "host": "localhost",
        "port": 5556,
        "name": "HCP0",
    },
}

# I2CStreamSocketConfig fields: host, port, name, dump_hex=True,
# dump_packet=False, connect_timeout=5.0, master=False, target_address=None.
hsp1_config = {
    "context": {
        "physical_address": {"address": 0xB0 >> 1},
        "supported_msg_types": [],  # e.g. MsgTypes.CTRL, MsgTypes.PLDM
        "assigned_eid": 34,
    },
    "config": {
        "type": ConfigTypes.I2CStream,
        "host": "localhost",
        "port": 5570,
        "name": "HSP1",
    },
}

hcp0 = EndpointManager.from_config(hcp0_config)
hsp1 = EndpointManager.from_config(hsp1_config)

By default (master=False), the socket speaks the slave/target model described above: WRITE frames are dispatched as parsed SmbusTransportPackets, and outbound data is buffered until a READ_REQ arrives (see qemu_i2c_stream.py).

Setting master=True instead speaks QEMU's i2c-target-remote master mode (peer-as-master / multi-master, mirroring the old UDP i2c-netdev transport): QEMU masters the (virtual) I2C bus on our behalf, so there is no READ_REQ/READ_RSP turn-around — every WRITE frame is address-prefixed instead:

WRITE (0x00) body := [addr_byte][data...]
addr_byte        := (i2c_7bit_address << 1) | 0   # write, no R/W bit set
  • send() (peer -> QEMU) prefixes the outgoing SMBus/MCTP bytes with target_address (the BMC-side SMBus address to master-write to, required when master=True) and transmits the WRITE frame immediately.
  • recv() (QEMU -> peer) strips the leading addr_byte (this endpoint's own address, as written to by the BMC mastering the bus) and parses the remainder as a SmbusTransportPacket.
hn_config = {
    "context": {
        "physical_address": {"address": 0x10},
        "supported_msg_types": [],  # e.g. MsgTypes.CTRL
        "assigned_eid": 66,
    },
    "config": {
        "type": ConfigTypes.I2CStream,
        "host": "localhost",
        "port": 5574,
        "name": "HN",
        "master": True,
        "target_address": 0x10,
    },
}

hn = EndpointManager.from_config(hn_config)

See docs/examples/l4a40_qemu_stream.py for a complete, runnable example.

QEMU side

QEMU listens (server=on) and PyMCTP connects as the TCP client, one port per endpoint/bus:

-device i3c-target-remote,bus=<bus>,port=<N>,server=on
-device i2c-target-remote,bus=<bus>,address=0x<NN>,port=<N>,server=on

Add master=on to have QEMU master the (virtual) I2C bus on our behalf instead of acting as the slave/target (peer-as-master / multi-master, like the old i2c-netdev transport) — pair this with master=True / target_address=<BMC addr> in the matching I2CStreamSocketConfig:

-device i2c-target-remote,bus=<bus>,address=0x<NN>,port=<N>,server=on,master=on

When QEMU itself runs inside Docker, publish each stream port with its own -p mapping so PyMCTP (running outside the container) can connect, e.g. -p 5556:5556 -p 5570:5570.

Auto-Registration

This package automatically registers exercisers with pymctp when installed, including:

  • qemu-i2c: QemuI2CNetDevSocket
  • qemu-i3c: QemuI3CCharDevSocket
  • qemu-i3c-stream: QemuI3CStreamSocket
  • qemu-i2c-stream: QemuI2CStreamSocket

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymctp_exerciser_qemu-0.3.0.tar.gz (23.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymctp_exerciser_qemu-0.3.0-py3-none-any.whl (32.4 kB view details)

Uploaded Python 3

File details

Details for the file pymctp_exerciser_qemu-0.3.0.tar.gz.

File metadata

  • Download URL: pymctp_exerciser_qemu-0.3.0.tar.gz
  • Upload date:
  • Size: 23.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pymctp_exerciser_qemu-0.3.0.tar.gz
Algorithm Hash digest
SHA256 bb88ee76d785804f115a353ec01fb6a7ed7267ab63eb054c98776d575b655640
MD5 5e406c5621357c1f8db9febe97b9159e
BLAKE2b-256 664b672b8779dfd25566ea75cf8ba50cf94fb351ed81b2fa9d5ac9183cc25aaa

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymctp_exerciser_qemu-0.3.0.tar.gz:

Publisher: publish.yml on jls5177/pymctp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pymctp_exerciser_qemu-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pymctp_exerciser_qemu-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8932b861392ac784d26fdf2c95910684e254344f2848f96e8fe54ddc601f1ede
MD5 c6eef7d08ce65e22676036b2f9cc6827
BLAKE2b-256 f81fdc7302232d721439b73af43ab61a39d5c4ab786dd21c3eff6d555fff1fe3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymctp_exerciser_qemu-0.3.0-py3-none-any.whl:

Publisher: publish.yml on jls5177/pymctp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.8

2 files

0.2.5

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page