RSSI Protocol

RSSI (Reliable Streaming Service Interface) provides reliable, in-order stream delivery over lower layers that are not inherently reliable (for example UDP). Rogue’s RSSI implementation uses sequence/acknowledge exchange, retransmission, timeout handling, and negotiated link parameters to maintain a stable stream. Conceptually, RSSI is based on the Reliable Data Protocol lineage defined by RFC 908 and RFC 1151.

Protocol documentation

The protocol reference links to the relevant RFC background used by RSSI’s reliability model (sequencing, acknowledgments, retransmission, and timeout behavior).

How RSSI classes fit together

The rogue::protocols::rssi classes are layered as follows:

  • Client / Server: convenience wrappers that instantiate and wire the full stack for each role.

  • Controller: the protocol state machine; performs handshake, negotiation, ACK handling, retransmission policy, and flow-control decisions.

  • Transport: lower stream edge carrying RSSI frames to/from the underlying transport link.

  • Application: upper stream edge carrying payload frames to/from application protocols.

  • Header: helper codec/container for parsing and encoding RSSI frame headers.

Typical stream topology:

[Underlying link] <-> Transport <-> Controller <-> Application <-> [Upper protocol]

Python usage example

In most PyRogue applications, RSSI links are created with pyrogue.protocols.UdpRssiPack. This helper bundles UDP socket transport, RSSI protocol endpoints, and packetizer wiring into a single object. It is implemented as a pyrogue.Device, so RSSI link/status variables are exposed directly in the PyRogue tree. For wrapper details, see Network Wrapper. For typical FPGA-facing links, instantiate it in client mode (server=False).

import pyrogue as pr
import pyrogue.protocols
import rogue.protocols.srp

class MyRoot(pr.Root):
    def __init__(self):
        super().__init__(name='MyRoot')

        self.add(pyrogue.protocols.UdpRssiPack(
            name='Net',
            server=False,
            host='10.0.0.5',
            port=8192,
            jumbo=True,
            packVer=2,
            enSsi=True,
        ))
        self.addInterface(self.Net)

        srp = rogue.protocols.srp.SrpV3()
        self.Net.application(dest=0) == srp

        # Example device using SRP as memBase
        # self.add(MyDevice(name='Dev', offset=0x0, memBase=srp))

For advanced debugging or custom wiring, you can still instantiate each layer explicitly. The following pattern is used in wrappers such as python/pyrogue/protocols/_Network.py:

import rogue.protocols.udp
import rogue.protocols.rssi
import rogue.protocols.packetizer

# Server side
s_udp = rogue.protocols.udp.Server(0, True)
s_rssi = rogue.protocols.rssi.Server(s_udp.maxPayload() - 8)
s_pack = rogue.protocols.packetizer.CoreV2(True, True, True)

s_udp == s_rssi.transport()
s_rssi.application() == s_pack.transport()

# Client side
c_udp = rogue.protocols.udp.Client("127.0.0.1", s_udp.port(), True)
c_rssi = rogue.protocols.rssi.Client(c_udp.maxPayload() - 8)
c_pack = rogue.protocols.packetizer.CoreV2(True, True, True)

c_udp == c_rssi.transport()
c_rssi.application() == c_pack.transport()

# Start RSSI state machines (Python binding names)
s_rssi._start()
c_rssi._start()

See also

C++ API details for RSSI protocol classes are documented in RSSI Protocol Class Descriptions.