patchpanel: mark forwarded traffic with fwmark routing tag

This patch adds mangle PREROUTING iptables rule for marking forwarded
traffic from VMs and containers with the fwmark routing tag.

For ARC++ and ARCVM, the traffic is directly marked with the fwmark
routing tag corresponding to the target output interface.

For other VMs that track the default network, a CONNMARK restore rule
is set to reapply the fwmark routing tag saved in conntrack. A follow-up
patch will add the POSTROUTING rules for setting CONNMARK based on the
output interface selected by routing.

BUG=b:161507671
BUG=b:161508179
TEST=Unit tests. Flashed rammus, checked ARC++ connectivity and Crosvm
connectivity, checked that traffic is correctly tagged in PREROUTING by
observing iptables counters for ARC++.

Change-Id: I648bbd55f2670192a764ce9ba65846912e7eb609
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2377336
Tested-by: Hugo Benichi <hugobenichi@google.com>
Commit-Queue: Hugo Benichi <hugobenichi@google.com>
Reviewed-by: Garrick Evans <garrick@chromium.org>
Reviewed-by: Taoyu Li <taoyl@chromium.org>
diff --git a/patchpanel/datapath.h b/patchpanel/datapath.h
index b0337e1..c2dcbfd 100644
--- a/patchpanel/datapath.h
+++ b/patchpanel/datapath.h
@@ -235,9 +235,20 @@
   virtual bool AddAdbPortAccessRule(const std::string& ifname);
   virtual void DeleteAdbPortAccessRule(const std::string& ifname);
 
+  // Set or override the interface name to index mapping for |ifname|.
+  // Only used for testing.
+  void SetIfnameIndex(const std::string& ifname, int ifindex);
+
   MinijailedProcessRunner& runner() const;
 
  private:
+  bool ModifyConnmarkRestore(IpFamily family,
+                             const std::string& chain,
+                             const std::string& op,
+                             const std::string& iif);
+  bool ModifyFwmarkRoutingTag(const std::string& op,
+                              const std::string& ext_ifname,
+                              const std::string& int_ifname);
   bool ModifyFwmarkSourceTag(const std::string& op,
                              const std::string& iif,
                              TrafficSource source);
@@ -252,12 +263,22 @@
                           const std::string& iif,
                           const std::string& oif,
                           bool log_failures = true);
+  bool ModifyRtentry(ioctl_req_t op, struct rtentry* route);
+  int FindIfIndex(const std::string& ifname);
 
   MinijailedProcessRunner* process_runner_;
   Firewall* firewall_;
   ioctl_t ioctl_;
 
-  bool ModifyRtentry(ioctl_req_t op, struct rtentry* route);
+  // A map used for remembering the interface index of an interface. This
+  // information is necessary when cleaning up iptables fwmark rules that
+  // directly references the interface index. When removing these rules on
+  // an RTM_DELLINK event, the interface index cannot be retrieved anymore.
+  // A new entry is only added when a new physical device appears, and entries
+  // are not removed.
+  // TODO(b/161507671) Rely on RoutingService to obtain this information once
+  // shill/routing_table.cc has been migrated to patchpanel.
+  std::map<std::string, int> if_nametoindex_;
 
   DISALLOW_COPY_AND_ASSIGN(Datapath);
 };