07eaf5ffb5f239b129c77fa1fd3f5ba67b4e118a
[tinc] / test / integration / device_tap.py
1 #!/usr/bin/env python3
2
3 """Test TAP device support."""
4
5 import typing as T
6
7 from testlib import check, util, cmd
8 from testlib.log import log
9 from testlib.proc import Script, Tinc
10 from testlib.test import Test
11 from testlib.external import netns_add, netns_exec, ping
12
13 util.require_root()
14 util.require_command("ip", "netns", "list")
15 util.require_path("/dev/net/tun")
16
17 IP_FOO = "10.0.0.1"
18 IP_BAR = "10.0.0.2"
19 IP_DUMMY = "10.0.0.3"
20
21 ARP_WORKS = {
22     "router": False,
23     "hub": True,
24     "switch": True,
25 }
26
27
28 def make_up(node: str, address: str) -> str:
29     """Create a network configuration script."""
30     return f"""
31     import subprocess as subp
32     subp.run(['ip', 'link', 'set', 'dev', '{node}', 'netns', '{node}'], check=True)
33     subp.run(['ip', 'netns', 'exec', '{node}', 'ip', 'addr', 'add', 'dev', '{node}', '{address}/24'], check=True)
34     subp.run(['ip', 'netns', 'exec', '{node}', 'ip', 'link', 'set', '{node}', 'up'], check=True)
35     """
36
37
38 def init(ctx: Test, mode: str) -> T.Tuple[Tinc, Tinc]:
39     """Configure nodes."""
40
41     stdin = f"""
42         set DeviceType tap
43         add Subnet {IP_FOO}
44         set Mode {mode}
45     """
46     foo = ctx.node(init=stdin)
47     foo.cmd("set", "Interface", foo.name)
48     netns_add(foo.name)
49
50     stdin = f"""
51         set DeviceType tap
52         add Subnet {IP_BAR}
53         set Mode {mode}
54     """
55     bar = ctx.node(init=stdin)
56     bar.cmd("set", "Interface", bar.name)
57     netns_add(bar.name)
58
59     return foo, bar
60
61
62 def run_tests(ctx: Test, mode: str) -> None:
63     """Test BindToAddress or ListenAddress."""
64
65     foo, bar = init(ctx, mode)
66
67     log.info("add tinc-up scripts")
68     foo.add_script(Script.TINC_UP, make_up(foo.name, IP_FOO))
69     bar.add_script(Script.TINC_UP, make_up(bar.name, IP_BAR))
70
71     log.info("start nodes and wait for them to connect")
72     cmd.connect(foo, bar)
73
74     log.info("test ICMP")
75     assert ping(IP_FOO, bar.name)
76
77     log.info("create a dummy device for sending ARP requests")
78     netns_exec(bar.name, "ip", "link", "add", "dummy0", "type", "dummy", check=True)
79     netns_exec(bar.name, "ip", "addr", "add", IP_DUMMY, "dev", "dummy0", check=True)
80     netns_exec(bar.name, "ip", "link", "set", "dummy0", "up", check=True)
81
82     log.info("test ARP with Mode %s", mode)
83     proc = netns_exec(foo.name, "arping", "-c1", IP_DUMMY)
84     check.equals(ARP_WORKS[dev_mode], proc.returncode == 0)
85
86
87 for dev_mode in "switch", "hub", "router":
88     with Test(f"test TAP device ({dev_mode})") as context:
89         run_tests(context, dev_mode)