Skip to content

Commit ef20690

Browse files
Geliang Tangintel-lab-lkp
authored andcommitted
selftests: mptcp: sockopt: add TCP_INQ server connection
Implement connect_one_server_inq() featuring: - Wait mechanisms for ACK verification - Large data transmission with flow control - Proper shutdown sequence handling - Integration with IPC signaling These codes are from mptcp_inq.c. Signed-off-by: Geliang Tang <[email protected]>
1 parent 0bc49b6 commit ef20690

File tree

1 file changed

+115
-1
lines changed

1 file changed

+115
-1
lines changed

tools/testing/selftests/net/mptcp/mptcp_sockopt.c

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <netinet/in.h>
2828

2929
#include <linux/tcp.h>
30+
#include <linux/sockios.h>
3031

3132
static int pf = AF_INET;
3233
static int proto_tx = IPPROTO_MPTCP;
@@ -660,6 +661,116 @@ static void connect_one_server(int fd, int pipefd)
660661
close(fd);
661662
}
662663

664+
/* wait up to timeout milliseconds */
665+
static void wait_for_ack(int fd, int timeout, size_t total)
666+
{
667+
int i;
668+
669+
for (i = 0; i < timeout; i++) {
670+
int nsd, ret, queued = -1;
671+
struct timespec req;
672+
673+
ret = ioctl(fd, TIOCOUTQ, &queued);
674+
if (ret < 0)
675+
die_perror("TIOCOUTQ");
676+
677+
ret = ioctl(fd, SIOCOUTQNSD, &nsd);
678+
if (ret < 0)
679+
die_perror("SIOCOUTQNSD");
680+
681+
if ((size_t)queued > total)
682+
xerror("TIOCOUTQ %u, but only %zu expected\n", queued, total);
683+
assert(nsd <= queued);
684+
685+
if (queued == 0)
686+
return;
687+
688+
/* wait for peer to ack rx of all data */
689+
req.tv_sec = 0;
690+
req.tv_nsec = 1 * 1000 * 1000ul; /* 1ms */
691+
nanosleep(&req, NULL);
692+
}
693+
694+
xerror("still tx data queued after %u ms\n", timeout);
695+
}
696+
697+
static void connect_one_server_inq(int fd, int unixfd)
698+
{
699+
size_t len, i, total, sent;
700+
char buf[4096], buf2[4096];
701+
ssize_t ret;
702+
703+
len = rand() % (sizeof(buf) - 1);
704+
705+
if (len < 128)
706+
len = 128;
707+
708+
for (i = 0; i < len ; i++) {
709+
buf[i] = rand() % 26;
710+
buf[i] += 'A';
711+
}
712+
713+
buf[i] = '\n';
714+
715+
/* un-block server */
716+
ret = read(unixfd, buf2, 4);
717+
assert(ret == 4);
718+
719+
assert(strncmp(buf2, "xmit", 4) == 0);
720+
721+
ret = write(unixfd, &len, sizeof(len));
722+
assert(ret == (ssize_t)sizeof(len));
723+
724+
ret = write(fd, buf, len);
725+
if (ret < 0)
726+
die_perror("write");
727+
728+
if (ret != (ssize_t)len)
729+
xerror("short write");
730+
731+
ret = read(unixfd, buf2, 4);
732+
assert(strncmp(buf2, "huge", 4) == 0);
733+
734+
total = rand() % (16 * 1024 * 1024);
735+
total += (1 * 1024 * 1024);
736+
sent = total;
737+
738+
ret = write(unixfd, &total, sizeof(total));
739+
assert(ret == (ssize_t)sizeof(total));
740+
741+
wait_for_ack(fd, 5000, len);
742+
743+
while (total > 0) {
744+
if (total > sizeof(buf))
745+
len = sizeof(buf);
746+
else
747+
len = total;
748+
749+
ret = write(fd, buf, len);
750+
if (ret < 0)
751+
die_perror("write");
752+
total -= ret;
753+
754+
/* we don't have to care about buf content, only
755+
* number of total bytes sent
756+
*/
757+
}
758+
759+
ret = read(unixfd, buf2, 4);
760+
assert(ret == 4);
761+
assert(strncmp(buf2, "shut", 4) == 0);
762+
763+
wait_for_ack(fd, 5000, sent);
764+
765+
ret = write(fd, buf, 1);
766+
assert(ret == 1);
767+
close(fd);
768+
ret = write(unixfd, "closed", 6);
769+
assert(ret == 6);
770+
771+
close(unixfd);
772+
}
773+
663774
static void process_one_client(int fd, int pipefd)
664775
{
665776
ssize_t ret, ret2, ret3;
@@ -961,7 +1072,10 @@ static int client(int ipcfd)
9611072

9621073
test_ip_tos_sockopt(fd);
9631074

964-
connect_one_server(fd, ipcfd);
1075+
if (inq)
1076+
connect_one_server_inq(fd, ipcfd);
1077+
else
1078+
connect_one_server(fd, ipcfd);
9651079

9661080
return 0;
9671081
}

0 commit comments

Comments
 (0)