1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker * Copyright 2016 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker *
4*8542734aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker *
8*8542734aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker *
10*8542734aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker *
16*8542734aSAndroid Build Coastguard Worker * BandwidthControllerTest.cpp - unit tests for BandwidthController.cpp
17*8542734aSAndroid Build Coastguard Worker */
18*8542734aSAndroid Build Coastguard Worker
19*8542734aSAndroid Build Coastguard Worker #include <string>
20*8542734aSAndroid Build Coastguard Worker #include <vector>
21*8542734aSAndroid Build Coastguard Worker
22*8542734aSAndroid Build Coastguard Worker #include <inttypes.h>
23*8542734aSAndroid Build Coastguard Worker #include <fcntl.h>
24*8542734aSAndroid Build Coastguard Worker #include <unistd.h>
25*8542734aSAndroid Build Coastguard Worker #include <sys/types.h>
26*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
27*8542734aSAndroid Build Coastguard Worker
28*8542734aSAndroid Build Coastguard Worker #include <gtest/gtest.h>
29*8542734aSAndroid Build Coastguard Worker
30*8542734aSAndroid Build Coastguard Worker #include <android-base/strings.h>
31*8542734aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
32*8542734aSAndroid Build Coastguard Worker
33*8542734aSAndroid Build Coastguard Worker #include <netdutils/MockSyscalls.h>
34*8542734aSAndroid Build Coastguard Worker #include "BandwidthController.h"
35*8542734aSAndroid Build Coastguard Worker #include "Fwmark.h"
36*8542734aSAndroid Build Coastguard Worker #include "IptablesBaseTest.h"
37*8542734aSAndroid Build Coastguard Worker #include "mainline/XtBpfProgLocations.h"
38*8542734aSAndroid Build Coastguard Worker #include "tun_interface.h"
39*8542734aSAndroid Build Coastguard Worker
40*8542734aSAndroid Build Coastguard Worker using ::testing::_;
41*8542734aSAndroid Build Coastguard Worker using ::testing::ByMove;
42*8542734aSAndroid Build Coastguard Worker using ::testing::Invoke;
43*8542734aSAndroid Build Coastguard Worker using ::testing::Return;
44*8542734aSAndroid Build Coastguard Worker using ::testing::StrictMock;
45*8542734aSAndroid Build Coastguard Worker
46*8542734aSAndroid Build Coastguard Worker using android::base::Join;
47*8542734aSAndroid Build Coastguard Worker using android::base::StringPrintf;
48*8542734aSAndroid Build Coastguard Worker using android::net::TunInterface;
49*8542734aSAndroid Build Coastguard Worker using android::netdutils::UniqueFile;
50*8542734aSAndroid Build Coastguard Worker using android::netdutils::status::ok;
51*8542734aSAndroid Build Coastguard Worker
52*8542734aSAndroid Build Coastguard Worker class BandwidthControllerTest : public IptablesBaseTest {
53*8542734aSAndroid Build Coastguard Worker protected:
BandwidthControllerTest()54*8542734aSAndroid Build Coastguard Worker BandwidthControllerTest() {
55*8542734aSAndroid Build Coastguard Worker BandwidthController::iptablesRestoreFunction = fakeExecIptablesRestoreWithOutput;
56*8542734aSAndroid Build Coastguard Worker }
57*8542734aSAndroid Build Coastguard Worker BandwidthController mBw;
58*8542734aSAndroid Build Coastguard Worker TunInterface mTun;
59*8542734aSAndroid Build Coastguard Worker
SetUp()60*8542734aSAndroid Build Coastguard Worker void SetUp() {
61*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(0, mTun.init());
62*8542734aSAndroid Build Coastguard Worker }
63*8542734aSAndroid Build Coastguard Worker
TearDown()64*8542734aSAndroid Build Coastguard Worker void TearDown() {
65*8542734aSAndroid Build Coastguard Worker mTun.destroy();
66*8542734aSAndroid Build Coastguard Worker }
67*8542734aSAndroid Build Coastguard Worker
expectSetupCommands(const std::string & expectedClean,const std::string & expectedAccounting)68*8542734aSAndroid Build Coastguard Worker void expectSetupCommands(const std::string& expectedClean,
69*8542734aSAndroid Build Coastguard Worker const std::string& expectedAccounting) {
70*8542734aSAndroid Build Coastguard Worker std::string expectedList =
71*8542734aSAndroid Build Coastguard Worker "*filter\n"
72*8542734aSAndroid Build Coastguard Worker "-S\n"
73*8542734aSAndroid Build Coastguard Worker "COMMIT\n";
74*8542734aSAndroid Build Coastguard Worker
75*8542734aSAndroid Build Coastguard Worker std::string expectedFlush =
76*8542734aSAndroid Build Coastguard Worker "*filter\n"
77*8542734aSAndroid Build Coastguard Worker ":bw_INPUT -\n"
78*8542734aSAndroid Build Coastguard Worker ":bw_OUTPUT -\n"
79*8542734aSAndroid Build Coastguard Worker ":bw_FORWARD -\n"
80*8542734aSAndroid Build Coastguard Worker ":bw_happy_box -\n"
81*8542734aSAndroid Build Coastguard Worker ":bw_penalty_box -\n"
82*8542734aSAndroid Build Coastguard Worker ":bw_data_saver -\n"
83*8542734aSAndroid Build Coastguard Worker ":bw_costly_shared -\n"
84*8542734aSAndroid Build Coastguard Worker ":bw_global_alert -\n"
85*8542734aSAndroid Build Coastguard Worker "COMMIT\n"
86*8542734aSAndroid Build Coastguard Worker "*raw\n"
87*8542734aSAndroid Build Coastguard Worker ":bw_raw_PREROUTING -\n"
88*8542734aSAndroid Build Coastguard Worker "COMMIT\n"
89*8542734aSAndroid Build Coastguard Worker "*mangle\n"
90*8542734aSAndroid Build Coastguard Worker ":bw_mangle_POSTROUTING -\n"
91*8542734aSAndroid Build Coastguard Worker "COMMIT\n";
92*8542734aSAndroid Build Coastguard Worker
93*8542734aSAndroid Build Coastguard Worker ExpectedIptablesCommands expected = {{ V4, expectedList }};
94*8542734aSAndroid Build Coastguard Worker if (expectedClean.size()) {
95*8542734aSAndroid Build Coastguard Worker expected.push_back({ V4V6, expectedClean });
96*8542734aSAndroid Build Coastguard Worker }
97*8542734aSAndroid Build Coastguard Worker expected.push_back({ V4V6, expectedFlush });
98*8542734aSAndroid Build Coastguard Worker if (expectedAccounting.size()) {
99*8542734aSAndroid Build Coastguard Worker expected.push_back({ V4V6, expectedAccounting });
100*8542734aSAndroid Build Coastguard Worker }
101*8542734aSAndroid Build Coastguard Worker
102*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
103*8542734aSAndroid Build Coastguard Worker }
104*8542734aSAndroid Build Coastguard Worker
105*8542734aSAndroid Build Coastguard Worker using IptOp = BandwidthController::IptOp;
106*8542734aSAndroid Build Coastguard Worker
runIptablesAlertCmd(IptOp a,const char * b,int64_t c)107*8542734aSAndroid Build Coastguard Worker int runIptablesAlertCmd(IptOp a, const char* b, int64_t c) {
108*8542734aSAndroid Build Coastguard Worker return mBw.runIptablesAlertCmd(a, b, c);
109*8542734aSAndroid Build Coastguard Worker }
110*8542734aSAndroid Build Coastguard Worker
setCostlyAlert(const std::string & a,int64_t b,int64_t * c)111*8542734aSAndroid Build Coastguard Worker int setCostlyAlert(const std::string& a, int64_t b, int64_t* c) {
112*8542734aSAndroid Build Coastguard Worker return mBw.setCostlyAlert(a, b, c);
113*8542734aSAndroid Build Coastguard Worker }
114*8542734aSAndroid Build Coastguard Worker
removeCostlyAlert(const std::string & a,int64_t * b)115*8542734aSAndroid Build Coastguard Worker int removeCostlyAlert(const std::string& a, int64_t* b) { return mBw.removeCostlyAlert(a, b); }
116*8542734aSAndroid Build Coastguard Worker
expectUpdateQuota(uint64_t quota)117*8542734aSAndroid Build Coastguard Worker void expectUpdateQuota(uint64_t quota) {
118*8542734aSAndroid Build Coastguard Worker uintptr_t dummy;
119*8542734aSAndroid Build Coastguard Worker FILE* dummyFile = reinterpret_cast<FILE*>(&dummy);
120*8542734aSAndroid Build Coastguard Worker
121*8542734aSAndroid Build Coastguard Worker EXPECT_CALL(mSyscalls, fopen(_, _)).WillOnce(Return(ByMove(UniqueFile(dummyFile))));
122*8542734aSAndroid Build Coastguard Worker EXPECT_CALL(mSyscalls, vfprintf(dummyFile, _, _))
123*8542734aSAndroid Build Coastguard Worker .WillOnce(Invoke([quota](FILE*, const std::string&, va_list ap) {
124*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(quota, va_arg(ap, uint64_t));
125*8542734aSAndroid Build Coastguard Worker return 0;
126*8542734aSAndroid Build Coastguard Worker }));
127*8542734aSAndroid Build Coastguard Worker EXPECT_CALL(mSyscalls, fclose(dummyFile)).WillOnce(Return(ok));
128*8542734aSAndroid Build Coastguard Worker }
129*8542734aSAndroid Build Coastguard Worker
130*8542734aSAndroid Build Coastguard Worker StrictMock<android::netdutils::ScopedMockSyscalls> mSyscalls;
131*8542734aSAndroid Build Coastguard Worker };
132*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,TestSetupIptablesHooks)133*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, TestSetupIptablesHooks) {
134*8542734aSAndroid Build Coastguard Worker // Pretend some bw_costly_shared_<iface> rules already exist...
135*8542734aSAndroid Build Coastguard Worker addIptablesRestoreOutput(
136*8542734aSAndroid Build Coastguard Worker "-P OUTPUT ACCEPT\n"
137*8542734aSAndroid Build Coastguard Worker "-N bw_costly_rmnet_data0\n"
138*8542734aSAndroid Build Coastguard Worker "-N bw_costly_shared\n"
139*8542734aSAndroid Build Coastguard Worker "-N unrelated\n"
140*8542734aSAndroid Build Coastguard Worker "-N bw_costly_rmnet_data7\n");
141*8542734aSAndroid Build Coastguard Worker
142*8542734aSAndroid Build Coastguard Worker // ... and expect that they be flushed and deleted.
143*8542734aSAndroid Build Coastguard Worker std::string expectedCleanCmds =
144*8542734aSAndroid Build Coastguard Worker "*filter\n"
145*8542734aSAndroid Build Coastguard Worker ":bw_costly_rmnet_data0 -\n"
146*8542734aSAndroid Build Coastguard Worker "-X bw_costly_rmnet_data0\n"
147*8542734aSAndroid Build Coastguard Worker ":bw_costly_rmnet_data7 -\n"
148*8542734aSAndroid Build Coastguard Worker "-X bw_costly_rmnet_data7\n"
149*8542734aSAndroid Build Coastguard Worker "COMMIT\n";
150*8542734aSAndroid Build Coastguard Worker
151*8542734aSAndroid Build Coastguard Worker mBw.setupIptablesHooks();
152*8542734aSAndroid Build Coastguard Worker expectSetupCommands(expectedCleanCmds, "");
153*8542734aSAndroid Build Coastguard Worker }
154*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,TestCheckUidBillingMask)155*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, TestCheckUidBillingMask) {
156*8542734aSAndroid Build Coastguard Worker uint32_t uidBillingMask = Fwmark::getUidBillingMask();
157*8542734aSAndroid Build Coastguard Worker
158*8542734aSAndroid Build Coastguard Worker // If mask is non-zero, and mask & mask-1 is equal to 0, then the mask is a power of two.
159*8542734aSAndroid Build Coastguard Worker bool isPowerOfTwo = uidBillingMask && (uidBillingMask & (uidBillingMask - 1)) == 0;
160*8542734aSAndroid Build Coastguard Worker
161*8542734aSAndroid Build Coastguard Worker // Must be exactly a power of two
162*8542734aSAndroid Build Coastguard Worker EXPECT_TRUE(isPowerOfTwo);
163*8542734aSAndroid Build Coastguard Worker }
164*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,TestEnableBandwidthControl)165*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, TestEnableBandwidthControl) {
166*8542734aSAndroid Build Coastguard Worker // Pretend no bw_costly_shared_<iface> rules already exist...
167*8542734aSAndroid Build Coastguard Worker addIptablesRestoreOutput(
168*8542734aSAndroid Build Coastguard Worker "-P OUTPUT ACCEPT\n"
169*8542734aSAndroid Build Coastguard Worker "-N bw_costly_shared\n"
170*8542734aSAndroid Build Coastguard Worker "-N unrelated\n");
171*8542734aSAndroid Build Coastguard Worker
172*8542734aSAndroid Build Coastguard Worker // ... so none are flushed or deleted.
173*8542734aSAndroid Build Coastguard Worker // clang-format off
174*8542734aSAndroid Build Coastguard Worker static const std::string expectedClean = "";
175*8542734aSAndroid Build Coastguard Worker static const std::string expectedAccounting =
176*8542734aSAndroid Build Coastguard Worker "*filter\n"
177*8542734aSAndroid Build Coastguard Worker "-A bw_INPUT -j bw_global_alert\n"
178*8542734aSAndroid Build Coastguard Worker "-A bw_INPUT -p esp -j RETURN\n"
179*8542734aSAndroid Build Coastguard Worker "-A bw_INPUT -m mark --mark 0x100000/0x100000 -j RETURN\n"
180*8542734aSAndroid Build Coastguard Worker "-A bw_INPUT -j MARK --or-mark 0x100000\n"
181*8542734aSAndroid Build Coastguard Worker "-A bw_OUTPUT -j bw_global_alert\n"
182*8542734aSAndroid Build Coastguard Worker "-A bw_costly_shared -j bw_penalty_box\n"
183*8542734aSAndroid Build Coastguard Worker "-I bw_penalty_box -m bpf --object-pinned " XT_BPF_DENYLIST_PROG_PATH " -j REJECT\n"
184*8542734aSAndroid Build Coastguard Worker "-A bw_penalty_box -j bw_happy_box\n"
185*8542734aSAndroid Build Coastguard Worker "-A bw_happy_box -j bw_data_saver\n"
186*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -j RETURN\n"
187*8542734aSAndroid Build Coastguard Worker "-I bw_happy_box -m bpf --object-pinned " XT_BPF_ALLOWLIST_PROG_PATH " -j RETURN\n"
188*8542734aSAndroid Build Coastguard Worker "COMMIT\n"
189*8542734aSAndroid Build Coastguard Worker "*raw\n"
190*8542734aSAndroid Build Coastguard Worker "-A bw_raw_PREROUTING -m mark --mark 0xdeadc1a7 -j DROP\n"
191*8542734aSAndroid Build Coastguard Worker "-A bw_raw_PREROUTING -i ipsec+ -j RETURN\n"
192*8542734aSAndroid Build Coastguard Worker "-A bw_raw_PREROUTING -m policy --pol ipsec --dir in -j RETURN\n"
193*8542734aSAndroid Build Coastguard Worker "-A bw_raw_PREROUTING -m bpf --object-pinned " XT_BPF_INGRESS_PROG_PATH "\n"
194*8542734aSAndroid Build Coastguard Worker "COMMIT\n"
195*8542734aSAndroid Build Coastguard Worker "*mangle\n"
196*8542734aSAndroid Build Coastguard Worker "-A bw_mangle_POSTROUTING -o ipsec+ -j RETURN\n"
197*8542734aSAndroid Build Coastguard Worker "-A bw_mangle_POSTROUTING -m policy --pol ipsec --dir out -j RETURN\n"
198*8542734aSAndroid Build Coastguard Worker "-A bw_mangle_POSTROUTING -j MARK --set-mark 0x0/0x100000\n"
199*8542734aSAndroid Build Coastguard Worker "-A bw_mangle_POSTROUTING -m bpf --object-pinned " XT_BPF_EGRESS_PROG_PATH "\n"
200*8542734aSAndroid Build Coastguard Worker "COMMIT\n";
201*8542734aSAndroid Build Coastguard Worker // clang-format on
202*8542734aSAndroid Build Coastguard Worker
203*8542734aSAndroid Build Coastguard Worker mBw.enableBandwidthControl();
204*8542734aSAndroid Build Coastguard Worker expectSetupCommands(expectedClean, expectedAccounting);
205*8542734aSAndroid Build Coastguard Worker }
206*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,TestEnableDataSaver)207*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, TestEnableDataSaver) {
208*8542734aSAndroid Build Coastguard Worker mBw.enableDataSaver(true);
209*8542734aSAndroid Build Coastguard Worker std::string expected4 =
210*8542734aSAndroid Build Coastguard Worker "*filter\n"
211*8542734aSAndroid Build Coastguard Worker ":bw_data_saver -\n"
212*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -j REJECT\n"
213*8542734aSAndroid Build Coastguard Worker "COMMIT\n";
214*8542734aSAndroid Build Coastguard Worker std::string expected6 =
215*8542734aSAndroid Build Coastguard Worker "*filter\n"
216*8542734aSAndroid Build Coastguard Worker ":bw_data_saver -\n"
217*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -p icmpv6 --icmpv6-type packet-too-big -j RETURN\n"
218*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -p icmpv6 --icmpv6-type router-solicitation -j RETURN\n"
219*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -p icmpv6 --icmpv6-type router-advertisement -j RETURN\n"
220*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-solicitation -j RETURN\n"
221*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -p icmpv6 --icmpv6-type neighbour-advertisement -j RETURN\n"
222*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -p icmpv6 --icmpv6-type redirect -j RETURN\n"
223*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -j REJECT\n"
224*8542734aSAndroid Build Coastguard Worker "COMMIT\n";
225*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands({
226*8542734aSAndroid Build Coastguard Worker {V4, expected4},
227*8542734aSAndroid Build Coastguard Worker {V6, expected6},
228*8542734aSAndroid Build Coastguard Worker });
229*8542734aSAndroid Build Coastguard Worker
230*8542734aSAndroid Build Coastguard Worker mBw.enableDataSaver(false);
231*8542734aSAndroid Build Coastguard Worker std::string expected = {
232*8542734aSAndroid Build Coastguard Worker "*filter\n"
233*8542734aSAndroid Build Coastguard Worker ":bw_data_saver -\n"
234*8542734aSAndroid Build Coastguard Worker "-A bw_data_saver -j RETURN\n"
235*8542734aSAndroid Build Coastguard Worker "COMMIT\n"};
236*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands({
237*8542734aSAndroid Build Coastguard Worker {V4, expected},
238*8542734aSAndroid Build Coastguard Worker {V6, expected},
239*8542734aSAndroid Build Coastguard Worker });
240*8542734aSAndroid Build Coastguard Worker }
241*8542734aSAndroid Build Coastguard Worker
makeInterfaceQuotaCommands(const std::string & iface,int ruleIndex,int64_t quota)242*8542734aSAndroid Build Coastguard Worker const std::vector<std::string> makeInterfaceQuotaCommands(const std::string& iface, int ruleIndex,
243*8542734aSAndroid Build Coastguard Worker int64_t quota) {
244*8542734aSAndroid Build Coastguard Worker const std::string chain = "bw_costly_" + iface;
245*8542734aSAndroid Build Coastguard Worker const char* c_chain = chain.c_str();
246*8542734aSAndroid Build Coastguard Worker const char* c_iface = iface.c_str();
247*8542734aSAndroid Build Coastguard Worker std::vector<std::string> cmds = {
248*8542734aSAndroid Build Coastguard Worker "*filter",
249*8542734aSAndroid Build Coastguard Worker StringPrintf(":%s -", c_chain),
250*8542734aSAndroid Build Coastguard Worker StringPrintf("-A %s -j bw_penalty_box", c_chain),
251*8542734aSAndroid Build Coastguard Worker StringPrintf("-I bw_INPUT %d -i %s -j %s", ruleIndex, c_iface, c_chain),
252*8542734aSAndroid Build Coastguard Worker StringPrintf("-I bw_OUTPUT %d -o %s -j %s", ruleIndex, c_iface, c_chain),
253*8542734aSAndroid Build Coastguard Worker StringPrintf("-A bw_FORWARD -i %s -j %s", c_iface, c_chain),
254*8542734aSAndroid Build Coastguard Worker StringPrintf("-A bw_FORWARD -o %s -j %s", c_iface, c_chain),
255*8542734aSAndroid Build Coastguard Worker StringPrintf("-A %s -m quota2 ! --quota %" PRIu64 " --name %s -j REJECT", c_chain,
256*8542734aSAndroid Build Coastguard Worker quota, c_iface),
257*8542734aSAndroid Build Coastguard Worker "COMMIT\n",
258*8542734aSAndroid Build Coastguard Worker };
259*8542734aSAndroid Build Coastguard Worker return {Join(cmds, "\n")};
260*8542734aSAndroid Build Coastguard Worker }
261*8542734aSAndroid Build Coastguard Worker
removeInterfaceQuotaCommands(const std::string & iface)262*8542734aSAndroid Build Coastguard Worker const std::vector<std::string> removeInterfaceQuotaCommands(const std::string& iface) {
263*8542734aSAndroid Build Coastguard Worker const std::string chain = "bw_costly_" + iface;
264*8542734aSAndroid Build Coastguard Worker const char* c_chain = chain.c_str();
265*8542734aSAndroid Build Coastguard Worker const char* c_iface = iface.c_str();
266*8542734aSAndroid Build Coastguard Worker std::vector<std::string> cmds = {
267*8542734aSAndroid Build Coastguard Worker "*filter",
268*8542734aSAndroid Build Coastguard Worker StringPrintf("-D bw_INPUT -i %s -j %s", c_iface, c_chain),
269*8542734aSAndroid Build Coastguard Worker StringPrintf("-D bw_OUTPUT -o %s -j %s", c_iface, c_chain),
270*8542734aSAndroid Build Coastguard Worker StringPrintf("-D bw_FORWARD -i %s -j %s", c_iface, c_chain),
271*8542734aSAndroid Build Coastguard Worker StringPrintf("-D bw_FORWARD -o %s -j %s", c_iface, c_chain),
272*8542734aSAndroid Build Coastguard Worker StringPrintf("-F %s", c_chain),
273*8542734aSAndroid Build Coastguard Worker StringPrintf("-X %s", c_chain),
274*8542734aSAndroid Build Coastguard Worker "COMMIT\n",
275*8542734aSAndroid Build Coastguard Worker };
276*8542734aSAndroid Build Coastguard Worker return {Join(cmds, "\n")};
277*8542734aSAndroid Build Coastguard Worker }
278*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,TestSetInterfaceQuota)279*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, TestSetInterfaceQuota) {
280*8542734aSAndroid Build Coastguard Worker constexpr uint64_t kOldQuota = 123456;
281*8542734aSAndroid Build Coastguard Worker const std::string iface = mTun.name();
282*8542734aSAndroid Build Coastguard Worker std::vector<std::string> expected = makeInterfaceQuotaCommands(iface, 1, kOldQuota);
283*8542734aSAndroid Build Coastguard Worker
284*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kOldQuota));
285*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
286*8542734aSAndroid Build Coastguard Worker
287*8542734aSAndroid Build Coastguard Worker constexpr uint64_t kNewQuota = kOldQuota + 1;
288*8542734aSAndroid Build Coastguard Worker expected = {};
289*8542734aSAndroid Build Coastguard Worker expectUpdateQuota(kNewQuota);
290*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.setInterfaceQuota(iface, kNewQuota));
291*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
292*8542734aSAndroid Build Coastguard Worker
293*8542734aSAndroid Build Coastguard Worker expected = removeInterfaceQuotaCommands(iface);
294*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.removeInterfaceQuota(iface));
295*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
296*8542734aSAndroid Build Coastguard Worker }
297*8542734aSAndroid Build Coastguard Worker
makeInterfaceSharedQuotaCommands(const std::string & iface,int ruleIndex,int64_t quota,bool insertQuota)298*8542734aSAndroid Build Coastguard Worker const std::vector<std::string> makeInterfaceSharedQuotaCommands(const std::string& iface,
299*8542734aSAndroid Build Coastguard Worker int ruleIndex, int64_t quota,
300*8542734aSAndroid Build Coastguard Worker bool insertQuota) {
301*8542734aSAndroid Build Coastguard Worker const std::string chain = "bw_costly_shared";
302*8542734aSAndroid Build Coastguard Worker const char* c_chain = chain.c_str();
303*8542734aSAndroid Build Coastguard Worker const char* c_iface = iface.c_str();
304*8542734aSAndroid Build Coastguard Worker std::vector<std::string> cmds = {
305*8542734aSAndroid Build Coastguard Worker "*filter",
306*8542734aSAndroid Build Coastguard Worker StringPrintf("-I bw_INPUT %d -i %s -j %s", ruleIndex, c_iface, c_chain),
307*8542734aSAndroid Build Coastguard Worker StringPrintf("-I bw_OUTPUT %d -o %s -j %s", ruleIndex, c_iface, c_chain),
308*8542734aSAndroid Build Coastguard Worker StringPrintf("-A bw_FORWARD -i %s -j %s", c_iface, c_chain),
309*8542734aSAndroid Build Coastguard Worker StringPrintf("-A bw_FORWARD -o %s -j %s", c_iface, c_chain),
310*8542734aSAndroid Build Coastguard Worker };
311*8542734aSAndroid Build Coastguard Worker if (insertQuota) {
312*8542734aSAndroid Build Coastguard Worker cmds.push_back(StringPrintf("-I %s -m quota2 ! --quota %" PRIu64 " --name shared -j REJECT",
313*8542734aSAndroid Build Coastguard Worker c_chain, quota));
314*8542734aSAndroid Build Coastguard Worker }
315*8542734aSAndroid Build Coastguard Worker cmds.push_back("COMMIT\n");
316*8542734aSAndroid Build Coastguard Worker return {Join(cmds, "\n")};
317*8542734aSAndroid Build Coastguard Worker }
318*8542734aSAndroid Build Coastguard Worker
removeInterfaceSharedQuotaCommands(const std::string & iface,int64_t quota,bool deleteQuota)319*8542734aSAndroid Build Coastguard Worker const std::vector<std::string> removeInterfaceSharedQuotaCommands(const std::string& iface,
320*8542734aSAndroid Build Coastguard Worker int64_t quota, bool deleteQuota) {
321*8542734aSAndroid Build Coastguard Worker const std::string chain = "bw_costly_shared";
322*8542734aSAndroid Build Coastguard Worker const char* c_chain = chain.c_str();
323*8542734aSAndroid Build Coastguard Worker const char* c_iface = iface.c_str();
324*8542734aSAndroid Build Coastguard Worker std::vector<std::string> cmds = {
325*8542734aSAndroid Build Coastguard Worker "*filter",
326*8542734aSAndroid Build Coastguard Worker StringPrintf("-D bw_INPUT -i %s -j %s", c_iface, c_chain),
327*8542734aSAndroid Build Coastguard Worker StringPrintf("-D bw_OUTPUT -o %s -j %s", c_iface, c_chain),
328*8542734aSAndroid Build Coastguard Worker StringPrintf("-D bw_FORWARD -i %s -j %s", c_iface, c_chain),
329*8542734aSAndroid Build Coastguard Worker StringPrintf("-D bw_FORWARD -o %s -j %s", c_iface, c_chain),
330*8542734aSAndroid Build Coastguard Worker };
331*8542734aSAndroid Build Coastguard Worker if (deleteQuota) {
332*8542734aSAndroid Build Coastguard Worker cmds.push_back(StringPrintf("-D %s -m quota2 ! --quota %" PRIu64 " --name shared -j REJECT",
333*8542734aSAndroid Build Coastguard Worker c_chain, quota));
334*8542734aSAndroid Build Coastguard Worker }
335*8542734aSAndroid Build Coastguard Worker cmds.push_back("COMMIT\n");
336*8542734aSAndroid Build Coastguard Worker return {Join(cmds, "\n")};
337*8542734aSAndroid Build Coastguard Worker }
338*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,TestSetInterfaceSharedQuotaDuplicate)339*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaDuplicate) {
340*8542734aSAndroid Build Coastguard Worker constexpr uint64_t kQuota = 123456;
341*8542734aSAndroid Build Coastguard Worker const std::string iface = mTun.name();
342*8542734aSAndroid Build Coastguard Worker std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, 123456, true);
343*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
344*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
345*8542734aSAndroid Build Coastguard Worker
346*8542734aSAndroid Build Coastguard Worker expected = {};
347*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
348*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
349*8542734aSAndroid Build Coastguard Worker
350*8542734aSAndroid Build Coastguard Worker expected = removeInterfaceSharedQuotaCommands(iface, kQuota, true);
351*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
352*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
353*8542734aSAndroid Build Coastguard Worker }
354*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,TestSetInterfaceSharedQuotaUpdate)355*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaUpdate) {
356*8542734aSAndroid Build Coastguard Worker constexpr uint64_t kOldQuota = 123456;
357*8542734aSAndroid Build Coastguard Worker const std::string iface = mTun.name();
358*8542734aSAndroid Build Coastguard Worker std::vector<std::string> expected = makeInterfaceSharedQuotaCommands(iface, 1, kOldQuota, true);
359*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kOldQuota));
360*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
361*8542734aSAndroid Build Coastguard Worker
362*8542734aSAndroid Build Coastguard Worker constexpr uint64_t kNewQuota = kOldQuota + 1;
363*8542734aSAndroid Build Coastguard Worker expected = {};
364*8542734aSAndroid Build Coastguard Worker expectUpdateQuota(kNewQuota);
365*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kNewQuota));
366*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
367*8542734aSAndroid Build Coastguard Worker
368*8542734aSAndroid Build Coastguard Worker expected = removeInterfaceSharedQuotaCommands(iface, kNewQuota, true);
369*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
370*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
371*8542734aSAndroid Build Coastguard Worker }
372*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,TestSetInterfaceSharedQuotaTwoInterfaces)373*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, TestSetInterfaceSharedQuotaTwoInterfaces) {
374*8542734aSAndroid Build Coastguard Worker constexpr uint64_t kQuota = 123456;
375*8542734aSAndroid Build Coastguard Worker const std::vector<std::string> ifaces{
376*8542734aSAndroid Build Coastguard Worker {"a" + mTun.name()},
377*8542734aSAndroid Build Coastguard Worker {"b" + mTun.name()},
378*8542734aSAndroid Build Coastguard Worker };
379*8542734aSAndroid Build Coastguard Worker
380*8542734aSAndroid Build Coastguard Worker for (const auto& iface : ifaces) {
381*8542734aSAndroid Build Coastguard Worker // Quota rule is only added when the total number of
382*8542734aSAndroid Build Coastguard Worker // interfaces transitions from 0 -> 1.
383*8542734aSAndroid Build Coastguard Worker bool first = (iface == ifaces[0]);
384*8542734aSAndroid Build Coastguard Worker auto expected = makeInterfaceSharedQuotaCommands(iface, 1, kQuota, first);
385*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.setInterfaceSharedQuota(iface, kQuota));
386*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
387*8542734aSAndroid Build Coastguard Worker }
388*8542734aSAndroid Build Coastguard Worker
389*8542734aSAndroid Build Coastguard Worker for (const auto& iface : ifaces) {
390*8542734aSAndroid Build Coastguard Worker // Quota rule is only removed when the total number of
391*8542734aSAndroid Build Coastguard Worker // interfaces transitions from 1 -> 0.
392*8542734aSAndroid Build Coastguard Worker bool last = (iface == ifaces[1]);
393*8542734aSAndroid Build Coastguard Worker auto expected = removeInterfaceSharedQuotaCommands(iface, kQuota, last);
394*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, mBw.removeInterfaceSharedQuota(iface));
395*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
396*8542734aSAndroid Build Coastguard Worker }
397*8542734aSAndroid Build Coastguard Worker }
398*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,IptablesAlertCmd)399*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, IptablesAlertCmd) {
400*8542734aSAndroid Build Coastguard Worker std::vector<std::string> expected = {
401*8542734aSAndroid Build Coastguard Worker "*filter\n"
402*8542734aSAndroid Build Coastguard Worker "-I bw_global_alert -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
403*8542734aSAndroid Build Coastguard Worker "COMMIT\n"};
404*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpInsert, "MyWonderfulAlert", 123456));
405*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
406*8542734aSAndroid Build Coastguard Worker
407*8542734aSAndroid Build Coastguard Worker expected = {
408*8542734aSAndroid Build Coastguard Worker "*filter\n"
409*8542734aSAndroid Build Coastguard Worker "-D bw_global_alert -m quota2 ! --quota 123456 --name MyWonderfulAlert\n"
410*8542734aSAndroid Build Coastguard Worker "COMMIT\n"};
411*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, runIptablesAlertCmd(IptOp::IptOpDelete, "MyWonderfulAlert", 123456));
412*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
413*8542734aSAndroid Build Coastguard Worker }
414*8542734aSAndroid Build Coastguard Worker
TEST_F(BandwidthControllerTest,CostlyAlert)415*8542734aSAndroid Build Coastguard Worker TEST_F(BandwidthControllerTest, CostlyAlert) {
416*8542734aSAndroid Build Coastguard Worker const int64_t kQuota = 123456;
417*8542734aSAndroid Build Coastguard Worker int64_t alertBytes = 0;
418*8542734aSAndroid Build Coastguard Worker
419*8542734aSAndroid Build Coastguard Worker std::vector<std::string> expected = {
420*8542734aSAndroid Build Coastguard Worker "*filter\n"
421*8542734aSAndroid Build Coastguard Worker "-A bw_costly_shared -m quota2 ! --quota 123456 --name sharedAlert\n"
422*8542734aSAndroid Build Coastguard Worker "COMMIT\n"
423*8542734aSAndroid Build Coastguard Worker };
424*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, setCostlyAlert("shared", kQuota, &alertBytes));
425*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(kQuota, alertBytes);
426*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
427*8542734aSAndroid Build Coastguard Worker
428*8542734aSAndroid Build Coastguard Worker expected = {};
429*8542734aSAndroid Build Coastguard Worker expectUpdateQuota(kQuota);
430*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, setCostlyAlert("shared", kQuota + 1, &alertBytes));
431*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(kQuota + 1, alertBytes);
432*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
433*8542734aSAndroid Build Coastguard Worker
434*8542734aSAndroid Build Coastguard Worker expected = {
435*8542734aSAndroid Build Coastguard Worker "*filter\n"
436*8542734aSAndroid Build Coastguard Worker "-D bw_costly_shared -m quota2 ! --quota 123457 --name sharedAlert\n"
437*8542734aSAndroid Build Coastguard Worker "COMMIT\n"
438*8542734aSAndroid Build Coastguard Worker };
439*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, removeCostlyAlert("shared", &alertBytes));
440*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, alertBytes);
441*8542734aSAndroid Build Coastguard Worker expectIptablesRestoreCommands(expected);
442*8542734aSAndroid Build Coastguard Worker }
443*8542734aSAndroid Build Coastguard Worker
444