Hugo Benichi | 2ac4d07 | 2019-05-28 14:51:23 +0900 | [diff] [blame] | 1 | // Copyright 2018 The Chromium OS Authors. All rights reserved. |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Stephen Barber | 47981a7 | 2018-01-25 18:45:14 -0800 | [diff] [blame] | 5 | #include <arpa/inet.h> |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 6 | #include <stdint.h> |
| 7 | |
| 8 | #include <algorithm> |
| 9 | #include <deque> |
| 10 | #include <memory> |
Zhizhou Yang | dfddb86 | 2019-08-06 11:00:29 -0700 | [diff] [blame] | 11 | #include <random> |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 12 | #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 Evans | 3388a03 | 2020-03-24 11:25:55 +0900 | [diff] [blame^] | 19 | #include "patchpanel/net_util.h" |
| 20 | #include "patchpanel/subnet.h" |
| 21 | #include "patchpanel/subnet_pool.h" |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 22 | |
| 23 | using std::string; |
| 24 | |
Garrick Evans | 3388a03 | 2020-03-24 11:25:55 +0900 | [diff] [blame^] | 25 | namespace patchpanel { |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 26 | namespace { |
| 27 | |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 28 | // The maximum number of subnets that can be allocated at a given time. |
Hugo Benichi | 6c63ae2 | 2019-05-29 11:19:15 +0900 | [diff] [blame] | 29 | constexpr uint32_t kBaseAddress = Ipv4Addr(44, 55, 66, 77); |
Hugo Benichi | bd8ec4d | 2019-05-28 12:52:49 +0900 | [diff] [blame] | 30 | constexpr uint32_t kPrefixLength = 30; |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 31 | |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 32 | } // namespace |
| 33 | |
Garrick Evans | 0dbd418 | 2019-03-07 08:38:38 +0900 | [diff] [blame] | 34 | // Tests cannot create a pool with more than 32 supported subnets. |
| 35 | TEST(SubnetPool, MaxSubnets) { |
Hugo Benichi | bd8ec4d | 2019-05-28 12:52:49 +0900 | [diff] [blame] | 36 | auto pool = SubnetPool::New(kBaseAddress, kPrefixLength, kMaxSubnets + 1); |
Garrick Evans | 0dbd418 | 2019-03-07 08:38:38 +0900 | [diff] [blame] | 37 | EXPECT_TRUE(pool == nullptr); |
| 38 | } |
| 39 | |
| 40 | // Tests that the SubnetPool does not allocate more than max subnets at a time. |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 41 | TEST(SubnetPool, AllocationRange) { |
Hugo Benichi | bd8ec4d | 2019-05-28 12:52:49 +0900 | [diff] [blame] | 42 | auto pool = SubnetPool::New(kBaseAddress, kPrefixLength, kMaxSubnets); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 43 | |
Chirantan Ekbote | bccb475 | 2018-10-31 13:53:08 -0700 | [diff] [blame] | 44 | std::deque<std::unique_ptr<Subnet>> subnets; |
Stephen Barber | 4195531 | 2019-01-14 16:37:40 -0800 | [diff] [blame] | 45 | for (size_t i = 0; i < kMaxSubnets; ++i) { |
Garrick Evans | 0dbd418 | 2019-03-07 08:38:38 +0900 | [diff] [blame] | 46 | auto subnet = pool->Allocate(); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 47 | ASSERT_TRUE(subnet); |
| 48 | |
| 49 | subnets.emplace_back(std::move(subnet)); |
| 50 | } |
Garrick Evans | 53a2a98 | 2020-02-05 10:53:35 +0900 | [diff] [blame] | 51 | EXPECT_EQ(subnets.size(), kMaxSubnets); |
Garrick Evans | 0dbd418 | 2019-03-07 08:38:38 +0900 | [diff] [blame] | 52 | EXPECT_FALSE(pool->Allocate()); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | // Tests that subnets are properly released and reused. |
| 56 | TEST(SubnetPool, Release) { |
Hugo Benichi | bd8ec4d | 2019-05-28 12:52:49 +0900 | [diff] [blame] | 57 | auto pool = SubnetPool::New(kBaseAddress, kPrefixLength, kMaxSubnets); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 58 | |
| 59 | // First allocate all the subnets. |
Chirantan Ekbote | bccb475 | 2018-10-31 13:53:08 -0700 | [diff] [blame] | 60 | std::deque<std::unique_ptr<Subnet>> subnets; |
Stephen Barber | 4195531 | 2019-01-14 16:37:40 -0800 | [diff] [blame] | 61 | for (size_t i = 0; i < kMaxSubnets; ++i) { |
Garrick Evans | 0dbd418 | 2019-03-07 08:38:38 +0900 | [diff] [blame] | 62 | auto subnet = pool->Allocate(); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 63 | ASSERT_TRUE(subnet); |
| 64 | |
| 65 | subnets.emplace_back(std::move(subnet)); |
| 66 | } |
Garrick Evans | 0dbd418 | 2019-03-07 08:38:38 +0900 | [diff] [blame] | 67 | ASSERT_FALSE(pool->Allocate()); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 68 | |
| 69 | // Now shuffle the elements. |
Zhizhou Yang | dfddb86 | 2019-08-06 11:00:29 -0700 | [diff] [blame] | 70 | std::shuffle(subnets.begin(), subnets.end(), |
| 71 | std::mt19937(base::RandUint64())); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 72 | |
| 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 Barber | 47981a7 | 2018-01-25 18:45:14 -0800 | [diff] [blame] | 78 | uint32_t gateway = subnet->AddressAtOffset(0); |
| 79 | uint32_t address = subnet->AddressAtOffset(1); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 80 | |
| 81 | // Release the subnet. |
| 82 | subnet.reset(); |
| 83 | |
| 84 | // Get a new subnet. |
Garrick Evans | 0dbd418 | 2019-03-07 08:38:38 +0900 | [diff] [blame] | 85 | subnet = pool->Allocate(); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 86 | ASSERT_TRUE(subnet); |
| 87 | |
Stephen Barber | 47981a7 | 2018-01-25 18:45:14 -0800 | [diff] [blame] | 88 | EXPECT_EQ(gateway, subnet->AddressAtOffset(0)); |
| 89 | EXPECT_EQ(address, subnet->AddressAtOffset(1)); |
Chirantan Ekbote | 1977ea2 | 2017-12-08 18:57:03 -0800 | [diff] [blame] | 90 | } |
| 91 | |
Garrick Evans | 43b4e2d | 2019-12-11 13:43:08 +0900 | [diff] [blame] | 92 | TEST(SubnetPool, Index) { |
| 93 | auto pool = SubnetPool::New(kBaseAddress, kPrefixLength, kMaxSubnets); |
Garrick Evans | 53a2a98 | 2020-02-05 10:53:35 +0900 | [diff] [blame] | 94 | auto subnet = pool->Allocate(1); |
Garrick Evans | 43b4e2d | 2019-12-11 13:43:08 +0900 | [diff] [blame] | 95 | ASSERT_TRUE(subnet); |
Garrick Evans | 53a2a98 | 2020-02-05 10:53:35 +0900 | [diff] [blame] | 96 | 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 Evans | 43b4e2d | 2019-12-11 13:43:08 +0900 | [diff] [blame] | 101 | subnet.reset(); |
Garrick Evans | 53a2a98 | 2020-02-05 10:53:35 +0900 | [diff] [blame] | 102 | EXPECT_TRUE(pool->Allocate(1)); |
| 103 | EXPECT_FALSE(pool->Allocate(kMaxSubnets + 1)); |
Garrick Evans | 43b4e2d | 2019-12-11 13:43:08 +0900 | [diff] [blame] | 104 | } |
| 105 | |
Garrick Evans | 3388a03 | 2020-03-24 11:25:55 +0900 | [diff] [blame^] | 106 | } // namespace patchpanel |