This is an automated email from the ASF dual-hosted git repository.
bmahler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git
The following commit(s) were added to refs/heads/master by this push:
new 70d9da223 [veth] Provide the ability to set veth peer link MAC address
on creation.
70d9da223 is described below
commit 70d9da223a204dc89431aa7b26db7beeb53a9f3c
Author: Jason Zhou <[email protected]>
AuthorDate: Mon Jul 15 18:02:54 2024 -0400
[veth] Provide the ability to set veth peer link MAC address on creation.
This addresses the previous todo where we want to set the MAC address
of the peer link when we are creating a veth pair so that we can avoid
the race condition we are racing against udev to see who will set the
MAC address of the interface last.
See: https://reviews.apache.org/r/75087/
See: https://issues.apache.org/jira/browse/MESOS-10243
Review: https://reviews.apache.org/r/75090/
---
src/linux/routing/link/veth.cpp | 47 +++++++----
src/linux/routing/link/veth.hpp | 6 +-
.../mesos/isolators/network/port_mapping.cpp | 23 ++---
src/tests/containerizer/routing_tests.cpp | 97 +++++++++-------------
4 files changed, 77 insertions(+), 96 deletions(-)
diff --git a/src/linux/routing/link/veth.cpp b/src/linux/routing/link/veth.cpp
index 36aad5fec..12c00cd16 100644
--- a/src/linux/routing/link/veth.cpp
+++ b/src/linux/routing/link/veth.cpp
@@ -38,42 +38,55 @@ Try<bool> create(
const string& veth,
const string& peer,
const Option<pid_t>& pid,
- const Option<net::MAC>& veth_mac)
+ const Option<net::MAC>& veth_mac,
+ const Option<net::MAC>& peer_mac)
{
+ auto set_addr_from_mac = [](struct rtnl_link* link, const net::MAC& mac)
+ {
+ struct nl_addr* addr;
+ unsigned char mac_addr_uchar[6];
+ for (int i = 0; i < 6; i++) {
+ mac_addr_uchar[i] = (unsigned char) mac[i];
+ }
+ addr = nl_addr_build(AF_LLC, mac_addr_uchar, 6);
+ rtnl_link_set_addr(link, addr);
+ return addr;
+ };
+
Try<Netlink<struct nl_sock>> socket = routing::socket();
if (socket.isError()) {
return Error(socket.error());
}
struct nl_sock *sock = socket->get();
- struct rtnl_link *link, *peer_link;
+ struct rtnl_link *veth_link, *peer_link;
int error = -NLE_NOMEM;
- if (!(link = rtnl_link_veth_alloc())) {
+ if (!(veth_link = rtnl_link_veth_alloc())) {
return Error(nl_geterror(error));
}
- peer_link = rtnl_link_veth_get_peer(link);
-
- struct nl_addr *addr;
+ peer_link = rtnl_link_veth_get_peer(veth_link);
+ Option<struct nl_addr*> veth_addr, peer_addr;
if (veth_mac.isSome()) {
- unsigned char mac_addr_uchar[6];
- for (int i = 0; i < 6; i++) {
- mac_addr_uchar[i] = (unsigned char) (*veth_mac)[i];
- }
- addr = nl_addr_build(AF_LLC, mac_addr_uchar, 6);
- rtnl_link_set_addr(link, addr);
+ veth_addr = set_addr_from_mac(veth_link, *veth_mac);
+ }
+ if (peer_mac.isSome()) {
+ peer_addr = set_addr_from_mac(peer_link, *peer_mac);
}
- rtnl_link_set_name(link, veth.c_str());
+ rtnl_link_set_name(veth_link, veth.c_str());
rtnl_link_set_name(peer_link, peer.c_str());
rtnl_link_set_ns_pid(peer_link, pid.getOrElse(getpid()));
- error = rtnl_link_add(sock, link, NLM_F_CREATE | NLM_F_EXCL);
+ error = rtnl_link_add(sock, veth_link, NLM_F_CREATE | NLM_F_EXCL);
- rtnl_link_put(link);
- if (veth_mac.isSome()) {
- nl_addr_put(addr);
+ rtnl_link_put(veth_link);
+ if (veth_addr.isSome()) {
+ nl_addr_put(*veth_addr);
+ }
+ if (peer_addr.isSome()) {
+ nl_addr_put(*peer_addr);
}
if (error != 0) {
diff --git a/src/linux/routing/link/veth.hpp b/src/linux/routing/link/veth.hpp
index 1e54ce696..693033623 100644
--- a/src/linux/routing/link/veth.hpp
+++ b/src/linux/routing/link/veth.hpp
@@ -24,6 +24,7 @@
#include <stout/option.hpp>
#include <stout/try.hpp>
#include <stout/mac.hpp>
+#include <stout/none.hpp>
namespace routing {
namespace link {
@@ -51,8 +52,9 @@ namespace veth {
Try<bool> create(
const std::string& veth,
const std::string& peer,
- const Option<pid_t>& pid,
- const Option<net::MAC>& veth_mac);
+ const Option<pid_t>& pid = None(),
+ const Option<net::MAC>& veth_mac = None(),
+ const Option<net::MAC>& peer_mac = None());
} // namespace veth {
} // namespace link {
diff --git a/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
b/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
index 894d77c56..4dd0b00ad 100644
--- a/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
+++ b/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
@@ -3598,10 +3598,8 @@ Future<Nothing> PortMappingIsolatorProcess::isolate(
// Create a virtual ethernet pair for this container, also set the MAC
// address of the host network namespace veth<pid> interface to match
// that of the host network namespace eth0.
- //
- // TODO(jasonzhou): Also set the mac address of the container network
- // namespace eth0 here on creation, to avoid the race with udev: MESOS-10243.
- Try<bool> createVethPair = link::veth::create(veth(pid), eth0, pid, hostMAC);
+ Try<bool> createVethPair =
+ link::veth::create(veth(pid), eth0, pid, hostMAC, hostMAC);
if (createVethPair.isError()) {
return Failure(
"Failed to create virtual ethernet pair: " +
@@ -5177,20 +5175,9 @@ string PortMappingIsolatorProcess::scripts(Info* info)
// checksum offloading ensures the TCP layer will checksum and drop
// it.
script << "ethtool -K " << eth0 << " rx off\n";
- // TODO(jasonzhou): Set the link for the container eth0 in veth::create on
- // creation to prevent race condition against udev
- //
- // Due to a systemd-induced race-condition related to the
- // MacAddressPolicy being set to 'persistent' on versions >= 242,
- // we will have to set the peer link MAC address of the peer link (eth0)
- // when we create the eth0 peer link so that the udev will not try to
- // overwrite it when it is notified that this device was created, which
- // would lead to a race condition here where us and udev are racing to see
- // who is the last one to write our MAC address to eth0.
- //
- // see: https://issues.apache.org/jira/browse/MESOS-10243
- script << "ip link set " << eth0 << " address " << hostMAC
- << " mtu " << hostEth0MTU << " up\n";
+
+ // Only set the MTU and bring the interface up, MAC address was set on
create.
+ script << "ip link set " << eth0 << " mtu " << hostEth0MTU << " up\n";
script << "ip addr add " << hostIPNetwork << " dev " << eth0 << "\n";
// Set up the default gateway to match that of eth0.
diff --git a/src/tests/containerizer/routing_tests.cpp
b/src/tests/containerizer/routing_tests.cpp
index b18f741e0..9982cb723 100644
--- a/src/tests/containerizer/routing_tests.cpp
+++ b/src/tests/containerizer/routing_tests.cpp
@@ -260,8 +260,7 @@ protected:
TEST_F(RoutingVethTest, ROOT_LinkCreate)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -271,17 +270,17 @@ TEST_F(RoutingVethTest, ROOT_LinkCreate)
// Test the case where the veth (with the same name) already exists.
EXPECT_SOME_FALSE(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
}
TEST_F(RoutingVethTest, ROOT_LinkCreateWithTargetMAC)
{
- uint8_t bytes[6] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
- net::MAC target_mac = net::MAC(bytes);
+ net::MAC target_veth_mac = net::MAC({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});
+ net::MAC target_peer_mac = net::MAC({0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12});
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), target_mac));
+ ASSERT_SOME(link::veth::create(
+ TEST_VETH_LINK, TEST_PEER_LINK, None(), target_veth_mac, target_peer_mac));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -292,18 +291,21 @@ TEST_F(RoutingVethTest, ROOT_LinkCreateWithTargetMAC)
Result<net::MAC> mac = net::mac(TEST_VETH_LINK);
ASSERT_SOME(mac);
- EXPECT_EQ(*mac, target_mac);
+ EXPECT_EQ(*mac, target_veth_mac);
+
+ mac = net::mac(TEST_PEER_LINK);
+
+ ASSERT_SOME(mac);
+ EXPECT_EQ(*mac, target_peer_mac);
// Test the case where the veth (with the same name) already exists.
- EXPECT_SOME_FALSE(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ EXPECT_SOME_FALSE(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
}
TEST_F(RoutingVethTest, ROOT_LinkRemove)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::remove(TEST_VETH_LINK));
EXPECT_SOME_FALSE(link::remove(TEST_VETH_LINK));
@@ -339,7 +341,7 @@ TEST_F(RoutingVethTest, ROOT_LinkCreatePid)
ASSERT_NE(-1, pid);
// In parent process.
- ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, pid, None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, pid));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
// The peer should not exist in parent network namespace.
@@ -362,8 +364,7 @@ TEST_F(RoutingVethTest, ROOT_LinkWait)
{
AWAIT_READY(link::removed(TEST_VETH_LINK));
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -378,8 +379,7 @@ TEST_F(RoutingVethTest, ROOT_LinkWait)
TEST_F(RoutingVethTest, ROOT_LinkSetUp)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -399,8 +399,7 @@ TEST_F(RoutingVethTest, ROOT_LinkSetUp)
TEST_F(RoutingVethTest, ROOT_LinkSetMAC)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -431,8 +430,7 @@ TEST_F(RoutingVethTest, ROOT_LinkSetMAC)
TEST_F(RoutingVethTest, ROOT_LinkMTU)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -453,8 +451,7 @@ TEST_F(RoutingVethTest, ROOT_IngressQdisc)
// Test for a qdisc on a nonexistent interface should fail.
EXPECT_SOME_FALSE(ingress::exists("noSuchInterface"));
- EXPECT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ EXPECT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -518,8 +515,7 @@ TEST_F(RoutingVethTest, ROOT_HTBQdisc)
// Test for a qdisc on a nonexistent interface should fail.
EXPECT_SOME_FALSE(htb::exists("noSuchInterface", EGRESS_ROOT));
- EXPECT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ EXPECT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -603,8 +599,7 @@ TEST_F(RoutingVethTest, ROOT_FqCodeQdisc)
// Test for a qdisc on a nonexistent interface should fail.
EXPECT_SOME_FALSE(fq_codel::exists("noSuchInterface", EGRESS_ROOT));
- EXPECT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ EXPECT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -685,8 +680,7 @@ TEST_F(RoutingVethTest, ROOT_FqCodeQdisc)
TEST_F(RoutingVethTest, ROOT_FqCodelClassifier)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -762,8 +756,7 @@ TEST_F(RoutingVethTest, ROOT_FqCodelClassifier)
TEST_F(RoutingVethTest, ROOT_ARPFilterCreate)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -783,8 +776,7 @@ TEST_F(RoutingVethTest, ROOT_ARPFilterCreate)
TEST_F(RoutingVethTest, ROOT_ARPFilterCreateDuplicated)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -814,8 +806,7 @@ TEST_F(RoutingVethTest, ROOT_ARPFilterCreateDuplicated)
TEST_F(RoutingVethTest, ROOT_ARPFilterRemove)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -840,8 +831,7 @@ TEST_F(RoutingVethTest, ROOT_ARPFilterRemove)
TEST_F(RoutingVethTest, ROOT_ARPFilterUpdate)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -878,8 +868,7 @@ TEST_F(RoutingVethTest, ROOT_ARPFilterUpdate)
TEST_F(RoutingVethTest, ROOT_ICMPFilterCreate)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -911,8 +900,7 @@ TEST_F(RoutingVethTest, ROOT_ICMPFilterCreate)
TEST_F(RoutingVethTest, ROOT_ICMPFilterCreateDuplicated)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -945,8 +933,7 @@ TEST_F(RoutingVethTest, ROOT_ICMPFilterCreateDuplicated)
TEST_F(RoutingVethTest, ROOT_ICMPFilterCreateMultiple)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -982,8 +969,7 @@ TEST_F(RoutingVethTest, ROOT_ICMPFilterCreateMultiple)
TEST_F(RoutingVethTest, ROOT_ICMPFilterRemove)
{
- ASSERT_SOME(link::veth::create(
- TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -1016,8 +1002,7 @@ TEST_F(RoutingVethTest, ROOT_ICMPFilterRemove)
TEST_F(RoutingVethTest, ROOT_ICMPFilterUpdate)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -1073,8 +1058,7 @@ TEST_F(RoutingVethTest, ROOT_ICMPFilterUpdate)
TEST_F(RoutingVethTest, ROOT_IPFilterCreate)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -1132,8 +1116,7 @@ TEST_F(RoutingVethTest, ROOT_IPFilterCreate)
TEST_F(RoutingVethTest, ROOT_IPFilterCreate2)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -1168,8 +1151,7 @@ TEST_F(RoutingVethTest, ROOT_IPFilterCreate2)
TEST_F(RoutingVethTest, ROOT_IPFilterCreateDuplicated)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -1218,8 +1200,7 @@ TEST_F(RoutingVethTest, ROOT_IPFilterCreateDuplicated)
TEST_F(RoutingVethTest, ROOT_IPFilterCreateMultiple)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -1311,8 +1292,7 @@ TEST_F(RoutingVethTest, ROOT_IPFilterCreateMultiple)
TEST_F(RoutingVethTest, ROOT_IPFilterRemove)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));
@@ -1389,8 +1369,7 @@ TEST_F(RoutingVethTest, ROOT_IPFilterRemove)
// Test the workaround introduced for MESOS-1617.
TEST_F(RoutingVethTest, ROOT_HandleGeneration)
{
- ASSERT_SOME(
- link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK, None(), None()));
+ ASSERT_SOME(link::veth::create(TEST_VETH_LINK, TEST_PEER_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_VETH_LINK));
EXPECT_SOME_TRUE(link::exists(TEST_PEER_LINK));