blob: ab1c781b95ffb4a3a05c76fc3221bdbf47ef6591 [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
33 virtual GuestMessage::GuestType guest() const = 0;
Garrick Evans015b0d62020-02-07 09:06:38 +090034 virtual uint32_t id() const = 0;
Garrick Evansb4eb3892019-11-13 12:07:07 +090035
Garrick Evans38b25a42020-04-06 15:17:42 +090036 // Returns the list of device configurations that were provided to the
37 // implementation at creation time plus the one for the ARC device, if
38 // applicable. Currently only ARCVM supports this method.
39 virtual std::vector<const Device::Config*> GetDeviceConfigs() const = 0;
40
Garrick Evans015b0d62020-02-07 09:06:38 +090041 virtual bool Start(uint32_t id) = 0;
42 virtual void Stop(uint32_t id) = 0;
43 virtual bool IsStarted(uint32_t* id = nullptr) const = 0;
Garrick Evansb4eb3892019-11-13 12:07:07 +090044 virtual bool OnStartDevice(Device* device) = 0;
45 virtual void OnStopDevice(Device* device) = 0;
Garrick Evans1b1f67c2020-02-04 16:21:25 +090046 virtual void OnDefaultInterfaceChanged(const std::string& new_ifname,
47 const std::string& prev_ifname) = 0;
Garrick Evansb4eb3892019-11-13 12:07:07 +090048
49 protected:
50 Impl() = default;
Garrick Evanse94b6de2020-02-20 09:19:13 +090051
52 // For now each implementation manages its own ARC device since ARCVM is
53 // still single-networked.
54 std::unique_ptr<Device> arc_device_;
Garrick Evans2c263102019-07-26 16:07:18 +090055 };
56
Garrick Evansd90a3822019-11-12 17:53:08 +090057 // Encapsulates all ARC++ container-specific logic.
Garrick Evansb4eb3892019-11-13 12:07:07 +090058 class ContainerImpl : public Impl {
Garrick Evansd90a3822019-11-12 17:53:08 +090059 public:
Garrick Evans2e5c9ab2020-03-05 14:33:58 +090060 ContainerImpl(Datapath* datapath,
61 AddressManager* addr_mgr,
62 TrafficForwarder* forwarder,
Garrick Evansd90a3822019-11-12 17:53:08 +090063 GuestMessage::GuestType guest);
64 ~ContainerImpl() = default;
65
Garrick Evansb4eb3892019-11-13 12:07:07 +090066 GuestMessage::GuestType guest() const override;
Garrick Evans015b0d62020-02-07 09:06:38 +090067 uint32_t id() const override;
Garrick Evans38b25a42020-04-06 15:17:42 +090068 std::vector<const Device::Config*> GetDeviceConfigs() const override {
69 return {};
70 }
Garrick Evansb4eb3892019-11-13 12:07:07 +090071
Garrick Evans015b0d62020-02-07 09:06:38 +090072 bool Start(uint32_t pid) override;
73 void Stop(uint32_t pid) override;
74 bool IsStarted(uint32_t* pid = nullptr) const override;
Garrick Evansb4eb3892019-11-13 12:07:07 +090075 bool OnStartDevice(Device* device) override;
76 void OnStopDevice(Device* device) override;
Garrick Evans1b1f67c2020-02-04 16:21:25 +090077 void OnDefaultInterfaceChanged(const std::string& new_ifname,
78 const std::string& prev_ifname) override;
Garrick Evansd90a3822019-11-12 17:53:08 +090079
80 private:
Garrick Evans015b0d62020-02-07 09:06:38 +090081 uint32_t pid_;
Garrick Evansd90a3822019-11-12 17:53:08 +090082 Datapath* datapath_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +090083 AddressManager* addr_mgr_;
84 TrafficForwarder* forwarder_;
Garrick Evansd90a3822019-11-12 17:53:08 +090085 GuestMessage::GuestType guest_;
86
Garrick Evansd90a3822019-11-12 17:53:08 +090087 base::WeakPtrFactory<ContainerImpl> weak_factory_{this};
88 DISALLOW_COPY_AND_ASSIGN(ContainerImpl);
89 };
90
Garrick Evansb4eb3892019-11-13 12:07:07 +090091 // Encapsulates all ARC VM-specific logic.
92 class VmImpl : public Impl {
93 public:
Garrick Evans2961c7c2020-04-03 11:34:40 +090094 // |configs| is an optional list of device configurations that, if provided,
95 // will be used to pre-allocated and associate them, when necessary, to
96 // devices as they are added. The caller retains ownership of the pointers.
Garrick Evansbbdf4b42020-03-05 12:59:06 +090097 VmImpl(ShillClient* shill_client,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +090098 Datapath* datapath,
99 AddressManager* addr_mgr,
Garrick Evansf5862122020-03-16 09:13:45 +0900100 TrafficForwarder* forwarder,
Garrick Evans2961c7c2020-04-03 11:34:40 +0900101 const std::vector<Device::Config*>& configs);
Garrick Evansb4eb3892019-11-13 12:07:07 +0900102 ~VmImpl() = default;
103
104 GuestMessage::GuestType guest() const override;
Garrick Evans015b0d62020-02-07 09:06:38 +0900105 uint32_t id() const override;
Garrick Evans38b25a42020-04-06 15:17:42 +0900106 std::vector<const Device::Config*> GetDeviceConfigs() const override;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900107
Garrick Evans015b0d62020-02-07 09:06:38 +0900108 bool Start(uint32_t cid) override;
109 void Stop(uint32_t cid) override;
110 bool IsStarted(uint32_t* cid = nullptr) const override;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900111 bool OnStartDevice(Device* device) override;
112 void OnStopDevice(Device* device) override;
Garrick Evans1b1f67c2020-02-04 16:21:25 +0900113 void OnDefaultInterfaceChanged(const std::string& new_ifname,
114 const std::string& prev_ifname) override;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900115
116 private:
Garrick Evansf5862122020-03-16 09:13:45 +0900117 // TODO(garrick): Remove once ARCVM P is gone.
118 bool OnStartArcPDevice();
119 void OnStopArcPDevice();
120
Garrick Evans2961c7c2020-04-03 11:34:40 +0900121 bool IsMultinetEnabled() const;
122
Garrick Evans015b0d62020-02-07 09:06:38 +0900123 uint32_t cid_;
Garrick Evansbbdf4b42020-03-05 12:59:06 +0900124 const ShillClient* const shill_client_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900125 Datapath* datapath_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900126 AddressManager* addr_mgr_;
127 TrafficForwarder* forwarder_;
Garrick Evans2961c7c2020-04-03 11:34:40 +0900128 std::vector<Device::Config*> configs_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900129
130 DISALLOW_COPY_AND_ASSIGN(VmImpl);
131 };
132
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900133 enum class InterfaceType {
134 UNKNOWN,
135 ETHERNET,
136 WIFI,
137 CELL,
138 };
139
Garrick Evans69b85872020-02-04 11:40:26 +0900140 // All pointers are required and cannot be null, and are owned by the caller.
141 ArcService(ShillClient* shill_client,
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900142 Datapath* datapath,
143 AddressManager* addr_mgr,
Garrick Evansf5862122020-03-16 09:13:45 +0900144 TrafficForwarder* forwarder,
145 bool enable_arcvm_multinet);
Garrick Evansf29f5a32019-12-06 11:34:25 +0900146 ~ArcService();
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900147
Garrick Evans015b0d62020-02-07 09:06:38 +0900148 bool Start(uint32_t id);
149 void Stop(uint32_t id);
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900150
Garrick Evans38b25a42020-04-06 15:17:42 +0900151 // Returns a list of device configurations. This method only really is useful
152 // when ARCVM is running as it enables the caller to discover which
153 // configurations, if any, are currently associated to TAP devices.
154 std::vector<const Device::Config*> GetDeviceConfigs() const;
Garrick Evanse94b6de2020-02-20 09:19:13 +0900155
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900156 private:
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900157 // Callback from ShillClient, invoked whenever the device list changes.
158 // |devices_| will contain all devices currently connected to shill
159 // (e.g. "eth0", "wlan0", etc).
160 void OnDevicesChanged(const std::set<std::string>& added,
161 const std::set<std::string>& removed);
162
163 // Callback from ShillClient, invoked whenever the default network
164 // interface changes or goes away.
165 void OnDefaultInterfaceChanged(const std::string& new_ifname,
166 const std::string& prev_ifname);
167
168 // Build and configure an ARC device for the interface |name| provided by
169 // Shill. The new device will be added to |devices_|. If an implementation is
170 // already running, the device will be started.
171 void AddDevice(const std::string& ifname);
172
173 // Deletes the ARC device; if an implementation is running, the device will be
174 // stopped first.
175 void RemoveDevice(const std::string& ifname);
176
177 // Starts a device by setting up the bridge and configuring some NAT rules,
178 // then invoking the implementation-specific start routine.
Garrick Evans54861622019-07-19 09:05:09 +0900179 void StartDevice(Device* device);
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900180
181 // Stops and cleans up any virtual interfaces and associated datapath.
Garrick Evans54861622019-07-19 09:05:09 +0900182 void StopDevice(Device* device);
183
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900184 // Creates device configurations for all available IPv4 subnets which will be
185 // assigned to devices as they are added.
186 void AllocateAddressConfigs();
187
188 // This function will temporarily remove existing devices, reallocate
189 // address configurations and re-add existing devices. This is necessary to
190 // properly handle the IPv4 addressing binding difference between ARC++ and
191 // ARCVM.
Garrick Evans2961c7c2020-04-03 11:34:40 +0900192 // Returns the list of all configurations ordered by type.
193 std::vector<Device::Config*> ReallocateAddressConfigs();
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900194
195 // Reserve a configuration for an interface.
196 std::unique_ptr<Device::Config> AcquireConfig(const std::string& ifname);
197
198 // Returns a configuration to the pool.
199 void ReleaseConfig(const std::string& ifname,
200 std::unique_ptr<Device::Config> config);
201
Garrick Evans69b85872020-02-04 11:40:26 +0900202 ShillClient* shill_client_;
Taoyu Li179dcc62019-10-17 11:21:08 +0900203 Datapath* datapath_;
Garrick Evans2e5c9ab2020-03-05 14:33:58 +0900204 AddressManager* addr_mgr_;
205 TrafficForwarder* forwarder_;
Garrick Evansf5862122020-03-16 09:13:45 +0900206 bool enable_arcvm_multinet_;
Garrick Evansb4eb3892019-11-13 12:07:07 +0900207 std::unique_ptr<Impl> impl_;
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900208 std::map<InterfaceType, std::deque<std::unique_ptr<Device::Config>>> configs_;
Garrick Evans6e4eb3b2020-03-09 07:18:31 +0900209 std::map<std::string, std::unique_ptr<Device>> devices_;
210
211 FRIEND_TEST(ArcServiceTest, StartDevice);
212 FRIEND_TEST(ArcServiceTest, StopDevice);
Garrick Evans86c7d9c2020-03-17 09:25:48 +0900213 FRIEND_TEST(ArcServiceTest, VerifyAddrConfigs);
214 FRIEND_TEST(ArcServiceTest, VerifyAddrOrder);
Garrick Evans54861622019-07-19 09:05:09 +0900215
216 base::WeakPtrFactory<ArcService> weak_factory_{this};
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900217 DISALLOW_COPY_AND_ASSIGN(ArcService);
218};
219
Garrick Evansf29f5a32019-12-06 11:34:25 +0900220namespace test {
221extern GuestMessage::GuestType guest;
222} // namespace test
223
Garrick Evans3388a032020-03-24 11:25:55 +0900224} // namespace patchpanel
Garrick Evans5d55f5e2019-07-17 15:28:10 +0900225
Garrick Evans3388a032020-03-24 11:25:55 +0900226#endif // PATCHPANEL_ARC_SERVICE_H_