blob: e5569db54c1e1320fd64eb3b512dc8b90f31d228 [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
Hugo Benichi2ac4d072019-05-28 14:51:23 +090018#include "arc/network/net_util.h"
19
Garrick Evans4b66f632019-01-24 15:09:16 +090020namespace arc_networkd {
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070021namespace {
22
Hugo Benichi2ac4d072019-05-28 14:51:23 +090023constexpr size_t kContainerBaseAddress = Ntohl(Ipv4Addr(100, 115, 92, 192));
24constexpr size_t kVmBaseAddress = Ntohl(Ipv4Addr(100, 115, 92, 24));
25constexpr size_t kPluginBaseAddress = Ntohl(Ipv4Addr(100, 115, 92, 128));
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070026
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090027constexpr size_t kContainerSubnetPrefixLength = 28;
28constexpr size_t kVmSubnetPrefixLength = 30;
29constexpr size_t kPluginSubnetPrefixLength = 28;
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070030
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090031// kExpectedAvailableCount[i] == AvailableCount() for subnet with prefix_length
32// i.
Chirantan Ekbote7e4aa422018-11-05 12:24:57 -080033constexpr size_t kExpectedAvailableCount[] = {
34 0xfffffffe, 0x7ffffffe, 0x3ffffffe, 0x1ffffffe, 0xffffffe, 0x7fffffe,
35 0x3fffffe, 0x1fffffe, 0xfffffe, 0x7ffffe, 0x3ffffe, 0x1ffffe,
36 0xffffe, 0x7fffe, 0x3fffe, 0x1fffe, 0xfffe, 0x7ffe,
37 0x3ffe, 0x1ffe, 0xffe, 0x7fe, 0x3fe, 0x1fe,
38 0xfe, 0x7e, 0x3e, 0x1e, 0xe, 0x6,
39 0x2, 0x0,
40};
41
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090042// kExpectedNetmask[i] == Netmask() for subnet with prefix_length i.
Chirantan Ekbote7e4aa422018-11-05 12:24:57 -080043constexpr uint32_t kExpectedNetmask[] = {
Hugo Benichi2ac4d072019-05-28 14:51:23 +090044 Ipv4Addr(0, 0, 0, 0), Ipv4Addr(128, 0, 0, 0),
45 Ipv4Addr(192, 0, 0, 0), Ipv4Addr(224, 0, 0, 0),
46 Ipv4Addr(240, 0, 0, 0), Ipv4Addr(248, 0, 0, 0),
47 Ipv4Addr(252, 0, 0, 0), Ipv4Addr(254, 0, 0, 0),
48 Ipv4Addr(255, 0, 0, 0), Ipv4Addr(255, 128, 0, 0),
49 Ipv4Addr(255, 192, 0, 0), Ipv4Addr(255, 224, 0, 0),
50 Ipv4Addr(255, 240, 0, 0), Ipv4Addr(255, 248, 0, 0),
51 Ipv4Addr(255, 252, 0, 0), Ipv4Addr(255, 254, 0, 0),
52 Ipv4Addr(255, 255, 0, 0), Ipv4Addr(255, 255, 128, 0),
53 Ipv4Addr(255, 255, 192, 0), Ipv4Addr(255, 255, 224, 0),
54 Ipv4Addr(255, 255, 240, 0), Ipv4Addr(255, 255, 248, 0),
55 Ipv4Addr(255, 255, 252, 0), Ipv4Addr(255, 255, 254, 0),
56 Ipv4Addr(255, 255, 255, 0), Ipv4Addr(255, 255, 255, 128),
57 Ipv4Addr(255, 255, 255, 192), Ipv4Addr(255, 255, 255, 224),
58 Ipv4Addr(255, 255, 255, 240), Ipv4Addr(255, 255, 255, 248),
59 Ipv4Addr(255, 255, 255, 252), Ipv4Addr(255, 255, 255, 254),
Chirantan Ekbote7e4aa422018-11-05 12:24:57 -080060};
61
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090062// kExpectedPrefix[i] == Prefix() for subnet with 4 * i offset to
63// |kVmBaseAddress|.
64constexpr uint32_t kExpectedPrefix[] = {
Hugo Benichi2ac4d072019-05-28 14:51:23 +090065 Ipv4Addr(100, 115, 92, 24), Ipv4Addr(100, 115, 92, 28),
66 Ipv4Addr(100, 115, 92, 32), Ipv4Addr(100, 115, 92, 36),
67 Ipv4Addr(100, 115, 92, 40), Ipv4Addr(100, 115, 92, 44),
68 Ipv4Addr(100, 115, 92, 48), Ipv4Addr(100, 115, 92, 52),
69 Ipv4Addr(100, 115, 92, 56), Ipv4Addr(100, 115, 92, 60),
70 Ipv4Addr(100, 115, 92, 64), Ipv4Addr(100, 115, 92, 68),
71 Ipv4Addr(100, 115, 92, 72), Ipv4Addr(100, 115, 92, 76),
72 Ipv4Addr(100, 115, 92, 80), Ipv4Addr(100, 115, 92, 84),
73 Ipv4Addr(100, 115, 92, 88), Ipv4Addr(100, 115, 92, 92),
74 Ipv4Addr(100, 115, 92, 96), Ipv4Addr(100, 115, 92, 100),
75 Ipv4Addr(100, 115, 92, 104), Ipv4Addr(100, 115, 92, 108),
76 Ipv4Addr(100, 115, 92, 112), Ipv4Addr(100, 115, 92, 116),
77 Ipv4Addr(100, 115, 92, 120), Ipv4Addr(100, 115, 92, 124),
78 Ipv4Addr(100, 115, 92, 128), Ipv4Addr(100, 115, 92, 132),
79 Ipv4Addr(100, 115, 92, 136), Ipv4Addr(100, 115, 92, 140),
80 Ipv4Addr(100, 115, 92, 144), Ipv4Addr(100, 115, 92, 148),
Hugo Benichibd8ec4d2019-05-28 12:52:49 +090081};
82
83// kExpectedCidrString[i] == ToCidrString() for subnet with 4 * i offset to
84// |kVmBaseAddress|.
85const char* kExpectedCidrString[] = {
86 "100.115.92.24/30", "100.115.92.28/30", "100.115.92.32/30",
87 "100.115.92.36/30", "100.115.92.40/30", "100.115.92.44/30",
88 "100.115.92.48/30", "100.115.92.52/30", "100.115.92.56/30",
89 "100.115.92.60/30", "100.115.92.64/30", "100.115.92.68/30",
90 "100.115.92.72/30", "100.115.92.76/30", "100.115.92.80/30",
91 "100.115.92.84/30", "100.115.92.88/30", "100.115.92.92/30",
92 "100.115.92.96/30", "100.115.92.100/30", "100.115.92.104/30",
93 "100.115.92.108/30", "100.115.92.112/30", "100.115.92.116/30",
94 "100.115.92.120/30", "100.115.92.124/30", "100.115.92.128/30",
95 "100.115.92.132/30", "100.115.92.136/30", "100.115.92.140/30",
96 "100.115.92.144/30", "100.115.92.148/30",
97};
98
Chirantan Ekbotebccb4752018-10-31 13:53:08 -070099class VmSubnetTest : public ::testing::TestWithParam<size_t> {};
100class ContainerSubnetTest : public ::testing::TestWithParam<size_t> {};
101class PrefixTest : public ::testing::TestWithParam<size_t> {};
102
103void DoNothing() {}
104
105void SetTrue(bool* value) {
106 *value = true;
107}
108
109} // namespace
110
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900111TEST_P(VmSubnetTest, Prefix) {
112 size_t index = GetParam();
113 Subnet subnet(kVmBaseAddress + index * 4, kVmSubnetPrefixLength,
114 base::Bind(&DoNothing));
115
116 EXPECT_EQ(kExpectedPrefix[index], subnet.Prefix());
117}
118
119TEST_P(VmSubnetTest, CidrString) {
120 size_t index = GetParam();
121 Subnet subnet(kVmBaseAddress + index * 4, kVmSubnetPrefixLength,
122 base::Bind(&DoNothing));
123
124 EXPECT_EQ(std::string(kExpectedCidrString[index]), subnet.ToCidrString());
125 EXPECT_EQ(kExpectedCidrString[index], subnet.ToCidrString());
126}
127
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700128TEST_P(VmSubnetTest, AddressAtOffset) {
129 size_t index = GetParam();
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900130 Subnet subnet(kVmBaseAddress + index * 4, kVmSubnetPrefixLength,
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700131 base::Bind(&DoNothing));
132
133 for (uint32_t offset = 0; offset < subnet.AvailableCount(); ++offset) {
134 uint32_t address = htonl(kVmBaseAddress + index * 4 + offset + 1);
135 EXPECT_EQ(address, subnet.AddressAtOffset(offset));
136 }
137}
138
139INSTANTIATE_TEST_CASE_P(AllValues,
140 VmSubnetTest,
Stephen Barber41955312019-01-14 16:37:40 -0800141 ::testing::Range(size_t{0}, size_t{26}));
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700142
143TEST_P(ContainerSubnetTest, AddressAtOffset) {
144 size_t index = GetParam();
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900145 Subnet subnet(kContainerBaseAddress + index * 16,
146 kContainerSubnetPrefixLength, base::Bind(&DoNothing));
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700147
148 for (uint32_t offset = 0; offset < subnet.AvailableCount(); ++offset) {
149 uint32_t address = htonl(kContainerBaseAddress + index * 16 + offset + 1);
150 EXPECT_EQ(address, subnet.AddressAtOffset(offset));
151 }
152}
153
154INSTANTIATE_TEST_CASE_P(AllValues,
155 ContainerSubnetTest,
156 ::testing::Range(size_t{1}, size_t{4}));
157
158TEST_P(PrefixTest, AvailableCount) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900159 size_t prefix_length = GetParam();
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700160
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900161 Subnet subnet(0, prefix_length, base::Bind(&DoNothing));
162 EXPECT_EQ(kExpectedAvailableCount[prefix_length], subnet.AvailableCount());
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700163}
164
165TEST_P(PrefixTest, Netmask) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900166 size_t prefix_length = GetParam();
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700167
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900168 Subnet subnet(0, prefix_length, base::Bind(&DoNothing));
Hugo Benichi2ac4d072019-05-28 14:51:23 +0900169 EXPECT_EQ(kExpectedNetmask[prefix_length], subnet.Netmask());
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700170}
171
172INSTANTIATE_TEST_CASE_P(AllValues,
173 PrefixTest,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800174 ::testing::Range(size_t{8}, size_t{32}));
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700175
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900176TEST(SubtnetAddress, StringConversion) {
177 Subnet container_subnet(kContainerBaseAddress, kContainerSubnetPrefixLength,
178 base::Bind(&DoNothing));
179 EXPECT_EQ("100.115.92.192/28", container_subnet.ToCidrString());
180 {
181 EXPECT_EQ("100.115.92.193",
182 container_subnet.AllocateAtOffset(0)->ToIPv4String());
183 EXPECT_EQ("100.115.92.194",
184 container_subnet.AllocateAtOffset(1)->ToIPv4String());
185 EXPECT_EQ("100.115.92.205",
186 container_subnet.AllocateAtOffset(12)->ToIPv4String());
187 EXPECT_EQ("100.115.92.206",
188 container_subnet.AllocateAtOffset(13)->ToIPv4String());
189 }
190 {
191 EXPECT_EQ("100.115.92.193/28",
192 container_subnet.AllocateAtOffset(0)->ToCidrString());
193 EXPECT_EQ("100.115.92.194/28",
194 container_subnet.AllocateAtOffset(1)->ToCidrString());
195 EXPECT_EQ("100.115.92.205/28",
196 container_subnet.AllocateAtOffset(12)->ToCidrString());
197 EXPECT_EQ("100.115.92.206/28",
198 container_subnet.AllocateAtOffset(13)->ToCidrString());
199 }
200
201 Subnet vm_subnet(kVmBaseAddress, kVmSubnetPrefixLength,
202 base::Bind(&DoNothing));
203 EXPECT_EQ("100.115.92.24/30", vm_subnet.ToCidrString());
204 {
205 EXPECT_EQ("100.115.92.25", vm_subnet.AllocateAtOffset(0)->ToIPv4String());
206 EXPECT_EQ("100.115.92.26", vm_subnet.AllocateAtOffset(1)->ToIPv4String());
207 }
208 {
209 EXPECT_EQ("100.115.92.25/30",
210 vm_subnet.AllocateAtOffset(0)->ToCidrString());
211 EXPECT_EQ("100.115.92.26/30",
212 vm_subnet.AllocateAtOffset(1)->ToCidrString());
213 }
214
215 Subnet plugin_subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
216 base::Bind(&DoNothing));
217 EXPECT_EQ("100.115.92.128/28", plugin_subnet.ToCidrString());
218 {
219 EXPECT_EQ("100.115.92.129",
220 plugin_subnet.AllocateAtOffset(0)->ToIPv4String());
221 EXPECT_EQ("100.115.92.130",
222 plugin_subnet.AllocateAtOffset(1)->ToIPv4String());
223 EXPECT_EQ("100.115.92.141",
224 plugin_subnet.AllocateAtOffset(12)->ToIPv4String());
225 EXPECT_EQ("100.115.92.142",
226 plugin_subnet.AllocateAtOffset(13)->ToIPv4String());
227 }
228 {
229 EXPECT_EQ("100.115.92.129/28",
230 plugin_subnet.AllocateAtOffset(0)->ToCidrString());
231 EXPECT_EQ("100.115.92.130/28",
232 plugin_subnet.AllocateAtOffset(1)->ToCidrString());
233 EXPECT_EQ("100.115.92.141/28",
234 plugin_subnet.AllocateAtOffset(12)->ToCidrString());
235 EXPECT_EQ("100.115.92.142/28",
236 plugin_subnet.AllocateAtOffset(13)->ToCidrString());
237 }
238}
239
Chirantan Ekbotebccb4752018-10-31 13:53:08 -0700240// Tests that the Subnet runs the provided cleanup callback when it gets
241// destroyed.
242TEST(Subnet, Cleanup) {
243 bool called = false;
244
245 { Subnet subnet(0, 24, base::Bind(&SetTrue, &called)); }
246
247 EXPECT_TRUE(called);
248}
249
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800250// Tests that the subnet rejects attempts to allocate addresses outside its
251// range.
252TEST(PluginSubnet, OutOfBounds) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900253 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800254 base::Bind(&base::DoNothing));
255
256 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress - 1));
257 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress));
258 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress +
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900259 (1ull << (32 - kPluginSubnetPrefixLength)) - 1));
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800260 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress +
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900261 (1ull << (32 - kPluginSubnetPrefixLength))));
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800262}
263
264// Tests that the subnet rejects attempts to allocate the same address twice.
265TEST(PluginSubnet, DuplicateAddress) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900266 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800267 base::Bind(&base::DoNothing));
268
269 auto addr = subnet.Allocate(kPluginBaseAddress + 1);
270 EXPECT_TRUE(addr);
271 EXPECT_FALSE(subnet.Allocate(kPluginBaseAddress + 1));
272}
273
274// Tests that the subnet allows allocating all addresses in the subnet's range.
275TEST(PluginSubnet, Allocate) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900276 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800277 base::Bind(&base::DoNothing));
278
279 std::vector<std::unique_ptr<SubnetAddress>> addrs;
280 addrs.reserve(subnet.AvailableCount());
281
282 for (size_t offset = 0; offset < subnet.AvailableCount(); ++offset) {
283 // Offset by one since the network id is not allocatable.
284 auto addr = subnet.Allocate(kPluginBaseAddress + offset + 1);
285 EXPECT_TRUE(addr);
286 EXPECT_EQ(htonl(kPluginBaseAddress + offset + 1), addr->Address());
287 addrs.emplace_back(std::move(addr));
288 }
289}
Garrick Evans0dbd4182019-03-07 08:38:38 +0900290// Tests that the subnet allows allocating all addresses in the subnet's range
291// using an offset.
292TEST(PluginSubnet, AllocateAtOffset) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900293 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Garrick Evans0dbd4182019-03-07 08:38:38 +0900294 base::Bind(&base::DoNothing));
295
296 std::vector<std::unique_ptr<SubnetAddress>> addrs;
297 addrs.reserve(subnet.AvailableCount());
298
299 for (size_t offset = 0; offset < subnet.AvailableCount(); ++offset) {
300 auto addr = subnet.AllocateAtOffset(offset);
301 EXPECT_TRUE(addr);
302 EXPECT_EQ(htonl(kPluginBaseAddress + offset + 1), addr->Address());
303 addrs.emplace_back(std::move(addr));
304 }
305}
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800306
307// Tests that the subnet frees addresses when they are destroyed.
308TEST(PluginSubnet, Free) {
Hugo Benichibd8ec4d2019-05-28 12:52:49 +0900309 Subnet subnet(kPluginBaseAddress, kPluginSubnetPrefixLength,
Chirantan Ekbote817b0c22018-11-14 16:55:10 -0800310 base::Bind(&base::DoNothing));
311
312 {
313 auto addr = subnet.Allocate(kPluginBaseAddress + 1);
314 EXPECT_TRUE(addr);
315 }
316
317 EXPECT_TRUE(subnet.Allocate(kPluginBaseAddress + 1));
318}
319
Garrick Evans4b66f632019-01-24 15:09:16 +0900320} // namespace arc_networkd