blob: 2876c2e1b8a65ad29deedfcf37d795da5bd4a668 [file] [log] [blame]
Jie Jiang31a0b4e2020-07-09 15:06:16 +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#ifndef PATCHPANEL_COUNTERS_SERVICE_H_
6#define PATCHPANEL_COUNTERS_SERVICE_H_
7
8#include <set>
9#include <string>
10#include <vector>
11
12#include "patchpanel/minijailed_process_runner.h"
13#include "patchpanel/shill_client.h"
14
15namespace patchpanel {
16
17// This class manages the iptables rules for traffic counters, and queries
18// iptables to get the counters when a request comes. This class will set up
19// several iptable rules to track the counters for each possible combination of
20// {bytes, packets} x (Traffic source) x (shill device) x {rx, tx} x {IPv4,
21// IPv6}. These counters will never be removed after they are set up, and thus
22// they represent the traffic usage from boot time.
23//
Jie Jiang31a0b4e2020-07-09 15:06:16 +090024// Implementation details
25//
26// Rules: All the rules/chains for accounting are in (INPUT, FORWARD or
27// POSTROUTING) chain in the mangle table. These rules take effect after routing
28// and will not change the fate of a packet. When a new interface comes up, we
29// will create the following new rules/chains (using both iptables and
30// ip6tables):
31// - Four accounting chains:
32// - For rx packets, `ingress_input_{ifname}` and `ingress_forward_{ifname}`
33// for INPUT and FORWARD chain, respectively;
34// - For tx packets, `egress_postrouting_{ifname}` and
35// `egress_forward_{ifname}` for POSTROUTING and FORWARD chain,
36// respectively. Note that we use `--socket-exists` in POSTROUTING chain to
37// avoid packets from FORWARD being matched again here.
38// - One accounting rule in each accounting chain, which provides the actual
39// counter for accounting. We will extend this to several rules when source
40// marking is ready.
41// - One jumping rule for each accounting chain in the corresponding prebuilt
42// chain, which matches packets with this new interface.
43// The above rules and chains will never be removed once created, so we will
44// check if one rule exists before creating it.
45//
Jie Jiangcf749152020-07-09 22:20:58 +090046// TODO(jiejiang): Query will be implemented in future patches.
47//
Jie Jiang31a0b4e2020-07-09 15:06:16 +090048// Query: Two commands (iptables and ip6tables) will be executed in the mangle
49// table to get all the chains and rules. And then we perform a text parsing on
50// the output to get the counters. Counters for the same entry will be merged
51// before return.
52class CountersService {
53 public:
54 CountersService(ShillClient* shill_client, MinijailedProcessRunner* runner);
55 ~CountersService() = default;
56
57 private:
58 // TODO(b/161060333): Move the following two functions elsewhere.
59 // Creates a new chain using both iptables and ip6tables in the mangle table.
60 void IptablesNewChain(const std::string& chain_name);
61
62 // Creates a new rule using both iptables and ip6tables in the mangle table.
63 // The first element in |params| should be "-I" (insert) or "-A" (append), and
64 // this function will replace it with "-C" to do the check before executing
65 // the actual insert or append command. This function will also append "-w" to
66 // |params|. Note that |params| is passed by value because it will be modified
67 // inside the function, and the normal pattern to use this function is passing
68 // an rvalue (e.g., `IptablesNewRule({"-I", "INPUT", ...})`), so no extra copy
69 // should happen in such cases.
70 void IptablesNewRule(std::vector<std::string> params);
71
Jie Jiangcf749152020-07-09 22:20:58 +090072 // Installs the required chains and rules for the given shill device.
73 void SetupChainsAndRules(const std::string& ifname);
74 // Installs the accounting rules in the given accounting chain. Currently we
75 // only need one rule to match all the traffic, without distinguishing
76 // different sources.
77 void SetupAccountingRules(const std::string& chain_name);
78
Jie Jiang31a0b4e2020-07-09 15:06:16 +090079 void OnDeviceChanged(const std::set<std::string>& added,
80 const std::set<std::string>& removed);
81
82 ShillClient* shill_client_;
83 MinijailedProcessRunner* runner_;
84
85 base::WeakPtrFactory<CountersService> weak_factory_{this};
86};
87
88} // namespace patchpanel
89
90#endif // PATCHPANEL_COUNTERS_SERVICE_H_