blob: 8ece81e112eac7d3602be30e846c084695afda2e [file] [log] [blame]
Jie Jiangcf749152020-07-09 22:20:58 +09001// Copyright 2020 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "patchpanel/counters_service.h"
6
Jie Jiang8fd0ace2020-09-01 14:51:57 +09007#include <net/if.h>
Hugo Benichi058a26a2020-11-26 10:10:39 +09008
9#include <memory>
Jie Jiangcf749152020-07-09 22:20:58 +090010#include <string>
11#include <vector>
12
13#include <chromeos/dbus/service_constants.h>
14#include <gmock/gmock.h>
15#include <gtest/gtest.h>
16
Hugo Benichicd27f4e2020-11-19 18:32:23 +090017#include "patchpanel/mock_firewall.h"
Jie Jiangcf749152020-07-09 22:20:58 +090018
19namespace patchpanel {
Jie Jiangcf749152020-07-09 22:20:58 +090020
Hugo Benichi058a26a2020-11-26 10:10:39 +090021using ::testing::_;
22using ::testing::AnyNumber;
Jie Jianged0b1cc2020-07-10 15:55:33 +090023using ::testing::ContainerEq;
Jie Jiangcf749152020-07-09 22:20:58 +090024using ::testing::Contains;
Jie Jianged0b1cc2020-07-10 15:55:33 +090025using ::testing::DoAll;
Jie Jiang8fd0ace2020-09-01 14:51:57 +090026using ::testing::Each;
Jie Jiangcf749152020-07-09 22:20:58 +090027using ::testing::ElementsAreArray;
Jie Jiang8fd0ace2020-09-01 14:51:57 +090028using ::testing::Lt;
Jie Jianged0b1cc2020-07-10 15:55:33 +090029using ::testing::Return;
30using ::testing::SetArgPointee;
Jie Jiang8fd0ace2020-09-01 14:51:57 +090031using ::testing::SizeIs;
Jie Jianged0b1cc2020-07-10 15:55:33 +090032
33using Counter = CountersService::Counter;
34using SourceDevice = CountersService::SourceDevice;
35
36// The following two functions should be put outside the anounymous namespace
37// otherwise they could not be found in the tests.
38std::ostream& operator<<(std::ostream& os, const Counter& counter) {
39 os << "rx_bytes:" << counter.rx_bytes << ", rx_packets:" << counter.rx_packets
40 << ", tx_bytes:" << counter.tx_bytes
41 << ", tx_packets:" << counter.tx_packets;
42 return os;
43}
44
45bool operator==(const CountersService::Counter lhs,
46 const CountersService::Counter rhs) {
47 return lhs.rx_bytes == rhs.rx_bytes && lhs.rx_packets == rhs.rx_packets &&
48 lhs.tx_bytes == rhs.tx_bytes && lhs.tx_packets == rhs.tx_packets;
49}
50
51namespace {
52// The following string is copied from the real output of iptables v1.6.2 by
53// `iptables -t mangle -L -x -v`. This output contains all the accounting
54// chains/rules for eth0 and wlan0.
55// TODO(jiejiang): presubmit checker is complaining about the line length for
56// this (and the other raw strings in this file). Find a way to make it happy.
57const char kIptablesOutput[] = R"(
58Chain PREROUTING (policy ACCEPT 22785 packets, 136093545 bytes)
59 pkts bytes target prot opt in out source destination
60 18 2196 MARK all -- arcbr0 any anywhere anywhere MARK set 0x1
61 0 0 MARK all -- vmtap+ any anywhere anywhere MARK set 0x1
62 6526 68051766 MARK all -- arc_eth0 any anywhere anywhere MARK set 0x1
63 9 1104 MARK all -- arc_wlan0 any anywhere anywhere MARK set 0x1
64
65Chain INPUT (policy ACCEPT 4421 packets, 2461233 bytes)
66 pkts bytes target prot opt in out source destination
Hugo Benichi33af8f72020-11-20 10:08:47 +090067 312491 1767147156 rx_eth0 all -- eth0 any anywhere anywhere
68 0 0 rx_wlan0 all -- wlan0 any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +090069
70Chain FORWARD (policy ACCEPT 18194 packets, 133612816 bytes)
71 pkts bytes target prot opt in out source destination
Hugo Benichi33af8f72020-11-20 10:08:47 +090072 6511 68041668 tx_eth0 all -- any eth0 anywhere anywhere
73 11683 65571148 rx_eth0 all -- eth0 any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +090074
75Chain OUTPUT (policy ACCEPT 4574 packets, 2900995 bytes)
76 pkts bytes target prot opt in out source destination
77
78Chain POSTROUTING (policy ACCEPT 22811 packets, 136518827 bytes)
79 pkts bytes target prot opt in out source destination
Hugo Benichi33af8f72020-11-20 10:08:47 +090080 202160 1807550291 tx_eth0 all -- any eth0 anywhere anywhere owner socket exists
81 2 96 tx_wlan0 all -- any wlan0 anywhere anywhere owner socket exists
Jie Jianged0b1cc2020-07-10 15:55:33 +090082
Hugo Benichi33af8f72020-11-20 10:08:47 +090083Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +090084 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +090085 1366 244427 RETURN all -- any any anywhere anywhere mark match 0x100/0x3f00
86 0 0 RETURN all -- any any anywhere anywhere mark match 0x200/0x3f00
87 20 1670 RETURN all -- any any anywhere anywhere mark match 0x300/0x3f00
88 550 138402 RETURN all -- any any anywhere anywhere mark match 0x400/0x3f00
89 0 0 RETURN all -- any any anywhere anywhere mark match 0x500/0x3f00
90 5374 876172 RETURN all -- any any anywhere anywhere mark match 0x2000/0x3f00
91 39 2690 RETURN all -- any any anywhere anywhere mark match 0x2100/0x3f00
92 0 0 RETURN all -- any any anywhere anywhere mark match 0x2200/0x3f00
93 0 0 RETURN all -- any any anywhere anywhere mark match 0x2300/0x3f00
94 0 0 RETURN all -- any any anywhere anywhere mark match 0x2400/0x3f00
Hugo Benichiae5803d2020-12-08 10:49:48 +090095 4 123 all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +090096
Hugo Benichi33af8f72020-11-20 10:08:47 +090097Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +090098 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +090099 310 57004 RETURN all -- any any anywhere anywhere mark match 0x100/0x3f00
100 0 0 RETURN all -- any any anywhere anywhere mark match 0x200/0x3f00
101 0 0 RETURN all -- any any anywhere anywhere mark match 0x300/0x3f00
102 24 2801 RETURN all -- any any anywhere anywhere mark match 0x400/0x3f00
103 0 0 RETURN all -- any any anywhere anywhere mark match 0x500/0x3f00
104 0 0 RETURN all -- any any anywhere anywhere mark match 0x2000/0x3f00
105 0 0 RETURN all -- any any anywhere anywhere mark match 0x2100/0x3f00
106 0 0 RETURN all -- any any anywhere anywhere mark match 0x2200/0x3f00
107 0 0 RETURN all -- any any anywhere anywhere mark match 0x2300/0x3f00
108 0 0 RETURN all -- any any anywhere anywhere mark match 0x2400/0x3f00
Hugo Benichiae5803d2020-12-08 10:49:48 +0900109 0 0 all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900110
Hugo Benichi33af8f72020-11-20 10:08:47 +0900111Chain rx_eth0 (2 references)
Hugo Benichi92fa2032020-11-20 17:47:32 +0900112 pkts bytes target prot opt in out source destination
113 73 11938 RETURN all -- any any anywhere anywhere mark match 0x100/0x3f00
114 0 0 RETURN all -- any any anywhere anywhere mark match 0x200/0x3f00
115 0 0 RETURN all -- any any anywhere anywhere mark match 0x300/0x3f00
116 5 694 RETURN all -- any any anywhere anywhere mark match 0x400/0x3f00
117 0 0 RETURN all -- any any anywhere anywhere mark match 0x500/0x3f00
118 0 0 RETURN all -- any any anywhere anywhere mark match 0x2000/0x3f00
119 0 0 RETURN all -- any any anywhere anywhere mark match 0x2100/0x3f00
120 0 0 RETURN all -- any any anywhere anywhere mark match 0x2200/0x3f00
121 0 0 RETURN all -- any any anywhere anywhere mark match 0x2300/0x3f00
122 0 0 RETURN all -- any any anywhere anywhere mark match 0x2400/0x3f00
Hugo Benichiae5803d2020-12-08 10:49:48 +0900123 6 345 all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900124
Hugo Benichi33af8f72020-11-20 10:08:47 +0900125Chain rx_wlan0 (2 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900126 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900127 153 28098 RETURN all -- any any anywhere anywhere mark match 0x100/0x3f00
128 0 0 RETURN all -- any any anywhere anywhere mark match 0x200/0x3f00
129 0 0 RETURN all -- any any anywhere anywhere mark match 0x300/0x3f00
130 6 840 RETURN all -- any any anywhere anywhere mark match 0x400/0x3f00
131 0 0 RETURN all -- any any anywhere anywhere mark match 0x500/0x3f00
132 0 0 RETURN all -- any any anywhere anywhere mark match 0x2000/0x3f00
133 0 0 RETURN all -- any any anywhere anywhere mark match 0x2100/0x3f00
134 0 0 RETURN all -- any any anywhere anywhere mark match 0x2200/0x3f00
135 0 0 RETURN all -- any any anywhere anywhere mark match 0x2300/0x3f00
136 0 0 RETURN all -- any any anywhere anywhere mark match 0x2400/0x3f00
Hugo Benichiae5803d2020-12-08 10:49:48 +0900137 0 0 all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900138)";
139
Jie Jiangcf749152020-07-09 22:20:58 +0900140class MockProcessRunner : public MinijailedProcessRunner {
141 public:
142 MockProcessRunner() = default;
143 ~MockProcessRunner() = default;
144
145 MOCK_METHOD(int,
146 iptables,
147 (const std::string& table,
148 const std::vector<std::string>& argv,
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900149 bool log_failures,
150 std::string* output),
Jie Jiangcf749152020-07-09 22:20:58 +0900151 (override));
152 MOCK_METHOD(int,
153 ip6tables,
154 (const std::string& table,
155 const std::vector<std::string>& argv,
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900156 bool log_failures,
157 std::string* output),
Jie Jiangcf749152020-07-09 22:20:58 +0900158 (override));
159};
160
161class CountersServiceTest : public testing::Test {
162 protected:
163 void SetUp() override {
Hugo Benichicd27f4e2020-11-19 18:32:23 +0900164 datapath_ = std::make_unique<Datapath>(&runner_, &firewall_);
Hugo Benichi058a26a2020-11-26 10:10:39 +0900165 counters_svc_ =
166 std::make_unique<CountersService>(datapath_.get(), &runner_);
Jie Jiangcf749152020-07-09 22:20:58 +0900167 }
168
Hugo Benichiae5803d2020-12-08 10:49:48 +0900169 // Makes `iptables` and `ip6tables` returning |ipv4_output| and
170 // |ipv6_output|, respectively. Expects an empty map from GetCounters().
171 void TestBadIptablesOutput(const std::string& ipv4_output,
172 const std::string& ipv6_output) {
Jie Jianged0b1cc2020-07-10 15:55:33 +0900173 EXPECT_CALL(runner_, iptables(_, _, _, _))
Hugo Benichiae5803d2020-12-08 10:49:48 +0900174 .WillRepeatedly(DoAll(SetArgPointee<3>(ipv4_output), Return(0)));
Jie Jianged0b1cc2020-07-10 15:55:33 +0900175 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
Hugo Benichiae5803d2020-12-08 10:49:48 +0900176 .WillRepeatedly(DoAll(SetArgPointee<3>(ipv6_output), Return(0)));
Jie Jianged0b1cc2020-07-10 15:55:33 +0900177
178 auto actual = counters_svc_->GetCounters({});
179 std::map<SourceDevice, Counter> expected;
180
181 EXPECT_THAT(actual, ContainerEq(expected));
182 }
183
Jie Jiangcf749152020-07-09 22:20:58 +0900184 MockProcessRunner runner_;
Hugo Benichicd27f4e2020-11-19 18:32:23 +0900185 MockFirewall firewall_;
Hugo Benichicd27f4e2020-11-19 18:32:23 +0900186 std::unique_ptr<Datapath> datapath_;
Jie Jiangcf749152020-07-09 22:20:58 +0900187 std::unique_ptr<CountersService> counters_svc_;
188};
189
Hugo Benichi058a26a2020-11-26 10:10:39 +0900190TEST_F(CountersServiceTest, OnCreation_WithNoDevices) {
191 // The following commands are expected when eth0 comes up.
192 const std::vector<std::vector<std::string>> expected_calls{
193 {"-N", "rx_vpn", "-w"},
194 {"-N", "tx_vpn", "-w"},
195 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
196 "RETURN", "-w"},
197 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
198 "RETURN", "-w"},
199 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
200 "RETURN", "-w"},
201 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
202 "RETURN", "-w"},
203 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
204 "RETURN", "-w"},
205 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
206 "RETURN", "-w"},
207 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
208 "RETURN", "-w"},
209 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
210 "RETURN", "-w"},
211 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
212 "RETURN", "-w"},
213 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
214 "RETURN", "-w"},
215 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
216 "RETURN", "-w"},
217 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
218 "RETURN", "-w"},
219 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
220 "RETURN", "-w"},
221 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
222 "RETURN", "-w"},
223 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
224 "RETURN", "-w"},
225 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
226 "RETURN", "-w"},
227 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
228 "RETURN", "-w"},
229 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
230 "RETURN", "-w"},
231 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
232 "RETURN", "-w"},
233 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
234 "RETURN", "-w"},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900235 {"-A", "tx_vpn", "-w"},
236 {"-A", "rx_vpn", "-w"},
Hugo Benichi058a26a2020-11-26 10:10:39 +0900237 };
238
239 for (const auto& rule : expected_calls) {
240 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
241 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
242 }
243
244 counters_svc_->Init({});
245}
246
247TEST_F(CountersServiceTest, OnCreation_WithDevices) {
248 // The following commands are expected when eth0 comes up.
249 const std::vector<std::vector<std::string>> expected_calls{
250 {"-N", "rx_vpn", "-w"},
251 {"-N", "tx_vpn", "-w"},
252 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
253 "RETURN", "-w"},
254 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
255 "RETURN", "-w"},
256 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
257 "RETURN", "-w"},
258 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
259 "RETURN", "-w"},
260 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
261 "RETURN", "-w"},
262 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
263 "RETURN", "-w"},
264 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
265 "RETURN", "-w"},
266 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
267 "RETURN", "-w"},
268 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
269 "RETURN", "-w"},
270 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
271 "RETURN", "-w"},
272 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
273 "RETURN", "-w"},
274 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
275 "RETURN", "-w"},
276 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
277 "RETURN", "-w"},
278 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
279 "RETURN", "-w"},
280 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
281 "RETURN", "-w"},
282 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
283 "RETURN", "-w"},
284 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
285 "RETURN", "-w"},
286 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
287 "RETURN", "-w"},
288 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
289 "RETURN", "-w"},
290 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
291 "RETURN", "-w"},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900292 {"-A", "tx_vpn", "-w"},
293 {"-A", "rx_vpn", "-w"},
Hugo Benichi058a26a2020-11-26 10:10:39 +0900294 {"-N", "rx_wlan0", "-w"},
295 {"-N", "tx_wlan0", "-w"},
296 {"-A", "INPUT", "-i", "wlan0", "-j", "rx_wlan0", "-w"},
297 {"-A", "FORWARD", "-i", "wlan0", "-j", "rx_wlan0", "-w"},
298 {"-A", "POSTROUTING", "-o", "wlan0", "-j", "tx_wlan0", "-w"},
299 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
300 "RETURN", "-w"},
301 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
302 "RETURN", "-w"},
303 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
304 "RETURN", "-w"},
305 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
306 "RETURN", "-w"},
307 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
308 "RETURN", "-w"},
309 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
310 "RETURN", "-w"},
311 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
312 "RETURN", "-w"},
313 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
314 "RETURN", "-w"},
315 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
316 "RETURN", "-w"},
317 {"-A", "tx_wlan0", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
318 "RETURN", "-w"},
319 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
320 "RETURN", "-w"},
321 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
322 "RETURN", "-w"},
323 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
324 "RETURN", "-w"},
325 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
326 "RETURN", "-w"},
327 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
328 "RETURN", "-w"},
329 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
330 "RETURN", "-w"},
331 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
332 "RETURN", "-w"},
333 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
334 "RETURN", "-w"},
335 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
336 "RETURN", "-w"},
337 {"-A", "rx_wlan0", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
338 "RETURN", "-w"},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900339 {"-A", "tx_wlan0", "-w"},
340 {"-A", "rx_wlan0", "-w"},
Hugo Benichi058a26a2020-11-26 10:10:39 +0900341 };
342
343 for (const auto& rule : expected_calls) {
344 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
345 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
346 }
347
348 counters_svc_->Init({"wlan0"});
349}
350
351TEST_F(CountersServiceTest, OnPhysicalDeviceAdded) {
Jie Jiangcf749152020-07-09 22:20:58 +0900352 // The following commands are expected when eth0 comes up.
353 const std::vector<std::vector<std::string>> expected_calls{
Hugo Benichi33af8f72020-11-20 10:08:47 +0900354 {"-N", "rx_eth0", "-w"},
Hugo Benichiaf2021b2020-11-20 14:07:16 +0900355 {"-N", "tx_eth0", "-w"},
Hugo Benichi33af8f72020-11-20 10:08:47 +0900356 {"-A", "INPUT", "-i", "eth0", "-j", "rx_eth0", "-w"},
357 {"-A", "FORWARD", "-i", "eth0", "-j", "rx_eth0", "-w"},
Hugo Benichi33af8f72020-11-20 10:08:47 +0900358 {"-A", "POSTROUTING", "-o", "eth0", "-j", "tx_eth0", "-w"},
Hugo Benichiaf2021b2020-11-20 14:07:16 +0900359 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
360 "RETURN", "-w"},
361 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
362 "RETURN", "-w"},
363 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
364 "RETURN", "-w"},
365 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
366 "RETURN", "-w"},
367 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
368 "RETURN", "-w"},
369 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
370 "RETURN", "-w"},
371 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
372 "RETURN", "-w"},
373 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
374 "RETURN", "-w"},
375 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
376 "RETURN", "-w"},
377 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
378 "RETURN", "-w"},
379 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
380 "RETURN", "-w"},
381 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
382 "RETURN", "-w"},
383 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
384 "RETURN", "-w"},
385 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
386 "RETURN", "-w"},
387 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
388 "RETURN", "-w"},
389 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
390 "RETURN", "-w"},
391 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
392 "RETURN", "-w"},
393 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
394 "RETURN", "-w"},
395 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
396 "RETURN", "-w"},
397 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
398 "RETURN", "-w"},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900399 {"-A", "tx_eth0", "-w"},
400 {"-A", "rx_eth0", "-w"},
Jie Jiangcf749152020-07-09 22:20:58 +0900401 };
402
403 for (const auto& rule : expected_calls) {
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900404 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
405 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
Jie Jiangcf749152020-07-09 22:20:58 +0900406 }
407
Hugo Benichi058a26a2020-11-26 10:10:39 +0900408 counters_svc_->OnPhysicalDeviceAdded("eth0");
409}
410
411TEST_F(CountersServiceTest, OnVpnDeviceAdded) {
412 // The following commands are expected when eth0 comes up.
413 const std::vector<std::vector<std::string>> expected_calls{
414 {"-N", "rx_vpn", "-w"},
415 {"-N", "tx_vpn", "-w"},
416 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
417 "RETURN", "-w"},
418 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
419 "RETURN", "-w"},
420 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
421 "RETURN", "-w"},
422 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
423 "RETURN", "-w"},
424 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
425 "RETURN", "-w"},
426 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
427 "RETURN", "-w"},
428 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
429 "RETURN", "-w"},
430 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
431 "RETURN", "-w"},
432 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
433 "RETURN", "-w"},
434 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
435 "RETURN", "-w"},
436 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
437 "RETURN", "-w"},
438 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
439 "RETURN", "-w"},
440 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
441 "RETURN", "-w"},
442 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
443 "RETURN", "-w"},
444 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
445 "RETURN", "-w"},
446 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
447 "RETURN", "-w"},
448 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
449 "RETURN", "-w"},
450 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
451 "RETURN", "-w"},
452 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
453 "RETURN", "-w"},
454 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
455 "RETURN", "-w"},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900456 {"-A", "tx_vpn", "-w"},
457 {"-A", "rx_vpn", "-w"},
Hugo Benichi058a26a2020-11-26 10:10:39 +0900458 {"-A", "FORWARD", "-i", "tun0", "-j", "rx_vpn", "-w"},
459 {"-A", "INPUT", "-i", "tun0", "-j", "rx_vpn", "-w"},
460 {"-A", "POSTROUTING", "-o", "tun0", "-j", "tx_vpn", "-w"},
461 };
462
463 for (const auto& rule : expected_calls) {
464 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
465 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
466 }
467
468 counters_svc_->Init({});
469 counters_svc_->OnVpnDeviceAdded("tun0");
Jie Jiangcf749152020-07-09 22:20:58 +0900470}
471
472TEST_F(CountersServiceTest, OnSameDeviceAppearAgain) {
Hugo Benichiddf00842020-11-20 10:24:08 +0900473 // Makes the chain creation commands return false (we already have these
474 // rules).
475 EXPECT_CALL(runner_, iptables(_, Contains("-N"), _, _))
476 .WillRepeatedly(Return(1));
477 EXPECT_CALL(runner_, ip6tables(_, Contains("-N"), _, _))
478 .WillRepeatedly(Return(1));
Jie Jiangcf749152020-07-09 22:20:58 +0900479
480 // Creating chains commands are expected but no more creating rules command
481 // (with "-I" or "-A") should come.
Hugo Benichiddf00842020-11-20 10:24:08 +0900482 EXPECT_CALL(runner_, iptables(_, Contains("-A"), _, _)).Times(0);
483 EXPECT_CALL(runner_, ip6tables(_, Contains("-A"), _, _)).Times(0);
484 EXPECT_CALL(runner_, iptables(_, Contains("-I"), _, _)).Times(0);
485 EXPECT_CALL(runner_, ip6tables(_, Contains("-I"), _, _)).Times(0);
Jie Jiangcf749152020-07-09 22:20:58 +0900486
Hugo Benichi058a26a2020-11-26 10:10:39 +0900487 counters_svc_->OnPhysicalDeviceAdded("eth0");
Jie Jiangcf749152020-07-09 22:20:58 +0900488}
489
Jie Jiang8fd0ace2020-09-01 14:51:57 +0900490TEST_F(CountersServiceTest, ChainNameLength) {
Jie Jiang8fd0ace2020-09-01 14:51:57 +0900491 // The name of a new chain must be shorter than 29 characters, otherwise
492 // iptables will reject the request. Uses Each() here for simplicity since no
493 // other params could be longer than 29 for now.
494 static constexpr int kMaxChainNameLength = 29;
495 EXPECT_CALL(runner_, iptables(_, Each(SizeIs(Lt(kMaxChainNameLength))), _, _))
496 .Times(AnyNumber());
497 EXPECT_CALL(runner_,
498 ip6tables(_, Each(SizeIs(Lt(kMaxChainNameLength))), _, _))
499 .Times(AnyNumber());
500
501 static const std::string kLongInterfaceName(IFNAMSIZ, 'a');
Hugo Benichi058a26a2020-11-26 10:10:39 +0900502 counters_svc_->OnPhysicalDeviceAdded(kLongInterfaceName);
Jie Jiang8fd0ace2020-09-01 14:51:57 +0900503}
504
Jie Jianged0b1cc2020-07-10 15:55:33 +0900505TEST_F(CountersServiceTest, QueryTrafficCounters) {
506 EXPECT_CALL(runner_, iptables(_, _, _, _))
507 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
508 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
509 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
510
511 auto actual = counters_svc_->GetCounters({});
512
Hugo Benichi92fa2032020-11-20 17:47:32 +0900513 // The expected counters for eth0 and wlan0. All values are doubled because
514 // the same output will be returned for both iptables and ip6tables in the
515 // tests.
Jie Jianged0b1cc2020-07-10 15:55:33 +0900516 std::map<SourceDevice, Counter> expected{
Hugo Benichi92fa2032020-11-20 17:47:32 +0900517 {{TrafficCounter::CHROME, "eth0"},
518 {23876 /*rx_bytes*/, 146 /*rx_packets*/, 488854 /*tx_bytes*/,
519 2732 /*tx_packets*/}},
520 {{TrafficCounter::UPDATE_ENGINE, "eth0"},
521 {0 /*rx_bytes*/, 0 /*rx_packets*/, 3340 /*tx_bytes*/,
522 40 /*tx_packets*/}},
523 {{TrafficCounter::SYSTEM, "eth0"},
524 {1388 /*rx_bytes*/, 10 /*rx_packets*/, 276804 /*tx_bytes*/,
525 1100 /*tx_packets*/}},
526 {{TrafficCounter::ARC, "eth0"},
527 {0 /*rx_bytes*/, 0 /*rx_packets*/, 1752344 /*tx_bytes*/,
528 10748 /*tx_packets*/}},
529 {{TrafficCounter::CROSVM, "eth0"},
530 {0 /*rx_bytes*/, 0 /*rx_packets*/, 5380 /*tx_bytes*/,
531 78 /*tx_packets*/}},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900532 {{TrafficCounter::UNKNOWN, "eth0"},
533 {690 /*rx_bytes*/, 12 /*rx_packets*/, 246 /*tx_bytes*/,
534 8 /*tx_packets*/}},
Hugo Benichi92fa2032020-11-20 17:47:32 +0900535 {{TrafficCounter::CHROME, "wlan0"},
536 {56196 /*rx_bytes*/, 306 /*rx_packets*/, 114008 /*tx_bytes*/,
537 620 /*tx_packets*/}},
538 {{TrafficCounter::SYSTEM, "wlan0"},
539 {1680 /*rx_bytes*/, 12 /*rx_packets*/, 5602 /*tx_bytes*/,
Hugo Benichiae5803d2020-12-08 10:49:48 +0900540 48 /*tx_packets*/}},
541 };
Jie Jianged0b1cc2020-07-10 15:55:33 +0900542
543 EXPECT_THAT(actual, ContainerEq(expected));
544}
545
546TEST_F(CountersServiceTest, QueryTrafficCountersWithFilter) {
547 EXPECT_CALL(runner_, iptables(_, _, _, _))
548 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
549 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
550 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
551
552 // Only counters for eth0 should be returned. eth1 should be ignored.
553 auto actual = counters_svc_->GetCounters({"eth0", "eth1"});
554
Hugo Benichi92fa2032020-11-20 17:47:32 +0900555 // The expected counters for eth0. All values are doubled because
556 // the same output will be returned for both iptables and ip6tables in the
557 // tests.
Jie Jianged0b1cc2020-07-10 15:55:33 +0900558 std::map<SourceDevice, Counter> expected{
Hugo Benichi92fa2032020-11-20 17:47:32 +0900559 {{TrafficCounter::CHROME, "eth0"},
560 {23876 /*rx_bytes*/, 146 /*rx_packets*/, 488854 /*tx_bytes*/,
561 2732 /*tx_packets*/}},
562 {{TrafficCounter::UPDATE_ENGINE, "eth0"},
563 {0 /*rx_bytes*/, 0 /*rx_packets*/, 3340 /*tx_bytes*/,
564 40 /*tx_packets*/}},
565 {{TrafficCounter::SYSTEM, "eth0"},
566 {1388 /*rx_bytes*/, 10 /*rx_packets*/, 276804 /*tx_bytes*/,
567 1100 /*tx_packets*/}},
568 {{TrafficCounter::ARC, "eth0"},
569 {0 /*rx_bytes*/, 0 /*rx_packets*/, 1752344 /*tx_bytes*/,
570 10748 /*tx_packets*/}},
571 {{TrafficCounter::CROSVM, "eth0"},
572 {0 /*rx_bytes*/, 0 /*rx_packets*/, 5380 /*tx_bytes*/,
573 78 /*tx_packets*/}},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900574 {{TrafficCounter::UNKNOWN, "eth0"},
575 {690 /*rx_bytes*/, 12 /*rx_packets*/, 246 /*tx_bytes*/,
576 8 /*tx_packets*/}},
577 };
578
579 EXPECT_THAT(actual, ContainerEq(expected));
580}
581
582TEST_F(CountersServiceTest, QueryTraffic_UnknownTrafficOnly) {
583 const std::string unkwown_traffic_only = R"(
584Chain tx_eth0 (1 references)
585 pkts bytes target prot opt in out source destination
586 6511 68041668 all -- any any anywhere anywhere
587)";
588
589 EXPECT_CALL(runner_, iptables(_, _, _, _))
590 .WillRepeatedly(DoAll(SetArgPointee<3>(unkwown_traffic_only), Return(0)));
591 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
592 .WillRepeatedly(DoAll(SetArgPointee<3>(unkwown_traffic_only), Return(0)));
593
594 auto actual = counters_svc_->GetCounters({});
595
596 std::map<SourceDevice, Counter> expected{
597 {{TrafficCounter::UNKNOWN, "eth0"},
598 {0 /*rx_bytes*/, 0 /*rx_packets*/, 136083336 /*tx_bytes*/,
599 13022 /*tx_packets*/}},
Jie Jianged0b1cc2020-07-10 15:55:33 +0900600 };
601
602 EXPECT_THAT(actual, ContainerEq(expected));
603}
604
605TEST_F(CountersServiceTest, QueryTrafficCountersWithEmptyIPv4Output) {
Hugo Benichiae5803d2020-12-08 10:49:48 +0900606 TestBadIptablesOutput("", kIptablesOutput);
Jie Jianged0b1cc2020-07-10 15:55:33 +0900607}
608
609TEST_F(CountersServiceTest, QueryTrafficCountersWithEmptyIPv6Output) {
Hugo Benichiae5803d2020-12-08 10:49:48 +0900610 TestBadIptablesOutput(kIptablesOutput, "");
Jie Jianged0b1cc2020-07-10 15:55:33 +0900611}
612
613TEST_F(CountersServiceTest, QueryTrafficCountersWithOnlyChainName) {
614 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900615Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900616 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900617 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900618
Hugo Benichi92fa2032020-11-20 17:47:32 +0900619Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900620)";
Hugo Benichiae5803d2020-12-08 10:49:48 +0900621 TestBadIptablesOutput(kBadOutput, kIptablesOutput);
Jie Jianged0b1cc2020-07-10 15:55:33 +0900622}
623
624TEST_F(CountersServiceTest, QueryTrafficCountersWithOnlyChainNameAndHeader) {
625 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900626Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900627 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900628 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900629
Hugo Benichiae5803d2020-12-08 10:49:48 +0900630Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900631 pkts bytes target prot opt in out source destination
632)";
Hugo Benichiae5803d2020-12-08 10:49:48 +0900633 TestBadIptablesOutput(kBadOutput, kIptablesOutput);
Jie Jianged0b1cc2020-07-10 15:55:33 +0900634}
635
636TEST_F(CountersServiceTest, QueryTrafficCountersWithNotFinishedCountersLine) {
637 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900638Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900639 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900640 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900641
Hugo Benichi92fa2032020-11-20 17:47:32 +0900642Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900643 pkts bytes target prot opt in out source destination pkts bytes target prot opt in out source destination
644 0 )";
Hugo Benichiae5803d2020-12-08 10:49:48 +0900645 TestBadIptablesOutput(kBadOutput, kIptablesOutput);
Jie Jianged0b1cc2020-07-10 15:55:33 +0900646}
647
Jie Jiangcf749152020-07-09 22:20:58 +0900648} // namespace
649} // namespace patchpanel