The Versity copyright line has no corporate suffix, so these
notices should not add one either. No functional change.
Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>
The host verbs shim and the RC server C ABI were written for the
gateway. They use the gateway Apache-2.0 header and carry a
copyright notice for that work. Notices on the hipObject ports
are unchanged.
Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>
Make an explicit RC device selection override any GID hint,
matching the --rc-device contract. A stale hint should not
prevent a named HCA from starting.
Query the selected port before allocating the protection domain and fail initialization when that query fails. Continuing with a zero LID advertises an invalid endpoint on InfiniBand and turns a clear startup error into a later RDMA data-plane failure.
The hipobj-rc-v2 server was written against RoCEv2, where the GRH
carries the whole route and the LID in the address handle is unused.
modifyQpToRtr therefore hard-coded ah_attr.dlid = 0, the PREPARE
handler dropped the LID the client token carries, and encodeReplyToken
never filled in our own LID. On an InfiniBand link layer the fabric
switches on the DLID, so every RC session fell over at the data phase:
the client's RDMA write failed with a transport retry exceeded or a
remote invalid request as soon as the QP pair left RTR.
Carry the LID end to end:
- DeviceHandle gains localLid, read from ibv_query_port at init.
- The PREPARE handler stashes the client LID from the token next to
the peer GID; the loopback fallback uses our own LID.
- READY passes that LID into the RTR transition, and modifyQpToRtr
sets ah_attr.dlid from it. is_global stays set: a GRH is valid on
IB and RoCE still needs it, and on RoCE the callers keep passing 0.
- encodeReplyToken fills token.lid so the client can address us.
The 44-byte token has always had the lid field; no wire change.
Verified on a native InfiniBand fabric (ConnectX-6, 200G HDR, SM lid 8)
with the gateway on a Rocky 8.10 storage node using inbox verbs and an
RC client that consumes the reply token LID: PUT and GET complete with
the DLID set, and fail exactly as described with the previous dlid = 0.
The hipobj-rc-v2 server chooses its HCA as "the first verbs device
that opens", or the first whose GID begins with --rc-gid-hint. Neither
works on a storage node with more than one RDMA adapter. Enumeration
order is not a fabric choice, and the hint compares only the first
four GID bytes: every port's GID 0 is link-local, so an InfiniBand
HCA and a RoCE NIC on the same host both match fe:80:0:0, and IPv4-
mapped RoCE GIDs all match 0:0:0:0.
We hit this on a node with two ConnectX-6 IB ports and two Broadcom
RoCE ports: the gateway silently bound bnxt_re0 (link_layer Ethernet,
LID 0, no path to the clients on the IB fabric) and every RC session
timed out in the data phase with nothing in the log to say why.
Add --rc-device / VGW_RC_DEVICE, plumbed through DeviceOpts.DevName
and rc_device_opts.dev_name, that filters the device list by
ibv_device.name before the GID-hint match. It takes precedence over
the hint; the hint still applies within the named device. The failure
message now names the device that was asked for.
A native completion call fires the teardown callback before it
returns, so an outcome recorded after the call is too late: every
successful transfer published as an expiry, and PUT failures and
panics lost their real outcome to the callback's placeholder.
The READY handler now reserves the session record before invoking
any completion call. A reserved record is invisible to the
callback, and the handler publishes the real outcome exactly once
after the result is known. A deferred safety net publishes on
panic unwinds before the unwind finalizer retires the session.
Successful PUTs forward the backend-assigned ETag and version into
the object-created event, and the audit record carries the
transferred byte count as the object size.
A READY whose re-authorization fails now publishes the denial
itself before canceling, instead of letting the cancel publish an
expiry.
The native side keeps the terminal reason on every failure exit:
a verify failure no longer overwrites the wire-failure outcome,
and QP transition or re-arm failures record the wire failure they
return. The unclaimed-teardown classification follows the wire
mapping, so every transfer-level failure the client would see as
502 publishes as the same 502 instead of a diverging per-cause
code.
The metrics bucket tag is documented as absent on synthesized
publications: route parameters come from route matching, which a
synthesized request never runs; the audit log derives the bucket
from the path and stays accurate.
RC sessions that never reach a completion (expired, abandoned, or canceled before READY) currently vanish inside the reaper without any trace on the operational surface. Add a terminal notification callback to the C ABI so the server reports the final outcome of every session exactly once, fired from the reaper with no server lock held.
Expose rc_server_sessions_snapshot, which copies every live session
into fixed rc_session_snapshot records under the map lock and invokes
the callback once per record outside the lock. Each session records a
monotonic creation timestamp, because the prepare/ready deadlines move
as the session progresses and cannot serve as an age reference. The
state byte combines the session state machine value with a
reap-pending marker, so callers can distinguish sessions that are
about to be reaped from healthy ones. Records whose op or target does
not fit the fixed fields are skipped rather than truncated.
The session id only existed as the sessions map key; the session
record itself kept an empty id string, so the terminal reap record
logged an empty id for every expired, cancelled, or destroyed
session. Copy the id into the record at creation time so teardown
logs identify the session they describe.
The verbs loader and device enumeration failures returned
RC_E_INTERNAL without any stderr trace, which made a VM or
container without RDMA indistinguishable from a genuine
library problem. Print the failing step so operators can tell
the two apart at startup.
Wire C-side diagnostics (session reap, READY data phase outcome,
init failures) through a sink callback so the gateway can surface
them next to its own logs instead of losing them in stderr noise.
The sink is a plain C function pointer installed once after init
and valid until destroy: the Go side registers a fixed cgo
trampoline (closures cannot cross the boundary), copies the
message immediately per the lifetime contract, and never runs
under the session map lock. Error-level lines keep the existing
stderr output; --debug enables the level-2 diagnostic stream.
Wrap the v2 session core with the server-side C ABI the gateway
binds to: prepare/ready/cancel session calls, staging leases for
GET side-loading, the put-view handoff for PUT commits, session
introspection, and the server lifecycle.
The ABI owns the parts that must be shared across sessions: the
verbs device handle, global and per-principal resource limits,
session accounting with consume-once handles keyed by epoch and
nonce, the completion reference that pins a session from the
READY claim until its finalizer, and the reaper that tears
transport objects down once every reference drains. A background
thread expires sessions past their prepare or execute deadlines
so abandoned sessions cannot pin the limits, and teardown
failures keep the affected verbs objects and device alive rather
than freeing memory the NIC may still reference.
A peer-busy READY rolls the claim back and re-arms the QP
through RESET so the client can retry the same session. The
vgwrdma target now links the archive built from these sources.
Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>