blob: f1678b473384b046ddfd0b04485f9ed6c5301351 [file] [log] [blame]
Chirantan Ekbotebccb4752018-10-31 13:53:08 -07001// Copyright 2018 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.h"
Chirantan Ekbotebccb4752018-10-31 13:53:08 -07006
7#include <arpa/inet.h>
8#include <stdint.h>
9
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090010#include <string>
Chirantan Ekbote817b0c22018-11-14 16:55:10 -080011#include <utility>
12#include <vector>
13
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070014#include <base/bind.h>
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090015#include <base/strings/string_util.h>
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070016#include <gtest/gtest.h>
17
Garrick Evans4b66f632019-01-24 15:09:16 +090018namespace arc_networkd {
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070019namespace {
20
21constexpr size_t kContainerBaseAddress = 0x64735cc0; // 100.115.92.192
Stephen Barber41955312019-01-14 16:37:40 -080022constexpr size_t kVmBaseAddress = 0x64735c18; // 100.115.92.24
Chirantan Ekbote817b0c22018-11-14 16:55:10 -080023constexpr size_t kPluginBaseAddress = 0x64735c80; // 100.115.92.128
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070024
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090025constexpr size_t kContainerSubnetPrefixLength = 28;
26constexpr size_t kVmSubnetPrefixLength = 30;
27constexpr size_t kPluginSubnetPrefixLength = 28;
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070028
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090029// kExpectedAvailableCount[i] == AvailableCount() for subnet with prefix_length
30// i.
Chirantan Ekbote7e4aa422018-11-05 12:24:57 -080031constexpr size_t kExpectedAvailableCount[] = {
32 0xfffffffe, 0x7ffffffe, 0x3ffffffe, 0x1ffffffe, 0xffffffe, 0x7fffffe,
33 0x3fffffe, 0x1fffffe, 0xfffffe, 0x7ffffe, 0x3ffffe, 0x1ffffe,
34 0xffffe, 0x7fffe, 0x3fffe, 0x1fffe, 0xfffe, 0x7ffe,
35 0x3ffe, 0x1ffe, 0xffe, 0x7fe, 0x3fe, 0x1fe,
36 0xfe, 0x7e, 0x3e, 0x1e, 0xe, 0x6,
37 0x2, 0x0,
38};
39
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090040// kExpectedNetmask[i] == Netmask() for subnet with prefix_length i.
Chirantan Ekbote7e4aa422018-11-05 12:24:57 -080041constexpr uint32_t kExpectedNetmask[] = {
42 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
43 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
44 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
45 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
46 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
47 0xfffffffc, 0xfffffffe,
48};
49
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090050// kExpectedPrefix[i] == Prefix() for subnet with 4 * i offset to
51// |kVmBaseAddress|.
52constexpr uint32_t kExpectedPrefix[] = {
53 0x185c7364, 0x1c5c7364, 0x205c7364, 0x245c7364, 0x285c7364, 0x2c5c7364,
54 0x305c7364, 0x345c7364, 0x385c7364, 0x3c5c7364, 0x405c7364, 0x445c7364,
55 0x485c7364, 0x4c5c7364, 0x505c7364, 0x545c7364, 0x585c7364, 0x5c5c7364,
56 0x605c7364, 0x645c7364, 0x685c7364, 0x6c5c7364, 0x705c7364, 0x745c7364,
57 0x785c7364, 0x7c5c7364, 0x805c7364, 0x845c7364, 0x885c7364, 0x8c5c7364,
58 0x905c7364, 0x945c7364,
59};
60
61// kExpectedCidrString[i] == ToCidrString() for subnet with 4 * i offset to
62// |kVmBaseAddress|.
63const char* kExpectedCidrString[] = {
64 "100.115.92.24/30", "100.115.92.28/30", "100.115.92.32/30",
65 "100.115.92.36/30", "100.115.92.40/30", "100.115.92.44/30",
66 "100.115.92.48/30", "100.115.92.52/30", "100.115.92.56/30",
67 "100.115.92.60/30", "100.115.92.64/30", "100.115.92.68/30",
68 "100.115.92.72/30", "100.115.92.76/30", "100.115.92.80/30",
69 "100.115.92.84/30", "100.115.92.88/30", "100.115.92.92/30",
70 "100.115.92.96/30", "100.115.92.100/30", "100.115.92.104/30",
71 "100.115.92.108/30", "100.115.92.112/30", "100.115.92.116/30",
72 "100.115.92.120/30", "100.115.92.124/30", "100.115.92.128/30",
73 "100.115.92.132/30", "100.115.92.136/30", "100.115.92.140/30",
74 "100.115.92.144/30", "100.115.92.148/30",
75};
76
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070077class VmSubnetTest : public ::testing::TestWithParam<size_t> {};
78class ContainerSubnetTest : public ::testing::TestWithParam<size_t> {};
79class PrefixTest : public ::testing::TestWithParam<size_t> {};
80
81void DoNothing() {}
82
83void SetTrue(bool* value) {
84 *value = true;
85}
86
87} // namespace
88
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090089TEST_P(VmSubnetTest, Prefix) {
90 size_t index = GetParam();
91 Subnet subnet(kVmBaseAddress + index * 4, kVmSubnetPrefixLength,
92 base::Bind(&DoNothing));
93
94 EXPECT_EQ(kExpectedPrefix[index], subnet.Prefix());
95}
96
97TEST_P(VmSubnetTest, CidrString) {
98 size_t index = GetParam();
99 Subnet subnet(kVmBaseAddress + index * 4, kVmSubnetPrefixLength,
100 base::Bind(&DoNothing));
101
102 EXPECT_EQ(std::string(kExpectedCidrString[index]), subnet.ToCidrString());
103 EXPECT_EQ(kExpectedCidrString[index], subnet.ToCidrString());
104}
105
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700106TEST_P(VmSubnetTest, AddressAtOffset) {
107 size_t index = GetParam();
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900108 Subnet subnet(kVmBaseAddress + index * 4, kVmSubnetPrefixLength,
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700109 base::Bind(&DoNothing));
110
111 for (uint32_t offset = 0; offset < subnet.AvailableCount(); ++offset) {
112 uint32_t address = htonl(kVmBaseAddress + index * 4 + offset + 1);
113 EXPECT_EQ(address, subnet.AddressAtOffset(offset));
114 }
115}
116
117INSTANTIATE_TEST_CASE_P(AllValues,
118 VmSubnetTest,
Stephen Barber41955312019-01-14 16:37:40 -0800119 ::testing::Range(size_t{0}, size_t{26}));
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700120
121TEST_P(ContainerSubnetTest, AddressAtOffset) {
122 size_t index = GetParam();
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900123 Subnet subnet(kContainerBaseAddress + index * 16,
124 kContainerSubnetPrefixLength, base::Bind(&DoNothing));
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700125
126 for (uint32_t offset = 0; offset < subnet.AvailableCount(); ++offset) {
127 uint32_t address = htonl(kContainerBaseAddress + index * 16 + offset + 1);
128 EXPECT_EQ(address, subnet.AddressAtOffset(offset));
129 }
130}
131
132INSTANTIATE_TEST_CASE_P(AllValues,
133 ContainerSubnetTest,
134 ::testing::Range(size_t{1}, size_t{4}));
135
136TEST_P(PrefixTest, AvailableCount) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900137 size_t prefix_length = GetParam();
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700138
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900139 Subnet subnet(0, prefix_length, base::Bind(&DoNothing));
140 EXPECT_EQ(kExpectedAvailableCount[prefix_length], subnet.AvailableCount());
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700141}
142
143TEST_P(PrefixTest, Netmask) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900144 size_t prefix_length = GetParam();
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700145
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900146 Subnet subnet(0, prefix_length, base::Bind(&DoNothing));
147 EXPECT_EQ(htonl(kExpectedNetmask[prefix_length]), subnet.Netmask());
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700148}
149
150INSTANTIATE_TEST_CASE_P(AllValues,
151 PrefixTest,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800152 ::testing::Range(size_t{8}, size_t{32}));
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700153
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900154TEST(SubtnetAddress, StringConversion) {
155 Subnet container_subnet(kContainerBaseAddress, kContainerSubnetPrefixLength,
156 base::Bind(&DoNothing));
157 EXPECT_EQ("100.115.92.192/28", container_subnet.ToCidrString());
158 {
159 EXPECT_EQ("100.115.92.193",
160 container_subnet.AllocateAtOffset(0)->ToIPv4String());
161 EXPECT_EQ("100.115.92.194",
162 container_subnet.AllocateAtOffset(1)->ToIPv4String());
163 EXPECT_EQ("100.115.92.205",
164 container_subnet.AllocateAtOffset(12)->ToIPv4String());
165 EXPECT_EQ("100.115.92.206",
166 container_subnet.AllocateAtOffset(13)->ToIPv4String());
167 }
168 {
169 EXPECT_EQ("100.115.92.193/28",
170 container_subnet.AllocateAtOffset(0)->ToCidrString());
171 EXPECT_EQ("100.115.92.194/28",
172 container_subnet.AllocateAtOffset(1)->ToCidrString());
173 EXPECT_EQ("100.115.92.205/28",
174 container_subnet.AllocateAtOffset(12)->ToCidrString());
175 EXPECT_EQ("100.115.92.206/28",
176 container_subnet.AllocateAtOffset(13)->ToCidrString());
177 }
178
179 Subnet vm_subnet(kVmBaseAddress, kVmSubnetPrefixLength,
180 base::Bind(&DoNothing));
181 EXPECT_EQ("100.115.92.24/30", vm_subnet.ToCidrString());
182 {
183 EXPECT_EQ("100.115.92.25", vm_subnet.AllocateAtOffset(0)->ToIPv4String());
184 EXPECT_EQ("100.115.92.26", vm_subnet.AllocateAtOffset(1)->ToIPv4String());
185 }
186 {
187 EXPECT_EQ("100.115.92.25/30",
188 vm_subnet.AllocateAtOffset(0)->ToCidrString());
189 EXPECT_EQ("100.115.92.26/30",
190 vm_subnet.AllocateAtOffset(1)->ToCidrString());
191 }
192
193 Subnet plugin_subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
194 base::Bind(&DoNothing));
195 EXPECT_EQ("100.115.92.128/28", plugin_subnet.ToCidrString());
196 {
197 EXPECT_EQ("100.115.92.129",
198 plugin_subnet.AllocateAtOffset(0)->ToIPv4String());
199 EXPECT_EQ("100.115.92.130",
200 plugin_subnet.AllocateAtOffset(1)->ToIPv4String());
201 EXPECT_EQ("100.115.92.141",
202 plugin_subnet.AllocateAtOffset(12)->ToIPv4String());
203 EXPECT_EQ("100.115.92.142",
204 plugin_subnet.AllocateAtOffset(13)->ToIPv4String());
205 }
206 {
207 EXPECT_EQ("100.115.92.129/28",
208 plugin_subnet.AllocateAtOffset(0)->ToCidrString());
209 EXPECT_EQ("100.115.92.130/28",
210 plugin_subnet.AllocateAtOffset(1)->ToCidrString());
211 EXPECT_EQ("100.115.92.141/28",
212 plugin_subnet.AllocateAtOffset(12)->ToCidrString());
213 EXPECT_EQ("100.115.92.142/28",
214 plugin_subnet.AllocateAtOffset(13)->ToCidrString());
215 }
216}
217
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700218// Tests that the Subnet runs the provided cleanup callback when it gets
219// destroyed.
220TEST(Subnet, Cleanup) {
221 bool called = false;
222
223 { Subnet subnet(0, 24, base::Bind(&SetTrue, &called)); }
224
225 EXPECT_TRUE(called);
226}
227
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800228// Tests that the subnet rejects attempts to allocate addresses outside its
229// range.
230TEST(PluginSubnet, OutOfBounds) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900231 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800232 base::Bind(&base::DoNothing));
233
234 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress - 1));
235 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress));
236 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress +
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900237 (1ull << (32 - kPluginSubnetPrefixLength)) - 1));
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800238 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress +
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900239 (1ull << (32 - kPluginSubnetPrefixLength))));
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800240}
241
242// Tests that the subnet rejects attempts to allocate the same address twice.
243TEST(PluginSubnet, DuplicateAddress) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900244 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800245 base::Bind(&base::DoNothing));
246
247 auto addr = subnet.Allocate(kPluginBaseAddress + 1);
248 EXPECT_TRUE(addr);
249 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress + 1));
250}
251
252// Tests that the subnet allows allocating all addresses in the subnet's range.
253TEST(PluginSubnet, Allocate) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900254 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800255 base::Bind(&base::DoNothing));
256
257 std::vector<std::unique_ptr<SubnetAddress>> addrs;
258 addrs.reserve(subnet.AvailableCount());
259
260 for (size_t offset = 0; offset < subnet.AvailableCount(); ++offset) {
261 // Offset by one since the network id is not allocatable.
262 auto addr = subnet.Allocate(kPluginBaseAddress + offset + 1);
263 EXPECT_TRUE(addr);
264 EXPECT_EQ(htonl(kPluginBaseAddress + offset + 1), addr->Address());
265 addrs.emplace_back(std::move(addr));
266 }
267}
Garrick Evans0dbd4182019-03-07 08:38:38 +0900268// Tests that the subnet allows allocating all addresses in the subnet's range
269// using an offset.
270TEST(PluginSubnet, AllocateAtOffset) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900271 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Garrick Evans0dbd4182019-03-07 08:38:38 +0900272 base::Bind(&base::DoNothing));
273
274 std::vector<std::unique_ptr<SubnetAddress>> addrs;
275 addrs.reserve(subnet.AvailableCount());
276
277 for (size_t offset = 0; offset < subnet.AvailableCount(); ++offset) {
278 auto addr = subnet.AllocateAtOffset(offset);
279 EXPECT_TRUE(addr);
280 EXPECT_EQ(htonl(kPluginBaseAddress + offset + 1), addr->Address());
281 addrs.emplace_back(std::move(addr));
282 }
283}
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800284
285// Tests that the subnet frees addresses when they are destroyed.
286TEST(PluginSubnet, Free) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900287 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800288 base::Bind(&base::DoNothing));
289
290 {
291 auto addr = subnet.Allocate(kPluginBaseAddress + 1);
292 EXPECT_TRUE(addr);
293 }
294
295 EXPECT_TRUE(subnet.Allocate(kPluginBaseAddress + 1));
296}
297
Garrick Evans4b66f632019-01-24 15:09:16 +0900298} // namespace arc_networkd