Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 1 | // Copyright 2019 The Chromium OS Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "arc/network/datapath.h" |
| 6 | |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 7 | #include <linux/if_tun.h> |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 8 | #include <net/if.h> |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 9 | #include <sys/ioctl.h> |
| 10 | |
| 11 | #include <set> |
Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 12 | #include <utility> |
| 13 | #include <vector> |
| 14 | |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 15 | #include <base/bind.h> |
Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 16 | #include <base/strings/string_util.h> |
Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 17 | #include <gtest/gtest.h> |
| 18 | |
| 19 | #include "arc/network/fake_process_runner.h" |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 20 | #include "arc/network/net_util.h" |
Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 21 | |
| 22 | namespace arc_networkd { |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 23 | namespace { |
| 24 | |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 25 | std::set<ioctl_req_t> ioctl_reqs; |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 26 | |
| 27 | // Capture all ioctls and succeed. |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 28 | int ioctl_req_cap(int fd, ioctl_req_t req, ...) { |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 29 | ioctl_reqs.insert(req); |
| 30 | return 0; |
| 31 | } |
| 32 | |
| 33 | } // namespace |
| 34 | |
| 35 | TEST(DatapathTest, AddTAP) { |
| 36 | FakeProcessRunner runner; |
| 37 | Datapath datapath(&runner, ioctl_req_cap); |
| 38 | MacAddress mac = {1, 2, 3, 4, 5, 6}; |
| 39 | Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::Bind(&base::DoNothing)); |
| 40 | auto addr = subnet.AllocateAtOffset(0); |
Garrick Evans | 4f9f557 | 2019-11-26 10:25:16 +0900 | [diff] [blame] | 41 | auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), ""); |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 42 | EXPECT_EQ(ifname, "foo0"); |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 43 | std::set<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, SIOCSIFADDR, |
| 44 | SIOCSIFNETMASK, SIOCSIFHWADDR, SIOCGIFFLAGS, |
| 45 | SIOCSIFFLAGS}; |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 46 | EXPECT_EQ(ioctl_reqs, expected); |
| 47 | ioctl_reqs.clear(); |
| 48 | } |
| 49 | |
| 50 | TEST(DatapathTest, AddTAPWithOwner) { |
| 51 | FakeProcessRunner runner; |
| 52 | Datapath datapath(&runner, ioctl_req_cap); |
| 53 | MacAddress mac = {1, 2, 3, 4, 5, 6}; |
| 54 | Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::Bind(&base::DoNothing)); |
| 55 | auto addr = subnet.AllocateAtOffset(0); |
Garrick Evans | 4f9f557 | 2019-11-26 10:25:16 +0900 | [diff] [blame] | 56 | auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "root"); |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 57 | EXPECT_EQ(ifname, "foo0"); |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 58 | std::set<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, TUNSETOWNER, |
| 59 | SIOCSIFADDR, SIOCSIFNETMASK, SIOCSIFHWADDR, |
| 60 | SIOCGIFFLAGS, SIOCSIFFLAGS}; |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 61 | EXPECT_EQ(ioctl_reqs, expected); |
| 62 | ioctl_reqs.clear(); |
| 63 | } |
| 64 | |
Garrick Evans | 621ed26 | 2019-11-13 12:28:43 +0900 | [diff] [blame] | 65 | TEST(DatapathTest, AddTAPNoAddrs) { |
| 66 | FakeProcessRunner runner; |
| 67 | Datapath datapath(&runner, ioctl_req_cap); |
Garrick Evans | 4f9f557 | 2019-11-26 10:25:16 +0900 | [diff] [blame] | 68 | auto ifname = datapath.AddTAP("foo0", nullptr, nullptr, ""); |
Garrick Evans | 621ed26 | 2019-11-13 12:28:43 +0900 | [diff] [blame] | 69 | EXPECT_EQ(ifname, "foo0"); |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 70 | std::set<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, SIOCGIFFLAGS, |
Garrick Evans | 4dec0c4 | 2019-11-29 12:51:57 +0900 | [diff] [blame] | 71 | SIOCSIFFLAGS}; |
Garrick Evans | 621ed26 | 2019-11-13 12:28:43 +0900 | [diff] [blame] | 72 | EXPECT_EQ(ioctl_reqs, expected); |
| 73 | ioctl_reqs.clear(); |
| 74 | } |
| 75 | |
Garrick Evans | c7ae82c | 2019-09-04 16:25:10 +0900 | [diff] [blame] | 76 | TEST(DatapathTest, RemoveTAP) { |
| 77 | FakeProcessRunner runner; |
| 78 | runner.Capture(true); |
| 79 | Datapath datapath(&runner); |
| 80 | datapath.RemoveTAP("foo0"); |
| 81 | runner.VerifyRuns({"/bin/ip tuntap del foo0 mode tap"}); |
| 82 | } |
Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 83 | |
Garrick Evans | 8a949dc | 2019-07-18 16:17:53 +0900 | [diff] [blame] | 84 | TEST(DatapathTest, AddBridge) { |
| 85 | FakeProcessRunner runner; |
| 86 | runner.Capture(true); |
| 87 | Datapath datapath(&runner); |
| 88 | datapath.AddBridge("br", "1.2.3.4"); |
| 89 | runner.VerifyRuns( |
| 90 | {"/sbin/brctl addbr br", |
| 91 | "/bin/ifconfig br 1.2.3.4 netmask 255.255.255.252 up", |
| 92 | "/sbin/iptables -t mangle -A PREROUTING -i br -j MARK --set-mark 1 -w"}); |
| 93 | } |
| 94 | |
Garrick Evans | 5486162 | 2019-07-19 09:05:09 +0900 | [diff] [blame] | 95 | TEST(DatapathTest, AddVirtualBridgedInterface) { |
| 96 | FakeProcessRunner runner; |
| 97 | runner.Capture(true); |
| 98 | Datapath datapath(&runner); |
| 99 | std::string peer = |
| 100 | datapath.AddVirtualBridgedInterface("foo", "00:11:22", "brfoo"); |
| 101 | EXPECT_EQ(peer, "peer_foo"); |
| 102 | runner.VerifyRuns( |
| 103 | {"/bin/ip link delete veth_foo", // RemoveInterface is run first |
| 104 | "/bin/ip link add veth_foo type veth peer name peer_foo", |
| 105 | "/bin/ifconfig veth_foo up", |
| 106 | "/bin/ip link set dev peer_foo addr 00:11:22 down", |
| 107 | "/sbin/brctl addif brfoo veth_foo"}); |
| 108 | } |
| 109 | |
| 110 | TEST(DatapathTest, RemoveInterface) { |
| 111 | FakeProcessRunner runner; |
| 112 | runner.Capture(true); |
| 113 | Datapath datapath(&runner); |
| 114 | datapath.RemoveInterface("foo"); |
| 115 | runner.VerifyRuns({"/bin/ip link delete foo"}); |
| 116 | } |
| 117 | |
Garrick Evans | 8a949dc | 2019-07-18 16:17:53 +0900 | [diff] [blame] | 118 | TEST(DatapathTest, RemoveBridge) { |
| 119 | FakeProcessRunner runner; |
| 120 | runner.Capture(true); |
| 121 | Datapath datapath(&runner); |
| 122 | datapath.RemoveBridge("br"); |
| 123 | runner.VerifyRuns( |
| 124 | {"/sbin/iptables -t mangle -D PREROUTING -i br -j MARK --set-mark 1 -w", |
| 125 | "/bin/ifconfig br down", "/sbin/brctl delbr br"}); |
| 126 | } |
| 127 | |
Garrick Evans | 5486162 | 2019-07-19 09:05:09 +0900 | [diff] [blame] | 128 | TEST(DatapathTest, AddInterfaceToContainer) { |
| 129 | FakeProcessRunner runner; |
| 130 | runner.Capture(true); |
| 131 | Datapath datapath(&runner); |
| 132 | datapath.AddInterfaceToContainer(123, "src", "dst", "1.2.3.4", true); |
| 133 | runner.VerifyRuns({"/bin/ip link set src netns 123"}); |
| 134 | runner.VerifyAddInterface("src", "dst", "1.2.3.4", "255.255.255.252", true, |
| 135 | "123"); |
| 136 | } |
| 137 | |
Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 138 | TEST(DatapathTest, AddLegacyIPv4DNAT) { |
| 139 | FakeProcessRunner runner; |
| 140 | runner.Capture(true); |
| 141 | Datapath datapath(&runner); |
| 142 | datapath.AddLegacyIPv4DNAT("1.2.3.4"); |
| 143 | runner.VerifyRuns( |
| 144 | {"/sbin/iptables -t nat -N dnat_arc -w", |
| 145 | "/sbin/iptables -t nat -A dnat_arc -j DNAT --to-destination " |
| 146 | "1.2.3.4 -w", |
| 147 | "/sbin/iptables -t nat -N try_arc -w", |
| 148 | "/sbin/iptables -t nat -A PREROUTING -m socket --nowildcard -j ACCEPT " |
| 149 | "-w", |
| 150 | "/sbin/iptables -t nat -A PREROUTING -p tcp -j try_arc -w", |
| 151 | "/sbin/iptables -t nat -A PREROUTING -p udp -j try_arc -w"}); |
| 152 | } |
| 153 | |
| 154 | TEST(DatapathTest, RemoveLegacyIPv4DNAT) { |
| 155 | FakeProcessRunner runner; |
| 156 | runner.Capture(true); |
| 157 | Datapath datapath(&runner); |
| 158 | datapath.RemoveLegacyIPv4DNAT(); |
| 159 | runner.VerifyRuns( |
| 160 | {"/sbin/iptables -t nat -D PREROUTING -p udp -j try_arc -w", |
| 161 | "/sbin/iptables -t nat -D PREROUTING -p tcp -j try_arc -w", |
| 162 | "/sbin/iptables -t nat -D PREROUTING -m socket --nowildcard -j " |
| 163 | "ACCEPT -w", |
| 164 | "/sbin/iptables -t nat -F try_arc -w", |
| 165 | "/sbin/iptables -t nat -X try_arc -w", |
| 166 | "/sbin/iptables -t nat -F dnat_arc -w", |
| 167 | "/sbin/iptables -t nat -X dnat_arc -w"}); |
| 168 | } |
| 169 | |
Garrick Evans | 5486162 | 2019-07-19 09:05:09 +0900 | [diff] [blame] | 170 | TEST(DatapathTest, AddLegacyIPv4InboundDNAT) { |
| 171 | FakeProcessRunner runner; |
| 172 | runner.Capture(true); |
| 173 | Datapath datapath(&runner); |
| 174 | datapath.AddLegacyIPv4InboundDNAT("wlan0"); |
| 175 | runner.VerifyRuns( |
| 176 | {"/sbin/iptables -t nat -A try_arc -i wlan0 -j dnat_arc -w"}); |
| 177 | } |
| 178 | |
| 179 | TEST(DatapathTest, RemoveLegacyIPv4InboundDNAT) { |
| 180 | FakeProcessRunner runner; |
| 181 | runner.Capture(true); |
| 182 | Datapath datapath(&runner); |
| 183 | datapath.RemoveLegacyIPv4InboundDNAT(); |
| 184 | runner.VerifyRuns({"/sbin/iptables -t nat -F try_arc -w"}); |
| 185 | } |
| 186 | |
Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 187 | TEST(DatapathTest, AddInboundIPv4DNAT) { |
| 188 | FakeProcessRunner runner; |
| 189 | runner.Capture(true); |
| 190 | Datapath datapath(&runner); |
| 191 | datapath.AddInboundIPv4DNAT("eth0", "1.2.3.4"); |
| 192 | runner.VerifyRuns( |
| 193 | {"/sbin/iptables -t nat -A PREROUTING -i eth0 -m socket --nowildcard -j " |
| 194 | "ACCEPT " |
| 195 | "-w", |
| 196 | "/sbin/iptables -t nat -A PREROUTING -i eth0 -p tcp -j DNAT " |
| 197 | "--to-destination 1.2.3.4 -w", |
| 198 | "/sbin/iptables -t nat -A PREROUTING -i eth0 -p udp -j DNAT " |
| 199 | "--to-destination 1.2.3.4 -w"}); |
| 200 | } |
| 201 | |
| 202 | TEST(DatapathTest, RemoveInboundIPv4DNAT) { |
| 203 | FakeProcessRunner runner; |
| 204 | runner.Capture(true); |
| 205 | Datapath datapath(&runner); |
| 206 | datapath.RemoveInboundIPv4DNAT("eth0", "1.2.3.4"); |
| 207 | runner.VerifyRuns( |
| 208 | {"/sbin/iptables -t nat -D PREROUTING -i eth0 -p udp -j DNAT " |
| 209 | "--to-destination 1.2.3.4 -w", |
| 210 | "/sbin/iptables -t nat -D PREROUTING -i eth0 -p tcp -j DNAT " |
| 211 | "--to-destination 1.2.3.4 -w", |
| 212 | "/sbin/iptables -t nat -D PREROUTING -i eth0 -m socket --nowildcard " |
| 213 | "-j ACCEPT -w"}); |
| 214 | } |
| 215 | |
| 216 | TEST(DatapathTest, AddOutboundIPv4) { |
| 217 | FakeProcessRunner runner; |
| 218 | runner.Capture(true); |
| 219 | Datapath datapath(&runner); |
| 220 | datapath.AddOutboundIPv4("eth0"); |
| 221 | runner.VerifyRuns( |
| 222 | {"/sbin/iptables -t filter -A FORWARD -o eth0 -j ACCEPT -w"}); |
| 223 | } |
| 224 | |
| 225 | TEST(DatapathTest, RemoveInboundIPv4) { |
| 226 | FakeProcessRunner runner; |
| 227 | runner.Capture(true); |
| 228 | Datapath datapath(&runner); |
| 229 | datapath.RemoveOutboundIPv4("eth0"); |
| 230 | runner.VerifyRuns( |
| 231 | {"/sbin/iptables -t filter -D FORWARD -o eth0 -j ACCEPT -w"}); |
| 232 | } |
| 233 | |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 234 | TEST(DatapathTest, SetInterfaceFlag) { |
| 235 | FakeProcessRunner runner; |
| 236 | Datapath datapath(&runner, ioctl_req_cap); |
| 237 | bool result = datapath.SetInterfaceFlag("foo0", IFF_DEBUG); |
| 238 | EXPECT_TRUE(result); |
| 239 | std::set<ioctl_req_t> expected = {SIOCGIFFLAGS, SIOCSIFFLAGS}; |
| 240 | EXPECT_EQ(ioctl_reqs, expected); |
| 241 | ioctl_reqs.clear(); |
| 242 | } |
| 243 | |
| 244 | TEST(DatapathTest, AddIPv6Forwarding) { |
| 245 | FakeProcessRunner runner; |
| 246 | runner.Capture(true); |
| 247 | Datapath datapath(&runner); |
Taoyu Li | ca49c83 | 2019-12-06 17:56:43 +0900 | [diff] [blame^] | 248 | // Return 1 on iptables -C to simulate rule not existing case |
| 249 | auto fake_iptables_run = [](const std::vector<std::string>& argv) { |
| 250 | return std::find(argv.begin(), argv.end(), "-C") == argv.end() ? 0 : 1; |
| 251 | }; |
| 252 | runner.SetRunOverride(base::Bind(fake_iptables_run)); |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 253 | datapath.AddIPv6Forwarding("eth0", "arc_eth0"); |
| 254 | runner.VerifyRuns( |
Taoyu Li | ca49c83 | 2019-12-06 17:56:43 +0900 | [diff] [blame^] | 255 | {"/sbin/ip6tables -C FORWARD -i eth0 -o arc_eth0 -j ACCEPT -w", |
| 256 | "/sbin/ip6tables -A FORWARD -i eth0 -o arc_eth0 -j ACCEPT -w", |
| 257 | "/sbin/ip6tables -C FORWARD -i arc_eth0 -o eth0 -j ACCEPT -w", |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 258 | "/sbin/ip6tables -A FORWARD -i arc_eth0 -o eth0 -j ACCEPT -w"}); |
| 259 | } |
| 260 | |
Taoyu Li | ca49c83 | 2019-12-06 17:56:43 +0900 | [diff] [blame^] | 261 | TEST(DatapathTest, AddIPv6ForwardingRuleExists) { |
| 262 | FakeProcessRunner runner; |
| 263 | runner.Capture(true); |
| 264 | Datapath datapath(&runner); |
| 265 | datapath.AddIPv6Forwarding("eth0", "arc_eth0"); |
| 266 | runner.VerifyRuns( |
| 267 | {"/sbin/ip6tables -C FORWARD -i eth0 -o arc_eth0 -j ACCEPT -w", |
| 268 | "/sbin/ip6tables -C FORWARD -i arc_eth0 -o eth0 -j ACCEPT -w"}); |
| 269 | } |
| 270 | |
Taoyu Li | 90c1391 | 2019-11-26 17:56:54 +0900 | [diff] [blame] | 271 | TEST(DatapathTest, RemoveIPv6Forwarding) { |
| 272 | FakeProcessRunner runner; |
| 273 | runner.Capture(true); |
| 274 | Datapath datapath(&runner); |
| 275 | datapath.RemoveIPv6Forwarding("eth0", "arc_eth0"); |
| 276 | runner.VerifyRuns( |
| 277 | {"/sbin/ip6tables -D FORWARD -i eth0 -o arc_eth0 -j ACCEPT -w", |
| 278 | "/sbin/ip6tables -D FORWARD -i arc_eth0 -o eth0 -j ACCEPT -w"}); |
| 279 | } |
| 280 | |
Taoyu Li | eb6cc8f | 2019-12-09 15:53:04 +0900 | [diff] [blame] | 281 | TEST(DatapathTest, AddIPv6HostRoute) { |
| 282 | FakeProcessRunner runner; |
| 283 | runner.Capture(true); |
| 284 | Datapath datapath(&runner); |
| 285 | datapath.AddIPv6HostRoute("eth0", "2001:da8:e00::1234", 128); |
| 286 | runner.VerifyRuns( |
| 287 | {"/bin/ip -6 route replace 2001:da8:e00::1234/128 dev eth0"}); |
| 288 | } |
| 289 | |
Garrick Evans | f0ab713 | 2019-06-18 14:50:42 +0900 | [diff] [blame] | 290 | } // namespace arc_networkd |