blob: 176b52ba0649f6e5bbe4be521432ccee9b8b006d [file] [log] [blame]
// Copyright 2017 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/subnet_pool.h"
#include <string>
#include <utility>
#include <base/bind.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/strings/stringprintf.h>
using std::string;
namespace arc_networkd {
namespace {
// The 100.115.92.0/24 subnet is reserved and not publicly routable. This subnet
// is then sliced into the following IP pools:
// +-------+----------------+-----------+------------+----------------------+
// | 0-23 | 24-127 | 128-143 | 144-191 | 192-255 |
// +-------+----------------+-----------+------------+----------------------+
// | ARC++ | VM pool (/30) | Plugin VM | Future use | Container pool (/28) |
// +-------+----------------+-----------+------------+----------------------+
// Within each /30 subnet:
// addr 0 - network identifier
// addr 1 - gateway (host) address
// addr 2 - VM (guest) address
// addr 3 - broadcast address
constexpr size_t kContainerAddressesPerIndex = 16;
constexpr size_t kContainerBaseAddress = 0x64735cc0; // 100.115.92.192
constexpr size_t kVmAddressesPerIndex = 4;
constexpr size_t kVmBaseAddress = 0x64735c18; // 100.115.92.24
constexpr size_t kContainerSubnetPrefix = 28;
constexpr size_t kVmSubnetPrefix = 30;
} // namespace
SubnetPool::~SubnetPool() {
if (vm_subnets_.any() || container_subnets_.any()) {
LOG(ERROR) << "SubnetPool destroyed with unreleased subnets";
}
}
std::unique_ptr<Subnet> SubnetPool::AllocateVM() {
// Find the first un-allocated subnet.
size_t index = 0;
while (index < vm_subnets_.size() && vm_subnets_.test(index)) {
++index;
}
if (index == vm_subnets_.size()) {
// All subnets are allocated.
return nullptr;
}
vm_subnets_.set(index);
return base::WrapUnique(new Subnet(
kVmBaseAddress + (index * kVmAddressesPerIndex), kVmSubnetPrefix,
base::Bind(&SubnetPool::ReleaseVM, weak_ptr_factory_.GetWeakPtr(),
index)));
}
std::unique_ptr<Subnet> SubnetPool::AllocateContainer() {
// Find the first un-allocated subnet.
size_t index = 0;
while (index < container_subnets_.size() && container_subnets_.test(index)) {
++index;
}
if (index == container_subnets_.size()) {
// All subnets are allocated.
return nullptr;
}
container_subnets_.set(index);
return base::WrapUnique(
new Subnet(kContainerBaseAddress + (index * kContainerAddressesPerIndex),
kContainerSubnetPrefix,
base::Bind(&SubnetPool::ReleaseContainer,
weak_ptr_factory_.GetWeakPtr(), index)));
}
void SubnetPool::ReleaseVM(size_t index) {
DCHECK(vm_subnets_.test(index));
vm_subnets_.reset(index);
}
void SubnetPool::ReleaseContainer(size_t index) {
DCHECK(container_subnets_.test(index));
container_subnets_.reset(index);
}
} // namespace arc_networkd