blob: 6897956e79138440ce9e673f1cd97e9b40a4decb [file] [log] [blame]
Garrick Evans54861622019-07-19 09:05:09 +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/arc_service.h"
Garrick Evans54861622019-07-19 09:05:09 +09006
Garrick Evanse94b6de2020-02-20 09:19:13 +09007#include <net/if.h>
8
Garrick Evans54861622019-07-19 09:05:09 +09009#include <utility>
10#include <vector>
11
12#include <base/bind.h>
13
14#include <gmock/gmock.h>
15#include <gtest/gtest.h>
16
Garrick Evans3388a032020-03-24 11:25:55 +090017#include "patchpanel/address_manager.h"
18#include "patchpanel/fake_process_runner.h"
19#include "patchpanel/fake_shill_client.h"
20#include "patchpanel/mock_datapath.h"
21#include "patchpanel/net_util.h"
Garrick Evans54861622019-07-19 09:05:09 +090022
23using testing::_;
Garrick Evanse94b6de2020-02-20 09:19:13 +090024using testing::AnyNumber;
Garrick Evansc7071122020-04-17 12:31:57 +090025using testing::Eq;
26using testing::Pointee;
Garrick Evans54861622019-07-19 09:05:09 +090027using testing::Return;
Garrick Evansb4eb3892019-11-13 12:07:07 +090028using testing::ReturnRef;
Garrick Evans54861622019-07-19 09:05:09 +090029using testing::StrEq;
30
Garrick Evans3388a032020-03-24 11:25:55 +090031namespace patchpanel {
Garrick Evans54861622019-07-19 09:05:09 +090032namespace {
Garrick Evansb4eb3892019-11-13 12:07:07 +090033constexpr pid_t kTestPID = -2;
Garrick Evansb4eb3892019-11-13 12:07:07 +090034constexpr uint32_t kTestCID = 2;
Garrick Evans7a1a9ee2020-01-28 11:03:57 +090035constexpr uint32_t kArcHostIP = Ipv4Addr(100, 115, 92, 1);
36constexpr uint32_t kArcGuestIP = Ipv4Addr(100, 115, 92, 2);
Garrick Evanse94b6de2020-02-20 09:19:13 +090037constexpr uint32_t kArcVmHostIP = Ipv4Addr(100, 115, 92, 5);
38constexpr uint32_t kArcVmGuestIP = Ipv4Addr(100, 115, 92, 6);
Garrick Evans86c7d9c2020-03-17 09:25:48 +090039constexpr uint32_t kFirstArcEthHostIP = kArcVmHostIP;
40constexpr uint32_t kFirstArcEthGuestIP = kArcVmGuestIP;
41constexpr uint32_t kSecondEthHostIP = Ipv4Addr(100, 115, 92, 9);
42constexpr uint32_t kFirstWifiHostIP = Ipv4Addr(100, 115, 92, 13);
43constexpr uint32_t kSecondWifiHostIP = Ipv4Addr(100, 115, 92, 17);
44constexpr uint32_t kFirstCellHostIP = Ipv4Addr(100, 115, 92, 21);
Garrick Evansc7071122020-04-17 12:31:57 +090045constexpr MacAddress kArcVmArc0MacAddr = {0x42, 0x37, 0x05, 0x13, 0x17, 0x01};
Garrick Evans54861622019-07-19 09:05:09 +090046
Garrick Evans2e5c9ab2020-03-05 14:33:58 +090047class MockTrafficForwarder : public TrafficForwarder {
48 public:
49 MockTrafficForwarder() = default;
50 ~MockTrafficForwarder() = default;
51
Jason Jeremy Iman0e9f8262020-03-06 14:50:49 +090052 MOCK_METHOD4(StartForwarding,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +090053 void(const std::string& ifname_physical,
54 const std::string& ifname_virtual,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +090055 bool ipv6,
56 bool multicast));
57
58 MOCK_METHOD4(StopForwarding,
59 void(const std::string& ifname_physical,
60 const std::string& ifname_virtual,
61 bool ipv6,
62 bool multicast));
63};
64
Garrick Evans6e4eb3b2020-03-09 07:18:31 +090065class MockImpl : public ArcService::Impl {
66 public:
67 MockImpl() = default;
68 ~MockImpl() = default;
69
70 MOCK_CONST_METHOD0(guest, GuestMessage::GuestType());
71 MOCK_CONST_METHOD0(id, uint32_t());
Garrick Evans38b25a42020-04-06 15:17:42 +090072 MOCK_CONST_METHOD0(GetDeviceConfigs, std::vector<const Device::Config*>());
Garrick Evans6e4eb3b2020-03-09 07:18:31 +090073 MOCK_METHOD1(Start, bool(uint32_t));
74 MOCK_METHOD1(Stop, void(uint32_t));
75 MOCK_CONST_METHOD1(IsStarted, bool(uint32_t*));
76 MOCK_METHOD1(OnStartDevice, bool(Device*));
77 MOCK_METHOD1(OnStopDevice, void(Device*));
78 MOCK_METHOD2(OnDefaultInterfaceChanged,
79 void(const std::string&, const std::string&));
80};
81
Garrick Evans54861622019-07-19 09:05:09 +090082} // namespace
83
84class ArcServiceTest : public testing::Test {
85 public:
Garrick Evans4ee5ce22020-03-18 07:05:17 +090086 ArcServiceTest() : testing::Test() {}
Garrick Evans54861622019-07-19 09:05:09 +090087
88 protected:
89 void SetUp() override {
Taoyu Li179dcc62019-10-17 11:21:08 +090090 runner_ = std::make_unique<FakeProcessRunner>();
Garrick Evans54861622019-07-19 09:05:09 +090091 runner_->Capture(false);
Taoyu Li179dcc62019-10-17 11:21:08 +090092 datapath_ = std::make_unique<MockDatapath>(runner_.get());
Garrick Evans69b85872020-02-04 11:40:26 +090093 shill_client_ = shill_helper_.Client();
Garrick Evans4ee5ce22020-03-18 07:05:17 +090094 addr_mgr_ = std::make_unique<AddressManager>();
Garrick Evans54861622019-07-19 09:05:09 +090095 }
96
Garrick Evansc7071122020-04-17 12:31:57 +090097 std::unique_ptr<ArcService> NewService(
98 GuestMessage::GuestType guest = GuestMessage::ARC) {
Garrick Evans3388a032020-03-24 11:25:55 +090099 patchpanel::test::guest = guest;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900100 return std::make_unique<ArcService>(shill_client_.get(), datapath_.get(),
Garrick Evansc7071122020-04-17 12:31:57 +0900101 addr_mgr_.get(), &forwarder_,
102 guest == GuestMessage::ARC_VM);
Garrick Evans54861622019-07-19 09:05:09 +0900103 }
104
Garrick Evans69b85872020-02-04 11:40:26 +0900105 FakeShillClientHelper shill_helper_;
106 std::unique_ptr<ShillClient> shill_client_;
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900107 std::unique_ptr<AddressManager> addr_mgr_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900108 MockTrafficForwarder forwarder_;
Taoyu Li179dcc62019-10-17 11:21:08 +0900109 std::unique_ptr<MockDatapath> datapath_;
110 std::unique_ptr<FakeProcessRunner> runner_;
Garrick Evans54861622019-07-19 09:05:09 +0900111};
112
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900113TEST_F(ArcServiceTest, StartDevice) {
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900114 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_eth0"), kFirstArcEthHostIP, 30))
Garrick Evans54861622019-07-19 09:05:09 +0900115 .WillOnce(Return(true));
116 EXPECT_CALL(*datapath_,
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900117 AddInboundIPv4DNAT(StrEq("eth0"),
118 IPv4AddressToString(kFirstArcEthGuestIP)))
Garrick Evans54861622019-07-19 09:05:09 +0900119 .WillOnce(Return(true));
120 EXPECT_CALL(*datapath_, AddOutboundIPv4(StrEq("arc_eth0")))
121 .WillOnce(Return(true));
Garrick Evans54861622019-07-19 09:05:09 +0900122
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900123 auto svc = NewService();
124 auto impl = std::make_unique<MockImpl>();
125 auto* mock_impl = impl.get();
126 svc->impl_ = std::move(impl);
127
128 EXPECT_CALL(*mock_impl, guest()).WillRepeatedly(Return(GuestMessage::ARC));
129 EXPECT_CALL(*mock_impl, IsStarted(_)).WillRepeatedly(Return(true));
130 EXPECT_CALL(*mock_impl, OnStartDevice(_)).WillOnce(Return(true));
131 svc->AddDevice("eth0");
132 EXPECT_TRUE(svc->devices_.find("eth0") != svc->devices_.end());
Garrick Evans54861622019-07-19 09:05:09 +0900133}
134
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900135TEST_F(ArcServiceTest, StopDevice) {
136 EXPECT_CALL(*datapath_, RemoveOutboundIPv4(StrEq("arc_eth0")));
137 EXPECT_CALL(*datapath_,
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900138 RemoveInboundIPv4DNAT(StrEq("eth0"),
139 IPv4AddressToString(kFirstArcEthGuestIP)));
Garrick Evans54861622019-07-19 09:05:09 +0900140 EXPECT_CALL(*datapath_, RemoveBridge(StrEq("arc_eth0")));
141
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900142 auto svc = NewService();
143 auto impl = std::make_unique<MockImpl>();
144 auto* mock_impl = impl.get();
145 svc->impl_ = std::move(impl);
146
147 EXPECT_CALL(*mock_impl, guest()).WillRepeatedly(Return(GuestMessage::ARC));
148 EXPECT_CALL(*mock_impl, IsStarted(_)).WillRepeatedly(Return(true));
149 EXPECT_CALL(*mock_impl, OnStopDevice(_));
150 svc->AddDevice("eth0");
151 svc->RemoveDevice("eth0");
152 EXPECT_TRUE(svc->devices_.find("eth0") == svc->devices_.end());
Garrick Evans54861622019-07-19 09:05:09 +0900153}
154
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900155TEST_F(ArcServiceTest, VerifyAddrConfigs) {
156 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_eth0"), kFirstArcEthHostIP, 30))
157 .WillOnce(Return(true));
158 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_eth1"), kSecondEthHostIP, 30))
159 .WillOnce(Return(true));
160 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_wlan0"), kFirstWifiHostIP, 30))
161 .WillOnce(Return(true));
162 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_wlan1"), kSecondWifiHostIP, 30))
163 .WillOnce(Return(true));
164 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_wwan0"), kFirstCellHostIP, 30))
165 .WillOnce(Return(true));
166 EXPECT_CALL(*datapath_, AddInboundIPv4DNAT(_, _))
167 .WillRepeatedly(Return(true));
168 EXPECT_CALL(*datapath_, AddOutboundIPv4(_)).WillRepeatedly(Return(true));
169
170 auto svc = NewService();
171 auto impl = std::make_unique<MockImpl>();
172 auto* mock_impl = impl.get();
173 svc->impl_ = std::move(impl);
174
175 EXPECT_CALL(*mock_impl, guest()).WillRepeatedly(Return(GuestMessage::ARC));
176 EXPECT_CALL(*mock_impl, IsStarted(_)).WillRepeatedly(Return(true));
177 EXPECT_CALL(*mock_impl, OnStartDevice(_)).WillRepeatedly(Return(true));
178 svc->AddDevice("eth0");
179 svc->AddDevice("eth1");
180 svc->AddDevice("wlan0");
181 svc->AddDevice("wlan1");
182 svc->AddDevice("wwan0");
183}
184
185TEST_F(ArcServiceTest, VerifyAddrOrder) {
186 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_eth0"), kFirstArcEthHostIP, 30))
187 .Times(2)
188 .WillRepeatedly(Return(true));
189 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_wlan0"), kFirstWifiHostIP, 30))
190 .WillOnce(Return(true));
191 EXPECT_CALL(*datapath_, AddInboundIPv4DNAT(_, _))
192 .WillRepeatedly(Return(true));
193 EXPECT_CALL(*datapath_, AddOutboundIPv4(_)).WillRepeatedly(Return(true));
194
195 auto svc = NewService();
196 auto impl = std::make_unique<MockImpl>();
197 auto* mock_impl = impl.get();
198 svc->impl_ = std::move(impl);
199
200 EXPECT_CALL(*mock_impl, guest()).WillRepeatedly(Return(GuestMessage::ARC));
201 EXPECT_CALL(*mock_impl, IsStarted(_)).WillRepeatedly(Return(true));
202 EXPECT_CALL(*mock_impl, OnStartDevice(_)).WillRepeatedly(Return(true));
203 svc->AddDevice("wlan0");
204 svc->AddDevice("eth0");
205 svc->RemoveDevice("eth0");
206 svc->AddDevice("eth0");
207}
208
Garrick Evansc7071122020-04-17 12:31:57 +0900209TEST_F(ArcServiceTest, StableArcVmMacAddrs) {
210 EXPECT_CALL(*datapath_, AddTAP(StrEq(""), _, nullptr, StrEq("crosvm")))
211 .WillRepeatedly(Return("vmtap"));
212 EXPECT_CALL(*datapath_, AddBridge(_, _, 30)).WillRepeatedly(Return(true));
213 EXPECT_CALL(*datapath_, AddToBridge(_, _)).WillRepeatedly(Return(true));
214
215 auto svc = NewService(GuestMessage::ARC_VM);
216 svc->Start(kTestCID);
217 auto configs = svc->GetDeviceConfigs();
218 EXPECT_EQ(configs.size(), 6);
219 auto mac_addr = kArcVmArc0MacAddr;
220 for (const auto* config : configs) {
221 EXPECT_EQ(config->mac_addr(), mac_addr);
222 mac_addr[5]++;
223 }
224}
225
Garrick Evansb4eb3892019-11-13 12:07:07 +0900226// ContainerImpl
227
228class ContainerImplTest : public testing::Test {
229 public:
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900230 ContainerImplTest() : testing::Test() {}
Garrick Evansb4eb3892019-11-13 12:07:07 +0900231
232 protected:
233 void SetUp() override {
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900234 addr_mgr_ = std::make_unique<AddressManager>();
Garrick Evansb4eb3892019-11-13 12:07:07 +0900235 runner_ = std::make_unique<FakeProcessRunner>();
236 runner_->Capture(false);
237 datapath_ = std::make_unique<MockDatapath>(runner_.get());
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900238 addr_mgr_ = std::make_unique<AddressManager>();
Garrick Evansb4eb3892019-11-13 12:07:07 +0900239 }
240
Garrick Evanse94b6de2020-02-20 09:19:13 +0900241 std::unique_ptr<ArcService::ContainerImpl> Impl(bool start = true) {
Garrick Evansb4eb3892019-11-13 12:07:07 +0900242 auto impl = std::make_unique<ArcService::ContainerImpl>(
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900243 datapath_.get(), addr_mgr_.get(), &forwarder_, GuestMessage::ARC);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900244 if (start) {
245 // Set expectations for tests that want it started already.
246 EXPECT_CALL(*datapath_, AddBridge(StrEq("arcbr0"), kArcHostIP, 30))
247 .WillOnce(Return(true));
248 EXPECT_CALL(*datapath_,
249 AddVirtualInterfacePair(StrEq("veth_arc0"), StrEq("arc0")))
250 .WillOnce(Return(true));
251 EXPECT_CALL(*datapath_, ConfigureInterface(StrEq("arc0"), _, kArcGuestIP,
252 30, true, _))
253 .WillOnce(Return(true));
254 EXPECT_CALL(*datapath_, ToggleInterface(StrEq("veth_arc0"), true))
255 .WillOnce(Return(true));
256 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arcbr0"), StrEq("veth_arc0")))
257 .WillOnce(Return(true));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900258
259 impl->Start(kTestPID);
260 }
Garrick Evansb4eb3892019-11-13 12:07:07 +0900261 return impl;
262 }
263
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900264 std::unique_ptr<Device> MakeDevice(const std::string& name,
265 const std::string& host,
Garrick Evans2961c7c2020-04-03 11:34:40 +0900266 const std::string& guest) {
Garrick Evans12eddef2020-03-18 09:18:02 +0900267 Device::Options opt{};
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900268 auto subnet = addr_mgr_->AllocateIPv4Subnet(AddressManager::Guest::ARC_NET);
269 auto addr0 = subnet->AllocateAtOffset(0);
270 auto addr1 = subnet->AllocateAtOffset(1);
271 auto cfg = std::make_unique<Device::Config>(
Garrick Evans6c7dcb82020-03-16 15:21:05 +0900272 addr_mgr_->GenerateMacAddress(), std::move(subnet), std::move(addr0),
273 std::move(addr1));
274 return std::make_unique<Device>(name, host, guest, std::move(cfg), opt);
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900275 }
276
277 std::unique_ptr<AddressManager> addr_mgr_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900278 std::unique_ptr<MockDatapath> datapath_;
279 std::unique_ptr<FakeProcessRunner> runner_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900280 MockTrafficForwarder forwarder_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900281};
282
Garrick Evanse94b6de2020-02-20 09:19:13 +0900283TEST_F(ContainerImplTest, Start) {
284 EXPECT_CALL(*datapath_, AddBridge(StrEq("arcbr0"), kArcHostIP, 30))
285 .WillOnce(Return(true));
Garrick Evansb4eb3892019-11-13 12:07:07 +0900286 EXPECT_CALL(*datapath_,
Garrick Evans2470caa2020-03-04 14:15:41 +0900287 AddVirtualInterfacePair(StrEq("veth_arc0"), StrEq("arc0")))
Garrick Evansb4eb3892019-11-13 12:07:07 +0900288 .WillOnce(Return(true));
Garrick Evans2470caa2020-03-04 14:15:41 +0900289 EXPECT_CALL(*datapath_,
290 ConfigureInterface(StrEq("arc0"), _, kArcGuestIP, 30, true, _))
291 .WillOnce(Return(true));
292 EXPECT_CALL(*datapath_, ToggleInterface(StrEq("veth_arc0"), true))
293 .WillOnce(Return(true));
294 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arcbr0"), StrEq("veth_arc0")))
295 .WillOnce(Return(true));
Jason Jeremy Iman0e9f8262020-03-06 14:50:49 +0900296 EXPECT_CALL(forwarder_, StartForwarding(_, _, _, _)).Times(0);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900297 Impl(false)->Start(kTestPID);
Garrick Evansb4eb3892019-11-13 12:07:07 +0900298}
299
Garrick Evanse94b6de2020-02-20 09:19:13 +0900300TEST_F(ContainerImplTest, Start_FailsToCreateInterface_Android) {
301 EXPECT_CALL(*datapath_, AddBridge(StrEq("arcbr0"), kArcHostIP, 30))
302 .WillOnce(Return(true));
Garrick Evans63378b32020-01-14 10:36:16 +0900303 EXPECT_CALL(*datapath_,
Garrick Evans2470caa2020-03-04 14:15:41 +0900304 AddVirtualInterfacePair(StrEq("veth_arc0"), StrEq("arc0")))
305 .WillOnce(Return(false));
306 EXPECT_CALL(*datapath_, ConfigureInterface(_, _, _, _, _, _)).Times(0);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900307 EXPECT_CALL(*datapath_, RemoveBridge(_)).Times(0);
308 Impl(false)->Start(kTestPID);
Garrick Evans63378b32020-01-14 10:36:16 +0900309}
310
Garrick Evansb05a7ff2020-02-18 12:59:55 +0900311TEST_F(ContainerImplTest, OnStartDevice_FailsToConfigureInterface_Android) {
Garrick Evanse94b6de2020-02-20 09:19:13 +0900312 EXPECT_CALL(*datapath_, AddBridge(StrEq("arcbr0"), kArcHostIP, 30))
313 .WillOnce(Return(true));
Garrick Evansb4eb3892019-11-13 12:07:07 +0900314 EXPECT_CALL(*datapath_,
Garrick Evans2470caa2020-03-04 14:15:41 +0900315 AddVirtualInterfacePair(StrEq("veth_arc0"), StrEq("arc0")))
Garrick Evans63378b32020-01-14 10:36:16 +0900316 .WillOnce(Return(true));
Garrick Evans63378b32020-01-14 10:36:16 +0900317 EXPECT_CALL(*datapath_,
Garrick Evans2470caa2020-03-04 14:15:41 +0900318 ConfigureInterface(StrEq("arc0"), _, kArcGuestIP, 30, true, _))
Garrick Evans63378b32020-01-14 10:36:16 +0900319 .WillOnce(Return(false));
Garrick Evans2470caa2020-03-04 14:15:41 +0900320 EXPECT_CALL(*datapath_, ToggleInterface(StrEq("veth_arc0"), true)).Times(0);
321 EXPECT_CALL(*datapath_, RemoveInterface(StrEq("arc0")));
Garrick Evans63378b32020-01-14 10:36:16 +0900322 EXPECT_CALL(*datapath_, RemoveBridge(_)).Times(0);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900323 Impl(false)->Start(kTestPID);
Garrick Evans63378b32020-01-14 10:36:16 +0900324}
325
Garrick Evanse94b6de2020-02-20 09:19:13 +0900326TEST_F(ContainerImplTest, OnStartDevice) {
Garrick Evansb4eb3892019-11-13 12:07:07 +0900327 EXPECT_CALL(*datapath_,
Garrick Evans2470caa2020-03-04 14:15:41 +0900328 AddVirtualInterfacePair(StrEq("veth_eth0"), StrEq("eth0")))
Garrick Evansb4eb3892019-11-13 12:07:07 +0900329 .WillOnce(Return(true));
Garrick Evans2470caa2020-03-04 14:15:41 +0900330 EXPECT_CALL(*datapath_,
331 ConfigureInterface(StrEq("eth0"), _, Ipv4Addr(100, 115, 92, 10),
332 30, true, _))
333 .WillOnce(Return(true));
334 EXPECT_CALL(*datapath_, ToggleInterface(StrEq("veth_eth0"), true))
335 .WillOnce(Return(true));
336 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arc_eth0"), StrEq("veth_eth0")))
337 .WillOnce(Return(true));
Jason Jeremy Iman0e9f8262020-03-06 14:50:49 +0900338 EXPECT_CALL(forwarder_,
339 StartForwarding(StrEq("eth0"), StrEq("arc_eth0"), _, _));
Garrick Evansb4eb3892019-11-13 12:07:07 +0900340 auto dev = MakeDevice("eth0", "arc_eth0", "eth0");
341 ASSERT_TRUE(dev);
342 Impl()->OnStartDevice(dev.get());
343}
344
Garrick Evanse94b6de2020-02-20 09:19:13 +0900345TEST_F(ContainerImplTest, Stop) {
346 EXPECT_CALL(*datapath_,
347 MaskInterfaceFlags(StrEq("arcbr0"), IFF_DEBUG, IFF_UP));
348 EXPECT_CALL(*datapath_, RemoveInterface(StrEq("veth_arc0")));
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900349 EXPECT_CALL(forwarder_, StopForwarding(_, _, _, _)).Times(0);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900350
351 Impl()->Stop(kTestPID);
Garrick Evansb4eb3892019-11-13 12:07:07 +0900352}
353
Garrick Evanse94b6de2020-02-20 09:19:13 +0900354TEST_F(ContainerImplTest, OnStopDevice) {
Garrick Evansb4eb3892019-11-13 12:07:07 +0900355 EXPECT_CALL(*datapath_, RemoveInterface(StrEq("veth_eth0")));
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900356 EXPECT_CALL(forwarder_,
357 StopForwarding(StrEq("eth0"), StrEq("arc_eth0"), _, _));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900358
Garrick Evansb4eb3892019-11-13 12:07:07 +0900359 auto dev = MakeDevice("eth0", "arc_eth0", "eth0");
360 ASSERT_TRUE(dev);
361 Impl()->OnStopDevice(dev.get());
362}
363
Garrick Evansb4eb3892019-11-13 12:07:07 +0900364// VM Impl
365
366class VmImplTest : public testing::Test {
367 public:
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900368 VmImplTest() : testing::Test() {}
Garrick Evansb4eb3892019-11-13 12:07:07 +0900369
370 protected:
371 void SetUp() override {
Garrick Evansc7071122020-04-17 12:31:57 +0900372 test::guest = GuestMessage::ARC_VM;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900373 addr_mgr_ = std::make_unique<AddressManager>();
Garrick Evansb4eb3892019-11-13 12:07:07 +0900374 runner_ = std::make_unique<FakeProcessRunner>();
375 runner_->Capture(false);
376 datapath_ = std::make_unique<MockDatapath>(runner_.get());
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900377 shill_client_ = helper_.FakeClient();
378 shill_client_->SetFakeDefaultInterface("eth0");
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900379 addr_mgr_ = std::make_unique<AddressManager>();
Garrick Evansb4eb3892019-11-13 12:07:07 +0900380 }
381
Garrick Evans2961c7c2020-04-03 11:34:40 +0900382 std::unique_ptr<ArcService::VmImpl> Impl(
383 bool start = true, const std::vector<Device::Config*> configs = {}) {
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900384 auto impl = std::make_unique<ArcService::VmImpl>(
Garrick Evansf5862122020-03-16 09:13:45 +0900385 shill_client_.get(), datapath_.get(), addr_mgr_.get(), &forwarder_,
Garrick Evans2961c7c2020-04-03 11:34:40 +0900386 configs);
Garrick Evanse94b6de2020-02-20 09:19:13 +0900387 if (start) {
388 impl->Start(kTestCID);
389 }
390
Garrick Evansb4eb3892019-11-13 12:07:07 +0900391 return impl;
392 }
393
Garrick Evans2961c7c2020-04-03 11:34:40 +0900394 std::unique_ptr<Device> MakeDevice(const std::string& name,
395 const std::string& host,
396 const std::string& guest) {
397 Device::Options opt{};
398 auto subnet = addr_mgr_->AllocateIPv4Subnet(AddressManager::Guest::ARC_NET);
399 auto addr0 = subnet->AllocateAtOffset(0);
400 auto addr1 = subnet->AllocateAtOffset(1);
401 auto cfg = std::make_unique<Device::Config>(
402 addr_mgr_->GenerateMacAddress(), std::move(subnet), std::move(addr0),
403 std::move(addr1));
404 return std::make_unique<Device>(name, host, guest, std::move(cfg), opt);
405 }
406
Garrick Evans4ee5ce22020-03-18 07:05:17 +0900407 std::unique_ptr<AddressManager> addr_mgr_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900408 std::unique_ptr<MockDatapath> datapath_;
409 std::unique_ptr<FakeProcessRunner> runner_;
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900410 std::unique_ptr<FakeShillClient> shill_client_;
411 FakeShillClientHelper helper_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900412 MockTrafficForwarder forwarder_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900413};
414
Garrick Evanse94b6de2020-02-20 09:19:13 +0900415TEST_F(VmImplTest, Start) {
Garrick Evansc7071122020-04-17 12:31:57 +0900416 EXPECT_CALL(*datapath_, AddTAP(StrEq(""), Pointee(Eq(kArcVmArc0MacAddr)),
417 nullptr, StrEq("crosvm")))
Garrick Evans2961c7c2020-04-03 11:34:40 +0900418 .WillOnce(Return("vmtap0"));
419 // OnStartDevice
Garrick Evanse94b6de2020-02-20 09:19:13 +0900420 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_br1"), kArcVmHostIP, 30))
421 .WillOnce(Return(true));
Garrick Evans2961c7c2020-04-03 11:34:40 +0900422 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arc_br1"), StrEq("vmtap0")))
423 .WillOnce(Return(true));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900424 EXPECT_CALL(*datapath_,
425 AddLegacyIPv4DNAT(StrEq(IPv4AddressToString(kArcVmGuestIP))))
426 .WillOnce(Return(true));
427 EXPECT_CALL(*datapath_, AddOutboundIPv4(StrEq("arc_br1")))
428 .WillOnce(Return(true));
Garrick Evansb4eb3892019-11-13 12:07:07 +0900429 // OnDefaultInterfaceChanged
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900430 EXPECT_CALL(forwarder_,
431 StopForwarding(StrEq(""), StrEq("arc_br1"), true, true));
Garrick Evansb4eb3892019-11-13 12:07:07 +0900432 EXPECT_CALL(*datapath_, RemoveLegacyIPv4InboundDNAT());
Jason Jeremy Iman0e9f8262020-03-06 14:50:49 +0900433 EXPECT_CALL(forwarder_,
434 StartForwarding(StrEq("eth0"), StrEq("arc_br1"), true, true));
Garrick Evansb4eb3892019-11-13 12:07:07 +0900435 EXPECT_CALL(*datapath_, AddLegacyIPv4InboundDNAT(StrEq("eth0")));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900436
437 Impl(false)->Start(kTestCID);
Garrick Evansb4eb3892019-11-13 12:07:07 +0900438}
Garrick Evansa51d0a12019-11-28 13:51:23 +0900439
Garrick Evans2961c7c2020-04-03 11:34:40 +0900440// Verifies TAPs are added for each provided config.
441TEST_F(VmImplTest, StartWithConfigs) {
Garrick Evansc7071122020-04-17 12:31:57 +0900442 EXPECT_CALL(*datapath_, AddTAP(StrEq(""), _, nullptr, StrEq("crosvm")))
Garrick Evans2961c7c2020-04-03 11:34:40 +0900443 .WillOnce(Return("vmtap0"))
444 .WillOnce(Return("vmtap1"))
445 .WillOnce(Return("vmtap2"));
446 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_br1"), kArcVmHostIP, 30))
447 .WillOnce(Return(true));
448 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arc_br1"), StrEq("vmtap0")))
449 .WillOnce(Return(true));
450
451 Device::Config config1({0, 0, 0, 0, 0, 0}, nullptr, nullptr, nullptr);
452 Device::Config config2({0, 0, 0, 0, 0, 0}, nullptr, nullptr, nullptr);
453 Impl(false, {&config1, &config2})->Start(kTestCID);
454 EXPECT_EQ(config1.tap_ifname(), "vmtap1");
455 EXPECT_EQ(config2.tap_ifname(), "vmtap2");
456}
457
458TEST_F(VmImplTest, StartDeviceWithConfigs) {
Garrick Evansc7071122020-04-17 12:31:57 +0900459 EXPECT_CALL(*datapath_, AddTAP(StrEq(""), _, nullptr, StrEq("crosvm")))
Garrick Evans2961c7c2020-04-03 11:34:40 +0900460 .WillOnce(Return("vmtap0"))
461 .WillOnce(Return("vmtap1"));
462 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_br1"), kArcVmHostIP, 30))
463 .WillOnce(Return(true));
464 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arc_br1"), StrEq("vmtap0")))
465 .WillOnce(Return(true));
466 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arc_eth0"), StrEq("vmtap1")))
467 .WillOnce(Return(true));
468 EXPECT_CALL(forwarder_,
469 StartForwarding(StrEq("eth0"), StrEq("arc_eth0"), _, _));
470
471 auto dev = MakeDevice("eth0", "arc_eth0", "eth0");
472 auto* config = &dev->config();
473 Impl(true, {config})->OnStartDevice(dev.get());
474 EXPECT_EQ(config->tap_ifname(), "vmtap1");
475}
476
Garrick Evanse94b6de2020-02-20 09:19:13 +0900477TEST_F(VmImplTest, Stop) {
478 // Start
Garrick Evansc7071122020-04-17 12:31:57 +0900479 EXPECT_CALL(*datapath_, AddTAP(StrEq(""), _, nullptr, StrEq("crosvm")))
Garrick Evans2961c7c2020-04-03 11:34:40 +0900480 .WillOnce(Return("vmtap0"));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900481 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_br1"), kArcVmHostIP, 30))
482 .WillOnce(Return(true));
Garrick Evans2961c7c2020-04-03 11:34:40 +0900483 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arc_br1"), StrEq("vmtap0")))
484 .WillOnce(Return(true));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900485 EXPECT_CALL(*datapath_,
486 AddLegacyIPv4DNAT(StrEq(IPv4AddressToString(kArcVmGuestIP))))
487 .WillOnce(Return(true));
488 EXPECT_CALL(*datapath_, AddOutboundIPv4(StrEq("arc_br1")))
489 .WillOnce(Return(true));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900490 // OnDefaultInterfaceChanged
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900491 EXPECT_CALL(forwarder_,
492 StopForwarding(StrEq(""), StrEq("arc_br1"), true, true));
Jason Jeremy Iman0e9f8262020-03-06 14:50:49 +0900493 EXPECT_CALL(forwarder_,
494 StartForwarding(StrEq("eth0"), StrEq("arc_br1"), true, true));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900495 EXPECT_CALL(*datapath_, AddLegacyIPv4InboundDNAT(StrEq("eth0")));
Garrick Evansa51d0a12019-11-28 13:51:23 +0900496
Garrick Evanse94b6de2020-02-20 09:19:13 +0900497 // Stop
498 EXPECT_CALL(*datapath_, RemoveOutboundIPv4(StrEq("arc_br1")));
499 EXPECT_CALL(*datapath_, RemoveLegacyIPv4DNAT());
Garrick Evansb4eb3892019-11-13 12:07:07 +0900500 EXPECT_CALL(*datapath_, RemoveInterface(StrEq("vmtap0")));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900501 EXPECT_CALL(*datapath_, RemoveBridge(StrEq("arc_br1")));
502 // OnDefaultInterfaceChanged
503 EXPECT_CALL(*datapath_, RemoveLegacyIPv4InboundDNAT())
504 .Times(2); // +1 for Start
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900505 EXPECT_CALL(forwarder_,
506 StopForwarding(StrEq("eth0"), StrEq("arc_br1"), true, true));
Garrick Evanse94b6de2020-02-20 09:19:13 +0900507 Impl()->Stop(kTestCID);
Garrick Evansb4eb3892019-11-13 12:07:07 +0900508}
509
Garrick Evans2961c7c2020-04-03 11:34:40 +0900510// Verifies TAPs are added for each provided config.
511TEST_F(VmImplTest, StopWithConfigs) {
Garrick Evansc7071122020-04-17 12:31:57 +0900512 EXPECT_CALL(*datapath_, AddTAP(StrEq(""), _, nullptr, StrEq("crosvm")))
Garrick Evans2961c7c2020-04-03 11:34:40 +0900513 .WillOnce(Return("vmtap0"))
514 .WillOnce(Return("vmtap1"))
515 .WillOnce(Return("vmtap2"));
516 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_br1"), kArcVmHostIP, 30))
517 .WillOnce(Return(true));
518 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arc_br1"), StrEq("vmtap0")))
519 .WillOnce(Return(true));
520 // Stop
521 EXPECT_CALL(*datapath_, RemoveInterface(StrEq("vmtap0")));
522 EXPECT_CALL(*datapath_, RemoveInterface(StrEq("vmtap1")));
523 EXPECT_CALL(*datapath_, RemoveInterface(StrEq("vmtap2")));
524
525 Device::Config config1({0, 0, 0, 0, 0, 0}, nullptr, nullptr, nullptr);
526 Device::Config config2({0, 0, 0, 0, 0, 0}, nullptr, nullptr, nullptr);
527 Impl(true, {&config1, &config2})->Stop(kTestCID);
528 EXPECT_TRUE(config1.tap_ifname().empty());
529 EXPECT_TRUE(config2.tap_ifname().empty());
530}
531
532TEST_F(VmImplTest, StopDeviceWithConfigs) {
Garrick Evansc7071122020-04-17 12:31:57 +0900533 EXPECT_CALL(*datapath_, AddTAP(StrEq(""), _, nullptr, StrEq("crosvm")))
Garrick Evans2961c7c2020-04-03 11:34:40 +0900534 .WillOnce(Return("vmtap0"))
535 .WillOnce(Return("vmtap1"));
536 EXPECT_CALL(*datapath_, AddBridge(StrEq("arc_br1"), kArcVmHostIP, 30))
537 .WillOnce(Return(true));
538 EXPECT_CALL(*datapath_, AddToBridge(StrEq("arc_br1"), StrEq("vmtap0")))
539 .WillOnce(Return(true));
540 EXPECT_CALL(forwarder_,
541 StopForwarding(StrEq("eth0"), StrEq("arc_eth0"), _, _));
542
543 auto dev = MakeDevice("eth0", "arc_eth0", "eth0");
544 auto* config = &dev->config();
545 config->set_tap_ifname("vmtap1"); // Usually happens in OnStartDevice.
546 Impl(true, {config})->OnStopDevice(dev.get());
547 EXPECT_TRUE(config->tap_ifname().empty());
548}
Garrick Evans3388a032020-03-24 11:25:55 +0900549
550} // namespace patchpanel