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