]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fixes OSPFv3 route generation for local stub networks.
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 2 Apr 2010 17:03:18 +0000 (19:03 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Fri, 2 Apr 2010 17:03:18 +0000 (19:03 +0200)
proto/ospf/rt.c

index b589459b3dce968b7f06bd3e3254f30ca45c8755..5c0b3fa20899973f4b40952d19a7f9e9a38e432f 100644 (file)
@@ -146,6 +146,46 @@ ri_install(struct proto_ospf *po, ip_addr prefix, int pxlen, int dest,
   }
 }
 
+#ifdef OSPFv2
+
+static struct ospf_iface *
+find_stub_src(struct ospf_area *oa, ip_addr px, int pxlen)
+{
+  struct ospf_iface *iff;
+  struct ifa *addr;
+
+  WALK_LIST(iff, oa->po->iface_list)
+    if ((iff->type != OSPF_IT_VLINK) &&
+       (iff->oa == oa) &&
+       ipa_equal(iff->addr->px, px) && 
+       (iff->addr->pxlen == pxlen))
+      return iff;
+
+  return NULL;
+}
+
+#else /* OSPFv3 */
+
+static struct ospf_iface *
+find_stub_src(struct ospf_area *oa, ip_addr px, int pxlen)
+{
+  struct ospf_iface *iff;
+  struct ifa *a;
+
+  WALK_LIST(iff, oa->po->iface_list)
+    if ((iff->type != OSPF_IT_VLINK) &&
+       (iff->oa == oa))
+      WALK_LIST(a, iff->iface->addrs)
+       if (ipa_equal(a->prefix, px) && 
+           (a->pxlen == pxlen) &&
+           !(a->flags & IA_SECONDARY))
+         return iff;
+
+  return NULL;
+}
+
+#endif
+
 static void
 add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_hash_entry *en)
 {
@@ -161,7 +201,21 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_
   nf.ifa = en->nhi;
   nf.rid = en->lsa.rt;
 
-  /* FIXME check nf.ifa on stubs */
+  if (en == oa->rt)
+  {
+    /* 
+     * Local stub networks does not have proper iface in en->nhi
+     * (because they all have common top_hash_entry en).
+     * We have to find iface responsible for that stub network.
+     * Some stubnets does not have any iface. Ignore them.
+     */
+
+    nf.ifa = find_stub_src(oa, px, pxlen);
+
+    if (!nf.ifa)
+      return;
+  }
+
   ri_install(oa->po, px, pxlen, ORT_NET, &nf, NULL);
 }
 
@@ -243,45 +297,10 @@ ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct to
        {
 #ifdef OSPFv2
        case LSART_STUB:
-         /*
-          * This violates rfc2328! But it is mostly harmless.
-          */
-         DBG("\n");
-
-         orta nf;
-         nf.type = RTS_OSPF;
-         nf.options = 0;
-         nf.metric1 = act->dist + rtl->metric;
-         nf.metric2 = LSINFINITY;
-         nf.tag = 0;
-         nf.oa = oa;
-         nf.ar = act;
-         nf.nh = act->nh;
-         nf.ifa = act->nhi;
-         nf.rid = act->lsa.rt;
-
-         if (act == oa->rt)
-           {
-             struct ospf_iface *iff;
-
-             WALK_LIST(iff, po->iface_list)    /* Try to find corresponding interface */
-               {
-                 // FIXME this is broken
-                 if (iff->iface && (iff->type != OSPF_IT_VLINK) &&
-                     (rtl->id == (ipa_to_u32(ipa_mkmask(iff->addr->pxlen))
-                                  & ipa_to_u32(iff->addr->prefix))))   /* No VLINK and IP must match */
-                   {
-                     nf.ifa = iff;
-                     break;
-                   }
-               }
-           }
-
-         if (!nf.ifa)
-           continue;
-
-         ri_install(po, ipa_from_u32(rtl->id),
-                    ipa_mklen(ipa_from_u32(rtl->data)), ORT_NET, &nf, NULL);
+         /* This violates RFC 2328! But it is mostly harmless. */
+         add_network(oa, ipa_from_u32(rtl->id),
+                     ipa_mklen(ipa_from_u32(rtl->data)),
+                     act->dist + rtl->metric, act);
          break;
 #endif
 
@@ -292,21 +311,18 @@ ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct to
 #else /* OSPFv3 */
          tmp = ospf_hash_find(po->gr, oa->areaid, rtl->nif, rtl->id, LSA_T_NET);
 #endif
-         if (tmp == NULL)
-           DBG("Not found!\n");
-         else
-           DBG("Found. :-)\n");
          break;
 
        case LSART_VLNK:
        case LSART_PTP:
          tmp = ospf_hash_find_rt(po->gr, oa->areaid, rtl->id);
-         DBG("PTP found.\n");
          break;
+
        default:
          log("Unknown link type in router lsa. (rid = %R)", act->lsa.id);
          break;
        }
+
       if (tmp)
        DBG("Going to add cand, Mydist: %u, Req: %u\n",
            tmp->dist, act->dist + rtl->metric);