Implementing RoCEv2 - #198
Open
Skinbow wants to merge 11 commits into
Open
Conversation
This was referenced Apr 1, 2026
Skinbow
marked this pull request as ready for review
April 7, 2026 10:54
Skinbow
marked this pull request as draft
April 21, 2026 12:23
Author
|
Added new changes (More versatile memory regions) and rebased on master + some minor bug fixes. |
Skinbow
marked this pull request as ready for review
April 29, 2026 15:22
Skinbow
marked this pull request as draft
May 26, 2026 03:12
Skinbow
marked this pull request as ready for review
June 23, 2026 05:48
Skinbow
force-pushed
the
rdma_pr
branch
3 times, most recently
from
August 12, 2026 13:04
4db3994 to
8364246
Compare
Introduces various headers from the RoCEv2 protocol for use in the IBT as well as the MAD layer for CM Adds IBT and MAD-specific sink/source layout descriptions. Adds layouts and constants for send, receive and completion queues. Adds enums representing IBT and MAD opcodes for better readability. Sets RoCEv2-related constants. Adds several helper functions.
RoCEv2 requires the don't fragment flag to be set to 1 in the IP header
Introduces numerous submodules useful for the IBT and the MAD CM
Adds cq.py:
RDMA uses CQ to transmit notifications about request completions to
upper layers.
Adds icrc.py:
Treats the Invariable Cyclic Redundancy Check required by the
IBT. The submodule will need to be placed between UDP and IBT
output and will listen to IP's output to calculate the CRC.
Adds pad.py:
The IBT requires all packets to be aligned to a size of 4 bytes,
and since all IBT headers have a size that is a multiple of 4,
the alignment needs to be insured using the payload's size.
Adds qp.py:
RDMA uses QPs to establish communication. The current
implementation will only allow one generic (RC) and one special
(QP1 UD) QPs to exist.
Adds mr.py:
Memory regions to be handled by QPs.
These submodules are essential for the RDMA implementation as they add a variable timer, specialized fifos (WaitPipe) and a modified packetizer and depacketizer. The variable timer is needed because the CM protocol sets delay times during connection establishment. The packetizer and depacketizer needed changing to accommodate for variable opcode-dependent headers in the IBT and MAD layers. The need for a specialized fifo comes from the need to be able to pipe entire packets and instantly dump them in case of an error.
The MAD CM layer is used for communication establishment and QP configuration. This allows to simplify the client-side API calls through the usage of the libmacm library (a standard in rdma_core). Also adds IPCM, a protocol a layer above CM made specifically for CM through the IP protocol. The CM gives the IPCM the ability to refuse a connection request. The latter also pipes requests private data to upper layers.
The bulk of the logic, the requester and responder are each split into two blocks between reception and transmission. The requester handles requests made by the FPGA's send queue as well as resend logic and checking for response validity. The responder handles requests made by the other machine, checks their validity and responds to them.
Adds the IBT layer of RoCEv2 and connects it to the requester, the responder and MAD CM (through the responder). The validation handles the validity of incoming packets regardless of whether they are a request or a response. The reception dispatches the incoming request to the requester or responder. The transmission alternates between requester and responder and arbitrates their use of the wire.
Adds the entire stack connected together, similar to the UDPIPCore, but with the IBT and MAD CM layers on top.
These are frontend modules that allow to pass a stream to rdma. The key exchanger handles a SEND request that the other machine must send after connection establishment to be able to make requests to its memory regions (it sends multple mrs' r_keys and vas). The streamer then uses the passed keys to alternate its writes and reads between local and remote mrs.
Adds tests for various submodules, as well as the entire RoCEv2 core.
Adding dont_fragment field to the IP packet requires a change in the packet model, which needs to be changed in several tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds RoCEv2 (RDMA over Converged Ethernet v2 with RDMA being Remote Direct Memory Access) functionality to LiteEth.
In particular, this pull request is built to be compliant with the InfiniBand Architecture Specification Volume 1 (Release 1.2.1).
It implements the Transport Layer (Chapter 9) of the InfiniBand protocol as well as the CM (Communication Management) protocol (Chapter 12) and part of the IP CM protocol (Annex A11) for standard connection establishment.
This is done on top of the UDP/IP (similarly to the
LiteEthUDPIPCore) to comply with the Annex 17 - RoCEv2 of the InfiniBand specification.The changes are gathered in the
LiteEthRoCEv2Corewhich includes the RDMA on top of the IP/UDP stack (which remains usable for normal UDP connections through ports other than 4791, which is the IANA assigned port for the RoCEv2 protocol).Both the responder and requester side of the protocol is implemented, meaning that the FPGA can function as the passive or active TCA (Target Channel Adapter) which can have one QP (Queue Pair) in RC (Reliable Connection) mode, as well as a Special QP (QP1) used for CM in UD (Unreliable Datagram) mode.
Only the responder side of the CM protocol is implemented here, so the connection establishment must be done by the other device.
Thus, an HCA (Host Channel Adapter) can establish a connection and send RDMA Read and Write operations, as well as Send operations to this module, and receive acknowledgements as specified in the protocol. Additionally, the module can send RDMA Read and Write requests as well as Send requests, to which the HCA has to respond. This allows existing hardware such as Mellanox ConnectX cards to communicate with the FPGA through the use of Infiniband's Verbs API as well as other calls to the rdma-core library. Regular networking cards can also communicate through RoCEv2 with Software ROCE, also implemented in the rdma-core library.
Note that for the FPGA to be the requester in this connection, for it to send RDMA requests, the HCA has to transfer its memory regions' keys to the FPGA. The way of doing this is not specified in the protocol. The LiteEthKeyExchanger module shows an example of how it can be done.
Tests
This module has been tested using a 1000BASE-T and 1000BASE-LX connection to a Mellanox ConnectX-4 Lx, as well as a regular networking card using Software ROCE.
It can be tested using the test.c script I am sharing through this gist.
Here are some tests results that I obtained with the Mellanox card:
Test of a RDMA_WRITE followed by an RDMA READ on the same memory region (twice):
with the transmission showing in Wireshark:

Benchmarks with RDMA_WRITEs:
Benchmarks with RDMA_READs
Benchmarks with RDMA_READs and RDMA_WRITEs in quick succession:
Related changes
This pull request relies on a couple of changes throughout the LiteX, such as an additional
lastsignal in theLiteDRAMDMAWriterof LiteDRAM's frontend/dma.py (see "Added last signal to LiteDRAMWriter#377").It also relies on a small change to the
Headerclass in LiteX's soc/interconnect/packet.py (see "Allow for changing starting position of header#2441").