blob: f0a761d31d1cdd2ccdc2a6ad5d8cd9768b023e83 [file] [log] [blame]
Hugo Benichi2ac4d072019-05-28 14:51:23 +09001// Copyright 2018 The Chromium OS Authors. All rights reserved.
Chirantan Ekbote1977ea22017-12-08 18:57:03 -08002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stephen Barber47981a72018-01-25 18:45:14 -08005#include <arpa/inet.h>
Chirantan Ekbote1977ea22017-12-08 18:57:03 -08006#include <stdint.h>
7
8#include <algorithm>
9#include <deque>
10#include <memory>
Zhizhou Yangdfddb862019-08-06 11:00:29 -070011#include <random>
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080012#include <string>
13#include <utility>
14
15#include <base/rand_util.h>
16#include <base/strings/stringprintf.h>
17#include <gtest/gtest.h>
18
Garrick Evans3388a032020-03-24 11:25:55 +090019#include "patchpanel/net_util.h"
20#include "patchpanel/subnet.h"
21#include "patchpanel/subnet_pool.h"
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080022
23using std::string;
24
Garrick Evans3388a032020-03-24 11:25:55 +090025namespace patchpanel {
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080026namespace {
27
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080028// The maximum number of subnets that can be allocated at a given time.
Hugo Benichi6c63ae22019-05-29 11:19:15 +090029constexpr uint32_t kBaseAddress = Ipv4Addr(44, 55, 66, 77);
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090030constexpr uint32_t kPrefixLength = 30;
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080031
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080032} // namespace
33
Garrick Evans0dbd4182019-03-07 08:38:38 +090034// Tests cannot create a pool with more than 32 supported subnets.
35TEST(SubnetPool, MaxSubnets) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090036 auto pool = SubnetPool::New(kBaseAddress, kPrefixLength, kMaxSubnets + 1);
Garrick Evans0dbd4182019-03-07 08:38:38 +090037 EXPECT_TRUE(pool == nullptr);
38}
39
40// Tests that the SubnetPool does not allocate more than max subnets at a time.
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080041TEST(SubnetPool, AllocationRange) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090042 auto pool = SubnetPool::New(kBaseAddress, kPrefixLength, kMaxSubnets);
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080043
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070044 std::deque<std::unique_ptr<Subnet>> subnets;
Stephen Barber41955312019-01-14 16:37:40 -080045 for (size_t i = 0; i < kMaxSubnets; ++i) {
Garrick Evans0dbd4182019-03-07 08:38:38 +090046 auto subnet = pool->Allocate();
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080047 ASSERT_TRUE(subnet);
48
49 subnets.emplace_back(std::move(subnet));
50 }
Garrick Evans53a2a982020-02-05 10:53:35 +090051 EXPECT_EQ(subnets.size(), kMaxSubnets);
Garrick Evans0dbd4182019-03-07 08:38:38 +090052 EXPECT_FALSE(pool->Allocate());
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080053}
54
55// Tests that subnets are properly released and reused.
56TEST(SubnetPool, Release) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090057 auto pool = SubnetPool::New(kBaseAddress, kPrefixLength, kMaxSubnets);
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080058
59 // First allocate all the subnets.
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070060 std::deque<std::unique_ptr<Subnet>> subnets;
Stephen Barber41955312019-01-14 16:37:40 -080061 for (size_t i = 0; i < kMaxSubnets; ++i) {
Garrick Evans0dbd4182019-03-07 08:38:38 +090062 auto subnet = pool->Allocate();
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080063 ASSERT_TRUE(subnet);
64
65 subnets.emplace_back(std::move(subnet));
66 }
Garrick Evans0dbd4182019-03-07 08:38:38 +090067 ASSERT_FALSE(pool->Allocate());
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080068
69 // Now shuffle the elements.
Zhizhou Yangdfddb862019-08-06 11:00:29 -070070 std::shuffle(subnets.begin(), subnets.end(),
71 std::mt19937(base::RandUint64()));
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080072
73 // Pop off the first element.
74 auto subnet = std::move(subnets.front());
75 subnets.pop_front();
76
77 // Store the gateway and address for testing later.
Stephen Barber47981a72018-01-25 18:45:14 -080078 uint32_t gateway = subnet->AddressAtOffset(0);
79 uint32_t address = subnet->AddressAtOffset(1);
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080080
81 // Release the subnet.
82 subnet.reset();
83
84 // Get a new subnet.
Garrick Evans0dbd4182019-03-07 08:38:38 +090085 subnet = pool->Allocate();
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080086 ASSERT_TRUE(subnet);
87
Stephen Barber47981a72018-01-25 18:45:14 -080088 EXPECT_EQ(gateway, subnet->AddressAtOffset(0));
89 EXPECT_EQ(address, subnet->AddressAtOffset(1));
Chirantan Ekbote1977ea22017-12-08 18:57:03 -080090}
91
Garrick Evans43b4e2d2019-12-11 13:43:08 +090092TEST(SubnetPool, Index) {
93 auto pool = SubnetPool::New(kBaseAddress, kPrefixLength, kMaxSubnets);
Garrick Evans53a2a982020-02-05 10:53:35 +090094 auto subnet = pool->Allocate(1);
Garrick Evans43b4e2d2019-12-11 13:43:08 +090095 ASSERT_TRUE(subnet);
Garrick Evans53a2a982020-02-05 10:53:35 +090096 EXPECT_FALSE(pool->Allocate(1));
97 EXPECT_TRUE(pool->Allocate(0));
98 EXPECT_TRUE(pool->Allocate());
99 EXPECT_TRUE(pool->Allocate(2));
100 EXPECT_TRUE(pool->Allocate(kMaxSubnets));
Garrick Evans43b4e2d2019-12-11 13:43:08 +0900101 subnet.reset();
Garrick Evans53a2a982020-02-05 10:53:35 +0900102 EXPECT_TRUE(pool->Allocate(1));
103 EXPECT_FALSE(pool->Allocate(kMaxSubnets + 1));
Garrick Evans43b4e2d2019-12-11 13:43:08 +0900104}
105
Garrick Evans3388a032020-03-24 11:25:55 +0900106} // namespace patchpanel