blob: cd66647377bec8d4a9c0414ad04aa426ef603a96 [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
Jie Jianged0b1cc2020-07-10 15:55:33 +09008#include <map>
Jie Jiang31a0b4e2020-07-09 15:06:16 +09009#include <set>
10#include <string>
Jie Jianged0b1cc2020-07-10 15:55:33 +090011#include <utility>
Jie Jiang31a0b4e2020-07-09 15:06:16 +090012#include <vector>
13
Jie Jianged0b1cc2020-07-10 15:55:33 +090014#include <patchpanel/proto_bindings/patchpanel_service.pb.h>
15
Hugo Benichicd27f4e2020-11-19 18:32:23 +090016#include "patchpanel/datapath.h"
Jie Jiang31a0b4e2020-07-09 15:06:16 +090017#include "patchpanel/minijailed_process_runner.h"
Hugo Benichiaf2021b2020-11-20 14:07:16 +090018#include "patchpanel/routing_service.h"
Jie Jiang31a0b4e2020-07-09 15:06:16 +090019
20namespace patchpanel {
21
22// This class manages the iptables rules for traffic counters, and queries
23// iptables to get the counters when a request comes. This class will set up
24// several iptable rules to track the counters for each possible combination of
25// {bytes, packets} x (Traffic source) x (shill device) x {rx, tx} x {IPv4,
26// IPv6}. These counters will never be removed after they are set up, and thus
27// they represent the traffic usage from boot time.
28//
Jie Jiang31a0b4e2020-07-09 15:06:16 +090029// Implementation details
30//
31// Rules: All the rules/chains for accounting are in (INPUT, FORWARD or
32// POSTROUTING) chain in the mangle table. These rules take effect after routing
33// and will not change the fate of a packet. When a new interface comes up, we
34// will create the following new rules/chains (using both iptables and
35// ip6tables):
Hugo Benichiae5803d2020-12-08 10:49:48 +090036// - Two accounting chains:
37// - For rx packets, `rx_{ifname}` for INPUT and FORWARD chains;
38// - For tx packets, `tx_{ifname}` for POSTROUTING chain.
39// - One accounting rule in each accounting chain for every source defined in
40// RoutingService plus one final accounting rule for untagged traffic.
41// - Jumping rules for each accounting chain in the corresponding prebuilt
Jie Jiang31a0b4e2020-07-09 15:06:16 +090042// chain, which matches packets with this new interface.
Hugo Benichiae5803d2020-12-08 10:49:48 +090043// The above accounting rules and chains will never be removed once created, so
44// we will check if one rule exists before creating it. Jumping rules are added
45// and removed dynamically based on physical device and vpn device creation and
46// removal events.
Jie Jiang31a0b4e2020-07-09 15:06:16 +090047//
48// 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:
Jie Jianged0b1cc2020-07-10 15:55:33 +090054 using SourceDevice = std::pair<TrafficCounter::Source, std::string>;
55 struct Counter {
56 Counter() = default;
57 Counter(uint64_t rx_bytes,
58 uint64_t rx_packets,
59 uint64_t tx_bytes,
60 uint64_t tx_packets);
61
62 uint64_t rx_bytes = 0;
63 uint64_t rx_packets = 0;
64 uint64_t tx_bytes = 0;
65 uint64_t tx_packets = 0;
66 };
67
Hugo Benichi058a26a2020-11-26 10:10:39 +090068 CountersService(Datapath* datapath, MinijailedProcessRunner* runner);
Jie Jiang31a0b4e2020-07-09 15:06:16 +090069 ~CountersService() = default;
70
Hugo Benichi058a26a2020-11-26 10:10:39 +090071 // Installs the initial iptables setup for vpn accounting and for the given
72 // set of devices.
73 void Init(const std::set<std::string>& devices);
74 // Adds accounting rules and jump rules for a new physical device if this is
75 // the first time this device is seen.
76 void OnPhysicalDeviceAdded(const std::string& ifname);
77 // Removes jump rules for a physical device.
78 void OnPhysicalDeviceRemoved(const std::string& ifname);
79 // Adds accounting rules and jump rules for a new VPN device.
80 void OnVpnDeviceAdded(const std::string& ifname);
81 // Removes jump rules for a VPN device.
82 void OnVpnDeviceRemoved(const std::string& ifname);
Jie Jianged0b1cc2020-07-10 15:55:33 +090083 // Collects and returns counters from all the existing iptables rules.
84 // |devices| is the set of interfaces for which counters should be returned,
85 // any unknown interfaces will be ignored. If |devices| is empty, counters for
86 // all known interfaces will be returned. An empty map will be returned on
87 // any failure. Note that currently all traffic to/from an interface will be
88 // counted by (UNKNOWN, ifname), i.e., no other sources except for UNKNOWN are
89 // used.
90 std::map<SourceDevice, Counter> GetCounters(
91 const std::set<std::string>& devices);
92
Jie Jiang31a0b4e2020-07-09 15:06:16 +090093 private:
Hugo Benichi058a26a2020-11-26 10:10:39 +090094 // Creates an iptables chain in the mangle table. Returns true if the chain
95 // was created, or false if the chain already existed.
Hugo Benichicd27f4e2020-11-19 18:32:23 +090096 bool MakeAccountingChain(const std::string& chain_name);
Hugo Benichiaf2021b2020-11-20 14:07:16 +090097 bool AddAccountingRule(const std::string& chain_name, TrafficSource source);
Hugo Benichi058a26a2020-11-26 10:10:39 +090098 // Installs the required accounting chains and rules for the target
99 // |chain_tag|. Returns false if these chains and rules already existed.
100 bool SetupAccountingRules(const std::string& chain_tag);
101 // Installs jump rules in POSTROUTING to count traffic ingressing and
102 // egressing |ifname| with the accounting target |chain_tag|.
103 void SetupJumpRules(const std::string& op,
104 const std::string& ifname,
105 const std::string& chain_tag);
Jie Jiang31a0b4e2020-07-09 15:06:16 +0900106
Hugo Benichicd27f4e2020-11-19 18:32:23 +0900107 Datapath* datapath_;
Jie Jiang31a0b4e2020-07-09 15:06:16 +0900108 MinijailedProcessRunner* runner_;
Jie Jiang31a0b4e2020-07-09 15:06:16 +0900109};
110
Hugo Benichi92fa2032020-11-20 17:47:32 +0900111TrafficCounter::Source TrafficSourceToProto(TrafficSource source);
112
Jie Jiang31a0b4e2020-07-09 15:06:16 +0900113} // namespace patchpanel
114
115#endif // PATCHPANEL_COUNTERS_SERVICE_H_