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