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

Metadata

Release files for pymctp-exerciser-qemu 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pymctp-exerciser-qemu 0.3.0
File Size Uploaded Provenance Actions
pymctp_exerciser_qemu-0.3.0.tar.gz 23.4 kB With provenance Details for pymctp_exerciser_qemu-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pymctp-exerciser-qemu 0.3.0
File Interpreter ABI Platform Actions
pymctp_exerciser_qemu-0.3.0-py3-none-any.whl Python 3 none any Details for pymctp_exerciser_qemu-0.3.0-py3-none-any.whl

Total release size: 55.8 kB

Release files / pymctp_exerciser_qemu-0.3.0.tar.gz

Download URL pymctp_exerciser_qemu-0.3.0.tar.gz
Size 23.4 kB
Tags Source
SHA-256 checksum
How to use checksums
bb88ee76d785804f115a353ec01fb6a7ed7267ab63eb054c98776d575b655640
BLAKE2b-256 checksum
How to use checksums
664b672b8779dfd25566ea75cf8ba50cf94fb351ed81b2fa9d5ac9183cc25aaa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 19, 2026.

Transparency log

Release files / pymctp_exerciser_qemu-0.3.0-py3-none-any.whl

Download URL pymctp_exerciser_qemu-0.3.0-py3-none-any.whl
Size 32.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8932b861392ac784d26fdf2c95910684e254344f2848f96e8fe54ddc601f1ede
BLAKE2b-256 checksum
How to use checksums
f81fdc7302232d721439b73af43ab61a39d5c4ab786dd21c3eff6d555fff1fe3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 19, 2026.

Transparency log

Security for pymctp-exerciser-qemu 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pymctp_exerciser_qemu-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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