blob: ee233b57a603190abe4414d10697970ed89fd8a8 [file] [log] [blame]
Garrick Evansf0ab7132019-06-18 14:50:42 +09001// 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
Garrick Evans3388a032020-03-24 11:25:55 +09005#include "patchpanel/datapath.h"
Garrick Evansf0ab7132019-06-18 14:50:42 +09006
Garrick Evansc7ae82c2019-09-04 16:25:10 +09007#include <linux/if_tun.h>
Taoyu Li90c13912019-11-26 17:56:54 +09008#include <net/if.h>
Garrick Evansc7ae82c2019-09-04 16:25:10 +09009#include <sys/ioctl.h>
10
Garrick Evansf0ab7132019-06-18 14:50:42 +090011#include <utility>
12#include <vector>
13
Garrick Evansc7ae82c2019-09-04 16:25:10 +090014#include <base/bind.h>
Qijiang Fane90b8792020-03-09 16:15:41 +090015#include <base/bind_helpers.h>
Garrick Evansf0ab7132019-06-18 14:50:42 +090016#include <base/strings/string_util.h>
Garrick Evans8e8e3472020-01-23 14:03:50 +090017#include <gmock/gmock.h>
Garrick Evansf0ab7132019-06-18 14:50:42 +090018#include <gtest/gtest.h>
19
Garrick Evans3388a032020-03-24 11:25:55 +090020#include "patchpanel/net_util.h"
Garrick Evansf0ab7132019-06-18 14:50:42 +090021
Garrick Evans8e8e3472020-01-23 14:03:50 +090022using testing::_;
23using testing::ElementsAre;
24using testing::Return;
25using testing::StrEq;
26
Garrick Evans3388a032020-03-24 11:25:55 +090027namespace patchpanel {
Garrick Evansc7ae82c2019-09-04 16:25:10 +090028namespace {
29
Hugo Benichi76675592020-04-08 14:29:57 +090030// TODO(hugobenichi) Centralize this constant definition
31constexpr pid_t kTestPID = -2;
32
Hugo Benichie8758b52020-04-03 14:49:01 +090033std::vector<ioctl_req_t> ioctl_reqs;
34std::vector<std::pair<std::string, struct rtentry>> ioctl_rtentry_args;
Garrick Evansc7ae82c2019-09-04 16:25:10 +090035
36// Capture all ioctls and succeed.
Taoyu Li90c13912019-11-26 17:56:54 +090037int ioctl_req_cap(int fd, ioctl_req_t req, ...) {
Hugo Benichie8758b52020-04-03 14:49:01 +090038 ioctl_reqs.push_back(req);
39 return 0;
40}
41
42// Capture ioctls for SIOCADDRT and SIOCDELRT and succeed.
43int ioctl_rtentry_cap(int fd, ioctl_req_t req, struct rtentry* arg) {
44 ioctl_reqs.push_back(req);
45 ioctl_rtentry_args.push_back({"", *arg});
46 // Copy the string poited by rtentry.rt_dev because Add/DeleteIPv4Route pass
47 // this value to ioctl() on the stack.
48 if (arg->rt_dev) {
49 auto& cap = ioctl_rtentry_args.back();
50 cap.first = std::string(arg->rt_dev);
51 cap.second.rt_dev = (char*)cap.first.c_str();
52 }
Garrick Evansc7ae82c2019-09-04 16:25:10 +090053 return 0;
54}
55
56} // namespace
57
Garrick Evans8e8e3472020-01-23 14:03:50 +090058class MockProcessRunner : public MinijailedProcessRunner {
59 public:
60 MockProcessRunner() = default;
61 ~MockProcessRunner() = default;
62
Garrick Evans2470caa2020-03-04 14:15:41 +090063 MOCK_METHOD2(RestoreDefaultNamespace,
64 int(const std::string& ifname, pid_t pid));
65 MOCK_METHOD1(WriteSentinelToContainer, int(pid_t pid));
Garrick Evans8e8e3472020-01-23 14:03:50 +090066 MOCK_METHOD3(brctl,
67 int(const std::string& cmd,
68 const std::vector<std::string>& argv,
69 bool log_failures));
70 MOCK_METHOD4(chown,
71 int(const std::string& uid,
72 const std::string& gid,
73 const std::string& file,
74 bool log_failures));
Garrick Evans8e8e3472020-01-23 14:03:50 +090075 MOCK_METHOD4(ip,
76 int(const std::string& obj,
77 const std::string& cmd,
78 const std::vector<std::string>& args,
79 bool log_failures));
80 MOCK_METHOD4(ip6,
81 int(const std::string& obj,
82 const std::string& cmd,
83 const std::vector<std::string>& args,
84 bool log_failures));
85 MOCK_METHOD3(iptables,
86 int(const std::string& table,
87 const std::vector<std::string>& argv,
88 bool log_failures));
89 MOCK_METHOD3(ip6tables,
90 int(const std::string& table,
91 const std::vector<std::string>& argv,
92 bool log_failures));
93 MOCK_METHOD2(modprobe_all,
94 int(const std::vector<std::string>& modules, bool log_failures));
95 MOCK_METHOD3(sysctl_w,
96 int(const std::string& key,
97 const std::string& value,
98 bool log_failures));
99};
100
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900101TEST(DatapathTest, AddTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900102 MockProcessRunner runner;
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900103 Datapath datapath(&runner, ioctl_req_cap);
104 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900105 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900106 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900107 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900108 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900109 std::vector<ioctl_req_t> expected = {
110 TUNSETIFF, TUNSETPERSIST, SIOCSIFADDR, SIOCSIFNETMASK,
111 SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900112 EXPECT_EQ(ioctl_reqs, expected);
113 ioctl_reqs.clear();
114}
115
116TEST(DatapathTest, AddTAPWithOwner) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900117 MockProcessRunner runner;
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900118 Datapath datapath(&runner, ioctl_req_cap);
119 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900120 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900121 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900122 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "root");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900123 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900124 std::vector<ioctl_req_t> expected = {
125 TUNSETIFF, TUNSETPERSIST, TUNSETOWNER, SIOCSIFADDR,
126 SIOCSIFNETMASK, SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900127 EXPECT_EQ(ioctl_reqs, expected);
128 ioctl_reqs.clear();
129}
130
Garrick Evans621ed262019-11-13 12:28:43 +0900131TEST(DatapathTest, AddTAPNoAddrs) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900132 MockProcessRunner runner;
Garrick Evans621ed262019-11-13 12:28:43 +0900133 Datapath datapath(&runner, ioctl_req_cap);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900134 auto ifname = datapath.AddTAP("foo0", nullptr, nullptr, "");
Garrick Evans621ed262019-11-13 12:28:43 +0900135 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900136 std::vector<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, SIOCGIFFLAGS,
137 SIOCSIFFLAGS};
Garrick Evans621ed262019-11-13 12:28:43 +0900138 EXPECT_EQ(ioctl_reqs, expected);
139 ioctl_reqs.clear();
140}
141
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900142TEST(DatapathTest, RemoveTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900143 MockProcessRunner runner;
144 EXPECT_CALL(runner, ip(StrEq("tuntap"), StrEq("del"),
145 ElementsAre("foo0", "mode", "tap"), true));
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900146 Datapath datapath(&runner);
147 datapath.RemoveTAP("foo0");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900148}
Garrick Evansf0ab7132019-06-18 14:50:42 +0900149
Garrick Evans8a949dc2019-07-18 16:17:53 +0900150TEST(DatapathTest, AddBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900151 MockProcessRunner runner;
Garrick Evans8a949dc2019-07-18 16:17:53 +0900152 Datapath datapath(&runner);
Garrick Evans8e8e3472020-01-23 14:03:50 +0900153 EXPECT_CALL(runner, brctl(StrEq("addbr"), ElementsAre("br"), true));
Garrick Evans6f4fa3a2020-02-10 16:15:09 +0900154 EXPECT_CALL(
155 runner,
156 ip(StrEq("addr"), StrEq("add"),
157 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "br"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900158 EXPECT_CALL(runner,
159 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "up"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900160 EXPECT_CALL(runner, iptables(StrEq("mangle"),
161 ElementsAre("-A", "PREROUTING", "-i", "br", "-j",
162 "MARK", "--set-mark", "1", "-w"),
163 true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900164 datapath.AddBridge("br", Ipv4Addr(1, 1, 1, 1), 30);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900165}
166
Hugo Benichi76675592020-04-08 14:29:57 +0900167TEST(DatapathTest, ConnectVethPair) {
168 MockProcessRunner runner;
169 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
170 ElementsAre("veth_foo", "type", "veth", "peer", "name",
171 "peer_foo"),
172 true));
173 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
174 ElementsAre("100.115.92.169/30", "brd",
175 "100.115.92.171", "dev", "peer_foo"),
176 true))
177 .WillOnce(Return(0));
178 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
179 ElementsAre("dev", "peer_foo", "up", "addr",
180 "01:02:03:04:05:06", "multicast", "on"),
181 true))
182 .WillOnce(Return(0));
183 EXPECT_CALL(runner, RestoreDefaultNamespace(StrEq("veth_foo"), kTestPID));
184 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
185 ElementsAre("veth_foo", "up"), true));
186 Datapath datapath(&runner);
187 EXPECT_TRUE(datapath.ConnectVethPair(kTestPID, "veth_foo", "peer_foo",
188 {1, 2, 3, 4, 5, 6},
189 Ipv4Addr(100, 115, 92, 169), 30, true));
190}
191
Garrick Evans2470caa2020-03-04 14:15:41 +0900192TEST(DatapathTest, AddVirtualInterfacePair) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900193 MockProcessRunner runner;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900194 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
195 ElementsAre("veth_foo", "type", "veth", "peer", "name",
196 "peer_foo"),
197 true));
Garrick Evans2470caa2020-03-04 14:15:41 +0900198 Datapath datapath(&runner);
199 EXPECT_TRUE(datapath.AddVirtualInterfacePair("veth_foo", "peer_foo"));
200}
201
202TEST(DatapathTest, ToggleInterface) {
203 MockProcessRunner runner;
204 EXPECT_CALL(runner,
205 ip(StrEq("link"), StrEq("set"), ElementsAre("foo", "up"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900206 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
Garrick Evans2470caa2020-03-04 14:15:41 +0900207 ElementsAre("bar", "down"), true));
208 Datapath datapath(&runner);
209 EXPECT_TRUE(datapath.ToggleInterface("foo", true));
210 EXPECT_TRUE(datapath.ToggleInterface("bar", false));
211}
212
213TEST(DatapathTest, ConfigureInterface) {
214 MockProcessRunner runner;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900215 EXPECT_CALL(
216 runner,
Garrick Evans2470caa2020-03-04 14:15:41 +0900217 ip(StrEq("addr"), StrEq("add"),
218 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "foo"), true))
219 .WillOnce(Return(0));
220 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
221 ElementsAre("dev", "foo", "up", "addr",
222 "02:02:02:02:02:02", "multicast", "on"),
223 true))
224 .WillOnce(Return(0));
225
Garrick Evans54861622019-07-19 09:05:09 +0900226 Datapath datapath(&runner);
Garrick Evans2470caa2020-03-04 14:15:41 +0900227 MacAddress mac_addr = {2, 2, 2, 2, 2, 2};
228 EXPECT_TRUE(datapath.ConfigureInterface("foo", mac_addr, Ipv4Addr(1, 1, 1, 1),
229 30, true, true));
Garrick Evans54861622019-07-19 09:05:09 +0900230}
231
232TEST(DatapathTest, RemoveInterface) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900233 MockProcessRunner runner;
234 EXPECT_CALL(runner,
235 ip(StrEq("link"), StrEq("delete"), ElementsAre("foo"), false));
Garrick Evans54861622019-07-19 09:05:09 +0900236 Datapath datapath(&runner);
237 datapath.RemoveInterface("foo");
Garrick Evans54861622019-07-19 09:05:09 +0900238}
239
Garrick Evans8a949dc2019-07-18 16:17:53 +0900240TEST(DatapathTest, RemoveBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900241 MockProcessRunner runner;
242 EXPECT_CALL(runner, iptables(StrEq("mangle"),
243 ElementsAre("-D", "PREROUTING", "-i", "br", "-j",
244 "MARK", "--set-mark", "1", "-w"),
245 true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900246 EXPECT_CALL(runner,
247 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "down"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900248 EXPECT_CALL(runner, brctl(StrEq("delbr"), ElementsAre("br"), true));
Garrick Evans8a949dc2019-07-18 16:17:53 +0900249 Datapath datapath(&runner);
250 datapath.RemoveBridge("br");
Garrick Evans8a949dc2019-07-18 16:17:53 +0900251}
252
Garrick Evansf0ab7132019-06-18 14:50:42 +0900253TEST(DatapathTest, AddLegacyIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900254 MockProcessRunner runner;
255 EXPECT_CALL(runner, iptables(StrEq("nat"),
256 ElementsAre("-N", "dnat_arc", "-w"), true));
257 EXPECT_CALL(runner, iptables(StrEq("nat"),
258 ElementsAre("-A", "dnat_arc", "-j", "DNAT",
259 "--to-destination", "1.2.3.4", "-w"),
260 true));
261 EXPECT_CALL(runner,
262 iptables(StrEq("nat"), ElementsAre("-N", "try_arc", "-w"), true));
263 EXPECT_CALL(runner,
264 iptables(StrEq("nat"),
265 ElementsAre("-A", "PREROUTING", "-m", "socket",
266 "--nowildcard", "-j", "ACCEPT", "-w"),
267 true));
268 EXPECT_CALL(runner, iptables(StrEq("nat"),
269 ElementsAre("-A", "PREROUTING", "-p", "tcp",
270 "-j", "try_arc", "-w"),
271 true));
272 EXPECT_CALL(runner, iptables(StrEq("nat"),
273 ElementsAre("-A", "PREROUTING", "-p", "udp",
274 "-j", "try_arc", "-w"),
275 true));
Garrick Evansf0ab7132019-06-18 14:50:42 +0900276 Datapath datapath(&runner);
277 datapath.AddLegacyIPv4DNAT("1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900278}
279
280TEST(DatapathTest, RemoveLegacyIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900281 MockProcessRunner runner;
282 EXPECT_CALL(runner, iptables(StrEq("nat"),
283 ElementsAre("-D", "PREROUTING", "-p", "udp",
284 "-j", "try_arc", "-w"),
285 true));
286 EXPECT_CALL(runner, iptables(StrEq("nat"),
287 ElementsAre("-D", "PREROUTING", "-p", "tcp",
288 "-j", "try_arc", "-w"),
289 true));
290 EXPECT_CALL(runner,
291 iptables(StrEq("nat"),
292 ElementsAre("-D", "PREROUTING", "-m", "socket",
293 "--nowildcard", "-j", "ACCEPT", "-w"),
294 true));
295 EXPECT_CALL(runner,
296 iptables(StrEq("nat"), ElementsAre("-F", "try_arc", "-w"), true));
297 EXPECT_CALL(runner,
298 iptables(StrEq("nat"), ElementsAre("-X", "try_arc", "-w"), true));
299 EXPECT_CALL(runner, iptables(StrEq("nat"),
300 ElementsAre("-F", "dnat_arc", "-w"), true));
301 EXPECT_CALL(runner, iptables(StrEq("nat"),
302 ElementsAre("-X", "dnat_arc", "-w"), true));
Garrick Evansf0ab7132019-06-18 14:50:42 +0900303 Datapath datapath(&runner);
304 datapath.RemoveLegacyIPv4DNAT();
Garrick Evansf0ab7132019-06-18 14:50:42 +0900305}
306
Garrick Evans54861622019-07-19 09:05:09 +0900307TEST(DatapathTest, AddLegacyIPv4InboundDNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900308 MockProcessRunner runner;
309 EXPECT_CALL(runner, iptables(StrEq("nat"),
310 ElementsAre("-A", "try_arc", "-i", "wlan0", "-j",
311 "dnat_arc", "-w"),
312 true));
Garrick Evans54861622019-07-19 09:05:09 +0900313 Datapath datapath(&runner);
314 datapath.AddLegacyIPv4InboundDNAT("wlan0");
Garrick Evans54861622019-07-19 09:05:09 +0900315}
316
317TEST(DatapathTest, RemoveLegacyIPv4InboundDNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900318 MockProcessRunner runner;
319 EXPECT_CALL(runner,
320 iptables(StrEq("nat"), ElementsAre("-F", "try_arc", "-w"), true));
Garrick Evans54861622019-07-19 09:05:09 +0900321 Datapath datapath(&runner);
322 datapath.RemoveLegacyIPv4InboundDNAT();
Garrick Evans54861622019-07-19 09:05:09 +0900323}
324
Garrick Evansf0ab7132019-06-18 14:50:42 +0900325TEST(DatapathTest, AddInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900326 MockProcessRunner runner;
327 EXPECT_CALL(runner, iptables(StrEq("nat"),
328 ElementsAre("-A", "PREROUTING", "-i", "eth0",
329 "-m", "socket", "--nowildcard", "-j",
330 "ACCEPT", "-w"),
331 true));
332 EXPECT_CALL(runner, iptables(StrEq("nat"),
333 ElementsAre("-A", "PREROUTING", "-i", "eth0",
334 "-p", "tcp", "-j", "DNAT",
335 "--to-destination", "1.2.3.4", "-w"),
336 true));
337 EXPECT_CALL(runner, iptables(StrEq("nat"),
338 ElementsAre("-A", "PREROUTING", "-i", "eth0",
339 "-p", "udp", "-j", "DNAT",
340 "--to-destination", "1.2.3.4", "-w"),
341 true));
Garrick Evansf0ab7132019-06-18 14:50:42 +0900342 Datapath datapath(&runner);
343 datapath.AddInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900344}
345
346TEST(DatapathTest, RemoveInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900347 MockProcessRunner runner;
348 EXPECT_CALL(runner, iptables(StrEq("nat"),
349 ElementsAre("-D", "PREROUTING", "-i", "eth0",
350 "-m", "socket", "--nowildcard", "-j",
351 "ACCEPT", "-w"),
352 true));
353 EXPECT_CALL(runner, iptables(StrEq("nat"),
354 ElementsAre("-D", "PREROUTING", "-i", "eth0",
355 "-p", "tcp", "-j", "DNAT",
356 "--to-destination", "1.2.3.4", "-w"),
357 true));
358 EXPECT_CALL(runner, iptables(StrEq("nat"),
359 ElementsAre("-D", "PREROUTING", "-i", "eth0",
360 "-p", "udp", "-j", "DNAT",
361 "--to-destination", "1.2.3.4", "-w"),
362 true));
Garrick Evansf0ab7132019-06-18 14:50:42 +0900363 Datapath datapath(&runner);
364 datapath.RemoveInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900365}
366
367TEST(DatapathTest, AddOutboundIPv4) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900368 MockProcessRunner runner;
369 EXPECT_CALL(runner, iptables(StrEq("filter"),
370 ElementsAre("-A", "FORWARD", "-o", "eth0", "-j",
371 "ACCEPT", "-w"),
372 true));
Garrick Evansf0ab7132019-06-18 14:50:42 +0900373 Datapath datapath(&runner);
374 datapath.AddOutboundIPv4("eth0");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900375}
376
377TEST(DatapathTest, RemoveInboundIPv4) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900378 MockProcessRunner runner;
379 EXPECT_CALL(runner, iptables(StrEq("filter"),
380 ElementsAre("-D", "FORWARD", "-o", "eth0", "-j",
381 "ACCEPT", "-w"),
382 true));
Garrick Evansf0ab7132019-06-18 14:50:42 +0900383 Datapath datapath(&runner);
384 datapath.RemoveOutboundIPv4("eth0");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900385}
386
Garrick Evans664a82f2019-12-17 12:18:05 +0900387TEST(DatapathTest, MaskInterfaceFlags) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900388 MockProcessRunner runner;
Taoyu Li90c13912019-11-26 17:56:54 +0900389 Datapath datapath(&runner, ioctl_req_cap);
Garrick Evans664a82f2019-12-17 12:18:05 +0900390 bool result = datapath.MaskInterfaceFlags("foo0", IFF_DEBUG);
Taoyu Li90c13912019-11-26 17:56:54 +0900391 EXPECT_TRUE(result);
Hugo Benichie8758b52020-04-03 14:49:01 +0900392 std::vector<ioctl_req_t> expected = {SIOCGIFFLAGS, SIOCSIFFLAGS};
Taoyu Li90c13912019-11-26 17:56:54 +0900393 EXPECT_EQ(ioctl_reqs, expected);
394 ioctl_reqs.clear();
395}
396
397TEST(DatapathTest, AddIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900398 MockProcessRunner runner;
Taoyu Lica49c832019-12-06 17:56:43 +0900399 // Return 1 on iptables -C to simulate rule not existing case
Garrick Evans8e8e3472020-01-23 14:03:50 +0900400 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
401 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
402 "arc_eth0", "-j", "ACCEPT", "-w"),
403 false))
404 .WillOnce(Return(1));
405 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
406 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
407 "arc_eth0", "-j", "ACCEPT", "-w"),
408 true));
409 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
410 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
411 "-o", "eth0", "-j", "ACCEPT", "-w"),
412 false))
413 .WillOnce(Return(1));
414 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
415 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
416 "-o", "eth0", "-j", "ACCEPT", "-w"),
417 true));
418 Datapath datapath(&runner);
Taoyu Li90c13912019-11-26 17:56:54 +0900419 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +0900420}
421
Taoyu Lica49c832019-12-06 17:56:43 +0900422TEST(DatapathTest, AddIPv6ForwardingRuleExists) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900423 MockProcessRunner runner;
424 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
425 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
426 "arc_eth0", "-j", "ACCEPT", "-w"),
427 false));
428 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
429 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
430 "-o", "eth0", "-j", "ACCEPT", "-w"),
431 false));
Taoyu Lica49c832019-12-06 17:56:43 +0900432 Datapath datapath(&runner);
433 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Lica49c832019-12-06 17:56:43 +0900434}
435
Taoyu Li90c13912019-11-26 17:56:54 +0900436TEST(DatapathTest, RemoveIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900437 MockProcessRunner runner;
438 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
439 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
440 "arc_eth0", "-j", "ACCEPT", "-w"),
441 true));
442 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
443 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
444 "-o", "eth0", "-j", "ACCEPT", "-w"),
445 true));
Taoyu Li90c13912019-11-26 17:56:54 +0900446 Datapath datapath(&runner);
447 datapath.RemoveIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +0900448}
449
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900450TEST(DatapathTest, AddIPv6HostRoute) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900451 MockProcessRunner runner;
452 EXPECT_CALL(runner,
453 ip6(StrEq("route"), StrEq("replace"),
454 ElementsAre("2001:da8:e00::1234/128", "dev", "eth0"), true));
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900455 Datapath datapath(&runner);
456 datapath.AddIPv6HostRoute("eth0", "2001:da8:e00::1234", 128);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900457}
458
Hugo Benichie8758b52020-04-03 14:49:01 +0900459TEST(DatapathTest, AddIPv4Route) {
460 MockProcessRunner runner;
461 Datapath datapath(&runner, (ioctl_t)ioctl_rtentry_cap);
462
463 datapath.AddIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
464 Ipv4Addr(255, 255, 255, 0));
465 datapath.DeleteIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
466 Ipv4Addr(255, 255, 255, 0));
467 datapath.AddIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
468 Ipv4Addr(255, 255, 255, 252));
469 datapath.DeleteIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
470 Ipv4Addr(255, 255, 255, 252));
471
472 std::vector<ioctl_req_t> expected_reqs = {SIOCADDRT, SIOCDELRT, SIOCADDRT,
473 SIOCDELRT};
474 EXPECT_EQ(expected_reqs, ioctl_reqs);
475 ioctl_reqs.clear();
476
477 std::string route1 =
478 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.93.0}, rt_genmask: "
479 "{family: AF_INET, port: 0, addr: 255.255.255.0}, rt_gateway: {family: "
480 "AF_INET, port: 0, addr: 192.168.1.1}, rt_dev: null, rt_flags: RTF_UP | "
481 "RTF_GATEWAY}";
482 std::string route2 =
483 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.92.8}, rt_genmask: "
484 "{family: AF_INET, port: 0, addr: 255.255.255.252}, rt_gateway: {unset}, "
485 "rt_dev: eth0, rt_flags: RTF_UP | RTF_GATEWAY}";
486 std::vector<std::string> captured_routes;
487 for (const auto& route : ioctl_rtentry_args) {
488 std::ostringstream stream;
489 stream << route.second;
490 captured_routes.emplace_back(stream.str());
491 }
492 ioctl_rtentry_args.clear();
493 EXPECT_EQ(route1, captured_routes[0]);
494 EXPECT_EQ(route1, captured_routes[1]);
495 EXPECT_EQ(route2, captured_routes[2]);
496 EXPECT_EQ(route2, captured_routes[3]);
497}
498
Garrick Evans2f581a02020-05-11 10:43:35 +0900499TEST(DatapathTest, ArcVethHostName) {
500 EXPECT_EQ("vetheth0", ArcVethHostName("eth0"));
501 EXPECT_EQ("vethrmnet0", ArcVethHostName("rmnet0"));
502 EXPECT_EQ("vethrmnet_data0", ArcVethHostName("rmnet_data0"));
503 EXPECT_EQ("vethifnamsiz_i0", ArcVethHostName("ifnamsiz_ifnam0"));
504 auto ifname = ArcVethHostName("exceeds_ifnamesiz_checkanyway");
505 EXPECT_EQ("vethexceeds_ify", ifname);
506 EXPECT_LT(ifname.length(), IFNAMSIZ);
507}
508
Garrick Evans8a067562020-05-11 12:47:30 +0900509TEST(DatapathTest, ArcBridgeName) {
510 EXPECT_EQ("arc_eth0", ArcBridgeName("eth0"));
511 EXPECT_EQ("arc_rmnet0", ArcBridgeName("rmnet0"));
512 EXPECT_EQ("arc_rmnet_data0", ArcBridgeName("rmnet_data0"));
513 EXPECT_EQ("arc_ifnamsiz_i0", ArcBridgeName("ifnamsiz_ifnam0"));
514 auto ifname = ArcBridgeName("exceeds_ifnamesiz_checkanyway");
515 EXPECT_EQ("arc_exceeds_ify", ifname);
516 EXPECT_LT(ifname.length(), IFNAMSIZ);
517}
518
Garrick Evans3388a032020-03-24 11:25:55 +0900519} // namespace patchpanel