Skip to content

Commit

Permalink
Merge pull request #17727 from idryzhov/netns-all-daemons
Browse files Browse the repository at this point in the history
lib: introduce global -w option for VRF netns backend
  • Loading branch information
donaldsharp authored Jan 16, 2025
2 parents 4e363bd + 754b949 commit acc3cfe
Show file tree
Hide file tree
Showing 16 changed files with 66 additions and 41 deletions.
2 changes: 2 additions & 0 deletions doc/manpages/frr-zebra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ OPTIONS available for the |DAEMON| command:

Enable namespace VRF backend. By default, the VRF backend relies on VRF-lite support from the Linux kernel. This option permits discovering Linux named network namespaces and mapping it to FRR VRF contexts.

This option is deprecated. Please use the global -w option instead.

ROUTES
------

Expand Down
11 changes: 11 additions & 0 deletions doc/user/basic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,17 @@ These options apply to all |PACKAGE_NAME| daemons.
be added to all files that use the statedir. If you have "/var/run/frr"
as the default statedir then it will become "/var/run/frr/<namespace>".

.. option:: -w, --vrfwnetns

Enable namespace VRF backend. By default, the VRF backend relies on VRF-lite
support from the Linux kernel. This option permits discovering Linux named
network namespaces and mapping them to FRR VRF contexts. This option must be
the same for all running daemons. The easiest way to pass the same option to
all daemons is to use the ``frr_global_options`` variable in the
:ref:`Daemons Configuration File <daemons-configuration-file>`.

.. seealso:: :ref:`zebra-vrf`

.. option:: -o, --vrfdefaultname <name>

Set the name used for the *Default VRF* in CLI commands and YANG models.
Expand Down
2 changes: 2 additions & 0 deletions doc/user/zebra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
VRF defined by *Zebra*, as usual. If this option is specified when running
*Zebra*, one must also specify the same option for *mgmtd*.

This options is deprecated. Please use the global -w option instead.

.. seealso:: :ref:`zebra-vrf`

.. option:: -z <path_to_socket>, --socket <path_to_socket>
Expand Down
2 changes: 0 additions & 2 deletions lib/if.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,6 @@ static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
{
switch (vrf_get_backend()) {
case VRF_BACKEND_UNKNOWN:
case VRF_BACKEND_NETNS:
return(if_lookup_by_ifindex(ifindex, vrf_id));
case VRF_BACKEND_VRF_LITE:
Expand Down Expand Up @@ -686,7 +685,6 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
struct vrf *vrf;

switch (vrf_get_backend()) {
case VRF_BACKEND_UNKNOWN:
case VRF_BACKEND_NETNS:
vrf = vrf_get(vrf_id, vrf_name);
assert(vrf);
Expand Down
14 changes: 14 additions & 0 deletions lib/libfrr.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ static const struct option lo_always[] = {
{ "module", no_argument, NULL, 'M' },
{ "profile", required_argument, NULL, 'F' },
{ "pathspace", required_argument, NULL, 'N' },
#ifdef HAVE_NETLINK
{ "vrfwnetns", no_argument, NULL, 'w' },
#endif
{ "vrfdefaultname", required_argument, NULL, 'o' },
{ "graceful_restart", optional_argument, NULL, 'K' },
{ "vty_socket", required_argument, NULL, OPTION_VTYSOCK },
Expand All @@ -120,13 +123,19 @@ static const struct option lo_always[] = {
{ NULL }
};
static const struct optspec os_always = {
#ifdef HAVE_NETLINK
"w"
#endif
"hvdM:F:N:o:K::",
" -h, --help Display this help and exit\n"
" -v, --version Print program version\n"
" -d, --daemon Runs in daemon mode\n"
" -M, --module Load specified module\n"
" -F, --profile Use specified configuration profile\n"
" -N, --pathspace Insert prefix into config & socket paths\n"
#ifdef HAVE_NETLINK
" -w, --vrfwnetns Use network namespaces for VRFs\n"
#endif
" -o, --vrfdefaultname Set default VRF name.\n"
" -K, --graceful_restart FRR starting in Graceful Restart mode, with optional route-cleanup timer\n"
" --vty_socket Override vty socket path\n"
Expand Down Expand Up @@ -516,6 +525,11 @@ static int frr_opt(int opt)
snprintf(frr_zclientpath, sizeof(frr_zclientpath),
ZAPI_SOCK_NAME);
break;
#ifdef HAVE_NETLINK
case 'w':
vrf_configure_backend(VRF_BACKEND_NETNS);
break;
#endif
case 'o':
vrf_set_default_name(optarg);
break;
Expand Down
16 changes: 1 addition & 15 deletions lib/vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ RB_GENERATE(vrf_name_head, vrf, name_entry, vrf_name_compare);
struct vrf_id_head vrfs_by_id = RB_INITIALIZER(&vrfs_by_id);
struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name);

static int vrf_backend;
static int vrf_backend_configured;
static int vrf_backend = VRF_BACKEND_VRF_LITE;
static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;

/*
Expand Down Expand Up @@ -582,15 +581,6 @@ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
"vrf_init: failed to create the default VRF!");
exit(1);
}
if (vrf_is_backend_netns()) {
struct ns *ns;

strlcpy(default_vrf->data.l.netns_name,
VRF_DEFAULT_NAME, NS_NAMSIZ);
ns = ns_lookup(NS_DEFAULT);
ns->vrf_ctxt = default_vrf;
default_vrf->ns_ctxt = ns;
}

/* Enable the default VRF. */
if (!vrf_enable(default_vrf)) {
Expand Down Expand Up @@ -654,16 +644,13 @@ int vrf_is_backend_netns(void)

int vrf_get_backend(void)
{
if (!vrf_backend_configured)
return VRF_BACKEND_UNKNOWN;
return vrf_backend;
}

int vrf_configure_backend(enum vrf_backend_type backend)
{
/* Work around issue in old gcc */
switch (backend) {
case VRF_BACKEND_UNKNOWN:
case VRF_BACKEND_NETNS:
case VRF_BACKEND_VRF_LITE:
break;
Expand All @@ -672,7 +659,6 @@ int vrf_configure_backend(enum vrf_backend_type backend)
}

vrf_backend = backend;
vrf_backend_configured = 1;

return 0;
}
Expand Down
1 change: 0 additions & 1 deletion lib/vrf.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ DECLARE_QOBJ_TYPE(vrf);
enum vrf_backend_type {
VRF_BACKEND_VRF_LITE,
VRF_BACKEND_NETNS,
VRF_BACKEND_UNKNOWN,
VRF_BACKEND_MAX,
};

Expand Down
9 changes: 5 additions & 4 deletions mgmtd/mgmt_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,9 @@ int main(int argc, char **argv)
int buffer_size = MGMTD_SOCKET_BUF_SIZE;

frr_preinit(&mgmtd_di, argc, argv);
frr_opt_add(
"s:n" DEPRECATED_OPTIONS, longopts,
" -s, --socket_size Set MGMTD peer socket send buffer size\n"
" -n, --vrfwnetns Use NetNS as VRF backend\n");
frr_opt_add("s:n" DEPRECATED_OPTIONS, longopts,
" -s, --socket_size Set MGMTD peer socket send buffer size\n"
" -n, --vrfwnetns Use NetNS as VRF backend (deprecated, use -w)\n");

/* Command line argument treatment. */
while (1) {
Expand All @@ -264,6 +263,8 @@ int main(int argc, char **argv)
buffer_size = atoi(optarg);
break;
case 'n':
fprintf(stderr,
"The -n option is deprecated, please use global -w option instead.\n");
vrf_configure_backend(VRF_BACKEND_NETNS);
break;
default:
Expand Down
6 changes: 2 additions & 4 deletions tests/topotests/bfd_vrf_topo1/test_bfd_vrf_topo1.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,9 @@ def setup_module(mod):
router.net.set_intf_netns(rname + "-eth2", ns, up=True)

for rname, router in router_list.items():
router.load_config(TopoRouter.RD_MGMTD, None, "--vrfwnetns")
router.use_netns_vrf()
router.load_config(
TopoRouter.RD_ZEBRA,
os.path.join(CWD, "{}/zebra.conf".format(rname)),
"--vrfwnetns",
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))
Expand Down
6 changes: 2 additions & 4 deletions tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,9 @@ def setup_module(mod):

for rname, router in router_list.items():
if rname == "r1":
router.load_config(TopoRouter.RD_MGMTD, None, "--vrfwnetns")
router.use_netns_vrf()
router.load_config(
TopoRouter.RD_ZEBRA,
os.path.join(CWD, "{}/zebra.conf".format(rname)),
"--vrfwnetns",
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
else:
router.load_config(
Expand Down
6 changes: 2 additions & 4 deletions tests/topotests/bgp_vrf_netns/test_bgp_vrf_netns_topo.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,9 @@ def setup_module(module):
router.net.set_intf_netns("r1-eth0", ns, up=True)

# run daemons
router.load_config(TopoRouter.RD_MGMTD, None, "--vrfwnetns")
router.use_netns_vrf()
router.load_config(
TopoRouter.RD_ZEBRA,
os.path.join(CWD, "{}/zebra.conf".format("r1")),
"--vrfwnetns",
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format("r1"))
)
router.load_config(
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format("r1"))
Expand Down
6 changes: 6 additions & 0 deletions tests/topotests/lib/topogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,12 @@ def __str__(self):
gear += " TopoRouter<>"
return gear

def use_netns_vrf(self):
"""
Use netns as VRF backend.
"""
self.net.useNetnsVRF()

def check_capability(self, daemon, param):
"""
Checks a capability daemon against an argument option
Expand Down
6 changes: 6 additions & 0 deletions tests/topotests/lib/topotest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,7 @@ def __init__(self, name, *posargs, **params):
self.daemons_options = {"zebra": ""}
self.reportCores = True
self.version = None
self.use_netns_vrf = False

self.ns_cmd = "sudo nsenter -a -t {} ".format(self.pid)
try:
Expand Down Expand Up @@ -1622,6 +1623,9 @@ def removeIPs(self):
# breakpoint()
# assert False, "can't remove IPs %s" % str(ex)

def useNetnsVRF(self):
self.use_netns_vrf = True

def checkCapability(self, daemon, param):
if param is not None:
daemon_path = os.path.join(self.daemondir, daemon)
Expand Down Expand Up @@ -1908,6 +1912,8 @@ def startRouterDaemons(self, daemons=None, tgen=None):

def start_daemon(daemon, instance=None):
daemon_opts = self.daemons_options.get(daemon, "")
if self.use_netns_vrf:
daemon_opts += " -w"

# get pid and vty filenames and remove the files
m = re.match(r"(.* |^)-n (\d+)( ?.*|$)", daemon_opts)
Expand Down
6 changes: 2 additions & 4 deletions tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,9 @@ def setup_module(mod):
router.net.set_intf_netns(rname + "-eth0", ns, up=True)
router.net.set_intf_netns(rname + "-eth1", ns, up=True)

router.load_config(TopoRouter.RD_MGMTD, None, "--vrfwnetns")
router.use_netns_vrf()
router.load_config(
TopoRouter.RD_ZEBRA,
os.path.join(CWD, "{}/zebra.conf".format(rname)),
"--vrfwnetns",
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
router.load_config(
TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
Expand Down
6 changes: 3 additions & 3 deletions zebra/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,6 @@ int main(int argc, char **argv)
if_notify_oper_changes = true;
vrf_notify_oper_changes = true;

vrf_configure_backend(VRF_BACKEND_VRF_LITE);

frr_preinit(&zebra_di, argc, argv);

frr_opt_add("baz:e:rK:s:R:"
Expand All @@ -379,7 +377,7 @@ int main(int argc, char **argv)
" --v6-with-v4-nexthops Underlying dataplane supports v6 routes with v4 nexthops\n"
#ifdef HAVE_NETLINK
" -s, --nl-bufsize Set netlink receive buffer size\n"
" -n, --vrfwnetns Use NetNS as VRF backend\n"
" -n, --vrfwnetns Use NetNS as VRF backend (deprecated, use -w)\n"
" --v6-rr-semantics Use v6 RR semantics\n"
#else
" -s, Set kernel socket receive buffer size\n"
Expand Down Expand Up @@ -440,6 +438,8 @@ int main(int argc, char **argv)
break;
#ifdef HAVE_NETLINK
case 'n':
fprintf(stderr,
"The -n option is deprecated, please use global -w option instead.\n");
vrf_configure_backend(VRF_BACKEND_NETNS);
break;
case OPTION_V6_RR_SEMANTICS:
Expand Down
8 changes: 8 additions & 0 deletions zebra/zebra_vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ static int zebra_vrf_new(struct vrf *vrf)
zvrf = zebra_vrf_alloc(vrf);
if (!vrf_is_backend_netns())
zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
else if (vrf->vrf_id == VRF_DEFAULT) {
struct ns *ns;

strlcpy(vrf->data.l.netns_name, VRF_DEFAULT_NAME, NS_NAMSIZ);
ns = ns_lookup(NS_DEFAULT);
ns->vrf_ctxt = vrf;
vrf->ns_ctxt = ns;
}

otable_init(&zvrf->other_tables);

Expand Down

0 comments on commit acc3cfe

Please sign in to comment.