]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/interface.c
*: Convert connected_free to a double pointer
[mirror_frr.git] / zebra / interface.c
index a2f80aff4e691101334561639e6b84b0ccc96359..5871b8746f1eef6eca6a1038cac07b3b11908de5 100644 (file)
@@ -70,10 +70,19 @@ static int if_zebra_speed_update(struct thread *thread)
        struct zebra_if *zif = ifp->info;
        uint32_t new_speed;
        bool changed = false;
+       int error = 0;
 
        zif->speed_update = NULL;
 
-       new_speed = kernel_get_speed(ifp);
+       new_speed = kernel_get_speed(ifp, &error);
+
+       /* error may indicate vrf not available or
+        * interfaces not available.
+        * note that loopback & virtual interfaces can return 0 as speed
+        */
+       if (error < 0)
+               return 1;
+
        if (new_speed != ifp->speed) {
                zlog_info("%s: %s old speed: %u new speed: %u",
                          __PRETTY_FUNCTION__, ifp->name, ifp->speed,
@@ -98,6 +107,17 @@ static void zebra_if_node_destroy(route_table_delegate_t *delegate,
        route_node_destroy(delegate, table, node);
 }
 
+static void zebra_if_nhg_dependents_free(struct zebra_if *zebra_if)
+{
+       nhg_connected_tree_free(&zebra_if->nhg_dependents);
+}
+
+static void zebra_if_nhg_dependents_init(struct zebra_if *zebra_if)
+{
+       nhg_connected_tree_init(&zebra_if->nhg_dependents);
+}
+
+
 route_table_delegate_t zebra_if_table_delegate = {
        .create_node = route_node_create,
        .destroy_node = zebra_if_node_destroy};
@@ -111,6 +131,9 @@ static int if_zebra_new_hook(struct interface *ifp)
 
        zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
        zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
+
+       zebra_if_nhg_dependents_init(zebra_if);
+
        zebra_ptm_if_init(zebra_if);
 
        ifp->ptm_enable = zebra_ptm_get_enable_state();
@@ -166,6 +189,34 @@ static int if_zebra_new_hook(struct interface *ifp)
        return 0;
 }
 
+static void if_nhg_dependents_check_valid(struct nhg_hash_entry *nhe)
+{
+       zebra_nhg_check_valid(nhe);
+       if (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID))
+               /* Assuming uninstalled as well here */
+               UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+}
+
+static void if_down_nhg_dependents(const struct interface *ifp)
+{
+       struct nhg_connected *rb_node_dep = NULL;
+       struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
+       frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep)
+               if_nhg_dependents_check_valid(rb_node_dep->nhe);
+}
+
+static void if_nhg_dependents_release(const struct interface *ifp)
+{
+       struct nhg_connected *rb_node_dep = NULL;
+       struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
+       frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
+               rb_node_dep->nhe->ifp = NULL; /* Null it out */
+               if_nhg_dependents_check_valid(rb_node_dep->nhe);
+       }
+}
+
 /* Called when interface is deleted. */
 static int if_zebra_delete_hook(struct interface *ifp)
 {
@@ -187,7 +238,11 @@ static int if_zebra_delete_hook(struct interface *ifp)
                list_delete(&rtadv->AdvDNSSLList);
 #endif /* HAVE_RTADV */
 
+               if_nhg_dependents_release(ifp);
+               zebra_if_nhg_dependents_free(zebra_if);
+
                XFREE(MTYPE_TMP, zebra_if->desc);
+
                THREAD_OFF(zebra_if->speed_update);
 
                XFREE(MTYPE_ZINFO, zebra_if);
@@ -261,8 +316,10 @@ struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns,
 
        for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
                ifp = (struct interface *)rn->info;
-               if (ifp && strcmp(ifp->name, ifname) == 0)
+               if (ifp && strcmp(ifp->name, ifname) == 0) {
+                       route_unlock_node(rn);
                        return (ifp);
+               }
        }
 
        return NULL;
@@ -681,7 +738,7 @@ static void if_delete_connected(struct interface *ifp)
                                                        ZEBRA_IFC_CONFIGURED)) {
                                                listnode_delete(ifp->connected,
                                                                ifc);
-                                               connected_free(ifc);
+                                               connected_free(&ifc);
                                        } else
                                                last = node;
                                }
@@ -702,7 +759,7 @@ static void if_delete_connected(struct interface *ifp)
                                last = node;
                        else {
                                listnode_delete(ifp->connected, ifc);
-                               connected_free(ifc);
+                               connected_free(&ifc);
                        }
                } else {
                        last = node;
@@ -767,6 +824,13 @@ void if_delete_update(struct interface *ifp)
                memset(&zif->brslave_info, 0,
                       sizeof(struct zebra_l2info_brslave));
        }
+
+       if (!ifp->configured) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("interface %s is being deleted from the system",
+                                  ifp->name);
+               if_delete(ifp);
+       }
 }
 
 /* VRF change for an interface */
@@ -907,6 +971,47 @@ static void if_down_del_nbr_connected(struct interface *ifp)
        }
 }
 
+void if_nhg_dependents_add(struct interface *ifp, struct nhg_hash_entry *nhe)
+{
+       if (ifp->info) {
+               struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
+               nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe);
+       }
+}
+
+void if_nhg_dependents_del(struct interface *ifp, struct nhg_hash_entry *nhe)
+{
+       if (ifp->info) {
+               struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
+               nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe);
+       }
+}
+
+unsigned int if_nhg_dependents_count(const struct interface *ifp)
+{
+       if (ifp->info) {
+               struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
+               return nhg_connected_tree_count(&zif->nhg_dependents);
+       }
+
+       return 0;
+}
+
+
+bool if_nhg_dependents_is_empty(const struct interface *ifp)
+{
+       if (ifp->info) {
+               struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
+               return nhg_connected_tree_is_empty(&zif->nhg_dependents);
+       }
+
+       return false;
+}
+
 /* Interface is up. */
 void if_up(struct interface *ifp)
 {
@@ -970,6 +1075,8 @@ void if_down(struct interface *ifp)
        zif->down_count++;
        quagga_timestamp(2, zif->down_last, sizeof(zif->down_last));
 
+       if_down_nhg_dependents(ifp);
+
        /* Handle interface down for specific types for EVPN. Non-VxLAN
         * interfaces
         * are checked to see if (remote) neighbor entries need to be purged
@@ -1081,12 +1188,10 @@ static void connected_dump_vty(struct vty *vty, struct connected *connected)
        vty_out(vty, "/%d", p->prefixlen);
 
        /* If there is destination address, print it. */
-       if (connected->destination) {
-               vty_out(vty,
-                       (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
+       if (CONNECTED_PEER(connected) && connected->destination) {
+               vty_out(vty, " peer ");
                prefix_vty_out(vty, connected->destination);
-               if (CONNECTED_PEER(connected))
-                       vty_out(vty, "/%d", connected->destination->prefixlen);
+               vty_out(vty, "/%d", connected->destination->prefixlen);
        }
 
        if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
@@ -1558,7 +1663,7 @@ struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1};
 #endif
 /* Show all interfaces to vty. */
 DEFPY(show_interface, show_interface_cmd,
-      "show interface [vrf NAME$name] [brief$brief]",
+      "show interface [vrf NAME$vrf_name] [brief$brief]",
       SHOW_STR
       "Interface status and configuration\n"
       VRF_CMD_HELP_STR
@@ -1570,8 +1675,8 @@ DEFPY(show_interface, show_interface_cmd,
 
        interface_update_stats();
 
-       if (name)
-               VRF_GET_ID(vrf_id, name, false);
+       if (vrf_name)
+               VRF_GET_ID(vrf_id, vrf_name, false);
 
        /* All interface print. */
        vrf = vrf_lookup_by_id(vrf_id);
@@ -2036,13 +2141,13 @@ DEFUN (link_params_enable,
        /* This command could be issue at startup, when activate MPLS TE */
        /* on a new interface or after a ON / OFF / ON toggle */
        /* In all case, TE parameters are reset to their default factory */
-       if (IS_ZEBRA_DEBUG_EVENT)
+       if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
                zlog_debug(
                        "Link-params: enable TE link parameters on interface %s",
                        ifp->name);
 
        if (!if_link_params_get(ifp)) {
-               if (IS_ZEBRA_DEBUG_EVENT)
+               if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
                        zlog_debug(
                                "Link-params: failed to init TE link parameters  %s",
                                ifp->name);
@@ -2065,8 +2170,9 @@ DEFUN (no_link_params_enable,
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
 
-       zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
-                  ifp->name);
+       if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
+               zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
+                          ifp->name);
 
        if_link_params_free(ifp);
 
@@ -2684,12 +2790,6 @@ static int ip_address_install(struct vty *vty, struct interface *ifp,
                        p = prefix_ipv4_new();
                        *p = pp;
                        ifc->destination = (struct prefix *)p;
-               } else if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) {
-                       p = prefix_ipv4_new();
-                       *p = lp;
-                       p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,
-                                                              p->prefixlen);
-                       ifc->destination = (struct prefix *)p;
                }
 
                /* Label. */
@@ -2778,7 +2878,7 @@ static int ip_address_uninstall(struct vty *vty, struct interface *ifp,
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
            || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
                listnode_delete(ifp->connected, ifc);
-               connected_free(ifc);
+               connected_free(&ifc);
                return CMD_WARNING_CONFIG_FAILED;
        }
 
@@ -3003,7 +3103,7 @@ static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp,
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
            || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
                listnode_delete(ifp->connected, ifc);
-               connected_free(ifc);
+               connected_free(&ifc);
                return CMD_WARNING_CONFIG_FAILED;
        }
 
@@ -3203,6 +3303,11 @@ void zebra_if_init(void)
        install_node(&interface_node, if_config_write);
        install_node(&link_params_node, NULL);
        if_cmd_init();
+       /*
+        * This is *intentionally* setting this to NULL, signaling
+        * that interface creation for zebra acts differently
+        */
+       if_zapi_callbacks(NULL, NULL, NULL, NULL);
 
        install_element(VIEW_NODE, &show_interface_cmd);
        install_element(VIEW_NODE, &show_interface_vrf_all_cmd);