summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@users.noreply.github.com>2022-07-22 14:12:17 +0000
committerGitHub <noreply@github.com>2022-07-22 14:12:17 +0000
commitb8443f7ad39ce0429f53c286d04a84b6faaeef83 (patch)
treecbe8317eb6858926883caf6fd2bae15a4b0f2b76
parentefb6140a9bf38ac9ccea43bd7e3da46a21b776ba (diff)
parent97413ed7786ebcc59e1b86d19bb03d50f9feb9f1 (diff)
Merge pull request #11565 from pguibert6WIND/bfd_vrf_lite_support
bfdd: allow l3vrf bfd sessions without udp leaking
-rw-r--r--bfdd/bfd.c66
-rw-r--r--bfdd/bfd_packet.c45
-rw-r--r--tests/topotests/bfd_vrflite_topo1/__init__.py0
-rw-r--r--tests/topotests/bfd_vrflite_topo1/r1/bfd_peers_status.json96
-rw-r--r--tests/topotests/bfd_vrflite_topo1/r1/bfdd.conf26
-rw-r--r--tests/topotests/bfd_vrflite_topo1/r1/zebra.conf24
-rw-r--r--tests/topotests/bfd_vrflite_topo1/r2/bfdd.conf26
-rw-r--r--tests/topotests/bfd_vrflite_topo1/r2/zebra.conf24
-rw-r--r--tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py153
-rw-r--r--tests/topotests/lib/micronet.py54
10 files changed, 480 insertions, 34 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 483beb1b17..a161926358 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -1950,40 +1950,38 @@ static int bfd_vrf_enable(struct vrf *vrf)
if (bglobal.debug_zebra)
zlog_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);
- if (vrf->vrf_id == VRF_DEFAULT ||
- vrf_get_backend() == VRF_BACKEND_NETNS) {
- if (!bvrf->bg_shop)
- bvrf->bg_shop = bp_udp_shop(vrf);
- if (!bvrf->bg_mhop)
- bvrf->bg_mhop = bp_udp_mhop(vrf);
- if (!bvrf->bg_shop6)
- bvrf->bg_shop6 = bp_udp6_shop(vrf);
- if (!bvrf->bg_mhop6)
- bvrf->bg_mhop6 = bp_udp6_mhop(vrf);
- if (!bvrf->bg_echo)
- bvrf->bg_echo = bp_echo_socket(vrf);
- if (!bvrf->bg_echov6)
- bvrf->bg_echov6 = bp_echov6_socket(vrf);
-
- if (!bvrf->bg_ev[0] && bvrf->bg_shop != -1)
- thread_add_read(master, bfd_recv_cb, bvrf,
- bvrf->bg_shop, &bvrf->bg_ev[0]);
- if (!bvrf->bg_ev[1] && bvrf->bg_mhop != -1)
- thread_add_read(master, bfd_recv_cb, bvrf,
- bvrf->bg_mhop, &bvrf->bg_ev[1]);
- if (!bvrf->bg_ev[2] && bvrf->bg_shop6 != -1)
- thread_add_read(master, bfd_recv_cb, bvrf,
- bvrf->bg_shop6, &bvrf->bg_ev[2]);
- if (!bvrf->bg_ev[3] && bvrf->bg_mhop6 != -1)
- thread_add_read(master, bfd_recv_cb, bvrf,
- bvrf->bg_mhop6, &bvrf->bg_ev[3]);
- if (!bvrf->bg_ev[4] && bvrf->bg_echo != -1)
- thread_add_read(master, bfd_recv_cb, bvrf,
- bvrf->bg_echo, &bvrf->bg_ev[4]);
- if (!bvrf->bg_ev[5] && bvrf->bg_echov6 != -1)
- thread_add_read(master, bfd_recv_cb, bvrf,
- bvrf->bg_echov6, &bvrf->bg_ev[5]);
- }
+ if (!bvrf->bg_shop)
+ bvrf->bg_shop = bp_udp_shop(vrf);
+ if (!bvrf->bg_mhop)
+ bvrf->bg_mhop = bp_udp_mhop(vrf);
+ if (!bvrf->bg_shop6)
+ bvrf->bg_shop6 = bp_udp6_shop(vrf);
+ if (!bvrf->bg_mhop6)
+ bvrf->bg_mhop6 = bp_udp6_mhop(vrf);
+ if (!bvrf->bg_echo)
+ bvrf->bg_echo = bp_echo_socket(vrf);
+ if (!bvrf->bg_echov6)
+ bvrf->bg_echov6 = bp_echov6_socket(vrf);
+
+ if (!bvrf->bg_ev[0] && bvrf->bg_shop != -1)
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,
+ &bvrf->bg_ev[0]);
+ if (!bvrf->bg_ev[1] && bvrf->bg_mhop != -1)
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,
+ &bvrf->bg_ev[1]);
+ if (!bvrf->bg_ev[2] && bvrf->bg_shop6 != -1)
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,
+ &bvrf->bg_ev[2]);
+ if (!bvrf->bg_ev[3] && bvrf->bg_mhop6 != -1)
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
+ &bvrf->bg_ev[3]);
+ if (!bvrf->bg_ev[4] && bvrf->bg_echo != -1)
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo,
+ &bvrf->bg_ev[4]);
+ if (!bvrf->bg_ev[5] && bvrf->bg_echov6 != -1)
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
+ &bvrf->bg_ev[5]);
+
if (vrf->vrf_id != VRF_DEFAULT) {
bfdd_zclient_register(vrf->vrf_id);
bfdd_sessions_enable_vrf(vrf);
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 26c7174f63..82b3f09b0c 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -876,6 +876,14 @@ void bfd_recv_cb(struct thread *t)
"no session found");
return;
}
+ /*
+ * We may have a situation where received packet is on wrong vrf
+ */
+ if (bfd && bfd->vrf && bfd->vrf != bvrf->vrf) {
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
+ "wrong vrfid.");
+ return;
+ }
/* Ensure that existing good sessions are not overridden. */
if (!cp->discrs.remote_discr && bfd->ses_state != PTM_BFD_DOWN &&
@@ -1208,10 +1216,41 @@ int bp_set_tos(int sd, uint8_t value)
return 0;
}
+static bool bp_set_reuse_addr(int sd)
+{
+ int one = 1;
+
+ if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
+ zlog_warn("set-reuse-addr: setsockopt(SO_REUSEADDR, %d): %s",
+ one, strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+static bool bp_set_reuse_port(int sd)
+{
+ int one = 1;
+
+ if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) == -1) {
+ zlog_warn("set-reuse-port: setsockopt(SO_REUSEPORT, %d): %s",
+ one, strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+
static void bp_set_ipopts(int sd)
{
int rcvttl = BFD_RCV_TTL_VAL;
+ if (!bp_set_reuse_addr(sd))
+ zlog_fatal("set-reuse-addr: failed");
+
+ if (!bp_set_reuse_port(sd))
+ zlog_fatal("set-reuse-port: failed");
+
if (bp_set_ttl(sd, BFD_TTL_VAL) != 0)
zlog_fatal("set-ipopts: TTL configuration failed");
@@ -1453,6 +1492,12 @@ static void bp_set_ipv6opts(int sd)
int ipv6_pktinfo = BFD_IPV6_PKT_INFO_VAL;
int ipv6_only = BFD_IPV6_ONLY_VAL;
+ if (!bp_set_reuse_addr(sd))
+ zlog_fatal("set-reuse-addr: failed");
+
+ if (!bp_set_reuse_port(sd))
+ zlog_fatal("set-reuse-port: failed");
+
if (bp_set_ttlv6(sd, BFD_TTL_VAL) == -1)
zlog_fatal(
"set-ipv6opts: setsockopt(IPV6_UNICAST_HOPS, %d): %s",
diff --git a/tests/topotests/bfd_vrflite_topo1/__init__.py b/tests/topotests/bfd_vrflite_topo1/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bfd_vrflite_topo1/__init__.py
diff --git a/tests/topotests/bfd_vrflite_topo1/r1/bfd_peers_status.json b/tests/topotests/bfd_vrflite_topo1/r1/bfd_peers_status.json
new file mode 100644
index 0000000000..07e96d74bd
--- /dev/null
+++ b/tests/topotests/bfd_vrflite_topo1/r1/bfd_peers_status.json
@@ -0,0 +1,96 @@
+[
+ {
+ "multihop":false,
+ "peer":"192.168.0.2",
+ "vrf":"vrf1",
+ "passive-mode":false,
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":1000,
+ "transmit-interval":1000,
+ "echo-receive-interval":50,
+ "echo-transmit-interval":0,
+ "detect-multiplier":3,
+ "remote-receive-interval":1000,
+ "remote-transmit-interval":1000,
+ "remote-echo-receive-interval":50,
+ "remote-detect-multiplier":3
+ },
+ {
+ "multihop":true,
+ "peer":"192.0.2.2",
+ "local":"192.0.2.1",
+ "vrf":"vrf2",
+ "passive-mode":false,
+ "minimum-ttl":254,
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":1000,
+ "transmit-interval":1000,
+ "echo-receive-interval":50,
+ "echo-transmit-interval":0,
+ "detect-multiplier":3,
+ "remote-receive-interval":1000,
+ "remote-transmit-interval":1000,
+ "remote-echo-receive-interval":50,
+ "remote-detect-multiplier":3
+ },
+ {
+ "multihop":false,
+ "peer":"192.168.0.2",
+ "vrf":"vrf2",
+ "passive-mode":false,
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":1000,
+ "transmit-interval":1000,
+ "echo-receive-interval":50,
+ "echo-transmit-interval":0,
+ "detect-multiplier":3,
+ "remote-receive-interval":1000,
+ "remote-transmit-interval":1000,
+ "remote-echo-receive-interval":50,
+ "remote-detect-multiplier":3
+ },
+ {
+ "multihop":false,
+ "peer":"192.168.0.2",
+ "vrf":"default",
+ "passive-mode":false,
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":1000,
+ "transmit-interval":1000,
+ "echo-receive-interval":50,
+ "echo-transmit-interval":0,
+ "detect-multiplier":3,
+ "remote-receive-interval":1000,
+ "remote-transmit-interval":1000,
+ "remote-echo-receive-interval":50,
+ "remote-detect-multiplier":3
+ },
+ {
+ "multihop":true,
+ "peer":"192.0.2.2",
+ "local":"192.0.2.1",
+ "vrf":"vrf1",
+ "passive-mode":false,
+ "minimum-ttl":254,
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":1000,
+ "transmit-interval":1000,
+ "echo-receive-interval":50,
+ "echo-transmit-interval":0,
+ "detect-multiplier":3,
+ "remote-receive-interval":1000,
+ "remote-transmit-interval":1000,
+ "remote-echo-receive-interval":50,
+ "remote-detect-multiplier":3
+ }
+]
diff --git a/tests/topotests/bfd_vrflite_topo1/r1/bfdd.conf b/tests/topotests/bfd_vrflite_topo1/r1/bfdd.conf
new file mode 100644
index 0000000000..96e8ff4b12
--- /dev/null
+++ b/tests/topotests/bfd_vrflite_topo1/r1/bfdd.conf
@@ -0,0 +1,26 @@
+!
+! debug bfd network
+! debug bfd peer
+! debug bfd zebra
+!
+bfd
+ peer 192.168.0.2 vrf vrf1
+ transmit-interval 1000
+ receive-interval 1000
+ !
+ peer 192.168.0.2 vrf vrf2
+ transmit-interval 1000
+ receive-interval 1000
+ !
+ peer 192.168.0.2
+ transmit-interval 1000
+ receive-interval 1000
+ !
+ peer 192.0.2.2 multihop local-address 192.0.2.1 vrf vrf1
+ transmit-interval 1000
+ receive-interval 1000
+ !
+ peer 192.0.2.2 multihop local-address 192.0.2.1 vrf vrf2
+ transmit-interval 1000
+ receive-interval 1000
+ ! \ No newline at end of file
diff --git a/tests/topotests/bfd_vrflite_topo1/r1/zebra.conf b/tests/topotests/bfd_vrflite_topo1/r1/zebra.conf
new file mode 100644
index 0000000000..ebb4e63be7
--- /dev/null
+++ b/tests/topotests/bfd_vrflite_topo1/r1/zebra.conf
@@ -0,0 +1,24 @@
+vrf vrf1
+ ip route 192.0.2.2/32 192.168.0.2
+!
+vrf vrf2
+ ip route 192.0.2.2/32 192.168.0.2
+!
+interface r1-eth0 vrf vrf3
+ ip address 192.168.0.1/24
+!
+interface r1-eth0.100 vrf vrf1
+ ip address 192.168.0.1/24
+!
+interface r1-eth0.200 vrf vrf2
+ ip address 192.168.0.1/24
+!
+interface r1-eth0.300
+ ip address 192.168.0.1/24
+!
+interface r1-loop1 vrf vrf1
+ ip address 192.0.2.1/32
+!
+interface r1-loop2 vrf vrf2
+ ip address 192.0.2.1/32
+! \ No newline at end of file
diff --git a/tests/topotests/bfd_vrflite_topo1/r2/bfdd.conf b/tests/topotests/bfd_vrflite_topo1/r2/bfdd.conf
new file mode 100644
index 0000000000..7b11a4785a
--- /dev/null
+++ b/tests/topotests/bfd_vrflite_topo1/r2/bfdd.conf
@@ -0,0 +1,26 @@
+!
+! debug bfd network
+! debug bfd peer
+! debug bfd zebra
+!
+bfd
+ peer 192.168.0.1 vrf vrf1
+ transmit-interval 1000
+ receive-interval 1000
+ !
+ peer 192.168.0.1 vrf vrf2
+ transmit-interval 1000
+ receive-interval 1000
+ !
+ peer 192.168.0.1
+ transmit-interval 1000
+ receive-interval 1000
+ !
+ peer 192.0.2.1 multihop local-address 192.0.2.2 vrf vrf1
+ transmit-interval 1000
+ receive-interval 1000
+ !
+ peer 192.0.2.1 multihop local-address 192.0.2.2 vrf vrf2
+ transmit-interval 1000
+ receive-interval 1000
+ ! \ No newline at end of file
diff --git a/tests/topotests/bfd_vrflite_topo1/r2/zebra.conf b/tests/topotests/bfd_vrflite_topo1/r2/zebra.conf
new file mode 100644
index 0000000000..d8b996e9ed
--- /dev/null
+++ b/tests/topotests/bfd_vrflite_topo1/r2/zebra.conf
@@ -0,0 +1,24 @@
+vrf vrf1
+ ip route 192.0.2.1/32 192.168.0.1
+!
+vrf vrf2
+ ip route 192.0.2.1/32 192.168.0.1
+!
+interface r2-eth0 vrf vrf3
+ ip address 192.168.0.2/24
+!
+interface r2-eth0.100 vrf vrf1
+ ip address 192.168.0.2/24
+!
+interface r2-eth0.200 vrf vrf2
+ ip address 192.168.0.2/24
+!
+interface r2-eth0.300
+ ip address 192.168.0.2/24
+!
+interface r2-loop1 vrf vrf1
+ ip address 192.0.2.2/32
+!
+interface r2-loop2 vrf vrf2
+ ip address 192.0.2.2/32
+! \ No newline at end of file
diff --git a/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py b/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
new file mode 100644
index 0000000000..b7afb8e3b9
--- /dev/null
+++ b/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+
+#
+# test_bfd_vrflite_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2018 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+# Copyright (c) 2022 by 6WIND
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_bfd_vrflite_topo1.py: Test the FRR BFD daemon.
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.bfdd, pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ # Create 2 routers
+ for routern in range(1, 3):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r1"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ logger.info("Testing with Linux VRF support and udp_l3mdev=0")
+ if os.system("echo 0 > /proc/sys/net/ipv4/udp_l3mdev_accept") != 0:
+ return pytest.skip(
+ "Skipping BFD vrflite Topo1 Test. Linux VRF not available on System"
+ )
+
+ for rname, router in router_list.items():
+ router.net.add_l3vrf("vrf1", 10)
+ router.net.add_l3vrf("vrf2", 20)
+ router.net.add_l3vrf("vrf3", 30)
+ router.net.add_vlan(rname + "-eth0.100", rname + "-eth0", 100)
+ router.net.add_vlan(rname + "-eth0.200", rname + "-eth0", 200)
+ router.net.add_vlan(rname + "-eth0.300", rname + "-eth0", 300)
+ router.net.attach_iface_to_l3vrf(rname + "-eth0.100", "vrf1")
+ router.net.attach_iface_to_l3vrf(rname + "-eth0.200", "vrf2")
+ router.net.add_loop(rname + "-loop1")
+ router.net.add_loop(rname + "-loop2")
+ router.net.attach_iface_to_l3vrf(rname + "-loop1", "vrf1")
+ router.net.attach_iface_to_l3vrf(rname + "-loop2", "vrf2")
+ router.net.attach_iface_to_l3vrf(rname + "-eth0", "vrf3")
+
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # Move interfaces out of vrf namespace and delete the namespace
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ router.net.del_iface(rname + "-eth0.100")
+ router.net.del_iface(rname + "-eth0.200")
+ router.net.del_iface(rname + "-eth0.300")
+ router.net.del_iface(rname + "-loop1")
+ router.net.del_iface(rname + "-loop2")
+
+ tgen.stop_topology()
+
+
+def test_bfd_connection():
+ "Assert that the BFD peers can find themselves."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+ logger.info("waiting for bfd peers to go up")
+ router = tgen.gears['r1']
+ json_file = "{}/{}/bfd_peers_status.json".format(CWD, 'r1')
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show bfd peers json", expected
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=16, wait=1)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/lib/micronet.py b/tests/topotests/lib/micronet.py
index 02f66e9c26..dfa10ccb2f 100644
--- a/tests/topotests/lib/micronet.py
+++ b/tests/topotests/lib/micronet.py
@@ -599,6 +599,60 @@ class LinuxNamespace(Commander):
self.cmd_raises("mkdir -p " + inner)
self.cmd_raises("mount --rbind {} {} ".format(outer, inner))
+ def add_vlan(self, vlanname, linkiface, vlanid):
+ self.logger.debug("Adding VLAN interface: %s (%s)", vlanname, vlanid)
+ ip_path = self.get_exec_path("ip")
+ assert ip_path, "XXX missing ip command!"
+ self.cmd_raises(
+ [
+ ip_path,
+ "link",
+ "add",
+ "link",
+ linkiface,
+ "name",
+ vlanname,
+ "type",
+ "vlan",
+ "id",
+ vlanid,
+ ]
+ )
+ self.cmd_raises([ip_path, "link", "set", "dev", vlanname, "up"])
+
+ def add_loop(self, loopname):
+ self.logger.debug("Adding Linux iface: %s", loopname)
+ ip_path = self.get_exec_path("ip")
+ assert ip_path, "XXX missing ip command!"
+ self.cmd_raises([ip_path, "link", "add", loopname, "type", "dummy"])
+ self.cmd_raises([ip_path, "link", "set", "dev", loopname, "up"])
+
+ def add_l3vrf(self, vrfname, tableid):
+ self.logger.debug("Adding Linux VRF: %s", vrfname)
+ ip_path = self.get_exec_path("ip")
+ assert ip_path, "XXX missing ip command!"
+ self.cmd_raises(
+ [ip_path, "link", "add", vrfname, "type", "vrf", "table", tableid]
+ )
+ self.cmd_raises([ip_path, "link", "set", "dev", vrfname, "up"])
+
+ def del_iface(self, iface):
+ self.logger.debug("Removing Linux Iface: %s", iface)
+ ip_path = self.get_exec_path("ip")
+ assert ip_path, "XXX missing ip command!"
+ self.cmd_raises([ip_path, "link", "del", iface])
+
+ def attach_iface_to_l3vrf(self, ifacename, vrfname):
+ self.logger.debug("Attaching Iface %s to Linux VRF %s", ifacename, vrfname)
+ ip_path = self.get_exec_path("ip")
+ assert ip_path, "XXX missing ip command!"
+ if vrfname:
+ self.cmd_raises(
+ [ip_path, "link", "set", "dev", ifacename, "master", vrfname]
+ )
+ else:
+ self.cmd_raises([ip_path, "link", "set", "dev", ifacename, "nomaster"])
+
def add_netns(self, ns):
self.logger.debug("Adding network namespace %s", ns)