From: Subrata M. <su...@li...> - 2008-08-22 22:14:03
|
Thanks Gowri for this Patch. I would however require posting of the results on running these tests on a NETNS enabled kernel. Probably you or Sudhir or Veerendra can provide me that once the patch series are reviewed and ACK-ed completely. Regards-- Subrata On Fri, 2008-08-22 at 17:59 +0530, Gowrishankar M wrote: > Hi Subrata, > Please find below the test case for network namespace to check the > functionality of tcp "echo" service. > > Signed-off-by: Gowrishankar Muthukrishnan <gom...@li...> > > Index: b/testcases/kernel/containers/netns/tcp_cmds/echo/Makefile > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ b/testcases/kernel/containers/netns/tcp_cmds/echo/Makefile > 2008-08-22 17:49:24.000000000 +0530 > @@ -0,0 +1,40 @@ > +################################################################################ > +## > ## > +## Copyright (c) International Business Machines Corp., > 2007 ## > +## > ## > +## This program is free software; you can redistribute it and#or > modify ## > +## it under the terms of the GNU General Public License as published > by ## > +## the Free Software Foundation; either version 2 of the License, > or ## > +## (at your option) any later > version. ## > +## > ## > +## This program is distributed in the hope that it will be useful, > but ## > +## WITHOUT ANY WARRANTY; without even the implied warranty of > MERCHANTABILITY ## > +## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public > License ## > +## for more > details. ## > +## > ## > +## You should have received a copy of the GNU General Public > License ## > +## along with this program; if not, write to the Free > Software ## > +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 > USA ## > +## > ## > +################################################################################ > + > +CFLAGS += -Wall -g > +CPPFLAGS += -I../../../../../../include -I../../../libclone > +LDLIBS += -L../../../../../../lib -L../../../libclone > ../../../libclone/libclone.a -lltp > + > +SRCS = $(wildcard *.c) > +TARGETS = $(patsubst %.c,%,$(SRCS)) > +NOLTP_TARGETS = $(patsubst %.c,%_noltp,$(NOLTPSRCS)) > + > + > +%_noltp : %.c > + $(CC) -g -DNO_LTP -o $@ $< ../../../libclone/libclone.a > + > +all: $(TARGETS) > + > +install: > + @set -e; for i in $(TARGETS) ; do ln -f $$i ../../../../../bin/$$i > ; done > +noltp: $(NOLTP_TARGETS) > + > +clean: > + rm -f $(TARGETS) *.o $(NOLTP_TARGETS) > Index: b/testcases/kernel/containers/netns/tcp_cmds/echo/echoc01.c > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ b/testcases/kernel/containers/netns/tcp_cmds/echo/echoc01.c > 2008-08-22 17:48:59.000000000 +0530 > @@ -0,0 +1,448 @@ > +/* > + * > + * Copyright (c) International Business Machines Corp., 2001 > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA > 02111-1307 USA > + */ > + > +/* > + * Test Name: echoc01 > + * > + * Test Description: > + * This test checks echo(tcp) service functionality in parent and child > + * network namespaces. > + * Objective of the test is that, after parent and child put some data in > + * the port of echo service (tcp), same data should be readback, while > + * both are running echo service at the same time. > + * > + * Usage: <for command-line> > + * echoc01 > + * > + * HISTORY > + * 21/2008 Gowrishankar Muthukrishnan(gom...@in...) Creation > + * > + * RESTRICTIONS: > + * None. > + * > + */ > + > +/* Standard include files */ > +#include <arpa/inet.h> > +#include <errno.h> > +#include <fcntl.h> > +#include <netdb.h> > +#include <sched.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/select.h> > +#include <sys/socket.h> > +#include <sys/stat.h> > +#include <sys/types.h> > +#include <unistd.h> > + > +/* User defined include files */ > +#include "libclone.h" > + > +/* Harness specific include files */ > +#ifndef NOLTP > +#include "test.h" > +#include "usctest.h" > +#endif > + > +#ifndef BUFFER_SIZE > +#define BUFFER_SIZE 200 > +#endif > + > +extern int Tst_count; > +extern char *TESTDIR; > +char *TCID = "echoc01"; > +int TST_TOTAL = 1; > + > +extern int errno; > +extern int h_errno; > +void do_setup(void); > +void do_cleanup(void); > +int do_parent_setup(void *); > +int do_child_setup(void *); > +int do_connect_socket(); > +void do_close_socket(int); > +int do_echofile(int, char*); > +int do_read_from_echo(int, int, char*); > + > +/* Common cleanup */ > +void do_cleanup(void) > +{ > + system("/etc/init.d/xinetd stop 1>/dev/null"); > + system("rm -f /tmp/FIFO-sync"); > + system("rm -f /tmp/echoc01-xinetd-p.pid /tmp/echoc01-xinetd-c.pid"); > +} > + > +/* Common setup */ > +void do_setup(void) > +{ > + int fd; > + char line[80]; > + do_cleanup(); > + system("rm -f echoc01-parent.dat* echoc01-child.dat*"); > + system("mkfifo /tmp/FIFO-sync"); > + fd = creat("echoc01-parent.dat", S_IRWXU|S_IRWXG|S_IROTH); > + if (fd < 0) { > + tst_brkm(TBROK, do_cleanup, > + "failed to create data file echoc01-parent.dat"); > + } > + sprintf(line, "%s",\ > + "AAAAAAAABBBBBSSS1111111222&&&&&&UUUUUNNNNNNNN\n\0"); > + write(fd, line, strlen(line)); > + close(fd); > + fd = creat("echoc01-child.dat", S_IRWXU|S_IRWXG|S_IROTH); > + if (fd < 0) { > + tst_brkm(TBROK, do_cleanup, > + "failed to create data file echoc01-child.dat"); > + } > + sprintf(line, "%s",\ > + "HHHHHDDDDDDD^^6666666633333333332222222QQQQQ\n\0"); > + write(fd, line, strlen(line)); > + close(fd); > +} > + > +/* Setup specific to parent process */ > +int do_parent_setup(void *file) > +{ > + int pid, ret, sd; > + int bytes; > + char *newfile; > + char command[80]; > + pid = getpid(); > + > + /* Activate loopback interface */ > + if (system("ifconfig lo up") != 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: activating loopback failed\n", pid); > + tst_resm(TINFO, "%d: activated loopback.", pid); > + > + /* Activate echo service */ > + if (system("xinetd -pidfile /tmp/echoc01-xinetd-p.pid \ > + -stayalive -inetd_compat") != 0) { > + tst_resm(TBROK, "%d: activating xinetd failed\n", pid); > + return 1; > + } > + tst_resm(TINFO, "%d: activated xinetd services.", pid); > + > + /* Create a socket and connect it to echo service */ > + sd = do_connect_socket(); > + tst_resm(TINFO, "%d: parent has connected socket", pid); > + > + /* Wait for child process to have xinetd activated (stage 1) */ > + system("echo sync stage 1 > /tmp/FIFO-sync"); > + > + /* Write data in socket connected to echo service */ > + bytes = do_echofile(sd, file); > + tst_resm(TINFO, "%d: parent has written into echo port.", pid); > + > + /* Wait for child to have its socket connected (stage 2) */ > + system("cat /tmp/FIFO-sync > /dev/null"); > + > + /* Wait for child to write data on its socket (stage 3) */ > + system("echo sync stage 3 > /tmp/FIFO-sync"); > + > + /* Read data that is being echoed */ > + newfile = malloc(strlen(file) + 1); > + newfile = memcpy(newfile, file, strlen(file)+1); > + newfile = strcat(newfile, ".echo"); > + ret = do_read_from_echo(sd, bytes, newfile); > + tst_resm(TINFO, "%d: parent has readback from echo.", pid); > + > + /* Close sockets and perform cleanup */ > + do_close_socket(sd); > + do_cleanup(); > + > + /* Validate the data that is echoed */ > + sprintf(command, "cmp -s %s %s", (char *)file, newfile); > + if (system(command) == 0) > + tst_resm(TPASS, "%s(PARENT) passed.", TCID); > + else > + tst_resm(TFAIL, "%s(PARENT) failed.", TCID); > + return 0; > +} > + > +/* Setup specific to child process */ > +int do_child_setup(void *file) > +{ > + int pid, ret, sd; > + int bytes; > + char *newfile; > + char command[80]; > + pid = getpid(); > + > + /* Activate loopback interface */ > + if (system("ifconfig lo up") != 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: activating loopback failed\n", pid); > + tst_resm(TINFO, "%d: activated loopback.", pid); > + > + /* Activate echo service */ > + if (system("xinetd -pidfile /tmp/echoc01-xinetd-c.pid \ > + -stayalive -inetd_compat") != 0) { > + tst_resm(TBROK, "%d: activating xinetd failed\n", pid); > + return 1; > + } > + tst_resm(TINFO, "%d: activated xinetd services.", pid); > + > + /* Wake up parent waiting for this point (stage 1) */ > + system("cat /tmp/FIFO-sync > /dev/null"); > + > + /* Create a socket and connect it to echo service */ > + sd = do_connect_socket(); > + tst_resm(TINFO, "%d: child has connected socket.", pid); > + > + /* Wake up parent waiting for this point (stage 2) */ > + system("echo sync stage 2 > /tmp/FIFO-sync"); > + > + /* Write data in socket connected to echo service */ > + bytes = do_echofile(sd, file); > + tst_resm(TINFO, "%d: child has written into echo port.", pid); > + > + /* Wake up parent waiting for this point (stage 3) */ > + system("cat /tmp/FIFO-sync > /dev/null"); > + > + /* Read data that is being echoed */ > + newfile = malloc(strlen(file) + 1); > + newfile = memcpy(newfile, file, strlen(file)+1); > + newfile = strcat(newfile, ".echo"); > + ret = do_read_from_echo(sd, bytes, newfile); > + tst_resm(TINFO, "%d: child has readback from echo.", pid); > + > + /* Close sockets and perform cleanup */ > + do_close_socket(sd); > + do_cleanup(); > + > + /* Validate the data that is echoed */ > + sprintf(command, "cmp -s %s %s", (char *)file, newfile); > + if (system(command) == 0) > + tst_resm(TPASS, "%s(CHILD) passed.", TCID); > + else > + tst_resm(TFAIL, "%s(CHILD) failed.", TCID); > + return 0; > +} > + > +int do_connect_socket() > +{ > + struct hostent *hent_ptr; > + struct servent *sent_ptr; > + struct protoent *pent_ptr; > + struct sockaddr_in sa_in; > + struct sockaddr_in sa; > + socklen_t sa_size; > + struct in_addr hostaddr; > + int sd, port; > + int pid; > + pid = getpid(); > + > + pent_ptr = getprotobyname("IP"); > + > + sd = socket(PF_INET, SOCK_STREAM, pent_ptr->p_proto); > + if (sd < 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: socket() failed with error: %s\n",\ > + pid, strerror(errno)); > + > + hent_ptr = gethostbyname("localhost"); > + if (hent_ptr == NULL) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: gethostbyname() failed with error: %s\n",\ > + pid, hstrerror(h_errno)); > + > + sent_ptr = getservbyname("echo", "tcp"); > + if (sent_ptr == NULL) > + tst_brkm(TWARN, do_cleanup,\ > + "%d: getservbyname() failed to get service entry\n", > + pid); > + > + port = sent_ptr->s_port; > + memcpy(&hostaddr, hent_ptr->h_addr_list[0], sizeof(struct in_addr)); > + memset((char *)&sa_in, 0x00, sizeof(sa_in)); > + sa_in.sin_port = port; > + sa_in.sin_family = PF_INET; > + sa_in.sin_addr = hostaddr; > + tst_resm(TINFO, "%d: host name is %s", pid, hent_ptr->h_name); > + > + if (connect(sd, (struct sockaddr *) &sa_in, sizeof(sa_in)) < 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: connect() failed with error: %s\n",\ > + pid, strerror(errno)); > + > + sa_size = sizeof(sa); > + if (getsockname(sd, (struct sockaddr *) &sa, &sa_size) != 0) > + tst_brkm(TWARN, do_cleanup,\ > + "%d: getsockname() failed with error : %s",\ > + pid, strerror(errno)); > + > + tst_resm(TINFO, "%d: local port is %d", pid, ntohs(sa.sin_port)); > + > + if (getpeername(sd, (struct sockaddr *) &sa, &sa_size) != 0) > + tst_brkm(TWARN, do_cleanup,\ > + "%d: getpeername() failed with error : %s",\ > + pid, strerror(errno)); > + > + tst_resm(TINFO, "%d: remote port is %d", pid, ntohs(sa.sin_port)); > + > + return sd; > +} > + > +int do_echofile(int sd, char *file) > +{ > + char buffer[BUFFER_SIZE]; > + int read_flag = 1, fdr, pid; > + int bytes = 0; > + unsigned int nbytes_r = 0, nbytes_w = 0; > + unsigned long bufindex; > + > + pid = getpid(); > + fdr = open(file, O_RDONLY); > + if (fdr < 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: failed to open %s: %s",\ > + pid, file, strerror(errno)); > + > + while (read_flag) { > + /* Flushout the buffer and initialize counters */ > + memset((char *)&buffer, 0x00, sizeof(buffer)); > + > + if (nbytes_r == 0) { > + bufindex = 0; > + /* Read till the end of file */ > + nbytes_r = read(fdr, buffer, sizeof(buffer)); > + if (nbytes_r < 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: failed to read from %s: %s",\ > + pid, file, strerror(errno)); > + } > + > + if (nbytes_r == 0) { > + /* Reached end of file */ > + break; > + } > + > + /* Write into socket whatever is read now */ > + nbytes_w = write(sd, buffer + bufindex, nbytes_r); > + if (nbytes_w < 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: failed to write in socket: %s",\ > + pid, strerror(errno)); > + > + if (nbytes_w < nbytes_r) { > + /* Write is not complete */ > + nbytes_r -= nbytes_w; > + bufindex += nbytes_w; > + } > + > + if (nbytes_w == nbytes_r) > + nbytes_r = 0; > + > + bytes += nbytes_w; > + nbytes_w = 0; > + } > + > + if (close(fdr) < 0) > + tst_resm(TWARN,\ > + "%d: closing %s failed: %s",\ > + pid, file, strerror(errno)); > + return bytes; > +} > + > +int do_read_from_echo(int sd, int bytes_tot, char *file) > +{ > + char buffer[BUFFER_SIZE]; > + int pid, fdw, read_flag = 1; > + int nbytes_w = 0, nbytes_r = 0; > + int bytes_read = 0; > + unsigned long bufindex; > + > + pid = getpid(); > + fdw = creat(file, S_IRWXU|S_IRWXG|S_IROTH); > + if (fdw < 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: failed to create %s: %s",\ > + pid, file, strerror(errno)); > + > + while (read_flag) { > + /* Flushout the buffer and initialize counters */ > + memset((char *)&buffer, 0x00, sizeof(buffer)); > + if (nbytes_w == nbytes_r) { > + nbytes_w = 0; > + nbytes_r = 0; > + bufindex = 0; > + } > + > + if (nbytes_r == 0) { > + nbytes_r = read(sd, buffer, sizeof(buffer)); > + if (nbytes_r < 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: failed to read from socket: %s",\ > + pid, strerror(errno)); > + } > + > + bytes_read += nbytes_r; > + > + /* Write into newfile whatever is just read from socket */ > + nbytes_w = write(fdw, buffer + bufindex , nbytes_r); > + if (nbytes_w < 0) > + tst_brkm(TBROK, do_cleanup,\ > + "%d: failed to write into file %s: %s",\ > + pid, file, strerror(errno)); > + > + if (nbytes_w < nbytes_r) { > + /* Write is not complete */ > + nbytes_r -= nbytes_w; > + bufindex += nbytes_w; > + } > + > + if (bytes_read == bytes_tot) { > + /* Reached end of file */ > + break; > + } > + } > + > + if (close(fdw) < 0) > + tst_brkm(TWARN, do_cleanup,\ > + "%d: closing %s failed: %s",\ > + pid, file, strerror(errno)); > + return 0; > +} > + > +void do_close_socket(int sd) > +{ > + int pid; > + pid = getpid(); > + if (close(sd) < 0) > + tst_resm(TWARN,\ > + "%d: closing socket failed: %s",\ > + pid, strerror(errno)); > +} > + > +int main(int argc, char **argv) > +{ > + int ret; > + int flags; > + do_setup(); > + flags = CLONE_NEWNET; > + flags |= CLONE_NEWNS; > + ret = do_unshare_tests(flags, > + do_child_setup, "echoc01-child.dat", > + do_parent_setup, "echoc01-parent.dat"); > + exit(ret); > +} > + > > -- > Gowrishankar |