]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: allow to create interfaces in non-existing VRFs
authorIgor Ryzhov <iryzhov@nfware.com>
Wed, 13 Oct 2021 12:06:38 +0000 (15:06 +0300)
committerIgor Ryzhov <iryzhov@nfware.com>
Tue, 19 Oct 2021 12:29:51 +0000 (15:29 +0300)
It allows FRR to read the interface config even when the necessary VRFs
are not yet created and interfaces are in "wrong" VRFs. Currently, such
config is rejected.

For VRF-lite backend, we don't care at all about the VRF of the inactive
interface. When the interface is created in the OS and becomes active,
we always use its actual VRF instead of the configured one. So there's
no need to reject the config.

For netns backend, we may have multiple interfaces with the same name in
different VRFs. So we care about the VRF of inactive interfaces. And we
must allow to preconfigure the interface in a VRF even before it is
moved to the corresponding netns. From now on, we allow to create
multiple configs for the same interface name in different VRFs and
the necessary config is applied once the OS interface is moved to the
corresponding netns.

Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
12 files changed:
lib/if.c
lib/if.h
lib/vrf.c
lib/zclient.c
ospf6d/ospf6_top.c
ospfd/ospf_interface.c
ospfd/ospf_vty.c
pimd/pim_iface.c
zebra/if_ioctl.c
zebra/if_netlink.c
zebra/interface.c
zebra/kernel_socket.c

index f316d1a9b74c98c0e2f1053d9eb2736a111e5cf8..cb6270f5ecd346a0313a9dbb3c1aaf8553af50b3 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -45,6 +45,7 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected");
 DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label");
 DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters");
 
+static void if_set_name(struct interface *ifp, const char *name);
 static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
                                              vrf_id_t vrf_id);
 static int if_cmp_func(const struct interface *, const struct interface *);
@@ -153,16 +154,19 @@ static void ifp_connected_free(void *arg)
 }
 
 /* Create new interface structure. */
-static struct interface *if_new(vrf_id_t vrf_id)
+static struct interface *if_new(struct vrf *vrf)
 {
        struct interface *ifp;
 
+       assert(vrf);
+
        ifp = XCALLOC(MTYPE_IF, sizeof(struct interface));
 
        ifp->ifindex = IFINDEX_INTERNAL;
        ifp->name[0] = '\0';
 
-       ifp->vrf_id = vrf_id;
+       ifp->vrf = vrf;
+       ifp->vrf_id = vrf->vrf_id;
 
        ifp->connected = list_new();
        ifp->connected->del = ifp_connected_free;
@@ -207,11 +211,11 @@ void if_down_via_zapi(struct interface *ifp)
                (*ifp_master.down_hook)(ifp);
 }
 
-struct interface *if_create_name(const char *name, vrf_id_t vrf_id)
+static struct interface *if_create_name(const char *name, struct vrf *vrf)
 {
        struct interface *ifp;
 
-       ifp = if_new(vrf_id);
+       ifp = if_new(vrf);
 
        if_set_name(ifp, name);
 
@@ -219,35 +223,23 @@ struct interface *if_create_name(const char *name, vrf_id_t vrf_id)
        return ifp;
 }
 
-struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id)
-{
-       struct interface *ifp;
-
-       ifp = if_new(vrf_id);
-
-       if_set_index(ifp, ifindex);
-
-       hook_call(if_add, ifp);
-       return ifp;
-}
-
 /* Create new interface structure. */
 void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
 {
        struct vrf *old_vrf, *vrf;
 
        /* remove interface from old master vrf list */
-       old_vrf = vrf_lookup_by_id(ifp->vrf_id);
-       if (old_vrf) {
-               if (ifp->name[0] != '\0')
-                       IFNAME_RB_REMOVE(old_vrf, ifp);
+       old_vrf = ifp->vrf;
 
-               if (ifp->ifindex != IFINDEX_INTERNAL)
-                       IFINDEX_RB_REMOVE(old_vrf, ifp);
-       }
+       if (ifp->name[0] != '\0')
+               IFNAME_RB_REMOVE(old_vrf, ifp);
+
+       if (ifp->ifindex != IFINDEX_INTERNAL)
+               IFINDEX_RB_REMOVE(old_vrf, ifp);
 
        ifp->vrf_id = vrf_id;
        vrf = vrf_get(ifp->vrf_id, NULL);
+       ifp->vrf = vrf;
 
        if (ifp->name[0] != '\0')
                IFNAME_RB_INSERT(vrf, ifp);
@@ -261,7 +253,7 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
         * the interface and readding it in the new VRF, which would have
         * several implications.
         */
-       if (yang_module_find("frr-interface")) {
+       if (!vrf_is_backend_netns() && yang_module_find("frr-interface")) {
                struct lyd_node *if_dnode;
                char oldpath[XPATH_MAXLEN];
                char newpath[XPATH_MAXLEN];
@@ -304,15 +296,15 @@ void if_delete_retain(struct interface *ifp)
 void if_delete(struct interface **ifp)
 {
        struct interface *ptr = *ifp;
-       struct vrf *vrf;
-
-       vrf = vrf_lookup_by_id(ptr->vrf_id);
-       assert(vrf);
+       struct vrf *vrf = ptr->vrf;
 
        IFNAME_RB_REMOVE(vrf, ptr);
        if (ptr->ifindex != IFINDEX_INTERNAL)
                IFINDEX_RB_REMOVE(vrf, ptr);
 
+       if (!vrf_is_enabled(vrf))
+               vrf_delete(vrf);
+
        if_delete_retain(ptr);
 
        list_delete(&ptr->connected);
@@ -439,7 +431,7 @@ struct interface *if_lookup_by_name_all_vrf(const char *name)
        if (!name || strnlen(name, INTERFACE_NAMSIZ) == INTERFACE_NAMSIZ)
                return NULL;
 
-       RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
                ifp = if_lookup_by_name_vrf(name, vrf);
                if (ifp)
                        return ifp;
@@ -582,72 +574,58 @@ size_t if_lookup_by_hwaddr(const uint8_t *hw_addr, size_t addrsz,
 
 /* Get interface by name if given name interface doesn't exist create
    one. */
-struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id)
+struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id,
+                                const char *vrf_name)
 {
-       struct interface *ifp;
+       struct interface *ifp = NULL;
+       struct vrf *vrf;
 
        switch (vrf_get_backend()) {
        case VRF_BACKEND_UNKNOWN:
        case VRF_BACKEND_NETNS:
-               ifp = if_lookup_by_name(name, vrf_id);
-               if (ifp)
-                       return ifp;
-               return if_create_name(name, vrf_id);
-       case VRF_BACKEND_VRF_LITE:
-               ifp = if_lookup_by_name_all_vrf(name);
+               vrf = vrf_get(vrf_id, vrf_name);
+               assert(vrf);
+
+               ifp = if_lookup_by_name_vrf(name, vrf);
                if (ifp) {
-                       if (ifp->vrf_id == vrf_id)
-                               return ifp;
                        /* If it came from the kernel or by way of zclient,
                         * believe it and update the ifp accordingly.
                         */
-                       if_update_to_new_vrf(ifp, vrf_id);
+                       if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+                               if_update_to_new_vrf(ifp, vrf_id);
+
                        return ifp;
                }
-               return if_create_name(name, vrf_id);
-       }
 
-       return NULL;
-}
-
-struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id)
-{
-       struct interface *ifp;
-
-       switch (vrf_get_backend()) {
-       case VRF_BACKEND_UNKNOWN:
-       case VRF_BACKEND_NETNS:
-               ifp = if_lookup_by_ifindex(ifindex, vrf_id);
-               if (ifp)
-                       return ifp;
-               return if_create_ifindex(ifindex, vrf_id);
+               break;
        case VRF_BACKEND_VRF_LITE:
-               ifp = if_lookup_by_index_all_vrf(ifindex);
+               ifp = if_lookup_by_name_all_vrf(name);
                if (ifp) {
-                       if (ifp->vrf_id == vrf_id)
-                               return ifp;
                        /* If it came from the kernel or by way of zclient,
                         * believe it and update the ifp accordingly.
                         */
-                       if_update_to_new_vrf(ifp, vrf_id);
+                       if (ifp->vrf_id != vrf_id && vrf_id != VRF_UNKNOWN)
+                               if_update_to_new_vrf(ifp, vrf_id);
+
                        return ifp;
                }
-               return if_create_ifindex(ifindex, vrf_id);
+
+               vrf = vrf_get(vrf_id, vrf_name);
+               assert(vrf);
+
+               break;
+       default:
+               return NULL;
        }
 
-       return NULL;
+       return if_create_name(name, vrf);
 }
 
 int if_set_index(struct interface *ifp, ifindex_t ifindex)
 {
-       struct vrf *vrf;
-
        if (ifp->ifindex == ifindex)
                return 0;
 
-       vrf = vrf_get(ifp->vrf_id, NULL);
-       assert(vrf);
-
        /*
         * If there is already an interface with this ifindex, we will collide
         * on insertion, so don't even try.
@@ -656,7 +634,7 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
                return -1;
 
        if (ifp->ifindex != IFINDEX_INTERNAL)
-               IFINDEX_RB_REMOVE(vrf, ifp);
+               IFINDEX_RB_REMOVE(ifp->vrf, ifp);
 
        ifp->ifindex = ifindex;
 
@@ -666,30 +644,25 @@ int if_set_index(struct interface *ifp, ifindex_t ifindex)
                 * already an interface with the desired ifindex at the top of
                 * the function. Nevertheless.
                 */
-               if (IFINDEX_RB_INSERT(vrf, ifp))
+               if (IFINDEX_RB_INSERT(ifp->vrf, ifp))
                        return -1;
        }
 
        return 0;
 }
 
-void if_set_name(struct interface *ifp, const char *name)
+static void if_set_name(struct interface *ifp, const char *name)
 {
-       struct vrf *vrf;
-
-       vrf = vrf_get(ifp->vrf_id, NULL);
-       assert(vrf);
-
        if (if_cmp_name_func(ifp->name, name) == 0)
                return;
 
        if (ifp->name[0] != '\0')
-               IFNAME_RB_REMOVE(vrf, ifp);
+               IFNAME_RB_REMOVE(ifp->vrf, ifp);
 
        strlcpy(ifp->name, name, sizeof(ifp->name));
 
        if (ifp->name[0] != '\0')
-               IFNAME_RB_INSERT(vrf, ifp);
+               IFNAME_RB_INSERT(ifp->vrf, ifp);
 }
 
 /* Does interface up ? */
@@ -817,15 +790,12 @@ static void if_dump(const struct interface *ifp)
        struct listnode *node;
        struct connected *c __attribute__((unused));
 
-       for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) {
-               struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
+       for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c))
                zlog_info(
                        "Interface %s vrf %s(%u) index %d metric %d mtu %d mtu6 %d %s",
-                       ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
+                       ifp->name, ifp->vrf->name, ifp->vrf_id, ifp->ifindex,
                        ifp->metric, ifp->mtu, ifp->mtu6,
                        if_flag_dump(ifp->flags));
-       }
 }
 
 /* Interface printing for all interface. */
@@ -894,16 +864,14 @@ connected_log(struct connected *connected, char *str)
 {
        struct prefix *p;
        struct interface *ifp;
-       struct vrf *vrf;
        char logbuf[BUFSIZ];
        char buf[BUFSIZ];
 
        ifp = connected->ifp;
        p = connected->address;
 
-       vrf = vrf_lookup_by_id(ifp->vrf_id);
        snprintf(logbuf, sizeof(logbuf), "%s interface %s vrf %s(%u) %s %pFX ",
-                str, ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id,
+                str, ifp->name, ifp->vrf->name, ifp->vrf_id,
                 prefix_family_str(p), p);
 
        p = connected->destination;
@@ -1059,30 +1027,15 @@ struct connected *connected_get_linklocal(struct interface *ifp)
 void if_terminate(struct vrf *vrf)
 {
        struct interface *ifp;
-       bool delete;
-
-       /*
-        * If the default VRF is being terminated or has
-        * already been terminated it means that
-        * the program is shutting down and we need to
-        * delete all the interfaces. Otherwise, we only
-        * need to move VRF's interfaces to the default VRF.
-        */
-       delete = vrf_is_backend_netns() || vrf->vrf_id == VRF_DEFAULT
-                || !vrf_lookup_by_id(VRF_DEFAULT);
 
        while (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
                ifp = RB_ROOT(if_name_head, &vrf->ifaces_by_name);
 
-               if (delete) {
-                       if (ifp->node) {
-                               ifp->node->info = NULL;
-                               route_unlock_node(ifp->node);
-                       }
-                       if_delete(&ifp);
-               } else {
-                       if_update_to_new_vrf(ifp, VRF_DEFAULT);
+               if (ifp->node) {
+                       ifp->node->info = NULL;
+                       route_unlock_node(ifp->node);
                }
+               if_delete(&ifp);
        }
 }
 
@@ -1186,6 +1139,25 @@ void if_link_params_free(struct interface *ifp)
 
 /* ----------- CLI commands ----------- */
 
+/* Guess the VRF of an interface. */
+static int vrfname_by_ifname(const char *ifname, const char **vrfname)
+{
+       struct vrf *vrf;
+       struct interface *ifp;
+       int count = 0;
+
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               FOR_ALL_INTERFACES (vrf, ifp) {
+                       if (strmatch(ifp->name, ifname)) {
+                               *vrfname = vrf->name;
+                               count++;
+                       }
+               }
+       }
+
+       return count;
+}
+
 /*
  * XPath: /frr-interface:lib/interface
  */
@@ -1197,12 +1169,9 @@ DEFPY_YANG_NOSH (interface,
        VRF_CMD_HELP_STR)
 {
        char xpath_list[XPATH_MAXLEN];
-       vrf_id_t vrf_id;
        struct interface *ifp;
-       int ret;
-
-       if (!vrf_name)
-               vrf_name = VRF_DEFAULT_NAME;
+       struct vrf *vrf;
+       int ret, count;
 
        /*
         * This command requires special handling to maintain backward
@@ -1211,30 +1180,30 @@ DEFPY_YANG_NOSH (interface,
         * interface is found, then a new one should be created on the default
         * VRF.
         */
-       VRF_GET_ID(vrf_id, vrf_name, false);
-       ifp = if_lookup_by_name_all_vrf(ifname);
-       if (ifp && ifp->vrf_id != vrf_id) {
-               struct vrf *vrf;
-
+       if (vrf_is_backend_netns()) {
                /*
-                * Special case 1: a VRF name was specified, but the found
-                * interface is associated to different VRF. Reject the command.
+                * For backward compatibility, if the VRF name is not specified
+                * and there is exactly one interface with this name in the
+                * system, use its VRF. Otherwise fallback to the default VRF.
                 */
-               if (vrf_id != VRF_DEFAULT) {
-                       vty_out(vty, "%% interface %s not in %s vrf\n", ifname,
-                               vrf_name);
-                       return CMD_WARNING_CONFIG_FAILED;
+               if (!vrf_name) {
+                       count = vrfname_by_ifname(ifname, &vrf_name);
+                       if (count != 1)
+                               vrf_name = VRF_DEFAULT_NAME;
                }
-
+       } else {
                /*
-                * Special case 2: a VRF name was *not* specified, and the found
-                * interface is associated to a VRF other than the default one.
-                * Update vrf_id and vrf_name to account for that.
+                * If the interface already exists, use its VRF regardless of
+                * what user specified. We can't have same interface name in
+                * different VRFs with VRF-lite backend.
                 */
-               vrf = vrf_lookup_by_id(ifp->vrf_id);
-               assert(vrf);
-               vrf_id = ifp->vrf_id;
-               vrf_name = vrf->name;
+               ifp = if_lookup_by_name_all_vrf(ifname);
+               if (ifp) {
+                       vrf_name = ifp->vrf->name;
+               } else {
+                       if (!vrf_name)
+                               vrf_name = VRF_DEFAULT_NAME;
+               }
        }
 
        snprintf(xpath_list, sizeof(xpath_list),
@@ -1252,7 +1221,15 @@ DEFPY_YANG_NOSH (interface,
                 * all interface-level commands are converted to the new
                 * northbound model.
                 */
-               ifp = if_lookup_by_name(ifname, vrf_id);
+               if (vrf_is_backend_netns()) {
+                       vrf = vrf_lookup_by_name(vrf_name);
+                       if (vrf)
+                               ifp = if_lookup_by_name_vrf(ifname, vrf);
+                       else
+                               ifp = NULL;
+               } else {
+                       ifp = if_lookup_by_name_all_vrf(ifname);
+               }
                if (ifp)
                        VTY_PUSH_CONTEXT(INTERFACE_NODE, ifp);
        }
@@ -1397,7 +1374,6 @@ static int lib_interface_create(struct nb_cb_create_args *args)
 {
        const char *ifname;
        const char *vrfname;
-       struct vrf *vrf;
        struct interface *ifp;
 
        ifname = yang_dnode_get_string(args->dnode, "./name");
@@ -1405,39 +1381,11 @@ static int lib_interface_create(struct nb_cb_create_args *args)
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               vrf = vrf_lookup_by_name(vrfname);
-               if (!vrf) {
-                       zlog_warn("%s: VRF %s doesn't exist", __func__,
-                                 vrfname);
-                       return NB_ERR_VALIDATION;
-               }
-               if (vrf->vrf_id == VRF_UNKNOWN) {
-                       zlog_warn("%s: VRF %s is not active", __func__,
-                                 vrf->name);
-                       return NB_ERR_VALIDATION;
-               }
-
-               /* if VRF is netns or not yet known - init for instance
-                * then assumption is that passed config is exact
-                * then the user intent was not to use an other iface
-                */
-               if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {
-                       ifp = if_lookup_by_name_all_vrf(ifname);
-                       if (ifp && ifp->vrf_id != vrf->vrf_id) {
-                               zlog_warn(
-                                       "%s: interface %s already exists in another VRF",
-                                       __func__, ifp->name);
-                               return NB_ERR_VALIDATION;
-                       }
-               }
-               break;
        case NB_EV_PREPARE:
        case NB_EV_ABORT:
                break;
        case NB_EV_APPLY:
-               vrf = vrf_lookup_by_name(vrfname);
-               assert(vrf);
-               ifp = if_get_by_name(ifname, vrf->vrf_id);
+               ifp = if_get_by_name(ifname, VRF_UNKNOWN, vrfname);
 
                ifp->configured = true;
                nb_running_set_entry(args->dnode, ifp);
@@ -1488,7 +1436,7 @@ static const void *lib_interface_get_next(struct nb_cb_get_next_args *args)
                assert(vrf);
                pif = RB_MIN(if_name_head, &vrf->ifaces_by_name);
        } else {
-               vrf = vrf_lookup_by_id(pif->vrf_id);
+               vrf = pif->vrf;
                pif = RB_NEXT(if_name_head, pif);
                /* if no more interfaces, switch to next vrf */
                while (pif == NULL) {
@@ -1506,13 +1454,9 @@ static int lib_interface_get_keys(struct nb_cb_get_keys_args *args)
 {
        const struct interface *ifp = args->list_entry;
 
-       struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
-
-       assert(vrf);
-
        args->keys->num = 2;
        strlcpy(args->keys->key[0], ifp->name, sizeof(args->keys->key[0]));
-       strlcpy(args->keys->key[1], vrf->name, sizeof(args->keys->key[1]));
+       strlcpy(args->keys->key[1], ifp->vrf->name, sizeof(args->keys->key[1]));
 
        return NB_OK;
 }
index 59e75d8b6885b9f10ba5e1ac23fe28aba3b3e7ef..1125acd2042179a81a145588b2e05cee5d830b28 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -293,6 +293,8 @@ struct interface {
 #endif /* HAVE_NET_RT_IFLIST */
 
        struct route_node *node;
+
+       struct vrf *vrf;
        vrf_id_t vrf_id;
 
        /*
@@ -510,11 +512,6 @@ extern int if_cmp_name_func(const char *p1, const char *p2);
  */
 extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id);
 
-/* Create new interface, adds to name list only */
-extern struct interface *if_create_name(const char *name, vrf_id_t vrf_id);
-
-/* Create new interface, adds to index list only */
-extern struct interface *if_create_ifindex(ifindex_t ifindex, vrf_id_t vrf_id);
 extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id);
 extern struct interface *if_vrf_lookup_by_index_next(ifindex_t ifindex,
                                                     vrf_id_t vrf_id);
@@ -532,13 +529,11 @@ struct vrf;
 extern struct interface *if_lookup_by_name_all_vrf(const char *ifname);
 extern struct interface *if_lookup_by_name_vrf(const char *name, struct vrf *vrf);
 extern struct interface *if_lookup_by_name(const char *ifname, vrf_id_t vrf_id);
-extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id);
-extern struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id);
+extern struct interface *if_get_by_name(const char *ifname, vrf_id_t vrf_id,
+                                       const char *vrf_name);
 
 /* Sets the index and adds to index list */
 extern int if_set_index(struct interface *ifp, ifindex_t ifindex);
-/* Sets the name and adds to name list */
-extern void if_set_name(struct interface *ifp, const char *name);
 
 /* Delete the interface, but do not free the structure, and leave it in the
    interface list.  It is often advisable to leave the pseudo interface
index 198d5253c8ed20fdcf06ccafb8e3dee28ce63b1c..6bc10b8cfd282327a8c602f9fd254dc634f98c29 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -272,32 +272,29 @@ void vrf_delete(struct vrf *vrf)
        if (vrf_is_enabled(vrf))
                vrf_disable(vrf);
 
+       if (vrf->vrf_id != VRF_UNKNOWN) {
+               RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
+               vrf->vrf_id = VRF_UNKNOWN;
+       }
+
        /* If the VRF is user configured, it'll stick around, just remove
         * the ID mapping. Interfaces assigned to this VRF should've been
         * removed already as part of the VRF going down.
         */
        if (vrf_is_user_cfged(vrf)) {
-               if (vrf->vrf_id != VRF_UNKNOWN) {
-                       /* Delete any VRF interfaces - should be only
-                        * the VRF itself, other interfaces should've
-                        * been moved out of the VRF.
-                        */
-                       if_terminate(vrf);
-                       RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
-                       vrf->vrf_id = VRF_UNKNOWN;
-               }
                vrf->ns_ctxt = NULL;
                return;
        }
 
+       /* Do not delete the VRF if it has interfaces configured in it. */
+       if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name))
+               return;
+
        if (vrf_master.vrf_delete_hook)
                (*vrf_master.vrf_delete_hook)(vrf);
 
        QOBJ_UNREG(vrf);
-       if_terminate(vrf);
 
-       if (vrf->vrf_id != VRF_UNKNOWN)
-               RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
        if (vrf->name[0] != '\0')
                RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
 
@@ -571,6 +568,7 @@ static void vrf_terminate_single(struct vrf *vrf)
 {
        /* Clear configured flag and invoke delete. */
        UNSET_FLAG(vrf->status, VRF_CONFIGURED);
+       if_terminate(vrf);
        vrf_delete(vrf);
 }
 
index d639fa84b80c52e1eb7e6a410b8c491c343a139c..eea118738cdea23b49cf9091a959789eb0986b6d 100644 (file)
@@ -2164,19 +2164,21 @@ static int zclient_interface_add(struct zclient *zclient, vrf_id_t vrf_id)
        struct interface *ifp;
        char ifname_tmp[INTERFACE_NAMSIZ + 1] = {};
        struct stream *s = zclient->ibuf;
+       struct vrf *vrf;
 
        /* Read interface name. */
        STREAM_GET(ifname_tmp, s, INTERFACE_NAMSIZ);
 
        /* Lookup/create interface by name. */
-       if (!vrf_get(vrf_id, NULL)) {
+       vrf = vrf_lookup_by_id(vrf_id);
+       if (!vrf) {
                zlog_debug(
                        "Rx'd interface add from Zebra, but VRF %u does not exist",
                        vrf_id);
                return -1;
        }
 
-       ifp = if_get_by_name(ifname_tmp, vrf_id);
+       ifp = if_get_by_name(ifname_tmp, vrf_id, vrf->name);
 
        zebra_interface_if_set_value(s, ifp);
 
index 9e3bb4895a82d7eed36d1f7a1d87d3da205dc870..7e9ed4160d546c4920f2fb4ea30ea45969757fea 100644 (file)
@@ -1032,7 +1032,6 @@ DEFUN_HIDDEN (ospf6_interface_area,
        struct ospf6_area *oa;
        struct ospf6_interface *oi;
        struct interface *ifp;
-       vrf_id_t vrf_id = VRF_DEFAULT;
        uint32_t area_id;
        int format;
 
@@ -1041,11 +1040,8 @@ DEFUN_HIDDEN (ospf6_interface_area,
        vty_out(vty,
                "Please, use \"ipv6 ospf6 area\" on an interface instead.\n");
 
-       if (ospf6->vrf_id != VRF_UNKNOWN)
-               vrf_id = ospf6->vrf_id;
-
        /* find/create ospf6 interface */
-       ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
+       ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
        oi = (struct ospf6_interface *)ifp->info;
        if (oi == NULL)
                oi = ospf6_interface_create(ifp);
@@ -1107,18 +1103,14 @@ DEFUN_HIDDEN (no_ospf6_interface_area,
        struct ospf6_area *oa;
        struct interface *ifp;
        uint32_t area_id;
-       vrf_id_t vrf_id = VRF_DEFAULT;
 
        vty_out(vty,
                "This command is deprecated, because it is not VRF-aware.\n");
        vty_out(vty,
                "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n");
 
-       if (ospf6->vrf_id != VRF_UNKNOWN)
-               vrf_id = ospf6->vrf_id;
-
        /* find/create ospf6 interface */
-       ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
+       ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name);
 
        if (ifp == NULL) {
                vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
index 81cc34600047b508f4156e0f499e1863d1f7bca0..60e109ea8006c24820f98de12a00b283d1867eeb 100644 (file)
@@ -915,9 +915,9 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf,
                        ospf->vrf_id);
 
        snprintf(ifname, sizeof(ifname), "VLINK%u", vlink_count);
-       vi = if_create_name(ifname, ospf->vrf_id);
+       vi = if_get_by_name(ifname, ospf->vrf_id, ospf->name);
        /*
-        * if_create_name sets ZEBRA_INTERFACE_LINKDETECTION
+        * if_get_by_name sets ZEBRA_INTERFACE_LINKDETECTION
         * virtual links don't need this.
         */
        UNSET_FLAG(vi->status, ZEBRA_INTERFACE_LINKDETECTION);
index 9863a101153fed8ff5190bc2307aea3a119e5b33..64d3b7a02817afe6cbe9a26fb163c0cd579ef94a 100644 (file)
@@ -445,7 +445,7 @@ DEFUN_HIDDEN (ospf_passive_interface_addr,
                "Please, use \"ip ospf passive\" on an interface instead.\n");
 
        if (ospf->vrf_id != VRF_UNKNOWN)
-               ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id);
+               ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id, ospf->name);
 
        if (ifp == NULL) {
                vty_out(vty, "interface %s not found.\n", (char *)argv[1]->arg);
@@ -506,7 +506,7 @@ DEFUN_HIDDEN (no_ospf_passive_interface,
                "Please, use \"no ip ospf passive\" on an interface instead.\n");
 
        if (ospf->vrf_id != VRF_UNKNOWN)
-               ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id);
+               ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id, ospf->name);
 
        if (ifp == NULL) {
                vty_out(vty, "interface %s not found.\n", (char *)argv[2]->arg);
index eb19cf4ddfda0a9a89028cdfc62f47ac20d8f0af..5e311d101a1087b3a0b3e1ae53c83a734c729619 100644 (file)
@@ -1482,7 +1482,8 @@ void pim_if_create_pimreg(struct pim_instance *pim)
                        snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
                                 pim->vrf->data.l.table_id);
 
-               pim->regiface = if_create_name(pimreg_name, pim->vrf->vrf_id);
+               pim->regiface = if_get_by_name(pimreg_name, pim->vrf->vrf_id,
+                                              pim->vrf->name);
                pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
 
                pim_if_new(pim->regiface, false, false, true,
index 14d8ac442ebaf0ef7553017d911f29dfec148285..c3faf22d17276e1677d4e8fbb1af98c7b30fff80 100644 (file)
@@ -109,7 +109,8 @@ static int interface_list_ioctl(void)
                unsigned int size;
 
                ifreq = (struct ifreq *)((caddr_t)ifconf.ifc_req + n);
-               ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT);
+               ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT,
+                                    VRF_DEFAULT_NAME);
                if_add_update(ifp);
                size = ifreq->ifr_addr.sa_len;
                if (size < sizeof(ifreq->ifr_addr))
@@ -119,7 +120,8 @@ static int interface_list_ioctl(void)
        }
 #else
        for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) {
-               ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT);
+               ifp = if_get_by_name(ifreq->ifr_name, VRF_DEFAULT,
+                                    VRF_DEFAULT_NAME);
                if_add_update(ifp);
                ifreq++;
        }
index fa3aabb1954069cbe7f6fa7649d12c4a8eafcf65..187cd10e9ce294f01a5f091bdc0d1ce77cecadca 100644 (file)
@@ -972,17 +972,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                link_nsid = ns_id_get_absolute(ns_id, link_nsid);
        }
 
-       /* Add interface.
-        * We add by index first because in some cases such as the master
-        * interface, we have the index before we have the name. Fixing
-        * back references on the slave interfaces is painful if not done
-        * this way, i.e. by creating by ifindex.
-        */
-       ifp = if_get_by_ifindex(ifi->ifi_index, vrf_id);
+       ifp = if_get_by_name(name, vrf_id, NULL);
        set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */
 
-       if_set_name(ifp, name);
-
        ifp->flags = ifi->ifi_flags & 0x0000fffff;
        ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]);
        ifp->metric = 0;
@@ -1814,7 +1806,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
 
                        if (ifp == NULL) {
                                /* unknown interface */
-                               ifp = if_get_by_name(name, vrf_id);
+                               ifp = if_get_by_name(name, vrf_id, NULL);
                        } else {
                                /* pre-configured interface, learnt now */
                                if (ifp->vrf_id != vrf_id)
index a68d00d55ce035c04d5812110d9c0a0a99e0179e..595862a6c99d847219d3c84d23df0d567ce64395 100644 (file)
@@ -1616,7 +1616,6 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
        struct listnode *node;
        struct route_node *rn;
        struct zebra_if *zebra_if;
-       struct vrf *vrf;
        char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
 
        zebra_if = ifp->info;
@@ -1644,8 +1643,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
 
        zebra_ptm_show_status(vty, NULL, ifp);
 
-       vrf = vrf_lookup_by_id(ifp->vrf_id);
-       vty_out(vty, "  vrf: %s\n", vrf->name);
+       vty_out(vty, "  vrf: %s\n", ifp->vrf->name);
 
        if (ifp->desc)
                vty_out(vty, "  Description: %s\n", ifp->desc);
@@ -1941,7 +1939,6 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
        struct listnode *node;
        struct route_node *rn;
        struct zebra_if *zebra_if;
-       struct vrf *vrf;
        char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN];
        char buf[BUFSIZ];
        json_object *json_if;
@@ -1979,8 +1976,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
 
        zebra_ptm_show_status(vty, json, ifp);
 
-       vrf = vrf_lookup_by_id(ifp->vrf_id);
-       json_object_string_add(json_if, "vrfName", vrf->name);
+       json_object_string_add(json_if, "vrfName", ifp->vrf->name);
 
        if (ifp->desc)
                json_object_string_add(json_if, "description", ifp->desc);
@@ -4206,21 +4202,19 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp)
 
 static int if_config_write(struct vty *vty)
 {
-       struct vrf *vrf0;
+       struct vrf *vrf;
        struct interface *ifp;
 
        zebra_ptm_write(vty);
 
-       RB_FOREACH (vrf0, vrf_name_head, &vrfs_by_name)
-               FOR_ALL_INTERFACES (vrf0, ifp) {
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
+               FOR_ALL_INTERFACES (vrf, ifp) {
                        struct zebra_if *if_data;
                        struct listnode *addrnode;
                        struct connected *ifc;
                        struct prefix *p;
-                       struct vrf *vrf;
 
                        if_data = ifp->info;
-                       vrf = vrf_lookup_by_id(ifp->vrf_id);
 
                        if (ifp->vrf_id == VRF_DEFAULT)
                                vty_frame(vty, "interface %s\n", ifp->name);
index d9c69ceb6d7ed043053981906d8ce1b4dca874bd..2db3e6e9047a67192c973236a0aabfb11eeaadcd 100644 (file)
@@ -443,7 +443,8 @@ static int ifan_read(struct if_announcemsghdr *ifan)
                                __func__, ifan->ifan_index, ifan->ifan_name);
 
                /* Create Interface */
-               ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT);
+               ifp = if_get_by_name(ifan->ifan_name, VRF_DEFAULT,
+                                    VRF_DEFAULT_NAME);
                if_set_index(ifp, ifan->ifan_index);
 
                if_get_metric(ifp);
@@ -624,7 +625,8 @@ int ifm_read(struct if_msghdr *ifm)
                if (ifp == NULL) {
                        /* Interface that zebra was not previously aware of, so
                         * create. */
-                       ifp = if_create_name(ifname, VRF_DEFAULT);
+                       ifp = if_get_by_name(ifname, VRF_DEFAULT,
+                                            VRF_DEFAULT_NAME);
                        if (IS_ZEBRA_DEBUG_KERNEL)
                                zlog_debug("%s: creating ifp for ifindex %d",
                                           __func__, ifm->ifm_index);