blob: a6d2a7885e785c47305f356f6044378918f60cdf [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 -080021
Garrick Evans0dbd4182019-03-07 08:38:38 +090022// static
23std::unique_ptr<SubnetPool> SubnetPool::New(uint32_t base_addr,
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090024 uint32_t prefix_length,
Garrick Evans0dbd4182019-03-07 08:38:38 +090025 uint32_t num_subnets) {
26 if (num_subnets > kMaxSubnets) {
27 LOG(ERROR) << "Maximum subnets supported is " << kMaxSubnets << "; got "
28 << num_subnets;
29 return nullptr;
30 }
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090031 return base::WrapUnique(
32 new SubnetPool(base_addr, prefix_length, num_subnets));
Garrick Evans0dbd4182019-03-07 08:38:38 +090033}
34
35SubnetPool::SubnetPool(uint32_t base_addr,
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090036 uint32_t prefix_length,
Garrick Evans0dbd4182019-03-07 08:38:38 +090037 uint32_t num_subnets)
38 : base_addr_(base_addr),
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090039 prefix_length_(prefix_length),
Garrick Evans0dbd4182019-03-07 08:38:38 +090040 num_subnets_(num_subnets),
Garrick Evans53a2a982020-02-05 10:53:35 +090041 addr_per_index_(1ull << (kMaxSubnets - prefix_length)) {
42 subnets_.set(0); // unused.
43}
Garrick Evans0dbd4182019-03-07 08:38:38 +090044
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080045SubnetPool::~SubnetPool() {
Garrick Evans53a2a982020-02-05 10:53:35 +090046 subnets_.reset(0);
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 Evans53a2a982020-02-05 10:53:35 +090052std::unique_ptr<Subnet> SubnetPool::Allocate(uint32_t index) {
53 if (index == 0) {
54 while (index <= num_subnets_ && subnets_.test(index)) {
Garrick Evans43b4e2d2019-12-11 13:43:08 +090055 ++index;
56 }
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080057 }
58
Garrick Evans53a2a982020-02-05 10:53:35 +090059 if (index > num_subnets_) {
60 LOG(ERROR) << "Desired index (" << index << ") execeeds number of"
61 << " available subnets (" << num_subnets_ << ")";
62 return nullptr;
63 }
64 if (subnets_.test(index)) {
65 LOG(WARNING) << "Subnet at index (" << index << ") is unavailable";
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080066 return nullptr;
67 }
68
Garrick Evans0dbd4182019-03-07 08:38:38 +090069 subnets_.set(index);
Garrick Evans53a2a982020-02-05 10:53:35 +090070 uint32_t subnet_addr =
71 htonl(ntohl(base_addr_) + (index - 1) * addr_per_index_);
Garrick Evans0dbd4182019-03-07 08:38:38 +090072 return std::make_unique<Subnet>(
Hugo Benichi6c63ae22019-05-29 11:19:15 +090073 subnet_addr, prefix_length_,
Garrick Evans0dbd4182019-03-07 08:38:38 +090074 base::Bind(&SubnetPool::Release, weak_ptr_factory_.GetWeakPtr(), index));
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080075}
76
Garrick Evans0dbd4182019-03-07 08:38:38 +090077void SubnetPool::Release(uint32_t index) {
Garrick Evans53a2a982020-02-05 10:53:35 +090078 if (index == 0) {
79 LOG(DFATAL) << "Invalid index value: 0";
80 return;
81 }
Garrick Evans0dbd4182019-03-07 08:38:38 +090082 DCHECK(subnets_.test(index));
83 subnets_.reset(index);
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080084}
85
Garrick Evans4b66f632019-01-24 15:09:16 +090086} // namespace arc_networkd