patchpanel: Query iptables counters in CountersService

This patch adds the code for querying iptables and parsing its output to
get traffic counters. Also adds some corresponding unit tests.

BUG=b:160113164
TEST=cros_workon_make --board=$BOARD --test patchpanel

Change-Id: Ifd73c077c8796dc8f84dfe1301bf57140d30f58a
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2291854
Tested-by: Jie Jiang <jiejiang@chromium.org>
Commit-Queue: Jie Jiang <jiejiang@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
diff --git a/patchpanel/counters_service.h b/patchpanel/counters_service.h
index 2876c2e..b2e8cde 100644
--- a/patchpanel/counters_service.h
+++ b/patchpanel/counters_service.h
@@ -5,10 +5,14 @@
 #ifndef PATCHPANEL_COUNTERS_SERVICE_H_
 #define PATCHPANEL_COUNTERS_SERVICE_H_
 
+#include <map>
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
+#include <patchpanel/proto_bindings/patchpanel_service.pb.h>
+
 #include "patchpanel/minijailed_process_runner.h"
 #include "patchpanel/shill_client.h"
 
@@ -43,17 +47,39 @@
 // The above rules and chains will never be removed once created, so we will
 // check if one rule exists before creating it.
 //
-// TODO(jiejiang): Query will be implemented in future patches.
-//
 // Query: Two commands (iptables and ip6tables) will be executed in the mangle
 // table to get all the chains and rules. And then we perform a text parsing on
 // the output to get the counters. Counters for the same entry will be merged
 // before return.
 class CountersService {
  public:
+  using SourceDevice = std::pair<TrafficCounter::Source, std::string>;
+  struct Counter {
+    Counter() = default;
+    Counter(uint64_t rx_bytes,
+            uint64_t rx_packets,
+            uint64_t tx_bytes,
+            uint64_t tx_packets);
+
+    uint64_t rx_bytes = 0;
+    uint64_t rx_packets = 0;
+    uint64_t tx_bytes = 0;
+    uint64_t tx_packets = 0;
+  };
+
   CountersService(ShillClient* shill_client, MinijailedProcessRunner* runner);
   ~CountersService() = default;
 
+  // Collects and returns counters from all the existing iptables rules.
+  // |devices| is the set of interfaces for which counters should be returned,
+  // any unknown interfaces will be ignored. If |devices| is empty, counters for
+  // all known interfaces will be returned. An empty map will be returned on
+  // any failure. Note that currently all traffic to/from an interface will be
+  // counted by (UNKNOWN, ifname), i.e., no other sources except for UNKNOWN are
+  // used.
+  std::map<SourceDevice, Counter> GetCounters(
+      const std::set<std::string>& devices);
+
  private:
   // TODO(b/161060333): Move the following two functions elsewhere.
   // Creates a new chain using both iptables and ip6tables in the mangle table.