]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/interface.c
Merge pull request #5789 from donaldsharp/bgp_ebgp_reason
[mirror_frr.git] / zebra / interface.c
index ef03cf87f62c061ee648a2fbb98e2279a0c5787b..bcb833b8d8f019b1ed7532533345b9a5bb2c4e42 100644 (file)
@@ -107,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};
@@ -120,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();
@@ -147,6 +161,7 @@ static int if_zebra_new_hook(struct interface *ifp)
                rtadv->HomeAgentLifetime =
                        -1; /* derive from AdvDefaultLifetime */
                rtadv->AdvIntervalOption = 0;
+               rtadv->UseFastRexmit = true;
                rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
 
                rtadv->AdvPrefixList = list_new();
@@ -175,6 +190,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)
 {
@@ -196,7 +239,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);
@@ -692,7 +739,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;
                                }
@@ -713,7 +760,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;
@@ -783,7 +830,7 @@ void if_delete_update(struct interface *ifp)
                if (IS_ZEBRA_DEBUG_KERNEL)
                        zlog_debug("interface %s is being deleted from the system",
                                   ifp->name);
-               if_delete(ifp);
+               if_delete(&ifp);
        }
 }
 
@@ -925,6 +972,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)
 {
@@ -950,7 +1038,8 @@ void if_up(struct interface *ifp)
 #if defined(HAVE_RTADV)
        /* Enable fast tx of RA if enabled && RA interval is not in msecs */
        if (zif->rtadv.AdvSendAdvertisements
-           && (zif->rtadv.MaxRtrAdvInterval >= 1000)) {
+           && (zif->rtadv.MaxRtrAdvInterval >= 1000)
+           && zif->rtadv.UseFastRexmit) {
                zif->rtadv.inFastRexmit = 1;
                zif->rtadv.NumFastReXmitsRemain = RTADV_NUM_FAST_REXMITS;
        }
@@ -973,7 +1062,9 @@ void if_up(struct interface *ifp)
                                                    zif->link_ifindex);
                if (link_if)
                        zebra_vxlan_svi_up(ifp, link_if);
-       }
+       } else if (IS_ZEBRA_IF_MACVLAN(ifp))
+               zebra_vxlan_macvlan_up(ifp);
+
 }
 
 /* Interface goes down.  We have to manage different behavior of based
@@ -988,6 +1079,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
@@ -1003,7 +1096,8 @@ void if_down(struct interface *ifp)
                                                    zif->link_ifindex);
                if (link_if)
                        zebra_vxlan_svi_down(ifp, link_if);
-       }
+       } else if (IS_ZEBRA_IF_MACVLAN(ifp))
+               zebra_vxlan_macvlan_down(ifp);
 
 
        /* Notify to the protocol daemons. */
@@ -1883,6 +1977,8 @@ DEFUN (shutdown_if,
        struct zebra_if *if_data;
 
        if (ifp->ifindex != IFINDEX_INTERNAL) {
+               /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
+               rtadv_stop_ra(ifp);
                ret = if_unset_flags(ifp, IFF_UP);
                if (ret < 0) {
                        vty_out(vty, "Can't shutdown interface\n");
@@ -2789,7 +2885,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;
        }
 
@@ -3014,7 +3110,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;
        }