]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Many bugfixes in routing table calculation and summary LSA origination.
authorOndrej Filip <feela@network.cz>
Sun, 13 Feb 2005 23:36:31 +0000 (23:36 +0000)
committerOndrej Filip <feela@network.cz>
Sun, 13 Feb 2005 23:36:31 +0000 (23:36 +0000)
proto/ospf/hello.c
proto/ospf/neighbor.c
proto/ospf/ospf.c
proto/ospf/packet.c
proto/ospf/rt.c
proto/ospf/rt.h
proto/ospf/topology.c
proto/ospf/topology.h

index d3145b9fb1a3ad4dbf6774710e0c585cb8c682c8..5711ac5fd0107a4c7afb0039fa38d01a1f134f54 100644 (file)
@@ -24,7 +24,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
   mask = ps->netmask;
   ipa_ntoh(mask);
 
-  if (((ifa->type != OSPF_IT_VLINK) || (ifa->type != OSPF_IT_PTP)) &&
+  if (((ifa->type != OSPF_IT_VLINK) && (ifa->type != OSPF_IT_PTP)) &&
       ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen))
   {
     log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask);
index af6b85349ae2beb6f3e2d146c8e773b55d861eb6..0339ec2dadd657b6021aa7d3b20f9024986a57fa 100644 (file)
@@ -115,6 +115,7 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
     {
       ifa->fadj--;
       schedule_rt_lsa(ifa->oa);
+      if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa);
       schedule_net_lsa(ifa);
     }
 
@@ -507,7 +508,7 @@ find_neigh(struct ospf_iface *ifa, u32 rid)
 }
 
 
-/* Find a closest neighbor which is at leas 2-Way */
+/* Find a closest neighbor which is at least 2-Way */
 struct ospf_neighbor *
 find_neigh_noifa(struct proto_ospf *po, u32 rid)
 {
index e9e45d7648a4890279903c5dbc3836a29e16214d..c753503b52c07bd546aad2028ad71d3442be134a 100644 (file)
@@ -153,13 +153,29 @@ ospf_start(struct proto *p)
   }
 
   /* Add all virtual links as interfaces */
-  if(po->backbone)
   {
     struct ospf_iface_patt *ipatt;
     WALK_LIST(ac, c->area_list)
     {
       WALK_LIST(ipatt, ac->vlink_list)
+      {
+        if(!po->backbone)
+       {
+          oa = mb_allocz(p->pool, sizeof(struct ospf_area));
+          add_tail(&po->area_list, NODE oa);
+          po->areano++;
+          oa->stub = 0;
+          oa->areaid = 0;
+          oa->rt = NULL;
+          oa->po = po;
+         fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib);
+          fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
+          po->backbone = oa;
+          oa->opt.byte = 0;
+          oa->opt.bit.e = 1;
+       }
         ospf_iface_new(po, NULL, ac, ipatt);
+      }
     }
   }
   return PS_UP;
index f6b68fd43114e044f361fc4a9e977954f10d7e84..6a334d0ddcec8175f5aa747908278cf71a78ef4a 100644 (file)
@@ -149,7 +149,8 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
       }
       if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE != size)
       {
-        OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch");
+        OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %s)",
+         ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size);
         return 0;
       }
 
@@ -356,7 +357,7 @@ ospf_tx_hook(sock * sk)
 {
   struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
   struct proto *p = (struct proto *) (ifa->oa->po);
-  DBG("%s: TX_Hook called on interface %s\n", p->name, sk->iface->name);
+  log(L_ERR "%s: TX_Hook called on interface %s\n", p->name, sk->iface->name);
 }
 
 void
@@ -364,7 +365,7 @@ ospf_err_hook(sock * sk, int err UNUSED)
 {
   struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
   struct proto *p = (struct proto *) (ifa->oa->po);
-  DBG("%s: Err_Hook called on interface %s\n", p->name, sk->iface->name);
+  log(L_ERR "%s: Err_Hook called on interface %s\n", p->name, sk->iface->name);
 }
 
 void
index ca1f58d189def50bd3430df6d90510b7c4c2f169..77627f913bb1923cea0aec5e37aea74de4c3a450 100644 (file)
@@ -7,9 +7,10 @@
  */
 
 #include "ospf.h"
+
 static void
 add_cand(list * l, struct top_hash_entry *en,
-        struct top_hash_entry *par, u16 dist, struct ospf_area *oa, int vlink);
+        struct top_hash_entry *par, u16 dist, struct ospf_area *oa);
 static void
 calc_next_hop(struct top_hash_entry *en,
              struct top_hash_entry *par, struct ospf_area *oa);
@@ -145,7 +146,6 @@ ospf_rt_spfa(struct ospf_area *oa)
   struct ospf_iface *iface;
   struct top_hash_entry *act, *tmp;
   node *n;
-  int vlink;
 
 
   if (oa->rt == NULL)
@@ -202,7 +202,6 @@ ospf_rt_spfa(struct ospf_area *oa)
       DBG("  Number of links: %u\n", rt->links);
       for (i = 0; i < rt->links; i++)
       {
-        vlink = 0;
        tmp = NULL;
        rtl = (rr + i);
        DBG("     Working on link: %I (type: %u)  ", rtl->id, rtl->type);
@@ -230,10 +229,10 @@ ospf_rt_spfa(struct ospf_area *oa)
 
            WALK_LIST(iff, po->iface_list)
            {
-               if (rtl->id == (ipa_to_u32(ipa_mkmask(iff->iface->addr->pxlen))
-                & ipa_to_u32(iff->iface->addr->prefix)))
+               if (iff->iface && (rtl->id == (ipa_to_u32(ipa_mkmask(iff->iface->addr->pxlen))
+                & ipa_to_u32(iff->iface->addr->prefix))))
               {
-                nf.ifa = iff->iface;
+                nf.ifa = iff;
                 break;
               }
             }
@@ -256,7 +255,6 @@ ospf_rt_spfa(struct ospf_area *oa)
          break;
 
        case LSART_VLNK:
-          vlink = 1;
        case LSART_PTP:
          tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
          DBG("PTP found.\n");
@@ -268,7 +266,7 @@ ospf_rt_spfa(struct ospf_area *oa)
        if (tmp)
          DBG("Going to add cand, Mydist: %u, Req: %u\n",
              tmp->dist, act->dist + rtl->metric);
-       add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa, vlink);
+       add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa);
       }
       break;
     case LSA_T_NET:
@@ -294,7 +292,7 @@ ospf_rt_spfa(struct ospf_area *oa)
          DBG("Found :-)\n");
        else
          DBG("Not found!\n");
-       add_cand(&oa->cand, tmp, act, act->dist, oa, 0);
+       add_cand(&oa->cand, tmp, act, act->dist, oa);
       }
       break;
     }
@@ -308,11 +306,11 @@ ospf_rt_spfa(struct ospf_area *oa)
       if ((tmp = ospf_hash_find(po->gr, oa->areaid, iface->vid, iface->vid, LSA_T_RT)) &&
         (!ipa_equal(tmp->lb, IPA_NONE)))
       {
-        if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi) || (!ipa_equal(iface->vip, tmp->lb)))
+        if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi->iface) || (!ipa_equal(iface->vip, tmp->lb)))
         {
           OSPF_TRACE(D_EVENTS, "Vlink peer %I found", tmp->lsa.id);
           ospf_iface_sm(iface, ISM_DOWN);
-          iface->iface = tmp->nhi;
+          iface->iface = tmp->nhi->iface;
           iface->vip = tmp->lb;
           ospf_iface_sm(iface, ISM_UP);
         }
@@ -499,11 +497,21 @@ ospf_rt_sum(struct ospf_area *oa)
 
     if (en->lsa.type == LSA_T_SUM_NET)
     {
+      struct ospf_area *oaa;
+      int skip = 0;
       mlen = ipa_mklen(*mask);
       ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
       /* Page 169 (3) */
-      if ((anet = fib_route(&oa->net_fib, ip, mlen)) && anet->active)
-        continue;
+      WALK_LIST(oaa, po->area_list)
+      {
+        if ((anet = fib_find(&oaa->net_fib, &ip, mlen)) && anet->active)
+       {
+         skip = 1;
+         break;
+       }
+      }
+      if (skip) continue;
+
       type = ORT_NET;
     }
     else
@@ -573,9 +581,6 @@ ospf_rt_spf(struct proto_ospf *po)
     }
     FIB_WALK_END;
 
-    fib_free(&oa->rtr);
-    fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
-
     FIB_WALK(&oa->net_fib, nftmp)
     {
       anet = (struct area_net *) nftmp;
@@ -585,13 +590,13 @@ ospf_rt_spf(struct proto_ospf *po)
     ospf_rt_spfa(oa);
   }
 
-  if (po->areano == 1)
+  if ((po->areano == 1) || (!po->backbone))
   {
     ospf_rt_sum(HEAD(po->area_list));
   }
   else
   {
-    if (po->backbone) ospf_rt_sum(po->backbone);       /* And if backbone is not connected? */
+    ospf_rt_sum(po->backbone);
   }
 
   WALK_LIST(oa, po->area_list)
@@ -630,7 +635,7 @@ ospf_ext_spf(struct proto_ospf *po)
   struct ospf_lsa_ext_tos *lt;
   int mlen;
   ip_addr ip, nh, rtid;
-  struct iface *nhi = NULL;
+  struct ospf_iface *nhi = NULL;
   int met1, met2;
   neighbor *nn;
   struct ospf_lsa_rt *rt;
@@ -731,7 +736,7 @@ ospf_ext_spf(struct proto_ospf *po)
       if ((nn = neigh_find(p, &lt->fwaddr, 0)) != NULL)
       {
        nh = lt->fwaddr;
-       nhi = nn->iface;
+       nhi = ospf_iface_find(po, nn->iface);
       }
       else
       {
@@ -760,7 +765,7 @@ ospf_ext_spf(struct proto_ospf *po)
 /* Add LSA into list of candidates in Dijkstra's algorithm */
 static void
 add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
-        u16 dist, struct ospf_area *oa, int vlink)
+        u16 dist, struct ospf_area *oa)
 {
   node *prev, *n;
   int added = 0;
@@ -791,7 +796,6 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
   en->nh = IPA_NONE;
 
   calc_next_hop(en, par, oa);
-  //if (vlink) en->nh = IPA_NONE;
 
   if (!en->nhi)
     return;                    /* We cannot find next hop, ignore it */
@@ -861,7 +865,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
            if (ifa->iface && (ipa_compare
                (ifa->iface->addr->ip, ipa_from_u32(en->lsa.id)) == 0))
          {
-           en->nhi = ifa->iface;
+           en->nhi = ifa;
            return;
          }
          log(L_ERR "I didn't find interface for my self originated LSA!\n");
@@ -873,7 +877,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
          ip_addr ip = ipa_from_u32(en->lsa.id);
          nn = neigh_find(p, &ip, 0);
          if (nn)
-           en->nhi = nn->iface;
+           en->nhi = ospf_iface_find(po, nn->iface);
          return;
        }
       }
@@ -881,7 +885,8 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
       {
        if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
          return;
-       en->nhi = neigh->ifa->iface;
+       en->nhi = neigh->ifa;
+       if (neigh->ifa->type == OSPF_IT_VLINK) 
        en->nh = neigh->ip;     /* Yes, neighbor is it's
                                 * own next hop */
        return;
@@ -895,7 +900,7 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
        bug("Did not find next hop interface for INSPF lsa!");
       if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
        return;
-      en->nhi = neigh->ifa->iface;
+      en->nhi = neigh->ifa;
       en->nh = neigh->ip;      /* Yes, neighbor is it's own
                                 * next hop */
       return;
@@ -932,6 +937,7 @@ again1:
   FIB_ITERATE_START(fib, &fit, nftmp)
   {
     nf = (ort *) nftmp;
+    check_sum_lsa(po, nf, ORT_NET);
     if (memcmp(&nf->n, &nf->o, sizeof(orta)))
     {                          /* Some difference */
       net *ne;
@@ -947,7 +953,8 @@ again1:
       a0.dest = RTD_ROUTER;
       a0.flags = 0;
       a0.aflags = 0;
-      a0.iface = nf->n.ifa;
+      a0.iface = NULL;
+      if (nf->n.ifa) a0.iface = nf->n.ifa->iface;
       a0.gw = nf->n.nh;
 
       if (ipa_equal(nf->n.nh, IPA_NONE)) a0.dest = RTD_DEVICE;
@@ -974,7 +981,6 @@ again1:
         if (!found) nf->n.metric1 = LSINFINITY; /* Delete it */
       }
       ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
-      check_sum_lsa(po, nf, ORT_NET);
       if (nf->n.metric1 < LSINFINITY)
       {
         e = rte_get_temp(&a0);
@@ -1024,13 +1030,18 @@ again2:
     {
       flush = 1;
       anet = (struct area_net *) nftmp;
-      if((!anet->hidden) && anet->active && (!oa->trcap))
+      if((!anet->hidden) && anet->active)
         flush = 0;
           
       WALK_LIST(oaa, po->area_list)
       {
+        int fl = flush;
+
         if (oaa == oa) continue;
-        if(flush) flush_sum_lsa(oaa, &anet->fn, ORT_NET);
+
+       if ((oa == po->backbone) && oaa->trcap) fl = 1;
+
+        if(fl) flush_sum_lsa(oaa, &anet->fn, ORT_NET);
         else originate_sum_lsa(oaa, &anet->fn, ORT_NET, 1);
       }
     }
index f7b33303ed57512269e1c8573df95f7c40f84121..ea2f28f5913f28c90d0c67e7176496afbc17cef4 100644 (file)
@@ -24,7 +24,7 @@ typedef struct orta
   int metric1;
   int metric2;
   ip_addr nh;                  /* Next hop */
-  struct iface *ifa;           /* Outgoing interface */
+  struct ospf_iface *ifa;      /* Outgoing interface */
   struct top_hash_entry *ar;   /* Advertising router */
   u32 tag;
 }
index 5ba41e83d0d0fcc13ec17f33f0b57269d3b0b9bd..43dbc7d68e5753fd115978accc5a557c7dde7eba 100644 (file)
@@ -24,6 +24,7 @@ static void *
 originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
 {
   struct proto_ospf *po = oa->po;
+  struct proto *p = &po->proto;
   struct ospf_iface *ifa;
   int j = 0, k = 0;
   u16 i = 0;
@@ -51,8 +52,12 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
 
   WALK_LIST(ifa, po->iface_list)
   {
-    if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (ifa->state > OSPF_IS_DOWN))
-      rt->veb.bit.v = 1;
+    if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (!EMPTY_LIST(ifa->neigh_list)))
+    {
+      neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
+      if ((neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
+        rt->veb.bit.v = 1;
+    }
 
     if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
       continue;
@@ -413,7 +418,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
     if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
     {
       sum = en->lsa_body;
-      if (fn->pxlen == ipa_mklen(sum->netmask))
+      if ((type == ORT_ROUTER) || (fn->pxlen == ipa_mklen(sum->netmask)))
       {
         en->lsa.age = LSA_MAXAGE;
         en->lsa.sn = LSA_MAXSEQNO;
@@ -521,27 +526,36 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
     flush = 0;
     if ((nf->n.metric1 >= LSINFINITY) || (nf->n.type > RTS_OSPF_IA))
       flush = 1;
-    if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR)))
+    if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ASBR)))
       flush = 1;
     if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid))
       flush = 1;
-    /* FIXME: Test next hop - is it in actual area? */
+
+    if (nf->n.ifa) {
+      if (nf->n.ifa->oa->areaid == oa->areaid)
+        flush = 1;
+      }
+    else flush = 1;
+
     if ((dest == ORT_ROUTER) && oa->stub)
       flush = 1;
     /* FIXME stub for networks? */
 
     mlen = nf->fn.pxlen;
     ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen));
-    if ((!flush) && (!nf->n.oa->trcap) &&
-        fib_route(&nf->n.oa->net_fib, ip, mlen))       /* The route fits into area networks */
-      flush = 1;
 
-    if(flush)          /* FIXME Go on... */
+    if ((oa == po->backbone) && (nf->n.type == RTS_OSPF_IA)) flush = 1;        /* Only intra-area can go to the backbone */
+
+    if ((!flush) && (dest == ORT_NET) && fib_route(&nf->n.oa->net_fib, ip, mlen))      /* The route fits into area networks */
     {
-      flush_sum_lsa(oa, &nf->fn, dest);
-      continue;
+      flush = 1;
+      if ((nf->n.oa == po->backbone) && (oa->trcap)) flush = 0;
     }
-    originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1);
+
+    if(flush)
+      flush_sum_lsa(oa, &nf->fn, dest);
+    else
+      originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1);
   }
 }
 
index bccff056154ace833d3fcc93708a7497497aeb81..21e545e7df0c77d96d6e9d2941e37ad8fbc66da1 100644 (file)
@@ -23,7 +23,7 @@ struct top_hash_entry
   bird_clock_t inst_t;         /* Time of installation into DB */
   ip_addr nh;                  /* Next hop */
   ip_addr lb;                  /* Link back */
-  struct iface *nhi;
+  struct ospf_iface *nhi;      /* Next hop interface */
   u32 dist;                    /* Distance from the root */
   u16 ini_age;
   u8 color;