RxRPC 网络协议¶
RxRPC 协议驱动程序提供了一种基于 UDP 的可靠的两阶段传输,可用于执行 RxRPC 远程操作。这是通过 AF_RXRPC 族的套接字完成的,使用 sendmsg() 和 recvmsg() 以及控制数据来发送和接收数据、中止和错误。
本文档内容
概述。
RxRPC 协议概要。
AF_RXRPC 驱动程序模型。
控制消息。
套接字选项。
安全性。
客户端使用示例。
服务器使用示例。
AF_RXRPC 内核接口。
可配置参数。
概述¶
RxRPC 是一个双层协议。有一个会话层,它使用基于 IPv4(或 IPv6)的 UDP 作为传输层来提供可靠的虚拟连接,但实现了一个真正的网络协议;还有一个表示层,它使用 XDR 将结构化数据渲染成二进制 blob 并再次渲染回去(SunRPC 也是如此)
+-------------+
| Application |
+-------------+
| XDR | Presentation
+-------------+
| RxRPC | Session
+-------------+
| UDP | Transport
+-------------+
AF_RXRPC 提供
RxRPC 功能的一部分,适用于内核和用户空间应用程序,方法是将其会话部分设为 Linux 网络协议 (AF_RXRPC)。
一个两阶段协议。客户端传输一个 blob(请求),然后接收一个 blob(回复),服务器接收请求,然后传输回复。
保留为一个调用设置的可重用传输系统位,以加速后续调用。
一种安全协议,使用 Linux 内核的密钥保留功能来管理客户端的安全。服务器端必须更积极地参与安全协商。
AF_RXRPC 不提供 XDR 编组/表示功能。这留给应用程序。 AF_RXRPC 只处理 blob。即使是操作 ID 也只是请求 blob 的前四个字节,因此超出了内核的兴趣范围。
AF_RXRPC 族的套接字是
创建为 SOCK_DGRAM 类型;
提供其将要使用的底层传输类型的协议 - 目前仅支持 PF_INET。
Andrew 文件系统 (AFS) 是一个使用此功能的应用程序示例,并且具有内核(文件系统)和用户空间(实用程序)组件。
RxRPC 协议概要¶
RxRPC 协议的概述
RxRPC 位于另一个网络协议之上(目前唯一选择是 UDP),并使用它来提供网络传输。例如,UDP 端口提供传输端点。
RxRPC 支持来自任何给定传输端点的多个虚拟“连接”,从而允许共享端点,即使到相同的远程端点。
每个连接都连接到特定的“服务”。一个连接可能无法连接到多个服务。可以将服务视为 RxRPC 等效的端口号。 AF_RXRPC 允许多个服务共享一个端点。
客户端发起的包被标记,因此传输端点可以在客户端和服务器连接之间共享(连接具有方向)。
在一个本地传输端点和一个远程端点上的一个服务之间,最多可以同时支持十亿个连接。 RxRPC 连接由七个数字描述
Local address } Local port } Transport (UDP) address Remote address } Remote port } Direction Connection ID Service ID每个 RxRPC 操作都是一个“调用”。一个连接可以进行多达 40 亿次调用,但在任何给定时间,一个连接上最多可以进行 4 次调用。
调用是双阶段的并且是不对称的:客户端发送其请求数据,服务接收该数据;然后服务传输客户端接收的回复数据。
数据 blob 的大小不确定,阶段的结束由数据包中的标志标记。但是,组成一个 blob 的数据包数量不得超过 40 亿个,因为这会导致序列号换行。
请求数据的前四个字节是服务操作 ID。
安全性是在每个连接的基础上协商的。连接由到达的第一个数据包启动。如果请求了安全性,则服务器会发出“质询”,然后客户端以“响应”进行回复。如果响应成功,则为该连接的生命周期设置安全性,并且所有后续调用都使用相同的安全性。如果服务器在客户端之前让连接失效,则如果客户端再次使用该连接,将重新协商安全性。
调用使用 ACK 数据包来处理可靠性。数据包也按每个调用显式排序。
有两种类型的肯定确认:硬 ACK 和软 ACK。硬 ACK 向远端指示已接收并处理到某个点的所有数据;软 ACK 指示已接收到数据,但可能仍会被丢弃并重新请求。在发送方硬 ACK 之前,发送方不得丢弃任何可传输的数据包。
接收到回复数据包隐式硬 ACK 了组成请求的所有数据包。
当请求已发送、回复已接收并且回复的最后一个数据包上的最终硬 ACK 已到达服务器时,调用完成。
在完成之前,任何一端都可以随时中止调用。
AF_RXRPC 驱动程序模型¶
关于 AF_RXRPC 驱动程序
AF_RXRPC 协议透明地使用传输协议的内部套接字来表示传输端点。
AF_RXRPC 套接字映射到 RxRPC 连接捆绑包。实际的 RxRPC 连接以透明方式处理。一个客户端套接字可用于对同一服务进行多次并发调用。一个服务器套接字可以处理来自多个客户端的调用。
将启动额外的并行客户端连接以支持额外的并发调用,直到可调整的限制。
每个连接在当前使用它的最后一个调用完成后的某个时间段内 [可调整] 保留,以防进行可以重用它的新调用。
每个内部 UDP 套接字在上次使用它的连接丢弃后的某个时间段内 [可调整] 保留 [可调整],以防进行可以使用它的新连接。
仅当客户端具有描述其安全性的相同密钥结构时,客户端连接才会在调用之间共享(并假设调用否则会共享连接)。未受保护的调用也可以相互共享连接。
如果客户端表示它在,则服务器端连接将被共享。
ACK 由协议驱动程序自动处理,包括 ping 回复。
SO_KEEPALIVE 自动 ping 另一端以保持连接活动 [TODO]。
如果收到 ICMP 错误,则受该错误影响的所有调用都将被中止,并且适当的网络错误将通过 recvmsg() 传递。
与 RxRPC 套接字用户的交互
通过绑定具有非零服务 ID 的地址,将套接字设为服务器套接字。
在客户端中,发送请求是通过一个或多个 sendmsgs 来实现的,然后通过一个或多个 recvmsgs 接收回复。
要从客户端发送的请求的第一个 sendmsg 包含一个标签,该标签将用于与该调用关联的所有其他 sendmsgs 或 recvmsgs 中。该标签在控制数据中携带。
connect() 用于为客户端套接字提供默认目标地址。这可能会被提供给调用的第一个 sendmsg() 的备用地址覆盖(struct msghdr::msg_name)。
如果在未绑定的客户端上调用 connect(),则在操作发生之前将绑定一个随机的本地端口。
服务器套接字也可以用于进行客户端调用。为此,调用的第一个 sendmsg() 必须指定目标地址。服务器的传输端点用于发送数据包。
一旦应用程序收到与调用关联的最后一个消息,则保证不会再次看到该标签,因此可以使用它来固定客户端资源。然后可以使用相同的标签启动新调用,而不用担心干扰。
在服务器中,使用一个或多个 recvmsgs 接收请求,然后使用一个或多个 sendmsgs 传输回复,然后使用最后一个 recvmsg 接收最终 ACK。
当发送调用的数据时,如果该调用还有更多数据要发送,则为 sendmsg 提供 MSG_MORE。
当接收调用的数据时,如果该调用还有更多数据要接收,则 recvmsg 标记 MSG_MORE。
当接收调用的数据或消息时,recvmsg 标记 MSG_EOR 以指示该调用的终端消息。
可以通过将中止控制消息添加到控制数据来中止调用。发出中止会终止内核对该调用标签的使用。该调用的接收队列中等待的所有消息都将被丢弃。
中止、繁忙通知和质询数据包通过 recvmsg 传递,并且将设置控制数据消息以指示上下文。接收中止或繁忙消息会终止内核对该调用标签的使用。
msghdr struct 的控制数据部分用于多种用途
预期或受影响调用的标签。
发送或接收错误、中止和繁忙通知。
传入调用的通知。
发送调试请求和接收调试回复 [TODO]。
当内核接收并设置传入调用时,它会向服务器应用程序发送一条消息,以告知它有一个新的调用正在等待其接受 [recvmsg 报告一个特殊的控制消息]。然后,服务器应用程序使用 sendmsg 为新调用分配标签。完成后,请求数据的第一部分将由 recvmsg 传递。
服务器应用程序必须为服务器套接字提供一个密钥环,其中包含与它允许的安全类型相对应的密钥。在设置安全连接时,内核会在密钥环中查找适当的密钥,然后向客户端发送一个质询数据包并接收一个响应数据包。然后,内核检查数据包的授权,并中止连接或设置安全性。
客户端将用于保护其通信的密钥的名称由套接字选项指定。
关于 sendmsg 的说明
可以设置 MSG_WAITALL 以告诉 sendmsg 忽略信号,如果对等方在合理的时间内接受数据包,以便我们设法将所有数据排队以进行传输。这要求客户端在每个 2*RTT 时间段内至少接受一个数据包。
如果未设置,则 sendmsg() 将立即返回,如果未消耗任何内容,则返回 EINTR/ERESTARTSYS,否则返回已消耗的数据量。
关于 recvmsg 的说明
如果接收队列中存在属于特定调用的一系列数据消息,则 recvmsg 将继续处理它们,直到
它遇到该调用已接收数据的末尾,
它遇到非数据消息,
它遇到属于不同调用的消息,或者
它填满用户缓冲区。
如果在阻塞模式下调用 recvmsg,它将继续休眠,等待接收更多数据,直到满足上述四个条件之一。
MSG_PEEK 的操作类似,但是如果它在缓冲区中放入了任何数据,它将立即返回,而不是休眠直到它可以填满缓冲区。
如果数据消息仅部分消耗在填充用户缓冲区中,则该消息的剩余部分将保留在队列的前面供下一个使用者使用。永远不会标记 MSG_TRUNC。
如果调用中有更多数据要读取(它尚未复制该阶段中最后一个数据消息的最后一个字节),则将标记 MSG_MORE。
控制消息¶
AF_RXRPC 使用 sendmsg() 和 recvmsg() 中的控制消息来复用调用、调用某些操作和报告某些条件。这些是
消息 ID
SRT
数据
含义
RXRPC_USER_CALL_ID
sr-
用户 ID
应用程序的调用说明符
RXRPC_ABORT
srt
中止代码
要发出/接收的中止代码
RXRPC_ACK
-rt
不适用
收到最终 ACK
RXRPC_NET_ERROR
-rt
错误编号
调用中的网络错误
RXRPC_BUSY
-rt
不适用
调用被拒绝(服务器繁忙)
RXRPC_LOCAL_ERROR
-rt
错误编号
遇到本地错误
RXRPC_NEW_CALL
-r-
不适用
收到新调用
RXRPC_ACCEPT
s--
不适用
接受新调用
RXRPC_EXCLUSIVE_CALL
s--
不适用
进行独占客户端调用
RXRPC_UPGRADE_SERVICE
s--
不适用
客户端调用可以升级
RXRPC_TX_LENGTH
s--
数据长度
Tx 数据的总长度
(SRT = 可在 Sendmsg 中使用 / 由 Recvmsg 传递 / 终端消息)
RXRPC_USER_CALL_ID
这用于指示应用程序的调用 ID。这是一个无符号长整型,应用程序通过将其附加到第一个数据消息来在客户端中指定它,或者通过将其与 RXRPC_ACCEPT 消息关联来在服务器中传递它。 recvmsg() 将其与除 RXRPC_NEW_CALL 消息之外的所有消息一起传递。
RXRPC_ABORT
应用程序可以使用它通过将其传递给 sendmsg 来中止调用,或者它可以通过 recvmsg 传递以指示接收到远程中止。无论哪种方式,它都必须与 RXRPC_USER_CALL_ID 关联以指定受影响的调用。如果要发送中止,则如果不存在具有该用户 ID 的调用,将返回错误 EBADSLT。
RXRPC_ACK
这被传递到服务器应用程序,以指示从客户端接收到调用的最终 ACK。它将与 RXRPC_USER_CALL_ID 关联,以指示现在已完成的调用。
RXRPC_NET_ERROR
这被传递到应用程序,以指示在尝试与对等方通信的过程中遇到了 ICMP 错误消息。一个 errno 类整数值将包含在指示问题的控制消息数据中,并且 RXRPC_USER_CALL_ID 将指示受影响的调用。
RXRPC_BUSY
这被传递到客户端应用程序,以指示由于服务器繁忙,该调用已被服务器拒绝。它将与 RXRPC_USER_CALL_ID 关联,以指示被拒绝的调用。
RXRPC_LOCAL_ERROR
这被传递到应用程序,以指示遇到了本地错误,并且由于该错误而中止了调用。一个 errno 类整数值将包含在指示问题的控制消息数据中,并且 RXRPC_USER_CALL_ID 将指示受影响的调用。
RXRPC_NEW_CALL
这被传递以指示服务器应用程序已收到新调用并且正在等待接受。没有用户 ID 与此关联,因为必须通过执行 RXRPC_ACCEPT 来随后分配用户 ID。
RXRPC_ACCEPT
这被服务器应用程序用于尝试接受调用并为其分配用户 ID。它应与 RXRPC_USER_CALL_ID 关联以指示要分配的用户 ID。如果没有要接受的调用(它可能已超时、中止等),则 sendmsg 将返回错误 ENODATA。如果用户 ID 已被另一个调用使用,则将返回错误 EBADSLT。
RXRPC_EXCLUSIVE_CALL
这用于指示应在一次性连接上进行客户端调用。一旦调用终止,连接将被丢弃。
RXRPC_UPGRADE_SERVICE
这用于进行客户端调用以探测指定的服务 ID 是否可以由服务器升级。调用方必须检查返回到 recvmsg() 的 msg_name 以了解实际使用的服务 ID。探测的操作必须是在两个服务中都采用相同参数的操作。
一旦使用它建立了服务器的升级能力(或缺乏该能力),则返回的服务 ID 应用于与该服务器的所有未来通信,并且不应再设置 RXRPC_UPGRADE_SERVICE。
RXRPC_TX_LENGTH
这用于通知内核将由调用传输的数据总量(无论是在客户端请求中还是在服务响应中)。如果给定,它允许内核直接从用户空间缓冲区加密到数据包缓冲区,而不是复制到缓冲区然后在原地加密。这只能与提供调用数据的第一个 sendmsg() 一起给出。如果实际给定的数据量不同,则将生成 EMSGSIZE。
这采用 __s64 类型的参数,该参数指示将传输多少数据。这可能不小于零。
符号 RXRPC__SUPPORTED 被定义为比支持的最高控制消息类型多一个。在运行时,可以通过 RXRPC_SUPPORTED_CMSG 套接字选项查询(参见下文)。
套接字选项¶
AF_RXRPC 套接字在 SOL_RXRPC 级别支持一些套接字选项
RXRPC_SECURITY_KEY
这用于指定要使用的密钥的描述。使用 request_key() 从调用进程的密钥环中提取密钥,并且应为“rxrpc”类型。
optval 指针指向描述字符串,optlen 指示字符串的长度,不包括 NUL 终止符。
RXRPC_SECURITY_KEYRING
与上述类似,但指定要使用的服务器密钥环(密钥类型“keyring”)。请参阅“安全性”部分。
RXRPC_EXCLUSIVE_CONNECTION
这用于请求为随后在该套接字上进行的每个调用使用新连接。 optval 应为 NULL,optlen 应为 0。
RXRPC_MIN_SECURITY_LEVEL
这用于指定此套接字上的调用所需的最低安全级别。 optval 必须指向一个 int,其中包含以下值之一
RXRPC_SECURITY_PLAIN
仅加密校验和。
RXRPC_SECURITY_AUTH
加密校验和加上数据包填充和数据包的前八个字节加密 - 其中包括实际数据包长度。
RXRPC_SECURITY_ENCRYPT
加密校验和加上整个数据包填充和加密,包括实际数据包长度。
RXRPC_UPGRADEABLE_SERVICE
这用于指示具有两个绑定的服务套接字可以根据客户端的请求将一个绑定服务升级到另一个绑定服务。 optval 必须指向一个由两个无符号短整型组成的数组。第一个是要从中升级的服务 ID,第二个是要升级到的服务 ID。
RXRPC_SUPPORTED_CMSG
这是一个只读选项,它将一个 int 写入缓冲区,指示支持的最高控制消息类型。
安全性¶
目前,仅实现了 Kerberos 4 等效协议(安全索引 2 - rxkad)。这要求加载 rxkad 模块,并且在客户端上,从 AFS kaserver 或 Kerberos 服务器获取适当类型的票证,并将其安装为“rxrpc”类型密钥。这通常使用 klog 程序完成。可以在以下位置找到一个简单的 klog 程序示例:
提供给客户端上的 add_key() 的有效负载应采用以下形式
struct rxrpc_key_sec2_v1 {
uint16_t security_index; /* 2 */
uint16_t ticket_length; /* length of ticket[] */
uint32_t expiry; /* time at which expires */
uint8_t kvno; /* key version number */
uint8_t __pad[3];
uint8_t session_key[8]; /* DES session key */
uint8_t ticket[0]; /* the encrypted ticket */
};
其中票证 blob 只是附加到上述结构。
对于服务器,必须向服务器提供类型为“rxrpc_s”的密钥。它们具有“<serviceID>:<securityIndex>”的描述(例如:“52:2”表示 AFS VL 服务的 rxkad 密钥)。创建此类密钥时,应将服务器的密钥作为实例化数据提供(参见下面的示例)。
add_key(“rxrpc_s”, “52:2”, secret_key, 8, keyring);
通过在 sockopt 中命名密钥环,将其传递给服务器套接字。然后,服务器套接字在进行安全传入连接时,在该密钥环中查找服务器密钥。这可以在以下位置找到的示例程序中看到:
客户端使用示例¶
客户端将通过以下方式发出操作:
通过以下方式设置 RxRPC 套接字:
client = socket(AF_RXRPC, SOCK_DGRAM, PF_INET);其中第三个参数指示所使用的传输套接字的协议族 - 通常为 IPv4,但也可以为 IPv6 [TODO]。
可以选择绑定本地地址
struct sockaddr_rxrpc srx = { .srx_family = AF_RXRPC, .srx_service = 0, /* we're a client */ .transport_type = SOCK_DGRAM, /* type of transport socket */ .transport.sin_family = AF_INET, .transport.sin_port = htons(7000), /* AFS callback */ .transport.sin_address = 0, /* all local interfaces */ }; bind(client, &srx, sizeof(srx));这指定要使用的本地 UDP 端口。如果未给定,将使用随机的非特权端口。可以在多个不相关的 RxRPC 套接字之间共享 UDP 端口。安全处理基于每个 RxRPC 虚拟连接。
设置安全性
const char *key = "AFS:cambridge.redhat.com"; setsockopt(client, SOL_RXRPC, RXRPC_SECURITY_KEY, key, strlen(key));这会发出 request_key() 以获取表示安全上下文的密钥。可以设置最低安全级别
unsigned int sec = RXRPC_SECURITY_ENCRYPT; setsockopt(client, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL, &sec, sizeof(sec));然后可以指定要联系的服务器(或者可以通过 sendmsg 完成此操作)
struct sockaddr_rxrpc srx = { .srx_family = AF_RXRPC, .srx_service = VL_SERVICE_ID, .transport_type = SOCK_DGRAM, /* type of transport socket */ .transport.sin_family = AF_INET, .transport.sin_port = htons(7005), /* AFS volume manager */ .transport.sin_address = ..., }; connect(client, &srx, sizeof(srx));然后应使用一系列 sendmsg() 调用将请求数据发布到服务器套接字,每个调用都附加了以下控制消息
RXRPC_USER_CALL_ID
指定此调用的用户 ID
除了请求的最后一部分之外,应在 msghdr::msg_flags 中设置 MSG_MORE。可以同时发出多个请求。
还可以在第一个 sendmsg() 调用上指定 RXRPC_TX_LENGTH 控制消息。
如果打算将调用发送到通过 connect() 指定的默认目标以外的目标,则应在该调用的第一个请求消息上设置 msghdr::msg_name。
然后将回复数据发布到服务器套接字,以供 recvmsg() 拾取。如果某个特定调用有更多回复数据要读取,则 recvmsg() 将标记 MSG_MORE。将在调用的终端读取上设置 MSG_EOR。
所有数据都将随附加的以下控制消息一起传递
RXRPC_USER_CALL_ID - 指定此调用的用户 ID
如果发生中止或错误,则将改为在控制数据缓冲区中返回此信息,并且将标记 MSG_EOR 以指示该调用的结束。
客户端可以请求它知道的服务 ID,并请求如果服务器提供更好的服务,则将该服务升级为更好的服务,方法是在调用的第一个 sendmsg() 上提供 RXRPC_UPGRADE_SERVICE。然后,客户端应在收集结果时检查 recvmsg() 填写的 msg_name 中的 srx_service。如果服务忽略了升级请求,则 srx_service 将保持与提供给 sendmsg() 相同的值 - 否则将被更改以指示服务器升级到的服务 ID。请注意,升级后的服务 ID 由服务器选择。在发送任何更多调用之前,调用方必须等到它在回复中看到服务 ID(在探针结束之前,将阻止对同一目标的进一步调用)。
服务器使用示例¶
将按以下方式设置服务器以接受操作:
通过以下方式创建 RxRPC 套接字:
server = socket(AF_RXRPC, SOCK_DGRAM, PF_INET);其中第三个参数指示所使用的传输套接字的地址类型 - 通常为 IPv4。
如果需要,可以通过向套接字提供一个包含服务器密钥的密钥环来设置安全性
keyring = add_key("keyring", "AFSkeys", NULL, 0, KEY_SPEC_PROCESS_KEYRING); const char secret_key[8] = { 0xa7, 0x83, 0x8a, 0xcb, 0xc7, 0x83, 0xec, 0x94 }; add_key("rxrpc_s", "52:2", secret_key, 8, keyring); setsockopt(server, SOL_RXRPC, RXRPC_SECURITY_KEYRING, "AFSkeys", 7);在将其提供给套接字后,可以操作密钥环。这允许服务器在运行时添加更多密钥、替换密钥等。
然后必须绑定本地地址
struct sockaddr_rxrpc srx = { .srx_family = AF_RXRPC, .srx_service = VL_SERVICE_ID, /* RxRPC service ID */ .transport_type = SOCK_DGRAM, /* type of transport socket */ .transport.sin_family = AF_INET, .transport.sin_port = htons(7000), /* AFS callback */ .transport.sin_address = 0, /* all local interfaces */ }; bind(server, &srx, sizeof(srx));如果传输参数相同,则可以将多个服务 ID 绑定到一个套接字。限制目前为两个。为此,应调用 bind() 两次。
如果需要服务升级,首先必须绑定两个服务 ID,然后必须设置以下选项
unsigned short service_ids[2] = { from_ID, to_ID }; setsockopt(server, SOL_RXRPC, RXRPC_UPGRADEABLE_SERVICE, service_ids, sizeof(service_ids));如果客户端请求,这将自动将服务 from_ID 上的连接升级到服务 to_ID。当将请求数据传递到用户空间时,这将反映在通过 recvmsg() 获得的 msg_name 中。
然后将服务器设置为侦听传入调用
listen(server, 100);内核通过为每个传入连接发送一条消息来通知服务器挂起的传入连接。这是通过服务器套接字上的 recvmsg() 接收的。它没有数据,并且附加了单个无数据控制消息
RXRPC_NEW_CALL此时可以由 recvmsg() 传递回的地址应被忽略,因为发布消息的调用可能在接受时已过期 - 在这种情况下,将接受队列中仍在的第一个调用。
然后,服务器通过发出带有两段控制数据且没有实际数据的 sendmsg() 来接受新调用
RXRPC_ACCEPT
指示连接接受
RXRPC_USER_CALL_ID
指定此调用的用户 ID
然后,第一个请求数据包将发布到服务器套接字,以供 recvmsg() 拾取。此时,可以从 msghdr struct 中的地址字段读取调用的 RxRPC 地址。
随后的请求数据将发布到服务器套接字,以供 recvmsg() 随着它的到达而收集。除了请求的最后一部分之外,所有请求数据都将标记 MSG_MORE。
所有数据都将随附加的以下控制消息一起传递
RXRPC_USER_CALL_ID
指定此调用的用户 ID
然后应使用一系列 sendmsg() 调用将回复数据发布到服务器套接字,每个调用都附加了以下控制消息
RXRPC_USER_CALL_ID
指定此调用的用户 ID
除了特定调用的最后一条消息之外,应在 msghdr::msg_flags 中设置 MSG_MORE。
客户端的最终 ACK 将在收到后发布以供 recvmsg() 检索。它将采用带有两个附加控制消息的无数据消息的形式
RXRPC_USER_CALL_ID
指定此调用的用户 ID
RXRPC_ACK
指示最终 ACK(无数据)
将标记 MSG_EOR 以指示这是此调用的最终消息。
在发送回复数据的最后一个数据包之前,可以通过调用带有带有以下附加控制消息的无数据消息的 sendmsg() 来中止调用
RXRPC_USER_CALL_ID
指定此调用的用户 ID
RXRPC_ABORT
指示中止代码(4 字节数据)
如果发出此命令,则套接字接收队列中等待的任何数据包都将被丢弃。
请注意,特定服务的所有通信都通过一个服务器套接字进行,使用 sendmsg() 和 recvmsg() 上的控制消息来确定受影响的调用。
AF_RXRPC 内核接口¶
AF_RXRPC 模块还提供了一个接口,供内核实用程序(例如 AFS 文件系统)使用。这允许此类实用程序
直接在一个套接字上的单个客户端调用上使用不同的密钥,而不是必须打开大量套接字,每个密钥可能想要使用一个套接字。
避免在发出调用或打开套接字时调用 RxRPC 的 request_key()。相反,实用程序负责在适当的时候请求密钥。例如,AFS 会在诸如 open() 或 unlink() 之类的 VFS 操作期间执行此操作。然后在发起调用时传递密钥。
请求使用 GFP_KERNEL 之外的其他东西来分配内存。
避免使用 recvmsg() 调用的开销。 RxRPC 消息可以在进入套接字 Rx 队列之前被拦截,并且可以直接操作套接字缓冲区。
要使用 RxRPC 功能,内核实用程序仍然必须打开一个 AF_RXRPC 套接字,根据需要绑定地址,如果它是一个服务器套接字,则进行监听,然后将其传递给内核接口函数。
内核接口函数如下
开始一个新的客户端调用
struct rxrpc_call * rxrpc_kernel_begin_call(struct socket *sock, struct sockaddr_rxrpc *srx, struct key *key, unsigned long user_call_ID, s64 tx_total_len, gfp_t gfp, rxrpc_notify_rx_t notify_rx, bool upgrade, bool intr, unsigned int debug_id);这会分配用于发起新 RxRPC 调用的基础结构,并分配调用和连接号。调用将在套接字绑定到的 UDP 端口上进行。除非提供了替代地址(srx 为非 NULL),否则该调用将转到已连接客户端套接字的目标地址。
如果提供了密钥,那么将使用它来保护调用,而不是使用 RXRPC_SECURITY_KEY sockopt 绑定到套接字的密钥。以这种方式保护的调用仍然会尽可能地共享连接。
user_call_ID 等同于在控制数据缓冲区中提供给 sendmsg() 的 ID。完全可以使用它来指向内核数据结构。
tx_total_len 是调用者打算通过此调用传输的数据量(如果此时未知,则为 -1)。设置数据大小允许内核直接加密到数据包缓冲区,从而节省复制。该值不能小于 -1。
notify_rx 是指向函数的指针,该函数在发生诸如传入数据包或远程中止之类的事件时被调用。
如果客户端操作应请求服务器将服务升级到更好的服务,则应将 upgrade 设置为 true。生成的服务 ID 由
rxrpc_kernel_recv_data()
返回。如果该调用应可中断,则应将 intr 设置为 true。如果未设置此项,则此函数可能不会返回,直到分配了一个通道;如果设置了此项,该函数可能会返回 -ERESTARTSYS。
debug_id 是用于跟踪的调用调试 ID。可以通过原子方式递增 rxrpc_debug_id 来获得此 ID。
如果此函数成功,则返回对 RxRPC 调用的不透明引用。调用者现在持有此引用,并且必须正确结束它。
关闭客户端调用
void rxrpc_kernel_shutdown_call(struct socket *sock, struct rxrpc_call *call);用于关闭先前开始的调用。 user_call_ID 从 AF_RXRPC 的知识中删除,并且不会再次与指定的调用关联。
释放对客户端调用的引用
void rxrpc_kernel_put_call(struct socket *sock, struct rxrpc_call *call);用于释放调用者对 rxrpc 调用的引用。
通过调用发送数据
typedef void (*rxrpc_notify_end_tx_t)(struct sock *sk, unsigned long user_call_ID, struct sk_buff *skb); int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call, struct msghdr *msg, size_t len, rxrpc_notify_end_tx_t notify_end_rx);用于提供客户端调用的请求部分或服务器调用的回复部分。 msg.msg_iovlen 和 msg.msg_iov 指定要使用的数据缓冲区。 msg_iov 不得为 NULL,并且必须专门指向内核虚拟地址。如果此调用将有后续数据发送,则可以给出 msg.msg_flags MSG_MORE。
msg 不得指定目标地址、控制数据或 MSG_MORE 之外的任何标志。 len 是要传输的数据总量。
notify_end_rx 可以为 NULL,也可以用于指定当调用状态更改为结束 Tx 阶段时要调用的函数。调用此函数时会持有一个自旋锁,以防止在函数返回之前传输最后一个 DATA 数据包。
从调用接收数据
int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call, void *buf, size_t size, size_t *_offset, bool want_more, u32 *_abort, u16 *_service) This is used to receive data from either the reply part of a client call or the request part of a service call. buf and size specify how much data is desired and where to store it. *_offset is added on to buf and subtracted from size internally; the amount copied into the buffer is added to *_offset before returning. want_more should be true if further data will be required after this is satisfied and false if this is the last item of the receive phase. There are three normal returns: 0 if the buffer was filled and want_more was true; 1 if the buffer was filled, the last DATA packet has been emptied and want_more was false; and -EAGAIN if the function needs to be called again. If the last DATA packet is processed but the buffer contains less than the amount requested, EBADMSG is returned. If want_more wasn't set, but more data was available, EMSGSIZE is returned. If a remote ABORT is detected, the abort code received will be stored in ``*_abort`` and ECONNABORTED will be returned. The service ID that the call ended up with is returned into *_service. This can be used to see if a call got a service upgrade.中止调用??
void rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call, u32 abort_code);如果调用仍处于可中止状态,则可以使用此函数中止调用。指定的中止代码将放置在发送的 ABORT 消息中。
拦截接收到的 RxRPC 消息
typedef void (*rxrpc_interceptor_t)(struct sock *sk, unsigned long user_call_ID, struct sk_buff *skb); void rxrpc_kernel_intercept_rx_messages(struct socket *sock, rxrpc_interceptor_t interceptor);这将在指定的 AF_RXRPC 套接字上安装一个拦截器函数。所有原本会进入套接字 Rx 队列的消息都会被转移到此函数。请注意,必须小心地按正确的顺序处理消息,以保持 DATA 消息的顺序性。
拦截器函数本身会获得套接字的地址和处理传入消息、内核实用程序分配给调用的 ID 以及包含该消息的套接字缓冲区。
skb->mark 字段指示消息的类型
标记
含义
RXRPC_SKB_MARK_DATA
数据消息
RXRPC_SKB_MARK_FINAL_ACK
收到的传入调用的最终 ACK
RXRPC_SKB_MARK_BUSY
客户端调用被拒绝,因为服务器繁忙
RXRPC_SKB_MARK_REMOTE_ABORT
调用被对等方中止
RXRPC_SKB_MARK_NET_ERROR
检测到网络错误
RXRPC_SKB_MARK_LOCAL_ERROR
遇到本地错误
RXRPC_SKB_MARK_NEW_CALL
等待接受的新传入调用
可以使用 rxrpc_kernel_get_abort_code() 探测远程中止消息。可以使用 rxrpc_kernel_get_error_number() 探测两条错误消息。可以使用 rxrpc_kernel_accept_call() 接受新的调用。
可以使用通常的套接字缓冲区操作函数提取数据消息的内容。可以使用 rxrpc_kernel_is_data_last() 确定数据消息是否是序列中的最后一个消息。当数据消息被用完时,应该在其上调用 rxrpc_kernel_data_consumed()。
应将消息处理为 rxrpc_kernel_free_skb() 以进行处置。可以获得所有类型的消息的额外引用以供以后释放,但这可能会固定调用的状态,直到最终释放该消息。
接受传入调用
struct rxrpc_call * rxrpc_kernel_accept_call(struct socket *sock, unsigned long user_call_ID);用于接受传入调用并为其分配调用 ID。此函数类似于
rxrpc_kernel_begin_call()
,并且接受的调用必须以相同的方式结束。如果此函数成功,则返回对 RxRPC 调用的不透明引用。调用者现在持有此引用,并且必须正确结束它。
拒绝传入调用
int rxrpc_kernel_reject_call(struct socket *sock);用于拒绝套接字队列中的第一个传入调用,并显示 BUSY 消息。如果没有传入调用,则返回 -ENODATA。如果调用已被中止 (-ECONNABORTED) 或已超时 (-ETIME),则可能会返回其他错误。
分配一个空密钥以进行匿名安全
struct key *rxrpc_get_null_key(const char *keyname);用于分配一个空 RxRPC 密钥,该密钥可用于指示特定域的匿名安全。
获取调用的对等地址
void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call, struct sockaddr_rxrpc *_srx);用于查找调用的远程对等地址。
设置调用中的总传输数据大小
void rxrpc_kernel_set_tx_length(struct socket *sock, struct rxrpc_call *call, s64 tx_total_len);设置调用者打算在调用中传输的数据量。它旨在用于设置回复大小,因为请求大小应在调用开始时设置。 tx_total_len 不得小于零。
获取调用 RTT
u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call);获取调用正在使用的对等方的 RTT 时间。返回的值以纳秒为单位。
检查调用是否仍然有效
bool rxrpc_kernel_check_life(struct socket *sock, struct rxrpc_call *call, u32 *_life); void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call);第一个函数在
*_life
中传递回一个数字,该数字在收到来自对等方的 ACK 时更新(特别包括我们可以通过发送 PING ACK 来引出的 PING RESPONSE ACK,以查看调用是否仍然存在于服务器上)。调用者应比较两个调用的数字,以查看在等待适当的间隔后调用是否仍然有效。只要调用尚未达到完成状态,它也会返回 true。这允许调用者在等待服务器处理客户端操作时确定服务器是否仍然可连接以及调用是否仍然在服务器上有效。
第二个函数会导致传输一个 ping ACK 以尝试刺激对等方进行响应,这将导致第一个函数返回的值发生更改。请注意,必须在 TASK_RUNNING 状态下调用此函数。
从内核内部将 RXRPC_MIN_SECURITY_LEVEL sockopt 应用于套接字
int rxrpc_sock_set_min_security_level(struct sock *sk, unsigned int val);这指定了此套接字上的调用所需的最低安全级别。
可配置参数¶
RxRPC 协议驱动程序具有许多可通过 /proc/net/rxrpc/ 中的 sysctl 进行调整的可配置参数。
req_ack_delay
在我们收到设置了 request-ack 标志的数据包后,在实际响应标志并实际发送所请求的 ack 之前的毫秒数。
通常,另一方在通告的接收窗口已满(最多 255 个数据包)之前不会停止发送数据包,因此延迟 ACK 允许一次 ACK 多个数据包。
soft_ack_delay
在我们收到一个新数据包后,在我们生成一个 soft-ACK 以告知发送者它不需要重新发送之前的毫秒数。
idle_ack_delay
在我们使用完接收队列中当前的所有数据包之后,在我们生成一个 hard-ACK 以告知发送者它可以释放其缓冲区之前的毫秒数,假设没有发生我们会发送 ACK 的其他原因。
resend_timeout
在我们传输一个数据包之后,在我们再次传输它之前的毫秒数,假设我们没有收到来自接收者的 ACK 告知我们他们收到了该数据包。
max_call_lifetime
在我们抢先终止调用之前,调用可能进行的以秒为单位的最长时间。
dead_call_expiry
在我们从调用列表中删除已死调用之前的以秒为单位的时间量。已死调用会保留一段时间,目的是重复 ACK 和 ABORT 数据包。
connection_expiry
在我们从连接列表中删除连接之前,连接上次使用的以秒为单位的时间量。当连接存在时,它可以作为协商的安全的占位符;当它被删除时,必须重新协商安全。
transport_expiry
在我们从传输列表中删除传输之前,传输上次使用的以秒为单位的时间量。当传输存在时,它可以作为对等数据和保持连接 ID 计数器的锚点。
rxrpc_rx_window_size
接收窗口的大小(以数据包为单位)。这是我们愿意为任何特定调用在内存中保存的未使用的接收数据包的最大数量。
rxrpc_rx_mtu
我们愿意接收的最大的数据包 MTU 大小(以字节为单位)。这向对等方表明我们是否愿意接受巨型数据包。
rxrpc_rx_jumbo_max
我们愿意在巨型数据包中接受的数据包的最大数量。巨型数据包中的非终端数据包必须包含一个四字节标头加上恰好 1412 字节的数据。终端数据包必须包含一个四字节标头加上任意数量的数据。在任何情况下,巨型数据包的大小都不得超过 rxrpc_rx_mtu。
API 函数参考¶
-
struct rxrpc_peer *rxrpc_kernel_lookup_peer(struct socket *sock, struct sockaddr_rxrpc *srx, gfp_t gfp)¶
获取地址的远程传输端点
参数
struct socket *sock
将通过其访问的套接字
struct sockaddr_rxrpc *srx
网络地址
gfp_t gfp
分配标志
描述
查找或创建指定地址的远程传输端点记录。
返回
找到的带有引用的对等记录,如果找不到记录,则返回 NULL
;如果地址无效或不受支持,则返回负错误代码。
-
struct rxrpc_peer *rxrpc_kernel_get_peer(struct rxrpc_peer *peer)¶
获取对等方的引用
参数
struct rxrpc_peer *peer
要获取引用的对等方(可以为 NULL)。
描述
获取远程对等记录的引用(如果不是 NULL)。
返回
peer 参数。
-
void rxrpc_kernel_put_peer(struct rxrpc_peer *peer)¶
允许内核应用程序删除对等引用
参数
struct rxrpc_peer *peer
要删除引用的对等方
描述
删除对等记录的引用。
-
struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, struct rxrpc_peer *peer, struct key *key, unsigned long user_call_ID, s64 tx_total_len, u32 hard_timeout, gfp_t gfp, rxrpc_notify_rx_t notify_rx, u16 service_id, bool upgrade, enum rxrpc_interruptibility interruptibility, unsigned int debug_id)¶
允许内核服务开始调用
参数
struct socket *sock
要在其上进行调用的套接字
struct rxrpc_peer *peer
要联系的对等方
struct key *key
要使用的安全上下文(默认为套接字设置)
unsigned long user_call_ID
要使用的 ID
s64 tx_total_len
在调用期间要传输的数据的总长度(或 -1)
u32 hard_timeout
调用最长的生存期(以秒为单位)
gfp_t gfp
分配约束
rxrpc_notify_rx_t notify_rx
将通知发送到何处而不是发送到套接字队列
u16 service_id
要联系的服务的 ID
bool upgrade
请求调用的服务升级
enum rxrpc_interruptibility interruptibility
调用可中断,或者可以取消。
unsigned int debug_id
要分配给调用的跟踪的调试 ID
描述
允许内核服务在指定的套接字上开始调用。这只是设置所有内部跟踪结构,并根据需要分配连接和调用 ID。
可以通过提供 srx 和 key 来覆盖默认的套接字目标地址和安全性。
返回
新调用或错误代码。
参数
struct socket *sock
调用所在的套接字
struct rxrpc_call *call
要结束的调用
描述
允许内核服务关闭其正在使用的调用。必须先完成调用才能调用此函数(如有必要,应中止调用)。
参数
struct socket *sock
调用所在的套接字
struct rxrpc_call *call
要放置的调用
描述
删除应用程序对 rxrpc 调用的引用。
参数
const struct socket *sock
调用所在的套接字
const struct rxrpc_call *call
要检查的调用
描述
允许内核服务找出调用是否仍然有效 - 它是否已成功完成并且是否已使用所有收到的数据。
返回
如果调用仍在进行中,则为 true
;如果已完成,则为 false
。
-
void rxrpc_kernel_set_notifications(struct socket *sock, const struct rxrpc_kernel_ops *app_ops)¶
设置回调操作表
参数
struct socket *sock
要在其上安装表的套接字
const struct rxrpc_kernel_ops *app_ops
要设置的回调操作表
描述
允许内核服务在套接字上设置事件通知表。
-
u8 rxrpc_kernel_query_call_security(struct rxrpc_call *call, u16 *_service_id, u32 *_enctype)¶
查询调用的安全参数
参数
struct rxrpc_call *call
要查询的调用
u16 *_service_id
在何处返回服务 ID
u32 *_enctype
在何处返回“编码类型”
描述
这将查询调用的安全参数,设置 *_service_id 和 *_enctype 并返回安全类。
返回
安全类协议号。
-
struct key *rxrpc_get_null_key(const char *keyname)¶
生成一个空的 RxRPC 密钥
参数
const char *keyname
用于指定密钥的名称。
描述
生成一个空的 RxRPC 密钥,可用于指示特定域需要匿名安全。
返回
新密钥或负错误代码。
-
enum rxrpc_oob_type rxrpc_kernel_query_oob(struct sk_buff *oob, struct rxrpc_peer **_peer, unsigned long *_peer_appdata)¶
查询带外消息的参数
参数
struct sk_buff *oob
要查询的消息
struct rxrpc_peer **_peer
用于返回对等体记录的位置
unsigned long *_peer_appdata
附加到对等体记录的应用程序数据
描述
从带外消息中提取有用的参数。源对等体参数通过参数列表返回,消息类型也被返回。
返回
RXRPC_OOB_CHALLENGE
- 需要响应的挑战。
-
struct sk_buff *rxrpc_kernel_dequeue_oob(struct socket *sock, enum rxrpc_oob_type *_type)¶
出列并返回最前面的 OOB 消息
参数
struct socket *sock
要查询的套接字
enum rxrpc_oob_type *_type
用于返回消息类型的位置
描述
出列最前面的 OOB 消息(如果存在),并返回它及其类型。
返回
表示 OOB 消息的 sk_buff 或 NULL
(如果队列为空)。
参数
struct sk_buff *oob
要释放的 OOB 消息
描述
释放 OOB 消息以及它所拥有的任何资源。
-
void rxrpc_kernel_query_challenge(struct sk_buff *challenge, struct rxrpc_peer **_peer, unsigned long *_peer_appdata, u16 *_service_id, u8 *_security_index)¶
查询挑战的参数
参数
struct sk_buff *challenge
要查询的挑战
struct rxrpc_peer **_peer
用于返回对等体记录的位置
unsigned long *_peer_appdata
附加到对等体记录的应用程序数据
u16 *_service_id
用于返回连接服务 ID 的位置
u8 *_security_index
用于返回连接安全索引的位置
描述
从 CHALLENGE 消息中提取有用的参数。
-
int rxrpc_kernel_reject_challenge(struct sk_buff *challenge, u32 abort_code, int error, enum rxrpc_abort_reason why)¶
允许内核服务拒绝挑战
参数
struct sk_buff *challenge
要拒绝的挑战
u32 abort_code
要放入 ABORT 数据包中的中止代码
int error
本地错误值
enum rxrpc_abort_reason why
指示原因。
描述
允许内核服务通过中止连接(如果它仍处于可中止状态)来拒绝挑战。返回错误,以便可以将此函数与 return 语句一起使用。
返回
The error
parameter.
-
struct rxrpc_peer *rxrpc_kernel_get_call_peer(struct socket *sock, struct rxrpc_call *call)¶
获取调用的对等地址
参数
struct socket *sock
呼叫正在进行的套接字。
struct rxrpc_call *call
要查询的调用
描述
获取呼叫中远程对等体的记录。
返回
呼叫的对等体记录。
-
unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *peer)¶
获取呼叫的对等体平滑 RTT
参数
const struct rxrpc_peer *peer
要查询的对等体
描述
获取呼叫的对等体平滑 RTT。
返回
以 uS 为单位的 RTT,或者如果没有样本,则为 UINT_MAX
。
-
const struct sockaddr_rxrpc *rxrpc_kernel_remote_srx(const struct rxrpc_peer *peer)¶
获取对等体的地址
参数
const struct rxrpc_peer *peer
要查询的对等体
描述
从对等体记录获取指向地址的指针。调用方负责确保地址未被释放。如果 peer
为 NULL,则将替换为伪造地址。
返回
rxrpc 地址记录或伪造记录。
-
const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *peer)¶
获取呼叫的对等体传输地址
参数
const struct rxrpc_peer *peer
要查询的对等体
描述
从对等体记录获取指向传输地址的指针。调用方负责确保地址未被释放。如果 peer
为 NULL,则将替换为伪造地址。
返回
传输地址记录或伪造记录。
-
unsigned long rxrpc_kernel_set_peer_data(struct rxrpc_peer *peer, unsigned long app_data)¶
在对等体上设置应用程序特定的数据。
参数
struct rxrpc_peer *peer
要更改的对等体
unsigned long app_data
要设置的数据
描述
在对等体上设置应用程序特定的数据。AF_RXRPC 不会尽力保留数据可能引用的任何内容。
返回
先前的 app_data。
-
unsigned long rxrpc_kernel_get_peer_data(const struct rxrpc_peer *peer)¶
从对等体获取应用程序特定的数据。
参数
const struct rxrpc_peer *peer
要查询的对等体
描述
从对等体检索应用程序特定的数据。
返回
对等体的应用程序数据。
-
int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call, struct iov_iter *iter, size_t *_len, bool want_more, u32 *_abort, u16 *_service)¶
允许内核服务接收数据/信息
参数
struct socket *sock
呼叫存在的套接字
struct rxrpc_call *call
用于发送数据的呼叫
struct iov_iter *iter
要接收到的缓冲区
size_t *_len
我们要接收的数据量(在返回时减少)
bool want_more
如果期望读取更多数据,则为 True
u32 *_abort
如果返回 -ECONNABORTED,则中止代码的存储位置
u16 *_service
实际服务 ID 的存储位置(可能会升级)
描述
允许内核服务接收数据并获取有关呼叫状态的信息。请注意,*_abort 也应初始化为 0
。
请注意,即使我们已经复制了请求的数据,我们也可以返回 -EAGAIN
以在数据末尾耗尽空数据包。
返回
如果获得了所请求的内容并且有更多可用内容,则为 0
;如果获得了所请求的内容并且我们位于数据末尾,则为 1
;如果我们需要更多数据,则为 -EAGAIN
。
参数
struct sk_buff *challenge
要查询的挑战数据包
返回
被挑战连接的 Kerberos 5 编码类型。
-
int rxgk_kernel_respond_to_challenge(struct sk_buff *challenge, struct krb5_buffer *appdata)¶
使用 appdata 响应挑战
参数
struct sk_buff *challenge
要响应的挑战
struct krb5_buffer *appdata
要包含在 RESPONSE 验证器中的应用程序数据
描述
允许内核应用程序使用要包含在 RxGK RESPONSE 验证器中的应用程序数据来响应 CHALLENGE。
返回
如果成功,则为 0
,否则为负错误代码。
参数
struct sk_buff *challenge
要响应的挑战
描述
允许内核应用程序响应 CHALLENGE。
返回
如果成功,则为 0
,否则为负错误代码。
-
int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call, struct msghdr *msg, size_t len, rxrpc_notify_end_tx_t notify_end_tx)¶
允许内核服务在呼叫上发送数据
参数
struct socket *sock
调用所在的套接字
struct rxrpc_call *call
用于发送数据的呼叫
struct msghdr *msg
要发送的数据
size_t len
要发送的数据量
rxrpc_notify_end_tx_t notify_end_tx
最后一个数据包已排队的通知。
描述
允许内核服务在呼叫上发送数据。呼叫必须处于适合发送数据的状态。不应在 msg 中提供控制数据,也不应提供地址。如果还有更多数据要发送,则应标记 MSG_MORE,否则此数据将结束传输阶段。
返回
如果成功,则为 0
,否则为负错误代码。
-
bool rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call, u32 abort_code, int error, enum rxrpc_abort_reason why)¶
允许内核服务中止一个调用
参数
struct socket *sock
调用所在的套接字
struct rxrpc_call *call
要中止的调用
u32 abort_code
要放入 ABORT 数据包中的中止代码
int error
本地错误值
enum rxrpc_abort_reason why
指示原因。
描述
允许内核服务在调用仍处于可中止状态时中止它。
返回
如果调用已中止,则为true
,如果调用已经完成,则为false
。
-
void rxrpc_kernel_set_tx_length(struct socket *sock, struct rxrpc_call *call, s64 tx_total_len)¶
设置调用上的总 Tx 长度
参数
struct socket *sock
调用所在的套接字
struct rxrpc_call *call
要通知的调用
s64 tx_total_len
此调用要传输的数据量
描述
允许内核服务设置调用上的总传输长度。这允许执行 buffer-to-packet encrypt-and-copy。
此函数主要用于设置回复长度,因为可以在开始调用时设置请求长度。
参数
struct sock *sk
要在其上设置密钥环的套接字
struct key *keyring
要设置的密钥环
描述
在 rxrpc 套接字上设置服务器安全密钥环。这用于为内核服务提供加密密钥。
返回
如果成功,则为 0
,否则为负错误代码。
参数
struct sock *sk
要在其上设置密钥环的套接字
bool set
True 设置,false 清除标志
描述
在 rxrpc 套接字上设置标志,以表明调用者想要管理 RESPONSE 数据包及其可能包含的用户定义数据。 设置此标志意味着 recvmsg() 将返回控制消息缓冲区中包含 RXRPC_CHALLENGED 的消息,其中包含有关挑战的信息。
用户应该通过使用 sendmsg() 向同一个调用传递带有 RXRPC_RESPOND 或 RXRPC_RESPOND_ABORT 控制消息来响应挑战。 可以包含补充控制消息,例如 RXRPC_RESP_RXGK_APPDATA,以指示用户想要提供的部分。
当服务器从每个调用中获取第一个数据时,将使用 RXRPC_RESPONDED 控制消息将响应数据传递给服务器。
请注意,这仅适用于需要辅助数据的安全类(例如 RxGK)。 那些不提供该功能的(例如 RxKAD)会在不咨询用户空间的情况下做出响应。
返回
先前的设置。