patchpanel: mark connections with fwmark routing tags

This patch enables per-network tracking of connections using
CONNMARK conntrack for storing the fwmark routing tag associated with
the output interface selected by routing. This is achieved with a mangle
POSTROUTING rule using the CONNMARK target.

A follow-up patch in shill will add the final piece and add ip rules
using these fwmark routing tags to complete the per-network connection
routing and fwmark routing system.

BUG=b:161507671
BUG=b:161508179
TEST=Unit tests. Manual tests: verified with /proc/net/ip_conntrack that
conntrack entries get marked with the fwmark routing tag of the network
through which they are routed.

Change-Id: I9f147179283246c1aafda87ad716e209ce387736
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2377337
Tested-by: Hugo Benichi <hugobenichi@google.com>
Tested-by: Mitu Aktar <mitu64649@gmail.com>
Commit-Queue: Hugo Benichi <hugobenichi@google.com>
Reviewed-by: Taoyu Li <taoyl@chromium.org>
diff --git a/patchpanel/datapath_test.cc b/patchpanel/datapath_test.cc
index 4df4342..f69e7d6 100644
--- a/patchpanel/datapath_test.cc
+++ b/patchpanel/datapath_test.cc
@@ -591,6 +591,35 @@
   }
 }
 
+TEST(DatapathTest, StartStopConnectionPinning) {
+  MockProcessRunner runner;
+  MockFirewall firewall;
+  EXPECT_CALL(runner, iptables(StrEq("mangle"),
+                               ElementsAre("-A", "POSTROUTING", "-o", "eth0",
+                                           "-j", "CONNMARK", "--set-mark",
+                                           "0x03eb0000/0xffff0000", "-w"),
+                               true, nullptr));
+  EXPECT_CALL(runner, iptables(StrEq("mangle"),
+                               ElementsAre("-D", "POSTROUTING", "-o", "eth0",
+                                           "-j", "CONNMARK", "--set-mark",
+                                           "0x03eb0000/0xffff0000", "-w"),
+                               true, nullptr));
+  EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+                                ElementsAre("-A", "POSTROUTING", "-o", "eth0",
+                                            "-j", "CONNMARK", "--set-mark",
+                                            "0x03eb0000/0xffff0000", "-w"),
+                                true, nullptr));
+  EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
+                                ElementsAre("-D", "POSTROUTING", "-o", "eth0",
+                                            "-j", "CONNMARK", "--set-mark",
+                                            "0x03eb0000/0xffff0000", "-w"),
+                                true, nullptr));
+  Datapath datapath(&runner, &firewall);
+  datapath.SetIfnameIndex("eth0", 3);
+  datapath.StartConnectionPinning("eth0");
+  datapath.StopConnectionPinning("eth0");
+}
+
 TEST(DatapathTest, AddInboundIPv4DNAT) {
   MockProcessRunner runner;
   MockFirewall firewall;