blob: 47b8dddeffa8b0d49a04fefbea8e6456144fd617 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "arc/network/device_manager.h"
#include <memory>
#include <utility>
#include <vector>
#include <base/files/file_descriptor_watcher_posix.h>
#include <base/message_loop/message_loop.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/mock_bus.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "arc/network/fake_process_runner.h"
#include "arc/network/fake_shill_client.h"
#include "arc/network/mock_datapath.h"
#include "arc/network/net_util.h"
namespace arc_networkd {
namespace {
class FakeAddressManager : public AddressManager {
public:
FakeAddressManager()
: AddressManager({
AddressManager::Guest::ARC,
AddressManager::Guest::ARC_NET,
}) {}
MacAddress GenerateMacAddress() override {
static const MacAddress kAddr = {0xf7, 0x69, 0xe5, 0xc4, 0x1f, 0x74};
return kAddr;
}
};
class DeviceManagerTest : public testing::Test {
protected:
DeviceManagerTest() = default;
void SetUp() override {
fpr_ = std::make_unique<FakeProcessRunner>();
fpr_->Capture(false);
datapath_ = std::make_unique<MockDatapath>(fpr_.get());
}
std::unique_ptr<DeviceManager> NewManager(bool is_arc_legacy = false) {
shill_helper_ = std::make_unique<FakeShillClientHelper>();
auto shill_client = shill_helper_->FakeClient();
shill_client_ = shill_client.get();
auto mgr = std::make_unique<DeviceManager>(
std::move(shill_client), &addr_mgr_, datapath_.get(), is_arc_legacy,
new arc_networkd::HelperProcess() /* mcast_proxy */);
return mgr;
}
FakeShillClient* shill_client_;
private:
std::unique_ptr<FakeShillClientHelper> shill_helper_;
FakeAddressManager addr_mgr_;
std::unique_ptr<MockDatapath> datapath_;
std::unique_ptr<FakeProcessRunner> fpr_;
// This is required because of the RT netlink handler.
base::MessageLoopForIO msg_loop_;
base::FileDescriptorWatcher watcher_{&msg_loop_};
};
} // namespace
TEST_F(DeviceManagerTest, MakeEthernetDevices) {
auto mgr = NewManager();
auto eth0 = mgr->MakeDevice("eth0");
const auto& cfg = eth0->config();
EXPECT_EQ(cfg.host_ifname(), "arc_eth0");
EXPECT_EQ(cfg.guest_ifname(), "eth0");
EXPECT_EQ(cfg.host_ipv4_addr(), Ipv4Addr(100, 115, 92, 9));
EXPECT_EQ(cfg.guest_ipv4_addr(), Ipv4Addr(100, 115, 92, 10));
EXPECT_TRUE(eth0->options().ipv6_enabled);
auto usb0 = mgr->MakeDevice("usb0");
const auto& cfgu = usb0->config();
EXPECT_EQ(cfgu.host_ifname(), "arc_usb0");
EXPECT_EQ(cfgu.guest_ifname(), "usb0");
EXPECT_EQ(cfgu.host_ipv4_addr(), Ipv4Addr(100, 115, 92, 13));
EXPECT_EQ(cfgu.guest_ipv4_addr(), Ipv4Addr(100, 115, 92, 14));
EXPECT_TRUE(usb0->options().ipv6_enabled);
}
TEST_F(DeviceManagerTest, MakeWifiDevices) {
auto mgr = NewManager();
auto wlan0 = mgr->MakeDevice("wlan0");
const auto& cfg = wlan0->config();
EXPECT_EQ(cfg.host_ifname(), "arc_wlan0");
EXPECT_EQ(cfg.guest_ifname(), "wlan0");
EXPECT_EQ(cfg.host_ipv4_addr(), Ipv4Addr(100, 115, 92, 9));
EXPECT_EQ(cfg.guest_ipv4_addr(), Ipv4Addr(100, 115, 92, 10));
EXPECT_TRUE(wlan0->options().ipv6_enabled);
auto mlan0 = mgr->MakeDevice("mlan0");
const auto& cfgm = mlan0->config();
EXPECT_EQ(cfgm.host_ifname(), "arc_mlan0");
EXPECT_EQ(cfgm.guest_ifname(), "mlan0");
EXPECT_EQ(cfgm.host_ipv4_addr(), Ipv4Addr(100, 115, 92, 13));
EXPECT_EQ(cfgm.guest_ipv4_addr(), Ipv4Addr(100, 115, 92, 14));
EXPECT_TRUE(mlan0->options().ipv6_enabled);
}
TEST_F(DeviceManagerTest, MakeCellularDevice) {
auto mgr = NewManager();
auto wwan0 = mgr->MakeDevice("wwan0");
const auto& cfg = wwan0->config();
EXPECT_EQ(cfg.host_ifname(), "arc_wwan0");
EXPECT_EQ(cfg.guest_ifname(), "wwan0");
EXPECT_EQ(cfg.host_ipv4_addr(), Ipv4Addr(100, 115, 92, 9));
EXPECT_EQ(cfg.guest_ipv4_addr(), Ipv4Addr(100, 115, 92, 10));
EXPECT_FALSE(wwan0->options().ipv6_enabled);
}
TEST_F(DeviceManagerTest, MakeDevice_Android) {
auto mgr = NewManager();
auto arc0 = mgr->MakeDevice(kAndroidDevice);
const auto& cfg = arc0->config();
EXPECT_EQ(cfg.host_ifname(), "arcbr0");
EXPECT_EQ(cfg.guest_ifname(), "arc0");
EXPECT_EQ(cfg.host_ipv4_addr(), Ipv4Addr(100, 115, 92, 1));
EXPECT_EQ(cfg.guest_ipv4_addr(), Ipv4Addr(100, 115, 92, 2));
EXPECT_FALSE(arc0->options().ipv6_enabled);
}
TEST_F(DeviceManagerTest, MakeDevice_LegacyAndroid) {
auto mgr = NewManager(true /* is_arc_legacy */);
auto arc0 = mgr->MakeDevice(kAndroidLegacyDevice);
const auto& cfg = arc0->config();
EXPECT_EQ(cfg.host_ifname(), "arcbr0");
EXPECT_EQ(cfg.guest_ifname(), "arc0");
EXPECT_EQ(cfg.host_ipv4_addr(), Ipv4Addr(100, 115, 92, 1));
EXPECT_EQ(cfg.guest_ipv4_addr(), Ipv4Addr(100, 115, 92, 2));
EXPECT_TRUE(arc0->options().ipv6_enabled);
}
TEST_F(DeviceManagerTest, MakeVpnTunDevice) {
auto mgr = NewManager();
auto tun0 = mgr->MakeDevice("tun0");
const auto& cfg = tun0->config();
EXPECT_EQ(cfg.host_ifname(), "arc_tun0");
EXPECT_EQ(cfg.guest_ifname(), "cros_tun0");
EXPECT_EQ(cfg.host_ipv4_addr(), Ipv4Addr(100, 115, 92, 9));
EXPECT_EQ(cfg.guest_ipv4_addr(), Ipv4Addr(100, 115, 92, 10));
EXPECT_FALSE(tun0->options().ipv6_enabled);
}
TEST_F(DeviceManagerTest, MakeDevice_NoMoreSubnets) {
auto mgr = NewManager();
std::vector<std::unique_ptr<Device>> devices;
for (int i = 0; i < 4; ++i) {
auto dev = mgr->MakeDevice(base::StringPrintf("%d", i));
EXPECT_TRUE(dev);
devices.emplace_back(std::move(dev));
}
EXPECT_FALSE(mgr->MakeDevice("x"));
}
TEST_F(DeviceManagerTest, AddNewDevices) {
auto mgr = NewManager();
mgr->OnGuestStart(GuestMessage::ARC);
std::vector<dbus::ObjectPath> devices = {dbus::ObjectPath("eth0"),
dbus::ObjectPath("wlan0")};
auto value = brillo::Any(devices);
shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty, value);
EXPECT_TRUE(mgr->Exists("eth0"));
EXPECT_TRUE(mgr->Exists("wlan0"));
}
TEST_F(DeviceManagerTest, NoDevicesAddedWhenMultinetDisabled) {
auto mgr = NewManager(true /* is_arc_legacy */);
mgr->OnGuestStart(GuestMessage::ARC_LEGACY);
std::vector<dbus::ObjectPath> devices = {dbus::ObjectPath("eth0"),
dbus::ObjectPath("wlan0")};
auto value = brillo::Any(devices);
shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty, value);
EXPECT_FALSE(mgr->Exists("eth0"));
EXPECT_FALSE(mgr->Exists("wlan0"));
}
TEST_F(DeviceManagerTest, PreviousDevicesRemoved) {
auto mgr = NewManager();
{
std::vector<dbus::ObjectPath> devices = {dbus::ObjectPath("eth0"),
dbus::ObjectPath("wlan0")};
auto value = brillo::Any(devices);
shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty, value);
EXPECT_TRUE(mgr->Exists("eth0"));
EXPECT_TRUE(mgr->Exists("wlan0"));
}
{
std::vector<dbus::ObjectPath> devices = {dbus::ObjectPath("eth0"),
dbus::ObjectPath("eth1")};
auto value = brillo::Any(devices);
shill_client_->NotifyManagerPropertyChange(shill::kDevicesProperty, value);
EXPECT_TRUE(mgr->Exists("eth0"));
EXPECT_TRUE(mgr->Exists("eth1"));
EXPECT_FALSE(mgr->Exists("wlan0"));
}
}
} // namespace arc_networkd