| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 1 | // Copyright 2023 The ChromiumOS Authors |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "patchpanel/clat_service.h" |
| 6 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 7 | #include <memory> |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 8 | #include <optional> |
| 9 | #include <string> |
| 10 | #include <vector> |
| 11 | |
| 12 | #include <gmock/gmock.h> |
| 13 | #include <gtest/gtest.h> |
| 14 | #include <net-base/ip_address_utils.h> |
| 15 | #include <net-base/ipv4_address.h> |
| 16 | #include <net-base/ipv6_address.h> |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 17 | #include <shill/net/mock_process_manager.h> |
| 18 | #include <shill/net/process_manager.h> |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 19 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 20 | #include "patchpanel/datapath.h" |
| 21 | #include "patchpanel/fake_system.h" |
| naoyatezuka | c8ebb46 | 2023-09-21 10:52:33 | [diff] [blame^] | 22 | #include "patchpanel/iptables.h" |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 23 | #include "patchpanel/mock_datapath.h" |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 24 | #include "patchpanel/shill_client.h" |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 25 | #include "patchpanel/system.h" |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 26 | |
| 27 | using testing::_; |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 28 | using testing::Eq; |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 29 | using testing::Exactly; |
| 30 | using testing::Invoke; |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 31 | using testing::IsEmpty; |
| 32 | using testing::Return; |
| 33 | using testing::StrEq; |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 34 | |
| 35 | namespace patchpanel { |
| 36 | namespace { |
| 37 | |
| 38 | MATCHER_P(ShillDeviceHasInterfaceName, expected_ifname, "") { |
| 39 | return arg.ifname == expected_ifname; |
| 40 | } |
| 41 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 42 | MATCHER_P(CIDRHasPrefix, expected_prefix_str, "") { |
| 43 | return net_base::IPv6CIDR::CreateFromCIDRString(expected_prefix_str) |
| 44 | ->InSameSubnetWith(arg.address()); |
| 45 | } |
| 46 | |
| 47 | MATCHER_P(AddressHasPrefix, expected_prefix_str, "") { |
| 48 | return net_base::IPv6CIDR::CreateFromCIDRString(expected_prefix_str) |
| 49 | ->InSameSubnetWith(arg); |
| 50 | } |
| 51 | |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 52 | class ClatServiceUnderTest : public ClatService { |
| 53 | public: |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 54 | ClatServiceUnderTest(Datapath* datapath, |
| 55 | shill::ProcessManager* process_manager, |
| 56 | System* system) |
| 57 | : ClatService(datapath, process_manager, system) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 58 | ON_CALL(*this, StartClat(_)) |
| 59 | .WillByDefault( |
| 60 | (Invoke(this, &ClatServiceUnderTest::SetClatRunningDeviceForTest))); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 61 | ON_CALL(*this, StopClat(true)) |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 62 | .WillByDefault( |
| 63 | Invoke(this, &ClatServiceUnderTest::ResetClatRunningDeviceForTest)); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 64 | Enable(); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 65 | } |
| 66 | |
| 67 | MOCK_METHOD(void, |
| 68 | StartClat, |
| 69 | (const ShillClient::Device& shill_device), |
| 70 | (override)); |
| 71 | |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 72 | MOCK_METHOD(void, StopClat, (bool clear_running_device), (override)); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 73 | }; |
| 74 | |
| 75 | constexpr char kIPv4CIDR[] = "10.10.0.2/16"; |
| 76 | constexpr char kIPv6CIDR[] = "2001:db8::1/64"; |
| 77 | |
| 78 | ShillClient::Device MakeFakeShillDevice(const std::string& ifname, |
| 79 | int ifindex) { |
| 80 | ShillClient::Device dev; |
| 81 | dev.type = ShillClient::Device::Type::kEthernet; |
| 82 | dev.ifindex = ifindex; |
| 83 | dev.ifname = ifname; |
| 84 | |
| 85 | return dev; |
| 86 | } |
| 87 | |
| 88 | ShillClient::Device MakeFakeIPv4OnlyShillDevice( |
| 89 | const std::string& ifname, |
| 90 | int ifindex = 1, |
| 91 | const char ipv4_cidr[] = kIPv4CIDR) { |
| 92 | ShillClient::Device dev = MakeFakeShillDevice(ifname, ifindex); |
| 93 | dev.ipconfig.ipv4_cidr = net_base::IPv4CIDR::CreateFromCIDRString(ipv4_cidr); |
| 94 | |
| 95 | return dev; |
| 96 | } |
| 97 | |
| 98 | ShillClient::Device MakeFakeIPv6OnlyShillDevice( |
| 99 | const std::string& ifname, |
| 100 | int ifindex = 1, |
| 101 | const char ipv6_cidr[] = kIPv6CIDR) { |
| 102 | ShillClient::Device dev = MakeFakeShillDevice(ifname, ifindex); |
| 103 | dev.ipconfig.ipv6_cidr = net_base::IPv6CIDR::CreateFromCIDRString(ipv6_cidr); |
| 104 | |
| 105 | return dev; |
| 106 | } |
| 107 | |
| 108 | ShillClient::Device MakeFakeDualStackShillDevice( |
| 109 | const std::string& ifname, |
| 110 | int ifindex = 1, |
| 111 | const char ipv4_cidr[] = kIPv4CIDR, |
| 112 | const char ipv6_cidr[] = kIPv6CIDR) { |
| 113 | ShillClient::Device dev = MakeFakeShillDevice(ifname, ifindex); |
| 114 | dev.ipconfig.ipv4_cidr = net_base::IPv4CIDR::CreateFromCIDRString(ipv4_cidr); |
| 115 | dev.ipconfig.ipv6_cidr = net_base::IPv6CIDR::CreateFromCIDRString(ipv6_cidr); |
| 116 | |
| 117 | return dev; |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 118 | } // namespace |
| 119 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 120 | class ClatServiceTest : public ::testing::Test { |
| 121 | protected: |
| 122 | void SetUp() override { |
| 123 | target_ = std::make_unique<ClatServiceUnderTest>( |
| 124 | &datapath_, &process_manager_, &system_); |
| 125 | } |
| 126 | MockDatapath datapath_ = MockDatapath(); |
| 127 | shill::MockProcessManager process_manager_ = shill::MockProcessManager(); |
| 128 | FakeSystem system_ = FakeSystem(); |
| 129 | std::unique_ptr<ClatServiceUnderTest> target_; |
| 130 | }; |
| 131 | |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 132 | // TODO(b/278970851): Merge tests for OnShillDefaultLogicalDeviceChanged into a |
| 133 | // single test with a testcase data array. |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 134 | TEST_F(ClatServiceTest, ChangeFromIPv4DeviceToIPv6OnlyDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 135 | const auto v4only_dev = MakeFakeIPv4OnlyShillDevice("v4only", 1); |
| 136 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 2); |
| 137 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 138 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("v6only"))); |
| 139 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, &v4only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 140 | } |
| 141 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 142 | TEST_F(ClatServiceTest, ChangeFromIPv6OnlyDeviceToIPv4Device) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 143 | const auto v4only_dev = MakeFakeIPv4OnlyShillDevice("v4only", 1); |
| 144 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 2); |
| 145 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 146 | // Start CLAT on the new_device. |
| 147 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 148 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 149 | EXPECT_CALL(*target_, StopClat(true)); |
| 150 | target_->OnShillDefaultLogicalDeviceChanged(&v4only_dev, &v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 151 | } |
| 152 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 153 | TEST_F(ClatServiceTest, ChangeFromIPv6OnlyDeviceToAnother) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 154 | const auto new_v6only_dev = |
| 155 | MakeFakeIPv6OnlyShillDevice("new_v6only", 1, "1020:db8::1/64"); |
| 156 | const auto prev_v6only_dev = |
| 157 | MakeFakeIPv6OnlyShillDevice("prev_v6only", 1, "2001:db8::2/64"); |
| 158 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 159 | // Start CLAT on the new_device. |
| 160 | target_->OnShillDefaultLogicalDeviceChanged(&prev_v6only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 161 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 162 | EXPECT_CALL(*target_, StopClat(true)); |
| 163 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("new_v6only"))); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 164 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 165 | target_->OnShillDefaultLogicalDeviceChanged(&new_v6only_dev, |
| 166 | &prev_v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 167 | } |
| 168 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 169 | TEST_F(ClatServiceTest, ChangeFromDualStackDeviceToIPv4OnlyDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 170 | const auto dual_dev = MakeFakeDualStackShillDevice("dual_dev", 1); |
| 171 | const auto v4only_dev = MakeFakeIPv4OnlyShillDevice("v4only", 2); |
| 172 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 173 | target_->OnShillDefaultLogicalDeviceChanged(&dual_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 174 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 175 | EXPECT_CALL(*target_, StopClat(_)).Times(Exactly(0)); |
| 176 | EXPECT_CALL(*target_, StartClat(_)).Times(Exactly(0)); |
| 177 | target_->OnShillDefaultLogicalDeviceChanged(&v4only_dev, &dual_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 178 | } |
| 179 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 180 | TEST_F(ClatServiceTest, ChangeFromIPv4OnlyDeviceToDualStackDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 181 | const auto dual_dev = MakeFakeDualStackShillDevice("dual_dev", 1); |
| 182 | const auto v4only_dev = MakeFakeIPv4OnlyShillDevice("v4only", 2); |
| 183 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 184 | target_->OnShillDefaultLogicalDeviceChanged(&v4only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 185 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 186 | EXPECT_CALL(*target_, StopClat(_)).Times(Exactly(0)); |
| 187 | EXPECT_CALL(*target_, StartClat(_)).Times(Exactly(0)); |
| 188 | target_->OnShillDefaultLogicalDeviceChanged(&dual_dev, &v4only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 189 | } |
| 190 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 191 | TEST_F(ClatServiceTest, ChangeFromDualStackDeviceToIPv6OnlyDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 192 | const auto dual_dev = MakeFakeDualStackShillDevice("dual_dev", 1); |
| 193 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 2); |
| 194 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 195 | target_->OnShillDefaultLogicalDeviceChanged(&dual_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 196 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 197 | EXPECT_CALL(*target_, StopClat(_)).Times(Exactly(0)); |
| 198 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("v6only"))); |
| 199 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, &dual_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 200 | } |
| 201 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 202 | TEST_F(ClatServiceTest, ChangeFromIPv6OnlyDeviceToDualStackDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 203 | const auto dual_dev = MakeFakeDualStackShillDevice("dual_dev", 1); |
| 204 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 2); |
| 205 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 206 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 207 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 208 | EXPECT_CALL(*target_, StopClat(true)); |
| 209 | EXPECT_CALL(*target_, StartClat(_)).Times(Exactly(0)); |
| 210 | target_->OnShillDefaultLogicalDeviceChanged(&dual_dev, &v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 211 | } |
| 212 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 213 | TEST_F(ClatServiceTest, ChangeFromDualStackDeviceToAnother) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 214 | const auto new_v6only_dev = MakeFakeDualStackShillDevice( |
| 215 | "new_dual_dev", 1, "10.10.0.2/24", "1020:db8::1/64"); |
| 216 | |
| 217 | const auto prev_v6only_dev = MakeFakeDualStackShillDevice( |
| 218 | "prev_dual_dev", 2, "10.20.0.2/24", "2001:db8::1/64"); |
| 219 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 220 | target_->OnShillDefaultLogicalDeviceChanged(&prev_v6only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 221 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 222 | EXPECT_CALL(*target_, StopClat(_)).Times(Exactly(0)); |
| 223 | EXPECT_CALL(*target_, StartClat(_)).Times(Exactly(0)); |
| 224 | target_->OnShillDefaultLogicalDeviceChanged(&new_v6only_dev, |
| 225 | &prev_v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 226 | } |
| 227 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 228 | TEST_F(ClatServiceTest, ChangeFromNonExstingDeviceToExistingDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 229 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only"); |
| 230 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 231 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("v6only"))); |
| 232 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 233 | } |
| 234 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 235 | TEST_F(ClatServiceTest, ChangeFromExstingDeviceToNonExistingDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 236 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only"); |
| 237 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 238 | // Start CLAT on the new_device. |
| 239 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 240 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 241 | EXPECT_CALL(*target_, StopClat(true)); |
| 242 | EXPECT_CALL(*target_, StartClat(_)).Times(Exactly(0)); |
| 243 | target_->OnShillDefaultLogicalDeviceChanged(nullptr, &v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 244 | } |
| 245 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 246 | TEST_F(ClatServiceTest, |
| 247 | DefaultDeviceChangeWhileClatIsRunningOnDifferentDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 248 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 1); |
| 249 | const auto prev_v6only_dev = |
| 250 | MakeFakeIPv6OnlyShillDevice("new_v6only", 2, "1020:db8::1/64"); |
| 251 | const auto new_v6only_dev = |
| 252 | MakeFakeIPv6OnlyShillDevice("prev_v6only", 3, "1030:db8::1/64"); |
| 253 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 254 | // Start CLAT on device "v6only_dev1". |
| 255 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 256 | |
| 257 | // Unexpectedly the default logical device changes from an device different |
| 258 | // from v6only_dev1 to another. |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 259 | EXPECT_CALL(*target_, StopClat(true)); |
| 260 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("new_v6only"))); |
| 261 | target_->OnShillDefaultLogicalDeviceChanged(&prev_v6only_dev, |
| 262 | &prev_v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 263 | } |
| 264 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 265 | TEST_F(ClatServiceTest, NewDefaultDeviceIsTheSameWithClatDevice) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 266 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 1); |
| 267 | const auto dual_dev = MakeFakeDualStackShillDevice("dual", 2); |
| 268 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 269 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, nullptr); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 270 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 271 | EXPECT_CALL(*target_, StopClat(_)).Times(Exactly(0)); |
| 272 | EXPECT_CALL(*target_, StartClat(_)).Times(Exactly(0)); |
| 273 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, &dual_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 274 | } |
| 275 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 276 | TEST_F(ClatServiceTest, |
| 277 | ChangeFromDualStackDeviceToIPv6OnlyDeviceWhileDisabled) { |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 278 | const auto dual_dev = MakeFakeDualStackShillDevice("dual", 1); |
| 279 | const auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 2); |
| 280 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 281 | target_->OnShillDefaultLogicalDeviceChanged(&dual_dev, nullptr); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 282 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 283 | EXPECT_CALL(*target_, StopClat(false)); |
| 284 | target_->Disable(); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 285 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 286 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("v6only"))); |
| 287 | target_->OnShillDefaultLogicalDeviceChanged(&v6only_dev, &dual_dev); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 288 | |
| 289 | // The default logical device is IPv6-only, so CLAT starts immdiately after |
| 290 | // it's enabled. |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 291 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("v6only"))); |
| 292 | target_->Enable(); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 293 | } |
| 294 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 295 | TEST_F(ClatServiceTest, IPv6OnlyDeviceGetIPv4Address) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 296 | auto default_logical_device = MakeFakeIPv6OnlyShillDevice("v6only"); |
| 297 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 298 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("v6only"))); |
| 299 | target_->OnDefaultLogicalDeviceIPConfigChanged(default_logical_device); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 300 | |
| 301 | // The default logical device gets IPv4 address because of IPConfig changes. |
| 302 | default_logical_device.ipconfig.ipv4_cidr = |
| 303 | net_base::IPv4CIDR::CreateFromCIDRString(kIPv4CIDR); |
| 304 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 305 | EXPECT_CALL(*target_, StopClat(true)); |
| 306 | target_->OnDefaultLogicalDeviceIPConfigChanged(default_logical_device); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 307 | } |
| 308 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 309 | TEST_F(ClatServiceTest, DeviceLoseIPv4Address) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 310 | auto default_logical_device = MakeFakeDualStackShillDevice("dual_stack", 1); |
| 311 | |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 312 | // The default logical device loses IPv4 address because of IPConfig changes. |
| 313 | default_logical_device.ipconfig.ipv4_cidr.reset(); |
| 314 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 315 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("dual_stack"))); |
| 316 | target_->OnDefaultLogicalDeviceIPConfigChanged(default_logical_device); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 317 | } |
| 318 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 319 | TEST_F(ClatServiceTest, IPConfigChangeWithoutIPv6AddressChange) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 320 | auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only"); |
| 321 | v6only_dev.ipconfig.ipv4_dns_addresses = std::vector<std::string>{"8.8.8.8"}; |
| 322 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 323 | target_->OnDefaultLogicalDeviceIPConfigChanged(v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 324 | |
| 325 | v6only_dev.ipconfig.ipv4_dns_addresses = std::vector<std::string>{"1.1.1.1"}; |
| 326 | |
| 327 | // This change has nothing with CLAT. |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 328 | EXPECT_CALL(*target_, StopClat(_)).Times(Exactly(0)); |
| 329 | EXPECT_CALL(*target_, StartClat(_)).Times(Exactly(0)); |
| 330 | target_->OnDefaultLogicalDeviceIPConfigChanged(v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 331 | } |
| 332 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 333 | TEST_F(ClatServiceTest, IPv6AddressChangeInTheSamePrefix) { |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 334 | auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 1, "2001:db8::1/64"); |
| 335 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 336 | target_->OnDefaultLogicalDeviceIPConfigChanged(v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 337 | |
| 338 | v6only_dev.ipconfig.ipv6_cidr = |
| 339 | net_base::IPv6CIDR::CreateFromCIDRString("2001:db8::2/64"); |
| 340 | |
| 341 | // Even the new IPn6 address of the default logical device has the same prefix |
| 342 | // as the old one, CLAT needs to be reconfigured because the new address |
| 343 | // conflict with the IPv6 address used by CLAT. |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 344 | EXPECT_CALL(*target_, StopClat(true)); |
| 345 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("v6only"))); |
| 346 | target_->OnDefaultLogicalDeviceIPConfigChanged(v6only_dev); |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 347 | } |
| 348 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 349 | TEST_F(ClatServiceTest, EnabledAfterGettingIPv4AddressWhileDisabled) { |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 350 | auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only"); |
| 351 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 352 | target_->OnDefaultLogicalDeviceIPConfigChanged(v6only_dev); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 353 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 354 | EXPECT_CALL(*target_, StopClat(false)); |
| 355 | target_->Disable(); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 356 | |
| 357 | v6only_dev.ipconfig.ipv4_cidr = |
| 358 | net_base::IPv4CIDR::CreateFromCIDRString(kIPv4CIDR); |
| 359 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 360 | EXPECT_CALL(*target_, StopClat(true)); |
| 361 | target_->OnDefaultLogicalDeviceIPConfigChanged(v6only_dev); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 362 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 363 | EXPECT_CALL(*target_, StartClat(_)).Times(Exactly(0)); |
| 364 | target_->Enable(); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 365 | } |
| 366 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 367 | TEST_F(ClatServiceTest, EnabledAfterBecomingIPv6OnlyWhileDisabled) { |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 368 | auto dual_dev = MakeFakeDualStackShillDevice("dual"); |
| 369 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 370 | target_->OnDefaultLogicalDeviceIPConfigChanged(dual_dev); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 371 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 372 | EXPECT_CALL(*target_, StopClat(false)); |
| 373 | target_->Disable(); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 374 | |
| 375 | dual_dev.ipconfig.ipv4_cidr.reset(); |
| 376 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 377 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("dual"))); |
| 378 | target_->OnDefaultLogicalDeviceIPConfigChanged(dual_dev); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 379 | |
| 380 | // The default logical device is IPv6-only, so CLAT starts immdiately after |
| 381 | // it's enabled. |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 382 | EXPECT_CALL(*target_, StartClat(ShillDeviceHasInterfaceName("dual"))); |
| 383 | target_->Enable(); |
| naoyatezuka | 6e778df | 2023-09-01 00:44:00 | [diff] [blame] | 384 | } |
| 385 | |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 386 | TEST_F(ClatServiceTest, VerifyStartAndStopClat) { |
| 387 | ClatService target(&datapath_, &process_manager_, &system_); |
| 388 | target.Enable(); |
| 389 | |
| 390 | auto v4only_dev = MakeFakeIPv4OnlyShillDevice("v4only", 1); |
| 391 | auto v6only_dev = MakeFakeIPv6OnlyShillDevice("v6only", 2); |
| 392 | |
| 393 | target.OnShillDefaultLogicalDeviceChanged(&v4only_dev, nullptr); |
| 394 | |
| 395 | EXPECT_CALL(system_, WriteConfigFile(_, _)).WillOnce(Return(true)); |
| 396 | EXPECT_CALL( |
| 397 | datapath_, |
| 398 | AddTunTap(StrEq("tun_nat64"), Eq(std::nullopt), |
| 399 | net_base::IPv4CIDR::CreateFromCIDRString("192.0.0.1/29"), |
| 400 | IsEmpty(), DeviceMode::kTun)) |
| 401 | .WillOnce(Return("tun_nat64")); |
| naoyatezuka | c8ebb46 | 2023-09-21 10:52:33 | [diff] [blame^] | 402 | EXPECT_CALL(datapath_, |
| 403 | ModifyClatAcceptRules(Iptables::Command::kA, StrEq("tun_nat64"))) |
| 404 | .WillOnce(Return(true)); |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 405 | EXPECT_CALL(datapath_, AddIPv6HostRoute(StrEq("tun_nat64"), |
| 406 | CIDRHasPrefix("2001:db8::/64"), |
| 407 | Eq(std::nullopt))) |
| 408 | .WillOnce(Return(true)); |
| 409 | EXPECT_CALL( |
| 410 | datapath_, |
| 411 | AddIPv6NeighborProxy(StrEq("v6only"), AddressHasPrefix("2001:db8::/64"))) |
| 412 | .WillOnce(Return(true)); |
| 413 | EXPECT_CALL(datapath_, AddIPv4RouteToTable(StrEq("tun_nat64"), |
| 414 | net_base::IPv4CIDR(), 249)) |
| 415 | .WillOnce(Return(true)); |
| 416 | // StartClat() is called. |
| 417 | target.OnShillDefaultLogicalDeviceChanged(&v6only_dev, &v4only_dev); |
| 418 | |
| 419 | EXPECT_CALL(datapath_, DeleteIPv4RouteFromTable(StrEq("tun_nat64"), |
| 420 | net_base::IPv4CIDR(), 249)); |
| 421 | EXPECT_CALL(datapath_, |
| 422 | RemoveIPv6NeighborProxy(StrEq("v6only"), |
| 423 | AddressHasPrefix("2001:db8::/64"))); |
| naoyatezuka | c8ebb46 | 2023-09-21 10:52:33 | [diff] [blame^] | 424 | EXPECT_CALL(datapath_, |
| 425 | ModifyClatAcceptRules(Iptables::Command::kD, StrEq("tun_nat64"))); |
| naoyatezuka | ca02c50 | 2023-09-05 06:53:43 | [diff] [blame] | 426 | EXPECT_CALL(datapath_, RemoveIPv6HostRoute(CIDRHasPrefix("2001:db8::/64"))); |
| 427 | EXPECT_CALL(datapath_, RemoveTunTap(StrEq("tun_nat64"), DeviceMode::kTun)); |
| 428 | // StopClat() is called. |
| 429 | target.OnShillDefaultLogicalDeviceChanged(&v4only_dev, &v6only_dev); |
| 430 | } |
| 431 | |
| 432 | } // namespace |
| naoyatezuka | 02db5c1 | 2023-08-23 01:46:11 | [diff] [blame] | 433 | } // namespace patchpanel |