| // 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. |
| |
| #ifndef PATCHPANEL_DEVICE_H_ |
| #define PATCHPANEL_DEVICE_H_ |
| |
| #include <linux/in6.h> |
| #include <netinet/in.h> |
| #include <sys/socket.h> |
| #include <unistd.h> |
| |
| #include <map> |
| #include <memory> |
| #include <ostream> |
| #include <string> |
| |
| #include <base/bind.h> |
| #include <base/memory/weak_ptr.h> |
| #include <gtest/gtest_prod.h> // for FRIEND_TEST |
| |
| #include "patchpanel/guest_type.h" |
| #include "patchpanel/ipc.pb.h" |
| #include "patchpanel/mac_address_generator.h" |
| #include "patchpanel/subnet.h" |
| |
| namespace patchpanel { |
| |
| // Represents a virtual network interface created and managed by patchpanel with |
| // its configuration. A Device can be associated with: |
| // - ARC container: a pair of virtual ethernet interfaces setup across the |
| // host / ARC namespace boundary, plus a software bridge to which the host-side |
| // veth interface is attached. |
| // - ARCVM: a TAP device plus a software bridge to which the TAP device is |
| // attached. |
| // - Termina VMs, plugin VMs: a TAP device, with no software bridge. |
| // Connected namespaces have currently no Device representation. |
| // A Device always is always associated with a unique IPv4 subnet statically |
| // assigned by AddressManager based on the type of guest. |
| class Device { |
| public: |
| enum class ChangeEvent { |
| ADDED, |
| REMOVED, |
| }; |
| using ChangeEventHandler = base::RepeatingCallback<void( |
| const Device&, ChangeEvent, GuestMessage::GuestType)>; |
| |
| class Config { |
| public: |
| Config(const MacAddress& mac_addr, |
| std::unique_ptr<Subnet> ipv4_subnet, |
| std::unique_ptr<SubnetAddress> host_ipv4_addr, |
| std::unique_ptr<SubnetAddress> guest_ipv4_addr, |
| std::unique_ptr<Subnet> lxd_ipv4_subnet = nullptr); |
| Config(const Config&) = delete; |
| Config& operator=(const Config&) = delete; |
| |
| ~Config() = default; |
| |
| MacAddress mac_addr() const { return mac_addr_; } |
| uint32_t host_ipv4_addr() const { return host_ipv4_addr_->Address(); } |
| uint32_t guest_ipv4_addr() const { return guest_ipv4_addr_->Address(); } |
| |
| const SubnetAddress* const host_ipv4_subnet_addr() const { |
| return host_ipv4_addr_.get(); |
| } |
| const SubnetAddress* const guest_ipv4_subnet_addr() const { |
| return guest_ipv4_addr_.get(); |
| } |
| |
| const Subnet* const ipv4_subnet() const { return ipv4_subnet_.get(); } |
| |
| const Subnet* const lxd_ipv4_subnet() const { |
| return lxd_ipv4_subnet_.get(); |
| } |
| |
| void set_tap_ifname(const std::string& tap); |
| const std::string& tap_ifname() const; |
| |
| private: |
| // A random MAC address assigned to the Device for the guest facing |
| // interface. |
| MacAddress mac_addr_; |
| // The static IPv4 subnet allocated for this Device for the host and guest |
| // facing interfaces. |
| std::unique_ptr<Subnet> ipv4_subnet_; |
| // The address allocated from |ipv4_subnet| for use by the host-side |
| // interface associated with this Device. This is also used as the next hop |
| // for the guest default route on the virtual network associated with that |
| // Device. |
| std::unique_ptr<SubnetAddress> host_ipv4_addr_; |
| // The address allocated from |ipv4_subnet| for use by the guest-side |
| // interface associated with this Device, if applicable. |
| std::unique_ptr<SubnetAddress> guest_ipv4_addr_; |
| // If applicable, an additional IPv4 subnet allocated for this Device for |
| // guests like Crostini to use for assigning addresses to containers running |
| // within the VM. |
| std::unique_ptr<Subnet> lxd_ipv4_subnet_; |
| // For VM guest, the interface name of the TAP device currently associated |
| // with the configuration. |
| std::string tap_; |
| }; |
| |
| // |type| the type of guest associated with this virtual device created by |
| // patchpanel. |phys_ifname| corresponds either to the physical interface |
| // provided by shill or a placeholder for a guest-specific control interface |
| // (e.g. arc0). |host_ifname| identifies the name of the virtual (bridge) |
| // interface. |guest_ifname|, if specified, identifies the name of the |
| // interface used inside the guest. |
| Device(GuestType type, |
| const std::string& phys_ifname, |
| const std::string& host_ifname, |
| const std::string& guest_ifname, |
| std::unique_ptr<Config> config); |
| Device(const Device&) = delete; |
| Device& operator=(const Device&) = delete; |
| |
| ~Device() = default; |
| |
| GuestType type() const { return type_; } |
| const std::string& phys_ifname() const { return phys_ifname_; } |
| const std::string& host_ifname() const { return host_ifname_; } |
| const std::string& guest_ifname() const { return guest_ifname_; } |
| Config& config() const; |
| std::unique_ptr<Config> release_config(); |
| |
| private: |
| GuestType type_; |
| std::string phys_ifname_; |
| std::string host_ifname_; |
| std::string guest_ifname_; |
| std::unique_ptr<Config> config_; |
| |
| FRIEND_TEST(DeviceTest, DisableLegacyAndroidDeviceSendsTwoMessages); |
| |
| base::WeakPtrFactory<Device> weak_factory_{this}; |
| }; |
| |
| std::ostream& operator<<(std::ostream& stream, const Device& device); |
| |
| } // namespace patchpanel |
| |
| #endif // PATCHPANEL_DEVICE_H_ |