]> git.puffer.fish Git - mirror/frr.git/commitdiff
* isis_spf.c: Changing cost from uint16_t to uint32_t. Unset
authorhasso <hasso>
Mon, 26 Sep 2005 18:26:26 +0000 (18:26 +0000)
committerhasso <hasso>
Mon, 26 Sep 2005 18:26:26 +0000 (18:26 +0000)
  ISIS_ROUTE_FLAG_ACTIVE flag before running SPF.
* isisd.[ch]: Separate route tables for different levels. SPF is done
  separately, but in case of L1L2 area they have to be merged.
* isis_zebra.c: Set/unset ISIS_ROUTE_FLAG_ZEBRA_SYNC flag correctly in
  case of adding/removing IPv4 routes.
* zebra_route.c: Rework route validating process. Merging L1 and L2
  tables in case of L1L2 area.

        In short - many changes to make SPF work more correctly, add/remove
        to/from RIB also works now. It's still very far from perfect though.

isisd/ChangeLog
isisd/isis_route.c
isisd/isis_route.h
isisd/isis_spf.c
isisd/isis_zebra.c
isisd/isisd.c
isisd/isisd.h

index 7f3cd9daf02bcb6bd2481c705848a380a408a1bc..8687ee75319d85471774098b9d599a4f242ab19b 100644 (file)
@@ -1,3 +1,14 @@
+2005-09-26 Hasso Tepper <hasso at quagga.net>
+
+       * isis_spf.c: Changing cost from uint16_t to uint32_t. Unset
+         ISIS_ROUTE_FLAG_ACTIVE flag before running SPF.
+       * isisd.[ch]: Separate route tables for different levels. SPF is done
+         separately, but in case of L1L2 area they have to be merged.
+       * isis_zebra.c: Set/unset ISIS_ROUTE_FLAG_ZEBRA_SYNC flag correctly in
+         case of adding/removing IPv4 routes.
+       * zebra_route.c: Rework route validating process. Merging L1 and L2
+         tables in case of L1L2 area.
+
 2005-09-26 Hasso Tepper <hasso at quagga.net>
 
        * isis_spf.[ch]: Added TE TLVs to the SPF process. It seems to work
index 7cee89ee32c032bdeb37e62e84a58ab14c1c5f83..e451312535b9d2253b7213a0495ae0799ffc894a 100644 (file)
@@ -451,7 +451,8 @@ isis_route_info_prefer_new (struct isis_route_info *new,
 
 struct isis_route_info *
 isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
-                  struct list *adjacencies, struct isis_area *area)
+                  struct list *adjacencies, struct isis_area *area,
+                  int level)
 {
   struct route_node *route_node;
   struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL;
@@ -471,10 +472,10 @@ isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
     }
 
   if (family == AF_INET)
-    route_node = route_node_get (area->route_table, prefix);
+    route_node = route_node_get (area->route_table[level - 1], prefix);
 #ifdef HAVE_IPV6
   else if (family == AF_INET6)
-    route_node = route_node_get (area->route_table6, prefix);
+    route_node = route_node_get (area->route_table6[level - 1], prefix);
 #endif /* HAVE_IPV6 */
   else
     return NULL;
@@ -585,31 +586,23 @@ isis_route_delete (struct prefix *prefix, struct route_table *table)
   return;
 }
 
-int
-isis_route_validate (struct thread *thread)
+/* Validating routes in particular table. */
+static void
+isis_route_validate_table (struct isis_area *area, struct route_table *table)
 {
-  struct isis_area *area;
-  struct route_table *table;
-  struct route_node *rode;
+  struct route_node *rnode, *drnode;
   struct isis_route_info *rinfo;
   u_char buff[BUFSIZ];
-#ifdef HAVE_IPV6
-  int v6done = 0;
-#endif
-  area = THREAD_ARG (thread);
-  table = area->route_table;
-#ifdef HAVE_IPV6
-again:
-#endif
-  for (rode = route_top (table); rode; rode = route_next (rode))
+
+  for (rnode = route_top (table); rnode; rnode = route_next (rnode))
     {
-      if (rode->info == NULL)
+      if (rnode->info == NULL)
        continue;
-      rinfo = rode->info;
+      rinfo = rnode->info;
 
       if (isis->debugs & DEBUG_RTE_EVENTS)
        {
-         prefix2str (&rode->p, (char *) buff, BUFSIZ);
+         prefix2str (&rnode->p, (char *) buff, BUFSIZ);
          zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s",
                      area->area_tag,
                      (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ?
@@ -618,16 +611,131 @@ again:
                      "active" : "inactive"), buff);
        }
 
-      isis_zebra_route_update (&rode->p, rinfo);
+      isis_zebra_route_update (&rnode->p, rinfo);
       if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
-       isis_route_delete (&rode->p, area->route_table);
+       {
+         /* Area is either L1 or L2 => we use level route tables directly for
+          * validating => no problems with deleting routes. */
+         if (area->is_type != IS_LEVEL_1_AND_2)
+           {
+             isis_route_delete (&rnode->p, table);
+             continue;
+           }
+         /* If area is L1L2, we work with merge table and therefore must
+          * delete node from level tables as well before deleting route info.
+          * FIXME: Is it performance problem? There has to be the better way.
+          * Like not to deal with it here at all (see the next comment)? */
+         if (rnode->p.family == AF_INET)
+           {
+             drnode = route_node_get (area->route_table[0], &rnode->p);
+             if (drnode->info == rnode->info)
+               drnode->info = NULL;
+             drnode = route_node_get (area->route_table[1], &rnode->p);
+             if (drnode->info == rnode->info)
+               drnode->info = NULL;
+           }
+         if (rnode->p.family == AF_INET6)
+           {
+             drnode = route_node_get (area->route_table6[0], &rnode->p);
+             if (drnode->info == rnode->info)
+               drnode->info = NULL;
+             drnode = route_node_get (area->route_table6[1], &rnode->p);
+             if (drnode->info == rnode->info)
+               drnode->info = NULL;
+           }
+             
+         isis_route_delete (&rnode->p, table);
+       }
+    }
+}
+
+/* Function to validate route tables for L1L2 areas. In this case we can't use
+ * level route tables directly, we have to merge them at first. L1 routes are
+ * preferred over the L2 ones.
+ *
+ * Merge algorithm is trivial (at least for now). All L1 paths are copied into
+ * merge table at first, then L2 paths are added if L1 path for same prefix
+ * doesn't already exists there.
+ *
+ * FIXME: Is it right place to do it at all? Maybe we should push both levels
+ * to the RIB with different zebra route types and let RIB handle this? */
+static void
+isis_route_validate_merge (struct isis_area *area, int family)
+{
+  struct route_table *table = NULL;
+  struct route_table *merge;
+  struct route_node *rnode, *mrnode;
+
+  merge = route_table_init ();
+
+  if (family == AF_INET)
+    table = area->route_table[0];
+  else if (family == AF_INET6)
+    table = area->route_table6[0];
+
+  for (rnode = route_top (table); rnode; rnode = route_next (rnode))
+    {
+      if (rnode->info == NULL)
+        continue;
+      mrnode = route_node_get (merge, &rnode->p);
+      mrnode->info = rnode->info;
     }
+
+  if (family == AF_INET)
+    table = area->route_table[1];
+  else if (family == AF_INET6)
+    table = area->route_table6[1];
+
+  for (rnode = route_top (table); rnode; rnode = route_next (rnode))
+    {
+      if (rnode->info == NULL)
+        continue;
+      mrnode = route_node_get (merge, &rnode->p);
+      if (mrnode->info != NULL)
+        continue;
+      mrnode->info = rnode->info;
+    }
+
+  isis_route_validate_table (area, merge);
+  route_table_finish (merge);
+}
+
+/* Walk through route tables and propagate necessary changes into RIB. In case
+ * of L1L2 area, level tables have to be merged at first. */
+int
+isis_route_validate (struct thread *thread)
+{
+  struct isis_area *area;
+
+  area = THREAD_ARG (thread);
+
+  if (area->is_type == IS_LEVEL_1)
+    { 
+      isis_route_validate_table (area, area->route_table[0]);
+      goto validate_ipv6;
+    }
+  if (area->is_type == IS_LEVEL_2)
+    {
+      isis_route_validate_table (area, area->route_table[1]);
+      goto validate_ipv6;
+    }
+
+  isis_route_validate_merge (area, AF_INET);
+
 #ifdef HAVE_IPV6
-  if (v6done)
-    return ISIS_OK;
-  table = area->route_table6;
-  v6done = 1;
-  goto again;
+validate_ipv6:
+  if (area->is_type == IS_LEVEL_1)
+    {
+      isis_route_validate_table (area, area->route_table6[0]);
+      return ISIS_OK;
+    }
+  if (area->is_type == IS_LEVEL_2)
+    {
+      isis_route_validate_table (area, area->route_table6[1]);
+      return ISIS_OK;
+    }
+
+  isis_route_validate_merge (area, AF_INET6);
 #endif
 
   return ISIS_OK;
index 59b6c226feb9becc370ca0f3f3d37609fe2ae701..4eac79b863d7093cffb381fb9e99bb2eed8a4bbe 100644 (file)
@@ -57,7 +57,7 @@ struct isis_route_info
 struct isis_route_info *isis_route_create (struct prefix *prefix,
                                           u_int32_t cost, u_int32_t depth,
                                           struct list *adjacencies,
-                                          struct isis_area *area);
+                                          struct isis_area *area, int level);
 
 int isis_route_validate (struct thread *thread);
 
index ac4c71f3f503cd4645c9a7695c7f61f2dcd92924..4cbc2cd16bbc1c19e3f00cf3ca758b58f7717f93 100644 (file)
@@ -394,7 +394,7 @@ isis_find_vertex (struct list *list, void *id, enum vertextype vtype)
  */
 static struct isis_vertex *
 isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
-                  void *id, struct isis_adjacency *adj, u_int16_t cost,
+                  void *id, struct isis_adjacency *adj, u_int32_t cost,
                   int depth, int family)
 {
   struct isis_vertex *vertex, *v;
@@ -457,7 +457,7 @@ isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype,
 
 static struct isis_vertex *
 isis_spf_add_local (struct isis_spftree *spftree, enum vertextype vtype,
-                   void *id, struct isis_adjacency *adj, u_int16_t cost,
+                   void *id, struct isis_adjacency *adj, u_int32_t cost,
                    int family)
 {
   struct isis_vertex *vertex;
@@ -553,7 +553,7 @@ process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id,
  */
 static int
 isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
-                     uint16_t cost, uint16_t depth, int family)
+                     uint32_t cost, uint16_t depth, int family)
 {
   struct listnode *node, *fragnode = NULL;
   u_int16_t dist;
@@ -945,7 +945,7 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
  */
 static void
 add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
-             struct isis_area *area)
+             struct isis_area *area, int level)
 {
 #ifdef EXTREME_DEBUG
   u_char buff[BUFSIZ];
@@ -960,8 +960,8 @@ add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex,
   if (vertex->type > VTYPE_ES)
     {
       if (listcount (vertex->Adj_N) > 0)
-       isis_route_create ((struct prefix *) &vertex->N.prefix,
-                          vertex->d_N, vertex->depth, vertex->Adj_N, area);
+       isis_route_create ((struct prefix *) &vertex->N.prefix, vertex->d_N,
+                          vertex->depth, vertex->Adj_N, area, level);
       else if (isis->debugs & DEBUG_SPF_EVENTS)
        zlog_debug ("ISIS-Spf: no adjacencies do not install route");
     }
@@ -989,6 +989,9 @@ isis_run_spf (struct isis_area *area, int level, int family)
   struct isis_spftree *spftree = NULL;
   u_char lsp_id[ISIS_SYS_ID_LEN + 2];
   struct isis_lsp *lsp;
+  struct route_table *table = NULL;
+  struct route_node *rode;
+  struct isis_route_info *rinfo;
 
   if (family == AF_INET)
     spftree = area->spftree[level - 1];
@@ -999,6 +1002,21 @@ isis_run_spf (struct isis_area *area, int level, int family)
 
   assert (spftree);
 
+  /* Make all routes in current route table inactive. */
+  if (family == AF_INET)
+    table = area->route_table[level - 1];
+  else if (family == AF_INET6)
+    table = area->route_table6[level - 1];
+
+  for (rode = route_top (table); rode; rode = route_next (rode))
+    {
+      if (rode->info == NULL)
+        continue;
+      rinfo = rode->info;
+
+      UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
+    }
+
   /*
    * C.2.5 Step 0
    */
@@ -1026,7 +1044,7 @@ isis_run_spf (struct isis_area *area, int level, int family)
       list_delete_node (spftree->tents, node);
       if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type))
        continue;
-      add_to_paths (spftree, vertex, area);
+      add_to_paths (spftree, vertex, area, level);
       if (vertex->type == VTYPE_PSEUDO_IS ||
          vertex->type == VTYPE_NONPSEUDO_IS)
        {
@@ -1225,7 +1243,7 @@ isis_run_spf6_l2 (struct thread *thread)
     }
 
   if (isis->debugs & DEBUG_SPF_EVENTS)
-    zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF", area->area_tag);
+    zlog_debug ("ISIS-Spf (%s) L2 SPF needed, periodic SPF.", area->area_tag);
 
   if (area->ipv6_circuits)
     retval = isis_run_spf (area, 2, AF_INET6);
index a385e6b5c94fd9e74b791fb201ec9daac8a9b216..aff6a716573e897fb8ad7e9ad718b9353b4fdfaf 100644 (file)
@@ -308,6 +308,7 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
 
       stream_putw_at (stream, 0, stream_get_endp (stream));
       zclient_send_message(zclient);
+      SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
     }
 }
 
@@ -328,6 +329,7 @@ isis_zebra_route_del_ipv4 (struct prefix *prefix,
       prefix4.prefix = prefix->u.prefix4;
       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
     }
+  UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
 
   return;
 }
index 2a60b8890147830953834537cefc13af8cccd8e1..dbaae8a8804e0ccc96887c8066a810e36f93f085 100644 (file)
@@ -106,9 +106,11 @@ isis_area_create ()
   area->lspdb[1] = lsp_db_init ();
 
   spftree_area_init (area);
-  area->route_table = route_table_init ();
+  area->route_table[0] = route_table_init ();
+  area->route_table[1] = route_table_init ();
 #ifdef HAVE_IPV6
-  area->route_table6 = route_table_init ();
+  area->route_table6[0] = route_table_init ();
+  area->route_table6[1] = route_table_init ();
 #endif /* HAVE_IPV6 */
   area->circuit_list = list_new ();
   area->area_addrs = list_new ();
index e61376e5b85c72d416b5e6a6ef4f34ff7dfbdefe..4e71640511e8532241bb87b8de4f5956bcde6410 100644 (file)
@@ -79,13 +79,13 @@ struct isis
 
 struct isis_area
 {
-  struct isis *isis;           /* back pointer */
-  dict_t *lspdb[ISIS_LEVELS];  /* link-state dbs */
-  struct isis_spftree *spftree[ISIS_LEVELS];   /* The v4 SPTs */
-  struct route_table *route_table;     /* IPv4 routes */
+  struct isis *isis;                             /* back pointer */
+  dict_t *lspdb[ISIS_LEVELS];                    /* link-state dbs */
+  struct isis_spftree *spftree[ISIS_LEVELS];     /* The v4 SPTs */
+  struct route_table *route_table[ISIS_LEVELS];          /* IPv4 routes */
 #ifdef HAVE_IPV6
-  struct isis_spftree *spftree6[ISIS_LEVELS];  /* The v4 SPTs */
-  struct route_table *route_table6;    /* IPv6 routes */
+  struct isis_spftree *spftree6[ISIS_LEVELS];    /* The v6 SPTs */
+  struct route_table *route_table6[ISIS_LEVELS];  /* IPv6 routes */
 #endif
   unsigned int min_bcast_mtu;
   struct list *circuit_list;   /* IS-IS circuits */