xref: /openbmc/linux/Documentation/networking/rds.rst (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1bad5b6e2SMauro Carvalho Chehab.. SPDX-License-Identifier: GPL-2.0
2bad5b6e2SMauro Carvalho Chehab
3*c4c55090SAhmed Zaki===
4bad5b6e2SMauro Carvalho ChehabRDS
5bad5b6e2SMauro Carvalho Chehab===
6bad5b6e2SMauro Carvalho Chehab
7bad5b6e2SMauro Carvalho ChehabOverview
8bad5b6e2SMauro Carvalho Chehab========
9bad5b6e2SMauro Carvalho Chehab
10bad5b6e2SMauro Carvalho ChehabThis readme tries to provide some background on the hows and whys of RDS,
11bad5b6e2SMauro Carvalho Chehaband will hopefully help you find your way around the code.
12bad5b6e2SMauro Carvalho Chehab
13bad5b6e2SMauro Carvalho ChehabIn addition, please see this email about RDS origins:
14bad5b6e2SMauro Carvalho Chehabhttp://oss.oracle.com/pipermail/rds-devel/2007-November/000228.html
15bad5b6e2SMauro Carvalho Chehab
16bad5b6e2SMauro Carvalho ChehabRDS Architecture
17bad5b6e2SMauro Carvalho Chehab================
18bad5b6e2SMauro Carvalho Chehab
19bad5b6e2SMauro Carvalho ChehabRDS provides reliable, ordered datagram delivery by using a single
20bad5b6e2SMauro Carvalho Chehabreliable connection between any two nodes in the cluster. This allows
21bad5b6e2SMauro Carvalho Chehabapplications to use a single socket to talk to any other process in the
22bad5b6e2SMauro Carvalho Chehabcluster - so in a cluster with N processes you need N sockets, in contrast
23bad5b6e2SMauro Carvalho Chehabto N*N if you use a connection-oriented socket transport like TCP.
24bad5b6e2SMauro Carvalho Chehab
25bad5b6e2SMauro Carvalho ChehabRDS is not Infiniband-specific; it was designed to support different
26bad5b6e2SMauro Carvalho Chehabtransports.  The current implementation used to support RDS over TCP as well
27bad5b6e2SMauro Carvalho Chehabas IB.
28bad5b6e2SMauro Carvalho Chehab
29bad5b6e2SMauro Carvalho ChehabThe high-level semantics of RDS from the application's point of view are
30bad5b6e2SMauro Carvalho Chehab
31bad5b6e2SMauro Carvalho Chehab *	Addressing
32bad5b6e2SMauro Carvalho Chehab
33bad5b6e2SMauro Carvalho Chehab	RDS uses IPv4 addresses and 16bit port numbers to identify
34bad5b6e2SMauro Carvalho Chehab	the end point of a connection. All socket operations that involve
35bad5b6e2SMauro Carvalho Chehab	passing addresses between kernel and user space generally
36bad5b6e2SMauro Carvalho Chehab	use a struct sockaddr_in.
37bad5b6e2SMauro Carvalho Chehab
38bad5b6e2SMauro Carvalho Chehab	The fact that IPv4 addresses are used does not mean the underlying
39bad5b6e2SMauro Carvalho Chehab	transport has to be IP-based. In fact, RDS over IB uses a
40bad5b6e2SMauro Carvalho Chehab	reliable IB connection; the IP address is used exclusively to
41bad5b6e2SMauro Carvalho Chehab	locate the remote node's GID (by ARPing for the given IP).
42bad5b6e2SMauro Carvalho Chehab
43bad5b6e2SMauro Carvalho Chehab	The port space is entirely independent of UDP, TCP or any other
44bad5b6e2SMauro Carvalho Chehab	protocol.
45bad5b6e2SMauro Carvalho Chehab
46bad5b6e2SMauro Carvalho Chehab *	Socket interface
47bad5b6e2SMauro Carvalho Chehab
48bad5b6e2SMauro Carvalho Chehab	RDS sockets work *mostly* as you would expect from a BSD
49bad5b6e2SMauro Carvalho Chehab	socket. The next section will cover the details. At any rate,
50bad5b6e2SMauro Carvalho Chehab	all I/O is performed through the standard BSD socket API.
51bad5b6e2SMauro Carvalho Chehab	Some additions like zerocopy support are implemented through
52bad5b6e2SMauro Carvalho Chehab	control messages, while other extensions use the getsockopt/
53bad5b6e2SMauro Carvalho Chehab	setsockopt calls.
54bad5b6e2SMauro Carvalho Chehab
55bad5b6e2SMauro Carvalho Chehab	Sockets must be bound before you can send or receive data.
56bad5b6e2SMauro Carvalho Chehab	This is needed because binding also selects a transport and
57bad5b6e2SMauro Carvalho Chehab	attaches it to the socket. Once bound, the transport assignment
58bad5b6e2SMauro Carvalho Chehab	does not change. RDS will tolerate IPs moving around (eg in
59bad5b6e2SMauro Carvalho Chehab	a active-active HA scenario), but only as long as the address
60bad5b6e2SMauro Carvalho Chehab	doesn't move to a different transport.
61bad5b6e2SMauro Carvalho Chehab
62bad5b6e2SMauro Carvalho Chehab *	sysctls
63bad5b6e2SMauro Carvalho Chehab
64bad5b6e2SMauro Carvalho Chehab	RDS supports a number of sysctls in /proc/sys/net/rds
65bad5b6e2SMauro Carvalho Chehab
66bad5b6e2SMauro Carvalho Chehab
67bad5b6e2SMauro Carvalho ChehabSocket Interface
68bad5b6e2SMauro Carvalho Chehab================
69bad5b6e2SMauro Carvalho Chehab
70bad5b6e2SMauro Carvalho Chehab  AF_RDS, PF_RDS, SOL_RDS
71bad5b6e2SMauro Carvalho Chehab	AF_RDS and PF_RDS are the domain type to be used with socket(2)
72bad5b6e2SMauro Carvalho Chehab	to create RDS sockets. SOL_RDS is the socket-level to be used
73bad5b6e2SMauro Carvalho Chehab	with setsockopt(2) and getsockopt(2) for RDS specific socket
74bad5b6e2SMauro Carvalho Chehab	options.
75bad5b6e2SMauro Carvalho Chehab
76bad5b6e2SMauro Carvalho Chehab  fd = socket(PF_RDS, SOCK_SEQPACKET, 0);
77bad5b6e2SMauro Carvalho Chehab	This creates a new, unbound RDS socket.
78bad5b6e2SMauro Carvalho Chehab
79bad5b6e2SMauro Carvalho Chehab  setsockopt(SOL_SOCKET): send and receive buffer size
80bad5b6e2SMauro Carvalho Chehab	RDS honors the send and receive buffer size socket options.
81bad5b6e2SMauro Carvalho Chehab	You are not allowed to queue more than SO_SNDSIZE bytes to
82bad5b6e2SMauro Carvalho Chehab	a socket. A message is queued when sendmsg is called, and
83bad5b6e2SMauro Carvalho Chehab	it leaves the queue when the remote system acknowledges
84bad5b6e2SMauro Carvalho Chehab	its arrival.
85bad5b6e2SMauro Carvalho Chehab
86bad5b6e2SMauro Carvalho Chehab	The SO_RCVSIZE option controls the maximum receive queue length.
87bad5b6e2SMauro Carvalho Chehab	This is a soft limit rather than a hard limit - RDS will
88bad5b6e2SMauro Carvalho Chehab	continue to accept and queue incoming messages, even if that
89bad5b6e2SMauro Carvalho Chehab	takes the queue length over the limit. However, it will also
90bad5b6e2SMauro Carvalho Chehab	mark the port as "congested" and send a congestion update to
91bad5b6e2SMauro Carvalho Chehab	the source node. The source node is supposed to throttle any
92bad5b6e2SMauro Carvalho Chehab	processes sending to this congested port.
93bad5b6e2SMauro Carvalho Chehab
94bad5b6e2SMauro Carvalho Chehab  bind(fd, &sockaddr_in, ...)
95bad5b6e2SMauro Carvalho Chehab	This binds the socket to a local IP address and port, and a
96bad5b6e2SMauro Carvalho Chehab	transport, if one has not already been selected via the
97bad5b6e2SMauro Carvalho Chehab	SO_RDS_TRANSPORT socket option
98bad5b6e2SMauro Carvalho Chehab
99bad5b6e2SMauro Carvalho Chehab  sendmsg(fd, ...)
100bad5b6e2SMauro Carvalho Chehab	Sends a message to the indicated recipient. The kernel will
101bad5b6e2SMauro Carvalho Chehab	transparently establish the underlying reliable connection
102bad5b6e2SMauro Carvalho Chehab	if it isn't up yet.
103bad5b6e2SMauro Carvalho Chehab
104bad5b6e2SMauro Carvalho Chehab	An attempt to send a message that exceeds SO_SNDSIZE will
105bad5b6e2SMauro Carvalho Chehab	return with -EMSGSIZE
106bad5b6e2SMauro Carvalho Chehab
107bad5b6e2SMauro Carvalho Chehab	An attempt to send a message that would take the total number
108bad5b6e2SMauro Carvalho Chehab	of queued bytes over the SO_SNDSIZE threshold will return
109bad5b6e2SMauro Carvalho Chehab	EAGAIN.
110bad5b6e2SMauro Carvalho Chehab
111bad5b6e2SMauro Carvalho Chehab	An attempt to send a message to a destination that is marked
112bad5b6e2SMauro Carvalho Chehab	as "congested" will return ENOBUFS.
113bad5b6e2SMauro Carvalho Chehab
114bad5b6e2SMauro Carvalho Chehab  recvmsg(fd, ...)
115bad5b6e2SMauro Carvalho Chehab	Receives a message that was queued to this socket. The sockets
116bad5b6e2SMauro Carvalho Chehab	recv queue accounting is adjusted, and if the queue length
117bad5b6e2SMauro Carvalho Chehab	drops below SO_SNDSIZE, the port is marked uncongested, and
118bad5b6e2SMauro Carvalho Chehab	a congestion update is sent to all peers.
119bad5b6e2SMauro Carvalho Chehab
120bad5b6e2SMauro Carvalho Chehab	Applications can ask the RDS kernel module to receive
121bad5b6e2SMauro Carvalho Chehab	notifications via control messages (for instance, there is a
122bad5b6e2SMauro Carvalho Chehab	notification when a congestion update arrived, or when a RDMA
123bad5b6e2SMauro Carvalho Chehab	operation completes). These notifications are received through
124bad5b6e2SMauro Carvalho Chehab	the msg.msg_control buffer of struct msghdr. The format of the
125bad5b6e2SMauro Carvalho Chehab	messages is described in manpages.
126bad5b6e2SMauro Carvalho Chehab
127bad5b6e2SMauro Carvalho Chehab  poll(fd)
128bad5b6e2SMauro Carvalho Chehab	RDS supports the poll interface to allow the application
129bad5b6e2SMauro Carvalho Chehab	to implement async I/O.
130bad5b6e2SMauro Carvalho Chehab
131bad5b6e2SMauro Carvalho Chehab	POLLIN handling is pretty straightforward. When there's an
132bad5b6e2SMauro Carvalho Chehab	incoming message queued to the socket, or a pending notification,
133bad5b6e2SMauro Carvalho Chehab	we signal POLLIN.
134bad5b6e2SMauro Carvalho Chehab
135bad5b6e2SMauro Carvalho Chehab	POLLOUT is a little harder. Since you can essentially send
136bad5b6e2SMauro Carvalho Chehab	to any destination, RDS will always signal POLLOUT as long as
137bad5b6e2SMauro Carvalho Chehab	there's room on the send queue (ie the number of bytes queued
138bad5b6e2SMauro Carvalho Chehab	is less than the sendbuf size).
139bad5b6e2SMauro Carvalho Chehab
140bad5b6e2SMauro Carvalho Chehab	However, the kernel will refuse to accept messages to
141bad5b6e2SMauro Carvalho Chehab	a destination marked congested - in this case you will loop
142bad5b6e2SMauro Carvalho Chehab	forever if you rely on poll to tell you what to do.
143bad5b6e2SMauro Carvalho Chehab	This isn't a trivial problem, but applications can deal with
144bad5b6e2SMauro Carvalho Chehab	this - by using congestion notifications, and by checking for
145bad5b6e2SMauro Carvalho Chehab	ENOBUFS errors returned by sendmsg.
146bad5b6e2SMauro Carvalho Chehab
147bad5b6e2SMauro Carvalho Chehab  setsockopt(SOL_RDS, RDS_CANCEL_SENT_TO, &sockaddr_in)
148bad5b6e2SMauro Carvalho Chehab	This allows the application to discard all messages queued to a
149bad5b6e2SMauro Carvalho Chehab	specific destination on this particular socket.
150bad5b6e2SMauro Carvalho Chehab
151bad5b6e2SMauro Carvalho Chehab	This allows the application to cancel outstanding messages if
152bad5b6e2SMauro Carvalho Chehab	it detects a timeout. For instance, if it tried to send a message,
153bad5b6e2SMauro Carvalho Chehab	and the remote host is unreachable, RDS will keep trying forever.
154bad5b6e2SMauro Carvalho Chehab	The application may decide it's not worth it, and cancel the
155bad5b6e2SMauro Carvalho Chehab	operation. In this case, it would use RDS_CANCEL_SENT_TO to
156bad5b6e2SMauro Carvalho Chehab	nuke any pending messages.
157bad5b6e2SMauro Carvalho Chehab
158bad5b6e2SMauro Carvalho Chehab  ``setsockopt(fd, SOL_RDS, SO_RDS_TRANSPORT, (int *)&transport ..), getsockopt(fd, SOL_RDS, SO_RDS_TRANSPORT, (int *)&transport ..)``
159bad5b6e2SMauro Carvalho Chehab	Set or read an integer defining  the underlying
160bad5b6e2SMauro Carvalho Chehab	encapsulating transport to be used for RDS packets on the
161bad5b6e2SMauro Carvalho Chehab	socket. When setting the option, integer argument may be
162bad5b6e2SMauro Carvalho Chehab	one of RDS_TRANS_TCP or RDS_TRANS_IB. When retrieving the
163bad5b6e2SMauro Carvalho Chehab	value, RDS_TRANS_NONE will be returned on an unbound socket.
164bad5b6e2SMauro Carvalho Chehab	This socket option may only be set exactly once on the socket,
165bad5b6e2SMauro Carvalho Chehab	prior to binding it via the bind(2) system call. Attempts to
166bad5b6e2SMauro Carvalho Chehab	set SO_RDS_TRANSPORT on a socket for which the transport has
167bad5b6e2SMauro Carvalho Chehab	been previously attached explicitly (by SO_RDS_TRANSPORT) or
168bad5b6e2SMauro Carvalho Chehab	implicitly (via bind(2)) will return an error of EOPNOTSUPP.
169bad5b6e2SMauro Carvalho Chehab	An attempt to set SO_RDS_TRANSPORT to RDS_TRANS_NONE will
170bad5b6e2SMauro Carvalho Chehab	always return EINVAL.
171bad5b6e2SMauro Carvalho Chehab
172bad5b6e2SMauro Carvalho ChehabRDMA for RDS
173bad5b6e2SMauro Carvalho Chehab============
174bad5b6e2SMauro Carvalho Chehab
175bad5b6e2SMauro Carvalho Chehab  see rds-rdma(7) manpage (available in rds-tools)
176bad5b6e2SMauro Carvalho Chehab
177bad5b6e2SMauro Carvalho Chehab
178bad5b6e2SMauro Carvalho ChehabCongestion Notifications
179bad5b6e2SMauro Carvalho Chehab========================
180bad5b6e2SMauro Carvalho Chehab
181bad5b6e2SMauro Carvalho Chehab  see rds(7) manpage
182bad5b6e2SMauro Carvalho Chehab
183bad5b6e2SMauro Carvalho Chehab
184bad5b6e2SMauro Carvalho ChehabRDS Protocol
185bad5b6e2SMauro Carvalho Chehab============
186bad5b6e2SMauro Carvalho Chehab
187bad5b6e2SMauro Carvalho Chehab  Message header
188bad5b6e2SMauro Carvalho Chehab
189bad5b6e2SMauro Carvalho Chehab    The message header is a 'struct rds_header' (see rds.h):
190bad5b6e2SMauro Carvalho Chehab
191bad5b6e2SMauro Carvalho Chehab    Fields:
192bad5b6e2SMauro Carvalho Chehab
193bad5b6e2SMauro Carvalho Chehab      h_sequence:
194bad5b6e2SMauro Carvalho Chehab	  per-packet sequence number
195bad5b6e2SMauro Carvalho Chehab      h_ack:
196bad5b6e2SMauro Carvalho Chehab	  piggybacked acknowledgment of last packet received
197bad5b6e2SMauro Carvalho Chehab      h_len:
198bad5b6e2SMauro Carvalho Chehab	  length of data, not including header
199bad5b6e2SMauro Carvalho Chehab      h_sport:
200bad5b6e2SMauro Carvalho Chehab	  source port
201bad5b6e2SMauro Carvalho Chehab      h_dport:
202bad5b6e2SMauro Carvalho Chehab	  destination port
203bad5b6e2SMauro Carvalho Chehab      h_flags:
204bad5b6e2SMauro Carvalho Chehab	  Can be:
205bad5b6e2SMauro Carvalho Chehab
206bad5b6e2SMauro Carvalho Chehab	  =============  ==================================
207bad5b6e2SMauro Carvalho Chehab	  CONG_BITMAP    this is a congestion update bitmap
208bad5b6e2SMauro Carvalho Chehab	  ACK_REQUIRED   receiver must ack this packet
209bad5b6e2SMauro Carvalho Chehab	  RETRANSMITTED  packet has previously been sent
210bad5b6e2SMauro Carvalho Chehab	  =============  ==================================
211bad5b6e2SMauro Carvalho Chehab
212bad5b6e2SMauro Carvalho Chehab      h_credit:
213bad5b6e2SMauro Carvalho Chehab	  indicate to other end of connection that
214bad5b6e2SMauro Carvalho Chehab	  it has more credits available (i.e. there is
215bad5b6e2SMauro Carvalho Chehab	  more send room)
216bad5b6e2SMauro Carvalho Chehab      h_padding[4]:
217bad5b6e2SMauro Carvalho Chehab	  unused, for future use
218bad5b6e2SMauro Carvalho Chehab      h_csum:
219bad5b6e2SMauro Carvalho Chehab	  header checksum
220bad5b6e2SMauro Carvalho Chehab      h_exthdr:
221bad5b6e2SMauro Carvalho Chehab	  optional data can be passed here. This is currently used for
222bad5b6e2SMauro Carvalho Chehab	  passing RDMA-related information.
223bad5b6e2SMauro Carvalho Chehab
224bad5b6e2SMauro Carvalho Chehab  ACK and retransmit handling
225bad5b6e2SMauro Carvalho Chehab
226bad5b6e2SMauro Carvalho Chehab      One might think that with reliable IB connections you wouldn't need
227bad5b6e2SMauro Carvalho Chehab      to ack messages that have been received.  The problem is that IB
228bad5b6e2SMauro Carvalho Chehab      hardware generates an ack message before it has DMAed the message
229bad5b6e2SMauro Carvalho Chehab      into memory.  This creates a potential message loss if the HCA is
230bad5b6e2SMauro Carvalho Chehab      disabled for any reason between when it sends the ack and before
231bad5b6e2SMauro Carvalho Chehab      the message is DMAed and processed.  This is only a potential issue
232bad5b6e2SMauro Carvalho Chehab      if another HCA is available for fail-over.
233bad5b6e2SMauro Carvalho Chehab
234bad5b6e2SMauro Carvalho Chehab      Sending an ack immediately would allow the sender to free the sent
235bad5b6e2SMauro Carvalho Chehab      message from their send queue quickly, but could cause excessive
236bad5b6e2SMauro Carvalho Chehab      traffic to be used for acks. RDS piggybacks acks on sent data
237bad5b6e2SMauro Carvalho Chehab      packets.  Ack-only packets are reduced by only allowing one to be
238bad5b6e2SMauro Carvalho Chehab      in flight at a time, and by the sender only asking for acks when
239bad5b6e2SMauro Carvalho Chehab      its send buffers start to fill up. All retransmissions are also
240bad5b6e2SMauro Carvalho Chehab      acked.
241bad5b6e2SMauro Carvalho Chehab
242bad5b6e2SMauro Carvalho Chehab  Flow Control
243bad5b6e2SMauro Carvalho Chehab
244bad5b6e2SMauro Carvalho Chehab      RDS's IB transport uses a credit-based mechanism to verify that
245bad5b6e2SMauro Carvalho Chehab      there is space in the peer's receive buffers for more data. This
246bad5b6e2SMauro Carvalho Chehab      eliminates the need for hardware retries on the connection.
247bad5b6e2SMauro Carvalho Chehab
248bad5b6e2SMauro Carvalho Chehab  Congestion
249bad5b6e2SMauro Carvalho Chehab
250bad5b6e2SMauro Carvalho Chehab      Messages waiting in the receive queue on the receiving socket
251bad5b6e2SMauro Carvalho Chehab      are accounted against the sockets SO_RCVBUF option value.  Only
252bad5b6e2SMauro Carvalho Chehab      the payload bytes in the message are accounted for.  If the
253bad5b6e2SMauro Carvalho Chehab      number of bytes queued equals or exceeds rcvbuf then the socket
254bad5b6e2SMauro Carvalho Chehab      is congested.  All sends attempted to this socket's address
255bad5b6e2SMauro Carvalho Chehab      should return block or return -EWOULDBLOCK.
256bad5b6e2SMauro Carvalho Chehab
257bad5b6e2SMauro Carvalho Chehab      Applications are expected to be reasonably tuned such that this
258bad5b6e2SMauro Carvalho Chehab      situation very rarely occurs.  An application encountering this
259bad5b6e2SMauro Carvalho Chehab      "back-pressure" is considered a bug.
260bad5b6e2SMauro Carvalho Chehab
261bad5b6e2SMauro Carvalho Chehab      This is implemented by having each node maintain bitmaps which
262bad5b6e2SMauro Carvalho Chehab      indicate which ports on bound addresses are congested.  As the
263bad5b6e2SMauro Carvalho Chehab      bitmap changes it is sent through all the connections which
264bad5b6e2SMauro Carvalho Chehab      terminate in the local address of the bitmap which changed.
265bad5b6e2SMauro Carvalho Chehab
266bad5b6e2SMauro Carvalho Chehab      The bitmaps are allocated as connections are brought up.  This
267bad5b6e2SMauro Carvalho Chehab      avoids allocation in the interrupt handling path which queues
268bad5b6e2SMauro Carvalho Chehab      sages on sockets.  The dense bitmaps let transports send the
269bad5b6e2SMauro Carvalho Chehab      entire bitmap on any bitmap change reasonably efficiently.  This
270bad5b6e2SMauro Carvalho Chehab      is much easier to implement than some finer-grained
271bad5b6e2SMauro Carvalho Chehab      communication of per-port congestion.  The sender does a very
272bad5b6e2SMauro Carvalho Chehab      inexpensive bit test to test if the port it's about to send to
273bad5b6e2SMauro Carvalho Chehab      is congested or not.
274bad5b6e2SMauro Carvalho Chehab
275bad5b6e2SMauro Carvalho Chehab
276bad5b6e2SMauro Carvalho ChehabRDS Transport Layer
277bad5b6e2SMauro Carvalho Chehab===================
278bad5b6e2SMauro Carvalho Chehab
279bad5b6e2SMauro Carvalho Chehab  As mentioned above, RDS is not IB-specific. Its code is divided
280bad5b6e2SMauro Carvalho Chehab  into a general RDS layer and a transport layer.
281bad5b6e2SMauro Carvalho Chehab
282bad5b6e2SMauro Carvalho Chehab  The general layer handles the socket API, congestion handling,
283bad5b6e2SMauro Carvalho Chehab  loopback, stats, usermem pinning, and the connection state machine.
284bad5b6e2SMauro Carvalho Chehab
285bad5b6e2SMauro Carvalho Chehab  The transport layer handles the details of the transport. The IB
286bad5b6e2SMauro Carvalho Chehab  transport, for example, handles all the queue pairs, work requests,
287bad5b6e2SMauro Carvalho Chehab  CM event handlers, and other Infiniband details.
288bad5b6e2SMauro Carvalho Chehab
289bad5b6e2SMauro Carvalho Chehab
290bad5b6e2SMauro Carvalho ChehabRDS Kernel Structures
291bad5b6e2SMauro Carvalho Chehab=====================
292bad5b6e2SMauro Carvalho Chehab
293bad5b6e2SMauro Carvalho Chehab  struct rds_message
294bad5b6e2SMauro Carvalho Chehab    aka possibly "rds_outgoing", the generic RDS layer copies data to
295bad5b6e2SMauro Carvalho Chehab    be sent and sets header fields as needed, based on the socket API.
296bad5b6e2SMauro Carvalho Chehab    This is then queued for the individual connection and sent by the
297bad5b6e2SMauro Carvalho Chehab    connection's transport.
298bad5b6e2SMauro Carvalho Chehab
299bad5b6e2SMauro Carvalho Chehab  struct rds_incoming
300bad5b6e2SMauro Carvalho Chehab    a generic struct referring to incoming data that can be handed from
301bad5b6e2SMauro Carvalho Chehab    the transport to the general code and queued by the general code
302bad5b6e2SMauro Carvalho Chehab    while the socket is awoken. It is then passed back to the transport
303bad5b6e2SMauro Carvalho Chehab    code to handle the actual copy-to-user.
304bad5b6e2SMauro Carvalho Chehab
305bad5b6e2SMauro Carvalho Chehab  struct rds_socket
306bad5b6e2SMauro Carvalho Chehab    per-socket information
307bad5b6e2SMauro Carvalho Chehab
308bad5b6e2SMauro Carvalho Chehab  struct rds_connection
309bad5b6e2SMauro Carvalho Chehab    per-connection information
310bad5b6e2SMauro Carvalho Chehab
311bad5b6e2SMauro Carvalho Chehab  struct rds_transport
312bad5b6e2SMauro Carvalho Chehab    pointers to transport-specific functions
313bad5b6e2SMauro Carvalho Chehab
314bad5b6e2SMauro Carvalho Chehab  struct rds_statistics
315bad5b6e2SMauro Carvalho Chehab    non-transport-specific statistics
316bad5b6e2SMauro Carvalho Chehab
317bad5b6e2SMauro Carvalho Chehab  struct rds_cong_map
318bad5b6e2SMauro Carvalho Chehab    wraps the raw congestion bitmap, contains rbnode, waitq, etc.
319bad5b6e2SMauro Carvalho Chehab
320bad5b6e2SMauro Carvalho ChehabConnection management
321bad5b6e2SMauro Carvalho Chehab=====================
322bad5b6e2SMauro Carvalho Chehab
323bad5b6e2SMauro Carvalho Chehab  Connections may be in UP, DOWN, CONNECTING, DISCONNECTING, and
324bad5b6e2SMauro Carvalho Chehab  ERROR states.
325bad5b6e2SMauro Carvalho Chehab
326bad5b6e2SMauro Carvalho Chehab  The first time an attempt is made by an RDS socket to send data to
327bad5b6e2SMauro Carvalho Chehab  a node, a connection is allocated and connected. That connection is
328bad5b6e2SMauro Carvalho Chehab  then maintained forever -- if there are transport errors, the
329bad5b6e2SMauro Carvalho Chehab  connection will be dropped and re-established.
330bad5b6e2SMauro Carvalho Chehab
331bad5b6e2SMauro Carvalho Chehab  Dropping a connection while packets are queued will cause queued or
332bad5b6e2SMauro Carvalho Chehab  partially-sent datagrams to be retransmitted when the connection is
333bad5b6e2SMauro Carvalho Chehab  re-established.
334bad5b6e2SMauro Carvalho Chehab
335bad5b6e2SMauro Carvalho Chehab
336bad5b6e2SMauro Carvalho ChehabThe send path
337bad5b6e2SMauro Carvalho Chehab=============
338bad5b6e2SMauro Carvalho Chehab
339bad5b6e2SMauro Carvalho Chehab  rds_sendmsg()
340bad5b6e2SMauro Carvalho Chehab    - struct rds_message built from incoming data
341bad5b6e2SMauro Carvalho Chehab    - CMSGs parsed (e.g. RDMA ops)
342bad5b6e2SMauro Carvalho Chehab    - transport connection alloced and connected if not already
343bad5b6e2SMauro Carvalho Chehab    - rds_message placed on send queue
344bad5b6e2SMauro Carvalho Chehab    - send worker awoken
345bad5b6e2SMauro Carvalho Chehab
346bad5b6e2SMauro Carvalho Chehab  rds_send_worker()
347bad5b6e2SMauro Carvalho Chehab    - calls rds_send_xmit() until queue is empty
348bad5b6e2SMauro Carvalho Chehab
349bad5b6e2SMauro Carvalho Chehab  rds_send_xmit()
350bad5b6e2SMauro Carvalho Chehab    - transmits congestion map if one is pending
351bad5b6e2SMauro Carvalho Chehab    - may set ACK_REQUIRED
352bad5b6e2SMauro Carvalho Chehab    - calls transport to send either non-RDMA or RDMA message
353bad5b6e2SMauro Carvalho Chehab      (RDMA ops never retransmitted)
354bad5b6e2SMauro Carvalho Chehab
355bad5b6e2SMauro Carvalho Chehab  rds_ib_xmit()
356bad5b6e2SMauro Carvalho Chehab    - allocs work requests from send ring
357bad5b6e2SMauro Carvalho Chehab    - adds any new send credits available to peer (h_credits)
358bad5b6e2SMauro Carvalho Chehab    - maps the rds_message's sg list
359bad5b6e2SMauro Carvalho Chehab    - piggybacks ack
360bad5b6e2SMauro Carvalho Chehab    - populates work requests
361bad5b6e2SMauro Carvalho Chehab    - post send to connection's queue pair
362bad5b6e2SMauro Carvalho Chehab
363bad5b6e2SMauro Carvalho ChehabThe recv path
364bad5b6e2SMauro Carvalho Chehab=============
365bad5b6e2SMauro Carvalho Chehab
366bad5b6e2SMauro Carvalho Chehab  rds_ib_recv_cq_comp_handler()
367bad5b6e2SMauro Carvalho Chehab    - looks at write completions
368bad5b6e2SMauro Carvalho Chehab    - unmaps recv buffer from device
369bad5b6e2SMauro Carvalho Chehab    - no errors, call rds_ib_process_recv()
370bad5b6e2SMauro Carvalho Chehab    - refill recv ring
371bad5b6e2SMauro Carvalho Chehab
372bad5b6e2SMauro Carvalho Chehab  rds_ib_process_recv()
373bad5b6e2SMauro Carvalho Chehab    - validate header checksum
374bad5b6e2SMauro Carvalho Chehab    - copy header to rds_ib_incoming struct if start of a new datagram
375bad5b6e2SMauro Carvalho Chehab    - add to ibinc's fraglist
376bad5b6e2SMauro Carvalho Chehab    - if competed datagram:
377bad5b6e2SMauro Carvalho Chehab	 - update cong map if datagram was cong update
378bad5b6e2SMauro Carvalho Chehab	 - call rds_recv_incoming() otherwise
379bad5b6e2SMauro Carvalho Chehab	 - note if ack is required
380bad5b6e2SMauro Carvalho Chehab
381bad5b6e2SMauro Carvalho Chehab  rds_recv_incoming()
382bad5b6e2SMauro Carvalho Chehab    - drop duplicate packets
383bad5b6e2SMauro Carvalho Chehab    - respond to pings
384bad5b6e2SMauro Carvalho Chehab    - find the sock associated with this datagram
385bad5b6e2SMauro Carvalho Chehab    - add to sock queue
386bad5b6e2SMauro Carvalho Chehab    - wake up sock
387bad5b6e2SMauro Carvalho Chehab    - do some congestion calculations
388bad5b6e2SMauro Carvalho Chehab  rds_recvmsg
389bad5b6e2SMauro Carvalho Chehab    - copy data into user iovec
390bad5b6e2SMauro Carvalho Chehab    - handle CMSGs
391bad5b6e2SMauro Carvalho Chehab    - return to application
392bad5b6e2SMauro Carvalho Chehab
393bad5b6e2SMauro Carvalho ChehabMultipath RDS (mprds)
394bad5b6e2SMauro Carvalho Chehab=====================
395bad5b6e2SMauro Carvalho Chehab  Mprds is multipathed-RDS, primarily intended for RDS-over-TCP
396bad5b6e2SMauro Carvalho Chehab  (though the concept can be extended to other transports). The classical
397bad5b6e2SMauro Carvalho Chehab  implementation of RDS-over-TCP is implemented by demultiplexing multiple
398bad5b6e2SMauro Carvalho Chehab  PF_RDS sockets between any 2 endpoints (where endpoint == [IP address,
399bad5b6e2SMauro Carvalho Chehab  port]) over a single TCP socket between the 2 IP addresses involved. This
400bad5b6e2SMauro Carvalho Chehab  has the limitation that it ends up funneling multiple RDS flows over a
401bad5b6e2SMauro Carvalho Chehab  single TCP flow, thus it is
402bad5b6e2SMauro Carvalho Chehab  (a) upper-bounded to the single-flow bandwidth,
403bad5b6e2SMauro Carvalho Chehab  (b) suffers from head-of-line blocking for all the RDS sockets.
404bad5b6e2SMauro Carvalho Chehab
405bad5b6e2SMauro Carvalho Chehab  Better throughput (for a fixed small packet size, MTU) can be achieved
406bad5b6e2SMauro Carvalho Chehab  by having multiple TCP/IP flows per rds/tcp connection, i.e., multipathed
407bad5b6e2SMauro Carvalho Chehab  RDS (mprds).  Each such TCP/IP flow constitutes a path for the rds/tcp
408bad5b6e2SMauro Carvalho Chehab  connection. RDS sockets will be attached to a path based on some hash
409bad5b6e2SMauro Carvalho Chehab  (e.g., of local address and RDS port number) and packets for that RDS
410bad5b6e2SMauro Carvalho Chehab  socket will be sent over the attached path using TCP to segment/reassemble
411bad5b6e2SMauro Carvalho Chehab  RDS datagrams on that path.
412bad5b6e2SMauro Carvalho Chehab
413bad5b6e2SMauro Carvalho Chehab  Multipathed RDS is implemented by splitting the struct rds_connection into
414bad5b6e2SMauro Carvalho Chehab  a common (to all paths) part, and a per-path struct rds_conn_path. All
415bad5b6e2SMauro Carvalho Chehab  I/O workqs and reconnect threads are driven from the rds_conn_path.
416bad5b6e2SMauro Carvalho Chehab  Transports such as TCP that are multipath capable may then set up a
417bad5b6e2SMauro Carvalho Chehab  TCP socket per rds_conn_path, and this is managed by the transport via
418bad5b6e2SMauro Carvalho Chehab  the transport privatee cp_transport_data pointer.
419bad5b6e2SMauro Carvalho Chehab
420bad5b6e2SMauro Carvalho Chehab  Transports announce themselves as multipath capable by setting the
421bad5b6e2SMauro Carvalho Chehab  t_mp_capable bit during registration with the rds core module. When the
422bad5b6e2SMauro Carvalho Chehab  transport is multipath-capable, rds_sendmsg() hashes outgoing traffic
423bad5b6e2SMauro Carvalho Chehab  across multiple paths. The outgoing hash is computed based on the
424bad5b6e2SMauro Carvalho Chehab  local address and port that the PF_RDS socket is bound to.
425bad5b6e2SMauro Carvalho Chehab
426bad5b6e2SMauro Carvalho Chehab  Additionally, even if the transport is MP capable, we may be
427bad5b6e2SMauro Carvalho Chehab  peering with some node that does not support mprds, or supports
428bad5b6e2SMauro Carvalho Chehab  a different number of paths. As a result, the peering nodes need
429bad5b6e2SMauro Carvalho Chehab  to agree on the number of paths to be used for the connection.
430bad5b6e2SMauro Carvalho Chehab  This is done by sending out a control packet exchange before the
431bad5b6e2SMauro Carvalho Chehab  first data packet. The control packet exchange must have completed
432bad5b6e2SMauro Carvalho Chehab  prior to outgoing hash completion in rds_sendmsg() when the transport
433bad5b6e2SMauro Carvalho Chehab  is mutlipath capable.
434bad5b6e2SMauro Carvalho Chehab
435bad5b6e2SMauro Carvalho Chehab  The control packet is an RDS ping packet (i.e., packet to rds dest
436bad5b6e2SMauro Carvalho Chehab  port 0) with the ping packet having a rds extension header option  of
437bad5b6e2SMauro Carvalho Chehab  type RDS_EXTHDR_NPATHS, length 2 bytes, and the value is the
438bad5b6e2SMauro Carvalho Chehab  number of paths supported by the sender. The "probe" ping packet will
439bad5b6e2SMauro Carvalho Chehab  get sent from some reserved port, RDS_FLAG_PROBE_PORT (in <linux/rds.h>)
440bad5b6e2SMauro Carvalho Chehab  The receiver of a ping from RDS_FLAG_PROBE_PORT will thus immediately
441bad5b6e2SMauro Carvalho Chehab  be able to compute the min(sender_paths, rcvr_paths). The pong
442bad5b6e2SMauro Carvalho Chehab  sent in response to a probe-ping should contain the rcvr's npaths
443bad5b6e2SMauro Carvalho Chehab  when the rcvr is mprds-capable.
444bad5b6e2SMauro Carvalho Chehab
445bad5b6e2SMauro Carvalho Chehab  If the rcvr is not mprds-capable, the exthdr in the ping will be
446bad5b6e2SMauro Carvalho Chehab  ignored.  In this case the pong will not have any exthdrs, so the sender
447bad5b6e2SMauro Carvalho Chehab  of the probe-ping can default to single-path mprds.
448bad5b6e2SMauro Carvalho Chehab
449