Module Name: src Committed By: ozaki-r Date: Tue May 26 00:42:07 UTC 2015
Modified Files: src/distrib/sets/lists/debug: mi src/distrib/sets/lists/tests: mi src/tests/net: Makefile src/tests/net/mcast: Makefile Added Files: src/tests/net/mcast: mcast.c t_mcast.sh Removed Files: src/tests/net/mcast: t_mcast.c Log Message: Run mcast tests on rump kernels The tests on anita qemus failed due to that the host network environment didn't meet the tests. The change makes the tests independent from host environments and the tests will pass on any environments including anita qemus. Discussed on tech-kern and tech-net. To generate a diff of this commit: cvs rdiff -u -r1.113 -r1.114 src/distrib/sets/lists/debug/mi cvs rdiff -u -r1.622 -r1.623 src/distrib/sets/lists/tests/mi cvs rdiff -u -r1.21 -r1.22 src/tests/net/Makefile cvs rdiff -u -r1.1 -r1.2 src/tests/net/mcast/Makefile cvs rdiff -u -r0 -r1.1 src/tests/net/mcast/mcast.c \ src/tests/net/mcast/t_mcast.sh cvs rdiff -u -r1.16 -r0 src/tests/net/mcast/t_mcast.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/debug/mi diff -u src/distrib/sets/lists/debug/mi:1.113 src/distrib/sets/lists/debug/mi:1.114 --- src/distrib/sets/lists/debug/mi:1.113 Fri May 1 14:17:56 2015 +++ src/distrib/sets/lists/debug/mi Tue May 26 00:42:07 2015 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.113 2015/05/01 14:17:56 christos Exp $ +# $NetBSD: mi,v 1.114 2015/05/26 00:42:07 ozaki-r Exp $ ./etc/mtree/set.debug comp-sys-root ./usr/lib/i18n/libBIG5_g.a comp-c-debuglib debuglib @@ -2174,7 +2174,7 @@ ./usr/libdata/debug/usr/tests/net/if/t_compat.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/if_loop/t_pr.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/in_cksum/in_cksum.debug tests-net-debug debug,atf -./usr/libdata/debug/usr/tests/net/mcast/t_mcast.debug tests-net-debug debug,atf +./usr/libdata/debug/usr/tests/net/mcast/mcast.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/net/t_pktinfo.debug tests-net-debug debug,atf ./usr/libdata/debug/usr/tests/net/net/t_raw.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/net/t_tcp.debug tests-net-debug debug,atf Index: src/distrib/sets/lists/tests/mi diff -u src/distrib/sets/lists/tests/mi:1.622 src/distrib/sets/lists/tests/mi:1.623 --- src/distrib/sets/lists/tests/mi:1.622 Mon May 18 06:27:04 2015 +++ src/distrib/sets/lists/tests/mi Tue May 26 00:42:07 2015 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.622 2015/05/18 06:27:04 ozaki-r Exp $ +# $NetBSD: mi,v 1.623 2015/05/26 00:42:07 ozaki-r Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -3151,9 +3151,10 @@ ./usr/tests/net/in_cksum/t_in_cksum tests-net-tests atf ./usr/tests/net/in_cksum/in_cksum tests-net-tests atf ./usr/tests/net/mcast tests-net-tests -./usr/tests/net/mcast/Atffile tests-net-tests atf -./usr/tests/net/mcast/Kyuafile tests-net-tests atf,kyua -./usr/tests/net/mcast/t_mcast tests-net-tests atf +./usr/tests/net/mcast/Atffile tests-net-tests atf,rump +./usr/tests/net/mcast/Kyuafile tests-net-tests atf,rump,kyua +./usr/tests/net/mcast/mcast tests-net-tests atf,rump +./usr/tests/net/mcast/t_mcast tests-net-tests atf,rump ./usr/tests/net/mpls tests-net-tests ./usr/tests/net/mpls/Atffile tests-net-tests atf,rump ./usr/tests/net/mpls/Kyuafile tests-net-tests atf,rump,kyua Index: src/tests/net/Makefile diff -u src/tests/net/Makefile:1.21 src/tests/net/Makefile:1.22 --- src/tests/net/Makefile:1.21 Wed May 20 17:39:04 2015 +++ src/tests/net/Makefile Tue May 26 00:42:07 2015 @@ -1,13 +1,13 @@ -# $NetBSD: Makefile,v 1.21 2015/05/20 17:39:04 christos Exp $ +# $NetBSD: Makefile,v 1.22 2015/05/26 00:42:07 ozaki-r Exp $ .include <bsd.own.mk> TESTSDIR= ${TESTSBASE}/net -TESTS_SUBDIRS= fdpass in_cksum mcast net sys +TESTS_SUBDIRS= fdpass in_cksum net sys .if (${MKRUMP} != "no") -TESTS_SUBDIRS+= bpf bpfilter carp icmp if if_bridge if_loop mpls npf -TESTS_SUBDIRS+= route +TESTS_SUBDIRS+= bpf bpfilter carp icmp if if_bridge if_loop mcast +TESTS_SUBDIRS+= mpls npf route .if (${MKSLJIT} != "no") TESTS_SUBDIRS+= bpfjit .endif Index: src/tests/net/mcast/Makefile diff -u src/tests/net/mcast/Makefile:1.1 src/tests/net/mcast/Makefile:1.2 --- src/tests/net/mcast/Makefile:1.1 Sat Oct 11 23:04:42 2014 +++ src/tests/net/mcast/Makefile Tue May 26 00:42:07 2015 @@ -1,10 +1,14 @@ -# $NetBSD: Makefile,v 1.1 2014/10/11 23:04:42 christos Exp $ +# $NetBSD: Makefile,v 1.2 2015/05/26 00:42:07 ozaki-r Exp $ # .include <bsd.own.mk> TESTSDIR= ${TESTSBASE}/net/mcast -TESTS_C= t_mcast +TESTS_SH= t_mcast + +PROGS= mcast +MAN.mcast= # empty +BINDIR.mcast= ${TESTSDIR} .include <bsd.test.mk> Added files: Index: src/tests/net/mcast/mcast.c diff -u /dev/null src/tests/net/mcast/mcast.c:1.1 --- /dev/null Tue May 26 00:42:07 2015 +++ src/tests/net/mcast/mcast.c Tue May 26 00:42:07 2015 @@ -0,0 +1,497 @@ +/* $NetBSD: mcast.c,v 1.1 2015/05/26 00:42:07 ozaki-r Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +#ifdef __RCSID +__RCSID("$NetBSD: mcast.c,v 1.1 2015/05/26 00:42:07 ozaki-r Exp $"); +#else +extern const char *__progname; +#define getprogname() __progname +#endif + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <sys/time.h> +#include <netinet/in.h> + +#include <assert.h> +#include <netdb.h> +#include <time.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <err.h> +#include <errno.h> +#include <poll.h> +#include <stdbool.h> + +#ifdef ATF +#include <atf-c.h> + +#define ERRX(ev, msg, ...) ATF_REQUIRE_MSG(0, msg, __VA_ARGS__) + +#define SKIPX(ev, msg, ...) do { \ + atf_tc_skip(msg, __VA_ARGS__); \ + return; \ +} while(/*CONSTCOND*/0) + +#else +#define ERRX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) +#define SKIPX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) +#endif + +static int debug; + +#define TOTAL 10 +#define PORT_V4MAPPED "6666" +#define HOST_V4MAPPED "::FFFF:239.1.1.1" +#define PORT_V4 "6666" +#define HOST_V4 "239.1.1.1" +#define PORT_V6 "6666" +#define HOST_V6 "FF05:1:0:0:0:0:0:1" + +struct message { + size_t seq; + struct timespec ts; +}; + +static int +addmc(int s, struct addrinfo *ai, bool bug) +{ + struct ip_mreq m4; + struct ipv6_mreq m6; + struct sockaddr_in *s4; + struct sockaddr_in6 *s6; + unsigned int ifc; + + switch (ai->ai_family) { + case AF_INET: + s4 = (void *)ai->ai_addr; + assert(sizeof(*s4) == ai->ai_addrlen); + m4.imr_multiaddr = s4->sin_addr; + m4.imr_interface.s_addr = htonl(INADDR_ANY); + return setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &m4, sizeof(m4)); + case AF_INET6: + s6 = (void *)ai->ai_addr; + /* + * Linux: Does not support the v6 ioctls on v4 mapped + * sockets but it does support the v4 ones and + * it works. + * MacOS/X: Supports the v6 ioctls on v4 mapped sockets, + * but does not work and also does not support + * the v4 ioctls. So no way to make multicasting + * work with mapped addresses. + * NetBSD: Supports both and works for both. + */ + if (bug && IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) { + memcpy(&m4.imr_multiaddr, &s6->sin6_addr.s6_addr[12], + sizeof(m4.imr_multiaddr)); + m4.imr_interface.s_addr = htonl(INADDR_ANY); + return setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &m4, sizeof(m4)); + } + assert(sizeof(*s6) == ai->ai_addrlen); + memset(&m6, 0, sizeof(m6)); +#if 0 + ifc = 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, + &ifc, sizeof(ifc)) == -1) + return -1; + ifc = 224; + if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, + &ifc, sizeof(ifc)) == -1) + return -1; + ifc = 1; /* XXX should pick a proper interface */ + if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifc, + sizeof(ifc)) == -1) + return -1; +#else + ifc = 0; /* Let pick an appropriate interface */ +#endif + m6.ipv6mr_interface = ifc; + m6.ipv6mr_multiaddr = s6->sin6_addr; + return setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &m6, sizeof(m6)); + default: + errno = EOPNOTSUPP; + return -1; + } +} + +static int +allowv4mapped(int s, struct addrinfo *ai) +{ + struct sockaddr_in6 *s6; + int zero = 0; + + if (ai->ai_family != AF_INET6) + return 0; + + s6 = (void *)ai->ai_addr; + + if (!IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) + return 0; + return setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)); +} + +static struct sockaddr_storage ss; +static int +connector(int fd, const struct sockaddr *sa, socklen_t slen) +{ + assert(sizeof(ss) > slen); + memcpy(&ss, sa, slen); + return 0; +} + +static void +show(const char *prefix, const struct message *msg) +{ + printf("%10.10s: %zu [%jd.%ld]\n", prefix, msg->seq, (intmax_t) + msg->ts.tv_sec, msg->ts.tv_nsec); +} + +static int +getsocket(const char *host, const char *port, + int (*f)(int, const struct sockaddr *, socklen_t), socklen_t *slen, + bool bug) +{ + int e, s, lasterrno = 0; + struct addrinfo hints, *ai0, *ai; + const char *cause = "?"; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + e = getaddrinfo(host, port, &hints, &ai0); + if (e) + ERRX(EXIT_FAILURE, "Can't resolve %s:%s (%s)", host, port, + gai_strerror(e)); + + s = -1; + for (ai = ai0; ai; ai = ai->ai_next) { + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s == -1) { + lasterrno = errno; + cause = "socket"; + continue; + } + if (allowv4mapped(s, ai) == -1) { + cause = "allow v4 mapped"; + goto out; + } + if ((*f)(s, ai->ai_addr, ai->ai_addrlen) == -1) { + cause = f == bind ? "bind" : "connect"; + goto out; + } + if ((f == bind || f == connector) && addmc(s, ai, bug) == -1) { + cause = "join group"; + goto out; + } + *slen = ai->ai_addrlen; + break; +out: + lasterrno = errno; + close(s); + s = -1; + continue; + } + freeaddrinfo(ai0); + if (s == -1) + ERRX(EXIT_FAILURE, "%s (%s)", cause, strerror(lasterrno)); + return s; +} + +static void +sender(const char *host, const char *port, size_t n, bool conn, bool bug) +{ + int s; + ssize_t l; + struct message msg; + + socklen_t slen; + + s = getsocket(host, port, conn ? connect : connector, &slen, bug); + for (msg.seq = 0; msg.seq < n; msg.seq++) { +#ifdef CLOCK_MONOTONIC + if (clock_gettime(CLOCK_MONOTONIC, &msg.ts) == -1) + ERRX(EXIT_FAILURE, "clock (%s)", strerror(errno)); +#else + struct timeval tv; + if (gettimeofday(&tv, NULL) == -1) + ERRX(EXIT_FAILURE, "clock (%s)", strerror(errno)); + msg.ts.tv_sec = tv.tv_sec; + msg.ts.tv_nsec = tv.tv_usec * 1000; +#endif + if (debug) + show("sending", &msg); + l = conn ? send(s, &msg, sizeof(msg), 0) : + sendto(s, &msg, sizeof(msg), 0, (void *)&ss, slen); + if (l == -1) + ERRX(EXIT_FAILURE, "send (%s)", strerror(errno)); + usleep(100); + } +} + +static void +receiver(const char *host, const char *port, size_t n, bool conn, bool bug) +{ + int s; + ssize_t l; + size_t seq; + struct message msg; + struct pollfd pfd; + socklen_t slen; + + s = getsocket(host, port, bind, &slen, bug); + pfd.fd = s; + pfd.events = POLLIN; + for (seq = 0; seq < n; seq++) { + if (poll(&pfd, 1, 10000) == -1) + ERRX(EXIT_FAILURE, "poll (%s)", strerror(errno)); + l = conn ? recv(s, &msg, sizeof(msg), 0) : + recvfrom(s, &msg, sizeof(msg), 0, (void *)&ss, &slen); + if (l == -1) + ERRX(EXIT_FAILURE, "recv (%s)", strerror(errno)); + if (debug) + show("got", &msg); + if (seq != msg.seq) + ERRX(EXIT_FAILURE, "seq %zu != %zu", seq, msg.seq); + } +} + +static void +run(const char *host, const char *port, size_t n, bool conn, bool bug) +{ + pid_t pid; + int status; + + switch ((pid = fork())) { + case 0: + receiver(host, port, n, conn, bug); + return; + case -1: + ERRX(EXIT_FAILURE, "fork (%s)", strerror(errno)); + default: + usleep(1000); + sender(host, port, n, conn, bug); + usleep(100); + again: + switch (waitpid(pid, &status, WNOHANG)) { + case -1: + ERRX(EXIT_FAILURE, "wait (%s)", strerror(errno)); + case 0: + if (kill(pid, SIGTERM) == -1) + ERRX(EXIT_FAILURE, "kill (%s)", + strerror(errno)); + goto again; + default: + if (WIFSIGNALED(status)) { + if (WTERMSIG(status) == SIGTERM) + ERRX(EXIT_FAILURE, + "receiver got terminated due to " \ + "deadline (%d usec)", 100); + else + ERRX(EXIT_FAILURE, + "receiver got signaled (%s)", + strsignal(WTERMSIG(status))); + } else if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) + ERRX(EXIT_FAILURE, + "receiver exited with status %d", + WEXITSTATUS(status)); + } else { + ERRX(EXIT_FAILURE, + "receiver exited with unexpected status %d", + status); + } + break; + } + return; + } +} + +#ifndef ATF +int +main(int argc, char *argv[]) +{ + const char *host, *port; + int c; + size_t n; + bool conn, bug; + + host = HOST_V4; + port = PORT_V4; + n = TOTAL; + bug = conn = false; + + while ((c = getopt(argc, argv, "46bcdmn:")) != -1) + switch (c) { + case '4': + host = HOST_V4; + port = PORT_V4; + break; + case '6': + host = HOST_V6; + port = PORT_V6; + break; + case 'b': + bug = true; + break; + case 'c': + conn = true; + break; + case 'd': + debug++; + break; + case 'm': + host = HOST_V4MAPPED; + port = PORT_V4MAPPED; + break; + case 'n': + n = atoi(optarg); + break; + default: + fprintf(stderr, "Usage: %s [-cdm46] [-n <tot>]", + getprogname()); + return 1; + } + + run(host, port, n, conn, bug); + return 0; +} +#else + +ATF_TC(conninet4); +ATF_TC_HEAD(conninet4, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks connected multicast for ipv4"); +} + +ATF_TC_BODY(conninet4, tc) +{ + run(HOST_V4, PORT_V4, TOTAL, true, false); +} + +ATF_TC(connmappedinet4); +ATF_TC_HEAD(connmappedinet4, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks connected multicast for mapped ipv4"); +} + +ATF_TC_BODY(connmappedinet4, tc) +{ + run(HOST_V4MAPPED, PORT_V4MAPPED, TOTAL, true, false); +} + +ATF_TC(connmappedbuginet4); +ATF_TC_HEAD(connmappedbuginet4, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks connected multicast for mapped ipv4 using the v4 ioctls"); +} + +ATF_TC_BODY(connmappedbuginet4, tc) +{ + run(HOST_V4MAPPED, PORT_V4MAPPED, TOTAL, true, true); +} + +ATF_TC(conninet6); +ATF_TC_HEAD(conninet6, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks connected multicast for ipv6"); +} + +ATF_TC_BODY(conninet6, tc) +{ + run(HOST_V6, PORT_V6, TOTAL, true, false); +} + +ATF_TC(unconninet4); +ATF_TC_HEAD(unconninet4, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks unconnected multicast for ipv4"); +} + +ATF_TC_BODY(unconninet4, tc) +{ + run(HOST_V4, PORT_V4, TOTAL, false, false); +} + +ATF_TC(unconnmappedinet4); +ATF_TC_HEAD(unconnmappedinet4, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks unconnected multicast for mapped ipv4"); +} + +ATF_TC_BODY(unconnmappedinet4, tc) +{ + run(HOST_V4MAPPED, PORT_V4MAPPED, TOTAL, false, false); +} + +ATF_TC(unconnmappedbuginet4); +ATF_TC_HEAD(unconnmappedbuginet4, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks unconnected multicast for mapped ipv4 using the v4 ioctls"); +} + +ATF_TC_BODY(unconnmappedbuginet4, tc) +{ + run(HOST_V4MAPPED, PORT_V4MAPPED, TOTAL, false, true); +} + +ATF_TC(unconninet6); +ATF_TC_HEAD(unconninet6, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks unconnected multicast for ipv6"); +} + +ATF_TC_BODY(unconninet6, tc) +{ + run(HOST_V6, PORT_V6, TOTAL, false, false); +} + +ATF_TP_ADD_TCS(tp) +{ + debug++; + ATF_TP_ADD_TC(tp, conninet4); + ATF_TP_ADD_TC(tp, connmappedinet4); + ATF_TP_ADD_TC(tp, connmappedbuginet4); + ATF_TP_ADD_TC(tp, conninet6); + ATF_TP_ADD_TC(tp, unconninet4); + ATF_TP_ADD_TC(tp, unconnmappedinet4); + ATF_TP_ADD_TC(tp, unconnmappedbuginet4); + ATF_TP_ADD_TC(tp, unconninet6); + + return atf_no_error(); +} +#endif Index: src/tests/net/mcast/t_mcast.sh diff -u /dev/null src/tests/net/mcast/t_mcast.sh:1.1 --- /dev/null Tue May 26 00:42:07 2015 +++ src/tests/net/mcast/t_mcast.sh Tue May 26 00:42:07 2015 @@ -0,0 +1,109 @@ +# $NetBSD: t_mcast.sh,v 1.1 2015/05/26 00:42:07 ozaki-r Exp $ +# +# Copyright (c) 2015 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +netserver="rump_server -lrumpnet -lrumpnet_net" +netserver="$netserver -lrumpnet_netinet -lrumpnet_netinet6 -lrumpnet_shmif" +export RUMP_SERVER=unix://commsock + +DEBUG=false + +run_test() +{ + local name="$1" + local opts="$2" + local mcast="$(atf_get_srcdir)/mcast" + + atf_check -s exit:0 ${netserver} ${RUMP_SERVER} + atf_check -s exit:0 rump.ifconfig shmif0 create + atf_check -s exit:0 rump.ifconfig shmif0 linkstr bus1 + atf_check -s exit:0 rump.ifconfig shmif0 10.0.0.2/24 + atf_check -s exit:0 rump.ifconfig shmif0 inet6 fc00::2/64 + atf_check -s exit:0 rump.ifconfig shmif0 up + + atf_check -s exit:0 rump.ifconfig -w 10 + atf_check -s not-exit:0 -x "rump.ifconfig shmif0 |grep -q tentative" + + # A route to the mcast address is required to join the mcast group + atf_check -s exit:0 -o ignore rump.route add default 10.0.0.1 + atf_check -s exit:0 -o ignore rump.route add -inet6 default fc00::1 + + $DEBUG && rump.ifconfig + $DEBUG && rump.netstat -nr + + export LD_PRELOAD=/usr/lib/librumphijack.so + #$DEBUG && /usr/sbin/ifmcstat # Not yet run on rump kernel + if $DEBUG; then + atf_check -s exit:0 -o ignore $mcast -d ${opts} + else + atf_check -s exit:0 $mcast ${opts} + fi + #$DEBUG && /usr/sbin/ifmcstat # Not yet run on rump kernel + unset LD_PRELOAD +} + +add_test() +{ + local name=$1 + local opts="$2" + local desc="$3" + + atf_test_case "mcast_${name}" cleanup + eval "mcast_${name}_head() { \ + atf_set \"descr\" \"${desc}\"; \ + atf_set \"require.progs\" \"rump_server\"; \ + }; \ + mcast_${name}_body() { \ + run_test \"${name}\" \"${opts}\"; \ + }; \ + mcast_${name}_cleanup() { \ + ${DEBUG} && /usr/bin/shmif_dumpbus -p - bus1 2>/dev/null | \ + /usr/sbin/tcpdump -n -e -r -; \ + env RUMP_SERVER=unix://commsock rump.halt; \ + }" + atf_add_test_case "mcast_${name}" +} + +atf_init_test_cases() +{ + + add_test conninet4 "-c -4" \ + "Checks connected multicast for ipv4" + add_test connmappedinet4 "-c -m -4" \ + "Checks connected multicast for mapped ipv4" + add_test connmappedbuginet4 "-c -m -b -4" \ + "Checks connected multicast for mapped ipv4 using the v4 ioctls" + add_test conninet6 "-c -6" \ + "Checks connected multicast for ipv6" + add_test unconninet4 "-4" \ + "Checks unconnected multicast for ipv4" + add_test unconnmappedinet4 "-m -4" \ + "Checks unconnected multicast for mapped ipv4" + add_test unconnmappedbuginet4 "-m -b -4" \ + "Checks unconnected multicast for mapped ipv4 using the v4 ioctls" + add_test unconninet6 "-6" \ + "Checks unconnected multicast for ipv6" +}