blob: 1085395d15ad1a4f0bb55381b1b7b7239d0e805e [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, OnPhysicalDeviceAdded) {
Jie Jiangcf749152020-07-09 22:20:58 +0900191 // The following commands are expected when eth0 comes up.
192 const std::vector<std::vector<std::string>> expected_calls{
Hugo Benichi33af8f72020-11-20 10:08:47 +0900193 {"-N", "rx_eth0", "-w"},
Hugo Benichiaf2021b2020-11-20 14:07:16 +0900194 {"-N", "tx_eth0", "-w"},
Hugo Benichi33af8f72020-11-20 10:08:47 +0900195 {"-A", "INPUT", "-i", "eth0", "-j", "rx_eth0", "-w"},
196 {"-A", "FORWARD", "-i", "eth0", "-j", "rx_eth0", "-w"},
Hugo Benichi33af8f72020-11-20 10:08:47 +0900197 {"-A", "POSTROUTING", "-o", "eth0", "-j", "tx_eth0", "-w"},
Hugo Benichiaf2021b2020-11-20 14:07:16 +0900198 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
199 "RETURN", "-w"},
200 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
201 "RETURN", "-w"},
202 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
203 "RETURN", "-w"},
204 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
205 "RETURN", "-w"},
206 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
207 "RETURN", "-w"},
208 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
209 "RETURN", "-w"},
210 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
211 "RETURN", "-w"},
212 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
213 "RETURN", "-w"},
214 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
215 "RETURN", "-w"},
216 {"-A", "tx_eth0", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
217 "RETURN", "-w"},
218 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
219 "RETURN", "-w"},
220 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
221 "RETURN", "-w"},
222 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
223 "RETURN", "-w"},
224 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
225 "RETURN", "-w"},
226 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
227 "RETURN", "-w"},
228 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
229 "RETURN", "-w"},
230 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
231 "RETURN", "-w"},
232 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
233 "RETURN", "-w"},
234 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
235 "RETURN", "-w"},
236 {"-A", "rx_eth0", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
237 "RETURN", "-w"},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900238 {"-A", "tx_eth0", "-w"},
239 {"-A", "rx_eth0", "-w"},
Jie Jiangcf749152020-07-09 22:20:58 +0900240 };
241
242 for (const auto& rule : expected_calls) {
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900243 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
244 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
Jie Jiangcf749152020-07-09 22:20:58 +0900245 }
246
Hugo Benichi058a26a2020-11-26 10:10:39 +0900247 counters_svc_->OnPhysicalDeviceAdded("eth0");
248}
249
Hugo Benichidf5e1022021-03-23 15:48:31 +0900250TEST_F(CountersServiceTest, OnPhysicalDeviceRemoved) {
251 const std::vector<std::vector<std::string>> expected_calls{
252 {"-D", "INPUT", "-i", "eth0", "-j", "rx_eth0", "-w"},
253 {"-D", "FORWARD", "-i", "eth0", "-j", "rx_eth0", "-w"},
254 {"-D", "POSTROUTING", "-o", "eth0", "-j", "tx_eth0", "-w"},
255 };
256
257 for (const auto& rule : expected_calls) {
258 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
259 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
260 }
261
262 counters_svc_->OnPhysicalDeviceRemoved("eth0");
263}
264
Hugo Benichi058a26a2020-11-26 10:10:39 +0900265TEST_F(CountersServiceTest, OnVpnDeviceAdded) {
Hugo Benichidf5e1022021-03-23 15:48:31 +0900266 // The following commands are expected when tun0 comes up.
Hugo Benichi058a26a2020-11-26 10:10:39 +0900267 const std::vector<std::vector<std::string>> expected_calls{
268 {"-N", "rx_vpn", "-w"},
269 {"-N", "tx_vpn", "-w"},
270 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
271 "RETURN", "-w"},
272 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
273 "RETURN", "-w"},
274 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
275 "RETURN", "-w"},
276 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
277 "RETURN", "-w"},
278 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
279 "RETURN", "-w"},
280 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
281 "RETURN", "-w"},
282 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
283 "RETURN", "-w"},
284 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
285 "RETURN", "-w"},
286 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
287 "RETURN", "-w"},
288 {"-A", "tx_vpn", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
289 "RETURN", "-w"},
290 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000100/0x00003f00", "-j",
291 "RETURN", "-w"},
292 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000200/0x00003f00", "-j",
293 "RETURN", "-w"},
294 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000300/0x00003f00", "-j",
295 "RETURN", "-w"},
296 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000400/0x00003f00", "-j",
297 "RETURN", "-w"},
298 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00000500/0x00003f00", "-j",
299 "RETURN", "-w"},
300 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002000/0x00003f00", "-j",
301 "RETURN", "-w"},
302 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002100/0x00003f00", "-j",
303 "RETURN", "-w"},
304 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002200/0x00003f00", "-j",
305 "RETURN", "-w"},
306 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002300/0x00003f00", "-j",
307 "RETURN", "-w"},
308 {"-A", "rx_vpn", "-m", "mark", "--mark", "0x00002400/0x00003f00", "-j",
309 "RETURN", "-w"},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900310 {"-A", "tx_vpn", "-w"},
311 {"-A", "rx_vpn", "-w"},
Hugo Benichi058a26a2020-11-26 10:10:39 +0900312 {"-A", "FORWARD", "-i", "tun0", "-j", "rx_vpn", "-w"},
313 {"-A", "INPUT", "-i", "tun0", "-j", "rx_vpn", "-w"},
314 {"-A", "POSTROUTING", "-o", "tun0", "-j", "tx_vpn", "-w"},
315 };
316
317 for (const auto& rule : expected_calls) {
318 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
319 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
320 }
321
Hugo Benichi058a26a2020-11-26 10:10:39 +0900322 counters_svc_->OnVpnDeviceAdded("tun0");
Jie Jiangcf749152020-07-09 22:20:58 +0900323}
324
Hugo Benichi2f8a1ea2020-12-14 14:19:21 +0900325TEST_F(CountersServiceTest, OnVpnDeviceRemoved) {
326 const std::vector<std::vector<std::string>> expected_calls{
327 {"-D", "FORWARD", "-i", "ppp0", "-j", "rx_vpn", "-w"},
328 {"-D", "INPUT", "-i", "ppp0", "-j", "rx_vpn", "-w"},
329 {"-D", "POSTROUTING", "-o", "ppp0", "-j", "tx_vpn", "-w"},
330 };
331
332 for (const auto& rule : expected_calls) {
333 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
334 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
335 }
336
337 counters_svc_->OnVpnDeviceRemoved("ppp0");
338}
339
Jie Jiangcf749152020-07-09 22:20:58 +0900340TEST_F(CountersServiceTest, OnSameDeviceAppearAgain) {
Hugo Benichiddf00842020-11-20 10:24:08 +0900341 // Makes the chain creation commands return false (we already have these
342 // rules).
343 EXPECT_CALL(runner_, iptables(_, Contains("-N"), _, _))
344 .WillRepeatedly(Return(1));
345 EXPECT_CALL(runner_, ip6tables(_, Contains("-N"), _, _))
346 .WillRepeatedly(Return(1));
Jie Jiangcf749152020-07-09 22:20:58 +0900347
Hugo Benichidf5e1022021-03-23 15:48:31 +0900348 // Only the jump rules should be recreated.
349 const std::vector<std::vector<std::string>> expected_calls{
350 {"-A", "FORWARD", "-i", "eth0", "-j", "rx_eth0", "-w"},
351 {"-A", "INPUT", "-i", "eth0", "-j", "rx_eth0", "-w"},
352 {"-A", "POSTROUTING", "-o", "eth0", "-j", "tx_eth0", "-w"},
353 };
354 for (const auto& rule : expected_calls) {
355 EXPECT_CALL(runner_, iptables("mangle", ElementsAreArray(rule), _, _));
356 EXPECT_CALL(runner_, ip6tables("mangle", ElementsAreArray(rule), _, _));
357 }
358
359 // No fwmark matching rule should be created.
360 EXPECT_CALL(runner_, iptables(_, Contains("mark"), _, _)).Times(0);
361 EXPECT_CALL(runner_, ip6tables(_, Contains("mark"), _, _)).Times(0);
Jie Jiangcf749152020-07-09 22:20:58 +0900362
Hugo Benichi058a26a2020-11-26 10:10:39 +0900363 counters_svc_->OnPhysicalDeviceAdded("eth0");
Jie Jiangcf749152020-07-09 22:20:58 +0900364}
365
Jie Jiang8fd0ace2020-09-01 14:51:57 +0900366TEST_F(CountersServiceTest, ChainNameLength) {
Jie Jiang8fd0ace2020-09-01 14:51:57 +0900367 // The name of a new chain must be shorter than 29 characters, otherwise
368 // iptables will reject the request. Uses Each() here for simplicity since no
369 // other params could be longer than 29 for now.
370 static constexpr int kMaxChainNameLength = 29;
371 EXPECT_CALL(runner_, iptables(_, Each(SizeIs(Lt(kMaxChainNameLength))), _, _))
372 .Times(AnyNumber());
373 EXPECT_CALL(runner_,
374 ip6tables(_, Each(SizeIs(Lt(kMaxChainNameLength))), _, _))
375 .Times(AnyNumber());
376
377 static const std::string kLongInterfaceName(IFNAMSIZ, 'a');
Hugo Benichi058a26a2020-11-26 10:10:39 +0900378 counters_svc_->OnPhysicalDeviceAdded(kLongInterfaceName);
Jie Jiang8fd0ace2020-09-01 14:51:57 +0900379}
380
Jie Jianged0b1cc2020-07-10 15:55:33 +0900381TEST_F(CountersServiceTest, QueryTrafficCounters) {
382 EXPECT_CALL(runner_, iptables(_, _, _, _))
383 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
384 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
385 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
386
387 auto actual = counters_svc_->GetCounters({});
388
Hugo Benichi92fa2032020-11-20 17:47:32 +0900389 // The expected counters for eth0 and wlan0. All values are doubled because
390 // the same output will be returned for both iptables and ip6tables in the
391 // tests.
Jie Jianged0b1cc2020-07-10 15:55:33 +0900392 std::map<SourceDevice, Counter> expected{
Hugo Benichi92fa2032020-11-20 17:47:32 +0900393 {{TrafficCounter::CHROME, "eth0"},
394 {23876 /*rx_bytes*/, 146 /*rx_packets*/, 488854 /*tx_bytes*/,
395 2732 /*tx_packets*/}},
396 {{TrafficCounter::UPDATE_ENGINE, "eth0"},
397 {0 /*rx_bytes*/, 0 /*rx_packets*/, 3340 /*tx_bytes*/,
398 40 /*tx_packets*/}},
399 {{TrafficCounter::SYSTEM, "eth0"},
400 {1388 /*rx_bytes*/, 10 /*rx_packets*/, 276804 /*tx_bytes*/,
401 1100 /*tx_packets*/}},
402 {{TrafficCounter::ARC, "eth0"},
403 {0 /*rx_bytes*/, 0 /*rx_packets*/, 1752344 /*tx_bytes*/,
404 10748 /*tx_packets*/}},
405 {{TrafficCounter::CROSVM, "eth0"},
406 {0 /*rx_bytes*/, 0 /*rx_packets*/, 5380 /*tx_bytes*/,
407 78 /*tx_packets*/}},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900408 {{TrafficCounter::UNKNOWN, "eth0"},
409 {690 /*rx_bytes*/, 12 /*rx_packets*/, 246 /*tx_bytes*/,
410 8 /*tx_packets*/}},
Hugo Benichi92fa2032020-11-20 17:47:32 +0900411 {{TrafficCounter::CHROME, "wlan0"},
412 {56196 /*rx_bytes*/, 306 /*rx_packets*/, 114008 /*tx_bytes*/,
413 620 /*tx_packets*/}},
414 {{TrafficCounter::SYSTEM, "wlan0"},
415 {1680 /*rx_bytes*/, 12 /*rx_packets*/, 5602 /*tx_bytes*/,
Hugo Benichiae5803d2020-12-08 10:49:48 +0900416 48 /*tx_packets*/}},
417 };
Jie Jianged0b1cc2020-07-10 15:55:33 +0900418
419 EXPECT_THAT(actual, ContainerEq(expected));
420}
421
422TEST_F(CountersServiceTest, QueryTrafficCountersWithFilter) {
423 EXPECT_CALL(runner_, iptables(_, _, _, _))
424 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
425 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
426 .WillRepeatedly(DoAll(SetArgPointee<3>(kIptablesOutput), Return(0)));
427
428 // Only counters for eth0 should be returned. eth1 should be ignored.
429 auto actual = counters_svc_->GetCounters({"eth0", "eth1"});
430
Hugo Benichi92fa2032020-11-20 17:47:32 +0900431 // The expected counters for eth0. All values are doubled because
432 // the same output will be returned for both iptables and ip6tables in the
433 // tests.
Jie Jianged0b1cc2020-07-10 15:55:33 +0900434 std::map<SourceDevice, Counter> expected{
Hugo Benichi92fa2032020-11-20 17:47:32 +0900435 {{TrafficCounter::CHROME, "eth0"},
436 {23876 /*rx_bytes*/, 146 /*rx_packets*/, 488854 /*tx_bytes*/,
437 2732 /*tx_packets*/}},
438 {{TrafficCounter::UPDATE_ENGINE, "eth0"},
439 {0 /*rx_bytes*/, 0 /*rx_packets*/, 3340 /*tx_bytes*/,
440 40 /*tx_packets*/}},
441 {{TrafficCounter::SYSTEM, "eth0"},
442 {1388 /*rx_bytes*/, 10 /*rx_packets*/, 276804 /*tx_bytes*/,
443 1100 /*tx_packets*/}},
444 {{TrafficCounter::ARC, "eth0"},
445 {0 /*rx_bytes*/, 0 /*rx_packets*/, 1752344 /*tx_bytes*/,
446 10748 /*tx_packets*/}},
447 {{TrafficCounter::CROSVM, "eth0"},
448 {0 /*rx_bytes*/, 0 /*rx_packets*/, 5380 /*tx_bytes*/,
449 78 /*tx_packets*/}},
Hugo Benichiae5803d2020-12-08 10:49:48 +0900450 {{TrafficCounter::UNKNOWN, "eth0"},
451 {690 /*rx_bytes*/, 12 /*rx_packets*/, 246 /*tx_bytes*/,
452 8 /*tx_packets*/}},
453 };
454
455 EXPECT_THAT(actual, ContainerEq(expected));
456}
457
458TEST_F(CountersServiceTest, QueryTraffic_UnknownTrafficOnly) {
459 const std::string unkwown_traffic_only = R"(
460Chain tx_eth0 (1 references)
461 pkts bytes target prot opt in out source destination
462 6511 68041668 all -- any any anywhere anywhere
463)";
464
465 EXPECT_CALL(runner_, iptables(_, _, _, _))
466 .WillRepeatedly(DoAll(SetArgPointee<3>(unkwown_traffic_only), Return(0)));
467 EXPECT_CALL(runner_, ip6tables(_, _, _, _))
468 .WillRepeatedly(DoAll(SetArgPointee<3>(unkwown_traffic_only), Return(0)));
469
470 auto actual = counters_svc_->GetCounters({});
471
472 std::map<SourceDevice, Counter> expected{
473 {{TrafficCounter::UNKNOWN, "eth0"},
474 {0 /*rx_bytes*/, 0 /*rx_packets*/, 136083336 /*tx_bytes*/,
475 13022 /*tx_packets*/}},
Jie Jianged0b1cc2020-07-10 15:55:33 +0900476 };
477
478 EXPECT_THAT(actual, ContainerEq(expected));
479}
480
481TEST_F(CountersServiceTest, QueryTrafficCountersWithEmptyIPv4Output) {
Hugo Benichiae5803d2020-12-08 10:49:48 +0900482 TestBadIptablesOutput("", kIptablesOutput);
Jie Jianged0b1cc2020-07-10 15:55:33 +0900483}
484
485TEST_F(CountersServiceTest, QueryTrafficCountersWithEmptyIPv6Output) {
Hugo Benichiae5803d2020-12-08 10:49:48 +0900486 TestBadIptablesOutput(kIptablesOutput, "");
Jie Jianged0b1cc2020-07-10 15:55:33 +0900487}
488
489TEST_F(CountersServiceTest, QueryTrafficCountersWithOnlyChainName) {
490 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900491Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900492 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900493 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900494
Hugo Benichi92fa2032020-11-20 17:47:32 +0900495Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900496)";
Hugo Benichiae5803d2020-12-08 10:49:48 +0900497 TestBadIptablesOutput(kBadOutput, kIptablesOutput);
Jie Jianged0b1cc2020-07-10 15:55:33 +0900498}
499
500TEST_F(CountersServiceTest, QueryTrafficCountersWithOnlyChainNameAndHeader) {
501 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900502Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900503 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900504 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900505
Hugo Benichiae5803d2020-12-08 10:49:48 +0900506Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900507 pkts bytes target prot opt in out source destination
508)";
Hugo Benichiae5803d2020-12-08 10:49:48 +0900509 TestBadIptablesOutput(kBadOutput, kIptablesOutput);
Jie Jianged0b1cc2020-07-10 15:55:33 +0900510}
511
512TEST_F(CountersServiceTest, QueryTrafficCountersWithNotFinishedCountersLine) {
513 const std::string kBadOutput = R"(
Hugo Benichi92fa2032020-11-20 17:47:32 +0900514Chain tx_eth0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900515 pkts bytes target prot opt in out source destination
Hugo Benichi92fa2032020-11-20 17:47:32 +0900516 6511 68041668 RETURN all -- any any anywhere anywhere
Jie Jianged0b1cc2020-07-10 15:55:33 +0900517
Hugo Benichi92fa2032020-11-20 17:47:32 +0900518Chain tx_wlan0 (1 references)
Jie Jianged0b1cc2020-07-10 15:55:33 +0900519 pkts bytes target prot opt in out source destination pkts bytes target prot opt in out source destination
520 0 )";
Hugo Benichiae5803d2020-12-08 10:49:48 +0900521 TestBadIptablesOutput(kBadOutput, kIptablesOutput);
Jie Jianged0b1cc2020-07-10 15:55:33 +0900522}
523
Jie Jiangcf749152020-07-09 22:20:58 +0900524} // namespace
525} // namespace patchpanel