From: Geliang Tang <tanggeliang@kylinos.cn>
Integrate process_one_client() and get_tcp_inq() from mptcp_inq.c into
mptcp_sockopt.c, and rename process_one_client() to process_inq_client()
to handle TCP_INQ-specific operations on server side.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
.../selftests/net/mptcp/mptcp_sockopt.c | 155 +++++++++++++++++-
1 file changed, 153 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index aadef8b0aea4..f5342903a80a 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/random.h>
+#include <sys/ioctl.h>
#include <netdb.h>
#include <netinet/in.h>
@@ -716,6 +717,153 @@ static void process_one_client(int fd, int ipcfd)
close(fd);
}
+static void get_tcp_inq(struct msghdr *msgh, unsigned int *inqv)
+{
+ struct cmsghdr *cmsg;
+
+ for (cmsg = CMSG_FIRSTHDR(msgh); cmsg ; cmsg = CMSG_NXTHDR(msgh, cmsg)) {
+ if (cmsg->cmsg_level == IPPROTO_TCP && cmsg->cmsg_type == TCP_CM_INQ) {
+ memcpy(inqv, CMSG_DATA(cmsg), sizeof(*inqv));
+ return;
+ }
+ }
+
+ xerror("could not find TCP_CM_INQ cmsg type");
+}
+
+static void process_inq_client(int fd, int ipcfd)
+{
+ unsigned int tcp_inq;
+ size_t expect_len;
+ char msg_buf[4096];
+ char buf[4096];
+ char tmp[16];
+ struct iovec iov = {
+ .iov_base = buf,
+ .iov_len = 1,
+ };
+ struct msghdr msg = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = msg_buf,
+ .msg_controllen = sizeof(msg_buf),
+ };
+ ssize_t ret, tot;
+
+ ret = write(ipcfd, "xmit", 4);
+ assert(ret == 4);
+
+ ret = read(ipcfd, &expect_len, sizeof(expect_len));
+ assert(ret == (ssize_t)sizeof(expect_len));
+
+ if (expect_len > sizeof(buf))
+ xerror("expect len %zu exceeds buffer size", expect_len);
+
+ for (;;) {
+ struct timespec req;
+ unsigned int queued;
+
+ ret = ioctl(fd, FIONREAD, &queued);
+ if (ret < 0)
+ die_perror("FIONREAD");
+ if (queued > expect_len)
+ xerror("FIONREAD returned %u, but only %zu expected\n",
+ queued, expect_len);
+ if (queued == expect_len)
+ break;
+
+ req.tv_sec = 0;
+ req.tv_nsec = 1000 * 1000ul;
+ nanosleep(&req, NULL);
+ }
+
+ /* read one byte, expect cmsg to return expected - 1 */
+ ret = recvmsg(fd, &msg, 0);
+ if (ret < 0)
+ die_perror("recvmsg");
+
+ if (msg.msg_controllen == 0)
+ xerror("msg_controllen is 0");
+
+ get_tcp_inq(&msg, &tcp_inq);
+
+ assert((size_t)tcp_inq == (expect_len - 1));
+
+ iov.iov_len = sizeof(buf);
+ ret = recvmsg(fd, &msg, 0);
+ if (ret < 0)
+ die_perror("recvmsg");
+
+ /* should have gotten exact remainder of all pending data */
+ assert(ret == (ssize_t)tcp_inq);
+
+ /* should be 0, all drained */
+ get_tcp_inq(&msg, &tcp_inq);
+ assert(tcp_inq == 0);
+
+ /* request a large swath of data. */
+ ret = write(ipcfd, "huge", 4);
+ assert(ret == 4);
+
+ ret = read(ipcfd, &expect_len, sizeof(expect_len));
+ assert(ret == (ssize_t)sizeof(expect_len));
+
+ /* peer should send us a few mb of data */
+ if (expect_len <= sizeof(buf))
+ xerror("expect len %zu too small\n", expect_len);
+
+ tot = 0;
+ do {
+ iov.iov_len = sizeof(buf);
+ ret = recvmsg(fd, &msg, 0);
+ if (ret < 0)
+ die_perror("recvmsg");
+
+ tot += ret;
+
+ get_tcp_inq(&msg, &tcp_inq);
+
+ if (tcp_inq > expect_len - tot)
+ xerror("inq %d, remaining %d total_len %d\n",
+ tcp_inq, expect_len - tot, (int)expect_len);
+
+ assert(tcp_inq <= expect_len - tot);
+ } while ((size_t)tot < expect_len);
+
+ ret = write(ipcfd, "shut", 4);
+ assert(ret == 4);
+
+ /* wait for hangup. Should have received one more byte of data. */
+ ret = read(ipcfd, tmp, sizeof(tmp));
+ assert(ret == 6);
+ assert(strncmp(tmp, "closed", 6) == 0);
+
+ sleep(1);
+
+ iov.iov_len = 1;
+ ret = recvmsg(fd, &msg, 0);
+ if (ret < 0)
+ die_perror("recvmsg");
+ assert(ret == 1);
+
+ get_tcp_inq(&msg, &tcp_inq);
+
+ /* tcp_inq should be 1 due to received fin. */
+ assert(tcp_inq == 1);
+
+ iov.iov_len = 1;
+ ret = recvmsg(fd, &msg, 0);
+ if (ret < 0)
+ die_perror("recvmsg");
+
+ /* expect EOF */
+ assert(ret == 0);
+ get_tcp_inq(&msg, &tcp_inq);
+ assert(tcp_inq == 1);
+
+ close(fd);
+}
+
static int xaccept(int s)
{
int fd = accept(s, NULL, 0);
@@ -756,10 +904,13 @@ static int server(int ipcfd)
alarm(15);
r = xaccept(fd);
- if (inq)
+ if (inq) {
do_setsockopt_inq(r);
- process_one_client(r, ipcfd);
+ process_inq_client(r, ipcfd);
+ } else {
+ process_one_client(r, ipcfd);
+ }
close(fd);
return 0;
--
2.48.1