blob: fc0e5a8683602a361c107bca3a62be87216dbd85 [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
Hugo Benichi6c63ae22019-05-29 11:19:15 +09007#include <arpa/inet.h>
8
Garrick Evans0dbd4182019-03-07 08:38:38 +09009#include <memory>
Stephen Barber47981a72018-01-25 18:45:14 -080010#include <string>
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080011#include <utility>
12
13#include <base/bind.h>
14#include <base/logging.h>
15#include <base/memory/ptr_util.h>
16#include <base/strings/stringprintf.h>
17
18using std::string;
19
Garrick Evans4b66f632019-01-24 15:09:16 +090020namespace arc_networkd {
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080021namespace {
Garrick Evans0dbd4182019-03-07 08:38:38 +090022constexpr uint32_t kMaxSubnets = 32;
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080023} // namespace
24
Garrick Evans0dbd4182019-03-07 08:38:38 +090025// static
26std::unique_ptr<SubnetPool> SubnetPool::New(uint32_t base_addr,
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090027 uint32_t prefix_length,
Garrick Evans0dbd4182019-03-07 08:38:38 +090028 uint32_t num_subnets) {
29 if (num_subnets > kMaxSubnets) {
30 LOG(ERROR) << "Maximum subnets supported is " << kMaxSubnets << "; got "
31 << num_subnets;
32 return nullptr;
33 }
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090034 return base::WrapUnique(
35 new SubnetPool(base_addr, prefix_length, num_subnets));
Garrick Evans0dbd4182019-03-07 08:38:38 +090036}
37
38SubnetPool::SubnetPool(uint32_t base_addr,
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090039 uint32_t prefix_length,
Garrick Evans0dbd4182019-03-07 08:38:38 +090040 uint32_t num_subnets)
41 : base_addr_(base_addr),
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090042 prefix_length_(prefix_length),
Garrick Evans0dbd4182019-03-07 08:38:38 +090043 num_subnets_(num_subnets),
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090044 addr_per_index_(1ull << (kMaxSubnets - prefix_length)) {}
Garrick Evans0dbd4182019-03-07 08:38:38 +090045
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080046SubnetPool::~SubnetPool() {
Garrick Evans0dbd4182019-03-07 08:38:38 +090047 if (subnets_.any()) {
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080048 LOG(ERROR) << "SubnetPool destroyed with unreleased subnets";
49 }
50}
51
Garrick Evans43b4e2d2019-12-11 13:43:08 +090052std::unique_ptr<Subnet> SubnetPool::Allocate(int index) {
53 if (index < 0) {
54 index = 0;
55 // Find the first un-allocated subnet.
56 while (index < num_subnets_ && subnets_.test(index)) {
57 ++index;
58 }
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080059 }
60
Garrick Evans43b4e2d2019-12-11 13:43:08 +090061 if (index >= num_subnets_ || subnets_.test(index)) {
62 // No applicable subnet available.
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080063 return nullptr;
64 }
65
Garrick Evans0dbd4182019-03-07 08:38:38 +090066 subnets_.set(index);
Hugo Benichi6c63ae22019-05-29 11:19:15 +090067 uint32_t subnet_addr = htonl(ntohl(base_addr_) + index * addr_per_index_);
Garrick Evans0dbd4182019-03-07 08:38:38 +090068 return std::make_unique<Subnet>(
Hugo Benichi6c63ae22019-05-29 11:19:15 +090069 subnet_addr, prefix_length_,
Garrick Evans0dbd4182019-03-07 08:38:38 +090070 base::Bind(&SubnetPool::Release, weak_ptr_factory_.GetWeakPtr(), index));
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080071}
72
Garrick Evans0dbd4182019-03-07 08:38:38 +090073void SubnetPool::Release(uint32_t index) {
74 DCHECK(subnets_.test(index));
75 subnets_.reset(index);
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080076}
77
Garrick Evans4b66f632019-01-24 15:09:16 +090078} // namespace arc_networkd