blob: 844681d070cec8077626daa9bc9e7afa31fd51e2 [file] [log] [blame]
Lorenzo Colitti86a47982016-03-18 17:52:25 +09001/*
2 * Copyright 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * BandwidthControllerTest.cpp - unit tests for BandwidthController.cpp
17 */
18
19#include <string>
20#include <vector>
Lorenzo Colitti86a47982016-03-18 17:52:25 +090021
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +090022#include <inttypes.h>
Lorenzo Colittibbeaf9a2016-07-08 18:24:26 +090023#include <fcntl.h>
24#include <unistd.h>
25#include <sys/types.h>
26#include <sys/socket.h>
27
Lorenzo Colitti86a47982016-03-18 17:52:25 +090028#include <gtest/gtest.h>
29
Lorenzo Colitti13debb82016-03-27 17:46:30 +090030#include <android-base/strings.h>
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +090031#include <android-base/stringprintf.h>
Lorenzo Colitti13debb82016-03-27 17:46:30 +090032
Joel Scherpelz01cc5492017-06-16 10:45:14 +090033#include <netdutils/MockSyscalls.h>
Lorenzo Colitti86a47982016-03-18 17:52:25 +090034#include "BandwidthController.h"
Benedict Wongb9baf262017-12-03 15:43:08 -080035#include "Fwmark.h"
Lorenzo Colitti0f150552016-03-28 02:30:27 +090036#include "IptablesBaseTest.h"
Maciej Żenczykowskid9fc54b2022-06-15 01:04:03 -070037#include "mainline/XtBpfProgLocations.h"
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +090038#include "tun_interface.h"
39
Bernie Innocentia5161a02019-01-30 22:40:53 +090040using ::testing::_;
Joel Scherpelz01cc5492017-06-16 10:45:14 +090041using ::testing::ByMove;
42using ::testing::Invoke;
43using ::testing::Return;
44using ::testing::StrictMock;
Joel Scherpelz01cc5492017-06-16 10:45:14 +090045
Lorenzo Colitti48f83002017-07-06 15:06:04 +090046using android::base::Join;
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +090047using android::base::StringPrintf;
48using android::net::TunInterface;
Joel Scherpelz01cc5492017-06-16 10:45:14 +090049using android::netdutils::UniqueFile;
Bernie Innocentia5161a02019-01-30 22:40:53 +090050using android::netdutils::status::ok;
Lorenzo Colitti86a47982016-03-18 17:52:25 +090051
Lorenzo Colitti0f150552016-03-28 02:30:27 +090052class BandwidthControllerTest : public IptablesBaseTest {
Joel Scherpelz01cc5492017-06-16 10:45:14 +090053protected:
Lorenzo Colitti86a47982016-03-18 17:52:25 +090054 BandwidthControllerTest() {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +090055 BandwidthController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
Lorenzo Colitti86a47982016-03-18 17:52:25 +090056 }
57 BandwidthController mBw;
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +090058 TunInterface mTun;
59
60 void SetUp() {
61 ASSERT_EQ(0, mTun.init());
62 }
63
64 void TearDown() {
65 mTun.destroy();
66 }
Lorenzo Colittibbeaf9a2016-07-08 18:24:26 +090067
Luke Huangae038f82018-11-05 11:17:31 +090068 void expectSetupCommands(const std::string& expectedClean,
69 const std::string& expectedAccounting) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +090070 std::string expectedList =
71 "*filter\n"
72 "-S\n"
73 "COMMIT\n";
74
75 std::string expectedFlush =
Luke Huangae038f82018-11-05 11:17:31 +090076 "*filter\n"
77 ":bw_INPUT -\n"
78 ":bw_OUTPUT -\n"
79 ":bw_FORWARD -\n"
80 ":bw_happy_box -\n"
81 ":bw_penalty_box -\n"
82 ":bw_data_saver -\n"
83 ":bw_costly_shared -\n"
84 ":bw_global_alert -\n"
85 "COMMIT\n"
86 "*raw\n"
87 ":bw_raw_PREROUTING -\n"
88 "COMMIT\n"
89 "*mangle\n"
90 ":bw_mangle_POSTROUTING -\n"
91 "COMMIT\n";
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +090092
93 ExpectedIptablesCommands expected = {{ V4, expectedList }};
94 if (expectedClean.size()) {
95 expected.push_back({ V4V6, expectedClean });
96 }
97 expected.push_back({ V4V6, expectedFlush });
98 if (expectedAccounting.size()) {
99 expected.push_back({ V4V6, expectedAccounting });
100 }
101
102 expectIptablesRestoreCommands(expected);
103 }
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900104
105 using IptOp = BandwidthController::IptOp;
106
Luke Huangae038f82018-11-05 11:17:31 +0900107 int runIptablesAlertCmd(IptOp a, const char* b, int64_t c) {
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900108 return mBw.runIptablesAlertCmd(a, b, c);
109 }
110
Bernie Innocenti7e25ec02018-07-02 19:32:17 +0900111 int setCostlyAlert(const std::string& a, int64_t b, int64_t* c) {
Lorenzo Colitti38078222017-07-06 17:27:23 +0900112 return mBw.setCostlyAlert(a, b, c);
113 }
114
Bernie Innocenti7e25ec02018-07-02 19:32:17 +0900115 int removeCostlyAlert(const std::string& a, int64_t* b) { return mBw.removeCostlyAlert(a, b); }
Lorenzo Colitti38078222017-07-06 17:27:23 +0900116
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900117 void expectUpdateQuota(uint64_t quota) {
118 uintptr_t dummy;
119 FILE* dummyFile = reinterpret_cast<FILE*>(&dummy);
120
121 EXPECT_CALL(mSyscalls, fopen(_, _)).WillOnce(Return(ByMove(UniqueFile(dummyFile))));
122 EXPECT_CALL(mSyscalls, vfprintf(dummyFile, _, _))
123 .WillOnce(Invoke([quota](FILE*, const std::string&, va_list ap) {
124 EXPECT_EQ(quota, va_arg(ap, uint64_t));
125 return 0;
126 }));
127 EXPECT_CALL(mSyscalls, fclose(dummyFile)).WillOnce(Return(ok));
128 }
129
130 StrictMock<android::netdutils::ScopedMockSyscalls> mSyscalls;
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900131};
132
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900133TEST_F(BandwidthControllerTest, TestSetupIptablesHooks) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900134 // Pretend some bw_costly_shared_<iface> rules already exist...
135 addIptablesRestoreOutput(
136 "-P OUTPUT ACCEPT\n"
137 "-N bw_costly_rmnet_data0\n"
138 "-N bw_costly_shared\n"
139 "-N unrelated\n"
140 "-N bw_costly_rmnet_data7\n");
141
142 // ... and expect that they be flushed and deleted.
143 std::string expectedCleanCmds =
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900144 "*filter\n"
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900145 ":bw_costly_rmnet_data0 -\n"
146 "-X bw_costly_rmnet_data0\n"
147 ":bw_costly_rmnet_data7 -\n"
148 "-X bw_costly_rmnet_data7\n"
149 "COMMIT\n";
150
151 mBw.setupIptablesHooks();
152 expectSetupCommands(expectedCleanCmds, "");
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900153}
154
Benedict Wongb9baf262017-12-03 15:43:08 -0800155TEST_F(BandwidthControllerTest, TestCheckUidBillingMask) {
156 uint32_t uidBillingMask = Fwmark::getUidBillingMask();
157
158 // If mask is non-zero, and mask & mask-1 is equal to 0, then the mask is a power of two.
159 bool isPowerOfTwo = uidBillingMask && (uidBillingMask & (uidBillingMask - 1)) == 0;
160
161 // Must be exactly a power of two
162 EXPECT_TRUE(isPowerOfTwo);
163}
164
Patrick Rohr03e3f7b2020-12-29 16:09:33 +0100165TEST_F(BandwidthControllerTest, TestEnableBandwidthControl) {
166 // Pretend no bw_costly_shared_<iface> rules already exist...
167 addIptablesRestoreOutput(
168 "-P OUTPUT ACCEPT\n"
169 "-N bw_costly_shared\n"
170 "-N unrelated\n");
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900171
Patrick Rohr03e3f7b2020-12-29 16:09:33 +0100172 // ... so none are flushed or deleted.
173 // clang-format off
174 static const std::string expectedClean = "";
175 static const std::string expectedAccounting =
176 "*filter\n"
177 "-A bw_INPUT -j bw_global_alert\n"
178 "-A bw_INPUT -p esp -j RETURN\n"
179 "-A bw_INPUT -m mark --mark 0x100000/0x100000 -j RETURN\n"
180 "-A bw_INPUT -j MARK --or-mark 0x100000\n"
181 "-A bw_OUTPUT -j bw_global_alert\n"
182 "-A bw_costly_shared -j bw_penalty_box\n"
183 "-I bw_penalty_box -m bpf --object-pinned " XT_BPF_DENYLIST_PROG_PATH " -j REJECT\n"
184 "-A bw_penalty_box -j bw_happy_box\n"
185 "-A bw_happy_box -j bw_data_saver\n"
186 "-A bw_data_saver -j RETURN\n"
187 "-I bw_happy_box -m bpf --object-pinned " XT_BPF_ALLOWLIST_PROG_PATH " -j RETURN\n"
188 "COMMIT\n"
189 "*raw\n"
Hungming Chenba815952022-04-01 19:57:45 +0800190 "-A bw_raw_PREROUTING -m mark --mark 0xdeadc1a7 -j DROP\n"
Patrick Rohr03e3f7b2020-12-29 16:09:33 +0100191 "-A bw_raw_PREROUTING -i ipsec+ -j RETURN\n"
192 "-A bw_raw_PREROUTING -m policy --pol ipsec --dir in -j RETURN\n"
193 "-A bw_raw_PREROUTING -m bpf --object-pinned " XT_BPF_INGRESS_PROG_PATH "\n"
194 "COMMIT\n"
195 "*mangle\n"
196 "-A bw_mangle_POSTROUTING -o ipsec+ -j RETURN\n"
197 "-A bw_mangle_POSTROUTING -m policy --pol ipsec --dir out -j RETURN\n"
198 "-A bw_mangle_POSTROUTING -j MARK --set-mark 0x0/0x100000\n"
Patrick Rohr03e3f7b2020-12-29 16:09:33 +0100199 "-A bw_mangle_POSTROUTING -m bpf --object-pinned " XT_BPF_EGRESS_PROG_PATH "\n"
200 "COMMIT\n";
201 // clang-format on
202
203 mBw.enableBandwidthControl();
204 expectSetupCommands(expectedClean, expectedAccounting);
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900205}
206
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900207TEST_F(BandwidthControllerTest, TestDisableBandwidthControl) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900208 // Pretend some bw_costly_shared_<iface> rules already exist...
209 addIptablesRestoreOutput(
210 "-P OUTPUT ACCEPT\n"
211 "-N bw_costly_rmnet_data0\n"
212 "-N bw_costly_shared\n"
213 "-N unrelated\n"
214 "-N bw_costly_rmnet_data7\n");
215
216 // ... and expect that they be flushed.
217 std::string expectedCleanCmds =
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900218 "*filter\n"
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900219 ":bw_costly_rmnet_data0 -\n"
220 ":bw_costly_rmnet_data7 -\n"
221 "COMMIT\n";
222
223 mBw.disableBandwidthControl();
224 expectSetupCommands(expectedCleanCmds, "");
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900225}
226
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900227TEST_F(BandwidthControllerTest, TestEnableDataSaver) {
228 mBw.enableDataSaver(true);
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900229 std::string expected4 =
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800230 "*filter\n"
231 ":bw_data_saver -\n"
232 "-A bw_data_saver -j REJECT\n"
233 "COMMIT\n";
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900234 std::string expected6 =
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800235 "*filter\n"
236 ":bw_data_saver -\n"
237 "-A bw_data_saver -p icmpv6 --icmpv6-type packet-too-big -j RETURN\n"
238 "-A bw_data_saver -p icmpv6 --icmpv6-type router-solicitation -j RETURN\n"
239 "-A bw_data_saver -p icmpv6 --icmpv6-type router-advertisement -j RETURN\n"
240 "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-solicitation -j RETURN\n"
241 "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-advertisement -j RETURN\n"
242 "-A bw_data_saver -p icmpv6 --icmpv6-type redirect -j RETURN\n"
243 "-A bw_data_saver -j REJECT\n"
244 "COMMIT\n";
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900245 expectIptablesRestoreCommands({
246 {V4, expected4},
247 {V6, expected6},
248 });
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900249
250 mBw.enableDataSaver(false);
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900251 std::string expected = {
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800252 "*filter\n"
253 ":bw_data_saver -\n"
254 "-A bw_data_saver -j RETURN\n"
255 "COMMIT\n"};
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900256 expectIptablesRestoreCommands({
257 {V4, expected},
258 {V6, expected},
259 });
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900260}
Lorenzo Colittibbeaf9a2016-07-08 18:24:26 +0900261
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900262const std::vector<std::string> makeInterfaceQuotaCommands(const std::string& iface, int ruleIndex,
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900263 int64_t quota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900264 const std::string chain = "bw_costly_" + iface;
265 const char* c_chain = chain.c_str();
266 const char* c_iface = iface.c_str();
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900267 std::vector<std::string> cmds = {
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800268 "*filter",
269 StringPrintf(":%s -", c_chain),
270 StringPrintf("-A %s -j bw_penalty_box", c_chain),
271 StringPrintf("-I bw_INPUT %d -i %s -j %s", ruleIndex, c_iface, c_chain),
272 StringPrintf("-I bw_OUTPUT %d -o %s -j %s", ruleIndex, c_iface, c_chain),
273 StringPrintf("-A bw_FORWARD -i %s -j %s", c_iface, c_chain),
274 StringPrintf("-A bw_FORWARD -o %s -j %s", c_iface, c_chain),
275 StringPrintf("-A %s -m quota2 ! --quota %" PRIu64 " --name %s -j REJECT", c_chain,
276 quota, c_iface),
277 "COMMIT\n",
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900278 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900279 return {Join(cmds, "\n")};
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900280}
281
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900282const std::vector<std::string> removeInterfaceQuotaCommands(const std::string& iface) {
283 const std::string chain = "bw_costly_" + iface;
284 const char* c_chain = chain.c_str();
285 const char* c_iface = iface.c_str();
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900286 std::vector<std::string> cmds = {
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800287 "*filter",
288 StringPrintf("-D bw_INPUT -i %s -j %s", c_iface, c_chain),
289 StringPrintf("-D bw_OUTPUT -o %s -j %s", c_iface, c_chain),
290 StringPrintf("-D bw_FORWARD -i %s -j %s", c_iface, c_chain),
291 StringPrintf("-D bw_FORWARD -o %s -j %s", c_iface, c_chain),
292 StringPrintf("-F %s", c_chain),
293 StringPrintf("-X %s", c_chain),
294 "COMMIT\n",
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900295 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900296 return {Join(cmds, "\n")};
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900297}
298
299TEST_F(BandwidthControllerTest, TestSetInterfaceQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900300 constexpr uint64_t kOldQuota = 123456;
301 const std::string iface = mTun.name();
302 std::vector<std::string> expected = makeInterfaceQuotaCommands(iface, 1, kOldQuota);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900303
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900304 EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kOldQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900305 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900306
307 constexpr uint64_t kNewQuota = kOldQuota + 1;
308 expected = {};
309 expectUpdateQuota(kNewQuota);
310 EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kNewQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900311 expectIptablesRestoreCommands(expected);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900312
313 expected = removeInterfaceQuotaCommands(iface);
314 EXPECT_EQ(0, mBw.removeInterfaceQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900315 expectIptablesRestoreCommands(expected);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900316}
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900317
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900318const std::vector<std::string> makeInterfaceSharedQuotaCommands(const std::string& iface,
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900319 int ruleIndex, int64_t quota,
320 bool insertQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900321 const std::string chain = "bw_costly_shared";
322 const char* c_chain = chain.c_str();
323 const char* c_iface = iface.c_str();
324 std::vector<std::string> cmds = {
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800325 "*filter",
326 StringPrintf("-I bw_INPUT %d -i %s -j %s", ruleIndex, c_iface, c_chain),
327 StringPrintf("-I bw_OUTPUT %d -o %s -j %s", ruleIndex, c_iface, c_chain),
328 StringPrintf("-A bw_FORWARD -i %s -j %s", c_iface, c_chain),
329 StringPrintf("-A bw_FORWARD -o %s -j %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900330 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900331 if (insertQuota) {
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800332 cmds.push_back(StringPrintf("-I %s -m quota2 ! --quota %" PRIu64 " --name shared -j REJECT",
333 c_chain, quota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900334 }
335 cmds.push_back("COMMIT\n");
336 return {Join(cmds, "\n")};
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900337}
338
339const std::vector<std::string> removeInterfaceSharedQuotaCommands(const std::string& iface,
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900340 int64_t quota, bool deleteQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900341 const std::string chain = "bw_costly_shared";
342 const char* c_chain = chain.c_str();
343 const char* c_iface = iface.c_str();
344 std::vector<std::string> cmds = {
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800345 "*filter",
346 StringPrintf("-D bw_INPUT -i %s -j %s", c_iface, c_chain),
347 StringPrintf("-D bw_OUTPUT -o %s -j %s", c_iface, c_chain),
348 StringPrintf("-D bw_FORWARD -i %s -j %s", c_iface, c_chain),
349 StringPrintf("-D bw_FORWARD -o %s -j %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900350 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900351 if (deleteQuota) {
Maciej Żenczykowskidec83c72019-12-24 15:27:14 -0800352 cmds.push_back(StringPrintf("-D %s -m quota2 ! --quota %" PRIu64 " --name shared -j REJECT",
353 c_chain, quota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900354 }
355 cmds.push_back("COMMIT\n");
356 return {Join(cmds, "\n")};
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900357}
358
359TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaDuplicate) {
360 constexpr uint64_t kQuota = 123456;
361 const std::string iface = mTun.name();
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900362 std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, 123456, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900363 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900364 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900365
366 expected = {};
367 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900368 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900369
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900370 expected = removeInterfaceSharedQuotaCommands(iface, kQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900371 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900372 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900373}
374
375TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaUpdate) {
376 constexpr uint64_t kOldQuota = 123456;
377 const std::string iface = mTun.name();
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900378 std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, kOldQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900379 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kOldQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900380 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900381
382 constexpr uint64_t kNewQuota = kOldQuota + 1;
383 expected = {};
384 expectUpdateQuota(kNewQuota);
385 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kNewQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900386 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900387
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900388 expected = removeInterfaceSharedQuotaCommands(iface, kNewQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900389 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900390 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900391}
392
393TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaTwoInterfaces) {
394 constexpr uint64_t kQuota = 123456;
395 const std::vector<std::string> ifaces{
396 {"a" + mTun.name()},
397 {"b" + mTun.name()},
398 };
399
400 for (const auto& iface : ifaces) {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900401 // Quota rule is only added when the total number of
402 // interfaces transitions from 0 -> 1.
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900403 bool first = (iface == ifaces[0]);
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900404 auto expected = makeInterfaceSharedQuotaCommands(iface, 1, kQuota, first);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900405 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900406 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900407 }
408
409 for (const auto& iface : ifaces) {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900410 // Quota rule is only removed when the total number of
411 // interfaces transitions from 1 -> 0.
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900412 bool last = (iface == ifaces[1]);
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900413 auto expected = removeInterfaceSharedQuotaCommands(iface, kQuota, last);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900414 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900415 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900416 }
417}
418
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900419TEST_F(BandwidthControllerTest, IptablesAlertCmd) {
420 std::vector<std::string> expected = {
Luke Huangae038f82018-11-05 11:17:31 +0900421 "*filter\n"
422 "-I bw_global_alert -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
423 "COMMIT\n"};
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900424 EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900425 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900426
427 expected = {
Luke Huangae038f82018-11-05 11:17:31 +0900428 "*filter\n"
429 "-D bw_global_alert -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
430 "COMMIT\n"};
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900431 EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900432 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900433}
434
Lorenzo Colitti38078222017-07-06 17:27:23 +0900435TEST_F(BandwidthControllerTest, CostlyAlert) {
436 const int64_t kQuota = 123456;
437 int64_t alertBytes = 0;
438
439 std::vector<std::string> expected = {
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900440 "*filter\n"
441 "-A bw_costly_shared -m quota2 ! --quota 123456 --name sharedAlert\n"
442 "COMMIT\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900443 };
444 EXPECT_EQ(0, setCostlyAlert("shared", kQuota, &alertBytes));
445 EXPECT_EQ(kQuota, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900446 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900447
448 expected = {};
449 expectUpdateQuota(kQuota);
450 EXPECT_EQ(0, setCostlyAlert("shared", kQuota + 1, &alertBytes));
451 EXPECT_EQ(kQuota + 1, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900452 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900453
454 expected = {
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900455 "*filter\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900456 "-D bw_costly_shared -m quota2 ! --quota 123457 --name sharedAlert\n"
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900457 "COMMIT\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900458 };
459 EXPECT_EQ(0, removeCostlyAlert("shared", &alertBytes));
460 EXPECT_EQ(0, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900461 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900462}
463