]> git.proxmox.com Git - mirror_frr.git/commitdiff
isisd: fix crash on "no router isis" (BZ#536)
authorFritz Reichmann <fritz@reichmann.nl>
Wed, 14 Sep 2011 15:31:51 +0000 (19:31 +0400)
committerDenis Ovsienko <infrastation@yandex.ru>
Tue, 27 Sep 2011 16:48:43 +0000 (20:48 +0400)
The crash is due to threads accessing data that gets destroyed
during the removal of the configuration.

* isis_circuit.c: Destroy adjacencies to stop adjacency expiry thread.
  Stop PSNP threads.
* isisd.c: Change state of circuit back to INIT and reassign the
  circuit structure to isis->init_circ_list rather than destroying
  the circuit data structure. Stop SPF threads. Stop LSP generation
  threads.
* isisd.h: Add pointers to LSP threads into area structure in order to
  stop them in isisd.c
* isis_lsp.c: Store pointer to LSP thread in area structure.
* isis_pdu.c: Stop PDU generation for a circuit with a removed area.
* isis_pfpacket.c: Stop processing received PDUs for a circuit with a
  removed area.

isisd/isis_circuit.c
isisd/isis_lsp.c
isisd/isis_pdu.c
isisd/isis_pfpacket.c
isisd/isisd.c
isisd/isisd.h

index d2923b575135eb0aa59f1026343f6bc8af456bbf..e34d491a6eaaf3f403e63d5e7f40f6d7c9981342 100644 (file)
@@ -142,6 +142,11 @@ isis_circuit_deconfigure (struct isis_circuit *circuit,
                          struct isis_area *area)
 {
 
+  /* destroy adjacencies */
+  if (circuit->u.bc.adjdb[0])
+    isis_adjdb_iterate (circuit->u.bc.adjdb[0], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[0]);
+  if (circuit->u.bc.adjdb[1])
+    isis_adjdb_iterate (circuit->u.bc.adjdb[1], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[1]);
   /* Remove circuit from area */
   listnode_delete (area->circuit_list, circuit);
   /* Free the index of SRM and SSN flags */
@@ -602,6 +607,13 @@ isis_circuit_down (struct isis_circuit *circuit)
     {
       THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello);
     }
+
+  if (circuit->t_send_psnp[0]) {
+    THREAD_TIMER_OFF (circuit->t_send_psnp[0]);
+  }
+  if (circuit->t_send_psnp[1]) {
+    THREAD_TIMER_OFF (circuit->t_send_psnp[1]);
+  }
   /* close the socket */
   close (circuit->fd);
 
index 50289db39ffb200e9d4a235f54a8e5ec784f49ab..e12e4ca8ea42b1b4465e792ef512100202903426 100644 (file)
@@ -1640,7 +1640,7 @@ lsp_regenerate_schedule (struct isis_area *area)
       if (diff < MIN_LSP_GEN_INTERVAL)
        {
          area->lsp_regenerate_pending[0] = 1;
-         thread_add_timer (master, lsp_l1_regenerate, area,
+         area->t_lsp_l1_regenerate=thread_add_timer (master, lsp_l1_regenerate, area,
                            MIN_LSP_GEN_INTERVAL - diff);
          goto L2;
        }
@@ -1663,7 +1663,7 @@ L2:
       if (diff < MIN_LSP_GEN_INTERVAL)
        {
          area->lsp_regenerate_pending[1] = 1;
-         thread_add_timer (master, lsp_l2_regenerate, area,
+         area->t_lsp_l2_regenerate=thread_add_timer (master, lsp_l2_regenerate, area,
                            MIN_LSP_GEN_INTERVAL - diff);
          return ISIS_OK;
        }
index a2ab0649d1bf055a933ccc94ad82a5c3e7b06bca..26330a4d65b786610ed8056e9b6d4baa1c92c3db 100644 (file)
@@ -1781,6 +1781,9 @@ isis_receive (struct thread *thread)
   circuit = THREAD_ARG (thread);
   assert (circuit);
 
+  if (!circuit->area)
+    return ISIS_OK;
+
   if (circuit->rcv_stream == NULL)
     circuit->rcv_stream = stream_new (ISO_MTU (circuit));
   else
@@ -2088,6 +2091,11 @@ send_lan_l2_hello (struct thread *thread)
 
   circuit = THREAD_ARG (thread);
   assert (circuit);
+
+  if (!circuit->area) {
+    return ISIS_OK;
+  }
+
   circuit->u.bc.t_send_lan_hello[1] = NULL;
 
   if (circuit->u.bc.run_dr_elect[1])
index 9e4165e35b8b2d772c8543a4ac8b48bc67d9ef74..8a5c3ed063088608418917bb7b1f7077a7490c87 100644 (file)
@@ -232,6 +232,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
                        LLC_LEN, MSG_PEEK,
                        (struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
 
+  if (!circuit->area) {
+    return ISIS_OK;
+  }
+
   if (bytesread < 0)
     {
       zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s",
index 1e84a1cedb6732594242f5c93c2f298eaf787ca9..20a328092100c5a925c75f3c7655c7a6fbb00c78 100644 (file)
@@ -52,6 +52,7 @@
 #include "isisd/isis_route.h"
 #include "isisd/isis_zebra.h"
 #include "isisd/isis_events.h"
+#include "isisd/isis_csm.h"
 
 #ifdef TOPOLOGY_GENERATE
 #include "spgrid.h"
@@ -217,21 +218,31 @@ isis_area_destroy (struct vty *vty, const char *area_tag)
       for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
        {
          /* The fact that it's in circuit_list means that it was configured */
+         isis_csm_state_change (ISIS_DISABLE, circuit, area);
+         isis_circuit_down (circuit);
          isis_circuit_deconfigure (circuit, area);
-         isis_circuit_del (circuit);
        }
       
       list_delete (area->circuit_list);
     }
   listnode_delete (isis->area_list, area);
+
   THREAD_TIMER_OFF (area->t_tick);
   if (area->t_remove_aged)
     thread_cancel (area->t_remove_aged);
   THREAD_TIMER_OFF (area->t_lsp_refresh[0]);
   THREAD_TIMER_OFF (area->t_lsp_refresh[1]);
 
+  THREAD_TIMER_OFF (area->spftree[0]->t_spf);
+  THREAD_TIMER_OFF (area->spftree[1]->t_spf);
+
+  THREAD_TIMER_OFF (area->t_lsp_l1_regenerate);
+  THREAD_TIMER_OFF (area->t_lsp_l2_regenerate);
+
   XFREE (MTYPE_ISIS_AREA, area);
 
+  isis->sysid_set=0;
+
   return CMD_SUCCESS;
 }
 
index 2277f27c68cf3f05f863ee99f5205f84ad6be7ec..b17982e2522a194a1f7c1de85a1aa644dba19b6e 100644 (file)
@@ -93,6 +93,8 @@ struct isis_area
   struct flags flags;
   struct thread *t_tick;       /* LSP walker */
   struct thread *t_remove_aged;
+  struct thread *t_lsp_l1_regenerate;
+  struct thread *t_lsp_l2_regenerate;
   int lsp_regenerate_pending[ISIS_LEVELS];
   struct thread *t_lsp_refresh[ISIS_LEVELS];