diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 138788194d..e0834604b2 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -266,6 +266,12 @@ static int bgp_vrf_enable(struct vrf *vrf) bgp = bgp_lookup_by_name(vrf->name); if (bgp) { + if (bgp->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) { + XFREE(MTYPE_BGP, bgp->name); + bgp->name = NULL; + XFREE(MTYPE_BGP, bgp->name_pretty); + bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default"); + } old_vrf_id = bgp->vrf_id; /* We have instance configured, link to VRF and make it "up". */ bgp_vrf_link(bgp, vrf); @@ -332,7 +338,8 @@ static int bgp_vrf_disable(struct vrf *vrf) static void bgp_vrf_init(void) { - vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete); + vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, + bgp_vrf_delete, NULL); } static void bgp_vrf_terminate(void) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 1460a26215..99c6f39230 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -312,10 +312,14 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, if (argv_find(argv, argc, "ip", idx)) *afi = AFI_IP; - if (argv_find(argv, argc, "view", idx) - || argv_find(argv, argc, "vrf", idx)) { + if (argv_find(argv, argc, "view", idx)) vrf_name = argv[*idx + 1]->arg; - + else if (argv_find(argv, argc, "vrf", idx)) { + vrf_name = argv[*idx + 1]->arg; + if (strmatch(vrf_name, VRF_DEFAULT_NAME)) + vrf_name = NULL; + } + if (vrf_name) { if (strmatch(vrf_name, "all")) *bgp = NULL; else { @@ -910,9 +914,12 @@ DEFUN_NOSH (router_bgp, if (argc > 3) { name = argv[idx_vrf]->arg; - if (!strcmp(argv[idx_view_vrf]->text, "vrf")) - inst_type = BGP_INSTANCE_TYPE_VRF; - else if (!strcmp(argv[idx_view_vrf]->text, "view")) + if (!strcmp(argv[idx_view_vrf]->text, "vrf")) { + if (strmatch(name, VRF_DEFAULT_NAME)) + name = NULL; + else + inst_type = BGP_INSTANCE_TYPE_VRF; + } else if (!strcmp(argv[idx_view_vrf]->text, "view")) inst_type = BGP_INSTANCE_TYPE_VIEW; } @@ -7144,13 +7151,17 @@ DEFUN (clear_ip_bgp_all, if (argv_find(argv, argc, "ip", &idx)) afi = AFI_IP; - /* [ VIEWVRFNAME] */ - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) { + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + idx += 2; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) { + /* [ VIEWVRFNAME] */ vrf = argv[idx + 1]->arg; idx += 2; } - /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) argv_find_and_parse_safi(argv, argc, &idx, &safi); @@ -7215,8 +7226,16 @@ DEFUN (clear_ip_bgp_prefix, int idx = 0; /* [ VIEWVRFNAME] */ - if (argv_find(argv, argc, "VIEWVRFNAME", &idx)) - vrf = argv[idx]->arg; + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + idx += 2; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) { + /* [ VIEWVRFNAME] */ + vrf = argv[idx + 1]->arg; + idx += 2; + } prefix = argv[argc - 1]->arg; @@ -7258,16 +7277,23 @@ DEFUN (clear_bgp_instance_ipv6_safi_prefix, "Clear bestpath and re-advertise\n" "IPv6 prefix\n") { - int idx_word = 3; int idx_safi = 0; + int idx_vrfview = 0; int idx_ipv6_prefix = 0; safi_t safi = SAFI_UNICAST; char *prefix = argv_find(argv, argc, "X:X::X:X/M", &idx_ipv6_prefix) ? argv[idx_ipv6_prefix]->arg : NULL; - /* [ VIEWVRFNAME] */ - char *vrfview = argv_find(argv, argc, "VIEWVRFNAME", &idx_word) ? - argv[idx_word]->arg : NULL; + char *vrfview = NULL; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx_vrfview)) { + vrfview = argv[idx_vrfview + 1]->arg; + if (vrfview && strmatch(vrfview, VRF_DEFAULT_NAME)) + vrfview = NULL; + } else if (argv_find(argv, argc, "view", &idx_vrfview)) { + /* [ VIEWVRFNAME] */ + vrfview = argv[idx_vrfview + 1]->arg; + } argv_find_and_parse_safi(argv, argc, &idx_safi, &safi); return bgp_clear_prefix( @@ -7458,10 +7484,18 @@ DEFUN(show_bgp_martian_nexthop_db, show_bgp_martian_nexthop_db_cmd, { struct bgp *bgp = NULL; int idx = 0; + char *name = NULL; - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) - bgp = bgp_lookup_by_name(argv[idx + 1]->arg); + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + name = argv[idx + 1]->arg; + if (name && strmatch(name, VRF_DEFAULT_NAME)) + name = NULL; + } else if (argv_find(argv, argc, "view", &idx)) + /* [ VIEWVRFNAME] */ + name = argv[idx + 1]->arg; + if (name) + bgp = bgp_lookup_by_name(name); else bgp = bgp_get_default(); @@ -8211,10 +8245,14 @@ DEFUN (show_ip_bgp_summary, /* show [ip] bgp */ if (argv_find(argv, argc, "ip", &idx)) afi = AFI_IP; - /* [ VIEWVRFNAME] */ - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) + /* [ VIEWVRFNAME] */ + vrf = argv[idx + 1]->arg; /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { argv_find_and_parse_safi(argv, argc, &idx, &safi); @@ -10888,8 +10926,13 @@ DEFUN (show_ip_bgp_neighbors, int idx = 0; - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) + /* [ VIEWVRFNAME] */ vrf = argv[idx + 1]->arg; idx++; @@ -11183,8 +11226,11 @@ DEFUN (show_ip_bgp_route_leak, return CMD_WARNING; } - if (argv_find(argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { argv_find_and_parse_safi(argv, argc, &idx, &safi); @@ -11257,10 +11303,14 @@ DEFUN (show_ip_bgp_updgrps, /* show [ip] bgp */ if (argv_find(argv, argc, "ip", &idx)) afi = AFI_IP; - /* [ VIEWVRFNAME] */ - if (argv_find(argv, argc, "view", &idx) - || argv_find(argv, argc, "vrf", &idx)) - vrf = argv[++idx]->arg; + /* [ VIEWVRFNAME] */ + if (argv_find(argv, argc, "vrf", &idx)) { + vrf = argv[idx + 1]->arg; + if (vrf && strmatch(vrf, VRF_DEFAULT_NAME)) + vrf = NULL; + } else if (argv_find(argv, argc, "view", &idx)) + /* [ VIEWVRFNAME] */ + vrf = argv[idx + 1]->arg; /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */ if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { argv_find_and_parse_safi(argv, argc, &idx, &safi); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 7ff5053ce3..5d258a765b 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7735,10 +7735,8 @@ static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token) struct listnode *next; struct bgp *bgp; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (vrf->vrf_id != VRF_DEFAULT) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); - } + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) { if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index af8e4b8d47..85f2a7af3e 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -48,6 +48,13 @@ Besides the common invocation options (:ref:`common-invocation-options`), the .. seealso:: :ref:`zebra-vrf` +.. option:: -o, --vrfdefaultname + + When *Zebra* starts with this option, the default VRF name is changed to the + parameter. + + .. seealso:: :ref:`zebra-vrf` + .. option:: --v6-rr-semantics The linux kernel is receiving the ability to use the same route @@ -355,6 +362,40 @@ commands in relationship to VRF. Here is an extract of some of those commands: will dump the routing table ``TABLENO`` of the *Linux network namespace* ``VRF``. +By using the :option:`-n` option, the *Linux network namespace* will be mapped +over the *Zebra* VRF. One nice feature that is possible by handling *Linux +network namespace* is the ability to name default VRF. At startup, *Zebra* +discovers the available *Linux network namespace* by parsing folder +`/var/run/netns`. Each file stands for a *Linux network namespace*, but not all +*Linux network namespaces* are available under that folder. This is the case for +default VRF. It is possible to name the default VRF, by creating a file, by +executing following commands. + +.. code-block:: shell + + touch /var/run/netns/vrf0 + mount --bind /proc/self/ns/net /var/run/netns/vrf0 + +Above command illustrates what happens when the default VRF is visible under +`var/run/netns/`. Here, the default VRF file is `vrf0`. +At startup, FRR detects the presence of that file. It detects that the file +statistics information matches the same file statistics information as +`/proc/self/ns/net` ( through stat() function). As statistics information +matches, then `vrf0` stands for the new default namespace name. +Consequently, the VRF naming `Default` will be overriden by the new discovered +namespace name `vrf0`. + +For those who don't use VRF backend with *Linux network namespace*, it is +possible to statically configure and recompile FRR. It is possible to choose an +alternate name for default VRF. Then, the default VRF naming will automatically +be updated with the new name. To illustrate, if you want to recompile with +`global` value, use the following command: + +.. code-block:: linux + + ./configure --with-defaultvrfname=global + +More information about the option in :ref:`_frr-configuration`. .. _zebra-mpls: diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c index 31101a52d4..9e9c4649fc 100644 --- a/eigrpd/eigrp_main.c +++ b/eigrpd/eigrp_main.c @@ -170,7 +170,7 @@ int main(int argc, char **argv, char **envp) master = eigrp_om->master; eigrp_error_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); /*EIGRPd init*/ eigrp_if_init(); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 5b18ab0a2c..3b4168adb9 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -192,7 +192,7 @@ int main(int argc, char **argv, char **envp) */ isis_error_init(); access_list_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); prefix_list_init(); isis_init(); isis_circuit_init(); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index e830263ded..935e959596 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -330,7 +330,7 @@ main(int argc, char *argv[]) master = frr_init(); vty_config_lockless(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); access_list_init(); ldp_vty_init(); ldp_zebra_init(master); diff --git a/lib/vrf.c b/lib/vrf.c index ecd09a6b91..1fb1b786c7 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -39,6 +39,7 @@ /* default VRF ID value used when VRF backend is not NETNS */ #define VRF_DEFAULT_INTERNAL 0 +#define VRF_DEFAULT_NAME_INTERNAL "default" DEFINE_MTYPE_STATIC(LIB, VRF, "VRF") DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map") @@ -56,6 +57,7 @@ struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name); static int vrf_backend; static struct zebra_privs_t *vrf_daemon_privs; +static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL; /* * Turn on/off debug code @@ -69,6 +71,7 @@ struct vrf_master { int (*vrf_delete_hook)(struct vrf *); int (*vrf_enable_hook)(struct vrf *); int (*vrf_disable_hook)(struct vrf *); + int (*vrf_update_name_hook)(struct vrf *vrf); } vrf_master = { 0, }; @@ -165,6 +168,13 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name) */ if (name) vrf = vrf_lookup_by_name(name); + if (vrf && vrf_id != VRF_UNKNOWN + && vrf->vrf_id != VRF_UNKNOWN + && vrf->vrf_id != vrf_id) { + zlog_debug("VRF_GET: avoid %s creation(%u), same name exists (%u)", + name, vrf_id, vrf->vrf_id); + return NULL; + } /* Try to find VRF both by ID and name */ if (!vrf && vrf_id != VRF_UNKNOWN) vrf = vrf_lookup_by_id(vrf_id); @@ -445,10 +455,8 @@ static void vrf_autocomplete(vector comps, struct cmd_token *token) { struct vrf *vrf = NULL; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - if (vrf->vrf_id != VRF_DEFAULT) - vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); - } + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name)); } static const struct cmd_variable_handler vrf_var_handlers[] = { @@ -461,7 +469,8 @@ static const struct cmd_variable_handler vrf_var_handlers[] = { /* Initialize VRF module. */ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), - int (*disable)(struct vrf *), int (*delete)(struct vrf *)) + int (*disable)(struct vrf *), int (*delete)(struct vrf *), + int ((*update)(struct vrf *))) { struct vrf *default_vrf; @@ -475,6 +484,7 @@ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), vrf_master.vrf_enable_hook = enable; vrf_master.vrf_disable_hook = disable; vrf_master.vrf_delete_hook = delete; + vrf_master.vrf_update_name_hook = update; /* The default VRF always exists. */ default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME); @@ -483,6 +493,9 @@ 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()) + strlcpy(default_vrf->data.l.netns_name, + VRF_DEFAULT_NAME, NS_NAMSIZ); /* Enable the default VRF. */ if (!vrf_enable(default_vrf)) { @@ -876,12 +889,40 @@ void vrf_cmd_init(int (*writefunc)(struct vty *vty), } } +void vrf_set_default_name(const char *default_name) +{ + struct vrf *def_vrf; + struct vrf *vrf_with_default_name = NULL; + + def_vrf = vrf_lookup_by_id(VRF_DEFAULT); + assert(default_name); + vrf_with_default_name = vrf_lookup_by_name(default_name); + if (vrf_with_default_name && vrf_with_default_name != def_vrf) { + /* vrf name already used by an other VRF */ + zlog_debug("VRF: %s, avoid changing name to %s, same name exists (%u)", + vrf_with_default_name->name, default_name, + vrf_with_default_name->vrf_id); + return; + } + snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name); + if (def_vrf) { + RB_REMOVE(vrf_name_head, &vrfs_by_name, def_vrf); + strlcpy(def_vrf->data.l.netns_name, + vrf_default_name, NS_NAMSIZ); + strlcpy(def_vrf->name, vrf_default_name, sizeof(def_vrf->name)); + RB_INSERT(vrf_name_head, &vrfs_by_name, def_vrf); + if (vrf_master.vrf_update_name_hook) + (*vrf_master.vrf_update_name_hook)(def_vrf); + } +} + +const char *vrf_get_default_name(void) +{ + return vrf_default_name; +} + vrf_id_t vrf_get_default_id(void) { - struct vrf *vrf = vrf_lookup_by_name(VRF_DEFAULT_NAME); - - if (vrf) - return vrf->vrf_id; /* backend netns is only known by zebra * for other daemons, we return VRF_DEFAULT_INTERNAL */ diff --git a/lib/vrf.h b/lib/vrf.h index 56ba101ff0..c962ac4c69 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -41,8 +41,6 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX }; #define VRF_NAMSIZ 36 #define NS_NAMSIZ 16 -#define VRF_DEFAULT_NAME "Default-IP-Routing-Table" - /* * The command strings */ @@ -201,8 +199,10 @@ extern int vrf_bitmap_check(vrf_bitmap_t, vrf_id_t); * delete -> Called back when a vrf is being deleted from * the system ( 2 and 3 ) above. */ -extern void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), - int (*disable)(struct vrf *), int (*delete)(struct vrf *)); +extern void vrf_init(int (*create)(struct vrf *vrf), int (*enable)(struct vrf *vrf), + int (*disable)(struct vrf *vrf), int (*delete)(struct vrf *vrf), + int ((*update)(struct vrf *vrf))); + /* * Call vrf_terminate when the protocol is being shutdown */ @@ -236,6 +236,10 @@ extern vrf_id_t vrf_get_default_id(void); /* The default VRF ID */ #define VRF_DEFAULT vrf_get_default_id() +extern void vrf_set_default_name(const char *default_name); +extern const char *vrf_get_default_name(void); +#define VRF_DEFAULT_NAME vrf_get_default_name() + /* VRF is mapped on netns or not ? */ int vrf_is_mapped_on_netns(struct vrf *vrf); diff --git a/lib/zclient.c b/lib/zclient.c index b2bafcb7d8..c5a48c178a 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1366,6 +1366,9 @@ static void zclient_vrf_add(struct zclient *zclient, vrf_id_t vrf_id) vrf = vrf_get(vrf_id, vrfname_tmp); vrf->data.l.table_id = data.l.table_id; memcpy(vrf->data.l.netns_name, data.l.netns_name, NS_NAMSIZ); + /* overwrite default vrf */ + if (vrf_id == VRF_DEFAULT) + vrf_set_default_name(vrfname_tmp); vrf_enable(vrf); } diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index e9f44e8558..737e70103e 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -130,7 +130,7 @@ int main(int argc, char **argv) /* Library inits. */ master = frr_init(); nhrp_error_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); nhrp_interface_init(); resolver_init(); diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 9580d87cf0..eadc856cac 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -208,7 +208,7 @@ int main(int argc, char *argv[], char *envp[]) /* thread master */ master = frr_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); access_list_init(); prefix_list_init(); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index fb9770d09a..39f14a00c3 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -145,6 +145,8 @@ static struct ospf *ospf_cmd_lookup_ospf(struct vty *vty, if (argv_find(argv, argc, "vrf", &idx_vrf)) { vrf_name = argv[idx_vrf + 1]->arg; + if (vrf_name == NULL || strmatch(vrf_name, VRF_DEFAULT_NAME)) + vrf_name = NULL; if (enable) { /* Allocate VRF aware instance */ ospf = ospf_get(*instance, vrf_name); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index bfaedf2fe7..d311b4da6b 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -234,12 +234,10 @@ static struct ospf *ospf_new(unsigned short instance, const char *name) new->instance = instance; new->router_id.s_addr = htonl(0); new->router_id_static.s_addr = htonl(0); - - if (name) { + if (name && !strmatch(name, VRF_DEFAULT_NAME)) { new->vrf_id = VRF_UNKNOWN; /* Freed in ospf_finish_final */ new->name = XSTRDUP(MTYPE_OSPF_TOP, name); - vrf = vrf_lookup_by_name(new->name); if (IS_DEBUG_OSPF_EVENT) zlog_debug( "%s: Create new ospf instance with vrf_name %s vrf_id %u", @@ -381,6 +379,9 @@ struct ospf *ospf_lookup_by_inst_name(unsigned short instance, const char *name) struct ospf *ospf = NULL; struct listnode *node, *nnode; + if (name == NULL || strmatch(name, VRF_DEFAULT_NAME)) + return ospf_lookup_by_vrf_id(VRF_DEFAULT); + for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) { if ((ospf->instance == instance) && ((ospf->name == NULL && name == NULL) @@ -2078,6 +2079,10 @@ static int ospf_vrf_enable(struct vrf *vrf) ospf = ospf_lookup_by_name(vrf->name); if (ospf) { + if (ospf->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) { + XFREE(MTYPE_OSPF_TOP, ospf->name); + ospf->name = NULL; + } old_vrf_id = ospf->vrf_id; /* We have instance configured, link to VRF and make it "up". */ ospf_vrf_link(ospf, vrf); @@ -2149,7 +2154,7 @@ static int ospf_vrf_disable(struct vrf *vrf) void ospf_vrf_init(void) { vrf_init(ospf_vrf_new, ospf_vrf_enable, ospf_vrf_disable, - ospf_vrf_delete); + ospf_vrf_delete, NULL); } void ospf_vrf_terminate(void) diff --git a/pbrd/pbr_main.c b/pbrd/pbr_main.c index ba09621083..f555ccc056 100644 --- a/pbrd/pbr_main.c +++ b/pbrd/pbr_main.c @@ -146,7 +146,7 @@ int main(int argc, char **argv, char **envp) pbr_debug_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); nexthop_group_init(pbr_nhgroup_add_cb, pbr_nhgroup_add_nexthop_cb, pbr_nhgroup_del_nexthop_cb, diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index 8dc48cc004..bf8d05d1e1 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -196,7 +196,8 @@ static int pim_vrf_config_write(struct vty *vty) void pim_vrf_init(void) { - vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, pim_vrf_delete); + vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, + pim_vrf_delete, NULL); vrf_cmd_init(pim_vrf_config_write, &pimd_privs); } diff --git a/ripd/rip_main.c b/ripd/rip_main.c index e5a5c3e227..16087c2349 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -170,7 +170,7 @@ int main(int argc, char **argv) /* Library initialization. */ rip_error_init(); keychain_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); /* RIP related initialization. */ rip_init(); diff --git a/ripngd/ripng_main.c b/ripngd/ripng_main.c index e4501d6f80..bc81a956d6 100644 --- a/ripngd/ripng_main.c +++ b/ripngd/ripng_main.c @@ -166,7 +166,7 @@ int main(int argc, char **argv) master = frr_init(); /* Library inits. */ - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); /* RIPngd inits. */ ripng_init(); diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c index f0e6e3db4a..65b1837f68 100644 --- a/sharpd/sharp_main.c +++ b/sharpd/sharp_main.c @@ -146,7 +146,7 @@ int main(int argc, char **argv, char **envp) master = frr_init(); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); access_list_init(); route_map_init(); diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index 6946f21271..d33c1539c8 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -190,7 +190,7 @@ int static_vrf_has_config(struct static_vrf *svrf) void static_vrf_init(void) { vrf_init(static_vrf_new, static_vrf_enable, - static_vrf_disable, static_vrf_delete); + static_vrf_disable, static_vrf_delete, NULL); vrf_cmd_init(static_vrf_config_write, &static_privs); } diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index fef7d39ff5..83af5e9c6d 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -913,7 +913,7 @@ int main(void) qobj_init(); master = thread_master_create(NULL); bgp_master_init(master); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); bgp_pthreads_init(); diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c index 8db1cb2ca1..603b678cf1 100644 --- a/tests/bgpd/test_mp_attr.c +++ b/tests/bgpd/test_mp_attr.c @@ -1079,7 +1079,7 @@ int main(void) bgp_vty_init(); master = thread_master_create("test mp attr"); bgp_master_init(master); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); bgp_attr_init(); diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c index d8d2286bf7..42f7d76759 100644 --- a/tests/bgpd/test_mpath.c +++ b/tests/bgpd/test_mpath.c @@ -379,7 +379,7 @@ static int global_test_init(void) master = thread_master_create(NULL); zclient = zclient_new_notify(master, &zclient_options_default); bgp_master_init(master); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); if (fileno(stdout) >= 0) diff --git a/tests/bgpd/test_packet.c b/tests/bgpd/test_packet.c index c58a85eed3..9719aceec9 100644 --- a/tests/bgpd/test_packet.c +++ b/tests/bgpd/test_packet.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) bgp_attr_init(); master = thread_master_create(NULL); bgp_master_init(master); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_option_set(BGP_OPT_NO_LISTEN); if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT)) diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c index 16bd5d96da..452245ec16 100644 --- a/tests/bgpd/test_peer_attr.c +++ b/tests/bgpd/test_peer_attr.c @@ -1387,7 +1387,7 @@ static void bgp_startup(void) master = thread_master_create(NULL); bgp_master_init(master); bgp_option_set(BGP_OPT_NO_LISTEN); - vrf_init(NULL, NULL, NULL, NULL); + vrf_init(NULL, NULL, NULL, NULL, NULL); bgp_init(); bgp_pthreads_run(); } diff --git a/zebra/main.c b/zebra/main.c index 5e7c69382f..8db1c48f22 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -99,6 +99,7 @@ struct option longopts[] = { {"ecmp", required_argument, NULL, 'e'}, {"label_socket", no_argument, NULL, 'l'}, {"retain", no_argument, NULL, 'r'}, + {"vrfdefaultname", required_argument, NULL, 'o'}, #ifdef HAVE_NETLINK {"vrfwnetns", no_argument, NULL, 'n'}, {"nl-bufsize", required_argument, NULL, 's'}, @@ -235,7 +236,7 @@ int main(int argc, char **argv) frr_preinit(&zebra_di, argc, argv); frr_opt_add( - "bakz:e:l:r" + "bakz:e:l:o:r" #ifdef HAVE_NETLINK "s:n" #endif @@ -254,6 +255,7 @@ int main(int argc, char **argv) " -l, --label_socket Socket to external label manager\n" " -k, --keep_kernel Don't delete old routes which were installed by zebra.\n" " -r, --retain When program terminates, retain added route by zebra.\n" + " -o, --vrfdefaultname Set default VRF name.\n" #ifdef HAVE_NETLINK " -n, --vrfwnetns Use NetNS as VRF backend\n" " -s, --nl-bufsize Set netlink receive buffer size\n" @@ -296,6 +298,9 @@ int main(int argc, char **argv) return 1; } break; + case 'o': + vrf_set_default_name(optarg); + break; case 'z': zserv_path = optarg; if (!frr_zclient_addr(&dummy, &dummylen, optarg)) { diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 2b7bf04ec3..12207805d9 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -149,6 +149,41 @@ static int zebra_ns_delete(char *name) return 0; } +static int zebra_ns_notify_self_identify(struct stat *netst) +{ + char net_path[64]; + int netns; + + sprintf(net_path, "/proc/self/ns/net"); + netns = open(net_path, O_RDONLY); + if (netns < 0) + return -1; + if (fstat(netns, netst) < 0) { + close(netns); + return -1; + } + close(netns); + return 0; +} + +static bool zebra_ns_notify_is_default_netns(const char *name) +{ + struct stat default_netns_stat; + struct stat st; + char netnspath[64]; + + if (zebra_ns_notify_self_identify(&default_netns_stat)) + return false; + + memset(&st, 0, sizeof(struct stat)); + snprintf(netnspath, 64, "%s/%s", NS_RUN_DIR, name); + /* compare with local stat */ + if (stat(netnspath, &st) == 0 && + (st.st_dev == default_netns_stat.st_dev) && + (st.st_ino == default_netns_stat.st_ino)) + return true; + return false; +} static int zebra_ns_ready_read(struct thread *t) { @@ -178,6 +213,14 @@ static int zebra_ns_ready_read(struct thread *t) if (err < 0) return zebra_ns_continue_read(zns_info, stop_retry); + if (zebra_ns_notify_is_default_netns(basename(netnspath))) { + zlog_warn( + "NS notify : NS %s is default VRF." + " Updating VRF Name", basename(netnspath)); + vrf_set_default_name(basename(netnspath)); + return zebra_ns_continue_read(zns_info, 1); + } + /* success : close fd and create zns context */ zebra_ns_notify_create_context_from_entry_name(basename(netnspath)); return zebra_ns_continue_read(zns_info, 1); @@ -259,6 +302,13 @@ void zebra_ns_notify_parse(void) dent->d_name); continue; } + if (zebra_ns_notify_is_default_netns(dent->d_name)) { + zlog_warn( + "NS notify : NS %s is default VRF." + " Updating VRF Name", dent->d_name); + vrf_set_default_name(dent->d_name); + continue; + } zebra_ns_notify_create_context_from_entry_name(dent->d_name); } closedir(srcdir); diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 05ae418b57..be8f879246 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -282,6 +282,19 @@ static int zebra_vrf_delete(struct vrf *vrf) return 0; } +static int zebra_vrf_update(struct vrf *vrf) +{ + struct zebra_vrf *zvrf = vrf->info; + + assert(zvrf); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("VRF %s id %u, name updated", vrf->name, + zvrf_id(zvrf)); + zebra_vrf_add_update(zvrf); + return 0; +} + + /* Return if this VRF has any FRR configuration or not. * IMPORTANT: This function needs to be updated when additional configuration * is added for a VRF. @@ -491,7 +504,7 @@ static int vrf_config_write(struct vty *vty) void zebra_vrf_init(void) { vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable, - zebra_vrf_delete); + zebra_vrf_delete, zebra_vrf_update); vrf_cmd_init(vrf_config_write, &zserv_privs); }