patchpanel: Support open a new netns via ConnectNamespace
Currently the ConnectNamespace API exposed by patchpanel via d-bus only
supports passing in a pid of a process and doing "ConnectNamespace" for
the netns associated with this process. While in the tast tests,
sometimes we need to open a new netns directly, and execute processes in
the created netns.
For this usage, this patch modifies the ConnectNamespace API so that
patchpanel accepts passing a special pid (i.e., pid==-1) to indicates
the client wants a new netns, invokes `ip netns add` for this case, and
returns the name of the created netns.
BUG=b:185210339
TEST=unit_tests;
TEST=Used this API in test VPN tast test, verified it worked;
TEST=Checked playstore still worked.
Change-Id: I3bbfab89df24899127e6087b0c0533e2c96037dc
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2896672
Reviewed-by: Garrick Evans <garrick@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
Tested-by: Jie Jiang <jiejiang@chromium.org>
Commit-Queue: Jie Jiang <jiejiang@chromium.org>
diff --git a/patchpanel/datapath_test.cc b/patchpanel/datapath_test.cc
index ae76b37..19cf8d7 100644
--- a/patchpanel/datapath_test.cc
+++ b/patchpanel/datapath_test.cc
@@ -118,6 +118,8 @@
int(const std::string& key,
const std::string& value,
bool log_failures));
+ MOCK_METHOD2(ip_netns_add,
+ int(const std::string& netns_name, bool log_failures));
MOCK_METHOD3(ip_netns_attach,
int(const std::string& netns_name,
pid_t netns_pid,
@@ -171,6 +173,11 @@
EXPECT_CALL(runner, sysctl_w(StrEq(key), StrEq(value), _));
}
+void Verify_ip_netns_add(MockProcessRunner& runner,
+ const std::string& netns_name) {
+ EXPECT_CALL(runner, ip_netns_add(StrEq(netns_name), _));
+}
+
void Verify_ip_netns_attach(MockProcessRunner& runner,
const std::string& netns_name,
pid_t pid) {
@@ -645,6 +652,33 @@
datapath.StopRoutingNamespace(nsinfo);
}
+TEST(DatapathTest, StartRoutingNewNamespace) {
+ MockProcessRunner runner;
+ MockFirewall firewall;
+ MacAddress mac = {1, 2, 3, 4, 5, 6};
+
+ // The running may fail at checking ScopedNS.IsValid() in
+ // Datapath::ConnectVethPair(), so we only check if `ip netns add` is invoked
+ // correctly here.
+ Verify_ip_netns_add(runner, "netns_foo");
+
+ ConnectedNamespace nsinfo = {};
+ nsinfo.pid = ConnectedNamespace::kNewNetnsPid;
+ nsinfo.netns_name = "netns_foo";
+ nsinfo.source = TrafficSource::USER;
+ nsinfo.outbound_ifname = "";
+ nsinfo.route_on_vpn = true;
+ nsinfo.host_ifname = "arc_ns0";
+ nsinfo.peer_ifname = "veth0";
+ nsinfo.peer_subnet = std::make_unique<Subnet>(Ipv4Addr(100, 115, 92, 128), 30,
+ base::DoNothing());
+ nsinfo.peer_mac_addr = mac;
+ Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
+ datapath.StartRoutingNamespace(nsinfo);
+ ioctl_reqs.clear();
+ ioctl_rtentry_args.clear();
+}
+
TEST(DatapathTest, StartRoutingDevice_Arc) {
MockProcessRunner runner;
MockFirewall firewall;