blob: 7fdd7b6f6813d86697b0bce36fe51f2f31752a89 [file] [log] [blame]
Garrick Evans5d55f5e2019-07-17 15:28:10 +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#ifndef PATCHPANEL_ARC_SERVICE_H_
6#define PATCHPANEL_ARC_SERVICE_H_
Garrick Evans5d55f5e2019-07-17 15:28:10 +09007
Garrick Evans86c7d9c2020-03-17 09:25:48 +09008#include <deque>
Garrick Evans1b1f67c2020-02-04 16:21:25 +09009#include <map>
Garrick Evans3915af32019-07-25 15:44:34 +090010#include <memory>
Garrick Evans6e4eb3b2020-03-09 07:18:31 +090011#include <set>
Garrick Evans3915af32019-07-25 15:44:34 +090012#include <string>
Garrick Evans2961c7c2020-04-03 11:34:40 +090013#include <vector>
Garrick Evans54861622019-07-19 09:05:09 +090014
15#include <base/memory/weak_ptr.h>
Garrick Evans6e4eb3b2020-03-09 07:18:31 +090016#include <gtest/gtest_prod.h> // for FRIEND_TEST
Garrick Evans54861622019-07-19 09:05:09 +090017
Garrick Evans3388a032020-03-24 11:25:55 +090018#include "patchpanel/address_manager.h"
19#include "patchpanel/datapath.h"
20#include "patchpanel/device.h"
21#include "patchpanel/ipc.pb.h"
22#include "patchpanel/shill_client.h"
23#include "patchpanel/traffic_forwarder.h"
Garrick Evans5d55f5e2019-07-17 15:28:10 +090024
Garrick Evans3388a032020-03-24 11:25:55 +090025namespace patchpanel {
Garrick Evans5d55f5e2019-07-17 15:28:10 +090026
Garrick Evansf29f5a32019-12-06 11:34:25 +090027class ArcService {
Garrick Evans5d55f5e2019-07-17 15:28:10 +090028 public:
Garrick Evansb4eb3892019-11-13 12:07:07 +090029 class Impl {
30 public:
31 virtual ~Impl() = default;
32
Garrick Evans015b0d62020-02-07 09:06:38 +090033 virtual uint32_t id() const = 0;
Garrick Evansb4eb3892019-11-13 12:07:07 +090034
Garrick Evans38b25a42020-04-06 15:17:42 +090035 // Returns the list of device configurations that were provided to the
36 // implementation at creation time plus the one for the ARC device, if
37 // applicable. Currently only ARCVM supports this method.
38 virtual std::vector<const Device::Config*> GetDeviceConfigs() const = 0;
39
Garrick Evans015b0d62020-02-07 09:06:38 +090040 virtual bool Start(uint32_t id) = 0;
41 virtual void Stop(uint32_t id) = 0;
42 virtual bool IsStarted(uint32_t* id = nullptr) const = 0;
Hugo Benichiad1bdd92020-06-12 13:48:37 +090043 // Enables the datapath for a physical Device. This is never called for
44 // the ARC management device.
Garrick Evansb4eb3892019-11-13 12:07:07 +090045 virtual bool OnStartDevice(Device* device) = 0;
Hugo Benichiad1bdd92020-06-12 13:48:37 +090046 // Disables the datapath for a physical Device. This is never called for
47 // the ARC management device.
Garrick Evansb4eb3892019-11-13 12:07:07 +090048 virtual void OnStopDevice(Device* device) = 0;
Garrick Evansb4eb3892019-11-13 12:07:07 +090049
50 protected:
51 Impl() = default;
Garrick Evans2c263102019-07-26 16:07:18 +090052 };
53
Garrick Evansd90a3822019-11-12 17:53:08 +090054 // Encapsulates all ARC++ container-specific logic.
Garrick Evansb4eb3892019-11-13 12:07:07 +090055 class ContainerImpl : public Impl {
Garrick Evansd90a3822019-11-12 17:53:08 +090056 public:
Hugo Benichiad1bdd92020-06-12 13:48:37 +090057 ContainerImpl(Datapath* datapath, TrafficForwarder* forwarder);
Garrick Evansd90a3822019-11-12 17:53:08 +090058 ~ContainerImpl() = default;
59
Garrick Evans015b0d62020-02-07 09:06:38 +090060 uint32_t id() const override;
Garrick Evans38b25a42020-04-06 15:17:42 +090061 std::vector<const Device::Config*> GetDeviceConfigs() const override {
62 return {};
63 }
Garrick Evansb4eb3892019-11-13 12:07:07 +090064
Garrick Evans015b0d62020-02-07 09:06:38 +090065 bool Start(uint32_t pid) override;
66 void Stop(uint32_t pid) override;
67 bool IsStarted(uint32_t* pid = nullptr) const override;
Garrick Evansb4eb3892019-11-13 12:07:07 +090068 bool OnStartDevice(Device* device) override;
69 void OnStopDevice(Device* device) override;
Garrick Evansd90a3822019-11-12 17:53:08 +090070
71 private:
Garrick Evans015b0d62020-02-07 09:06:38 +090072 uint32_t pid_;
Garrick Evansd90a3822019-11-12 17:53:08 +090073 Datapath* datapath_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +090074 TrafficForwarder* forwarder_;
Garrick Evansd90a3822019-11-12 17:53:08 +090075
Garrick Evansd90a3822019-11-12 17:53:08 +090076 base::WeakPtrFactory<ContainerImpl> weak_factory_{this};
77 DISALLOW_COPY_AND_ASSIGN(ContainerImpl);
78 };
79
Garrick Evansb4eb3892019-11-13 12:07:07 +090080 // Encapsulates all ARC VM-specific logic.
81 class VmImpl : public Impl {
82 public:
Garrick Evans2961c7c2020-04-03 11:34:40 +090083 // |configs| is an optional list of device configurations that, if provided,
84 // will be used to pre-allocated and associate them, when necessary, to
85 // devices as they are added. The caller retains ownership of the pointers.
Hugo Benichiad1bdd92020-06-12 13:48:37 +090086 VmImpl(Datapath* datapath,
Garrick Evansf5862122020-03-16 09:13:45 +090087 TrafficForwarder* forwarder,
Garrick Evans2961c7c2020-04-03 11:34:40 +090088 const std::vector<Device::Config*>& configs);
Garrick Evansb4eb3892019-11-13 12:07:07 +090089 ~VmImpl() = default;
90
Garrick Evans015b0d62020-02-07 09:06:38 +090091 uint32_t id() const override;
Garrick Evans38b25a42020-04-06 15:17:42 +090092 std::vector<const Device::Config*> GetDeviceConfigs() const override;
Garrick Evansb4eb3892019-11-13 12:07:07 +090093
Garrick Evans015b0d62020-02-07 09:06:38 +090094 bool Start(uint32_t cid) override;
95 void Stop(uint32_t cid) override;
96 bool IsStarted(uint32_t* cid = nullptr) const override;
Garrick Evansb4eb3892019-11-13 12:07:07 +090097 bool OnStartDevice(Device* device) override;
98 void OnStopDevice(Device* device) override;
Garrick Evansb4eb3892019-11-13 12:07:07 +090099
100 private:
Garrick Evans015b0d62020-02-07 09:06:38 +0900101 uint32_t cid_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900102 Datapath* datapath_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900103 TrafficForwarder* forwarder_;
Garrick Evans2961c7c2020-04-03 11:34:40 +0900104 std::vector<Device::Config*> configs_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900105
106 DISALLOW_COPY_AND_ASSIGN(VmImpl);
107 };
108
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900109 enum class InterfaceType {
110 UNKNOWN,
111 ETHERNET,
112 WIFI,
113 CELL,
114 };
115
Garrick Evans69b85872020-02-04 11:40:26 +0900116 // All pointers are required and cannot be null, and are owned by the caller.
117 ArcService(ShillClient* shill_client,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900118 Datapath* datapath,
119 AddressManager* addr_mgr,
Garrick Evansf5862122020-03-16 09:13:45 +0900120 TrafficForwarder* forwarder,
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900121 GuestMessage::GuestType guest);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900122 ~ArcService();
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900123
Garrick Evans015b0d62020-02-07 09:06:38 +0900124 bool Start(uint32_t id);
125 void Stop(uint32_t id);
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900126
Garrick Evans38b25a42020-04-06 15:17:42 +0900127 // Returns a list of device configurations. This method only really is useful
128 // when ARCVM is running as it enables the caller to discover which
129 // configurations, if any, are currently associated to TAP devices.
130 std::vector<const Device::Config*> GetDeviceConfigs() const;
Garrick Evanse94b6de2020-02-20 09:19:13 +0900131
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900132 private:
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900133 // Callback from ShillClient, invoked whenever the device list changes.
134 // |devices_| will contain all devices currently connected to shill
135 // (e.g. "eth0", "wlan0", etc).
136 void OnDevicesChanged(const std::set<std::string>& added,
137 const std::set<std::string>& removed);
138
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900139 // Build and configure an ARC device for the interface |name| provided by
140 // Shill. The new device will be added to |devices_|. If an implementation is
141 // already running, the device will be started.
142 void AddDevice(const std::string& ifname);
143
144 // Deletes the ARC device; if an implementation is running, the device will be
145 // stopped first.
146 void RemoveDevice(const std::string& ifname);
147
148 // Starts a device by setting up the bridge and configuring some NAT rules,
149 // then invoking the implementation-specific start routine.
Garrick Evans54861622019-07-19 09:05:09 +0900150 void StartDevice(Device* device);
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900151
152 // Stops and cleans up any virtual interfaces and associated datapath.
Garrick Evans54861622019-07-19 09:05:09 +0900153 void StopDevice(Device* device);
154
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900155 // Creates device configurations for all available IPv4 subnets which will be
156 // assigned to devices as they are added.
157 void AllocateAddressConfigs();
158
159 // This function will temporarily remove existing devices, reallocate
160 // address configurations and re-add existing devices. This is necessary to
161 // properly handle the IPv4 addressing binding difference between ARC++ and
162 // ARCVM.
Garrick Evans2961c7c2020-04-03 11:34:40 +0900163 // Returns the list of all configurations ordered by type.
164 std::vector<Device::Config*> ReallocateAddressConfigs();
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900165
166 // Reserve a configuration for an interface.
167 std::unique_ptr<Device::Config> AcquireConfig(const std::string& ifname);
168
169 // Returns a configuration to the pool.
170 void ReleaseConfig(const std::string& ifname,
171 std::unique_ptr<Device::Config> config);
172
Garrick Evans69b85872020-02-04 11:40:26 +0900173 ShillClient* shill_client_;
Taoyu Li179dcc62019-10-17 11:21:08 +0900174 Datapath* datapath_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900175 AddressManager* addr_mgr_;
176 TrafficForwarder* forwarder_;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900177 GuestMessage::GuestType guest_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900178 std::unique_ptr<Impl> impl_;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900179 // A set of preallocated device configurations keyed by technology type and
180 // used for setting up ARCVM tap devices at VM booting time.
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900181 std::map<InterfaceType, std::deque<std::unique_ptr<Device::Config>>> configs_;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900182 // The ARC device configurations corresponding to the host physical devices,
183 // keyed by device interface name.
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900184 std::map<std::string, std::unique_ptr<Device>> devices_;
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900185 // The ARC management device used for legacy adb-over-tcp support and VPN
186 // forwarding.
187 std::unique_ptr<Device> arc_device_;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900188
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900189 FRIEND_TEST(ArcServiceTest, ContainerImpl_OnStartDevice);
190 FRIEND_TEST(ArcServiceTest, ContainerImpl_FailsToConfigureInterface);
191 FRIEND_TEST(ArcServiceTest, ContainerImpl_OnStopDevice);
192 FRIEND_TEST(ArcServiceTest, ContainerImpl_Start);
193 FRIEND_TEST(ArcServiceTest, ContainerImpl_FailsToCreateInterface);
194 FRIEND_TEST(ArcServiceTest, ContainerImpl_Stop);
195 FRIEND_TEST(ArcServiceTest, NotStarted_AddDevice);
196 FRIEND_TEST(ArcServiceTest, NotStarted_AddRemoveDevice);
197 FRIEND_TEST(ArcServiceTest, StableArcVmMacAddrs);
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900198 FRIEND_TEST(ArcServiceTest, StopDevice);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900199 FRIEND_TEST(ArcServiceTest, VerifyAddrConfigs);
200 FRIEND_TEST(ArcServiceTest, VerifyAddrOrder);
Hugo Benichiad1bdd92020-06-12 13:48:37 +0900201 FRIEND_TEST(ArcServiceTest, VmImpl_Start);
202 FRIEND_TEST(ArcServiceTest, VmImpl_StartDevice);
203 FRIEND_TEST(ArcServiceTest, VmImpl_StartMultipleDevices);
204 FRIEND_TEST(ArcServiceTest, VmImpl_Stop);
205 FRIEND_TEST(ArcServiceTest, VmImpl_StopDevice);
Garrick Evans54861622019-07-19 09:05:09 +0900206
207 base::WeakPtrFactory<ArcService> weak_factory_{this};
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900208 DISALLOW_COPY_AND_ASSIGN(ArcService);
209};
210
Garrick Evans3388a032020-03-24 11:25:55 +0900211} // namespace patchpanel
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900212
Garrick Evans3388a032020-03-24 11:25:55 +0900213#endif // PATCHPANEL_ARC_SERVICE_H_