]> git.proxmox.com Git - mirror_frr.git/commitdiff
isisd: make spf MT aware
authorChristian Franke <chris@opensourcerouting.org>
Thu, 27 Apr 2017 11:56:47 +0000 (13:56 +0200)
committerChristian Franke <chris@opensourcerouting.org>
Fri, 28 Apr 2017 10:03:23 +0000 (12:03 +0200)
Signed-off-by: Christian Franke <chris@opensourcerouting.org>
isisd/isis_mt.c
isisd/isis_mt.h
isisd/isis_spf.c
isisd/isis_spf.h

index baf72ad22c86f7ce890830b2fabfabe6bc6b0357..42e7b57aa40e3cd14159d4bc6896142f4c243cb5 100644 (file)
@@ -447,6 +447,15 @@ tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
   return changed;
 }
 
+bool
+adj_has_mt(struct isis_adjacency *adj, uint16_t mtid)
+{
+  for (unsigned int i = 0; i < adj->mt_count; i++)
+    if (adj->mt_set[i] == mtid)
+      return true;
+  return false;
+}
+
 void
 adj_mt_finish(struct isis_adjacency *adj)
 {
@@ -454,6 +463,13 @@ adj_mt_finish(struct isis_adjacency *adj)
   adj->mt_count = 0;
 }
 
+/* TLV Router info api */
+struct mt_router_info*
+tlvs_lookup_mt_router_info(struct tlvs *tlvs, uint16_t mtid)
+{
+  return lookup_mt_setting(tlvs->mt_router_info, mtid);
+}
+
 /* TLV MT Neighbors api */
 struct tlv_mt_neighbors*
 tlvs_lookup_mt_neighbors(struct tlvs *tlvs, uint16_t mtid)
index 4c991dc5c95c9894893ea5bebe42007df0c5ac82..d4dc4c6f2a5a523f15644892adfb7d643e62ef4a 100644 (file)
@@ -92,6 +92,8 @@ struct te_is_neigh;
 
 uint16_t isis_area_ipv6_topology(struct isis_area *area);
 
+struct mt_router_info* tlvs_lookup_mt_router_info(struct tlvs *tlvs, uint16_t mtid);
+
 struct tlv_mt_neighbors* tlvs_lookup_mt_neighbors(struct tlvs *tlvs, uint16_t mtid);
 struct tlv_mt_neighbors* tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid);
 
@@ -135,6 +137,7 @@ struct isis_circuit_mt_setting** circuit_mt_settings(struct isis_circuit *circui
                                                      unsigned int *mt_count);
 bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
                         struct isis_adjacency *adj);
+bool adj_has_mt(struct isis_adjacency *adj, uint16_t mtid);
 void adj_mt_finish(struct isis_adjacency *adj);
 void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit,
                        int level, struct te_is_neigh *neigh);
index 8dd1dc981f0e40865a3bc7d4fc742625341a19b8..d85f08f50b7374ed851ba2cb342718138baded15 100644 (file)
@@ -51,6 +51,7 @@
 #include "isis_spf.h"
 #include "isis_route.h"
 #include "isis_csm.h"
+#include "isis_mt.h"
 
 DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info");
 
@@ -683,8 +684,14 @@ isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp,
   struct prefix prefix;
   struct ipv6_reachability *ip6reach;
   static const u_char null_sysid[ISIS_SYS_ID_LEN];
+  struct mt_router_info *mt_router_info = NULL;
 
-  if (!pseudo_lsp && !speaks (lsp->tlv_data.nlpids, spftree->family))
+  if (spftree->mtid != ISIS_MT_IPV4_UNICAST)
+    mt_router_info = tlvs_lookup_mt_router_info(&lsp->tlv_data, spftree->mtid);
+
+  if (!pseudo_lsp
+      && (spftree->mtid == ISIS_MT_IPV4_UNICAST && !speaks(lsp->tlv_data.nlpids, spftree->family))
+      && !mt_router_info)
     return ISIS_OK;
 
 lspfragloop:
@@ -699,9 +706,12 @@ lspfragloop:
 #endif /* EXTREME_DEBUG */
 
   /* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
-  if (pseudo_lsp || !ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
+  if (pseudo_lsp
+      || (spftree->mtid == ISIS_MT_IPV4_UNICAST && !ISIS_MASK_LSP_OL_BIT (lsp->lsp_header->lsp_bits))
+      || (mt_router_info && !mt_router_info->overload))
+
   {
-    if (lsp->tlv_data.is_neighs)
+    if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST)
     {
       for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.is_neighs, node, is_neigh))
       {
@@ -717,10 +727,20 @@ lspfragloop:
                    (void *) is_neigh->neigh_id, dist, depth + 1, parent);
       }
     }
-    if (lsp->tlv_data.te_is_neighs)
-    {
-      for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_is_neighs, node,
-            te_is_neigh))
+
+    struct list *te_is_neighs = NULL;
+    if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST)
+      {
+        te_is_neighs = lsp->tlv_data.te_is_neighs;
+      }
+    else
+      {
+        struct tlv_mt_neighbors *mt_neighbors;
+        mt_neighbors = tlvs_lookup_mt_neighbors(&lsp->tlv_data, spftree->mtid);
+        if (mt_neighbors)
+          te_is_neighs = mt_neighbors->list;
+      }
+    for (ALL_LIST_ELEMENTS_RO (te_is_neighs, node, te_is_neigh))
       {
         if (!memcmp (te_is_neigh->neigh_id, root_sysid, ISIS_SYS_ID_LEN))
           continue;
@@ -731,10 +751,11 @@ lspfragloop:
                                                                  : VTYPE_NONPSEUDO_TE_IS,
                    (void *) te_is_neigh->neigh_id, dist, depth + 1, parent);
       }
-    }
   }
 
-  if (!pseudo_lsp && spftree->family == AF_INET)
+  if (!pseudo_lsp
+      && spftree->family == AF_INET
+      && spftree->mtid == ISIS_MT_IPV4_UNICAST)
   {
     struct list *reachs[] = {lsp->tlv_data.ipv4_int_reachs,
                               lsp->tlv_data.ipv4_ext_reachs};
@@ -754,9 +775,26 @@ lspfragloop:
                        parent);
           }
       }
+  }
+
+  if (!pseudo_lsp && spftree->family == AF_INET)
+  {
+    struct list *ipv4reachs = NULL;
+
+    if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
+      {
+        ipv4reachs = lsp->tlv_data.te_ipv4_reachs;
+      }
+    else
+      {
+        struct tlv_mt_ipv4_reachs *mt_reachs;
+        mt_reachs = tlvs_lookup_mt_ipv4_reachs(&lsp->tlv_data, spftree->mtid);
+        if (mt_reachs)
+          ipv4reachs = mt_reachs->list;
+      }
 
-    for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.te_ipv4_reachs,
-                               node, te_ipv4_reach))
+    prefix.family = AF_INET;
+    for (ALL_LIST_ELEMENTS_RO (ipv4reachs, node, te_ipv4_reach))
     {
       assert ((te_ipv4_reach->control & 0x3F) <= IPV4_MAX_BITLEN);
 
@@ -770,10 +808,25 @@ lspfragloop:
     }
   }
 
-  if (!pseudo_lsp && spftree->family == AF_INET6)
+  if (!pseudo_lsp
+      && spftree->family == AF_INET6)
   {
+    struct list *ipv6reachs = NULL;
+
+    if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
+      {
+        ipv6reachs = lsp->tlv_data.ipv6_reachs;
+      }
+    else
+      {
+        struct tlv_mt_ipv6_reachs *mt_reachs;
+        mt_reachs = tlvs_lookup_mt_ipv6_reachs(&lsp->tlv_data, spftree->mtid);
+        if (mt_reachs)
+          ipv6reachs = mt_reachs->list;
+      }
+
     prefix.family = AF_INET6;
-    for (ALL_LIST_ELEMENTS_RO (lsp->tlv_data.ipv6_reachs, node, ip6reach))
+    for (ALL_LIST_ELEMENTS_RO (ipv6reachs, node, ip6reach))
     {
       assert (ip6reach->prefix_len <= IPV6_MAX_BITLEN);
 
@@ -820,9 +873,13 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
   u_char lsp_id[ISIS_SYS_ID_LEN + 2];
   static u_char null_lsp_id[ISIS_SYS_ID_LEN + 2];
   struct prefix_ipv6 *ipv6;
+  struct isis_circuit_mt_setting *circuit_mt;
 
   for (ALL_LIST_ELEMENTS_RO (spftree->area->circuit_list, cnode, circuit))
     {
+      circuit_mt = circuit_lookup_mt_setting(circuit, spftree->mtid);
+      if (circuit_mt && !circuit_mt->enabled)
+       continue;
       if (circuit->state != C_STATE_UP)
        continue;
       if (!(circuit->is_type & spftree->level))
@@ -876,8 +933,10 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
            }
           for (ALL_LIST_ELEMENTS_RO (adj_list, anode, adj))
            {
-             if (!speaks (&adj->nlpids, spftree->family))
-                 continue;
+             if (!adj_has_mt(adj, spftree->mtid))
+               continue;
+             if (spftree->mtid == ISIS_MT_IPV4_UNICAST && !speaks (&adj->nlpids, spftree->family))
+               continue;
              switch (adj->sys_type)
                {
                case ISIS_SYSTYPE_ES:
@@ -953,6 +1012,8 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
          adj = circuit->u.p2p.neighbor;
          if (!adj)
            continue;
+         if (!adj_has_mt(adj, spftree->mtid))
+           continue;
          switch (adj->sys_type)
            {
            case ISIS_SYSTYPE_ES:
@@ -966,7 +1027,7 @@ isis_spf_preload_tent (struct isis_spftree *spftree,
              memcpy (lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
              LSP_PSEUDO_ID (lsp_id) = 0;
              LSP_FRAGMENT (lsp_id) = 0;
-             if (speaks (&adj->nlpids, spftree->family))
+             if (spftree->mtid != ISIS_MT_IPV4_UNICAST || speaks (&adj->nlpids, spftree->family))
                isis_spf_add_local (spftree,
                                    spftree->area->oldmetric ? VTYPE_NONPSEUDO_IS
                                                             : VTYPE_NONPSEUDO_TE_IS,
@@ -1029,13 +1090,14 @@ add_to_paths (struct isis_spftree *spftree, struct isis_vertex *vertex)
 }
 
 static void
-init_spt (struct isis_spftree *spftree, int level, int family)
+init_spt (struct isis_spftree *spftree, int mtid, int level, int family)
 {
   spftree->tents->del = spftree->paths->del = (void (*)(void *)) isis_vertex_del;
   list_delete_all_node (spftree->tents);
   list_delete_all_node (spftree->paths);
   spftree->tents->del = spftree->paths->del = NULL;
 
+  spftree->mtid = mtid;
   spftree->level = level;
   spftree->family = family;
   return;
@@ -1054,6 +1116,7 @@ isis_run_spf (struct isis_area *area, int level, int family, u_char *sysid)
   struct route_table *table = NULL;
   struct timeval time_now;
   unsigned long long start_time, end_time;
+  uint16_t mtid;
 
   /* Get time that can't roll backwards. */
   monotime(&time_now);
@@ -1075,10 +1138,16 @@ isis_run_spf (struct isis_area *area, int level, int family, u_char *sysid)
 
   isis_route_invalidate_table (area, table);
 
+  /* We only support ipv4-unicast and ipv6-unicast as topologies for now */
+  if (family == AF_INET6)
+    mtid = isis_area_ipv6_topology(area);
+  else
+    mtid = ISIS_MT_IPV4_UNICAST;
+
   /*
    * C.2.5 Step 0
    */
-  init_spt (spftree, level, family);
+  init_spt (spftree, mtid, level, family);
   /*              a) */
   root_vertex = isis_spf_add_root (spftree, sysid);
   /*              b) */
index 64582c62c90617b28730a6b91843169aedbde1c9..9f06dbb602bdde9df1f7be6936ae65bf05d2cf3d 100644 (file)
@@ -71,6 +71,7 @@ struct isis_spftree
   time_t last_run_timestamp;    /* last run timestamp for scheduling */
   time_t last_run_duration;     /* last run duration in msec */
 
+  uint16_t mtid;
   int family;
   int level;
 };