rds 子例程
用途
可靠数据报套接字 (RDS) 通过各种网络传输在套接字之间提供可靠的按顺序数据报传递。
库
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/bypass.h>
#include <net/rds_rdma.h>描述
RDS 是 RDS 应用程序编程接口 (API) 的实现。 可以通过 InfiniBand 和回送来传输 RDS 。 已禁用 RDS (通过 TCP)。 RDS 使用标准 AF_INET 地址来标识端点。
套接字创建
rds_socket = socket(AF_BYPASS, SOCK_SEQPACKET, BYPASSPROTO_RDS);套接字选项
- 接收缓冲区
- 指定该接收缓冲区的大小。 请参阅 "拥塞控制"。
- SO_SNDBUF
- 指定该发送缓冲区的大小。 请参阅 "消息传输"。
- SO_SNDTIME
- 指定在阻塞方式下将消息排队到具有完整队列的套接字上时套接字的发送超时。
SOL_RDS 套接字级别的多个特定于协议的选项。绑定
新 RDS 在最初从 socket 调用返回时没有本地地址。 在发送或接收任何消息之前,必须通过运行 bind 系统调用将套接字绑定到本地地址。 bind 调用根据本地地址所连接的接口类型将套接字连接到特定网络传输。 从呼叫连接到套接字的点开始,套接字可以到达通过此网络传输提供的目标。
例如,当绑定到 InfiniBand 接口 (例如 ib0) 的地址时,套接字将使用 InfiniBand 传输系统。 如果 RDS 无法将传输系统与特定地址相关联,那么它将返回 EADDRNOTAVAIL 值。
RDS 套接字只能绑定到一个地址,只有一个套接字可以绑定到特定地址或端口对。 如果在绑定地址中未指定任何端口,那么将随机选择未绑定的端口。
RDS 不允许应用程序将先前绑定的套接字绑定到另一个地址。 不允许绑定到 INADDR_ANY 通配符地址。
正在连接
在缺省操作方式下, RDS 使用未连接的套接字,并指定目标地址作为 sendmsg 子例程的自变量。 但是, RDS 允许使用 connect 子例程将套接字连接到远程端点。 如果套接字已连接,那么可以在不指定目标地址的情况下调用 sendmsg 子例程,并且子例程使用先前提供的远程地址。
拥塞控制
RDS 没有像 TCP 之类的公共流协议那样的显式拥塞控制机制。 套接字具有两个队列限制,即 send
queue size 和 receive queue size。 根据有效内容的字节数对消息进行解释。
send
queue size 限制本地进程可以在本地套接字上排队的数据。 如果超过此限制,那么内核将不接受消息,直到队列空闲并且远程主机传递并确认消息为止。
在将套接字标记为 拥塞之前, receive queue size 会限制 RDS 存储在套接字的接收队列上的数据。 当套接字变得拥塞时, RDS 会将 拥塞映射 更新发送到其他参与主机,然后预期这些主机会停止向此端口发送更多消息。
有一个计时窗口,在此期间远程主机可以继续向拥塞的端口发送消息。 RDS 通过接受消息 (即使套接字的接收队列超过限制) 来解析计时窗口。
当应用程序使用 recvmsg 系统调用从接收队列接收入局消息时,接收队列上的字节数将减少到低于接收队列大小,并且端口将标记为 uncongested。 将向所有参与主机发送拥塞更新。
应用程序可以通过 SO_SNDBUF 和 SO_RCVBUF 套接字选项来调整发送缓冲区大小和接收缓冲区大小的值。
阻止行为
在各种情况下,可以阻止 sendmsg 和 recvmsg 调用。 根据文件描述符和 MSG_DONTWAIT 消息标志的非分块设置,可以阻止或返回带有错误的调用。 如果文件描述符设置为分块方式 (缺省值) ,并且未指定 MSG_DONTWAIT 标志,那么将阻塞调用。
SO_SNDTIMEO 和 SO_RCVTIMEO 套接字选项用于指定超时 (以秒计) ,在此超时之后,调用将结束并返回错误。 缺省超时为 0 ,这允许 RDS 无限期阻止。
消息传输
在绑定 RDS 套接字后,可以使用 sendmsg 调用来发送消息。 消息长度不能超过 4 GB ,因为有线协议使用无符号的 32 位整数来表示消息长度。
RDS 不支持频带外数据。 应用程序只能将数据发送到不支持广播或多点广播的单点广播地址。
成功的 sendmsg 调用将消息放置在套接字的传输队列中,直到目标确认该消息不再存在于网络中,或者应用程序从发送队列中除去该消息为止。
可以使用 RDS_CANCEL_SENT_TO 套接字选项从发送队列中除去消息。
当消息在传输队列中时,将考虑其有效内容字节。 如果尝试在传输队列不可用时发送消息,那么调用将阻塞或返回 EAGAIN 值。
将消息发送到标记为拥塞的目标时,将阻止调用或返回ENOBUFS 值。
如果发送的消息没有有效内容字节,那么在目标的发送缓冲区中不需要任何空间,但会向目标发送消息回执。 接收方无法获取任何有效内容数据,但可以查看发送方的地址。
发送到未绑定任何套接字的端口的消息将被目标主机废弃。 不会向发送方报告任何错误消息。
消息接收
在消息与源地址绑定后,可以通过 RDS 上的 recvmsg 调用来接收消息。 RDS 按发送方发送消息的顺序返回消息。
如果设置了该字段,那么发送方的地址将在 msg_name 字段所指向的 索克德报告 结构中返回。
如果设置了 MSG_PEEK 标志,那么将返回接收队列上的第一条消息,而不会从队列中除去该消息。
等待传递的消息所使用的内存不限制可以排队等待接收的消息数。 RDS 尝试控制拥塞。
如果消息的长度超过提供给 recvmsg 调用的缓冲区的大小,那么将废弃消息中的剩余字节,并在 msg_flags 字段中设置 MSG_TRUNC 标志。 在这种情况下, recvmsg 调用将返回复制的字节数。 它不会返回整条消息的长度。 如果在 recvmsg的 flags 参数中设置了 MSG_TRUNC ,那么它将返回整个消息中的字节数。 您可以在接收队列中查看下一条消息的大小,而不提供长度为零的缓冲区以及在 flags 参数中设置 MSG_PEEK 和 MSG_TRUNC 选项。
msg_name 字段中提供了长度为零的消息的发送地址。
控制消息
RDS 通过使用 sendmsg 和 recvmsg 调用中的 msg_control 和 msg_controllen 字段来使用作为辅助数据的控制消息。 RDS 生成的控制消息的 cmsg_level 值为 sol_rds。 大多数控制消息与 RDS 版本 3 中添加的 zerocopy 接口相关,并在 rds-rdma 子例程中进行描述。
唯一的例外是 RDS_CMSG_CONG_UPDATE 消息。
正在轮询
对 poll 接口的支持有限。 当有 RDS 消息或控制消息在套接字的接收队列中等待时,将返回 POLLIN 。 当套接字的发送队列上有空间时,将返回 POLLOUT 。
向拥塞端口发送消息需要特殊处理机制。 当应用程序尝试将消息发送到拥塞的目标时,系统调用会返回 ENOBUFS 值。 RDS 无法轮询 POLLOUT ,因为传输队列仍可容纳消息,并且对 poll 接口的调用可能会立即返回,即使目标已拥塞也是如此。
- 轮询
POLLIN选项。 缺省情况下,在更新拥塞映射时,将激活在 poll 接口中休眠的进程。 应用程序可以重试任何先前拥塞的发送操作。 - 监视显式拥塞,这会给予应用程序更大的控制。
POLLIN 选项,另外使用 RDS_CONG_MONITOR 套接字选项在套接字中安装 64 位掩码值,其中每个位对应于一组端口。 接收到拥塞更新时, RDS 套接字会根据套接字中安装的位掩码来检查变为 uncongested 的端口集。 如果它们重叠,那么控制消息将在套接字上排队,并且应用程序将激活。 调用 recvmsg 调用时, RDS 会提供包含套接字上的位图的控制消息。可以使用带有 RDS_CONG_MONITOR 选项的 setsockopt 调用以及指向 64 位掩码变量的指针来设置和查询 拥塞监视器位掩码 。
拥塞更新通过 RDS_CMSG_CONG_UPDATE 控制消息传递到应用程序。 控制消息单独传递,但从不使用 RDS 数据消息。 控制消息的 cmsg_data 字段是包含 64 位掩码值的 8 字节数据。
#define RDS_CONG_MONITOR_SIZE 64
#define RDS_CONG_MONITOR_BIT(port) (((unsigned int) port) % RDS_CONG_MONITOR_SIZE)
#define RDS_CONG_MONITOR_MASK(port) (1 << RDS_CONG_MONITOR_BIT(port))取消消息
sockaddr_in 地址结构作为自变量。 仅废弃由 sockaddr_in 地址指定的目标地址的消息。 如果未提供地址,那么将废弃所有暂挂消息。可靠性
如果 sendmsg 成功,那么只要该目标套接字保持打开状态, RDS 将保证该消息对绑定到目标地址的套接字上的 recvmsg 可视。
如果目标上没有套接字绑定,那么将删除该消息。 如果正在发送消息的 RDS 不确定套接字是否已绑定,那么它将尝试无限期地发送消息,直到确定或取消已发送的消息为止。
如果套接字已关闭,那么套接字上的暂挂已发送消息将被取消,并且接收方可以看到或无法看到这些消息。
RDS_CANCEL_SENT_TO 套接字选项可用于取消给定目标的所有暂挂消息。
如果接收套接字与暂挂消息一起关闭,那么发送方会将这些消息视为已离开网络,并且不会重新发送这些消息。
除非指定了 MSG_PEEK ,否则 recvmsg 调用会看到一条消息。 当传递消息时,将从发送套接字的传输队列中除去该消息。
从同一套接字发送到同一目标的所有消息都按其发送顺序进行传递。 从不同套接字发送或发送到不同目标的消息将随机传递。