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_test.cc b/patchpanel/datapath_test.cc
index 77ad28b..4df4342 100644
--- a/patchpanel/datapath_test.cc
+++ b/patchpanel/datapath_test.cc
@@ -343,14 +343,26 @@
                                            "-j", "MARK", "--set-mark",
                                            "0x00002000/0x00003f00", "-w"),
                                true, nullptr));
+  EXPECT_CALL(runner, iptables(StrEq("mangle"),
+                               ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
+                                           "-j", "MARK", "--set-mark",
+                                           "0x03ea0000/0xffff0000", "-w"),
+                               true, nullptr));
   EXPECT_CALL(
       runner,
       ip6tables(StrEq("mangle"),
                 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
                             "--set-mark", "0x00002000/0x00003f00", "-w"),
                 true, nullptr));
+  EXPECT_CALL(
+      runner,
+      ip6tables(StrEq("mangle"),
+                ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
+                            "--set-mark", "0x03ea0000/0xffff0000", "-w"),
+                true, nullptr));
 
   Datapath datapath(&runner, &firewall);
+  datapath.SetIfnameIndex("eth0", 2);
   datapath.StartRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
                               TrafficSource::ARC);
 }
@@ -371,11 +383,21 @@
                                            "-j", "MARK", "--set-mark",
                                            "0x00002100/0x00003f00", "-w"),
                                true, nullptr));
+  EXPECT_CALL(runner, iptables(StrEq("mangle"),
+                               ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
+                                           "-j", "CONNMARK", "--restore-mark",
+                                           "--mask", "0xffff0000", "-w"),
+                               true, nullptr));
   EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
                                 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
                                             "-j", "MARK", "--set-mark",
                                             "0x00002100/0x00003f00", "-w"),
                                 true, nullptr));
+  EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+                                ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
+                                            "-j", "CONNMARK", "--restore-mark",
+                                            "--mask", "0xffff0000", "-w"),
+                                true, nullptr));
 
   Datapath datapath(&runner, &firewall);
   datapath.StartRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
@@ -413,14 +435,26 @@
                                            "-j", "MARK", "--set-mark",
                                            "0x00002000/0x00003f00", "-w"),
                                true, nullptr));
+  EXPECT_CALL(runner, iptables(StrEq("mangle"),
+                               ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
+                                           "-j", "MARK", "--set-mark",
+                                           "0x03ea0000/0xffff0000", "-w"),
+                               true, nullptr));
   EXPECT_CALL(
       runner,
       ip6tables(StrEq("mangle"),
                 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
                             "--set-mark", "0x00002000/0x00003f00", "-w"),
                 true, nullptr));
+  EXPECT_CALL(
+      runner,
+      ip6tables(StrEq("mangle"),
+                ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
+                            "--set-mark", "0x03ea0000/0xffff0000", "-w"),
+                true, nullptr));
 
   Datapath datapath(&runner, &firewall);
+  datapath.SetIfnameIndex("eth0", 2);
   datapath.StopRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
                              TrafficSource::ARC);
 }
@@ -441,11 +475,21 @@
                                            "-j", "MARK", "--set-mark",
                                            "0x00002100/0x00003f00", "-w"),
                                true, nullptr));
+  EXPECT_CALL(runner, iptables(StrEq("mangle"),
+                               ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
+                                           "-j", "CONNMARK", "--restore-mark",
+                                           "--mask", "0xffff0000", "-w"),
+                               true, nullptr));
   EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
                                 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
                                             "-j", "MARK", "--set-mark",
                                             "0x00002100/0x00003f00", "-w"),
                                 true, nullptr));
+  EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+                                ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
+                                            "-j", "CONNMARK", "--restore-mark",
+                                            "--mask", "0xffff0000", "-w"),
+                                true, nullptr));
 
   Datapath datapath(&runner, &firewall);
   datapath.StopRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),