--- test/zdtm/customization/Makefile | 3 +- test/zdtm/customization/tcp00.c | 101 +++++++++++++++++++++++++++++ test/zdtm/customization/tcp00.desc | 1 + 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 test/zdtm/customization/tcp00.c create mode 100644 test/zdtm/customization/tcp00.desc
diff --git a/test/zdtm/customization/Makefile b/test/zdtm/customization/Makefile index 728646b..1111908 100644 --- a/test/zdtm/customization/Makefile +++ b/test/zdtm/customization/Makefile @@ -13,7 +13,8 @@ TST_NOFILE = \ maps008 \ notifier00 \ chardev00 \ - infiniband_with_unix_sk + infiniband_with_unix_sk \ + tcp00
TST_FILE = \ maps00 \ diff --git a/test/zdtm/customization/tcp00.c b/test/zdtm/customization/tcp00.c new file mode 100644 index 0000000..d1ead82 --- /dev/null +++ b/test/zdtm/customization/tcp00.c @@ -0,0 +1,101 @@ +#include <stdio.h> +#include <stdbool.h> +#include <unistd.h> +#include <string.h> +#include <arpa/inet.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include "zdtmtst.h" + +#define PORT 17173 + +const char *test_doc = "Test TCP SO_REUSEADDR checkpoint/restore using `share_{src,dst}_ports`"; + +static int sock_bind_and_listen(void) +{ + int serv_sk; + int optval = 1; + struct sockaddr_in serv = { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl(INADDR_ANY), + .sin_port = htons(PORT), + }; + + serv_sk = socket(AF_INET, SOCK_STREAM, 0); + if (serv_sk < 0) { + pr_perror("server socket failed"); + exit(1); + } + + if (setsockopt(serv_sk, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { + pr_perror("setsockopt"); + exit(1); + } + + if (bind(serv_sk, (struct sockaddr *)&serv, sizeof(serv)) < 0) { + pr_perror("bind"); + exit(1); + } + + if (listen(serv_sk, 5) != 0) { + pr_perror("listen"); + exit(1); + } + + return serv_sk; +} + +static void client_connect(void) +{ + int sk; + struct sockaddr_in sockaddr = { + .sin_family = AF_INET, + }; + + sk = socket(AF_INET, SOCK_STREAM, 0); + if (sk < 0) { + pr_perror("client socket failed"); + exit(1); + } + + sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + sockaddr.sin_port = htons(PORT); + + if (connect(sk, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { + pr_perror("connect failed"); + exit(1); + } + + close(sk); +} + +int main(int argc, char *argv[]) +{ + int serv_sk; + int optval = 0; + socklen_t len = sizeof(optval); + + test_init(argc, argv); + + serv_sk = sock_bind_and_listen(); + + test_msg("listen 0.0.0.0: %d\n", PORT); + /* create CLOSE-WAIT status socket */ + client_connect(); + + test_daemon(); + test_waitsig(); + + if (getsockopt(serv_sk, SOL_SOCKET, SO_REUSEADDR, &optval, &len) != 0) { + pr_perror("getsockopt failed"); + return -1; + } + + if (optval != 1) { + pr_err("SO_REUSEADDR flag is %d, should 1", optval); + } else + pass(); + + return 0; +} \ No newline at end of file diff --git a/test/zdtm/customization/tcp00.desc b/test/zdtm/customization/tcp00.desc new file mode 100644 index 0000000..bc3b4a8 --- /dev/null +++ b/test/zdtm/customization/tcp00.desc @@ -0,0 +1 @@ +{'arch': 'aarch64', 'opts': '--use-fork-pid --share-src-ports=17173 --share-dst-ports=17173 --skip-in-flight', 'flavor': 'h', 'sysfs': '/sys/kernel/repair_share_socket'}