blob: 802acbb50cbd8ae06605f0eca0b4ab9dffd7c481 [file] [log] [blame]
Chirantan Ekbote1977ea22017-12-08 18:57:03 -08001// Copyright 2017 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 Evans4b66f632019-01-24 15:09:16 +09005#include "arc/network/subnet_pool.h"
Chirantan Ekbote1977ea22017-12-08 18:57:03 -08006
Garrick Evans0dbd4182019-03-07 08:38:38 +09007#include <memory>
Stephen Barber47981a72018-01-25 18:45:14 -08008#include <string>
Chirantan Ekbote1977ea22017-12-08 18:57:03 -08009#include <utility>
10
11#include <base/bind.h>
12#include <base/logging.h>
13#include <base/memory/ptr_util.h>
14#include <base/strings/stringprintf.h>
15
16using std::string;
17
Garrick Evans4b66f632019-01-24 15:09:16 +090018namespace arc_networkd {
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080019namespace {
Garrick Evans0dbd4182019-03-07 08:38:38 +090020constexpr uint32_t kMaxSubnets = 32;
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080021} // namespace
22
Garrick Evans0dbd4182019-03-07 08:38:38 +090023// static
24std::unique_ptr<SubnetPool> SubnetPool::New(uint32_t base_addr,
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090025 uint32_t prefix_length,
Garrick Evans0dbd4182019-03-07 08:38:38 +090026 uint32_t num_subnets) {
27 if (num_subnets > kMaxSubnets) {
28 LOG(ERROR) << "Maximum subnets supported is " << kMaxSubnets << "; got "
29 << num_subnets;
30 return nullptr;
31 }
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090032 return base::WrapUnique(
33 new SubnetPool(base_addr, prefix_length, num_subnets));
Garrick Evans0dbd4182019-03-07 08:38:38 +090034}
35
36SubnetPool::SubnetPool(uint32_t base_addr,
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090037 uint32_t prefix_length,
Garrick Evans0dbd4182019-03-07 08:38:38 +090038 uint32_t num_subnets)
39 : base_addr_(base_addr),
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090040 prefix_length_(prefix_length),
Garrick Evans0dbd4182019-03-07 08:38:38 +090041 num_subnets_(num_subnets),
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090042 addr_per_index_(1ull << (kMaxSubnets - prefix_length)) {}
Garrick Evans0dbd4182019-03-07 08:38:38 +090043
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080044SubnetPool::~SubnetPool() {
Garrick Evans0dbd4182019-03-07 08:38:38 +090045 if (subnets_.any()) {
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080046 LOG(ERROR) << "SubnetPool destroyed with unreleased subnets";
47 }
48}
49
Garrick Evans0dbd4182019-03-07 08:38:38 +090050std::unique_ptr<Subnet> SubnetPool::Allocate() {
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080051 // Find the first un-allocated subnet.
Garrick Evans0dbd4182019-03-07 08:38:38 +090052 uint32_t index = 0;
53 while (index < num_subnets_ && subnets_.test(index)) {
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080054 ++index;
55 }
56
Garrick Evans0dbd4182019-03-07 08:38:38 +090057 if (index == num_subnets_) {
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080058 // All subnets are allocated.
59 return nullptr;
60 }
61
Garrick Evans0dbd4182019-03-07 08:38:38 +090062 subnets_.set(index);
63 return std::make_unique<Subnet>(
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090064 base_addr_ + (index * addr_per_index_), prefix_length_,
Garrick Evans0dbd4182019-03-07 08:38:38 +090065 base::Bind(&SubnetPool::Release, weak_ptr_factory_.GetWeakPtr(), index));
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080066}
67
Garrick Evans0dbd4182019-03-07 08:38:38 +090068void SubnetPool::Release(uint32_t index) {
69 DCHECK(subnets_.test(index));
70 subnets_.reset(index);
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080071}
72
Garrick Evans4b66f632019-01-24 15:09:16 +090073} // namespace arc_networkd