blob: 027e90b61998a4cf422cb3055cddcb04f6d88b2b [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"
Lorenzo Colitti0f150552016-03-28 02:30:27 +090035#include "IptablesBaseTest.h"
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +090036#include "tun_interface.h"
37
Joel Scherpelz01cc5492017-06-16 10:45:14 +090038using ::testing::ByMove;
39using ::testing::Invoke;
40using ::testing::Return;
41using ::testing::StrictMock;
42using ::testing::Test;
43using ::testing::_;
44
Lorenzo Colitti48f83002017-07-06 15:06:04 +090045using android::base::Join;
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +090046using android::base::StringPrintf;
47using android::net::TunInterface;
Joel Scherpelz01cc5492017-06-16 10:45:14 +090048using android::netdutils::status::ok;
49using android::netdutils::UniqueFile;
Lorenzo Colitti86a47982016-03-18 17:52:25 +090050
Lorenzo Colitti0f150552016-03-28 02:30:27 +090051class BandwidthControllerTest : public IptablesBaseTest {
Joel Scherpelz01cc5492017-06-16 10:45:14 +090052protected:
Lorenzo Colitti86a47982016-03-18 17:52:25 +090053 BandwidthControllerTest() {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +090054 BandwidthController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
Lorenzo Colitti86a47982016-03-18 17:52:25 +090055 }
56 BandwidthController mBw;
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +090057 TunInterface mTun;
58
59 void SetUp() {
60 ASSERT_EQ(0, mTun.init());
61 }
62
63 void TearDown() {
64 mTun.destroy();
65 }
Lorenzo Colittibbeaf9a2016-07-08 18:24:26 +090066
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +090067 void expectSetupCommands(const std::string& expectedClean, std::string expectedAccounting) {
68 std::string expectedList =
69 "*filter\n"
70 "-S\n"
71 "COMMIT\n";
72
73 std::string expectedFlush =
74 "*filter\n"
75 ":bw_INPUT -\n"
76 ":bw_OUTPUT -\n"
77 ":bw_FORWARD -\n"
78 ":bw_happy_box -\n"
79 ":bw_penalty_box -\n"
80 ":bw_data_saver -\n"
81 ":bw_costly_shared -\n"
82 "COMMIT\n"
83 "*raw\n"
84 ":bw_raw_PREROUTING -\n"
85 "COMMIT\n"
86 "*mangle\n"
87 ":bw_mangle_POSTROUTING -\n"
88 "COMMIT\n";
89
90 ExpectedIptablesCommands expected = {{ V4, expectedList }};
91 if (expectedClean.size()) {
92 expected.push_back({ V4V6, expectedClean });
93 }
94 expected.push_back({ V4V6, expectedFlush });
95 if (expectedAccounting.size()) {
96 expected.push_back({ V4V6, expectedAccounting });
97 }
98
99 expectIptablesRestoreCommands(expected);
100 }
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900101
102 using IptOp = BandwidthController::IptOp;
103
104 int runIptablesAlertCmd(IptOp a, const char *b, int64_t c) {
105 return mBw.runIptablesAlertCmd(a, b, c);
106 }
107
108 int runIptablesAlertFwdCmd(IptOp a, const char *b, int64_t c) {
109 return mBw.runIptablesAlertFwdCmd(a, b, c);
110 }
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900111
Lorenzo Colitti38078222017-07-06 17:27:23 +0900112 int setCostlyAlert(const std::string a, int64_t b, int64_t *c) {
113 return mBw.setCostlyAlert(a, b, c);
114 }
115
116 int removeCostlyAlert(const std::string a, int64_t *b) {
117 return mBw.removeCostlyAlert(a, b);
118 }
119
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900120 void expectUpdateQuota(uint64_t quota) {
121 uintptr_t dummy;
122 FILE* dummyFile = reinterpret_cast<FILE*>(&dummy);
123
124 EXPECT_CALL(mSyscalls, fopen(_, _)).WillOnce(Return(ByMove(UniqueFile(dummyFile))));
125 EXPECT_CALL(mSyscalls, vfprintf(dummyFile, _, _))
126 .WillOnce(Invoke([quota](FILE*, const std::string&, va_list ap) {
127 EXPECT_EQ(quota, va_arg(ap, uint64_t));
128 return 0;
129 }));
130 EXPECT_CALL(mSyscalls, fclose(dummyFile)).WillOnce(Return(ok));
131 }
132
133 StrictMock<android::netdutils::ScopedMockSyscalls> mSyscalls;
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900134};
135
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900136TEST_F(BandwidthControllerTest, TestSetupIptablesHooks) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900137 // Pretend some bw_costly_shared_<iface> rules already exist...
138 addIptablesRestoreOutput(
139 "-P OUTPUT ACCEPT\n"
140 "-N bw_costly_rmnet_data0\n"
141 "-N bw_costly_shared\n"
142 "-N unrelated\n"
143 "-N bw_costly_rmnet_data7\n");
144
145 // ... and expect that they be flushed and deleted.
146 std::string expectedCleanCmds =
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900147 "*filter\n"
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900148 ":bw_costly_rmnet_data0 -\n"
149 "-X bw_costly_rmnet_data0\n"
150 ":bw_costly_rmnet_data7 -\n"
151 "-X bw_costly_rmnet_data7\n"
152 "COMMIT\n";
153
154 mBw.setupIptablesHooks();
155 expectSetupCommands(expectedCleanCmds, "");
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900156}
157
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900158TEST_F(BandwidthControllerTest, TestEnableBandwidthControl) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900159 // Pretend no bw_costly_shared_<iface> rules already exist...
160 addIptablesRestoreOutput(
161 "-P OUTPUT ACCEPT\n"
162 "-N bw_costly_shared\n"
163 "-N unrelated\n");
164
165 // ... so none are flushed or deleted.
166 std::string expectedClean = "";
167
168 std::string expectedAccounting =
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900169 "*filter\n"
170 "-A bw_INPUT -m owner --socket-exists\n"
171 "-A bw_OUTPUT -m owner --socket-exists\n"
172 "-A bw_costly_shared --jump bw_penalty_box\n"
173 "-A bw_penalty_box --jump bw_happy_box\n"
174 "-A bw_happy_box --jump bw_data_saver\n"
175 "-A bw_data_saver -j RETURN\n"
176 "-I bw_happy_box -m owner --uid-owner 0-9999 --jump RETURN\n"
177 "COMMIT\n"
178 "*raw\n"
179 "-A bw_raw_PREROUTING -m owner --socket-exists\n"
180 "COMMIT\n"
181 "*mangle\n"
182 "-A bw_mangle_POSTROUTING -m owner --socket-exists\n"
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900183 "COMMIT\n";
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900184
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900185 mBw.enableBandwidthControl(false);
186 expectSetupCommands(expectedClean, expectedAccounting);
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900187}
188
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900189TEST_F(BandwidthControllerTest, TestDisableBandwidthControl) {
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900190 // Pretend some bw_costly_shared_<iface> rules already exist...
191 addIptablesRestoreOutput(
192 "-P OUTPUT ACCEPT\n"
193 "-N bw_costly_rmnet_data0\n"
194 "-N bw_costly_shared\n"
195 "-N unrelated\n"
196 "-N bw_costly_rmnet_data7\n");
197
198 // ... and expect that they be flushed.
199 std::string expectedCleanCmds =
Lorenzo Colitti13debb82016-03-27 17:46:30 +0900200 "*filter\n"
Lorenzo Colitti56c4b1e2017-02-01 02:45:10 +0900201 ":bw_costly_rmnet_data0 -\n"
202 ":bw_costly_rmnet_data7 -\n"
203 "COMMIT\n";
204
205 mBw.disableBandwidthControl();
206 expectSetupCommands(expectedCleanCmds, "");
Lorenzo Colittia0dc8a52016-03-26 22:42:07 +0900207}
208
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900209TEST_F(BandwidthControllerTest, TestEnableDataSaver) {
210 mBw.enableDataSaver(true);
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900211 std::string expected4 =
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900212 "*filter\n"
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900213 ":bw_data_saver -\n"
214 "-A bw_data_saver --jump REJECT\n"
215 "COMMIT\n";
216 std::string expected6 =
217 "*filter\n"
218 ":bw_data_saver -\n"
219 "-A bw_data_saver -p icmpv6 --icmpv6-type packet-too-big -j RETURN\n"
220 "-A bw_data_saver -p icmpv6 --icmpv6-type router-solicitation -j RETURN\n"
221 "-A bw_data_saver -p icmpv6 --icmpv6-type router-advertisement -j RETURN\n"
222 "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-solicitation -j RETURN\n"
223 "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-advertisement -j RETURN\n"
224 "-A bw_data_saver -p icmpv6 --icmpv6-type redirect -j RETURN\n"
225 "-A bw_data_saver --jump REJECT\n"
226 "COMMIT\n";
227 expectIptablesRestoreCommands({
228 {V4, expected4},
229 {V6, expected6},
230 });
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900231
232 mBw.enableDataSaver(false);
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900233 std::string expected = {
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900234 "*filter\n"
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900235 ":bw_data_saver -\n"
236 "-A bw_data_saver --jump RETURN\n"
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900237 "COMMIT\n"
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900238 };
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900239 expectIptablesRestoreCommands({
240 {V4, expected},
241 {V6, expected},
242 });
Lorenzo Colitti86a47982016-03-18 17:52:25 +0900243}
Lorenzo Colittibbeaf9a2016-07-08 18:24:26 +0900244
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900245const std::vector<std::string> makeInterfaceQuotaCommands(const std::string& iface, int ruleIndex,
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900246 int64_t quota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900247 const std::string chain = "bw_costly_" + iface;
248 const char* c_chain = chain.c_str();
249 const char* c_iface = iface.c_str();
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900250 std::vector<std::string> cmds = {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900251 "*filter",
252 StringPrintf(":%s -", c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900253 StringPrintf("-A %s -j bw_penalty_box", c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900254 StringPrintf("-I bw_INPUT %d -i %s --jump %s", ruleIndex, c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900255 StringPrintf("-I bw_OUTPUT %d -o %s --jump %s", ruleIndex, c_iface, c_chain),
Erik Kline51eb3242017-09-20 18:30:47 +0900256 StringPrintf("-A bw_FORWARD -i %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900257 StringPrintf("-A bw_FORWARD -o %s --jump %s", c_iface, c_chain),
258 StringPrintf("-A %s -m quota2 ! --quota %" PRIu64 " --name %s --jump REJECT", c_chain,
259 quota, c_iface),
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900260 "COMMIT\n",
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900261 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900262 return {Join(cmds, "\n")};
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900263}
264
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900265const std::vector<std::string> removeInterfaceQuotaCommands(const std::string& iface) {
266 const std::string chain = "bw_costly_" + iface;
267 const char* c_chain = chain.c_str();
268 const char* c_iface = iface.c_str();
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900269 std::vector<std::string> cmds = {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900270 "*filter",
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900271 StringPrintf("-D bw_INPUT -i %s --jump %s", c_iface, c_chain),
272 StringPrintf("-D bw_OUTPUT -o %s --jump %s", c_iface, c_chain),
Erik Kline51eb3242017-09-20 18:30:47 +0900273 StringPrintf("-D bw_FORWARD -i %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900274 StringPrintf("-D bw_FORWARD -o %s --jump %s", c_iface, c_chain),
275 StringPrintf("-F %s", c_chain),
276 StringPrintf("-X %s", c_chain),
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900277 "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
282TEST_F(BandwidthControllerTest, TestSetInterfaceQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900283 constexpr uint64_t kOldQuota = 123456;
284 const std::string iface = mTun.name();
285 std::vector<std::string> expected = makeInterfaceQuotaCommands(iface, 1, kOldQuota);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900286
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900287 EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kOldQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900288 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900289
290 constexpr uint64_t kNewQuota = kOldQuota + 1;
291 expected = {};
292 expectUpdateQuota(kNewQuota);
293 EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kNewQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900294 expectIptablesRestoreCommands(expected);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900295
296 expected = removeInterfaceQuotaCommands(iface);
297 EXPECT_EQ(0, mBw.removeInterfaceQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900298 expectIptablesRestoreCommands(expected);
Lorenzo Colittidf42ddd2017-02-28 01:20:13 +0900299}
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900300
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900301const std::vector<std::string> makeInterfaceSharedQuotaCommands(const std::string& iface,
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900302 int ruleIndex, int64_t quota,
303 bool insertQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900304 const std::string chain = "bw_costly_shared";
305 const char* c_chain = chain.c_str();
306 const char* c_iface = iface.c_str();
307 std::vector<std::string> cmds = {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900308 "*filter",
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900309 StringPrintf("-I bw_INPUT %d -i %s --jump %s", ruleIndex, c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900310 StringPrintf("-I bw_OUTPUT %d -o %s --jump %s", ruleIndex, c_iface, c_chain),
Erik Kline51eb3242017-09-20 18:30:47 +0900311 StringPrintf("-A bw_FORWARD -i %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900312 StringPrintf("-A bw_FORWARD -o %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900313 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900314 if (insertQuota) {
315 cmds.push_back(StringPrintf(
316 "-I %s -m quota2 ! --quota %" PRIu64 " --name shared --jump REJECT", c_chain, quota));
317 }
318 cmds.push_back("COMMIT\n");
319 return {Join(cmds, "\n")};
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900320}
321
322const std::vector<std::string> removeInterfaceSharedQuotaCommands(const std::string& iface,
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900323 int64_t quota, bool deleteQuota) {
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900324 const std::string chain = "bw_costly_shared";
325 const char* c_chain = chain.c_str();
326 const char* c_iface = iface.c_str();
327 std::vector<std::string> cmds = {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900328 "*filter",
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900329 StringPrintf("-D bw_INPUT -i %s --jump %s", c_iface, c_chain),
330 StringPrintf("-D bw_OUTPUT -o %s --jump %s", c_iface, c_chain),
Erik Kline51eb3242017-09-20 18:30:47 +0900331 StringPrintf("-D bw_FORWARD -i %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900332 StringPrintf("-D bw_FORWARD -o %s --jump %s", c_iface, c_chain),
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900333 };
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900334 if (deleteQuota) {
335 cmds.push_back(StringPrintf(
336 "-D %s -m quota2 ! --quota %" PRIu64 " --name shared --jump REJECT", c_chain, quota));
337 }
338 cmds.push_back("COMMIT\n");
339 return {Join(cmds, "\n")};
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900340}
341
342TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaDuplicate) {
343 constexpr uint64_t kQuota = 123456;
344 const std::string iface = mTun.name();
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900345 std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, 123456, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900346 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900347 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900348
349 expected = {};
350 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900351 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900352
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900353 expected = removeInterfaceSharedQuotaCommands(iface, kQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900354 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900355 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900356}
357
358TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaUpdate) {
359 constexpr uint64_t kOldQuota = 123456;
360 const std::string iface = mTun.name();
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900361 std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, kOldQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900362 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kOldQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900363 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900364
365 constexpr uint64_t kNewQuota = kOldQuota + 1;
366 expected = {};
367 expectUpdateQuota(kNewQuota);
368 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kNewQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900369 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900370
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900371 expected = removeInterfaceSharedQuotaCommands(iface, kNewQuota, true);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900372 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900373 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900374}
375
376TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaTwoInterfaces) {
377 constexpr uint64_t kQuota = 123456;
378 const std::vector<std::string> ifaces{
379 {"a" + mTun.name()},
380 {"b" + mTun.name()},
381 };
382
383 for (const auto& iface : ifaces) {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900384 // Quota rule is only added when the total number of
385 // interfaces transitions from 0 -> 1.
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900386 bool first = (iface == ifaces[0]);
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900387 auto expected = makeInterfaceSharedQuotaCommands(iface, 1, kQuota, first);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900388 EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900389 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900390 }
391
392 for (const auto& iface : ifaces) {
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900393 // Quota rule is only removed when the total number of
394 // interfaces transitions from 1 -> 0.
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900395 bool last = (iface == ifaces[1]);
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900396 auto expected = removeInterfaceSharedQuotaCommands(iface, kQuota, last);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900397 EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
Lorenzo Colitti48f83002017-07-06 15:06:04 +0900398 expectIptablesRestoreCommands(expected);
Joel Scherpelz01cc5492017-06-16 10:45:14 +0900399 }
400}
401
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900402TEST_F(BandwidthControllerTest, IptablesAlertCmd) {
403 std::vector<std::string> expected = {
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900404 "*filter\n"
405 "-I bw_INPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
406 "-I bw_OUTPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
407 "COMMIT\n"
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900408 };
409 EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900410 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900411
412 expected = {
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900413 "*filter\n"
414 "-D bw_INPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
415 "-D bw_OUTPUT -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
416 "COMMIT\n"
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900417 };
418 EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900419 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900420}
421
422TEST_F(BandwidthControllerTest, IptablesAlertFwdCmd) {
423 std::vector<std::string> expected = {
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900424 "*filter\n"
425 "-I bw_FORWARD -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
426 "COMMIT\n"
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900427 };
428 EXPECT_EQ(0, runIptablesAlertFwdCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900429 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900430
431 expected = {
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900432 "*filter\n"
433 "-D bw_FORWARD -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
434 "COMMIT\n"
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900435 };
436 EXPECT_EQ(0, runIptablesAlertFwdCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
Lorenzo Colitti3c272702017-04-26 15:48:13 +0900437 expectIptablesRestoreCommands(expected);
Lorenzo Colittie8b56e42017-04-26 15:16:03 +0900438}
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900439
Lorenzo Colitti38078222017-07-06 17:27:23 +0900440TEST_F(BandwidthControllerTest, CostlyAlert) {
441 const int64_t kQuota = 123456;
442 int64_t alertBytes = 0;
443
444 std::vector<std::string> expected = {
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900445 "*filter\n"
446 "-A bw_costly_shared -m quota2 ! --quota 123456 --name sharedAlert\n"
447 "COMMIT\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900448 };
449 EXPECT_EQ(0, setCostlyAlert("shared", kQuota, &alertBytes));
450 EXPECT_EQ(kQuota, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900451 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900452
453 expected = {};
454 expectUpdateQuota(kQuota);
455 EXPECT_EQ(0, setCostlyAlert("shared", kQuota + 1, &alertBytes));
456 EXPECT_EQ(kQuota + 1, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900457 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900458
459 expected = {
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900460 "*filter\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900461 "-D bw_costly_shared -m quota2 ! --quota 123457 --name sharedAlert\n"
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900462 "COMMIT\n"
Lorenzo Colitti38078222017-07-06 17:27:23 +0900463 };
464 EXPECT_EQ(0, removeCostlyAlert("shared", &alertBytes));
465 EXPECT_EQ(0, alertBytes);
Lorenzo Colittie85ffe12017-07-06 17:25:37 +0900466 expectIptablesRestoreCommands(expected);
Lorenzo Colitti38078222017-07-06 17:27:23 +0900467}
468
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900469TEST_F(BandwidthControllerTest, ManipulateSpecialApps) {
470 std::vector<const char *> appUids = { "1000", "1001", "10012" };
471
472 std::vector<std::string> expected = {
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900473 "*filter\n"
474 "-I bw_happy_box -m owner --uid-owner 1000 --jump RETURN\n"
475 "-I bw_happy_box -m owner --uid-owner 1001 --jump RETURN\n"
476 "-I bw_happy_box -m owner --uid-owner 10012 --jump RETURN\n"
477 "COMMIT\n"
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900478 };
479 EXPECT_EQ(0, mBw.addNiceApps(appUids.size(), const_cast<char**>(&appUids[0])));
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900480 expectIptablesRestoreCommands(expected);
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900481
482 expected = {
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900483 "*filter\n"
484 "-D bw_penalty_box -m owner --uid-owner 1000 --jump REJECT\n"
485 "-D bw_penalty_box -m owner --uid-owner 1001 --jump REJECT\n"
486 "-D bw_penalty_box -m owner --uid-owner 10012 --jump REJECT\n"
487 "COMMIT\n"
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900488 };
489 EXPECT_EQ(0, mBw.removeNaughtyApps(appUids.size(), const_cast<char**>(&appUids[0])));
Lorenzo Colitti911bc4c2017-04-28 14:34:01 +0900490 expectIptablesRestoreCommands(expected);
Lorenzo Colittif4dfa682017-04-28 11:09:07 +0900491}