Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157982407
D55244.id174564.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D55244.id174564.diff
View Options
diff --git a/tests/sys/netinet/Makefile b/tests/sys/netinet/Makefile
--- a/tests/sys/netinet/Makefile
+++ b/tests/sys/netinet/Makefile
@@ -29,9 +29,10 @@
output \
redirect
-ATF_TESTS_PYTEST+= carp.py
-ATF_TESTS_PYTEST+= igmp.py
-ATF_TESTS_PYTEST+= tcp_hpts_test.py
+ATF_TESTS_PYTEST+= carp.py \
+ igmp.py \
+ ip_mroute.py \
+ tcp_hpts_test.py
LIBADD.so_reuseport_lb_test= pthread
LIBADD.udp_bindings= pthread
@@ -54,7 +55,11 @@
execenv_jail_params="vnet allow.raw_sockets"
TEST_METADATA.redirect+= required_programs="python"
-PROGS= udp_dontroute tcp_user_cookie multicast-send multicast-receive
+PROGS= ip6_mrouted \
+ multicast-send \
+ multicast-receive \
+ tcp_user_cookie \
+ udp_dontroute
${PACKAGE}FILES+= redirect.py
diff --git a/tests/sys/netinet/ip6_mrouted.c b/tests/sys/netinet/ip6_mrouted.c
new file mode 100644
--- /dev/null
+++ b/tests/sys/netinet/ip6_mrouted.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2026 Stormshield
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * A dead-simple IPv6 multicast routing daemon. It registers itself with the
+ * multicast routing code and then waits for messages from the kernel. Received
+ * messages are handled by installing multicast routes.
+ */
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet6/ip6_mroute.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct mif {
+ const char *name;
+ int mifi;
+ int pifi;
+ STAILQ_ENTRY(mif) next;
+};
+static STAILQ_HEAD(, mif) miflist = STAILQ_HEAD_INITIALIZER(miflist);
+
+static void *
+xmalloc(size_t size)
+{
+ void *ptr;
+
+ ptr = malloc(size);
+ if (ptr == NULL)
+ err(1, "malloc");
+ return (ptr);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: %s [-i <iface>] [-m <srcaddr>/<groupaddr>/<iface>]\n",
+ getprogname());
+ exit(1);
+}
+
+static void
+add_route(int sd, const struct in6_addr *src, const struct in6_addr *group,
+ mifi_t mifi)
+{
+ struct mf6cctl mfcc;
+ struct mif *mif;
+ int error;
+
+ memset(&mfcc, 0, sizeof(mfcc));
+ mfcc.mf6cc_parent = mifi;
+ mfcc.mf6cc_origin.sin6_family = AF_INET6;
+ mfcc.mf6cc_origin.sin6_len = sizeof(struct sockaddr_in6);
+ mfcc.mf6cc_origin.sin6_addr = *src;
+ mfcc.mf6cc_mcastgrp.sin6_family = AF_INET6;
+ mfcc.mf6cc_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
+ mfcc.mf6cc_mcastgrp.sin6_addr = *group;
+
+ STAILQ_FOREACH(mif, &miflist, next) {
+ if (mif->mifi != mifi)
+ IF_SET(mif->mifi, &mfcc.mf6cc_ifset);
+ }
+
+ error = setsockopt(sd, IPPROTO_IPV6, MRT6_ADD_MFC,
+ &mfcc, sizeof(mfcc));
+ if (error != 0)
+ err(1, "setsockopt(MRT6_ADD_MFC)");
+}
+
+static void
+handle_upcalls(int sd)
+{
+ struct kevent ev;
+ int kq;
+
+ kq = kqueue();
+ if (kq < 0)
+ err(1, "kqueue");
+ EV_SET(&ev, sd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL);
+ if (kevent(kq, &ev, 1, NULL, 0, NULL) < 0)
+ err(1, "kevent");
+
+ for (;;) {
+ char buf1[INET6_ADDRSTRLEN], buf2[INET6_ADDRSTRLEN];
+ struct mrt6msg msg;
+ ssize_t len;
+ int n;
+
+ n = kevent(kq, NULL, 0, &ev, 1, NULL);
+ if (n < 0) {
+ if (errno == EINTR)
+ break;
+ err(1, "kevent");
+ }
+ if (n == 0)
+ continue;
+ assert(n == 1);
+ assert(ev.filter == EVFILT_READ);
+
+ len = recv(sd, &msg, sizeof(msg), 0);
+ if (len < 0)
+ err(1, "recv");
+ if ((size_t)len < sizeof(msg)) {
+ warnx("short read on upcall, %zd bytes", len);
+ continue;
+ }
+
+ printf("upcall received:\n");
+ printf("msgtype=%d mif=%d src=%s dst=%s\n",
+ msg.im6_msgtype, msg.im6_mif,
+ inet_ntop(AF_INET6, &msg.im6_src, buf1, sizeof(buf1)),
+ inet_ntop(AF_INET6, &msg.im6_dst, buf2, sizeof(buf2)));
+
+ add_route(sd, &msg.im6_src, &msg.im6_dst, msg.im6_mif);
+ }
+
+ close(kq);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct mif *mif;
+ int ch, error, mifi, sd, v;
+
+ mifi = 0;
+ while ((ch = getopt(argc, argv, "i:m:")) != -1) {
+ switch (ch) {
+ case 'i':
+ mif = xmalloc(sizeof(*mif));
+ mif->name = strdup(optarg);
+ mif->mifi = mifi++;
+ mif->pifi = if_nametoindex(optarg);
+ if (mif->pifi == 0)
+ errx(1, "unknown interface %s", optarg);
+ STAILQ_INSERT_TAIL(&miflist, mif, next);
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ sd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ if (sd < 0)
+ err(1, "socket");
+
+ v = 1;
+ error = setsockopt(sd, IPPROTO_IPV6, MRT6_INIT, &v, sizeof(v));
+ if (error != 0)
+ err(1, "setsockopt(MRT6_INIT)");
+
+ STAILQ_FOREACH(mif, &miflist, next) {
+ struct mif6ctl mifc;
+
+ mifc.mif6c_mifi = mif->mifi;
+ mifc.mif6c_pifi = mif->pifi;
+ mifc.mif6c_flags = 0;
+ error = setsockopt(sd, IPPROTO_IPV6, MRT6_ADD_MIF,
+ &mifc, sizeof(mifc));
+ if (error != 0)
+ err(1, "setsockopt(MRT6_ADD_MIF) on %s", mif->name);
+ }
+
+ handle_upcalls(sd);
+
+ error = setsockopt(sd, IPPROTO_IPV6, MRT6_DONE, NULL, 0);
+ if (error != 0)
+ err(1, "setsockopt(MRT6_DONE)");
+
+ return (0);
+}
diff --git a/tests/sys/netinet/ip_mroute.py b/tests/sys/netinet/ip_mroute.py
new file mode 100644
--- /dev/null
+++ b/tests/sys/netinet/ip_mroute.py
@@ -0,0 +1,428 @@
+#
+# Copyright (c) 2025 Stormshield
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+import pytest
+import socket
+import struct
+import subprocess
+import time
+from pathlib import Path
+
+from atf_python.sys.net.vnet import VnetTestTemplate
+
+
+class MRouteTestTemplate(VnetTestTemplate):
+ """
+ Helper class for multicast routing tests. Test classes should inherit from this one.
+ """
+ COORD_SOCK = "coord.sock"
+
+ @staticmethod
+ def _msgwait(sock: socket.socket, expected: bytes):
+ msg = sock.recv(1024)
+ assert msg == expected
+
+ @staticmethod
+ def sendmsg(msg: bytes, path: str):
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+ s.sendto(msg, path)
+ s.close()
+
+ @staticmethod
+ def _makesock(path: str):
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+ s.bind(path)
+ return s
+
+ @staticmethod
+ def mcast_join_INET6(addr: str, port: int):
+ pass
+
+ def jointest(self, vnet):
+ """Let the coordinator know that we're ready, and wait for go-ahead."""
+ coord = self._makesock(vnet.alias + ".sock")
+ self.sendmsg(b"ok " + vnet.alias.encode(), self.COORD_SOCK)
+ self._msgwait(coord, b"join")
+
+ def donetest(self):
+ """Let the coordinator that we completed successfully."""
+ self.sendmsg(b"done", self.COORD_SOCK)
+
+ def starttest(self, vnets: list[str]):
+ self.vnets = vnets
+ for vnet in vnets:
+ self.sendmsg(b"join", vnet + ".sock")
+
+ def waittest(self):
+ for vnet in self.vnets:
+ self._msgwait(self.coord, b"done")
+
+ def setup_method(self, method):
+ self.coord = self._makesock(self.COORD_SOCK)
+ super().setup_method(method)
+
+ # Loop until all other hosts have sent the ok message.
+ received = set()
+ vnet_names = set(self.vnet_map.keys()) - {self.vnet.alias}
+ while len(received) < len(vnet_names):
+ msg = self.coord.recv(1024)
+ received.add(msg)
+ assert received == {b"ok " + name.encode() for name in vnet_names}
+
+
+class MRouteINETTestTemplate(MRouteTestTemplate):
+ @staticmethod
+ def run_pimd(ident: str, ifaces: list[str], rpaddr: str, group: str, fib=0):
+ conf = f"pimd-{ident}.conf"
+ with open(conf, "w") as conf_file:
+ conf_file.write("no phyint\n")
+ for iface in ifaces:
+ conf_file.write(f"phyint {iface} enable\n")
+ conf_file.write(f"rp-address {rpaddr} {group}\n")
+
+ cmd = f"setfib {fib} pimd -i {ident} -f {conf} -p pimd-{ident}.pid -n"
+ return subprocess.Popen(cmd.split(), stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL)
+
+ @staticmethod
+ def mcast_join(addr: str, port: int):
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ mreq = struct.pack("4si", socket.inet_aton(addr), socket.INADDR_ANY)
+ s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
+ s.bind((addr, port))
+ time.sleep(1) # Give the kernel a bit of time to join the group.
+ return s
+
+ @staticmethod
+ def mcast_sendto(addr: str, port: int, iface: str, msg: bytes):
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ mreqn = struct.pack("iii", socket.INADDR_ANY, socket.INADDR_ANY,
+ socket.if_nametoindex(iface))
+ s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, mreqn)
+ s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 64)
+ s.sendto(msg, (addr, port))
+ s.close()
+
+ def setup_method(self, method):
+ self.require_module("ip_mroute")
+ super().setup_method(method)
+
+
+class MRouteINET6TestTemplate(MRouteTestTemplate):
+ @staticmethod
+ def run_ip6_mrouted(ident: str, ifaces: list[str], fib=0):
+ ifaces_str = ' '.join(f"-i {iface}" for iface in ifaces)
+ exepath = Path(__file__).parent / "ip6_mrouted"
+ cmd = f"setfib {fib} {exepath} {ifaces_str}"
+ return subprocess.Popen(cmd.split(), stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL)
+
+ @staticmethod
+ def mcast_join(addr: str, port: int, iface: str):
+ s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ mreq = struct.pack("16si", socket.inet_pton(socket.AF_INET6, addr),
+ socket.if_nametoindex(iface))
+ s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
+ s.bind((addr, port))
+ time.sleep(1) # Give the kernel a bit of time to join the
+ return s
+
+ @staticmethod
+ def mcast_sendto(addr: str, port: int, iface: str, msg: bytes):
+ s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+ mreq = struct.pack("i", socket.if_nametoindex(iface))
+ s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, mreq)
+ s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 64)
+ s.sendto(msg, (addr, port))
+ s.close()
+
+ def setup_method(self, method):
+ self.require_module("ip6_mroute")
+ super().setup_method(method)
+
+
+class Test1RBasicINET(MRouteINETTestTemplate):
+ """Basic multicast routing setup with 2 hosts connected via a router."""
+
+ TOPOLOGY = {
+ "vnet_router": {"ifaces": ["if1", "if2"]},
+ "vnet_host1": {"ifaces": ["if1"]},
+ "vnet_host2": {"ifaces": ["if2"]},
+ "if1": {"prefixes4": [("192.168.1.1/24", "192.168.1.2/24")]},
+ "if2": {"prefixes4": [("192.168.2.1/24", "192.168.2.2/24")]},
+ }
+ MULTICAST_ADDR = "239.0.0.1"
+
+ def setup_method(self, method):
+ # Create VNETs and start the handlers.
+ super().setup_method(method)
+
+ ifaces = [self.vnet.iface_alias_map[i].name for i in ["if1", "if2"]]
+ self.pimd = self.run_pimd("test", ifaces, "127.0.0.1", self.MULTICAST_ADDR + "/32")
+ time.sleep(3) # Give pimd a bit of time to get itself together.
+
+ def vnet_host1_handler(self, vnet):
+ self.jointest(vnet)
+
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345)
+
+ # Wait for host 2 to send a message, then send a reply.
+ self._msgwait(self.sock, b"Hello, Multicast!")
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Goodbye, Multicast!")
+ self._msgwait(self.sock, b"Goodbye, Multicast!")
+ self.donetest()
+
+ def vnet_host2_handler(self, vnet):
+ self.jointest(vnet)
+
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345)
+
+ # Send a message to host 1, then wait for a reply.
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Hello, Multicast!")
+ self._msgwait(self.sock, b"Hello, Multicast!")
+ self._msgwait(self.sock, b"Goodbye, Multicast!")
+ self.donetest()
+
+ @pytest.mark.require_user("root")
+ @pytest.mark.require_progs(["pimd"])
+ @pytest.mark.timeout(30)
+ def test(self):
+ self.starttest(["vnet_host1", "vnet_host2"])
+ self.waittest()
+
+
+class Test1RCrissCrossINET(MRouteINETTestTemplate):
+ """
+ Test a router connected to four hosts, with pairs of interfaces
+ in different FIBs.
+ """
+
+ TOPOLOGY = {
+ "vnet_router": {"ifaces": ["if1", "if2", "if3", "if4"]},
+ "vnet_host1": {"ifaces": ["if1"]},
+ "vnet_host2": {"ifaces": ["if2"]},
+ "vnet_host3": {"ifaces": ["if3"]},
+ "vnet_host4": {"ifaces": ["if4"]},
+ "if1": {
+ "prefixes4": [("192.168.1.1/24", "192.168.1.2/24")],
+ "prefixes6": [],
+ "fib": (0, 0),
+ },
+ "if2": {
+ "prefixes4": [("192.168.2.1/24", "192.168.2.2/24")],
+ "prefixes6": [],
+ "fib": (0, 0),
+ },
+ "if3": {
+ "prefixes4": [("192.168.3.1/24", "192.168.3.2/24")],
+ "prefixes6": [],
+ "fib": (1, 0),
+ },
+ "if4": {
+ "prefixes4": [("192.168.4.1/24", "192.168.4.2/24")],
+ "prefixes6": [],
+ "fib": (1, 0),
+ },
+ }
+ MULTICAST_ADDR = "239.0.0.1"
+
+ def setup_method(self, method):
+ # Create VNETs and start the handlers.
+ super().setup_method(method)
+
+ # Start a pimd instance per FIB.
+ ifaces = [self.vnet.iface_alias_map[i].name for i in ["if1", "if2"]]
+ self.pimd0 = self.run_pimd("test0", ifaces, "127.0.0.1", self.MULTICAST_ADDR + "/32",
+ fib=0)
+ ifaces = [self.vnet.iface_alias_map[i].name for i in ["if3", "if4"]]
+ self.pimd1 = self.run_pimd("test1", ifaces, "127.0.0.1", self.MULTICAST_ADDR + "/32",
+ fib=1)
+ time.sleep(3) # Give pimd a bit of time to get itself together.
+
+ def vnet_host1_handler(self, vnet):
+ self.jointest(vnet)
+
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345)
+ self._msgwait(self.sock, b"Hello, Multicast on FIB 0!")
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Goodbye, Multicast on FIB 0!")
+ self.donetest()
+
+ def vnet_host2_handler(self, vnet):
+ self.jointest(vnet)
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345)
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Hello, Multicast on FIB 0!")
+ self._msgwait(self.sock, b"Hello, Multicast on FIB 0!")
+ self._msgwait(self.sock, b"Goodbye, Multicast on FIB 0!")
+ self.donetest()
+
+ def vnet_host3_handler(self, vnet):
+ self.jointest(vnet)
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345)
+ self._msgwait(self.sock, b"Hello, Multicast on FIB 1!")
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345,
+ vnet.ifaces[0].name, b"Goodbye, Multicast on FIB 1!")
+ self.donetest()
+
+ def vnet_host4_handler(self, vnet):
+ self.jointest(vnet)
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345)
+ time.sleep(1)
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Hello, Multicast on FIB 1!")
+ self._msgwait(self.sock, b"Hello, Multicast on FIB 1!")
+ self._msgwait(self.sock, b"Goodbye, Multicast on FIB 1!")
+ self.donetest()
+
+ @pytest.mark.require_user("root")
+ @pytest.mark.require_progs(["pimd"])
+ @pytest.mark.timeout(30)
+ def test(self):
+ self.starttest(["vnet_host1", "vnet_host2", "vnet_host3", "vnet_host4"])
+ self.waittest()
+
+
+class Test1RBasicINET6(MRouteINET6TestTemplate):
+ """Basic multicast routing setup with 2 hosts connected via a router."""
+
+ TOPOLOGY = {
+ "vnet_router": {"ifaces": ["if1", "if2"]},
+ "vnet_host1": {"ifaces": ["if1"]},
+ "vnet_host2": {"ifaces": ["if2"]},
+ "if1": {
+ "prefixes6": [("2001:db8:0:1::1/64", "2001:db8:0:1::2/64")]
+ },
+ "if2": {
+ "prefixes6": [("2001:db8:0:2::1/64", "2001:db8:0:2::2/64")]
+ },
+ }
+ MULTICAST_ADDR = "ff05::1"
+
+ def setup_method(self, method):
+ # Create VNETs and start the handlers.
+ super().setup_method(method)
+
+ ifaces = [self.vnet.iface_alias_map[i].name for i in ["if1", "if2"]]
+ self.mrouted = self.run_ip6_mrouted("test", ifaces)
+ time.sleep(1)
+
+ def vnet_host1_handler(self, vnet):
+ self.jointest(vnet)
+
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name)
+
+ # Wait for host 2 to send a message, then send a reply.
+ self._msgwait(self.sock, b"Hello, Multicast!")
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Goodbye, Multicast!")
+ self._msgwait(self.sock, b"Goodbye, Multicast!")
+ self.donetest()
+
+ def vnet_host2_handler(self, vnet):
+ self.jointest(vnet)
+
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name)
+
+ # Send a message to host 1, then wait for a reply.
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Hello, Multicast!")
+ self._msgwait(self.sock, b"Hello, Multicast!")
+ self._msgwait(self.sock, b"Goodbye, Multicast!")
+ self.donetest()
+
+ @pytest.mark.require_user("root")
+ @pytest.mark.timeout(30)
+ def test(self):
+ self.starttest(["vnet_host1", "vnet_host2"])
+ self.waittest()
+
+
+class Test1RCrissCrossINET6(MRouteINET6TestTemplate):
+ """
+ Test a router connected to four hosts, with pairs of interfaces
+ in different FIBs.
+ """
+
+ TOPOLOGY = {
+ "vnet_router": {"ifaces": ["if1", "if2", "if3", "if4"]},
+ "vnet_host1": {"ifaces": ["if1"]},
+ "vnet_host2": {"ifaces": ["if2"]},
+ "vnet_host3": {"ifaces": ["if3"]},
+ "vnet_host4": {"ifaces": ["if4"]},
+ "if1": {
+ "prefixes6": [("2001:db8:0:1::1/64", "2001:db8:0:1::2/64")],
+ "fib": (0, 0),
+ },
+ "if2": {
+ "prefixes6": [("2001:db8:0:2::1/64", "2001:db8:0:2::2/64")],
+ "fib": (0, 0),
+ },
+ "if3": {
+ "prefixes6": [("2001:db8:0:3::1/64", "2001:db8:0:3::2/64")],
+ "fib": (1, 0),
+ },
+ "if4": {
+ "prefixes6": [("2001:db8:0:4::1/64", "2001:db8:0:4::2/64")],
+ "fib": (1, 0),
+ },
+ }
+ MULTICAST_ADDR = "ff05::1"
+
+ def setup_method(self, method):
+ # Create VNETs and start the handlers.
+ super().setup_method(method)
+
+ # Start an ip6_mrouted instance per FIB.
+ ifaces = [self.vnet.iface_alias_map[i].name for i in ["if1", "if2"]]
+ self.pimd0 = self.run_ip6_mrouted("test0", ifaces, fib=0)
+ ifaces = [self.vnet.iface_alias_map[i].name for i in ["if3", "if4"]]
+ self.pimd1 = self.run_ip6_mrouted("test1", ifaces, fib=1)
+ time.sleep(1) # Give ip6_mrouted a bit of time to get itself together.
+
+ def vnet_host1_handler(self, vnet):
+ self.jointest(vnet)
+
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name)
+ self._msgwait(self.sock, b"Hello, Multicast on FIB 0!")
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Goodbye, Multicast on FIB 0!")
+ self.donetest()
+
+ def vnet_host2_handler(self, vnet):
+ self.jointest(vnet)
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name)
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Hello, Multicast on FIB 0!")
+ self._msgwait(self.sock, b"Hello, Multicast on FIB 0!")
+ self._msgwait(self.sock, b"Goodbye, Multicast on FIB 0!")
+ self.donetest()
+
+ def vnet_host3_handler(self, vnet):
+ self.jointest(vnet)
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name)
+ self._msgwait(self.sock, b"Hello, Multicast on FIB 1!")
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345,
+ vnet.ifaces[0].name, b"Goodbye, Multicast on FIB 1!")
+ self.donetest()
+
+ def vnet_host4_handler(self, vnet):
+ self.jointest(vnet)
+ self.sock = self.mcast_join(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name)
+ time.sleep(1)
+ self.mcast_sendto(self.MULTICAST_ADDR, 12345, vnet.ifaces[0].name,
+ b"Hello, Multicast on FIB 1!")
+ self._msgwait(self.sock, b"Hello, Multicast on FIB 1!")
+ self._msgwait(self.sock, b"Goodbye, Multicast on FIB 1!")
+ self.donetest()
+
+ @pytest.mark.require_user("root")
+ @pytest.mark.timeout(30)
+ def test(self):
+ self.starttest(["vnet_host1", "vnet_host2", "vnet_host3", "vnet_host4"])
+ self.waittest()
diff --git a/tests/sys/netinet6/Makefile b/tests/sys/netinet6/Makefile
--- a/tests/sys/netinet6/Makefile
+++ b/tests/sys/netinet6/Makefile
@@ -1,6 +1,7 @@
PACKAGE= tests
TESTSDIR= ${TESTSBASE}/sys/netinet6
+BINDIR= ${TESTSDIR}
FILESDIR= ${TESTSDIR}
ATF_TESTS_PYTEST= test_ip6_output.py
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, May 28, 3:38 AM (5 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33576652
Default Alt Text
D55244.id174564.diff (21 KB)
Attached To
Mode
D55244: tests: Add some simple regression tests for ip_mroute
Attached
Detach File
Event Timeline
Log In to Comment