Simple bulk TCP test

Send 8 MiB from one socket to another, anticipating short writes and
short reads from sockets.

Fix #2989
This commit is contained in:
Ehmry - 2018-09-17 17:45:22 +02:00 committed by Christian Helmuth
parent f65a7650c5
commit c697fb6345
5 changed files with 288 additions and 0 deletions

View File

@ -0,0 +1,112 @@
create_boot_directory
append build_components {
core init
drivers/timer
server/nic_bridge
server/nic_loopback
test/tcp
}
append_socket_fs_build_components
build $build_components
append config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="256"/>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="nic_loopback">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Nic"/> </provides>
</start>
<start name="nic_bridge">
<resource name="RAM" quantum="4M"/>
<provides><service name="Nic"/></provides>
<config verbose="no">
<policy label_prefix="recv" ip_addr="192.168.1.1" />
<policy label_prefix="send" ip_addr="192.168.1.2" />
</config>
<route>
<service name="Nic"> <child name="nic_loopback"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="recv">
<binary name="test-tcp"/>
<resource name="RAM" quantum="32M"/>
<config>
<arg value="recv"/>
<libc stdout="/log" stderr="/log" socket="/sockets"/>
<vfs>
<log/>
<dir name="sockets">
<} [socket_fs_plugin] { ip_addr="192.168.1.1" netmask="255.255.255.0"/>
</dir>
</vfs>
</config>
<route>
<service name="Nic"> <child name="nic_bridge"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="send">
<binary name="test-tcp"/>
<resource name="RAM" quantum="32M"/>
<config>
<arg value="send"/>
<arg value="192.168.1.1"/>
<libc stdout="/log" stderr="/log" socket="/sockets"/>
<vfs>
<log/>
<dir name="sockets">
<} [socket_fs_plugin] { ip_addr="192.168.1.2" netmask="255.255.255.0"/>
</dir>
</vfs>
</config>
<route>
<service name="Nic"> <child name="nic_bridge"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
</config>
}
install_config $config
append boot_modules {
core ld.lib.so init timer
nic_bridge
nic_loopback
posix.lib.so libc.lib.so libm.lib.so vfs.lib.so vfs_lwip.lib.so
test-tcp
}
append_socket_fs_boot_modules
build_boot_image $boot_modules
append qemu_args " -nographic"
run_genode_until {child "recv" exited with exit value 0} 240
# vi: set ft=tcl :

View File

@ -0,0 +1,2 @@
source ${genode_dir}/repos/libports/run/vfs_lwip.inc
source ${genode_dir}/repos/libports/run/tcp_bulk.inc

View File

@ -0,0 +1,2 @@
source ${genode_dir}/repos/dde_linux/run/vfs_lxip.inc
source ${genode_dir}/repos/libports/run/tcp_bulk.inc

View File

@ -0,0 +1,167 @@
/*
* \brief Libc tcp send and recv test
* \author Emery Hemingway
* \date 2018-09-17
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Libc includes */
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
/* PCG includes */
#include <pcg_variants.h>
enum { NUM_TEST_INTS = 1<<20, BULK_ITERATIONS = 2 };
static uint32_t data[NUM_TEST_INTS];
int test_send(char const *host)
{
usleep(1000000);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("`socket` failed");
return sock;
}
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(2);
fprintf(stderr, "connect to %s\n", host);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr))) {
perror("`connect` failed");
return ~0;
}
}
pcg32_random_t rng = PCG32_INITIALIZER;
for (int j = 0; j < BULK_ITERATIONS; ++j) {
for (size_t i = 0; i < NUM_TEST_INTS; ++i)
data[i] = pcg32_random_r(&rng);
size_t total = sizeof(data);
size_t offset = 0;
char *buf = (char *)data;
while (offset < total) {
ssize_t res = send(sock, buf+offset, total-offset, 0);
if (res < 1) {
perror("send failed");
return -1;
}
offset += res;
}
}
fprintf(stderr, "close server\n");
shutdown(sock, SHUT_RDWR);
usleep(10000000);
return 0;
}
int test_recv()
{
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("`socket` failed");
return sock;
}
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(2);
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) {
perror("`bind` failed");
return ~0;
}
}
if (listen(sock, 1)) {
perror("listen broke");
}
for (;;) {
char string[INET_ADDRSTRLEN];
struct sockaddr_in addr;
socklen_t super_socket_safety = sizeof(addr);
int client = accept(sock, (struct sockaddr*)&addr, &super_socket_safety);
if (client < 0) {
perror("invalid socket from accept!");
return ~0;
}
inet_ntop(AF_INET, &(addr.sin_addr), string, super_socket_safety);
fprintf(stderr, "recv from %s\n", string);
pcg32_random_t rng = PCG32_INITIALIZER;
for (int j = 0; j < BULK_ITERATIONS; ++j) {
size_t total = sizeof(data);
size_t offset = 0;
char *buf = (char *)data;
while (offset < total) {
ssize_t res = recv(client, buf+offset, total-offset, 0);
if (res < 1) {
perror("recv failed");
return ~0;
}
offset += res;
}
for (size_t i = 0; i < NUM_TEST_INTS; ++i) {
if (data[i] != pcg32_random_r(&rng)) {
fprintf(stderr, "bad data at byte offset %ld\n", i<<2);
return ~0;
}
}
}
fprintf(stderr, "close client\n");
shutdown(client, SHUT_RDWR);
return 0;
}
}
int main(int argc, char **argv)
{
if (argc < 1) {
fprintf(stderr, "no test name passed thru argv\n");
return ~0;
}
if (argc < 2) {
if (strcmp(argv[0], "recv") == 0)
return test_recv();
}
if (argc < 3) {
if (strcmp(argv[0], "send") == 0)
return test_send(argv[1]);
}
fprintf(stderr, "\"%s\" not a valid test\n", argv[0]);
return ~0;
}

View File

@ -0,0 +1,5 @@
TARGET = test-tcp
LIBS += posix libc libpcg_random
SRC_C += main.c
CC_CXX_WARN_STRICT =