]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #7790 from mobash-rasool/ospfv3-max-path
authorDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 18 Jan 2021 11:44:18 +0000 (06:44 -0500)
committerGitHub <noreply@github.com>
Mon, 18 Jan 2021 11:44:18 +0000 (06:44 -0500)
ospfd: Clear ip ospf process and clear ip ospf neighbor

doc/user/ospfd.rst
ospfd/ospf_ase.c
ospfd/ospf_lsa.c
ospfd/ospf_vty.c
ospfd/ospfd.c
ospfd/ospfd.h

index cbde0fd46f1b92c1af6a95858cd931d0937eeaa2..7184a0e19757fc6ccd68c084618a4c5d9c563922 100644 (file)
@@ -322,6 +322,23 @@ To start OSPF process you have to specify the OSPF router.
 
    This feature is enabled by default.
 
+.. index:: clear ip ospf [(1-65535)] process
+.. clicmd:: clear ip ospf [(1-65535)] process
+
+   This command can be used to clear the ospf process data structures. This
+   will clear the ospf neighborship as well and it will get re-established.
+   This will clear the LSDB too. This will be helpful when there is a change
+   in router-id and if user wants the router-id change to take effect, user can
+   use this cli instead of restarting the ospfd daemon.
+
+.. index:: clear ip ospf [(1-65535)] neighbor
+.. clicmd:: clear ip ospf [(1-65535)] neighbor
+
+   This command can be used to clear the ospf neighbor data structures. This
+   will clear the ospf neighborship and it will get re-established. This
+   command can be used when the neighbor state get stuck at some state and
+   this can be used to recover it from that state.
+
 .. _ospf-area:
 
 Areas
index e99653f91879d91f3f4b7808568db231097446bb..e18d8ddb31d0f20e455a3a68b0366e80b9f56957 100644 (file)
@@ -748,8 +748,13 @@ void ospf_ase_unregister_external_lsa(struct ospf_lsa *lsa, struct ospf *top)
 
        if (rn) {
                lst = rn->info;
-               listnode_delete(lst, lsa);
-               ospf_lsa_unlock(&lsa); /* external_lsas list */
+               struct listnode *node = listnode_lookup(lst, lsa);
+               /* Unlock lsa only if node is present in the list */
+               if (node) {
+                       listnode_delete(lst, lsa);
+                       ospf_lsa_unlock(&lsa); /* external_lsas list */
+               }
+
                route_unlock_node(rn);
        }
 }
index d5eba74fd43e42186fcfca705fb4b6c366c9a8e5..4c9db16c6b8ec46dea633ad8cf636d872a578002 100644 (file)
@@ -2789,7 +2789,7 @@ int ospf_check_nbr_status(struct ospf *ospf)
 static int ospf_maxage_lsa_remover(struct thread *thread)
 {
        struct ospf *ospf = THREAD_ARG(thread);
-       struct ospf_lsa *lsa;
+       struct ospf_lsa *lsa, *old;
        struct route_node *rn;
        int reschedule = 0;
 
@@ -2851,6 +2851,17 @@ static int ospf_maxage_lsa_remover(struct thread *thread)
 
                        /* Remove from lsdb. */
                        if (lsa->lsdb) {
+                               old = ospf_lsdb_lookup(lsa->lsdb, lsa);
+                               /* The max age LSA here must be the same
+                                * as the LSA in LSDB
+                                */
+                               if (old != lsa) {
+                                       flog_err(EC_OSPF_LSA_MISSING,
+                                       "%s: LSA[Type%d:%s]: LSA not in LSDB",
+                                       __func__, lsa->data->type,
+                                       inet_ntoa(lsa->data->id));
+                                       continue;
+                               }
                                ospf_discard_from_db(ospf, lsa->lsdb, lsa);
                                ospf_lsdb_delete(lsa->lsdb, lsa);
                        } else {
index c58073c52152378b6fcd34aae3236cb703b3cdbd..68ad62cda41d91b35f9d9090d3fdc44c673719f1 100644 (file)
@@ -280,7 +280,7 @@ DEFPY (ospf_router_id,
        for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
                if (area->full_nbrs) {
                        vty_out(vty,
-                               "For this router-id change to take effect, save config and restart ospfd\n");
+                               "For this router-id change to take effect, use “clear ip ospf process” command\n");
                        return CMD_SUCCESS;
                }
 
@@ -313,7 +313,7 @@ DEFUN_HIDDEN (ospf_router_id_old,
        for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
                if (area->full_nbrs) {
                        vty_out(vty,
-                               "For this router-id change to take effect, save config and restart ospfd\n");
+                               "For this router-id change to take effect, use “clear ip ospf process” command\n");
                        return CMD_SUCCESS;
                }
 
@@ -346,7 +346,7 @@ DEFPY (no_ospf_router_id,
        for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
                if (area->full_nbrs) {
                        vty_out(vty,
-                               "For this router-id change to take effect, save config and restart ospfd\n");
+                               "For this router-id change to take effect, use “clear ip ospf process” command\n");
                        return CMD_SUCCESS;
                }
 
@@ -11227,6 +11227,70 @@ DEFUN (show_ip_ospf_vrfs,
 
        return CMD_SUCCESS;
 }
+DEFPY (clear_ip_ospf_neighbor,
+       clear_ip_ospf_neighbor_cmd,
+       "clear ip ospf [(1-65535)]$instance neighbor [A.B.C.D$nbr_id]",
+       CLEAR_STR
+       IP_STR
+       "OSPF information\n"
+       "Instance ID\n"
+       "Reset OSPF Neighbor\n"
+       "Neighbor ID\n")
+{
+       struct listnode *node;
+       struct ospf *ospf = NULL;
+
+       /* If user does not specify the arguments,
+        * instance = 0 and nbr_id = 0.0.0.0
+        */
+       if (instance != 0) {
+               /* This means clear only the particular ospf process */
+               ospf = ospf_lookup_instance(instance);
+               if (ospf == NULL)
+                       return CMD_NOT_MY_INSTANCE;
+       }
+
+       /* Clear all the ospf processes */
+       for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
+               if (!ospf->oi_running)
+                       continue;
+
+               ospf_neighbor_reset(ospf, nbr_id, nbr_id_str);
+       }
+
+       return CMD_SUCCESS;
+}
+
+DEFPY (clear_ip_ospf_process,
+       clear_ip_ospf_process_cmd,
+       "clear ip ospf [(1-65535)]$instance process",
+       CLEAR_STR
+       IP_STR
+       "OSPF information\n"
+       "Instance ID\n"
+       "Reset OSPF Process\n")
+{
+       struct listnode *node;
+       struct ospf *ospf = NULL;
+
+       /* Check if instance is not passed as an argument */
+       if (instance != 0) {
+               /* This means clear only the particular ospf process */
+               ospf = ospf_lookup_instance(instance);
+               if (ospf == NULL)
+                       return CMD_NOT_MY_INSTANCE;
+       }
+
+       /* Clear all the ospf processes */
+       for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
+               if (!ospf->oi_running)
+                       continue;
+
+               ospf_process_reset(ospf);
+       }
+
+       return CMD_SUCCESS;
+}
 
 static const char *const ospf_abr_type_str[] = {
        "unknown", "standard", "ibm", "cisco", "shortcut"
@@ -12623,6 +12687,8 @@ DEFUN (clear_ip_ospf_interface,
 void ospf_vty_clear_init(void)
 {
        install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd);
+       install_element(ENABLE_NODE, &clear_ip_ospf_process_cmd);
+       install_element(ENABLE_NODE, &clear_ip_ospf_neighbor_cmd);
 }
 
 
index 0adf8a7b41d8df8f7b085298abd40b9f90b4beed..bab75995b7d0dca36e2f864074f7c73d6c6647a7 100644 (file)
@@ -87,13 +87,15 @@ static void ospf_finish_final(struct ospf *);
 
 #define OSPF_EXTERNAL_LSA_ORIGINATE_DELAY 1
 
-void ospf_router_id_update(struct ospf *ospf)
+void ospf_process_refresh_data(struct ospf *ospf, bool reset)
 {
        struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id);
        struct in_addr router_id, router_id_old;
        struct ospf_interface *oi;
        struct interface *ifp;
-       struct listnode *node;
+       struct listnode *node, *nnode;
+       struct ospf_area *area;
+       bool rid_change = false;
 
        if (!ospf->oi_running) {
                if (IS_DEBUG_OSPF_EVENT)
@@ -126,8 +128,8 @@ void ospf_router_id_update(struct ospf *ospf)
                zlog_debug("Router-ID[OLD:%pI4]: Update to %pI4",
                           &ospf->router_id, &router_id);
 
-       if (!IPV4_ADDR_SAME(&router_id_old, &router_id)) {
-
+       rid_change = !(IPV4_ADDR_SAME(&router_id_old, &router_id));
+       if (rid_change || (reset)) {
                for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
                        /* Some nbrs are identified by router_id, these needs
                         * to be rebuilt. Possible optimization would be to do
@@ -149,16 +151,8 @@ void ospf_router_id_update(struct ospf *ospf)
                                ospf_if_up(oi);
                }
 
-               /* Flush (inline) all external LSAs based on the OSPF_LSA_SELF
-                * flag */
-               if (ospf->lsdb) {
-                       struct route_node *rn;
-                       struct ospf_lsa *lsa;
-
-                       LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
-                               if (IS_LSA_SELF(lsa))
-                                       ospf_lsa_flush_schedule(ospf, lsa);
-               }
+               /* Flush (inline) all the self originated LSAs */
+               ospf_flush_self_originated_lsas_now(ospf);
 
                ospf->router_id = router_id;
                if (IS_DEBUG_OSPF_EVENT)
@@ -183,24 +177,81 @@ void ospf_router_id_update(struct ospf *ospf)
                        LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa) {
                                /* AdvRouter and Router ID is the same. */
                                if (IPV4_ADDR_SAME(&lsa->data->adv_router,
-                                                  &ospf->router_id)) {
+                                       &ospf->router_id) && rid_change) {
                                        SET_FLAG(lsa->flags,
                                                 OSPF_LSA_SELF_CHECKED);
                                        SET_FLAG(lsa->flags, OSPF_LSA_SELF);
                                        ospf_lsa_flush_schedule(ospf, lsa);
                                }
+                               /* The above flush will send immediately
+                                * So discard the LSA to originate new
+                                */
+                               ospf_discard_from_db(ospf, ospf->lsdb, lsa);
                        }
+
+                       LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
+                               ospf_discard_from_db(ospf, ospf->lsdb, lsa);
+
+                       ospf_lsdb_delete_all(ospf->lsdb);
                }
 
+               /* Delete the LSDB */
+               for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
+                       ospf_area_lsdb_discard_delete(area);
+
                /* update router-lsa's for each area */
                ospf_router_lsa_update(ospf);
 
                /* update ospf_interface's */
-               FOR_ALL_INTERFACES (vrf, ifp)
-                       ospf_if_update(ospf, ifp);
+               FOR_ALL_INTERFACES (vrf, ifp) {
+                       if (reset)
+                               ospf_if_reset(ifp);
+                       else
+                               ospf_if_update(ospf, ifp);
+               }
 
                ospf_external_lsa_rid_change(ospf);
        }
+
+       ospf->inst_shutdown = 0;
+}
+
+void ospf_router_id_update(struct ospf *ospf)
+{
+       ospf_process_refresh_data(ospf, false);
+}
+
+void ospf_process_reset(struct ospf *ospf)
+{
+       ospf_process_refresh_data(ospf, true);
+}
+
+void ospf_neighbor_reset(struct ospf *ospf, struct in_addr nbr_id,
+                       const char *nbr_str)
+{
+       struct route_node *rn;
+       struct ospf_neighbor *nbr;
+       struct ospf_interface *oi;
+       struct listnode *node;
+
+       /* Clear only a particular nbr with nbr router id as nbr_id */
+       if (nbr_str != NULL) {
+               for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
+                       nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, &nbr_id);
+                       if (nbr)
+                               OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
+               }
+               return;
+       }
+
+       /* send Neighbor event KillNbr to all associated neighbors. */
+       for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
+               for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+                       nbr = rn->info;
+                       if (nbr && (nbr != oi->nbr_self))
+                               OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
+               }
+       }
 }
 
 /* For OSPF area sort by area id. */
@@ -870,14 +921,11 @@ static struct ospf_area *ospf_area_new(struct ospf *ospf,
        return new;
 }
 
-static void ospf_area_free(struct ospf_area *area)
+void ospf_area_lsdb_discard_delete(struct ospf_area *area)
 {
        struct route_node *rn;
        struct ospf_lsa *lsa;
 
-       ospf_opaque_type10_lsa_term(area);
-
-       /* Free LSDBs. */
        LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
                ospf_discard_from_db(area->ospf, area->lsdb, lsa);
        LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
@@ -895,6 +943,15 @@ static void ospf_area_free(struct ospf_area *area)
                ospf_discard_from_db(area->ospf, area->lsdb, lsa);
 
        ospf_lsdb_delete_all(area->lsdb);
+}
+
+static void ospf_area_free(struct ospf_area *area)
+{
+       ospf_opaque_type10_lsa_term(area);
+
+       /* Free LSDBs. */
+       ospf_area_lsdb_discard_delete(area);
+
        ospf_lsdb_free(area->lsdb);
 
        ospf_lsa_unlock(&area->router_lsa_self);
index 3087b735aea771e8066b7386d4aba13e8876b74d..6960d151c2213fd4a7011657eddf4845095eb979 100644 (file)
@@ -571,7 +571,11 @@ extern struct ospf *ospf_lookup_by_inst_name(unsigned short instance,
                                             const char *name);
 extern struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id);
 extern void ospf_finish(struct ospf *);
+extern void ospf_process_refresh_data(struct ospf *ospf, bool reset);
 extern void ospf_router_id_update(struct ospf *ospf);
+extern void ospf_process_reset(struct ospf *ospf);
+extern void ospf_neighbor_reset(struct ospf *ospf, struct in_addr nbr_id,
+                               const char *nbr_str);
 extern int ospf_network_set(struct ospf *, struct prefix_ipv4 *, struct in_addr,
                            int);
 extern int ospf_network_unset(struct ospf *, struct prefix_ipv4 *,
@@ -596,6 +600,7 @@ extern int ospf_area_shortcut_set(struct ospf *, struct ospf_area *, int);
 extern int ospf_area_shortcut_unset(struct ospf *, struct ospf_area *);
 extern int ospf_timers_refresh_set(struct ospf *, int);
 extern int ospf_timers_refresh_unset(struct ospf *);
+void ospf_area_lsdb_discard_delete(struct ospf_area *area);
 extern int ospf_nbr_nbma_set(struct ospf *, struct in_addr);
 extern int ospf_nbr_nbma_unset(struct ospf *, struct in_addr);
 extern int ospf_nbr_nbma_priority_set(struct ospf *, struct in_addr, uint8_t);