blob: d4a1a7d3d8a4451a153f54bd7eb6eac9490a143a [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"
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +090037#include "tun_interface.h"
38
Joel Scherpelz01cc5492017-06-16 10:45:14 +090039using ::testing::ByMove;
40using ::testing::Invoke;
41using ::testing::Return;
42using ::testing::StrictMock;
43using ::testing::Test;
44using ::testing::_;
45
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::status::ok;
50using android::netdutils::UniqueFile;
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
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +090068 void expectSetupCommands(const std::string& expectedClean, std::string expectedAccounting) {
69 std::string expectedList =
70 "*filter\n"
71 "-S\n"
72 "COMMIT\n";
73
74 std::string expectedFlush =
75 "*filter\n"
76 ":bw_INPUT -\n"
77 ":bw_OUTPUT -\n"
78 ":bw_FORWARD -\n"
79 ":bw_happy_box -\n"
80 ":bw_penalty_box -\n"
81 ":bw_data_saver -\n"
82 ":bw_costly_shared -\n"
83 "COMMIT\n"
84 "*raw\n"
85 ":bw_raw_PREROUTING -\n"
86 "COMMIT\n"
87 "*mangle\n"
88 ":bw_mangle_POSTROUTING -\n"
89 "COMMIT\n";
90
91 ExpectedIptablesCommands expected = {{ V4, expectedList }};
92 if (expectedClean.size()) {
93 expected.push_back({ V4V6, expectedClean });
94 }
95 expected.push_back({ V4V6, expectedFlush });
96 if (expectedAccounting.size()) {
97 expected.push_back({ V4V6, expectedAccounting });
98 }
99
100 expectIptablesRestoreCommands(expected);
101 }
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900102
103 using IptOp = BandwidthController::IptOp;
104
105 int runIptablesAlertCmd(IptOp a, const char *b, int64_t c) {
106 return mBw.runIptablesAlertCmd(a, b, c);
107 }
108
109 int runIptablesAlertFwdCmd(IptOp a, const char *b, int64_t c) {
110 return mBw.runIptablesAlertFwdCmd(a, b, c);
111 }
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900112
Lorenzo Colitti38078222017-07-06 17:27:23 +0900113 int setCostlyAlert(const std::string a, int64_t b, int64_t *c) {
114 return mBw.setCostlyAlert(a, b, c);
115 }
116
117 int removeCostlyAlert(const std::string a, int64_t *b) {
118 return mBw.removeCostlyAlert(a, b);
119 }
120
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900121 void expectUpdateQuota(uint64_t quota) {
122 uintptr_t dummy;
123 FILE* dummyFile = reinterpret_cast<FILE*>(&dummy);
124
125 EXPECT_CALL(mSyscalls, fopen(_, _)).WillOnce(Return(ByMove(UniqueFile(dummyFile))));
126 EXPECT_CALL(mSyscalls, vfprintf(dummyFile, _, _))
127 .WillOnce(Invoke([quota](FILE*, const std::string&, va_list ap) {
128 EXPECT_EQ(quota, va_arg(ap, uint64_t));
129 return 0;
130 }));
131 EXPECT_CALL(mSyscalls, fclose(dummyFile)).WillOnce(Return(ok));
132 }
133
134 StrictMock<android::netdutils::ScopedMockSyscalls> mSyscalls;
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900135};
136
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900137TEST_F(BandwidthControllerTest, TestSetupIptablesHooks) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900138 // Pretend some bw_costly_shared_<iface> rules already exist...
139 addIptablesRestoreOutput(
140 "-P OUTPUT ACCEPT\n"
141 "-N bw_costly_rmnet_data0\n"
142 "-N bw_costly_shared\n"
143 "-N unrelated\n"
144 "-N bw_costly_rmnet_data7\n");
145
146 // ... and expect that they be flushed and deleted.
147 std::string expectedCleanCmds =
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900148 "*filter\n"
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900149 ":bw_costly_rmnet_data0 -\n"
150 "-X bw_costly_rmnet_data0\n"
151 ":bw_costly_rmnet_data7 -\n"
152 "-X bw_costly_rmnet_data7\n"
153 "COMMIT\n";
154
155 mBw.setupIptablesHooks();
156 expectSetupCommands(expectedCleanCmds, "");
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900157}
158
Benedict Wongb9baf262017-12-03 15:43:08 -0800159TEST_F(BandwidthControllerTest, TestCheckUidBillingMask) {
160 uint32_t uidBillingMask = Fwmark::getUidBillingMask();
161
162 // If mask is non-zero, and mask & mask-1 is equal to 0, then the mask is a power of two.
163 bool isPowerOfTwo = uidBillingMask && (uidBillingMask & (uidBillingMask - 1)) == 0;
164
165 // Must be exactly a power of two
166 EXPECT_TRUE(isPowerOfTwo);
167}
168
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900169TEST_F(BandwidthControllerTest, TestEnableBandwidthControl) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900170 // Pretend no bw_costly_shared_<iface> rules already exist...
171 addIptablesRestoreOutput(
172 "-P OUTPUT ACCEPT\n"
173 "-N bw_costly_shared\n"
174 "-N unrelated\n");
175
176 // ... so none are flushed or deleted.
177 std::string expectedClean = "";
178
Benedict Wongb9baf262017-12-03 15:43:08 -0800179 uint32_t uidBillingMask = Fwmark::getUidBillingMask();
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900180 std::string expectedAccounting =
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900181 "*filter\n"
Benedict Wongb9baf262017-12-03 15:43:08 -0800182 "-A bw_INPUT -p esp -j RETURN\n" +
183 StringPrintf("-A bw_INPUT -m mark --mark 0x%x/0x%x -j RETURN\n",
184 uidBillingMask, uidBillingMask) +
185 "-A bw_INPUT -m owner --socket-exists\n" +
186 StringPrintf("-A bw_INPUT -j MARK --or-mark 0x%x\n", uidBillingMask) +
187 "-A bw_OUTPUT -o " IPSEC_IFACE_PREFIX "+ -j RETURN\n"
188 "-A bw_OUTPUT -m policy --pol ipsec --dir out -j RETURN\n"
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900189 "-A bw_OUTPUT -m owner --socket-exists\n"
190 "-A bw_costly_shared --jump bw_penalty_box\n"
191 "-A bw_penalty_box --jump bw_happy_box\n"
192 "-A bw_happy_box --jump bw_data_saver\n"
193 "-A bw_data_saver -j RETURN\n"
194 "-I bw_happy_box -m owner --uid-owner 0-9999 --jump RETURN\n"
195 "COMMIT\n"
196 "*raw\n"
Benedict Wongb9baf262017-12-03 15:43:08 -0800197 "-A bw_raw_PREROUTING -i " IPSEC_IFACE_PREFIX "+ -j RETURN\n"
198 "-A bw_raw_PREROUTING -m policy --pol ipsec --dir in -j RETURN\n"
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900199 "-A bw_raw_PREROUTING -m owner --socket-exists\n"
200 "COMMIT\n"
201 "*mangle\n"
Benedict Wongb9baf262017-12-03 15:43:08 -0800202 "-A bw_mangle_POSTROUTING -o " IPSEC_IFACE_PREFIX "+ -j RETURN\n"
203 "-A bw_mangle_POSTROUTING -m policy --pol ipsec --dir out -j RETURN\n"
204 "-A bw_mangle_POSTROUTING -m owner --socket-exists\n" +
205 StringPrintf("-A bw_mangle_POSTROUTING -j MARK --set-mark 0x0/0x%x\n", uidBillingMask) +
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900206 "COMMIT\n";
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900207
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900208 mBw.enableBandwidthControl(false);
209 expectSetupCommands(expectedClean, expectedAccounting);
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900210}
211
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900212TEST_F(BandwidthControllerTest, TestDisableBandwidthControl) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900213 // Pretend some bw_costly_shared_<iface> rules already exist...
214 addIptablesRestoreOutput(
215 "-P OUTPUT ACCEPT\n"
216 "-N bw_costly_rmnet_data0\n"
217 "-N bw_costly_shared\n"
218 "-N unrelated\n"
219 "-N bw_costly_rmnet_data7\n");
220
221 // ... and expect that they be flushed.
222 std::string expectedCleanCmds =
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900223 "*filter\n"
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900224 ":bw_costly_rmnet_data0 -\n"
225 ":bw_costly_rmnet_data7 -\n"
226 "COMMIT\n";
227
228 mBw.disableBandwidthControl();
229 expectSetupCommands(expectedCleanCmds, "");
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900230}
231
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900232TEST_F(BandwidthControllerTest, TestEnableDataSaver) {
233 mBw.enableDataSaver(true);
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900234 std::string expected4 =
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900235 "*filter\n"
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900236 ":bw_data_saver -\n"
237 "-A bw_data_saver --jump REJECT\n"
238 "COMMIT\n";
239 std::string expected6 =
240 "*filter\n"
241 ":bw_data_saver -\n"
242 "-A bw_data_saver -p icmpv6 --icmpv6-type packet-too-big -j RETURN\n"
243 "-A bw_data_saver -p icmpv6 --icmpv6-type router-solicitation -j RETURN\n"
244 "-A bw_data_saver -p icmpv6 --icmpv6-type router-advertisement -j RETURN\n"
245 "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-solicitation -j RETURN\n"
246 "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-advertisement -j RETURN\n"
247 "-A bw_data_saver -p icmpv6 --icmpv6-type redirect -j RETURN\n"
248 "-A bw_data_saver --jump REJECT\n"
249 "COMMIT\n";
250 expectIptablesRestoreCommands({
251 {V4, expected4},
252 {V6, expected6},
253 });
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900254
255 mBw.enableDataSaver(false);
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900256 std::string expected = {
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900257 "*filter\n"
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900258 ":bw_data_saver -\n"
259 "-A bw_data_saver --jump RETURN\n"
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900260 "COMMIT\n"
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900261 };
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900262 expectIptablesRestoreCommands({
263 {V4, expected},
264 {V6, expected},
265 });
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900266}
Lorenzo Colittibbeaf9a2016-07-08 18:24:26 +0900267
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900268const std::vector<std::string> makeInterfaceQuotaCommands(const std::string& iface, int ruleIndex,
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900269 int64_t quota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900270 const std::string chain = "bw_costly_" + iface;
271 const char* c_chain = chain.c_str();
272 const char* c_iface = iface.c_str();
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900273 std::vector<std::string> cmds = {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900274 "*filter",
275 StringPrintf(":%s -", c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900276 StringPrintf("-A %s -j bw_penalty_box", c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900277 StringPrintf("-I bw_INPUT %d -i %s --jump %s", ruleIndex, c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900278 StringPrintf("-I bw_OUTPUT %d -o %s --jump %s", ruleIndex, c_iface, c_chain),
Erik Kline51eb3242017-09-20 18:30:47 +0900279 StringPrintf("-A bw_FORWARD -i %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900280 StringPrintf("-A bw_FORWARD -o %s --jump %s", c_iface, c_chain),
281 StringPrintf("-A %s -m quota2 ! --quota %" PRIu64 " --name %s --jump REJECT", c_chain,
282 quota, c_iface),
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900283 "COMMIT\n",
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900284 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900285 return {Join(cmds, "\n")};
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900286}
287
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900288const std::vector<std::string> removeInterfaceQuotaCommands(const std::string& iface) {
289 const std::string chain = "bw_costly_" + iface;
290 const char* c_chain = chain.c_str();
291 const char* c_iface = iface.c_str();
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900292 std::vector<std::string> cmds = {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900293 "*filter",
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900294 StringPrintf("-D bw_INPUT -i %s --jump %s", c_iface, c_chain),
295 StringPrintf("-D bw_OUTPUT -o %s --jump %s", c_iface, c_chain),
Erik Kline51eb3242017-09-20 18:30:47 +0900296 StringPrintf("-D bw_FORWARD -i %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900297 StringPrintf("-D bw_FORWARD -o %s --jump %s", c_iface, c_chain),
298 StringPrintf("-F %s", c_chain),
299 StringPrintf("-X %s", c_chain),
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900300 "COMMIT\n",
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900301 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900302 return {Join(cmds, "\n")};
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900303}
304
305TEST_F(BandwidthControllerTest, TestSetInterfaceQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900306 constexpr uint64_t kOldQuota = 123456;
307 const std::string iface = mTun.name();
308 std::vector<std::string> expected = makeInterfaceQuotaCommands(iface, 1, kOldQuota);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900309
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900310 EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kOldQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900311 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900312
313 constexpr uint64_t kNewQuota = kOldQuota + 1;
314 expected = {};
315 expectUpdateQuota(kNewQuota);
316 EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kNewQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900317 expectIptablesRestoreCommands(expected);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900318
319 expected = removeInterfaceQuotaCommands(iface);
320 EXPECT_EQ(0, mBw.removeInterfaceQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900321 expectIptablesRestoreCommands(expected);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900322}
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900323
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900324const std::vector<std::string> makeInterfaceSharedQuotaCommands(const std::string& iface,
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900325 int ruleIndex, int64_t quota,
326 bool insertQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900327 const std::string chain = "bw_costly_shared";
328 const char* c_chain = chain.c_str();
329 const char* c_iface = iface.c_str();
330 std::vector<std::string> cmds = {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900331 "*filter",
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900332 StringPrintf("-I bw_INPUT %d -i %s --jump %s", ruleIndex, c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900333 StringPrintf("-I bw_OUTPUT %d -o %s --jump %s", ruleIndex, c_iface, c_chain),
Erik Kline51eb3242017-09-20 18:30:47 +0900334 StringPrintf("-A bw_FORWARD -i %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900335 StringPrintf("-A bw_FORWARD -o %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900336 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900337 if (insertQuota) {
338 cmds.push_back(StringPrintf(
339 "-I %s -m quota2 ! --quota %" PRIu64 " --name shared --jump REJECT", c_chain, quota));
340 }
341 cmds.push_back("COMMIT\n");
342 return {Join(cmds, "\n")};
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900343}
344
345const std::vector<std::string> removeInterfaceSharedQuotaCommands(const std::string& iface,
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900346 int64_t quota, bool deleteQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900347 const std::string chain = "bw_costly_shared";
348 const char* c_chain = chain.c_str();
349 const char* c_iface = iface.c_str();
350 std::vector<std::string> cmds = {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900351 "*filter",
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900352 StringPrintf("-D bw_INPUT -i %s --jump %s", c_iface, c_chain),
353 StringPrintf("-D bw_OUTPUT -o %s --jump %s", c_iface, c_chain),
Erik Kline51eb3242017-09-20 18:30:47 +0900354 StringPrintf("-D bw_FORWARD -i %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900355 StringPrintf("-D bw_FORWARD -o %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900356 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900357 if (deleteQuota) {
358 cmds.push_back(StringPrintf(
359 "-D %s -m quota2 ! --quota %" PRIu64 " --name shared --jump REJECT", c_chain, quota));
360 }
361 cmds.push_back("COMMIT\n");
362 return {Join(cmds, "\n")};
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900363}
364
365TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaDuplicate) {
366 constexpr uint64_t kQuota = 123456;
367 const std::string iface = mTun.name();
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900368 std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, 123456, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900369 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900370 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900371
372 expected = {};
373 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900374 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900375
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900376 expected = removeInterfaceSharedQuotaCommands(iface, kQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900377 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900378 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900379}
380
381TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaUpdate) {
382 constexpr uint64_t kOldQuota = 123456;
383 const std::string iface = mTun.name();
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900384 std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, kOldQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900385 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kOldQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900386 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900387
388 constexpr uint64_t kNewQuota = kOldQuota + 1;
389 expected = {};
390 expectUpdateQuota(kNewQuota);
391 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kNewQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900392 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900393
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900394 expected = removeInterfaceSharedQuotaCommands(iface, kNewQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900395 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900396 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900397}
398
399TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaTwoInterfaces) {
400 constexpr uint64_t kQuota = 123456;
401 const std::vector<std::string> ifaces{
402 {"a" + mTun.name()},
403 {"b" + mTun.name()},
404 };
405
406 for (const auto& iface : ifaces) {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900407 // Quota rule is only added when the total number of
408 // interfaces transitions from 0 -> 1.
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900409 bool first = (iface == ifaces[0]);
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900410 auto expected = makeInterfaceSharedQuotaCommands(iface, 1, kQuota, first);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900411 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900412 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900413 }
414
415 for (const auto& iface : ifaces) {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900416 // Quota rule is only removed when the total number of
417 // interfaces transitions from 1 -> 0.
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900418 bool last = (iface == ifaces[1]);
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900419 auto expected = removeInterfaceSharedQuotaCommands(iface, kQuota, last);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900420 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900421 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900422 }
423}
424
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900425TEST_F(BandwidthControllerTest, IptablesAlertCmd) {
426 std::vector<std::string> expected = {
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900427 "*filter\n"
428 "-I bw_INPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
429 "-I bw_OUTPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
430 "COMMIT\n"
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900431 };
432 EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900433 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900434
435 expected = {
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900436 "*filter\n"
437 "-D bw_INPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
438 "-D bw_OUTPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
439 "COMMIT\n"
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900440 };
441 EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900442 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900443}
444
445TEST_F(BandwidthControllerTest, IptablesAlertFwdCmd) {
446 std::vector<std::string> expected = {
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900447 "*filter\n"
448 "-I bw_FORWARD -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
449 "COMMIT\n"
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900450 };
451 EXPECT_EQ(0, runIptablesAlertFwdCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900452 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900453
454 expected = {
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900455 "*filter\n"
456 "-D bw_FORWARD -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
457 "COMMIT\n"
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900458 };
459 EXPECT_EQ(0, runIptablesAlertFwdCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900460 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900461}
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900462
Lorenzo Colitti38078222017-07-06 17:27:23 +0900463TEST_F(BandwidthControllerTest, CostlyAlert) {
464 const int64_t kQuota = 123456;
465 int64_t alertBytes = 0;
466
467 std::vector<std::string> expected = {
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900468 "*filter\n"
469 "-A bw_costly_shared -m quota2 ! --quota 123456 --name sharedAlert\n"
470 "COMMIT\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900471 };
472 EXPECT_EQ(0, setCostlyAlert("shared", kQuota, &alertBytes));
473 EXPECT_EQ(kQuota, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900474 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900475
476 expected = {};
477 expectUpdateQuota(kQuota);
478 EXPECT_EQ(0, setCostlyAlert("shared", kQuota + 1, &alertBytes));
479 EXPECT_EQ(kQuota + 1, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900480 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900481
482 expected = {
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900483 "*filter\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900484 "-D bw_costly_shared -m quota2 ! --quota 123457 --name sharedAlert\n"
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900485 "COMMIT\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900486 };
487 EXPECT_EQ(0, removeCostlyAlert("shared", &alertBytes));
488 EXPECT_EQ(0, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900489 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900490}
491
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900492TEST_F(BandwidthControllerTest, ManipulateSpecialApps) {
493 std::vector<const char *> appUids = { "1000", "1001", "10012" };
494
495 std::vector<std::string> expected = {
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900496 "*filter\n"
497 "-I bw_happy_box -m owner --uid-owner 1000 --jump RETURN\n"
498 "-I bw_happy_box -m owner --uid-owner 1001 --jump RETURN\n"
499 "-I bw_happy_box -m owner --uid-owner 10012 --jump RETURN\n"
500 "COMMIT\n"
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900501 };
502 EXPECT_EQ(0, mBw.addNiceApps(appUids.size(), const_cast<char**>(&appUids[0])));
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900503 expectIptablesRestoreCommands(expected);
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900504
505 expected = {
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900506 "*filter\n"
507 "-D bw_penalty_box -m owner --uid-owner 1000 --jump REJECT\n"
508 "-D bw_penalty_box -m owner --uid-owner 1001 --jump REJECT\n"
509 "-D bw_penalty_box -m owner --uid-owner 10012 --jump REJECT\n"
510 "COMMIT\n"
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900511 };
512 EXPECT_EQ(0, mBw.removeNaughtyApps(appUids.size(), const_cast<char**>(&appUids[0])));
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900513 expectIptablesRestoreCommands(expected);
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900514}