]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Huge OSPF database redesign. Since now, all LSAs of all areas
authorOndrej Filip <feela@network.cz>
Thu, 15 Jul 2004 16:37:52 +0000 (16:37 +0000)
committerOndrej Filip <feela@network.cz>
Thu, 15 Jul 2004 16:37:52 +0000 (16:37 +0000)
are in single database. This avoids duplication of external LSAs and
fixes bug in external LSA distribution.

17 files changed:
TODO
proto/ospf/config.Y
proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsack.c
proto/ospf/lsalib.c
proto/ospf/lsalib.h
proto/ospf/lsreq.c
proto/ospf/lsupd.c
proto/ospf/neighbor.c
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/rt.c
proto/ospf/topology.c
proto/ospf/topology.h

diff --git a/TODO b/TODO
index b6693366eec5bd1d3fa42b8692844dd0d3e7b1d6..f0c60b6b2e7c523c21e8a6d3a66a6a37bc39e7dd 100644 (file)
--- a/TODO
+++ b/TODO
@@ -49,5 +49,4 @@ OSPF
        - automatic generation of external route tags (RFC1403)
        - RFC1587 NSSA areas
        - RFC2370 opaque LSA's
-        - AS external LSAs are in topology database of every OSPF Area
         - Limit export rate of external LSAs (like Gated does)
index bd3a2e5435161b38e5f7c60ed2b35dbb8e04c5f3..4a625498987e9ec2d65b779f055a81c03954a784 100644 (file)
@@ -104,7 +104,6 @@ ospf_vlink_item:
 
 ospf_vlink_start: VIRTUAL LINK idval
  {
-  log("Vlink start");
   if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone");
   this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
   add_tail(&this_area->vlink_list, NODE this_ipatt);
@@ -200,7 +199,6 @@ ipa_ne: IPA ELIGIBLE ';'
  
 ospf_iface_start:
  {
-  log("Iface start");
   this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
   add_tail(&this_area->patt_list, NODE this_ipatt);
   OSPF_PATT->cost = COST_D;
index 6e84eddfafe53a59c3f3629263d06420d44a4e27..7f181fb63fdbfd837fe2c688a8de5b3a2a646855 100644 (file)
@@ -25,11 +25,11 @@ ospf_dbdes_send(struct ospf_neighbor *n)
   struct ospf_packet *op;
   struct ospf_iface *ifa = n->ifa;
   struct ospf_area *oa = ifa->oa;
-  u16 length;
-  struct proto *p = (struct proto *) (ifa->proto);
-  u16 i, j;
+  struct proto_ospf *po = oa->po;
+  struct proto *p = &po->proto;
+  u16 length, i, j;
 
-  if ((oa->rt == NULL) || (EMPTY_LIST(oa->lsal)))
+  if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal)))
     originate_rt_lsa(oa);
 
   switch (n->state)
@@ -40,7 +40,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
     op = (struct ospf_packet *) pkt;
     ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
     pkt->iface_mtu = htons(ifa->iface->mtu);
-    pkt->options = ifa->oa->opt.byte;
+    pkt->options = oa->opt.byte;
     pkt->imms = n->myimms;
     pkt->ddseq = htonl(n->dds);
     length = sizeof(struct ospf_dbdes_packet);
@@ -64,7 +64,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
 
       ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
       pkt->iface_mtu = htons(ifa->iface->mtu);
-      pkt->options = ifa->oa->opt.byte;
+      pkt->options = oa->opt.byte;
       pkt->ddseq = htonl(n->dds);
 
       j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header);     /* Number of possible lsaheaders to send */
@@ -77,10 +77,17 @@ ospf_dbdes_send(struct ospf_neighbor *n)
        DBG("Number of LSA: %d\n", j);
        for (; i > 0; i--)
        {
-         struct top_hash_entry *en;
-         en = (struct top_hash_entry *) sn;
+         struct top_hash_entry *en= (struct top_hash_entry *) sn;
+          int send = 1;
 
-          if ((n->ifa->type != OSPF_IT_VLINK) || (en->lsa.type != LSA_T_EXT))
+          /* Don't send ext LSA into stub areas */
+          if (oa->stub && (en->lsa.type == LSA_T_EXT)) send = 0;
+          /* Don't send ext LSAs through VLINK  */
+          if ((ifa->type == OSPF_IT_VLINK) && (en->lsa.type == LSA_T_EXT)) send = 0;;
+          /* Don't send LSA of other areas */
+          if ((en->lsa.type != LSA_T_EXT) && (en->oa != oa)) send = 0;
+
+          if (send)
           {
            htonlsah(&(en->lsa), lsa);
            DBG("Working on: %d\n", i);
@@ -91,7 +98,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
           }
           else i++;    /* No lsa added */
 
-         if (sn == STAIL(n->ifa->oa->lsal))
+         if (sn == STAIL(po->lsal))
           {
             i--;
            break;
@@ -100,7 +107,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
          sn = sn->next;
        }
 
-       if (sn == STAIL(n->ifa->oa->lsal))
+       if (sn == STAIL(po->lsal))
        {
          DBG("Number of LSA NOT sent: %d\n", i);
          DBG("M bit unset.\n");
@@ -163,7 +170,8 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
 {
   struct ospf_lsa_header *plsa, lsa;
   struct top_hash_entry *he, *sn;
-  struct top_graph *gr = n->ifa->oa->gr;
+  struct ospf_area *oa = n->ifa->oa;
+  struct top_graph *gr = oa->po->gr;
   struct ospf_packet *op;
   int i, j;
 
@@ -177,13 +185,13 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
   for (i = 0; i < j; i++)
   {
     ntohlsah(plsa + i, &lsa);
-    if (((he = ospf_hash_find(gr, lsa.id, lsa.rt, lsa.type)) == NULL) ||
+    if (((he = ospf_hash_find(gr, oa->areaid, lsa.id, lsa.rt, lsa.type)) == NULL) ||
        (lsa_comp(&lsa, &(he->lsa)) == 1))
     {
       /* Is this condition necessary? */
-      if (ospf_hash_find(n->lsrqh, lsa.id, lsa.rt, lsa.type) == NULL)
+      if (ospf_hash_find(n->lsrqh, oa->areaid, lsa.id, lsa.rt, lsa.type) == NULL)
       {
-       sn = ospf_hash_get(n->lsrqh, lsa.id, lsa.rt, lsa.type);
+       sn = ospf_hash_get(n->lsrqh, oa, lsa.id, lsa.rt, lsa.type);
        ntohlsah(plsa + i, &(sn->lsa));
        s_add_tail(&(n->lsrql), SNODE sn);
       }
@@ -195,7 +203,7 @@ void
 ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
                   struct ospf_iface *ifa, struct ospf_neighbor *n)
 {
-  struct proto *p = (struct proto *) ifa->proto;
+  struct proto *p = &ifa->oa->po->proto;
   u32 myrid = p->cf->global->router_id;
   unsigned int size = ntohs(ps->ospf_packet.length);
 
index 350bad7c1d0ea503e3467e0143019e3c75514260..58d1423a8897132b259a586dc21b859e22c260fe 100644 (file)
@@ -16,7 +16,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
   ip_addr olddr, oldbdr;
   ip_addr mask;
   char *beg = "Bad OSPF hello packet from ", *rec = " received: ";
-  struct proto *p = (struct proto *) ifa->proto;
+  struct proto *p = (struct proto *) ifa->oa->po;
   unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers;
 
   OSPF_TRACE(D_PACKETS, "Received hello from %I via %s%s", faddr,
@@ -172,6 +172,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
   u32 *pp;
   int i, send;
   struct nbma_node *nb;
+
   if (timer == NULL)
     ifa = dirn->ifa;
   else
@@ -183,7 +184,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
   if (ifa->stub)
     return;                    /* Don't send any packet on stub iface */
 
-  p = (struct proto *) (ifa->proto);
+  p = (struct proto *) (ifa->oa->po);
   DBG("%s: Hello/Poll timer fired on interface %s.\n",
       p->name, ifa->iface->name);
   /* Now we should send a hello packet */
index 5a10cde7d28eb6795e00fd9accd73b008e8ee09a..68b6377d9c6b44dbc45b6495b0a2dd1e85cfacba 100644 (file)
@@ -35,7 +35,7 @@ static void
 wait_timer_hook(timer * timer)
 {
   struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
-  struct proto *p = (struct proto *) (ifa->proto);
+  struct proto *p = &ifa->oa->po->proto;
 
   OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name);
   ospf_iface_sm(ifa, ISM_WAITF);
@@ -45,9 +45,7 @@ static sock *
 ospf_open_ip_socket(struct ospf_iface *ifa)
 {
   sock *ipsk;
-  struct proto *p;
-
-  p = (struct proto *) (ifa->proto);
+  struct proto *p = &ifa->oa->po->proto;
 
   ipsk = sk_new(p->pool);
   ipsk->type = SK_IP;
@@ -86,7 +84,7 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
 void
 ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
 {
-  struct proto_ospf *po = ifa->proto;
+  struct proto_ospf *po = ifa->oa->po;
   struct proto *p = &po->proto;
   u8 oldstate = ifa->state;
 
@@ -149,8 +147,8 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
          {
            ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa);
          }
-         if (can_flush_lsa(ifa->oa))
-           flush_lsa(ifa->nlsa, ifa->oa);
+         if (can_flush_lsa(po))
+           flush_lsa(ifa->nlsa, po);
          ifa->nlsa = NULL;
        }
       }
@@ -162,8 +160,8 @@ static void
 ospf_iface_down(struct ospf_iface *ifa)
 {
   struct ospf_neighbor *n, *nx;
-  struct proto *p = &ifa->proto->proto;
-  struct proto_ospf *po = ifa->proto;
+  struct proto_ospf *po = ifa->oa->po;
+  struct proto *p = &po->proto;
   struct ospf_iface *iff;
 
   /* First of all kill all the related vlinks */
@@ -287,9 +285,7 @@ static sock *
 ospf_open_mc_socket(struct ospf_iface *ifa)
 {
   sock *mcsk;
-  struct proto *p;
-
-  p = (struct proto *) (ifa->proto);
+  struct proto *p = &ifa->oa->po->proto;
 
   mcsk = sk_new(p->pool);
   mcsk->type = SK_IP_MC;
@@ -342,9 +338,9 @@ static void
 ospf_iface_add(struct object_lock *lock)
 {
   struct ospf_iface *ifa = lock->data;
-  struct proto_ospf *po = ifa->proto;
-  struct iface *iface = lock->iface;
+  struct proto_ospf *po = ifa->oa->po;
   struct proto *p = &po->proto;
+  struct iface *iface = lock->iface;
 
   ifa->lock = lock;
 
@@ -387,7 +383,6 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface,
   struct ospf_area *oa;
 
   ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
-  ifa->proto = po;
   ifa->iface = iface;
 
   ifa->cost = ip->cost;
index 14832b8205c7487f7459a6502b2ab62b6531db93..bb1afa0abed8135d2698f21b8c41757aefbb0021 100644 (file)
@@ -37,7 +37,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
   struct ospf_lsa_header *h;
   struct lsah_n *no;
   struct ospf_iface *ifa = n->ifa;
-  struct proto *p = &n->ifa->proto->proto;
+  struct proto *p = &n->ifa->oa->po->proto;
 
   if (EMPTY_LIST(n->ackl[queue]))
     return;
@@ -122,7 +122,7 @@ ospf_lsack_receive(struct ospf_lsack_packet *ps,
   struct ospf_lsa_header lsa, *plsa;
   u16 nolsa;
   struct top_hash_entry *en;
-  struct proto *p = (struct proto *) ifa->proto;
+  struct proto *p = &ifa->oa->po->proto;
   unsigned int size = ntohs(ps->ospf_packet.length), i;
 
   OSPF_TRACE(D_PACKETS, "Received LS ack from %I", n->ip);
@@ -146,7 +146,7 @@ ospf_lsack_receive(struct ospf_lsack_packet *ps,
   for (i = 0; i < nolsa; i++)
   {
     ntohlsah(plsa + i, &lsa);
-    if ((en = ospf_hash_find_header(n->lsrth, &lsa)) == NULL)
+    if ((en = ospf_hash_find_header(n->lsrth, n->ifa->oa->areaid, &lsa)) == NULL)
       continue;                        /* pg 155 */
 
     if (lsa_comp(&lsa, &en->lsa) != CMP_SAME)  /* pg 156 */
index b244c3f2013b8433b1c8513c0ad30eefa23c3968..af3f743ae9c5bb8ba3882a85c978dc957273c71f 100644 (file)
@@ -9,9 +9,10 @@
 #include "ospf.h"
 
 void
-flush_lsa(struct top_hash_entry *en, struct ospf_area *oa)
+flush_lsa(struct top_hash_entry *en, struct proto_ospf *po)
 {
-  struct proto *p = &oa->po->proto;
+  struct proto *p = &po->proto;
+
   OSPF_TRACE(D_EVENTS,
             "Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u, SN: 0x%x",
             en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
@@ -19,14 +20,14 @@ flush_lsa(struct top_hash_entry *en, struct ospf_area *oa)
   if (en->lsa_body != NULL)
     mb_free(en->lsa_body);
   en->lsa_body = NULL;
-  ospf_hash_delete(oa->gr, en);
+  ospf_hash_delete(po->gr, en);
 }
 
 /**
  * ospf_age
- * @oa: ospf area
+ * @po: ospf protocol
  *
- * This function is periodicaly invoked from area_disp(). It computes the new
+ * This function is periodicaly invoked from ospf_disp(). It computes the new
  * age of all LSAs and old (@age is higher than %LSA_MAXAGE) LSAs are flushed
  * whenever possible. If an LSA originated by the router itself is older
  * than %LSREFRESHTIME a new instance is originated.
@@ -38,19 +39,17 @@ flush_lsa(struct top_hash_entry *en, struct ospf_area *oa)
  * table calculation results.
  */
 void
-ospf_age(struct ospf_area *oa)
+ospf_age(struct proto_ospf *po)
 {
-  struct proto *p = &oa->po->proto;
-  struct proto_ospf *po = (struct proto_ospf *) p;
+  struct proto *p = &po->proto;
   struct top_hash_entry *en, *nxt;
-  int flush = can_flush_lsa(oa);
-  int cleanup = (oa->rt && (oa->rt->dist != LSINFINITY));
+  int flush = can_flush_lsa(po);
 
-  if (cleanup) OSPF_TRACE(D_EVENTS, "Running ospf_age cleanup");
+  if (po->cleanup) OSPF_TRACE(D_EVENTS, "Running ospf_age cleanup");
 
-  WALK_SLIST_DELSAFE(en, nxt, oa->lsal)
+  WALK_SLIST_DELSAFE(en, nxt, po->lsal)
   {
-    if (cleanup)
+    if (po->cleanup)
     {
       en->color = OUTSPF;
       en->dist = LSINFINITY;
@@ -63,7 +62,7 @@ ospf_age(struct ospf_area *oa)
     if (en->lsa.age == LSA_MAXAGE)
     {
       if (flush)
-       flush_lsa(en, oa);
+       flush_lsa(en, po);
       continue;
     }
     if ((en->lsa.rt == p->cf->global->router_id) &&(en->lsa.age >=
@@ -76,20 +75,21 @@ ospf_age(struct ospf_area *oa)
       en->inst_t = now;
       en->ini_age = 0;
       lsasum_calculate(&en->lsa, en->lsa_body);
-      ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
+      ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, en->oa, 1);
       continue;
     }
     if ((en->lsa.age = (en->ini_age + (now - en->inst_t))) >= LSA_MAXAGE)
     {
       if (flush)
       {
-       flush_lsa(en, oa);
+       flush_lsa(en, po);
        schedule_rtcalc(po);
       }
       else
        en->lsa.age = LSA_MAXAGE;
     }
   }
+  po->cleanup = 0;
 }
 
 void
@@ -446,9 +446,9 @@ lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa)
   struct top_hash_entry *en;
   struct proto_ospf *po = oa->po;
 
-  if ((en = ospf_hash_find_header(oa->gr, lsa)) == NULL)
+  if ((en = ospf_hash_find_header(po->gr, oa->areaid, lsa)) == NULL)
   {
-    en = ospf_hash_get_header(oa->gr, lsa);
+    en = ospf_hash_get_header(po->gr, oa, lsa);
     change = 1;
   }
   else
@@ -474,7 +474,7 @@ lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa)
   DBG("Inst lsa: Id: %I, Rt: %I, Type: %u, Age: %u, Sum: %u, Sn: 0x%x\n",
       lsa->id, lsa->rt, lsa->type, lsa->age, lsa->checksum, lsa->sn);
 
-  s_add_tail(&oa->lsal, SNODE en);
+  s_add_tail(&po->lsal, SNODE en);
   en->inst_t = now;
   if (en->lsa_body != NULL)
     mb_free(en->lsa_body);
index 43f95130a35b05c62382eb0058155b4bc5f9c415..c7f16d511bbbe8c34115c8d34b703767cc9f5fc0 100644 (file)
@@ -22,7 +22,7 @@ u16 lsasum_check(struct ospf_lsa_header *h, void *body);
 int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
 struct top_hash_entry *lsa_install_new(struct ospf_lsa_header *lsa,
                                       void *body, struct ospf_area *oa);
-void ospf_age(struct ospf_area *oa);
-void flush_lsa(struct top_hash_entry *en, struct ospf_area *oa);
+void ospf_age(struct proto_ospf *po);
+void flush_lsa(struct top_hash_entry *en, struct proto_ospf *po);
 
 #endif /* _BIRD_OSPF_LSALIB_H_ */
index 64f108271613834f03235470fc79106b5f9ef3e1..3c8b7220338f76878c8c8ffc5d9f563910da209e 100644 (file)
@@ -18,7 +18,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
   struct ospf_lsreq_header *lsh;
   u16 length;
   int i, j;
-  struct proto *p = &n->ifa->proto->proto;
+  struct proto *p = &n->ifa->oa->po->proto;
 
   pk = (struct ospf_lsreq_packet *) n->ifa->ip_sk->tbuf;
   op = (struct ospf_packet *) n->ifa->ip_sk->tbuf;
@@ -73,7 +73,9 @@ ospf_lsreq_receive(struct ospf_lsreq_packet *ps,
   slab *upslab;
   unsigned int size = ntohs(ps->ospf_packet.length);
   int i, lsano;
-  struct proto *p = (struct proto *) ifa->proto;
+  struct ospf_area *oa = ifa->oa;
+  struct proto_ospf *po = oa->po;
+  struct proto *p = &po->proto;
 
   if (n->state < NEIGHBOR_EXCHANGE)
     return;
@@ -96,7 +98,7 @@ ospf_lsreq_receive(struct ospf_lsreq_packet *ps,
     llsh->lsh.rt = ntohl(lsh->rt);
     llsh->lsh.type = lsh->type;
     add_tail(&uplist, NODE llsh);
-    if (ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt,
+    if (ospf_hash_find(po->gr, oa->areaid, llsh->lsh.id, llsh->lsh.rt,
                       llsh->lsh.type) == NULL)
     {
       log(L_WARN
index 51b38afd791e8782cc101774ed2e573cee696fc6..c619442472049c9394e24ce0828fd559bcc3760d 100644 (file)
@@ -13,7 +13,6 @@
  * @n: neighbor than sent this lsa (or NULL if generated)
  * @hn: LSA header followed by lsa body in network endianity (may be NULL) 
  * @hh: LSA header in host endianity (must be filled)
- * @po: actual instance of OSPF protocol
  * @iff: interface which received this LSA (or NULL if LSA is generated)
  * @oa: ospf_area which is the LSA generated for
  * @rtl: add this LSA into retransmission list
@@ -48,16 +47,8 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
     }
     else
     {
-      if (oa->areaid == BACKBONE)
-      {
-       if ((ifa->type != OSPF_IT_VLINK) && (ifa->oa != oa))
-         continue;
-      }
-      else
-      {
-       if (ifa->oa != oa)
-         continue;
-      }
+      if (ifa->oa != oa)
+        continue;
     }
     ret = 0;
     WALK_LIST(NODE nn, ifa->neigh_list)
@@ -66,7 +57,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
        continue;
       if (nn->state < NEIGHBOR_FULL)
       {
-       if ((en = ospf_hash_find_header(nn->lsrqh, hh)) != NULL)
+       if ((en = ospf_hash_find_header(nn->lsrqh, nn->ifa->oa->areaid, hh)) != NULL)
        {
          switch (lsa_comp(hh, &en->lsa))
          {
@@ -105,9 +96,9 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
 
       if (rtl)
       {
-       if ((en = ospf_hash_find_header(nn->lsrth, hh)) == NULL)
+       if ((en = ospf_hash_find_header(nn->lsrth, nn->ifa->oa->areaid, hh)) == NULL)
        {
-         en = ospf_hash_get_header(nn->lsrth, hh);
+         en = ospf_hash_get_header(nn->lsrth, nn->ifa->oa, hh);
        }
        else
        {
@@ -120,7 +111,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
       }
       else
       {
-       if ((en = ospf_hash_find_header(nn->lsrth, hh)) != NULL)
+       if ((en = ospf_hash_find_header(nn->lsrth, nn->ifa->oa->areaid, hh)) != NULL)
        {
          s_rem_node(SNODE en);
          if (en->lsa_body != NULL)
@@ -177,7 +168,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
 
        htonlsah(hh, lh);
        help = (u8 *) (lh + 1);
-       en = ospf_hash_find_header(oa->gr, hh);
+       en = ospf_hash_find_header(po->gr, oa->areaid, hh);
        htonlsab(en->lsa_body, help, hh->type, hh->length
                 - sizeof(struct ospf_lsa_header));
       }
@@ -229,7 +220,9 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
   struct top_hash_entry *en;
   struct ospf_lsupd_packet *pk;
   struct ospf_packet *op;
-  struct proto *p = &n->ifa->oa->po->proto;
+  struct ospf_area *oa = n->ifa->oa;
+  struct proto_ospf *po = oa->po;
+  struct proto *p = &po->proto;
   void *pktpos;
 
   if (EMPTY_LIST(*l))
@@ -247,7 +240,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
 
   WALK_LIST(llsh, *l)
   {
-    if ((en = ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt,
+    if ((en = ospf_hash_find(po->gr, oa->areaid, llsh->lsh.id, llsh->lsh.rt,
                             llsh->lsh.type)) == NULL)
       continue;                        /* Probably flushed LSA */
     /* FIXME This is a bug! I cannot flush LSA that is in lsrt */
@@ -294,8 +287,8 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
   struct ospf_neighbor *ntmp;
   struct ospf_lsa_header *lsa;
   struct ospf_area *oa;
-  struct proto_ospf *po = ifa->proto;
-  struct proto *p = (struct proto *) po;
+  struct proto_ospf *po = ifa->oa->po;
+  struct proto *p = &po->proto;
   unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length);
 
   if (n->state < NEIGHBOR_EXCHANGE)
@@ -372,7 +365,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
        lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age,
        lsatmp.checksum);
 
-    lsadb = ospf_hash_find_header(oa->gr, &lsatmp);
+    lsadb = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp);
 
 #ifdef LOCAL_DEBUG
     if (lsadb)
@@ -382,7 +375,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
 #endif
 
     /* pg 143 (4) */
-    if ((lsatmp.age == LSA_MAXAGE) && (lsadb == NULL) && can_flush_lsa(oa))
+    if ((lsatmp.age == LSA_MAXAGE) && (lsadb == NULL) && can_flush_lsa(po))
     {
       ospf_lsack_enqueue(n, lsa, ACKL_DIRECT);
       continue;
@@ -433,7 +426,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
        lsasum_check(lsa, (lsa + 1));   /* It also calculates chsum! */
        lsatmp.checksum = ntohs(lsa->checksum);
        ospf_lsupd_flood(NULL, lsa, &lsatmp, NULL, oa, 0);
-       if (en = ospf_hash_find_header(oa->gr, &lsatmp))
+       if (en = ospf_hash_find_header(po->gr, oa->areaid, &lsatmp))
        {
          ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
        }
@@ -468,7 +461,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
       {
        struct top_hash_entry *en;
        if (ntmp->state > NEIGHBOR_EXSTART)
-         if ((en = ospf_hash_find_header(ntmp->lsrth, &lsadb->lsa)) != NULL)
+         if ((en = ospf_hash_find_header(ntmp->lsrth, ntmp->ifa->oa->areaid, &lsadb->lsa)) != NULL)
          {
            s_rem_node(SNODE en);
            if (en->lsa_body != NULL)
@@ -479,9 +472,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
       }
 
       if ((lsatmp.age == LSA_MAXAGE) && (lsatmp.sn == LSA_MAXSEQNO)
-         && lsadb && can_flush_lsa(oa))
+         && lsadb && can_flush_lsa(po))
       {
-       flush_lsa(lsadb, oa);
+       flush_lsa(lsadb, po);
        schedule_rtcalc(po);
        continue;
       }                                /* FIXME lsack? */
@@ -504,7 +497,7 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps,
     {
       struct top_hash_entry *en;
       DBG("PG145(7) Got the same LSA\n");
-      if ((en = ospf_hash_find_header(n->lsrth, &lsadb->lsa)) != NULL)
+      if ((en = ospf_hash_find_header(n->lsrth, n->ifa->oa->areaid, &lsadb->lsa)) != NULL)
       {
        /* pg145 (7a) */
        s_rem_node(SNODE en);
index 869db2b74cd889cc322954137c9162ce989f9f0d..af6b85349ae2beb6f3e2d146c8e773b55d861eb6 100644 (file)
@@ -33,7 +33,7 @@ void ackd_timer_hook(timer * t);
 struct ospf_neighbor *
 ospf_neighbor_new(struct ospf_iface *ifa)
 {
-  struct proto *p = (struct proto *) (ifa->proto);
+  struct proto *p = (struct proto *) (ifa->oa->po);
   struct pool *pool = rp_new(p->pool, "OSPF Neighbor");
   struct ospf_neighbor *n = mb_allocz(pool, sizeof(struct ospf_neighbor));
 
@@ -231,7 +231,7 @@ can_do_adj(struct ospf_neighbor *n)
   int i;
 
   ifa = n->ifa;
-  p = (struct proto *) (ifa->proto);
+  p = (struct proto *) (ifa->oa->po);
   i = 0;
 
   switch (ifa->type)
@@ -289,8 +289,8 @@ can_do_adj(struct ospf_neighbor *n)
 void
 ospf_neigh_sm(struct ospf_neighbor *n, int event)
 {
-  struct proto_ospf *po = n->ifa->proto;
-  struct proto *p = (struct proto *) po;
+  struct proto_ospf *po = n->ifa->oa->po;
+  struct proto *p = &po->proto;
 
   DBG("Neighbor state machine for neighbor %I, event \"%s\".", n->ip,
             ospf_inm[event]);
@@ -322,7 +322,7 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
     if (n->state == NEIGHBOR_EXSTART)
     {
       neigh_chstate(n, NEIGHBOR_EXCHANGE);
-      s_init(&(n->dbsi), &(n->ifa->oa->lsal));
+      s_init(&(n->dbsi), &po->lsal);
       while (!EMPTY_LIST(n->ackl[ACKL_DELAY]))
       {
        struct lsah_n *no;
@@ -396,7 +396,7 @@ bdr_election(struct ospf_iface *ifa)
   u32 myid;
   ip_addr ndrip, nbdrip;
   int doadj;
-  struct proto *p = &ifa->proto->proto;
+  struct proto *p = &ifa->oa->po->proto;
 
   DBG("(B)DR election.\n");
 
@@ -541,13 +541,10 @@ ospf_find_area(struct proto_ospf *po, u32 aid)
 void
 neighbor_timer_hook(timer * timer)
 {
-  struct ospf_neighbor *n;
-  struct ospf_iface *ifa;
-  struct proto *p;
+  struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
+  struct ospf_iface *ifa = n->ifa;
+  struct proto *p = &ifa->oa->po->proto;
 
-  n = (struct ospf_neighbor *) timer->data;
-  ifa = n->ifa;
-  p = (struct proto *) (ifa->proto);
   OSPF_TRACE(D_EVENTS,
             "Inactivity timer fired on interface %s for neighbor %I.",
             ifa->iface->name, n->ip);
@@ -557,11 +554,9 @@ neighbor_timer_hook(timer * timer)
 void
 ospf_neigh_remove(struct ospf_neighbor *n)
 {
-  struct ospf_iface *ifa;
-  struct proto *p;
+  struct ospf_iface *ifa = n->ifa;
+  struct proto *p = &ifa->oa->po->proto;
 
-  ifa = n->ifa;
-  p = (struct proto *) (ifa->proto);
   neigh_chstate(n, NEIGHBOR_DOWN);
   rem_node(NODE n);
   rfree(n->pool);
index 8f6b2171f66d04ee8a336fab1d290b1b640df5c9..e9e45d7648a4890279903c5dbc3836a29e16214d 100644 (file)
  * describes the link-state database. It allows fast search, addition
  * and deletion. Each LSA is kept in two pieces: header and body. Both of them are
  * kept in the endianity of the CPU.
+ *
+ * The heart beat of ospf is ospf_disp(). It is called at regular intervals
+ * (&proto_ospf->tick). It is responsible for aging and flushing of LSAs in
+ * the database, for routing table calculaction and it call area_disp() of every
+ * ospf_area.
  * 
- * Every area has its own area_disp() which is
- * responsible for late originating of router LSA, calculating
- * of the routing table and it also ages and flushes the LSAs. This
- * function is called in regular intervals from ospf_disp()
+ * The function area_disp() is
+ * responsible for late originating of router LSA and network LSA
+ * and for cleanup after routing table calculation process in
+ * the area.
  * To every &ospf_iface, we connect one or more
  * &ospf_neighbor's -- a structure containing many timers and queues
  * for building adjacency and for exchange of routing messages.
@@ -122,6 +127,9 @@ ospf_start(struct proto *p)
   init_list(&(po->area_list));
   fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
   po->areano = 0;
+  po->gr = ospf_top_new(p->pool);
+  po->cleanup = 1;
+  s_init_list(&(po->lsal));
   if (EMPTY_LIST(c->area_list))
   {
     log(L_ERR "Cannot start, no OSPF areas configured!");
@@ -135,8 +143,6 @@ ospf_start(struct proto *p)
     po->areano++;
     oa->stub = ac->stub;
     oa->areaid = ac->areaid;
-    oa->gr = ospf_top_new(p->pool);
-    s_init_list(&(oa->lsal));
     oa->rt = NULL;
     oa->po = po;
     add_area_nets(oa, ac);
@@ -181,13 +187,9 @@ ospf_dump(struct proto *p)
     }
   }
 
-  WALK_LIST(NODE oa, po->area_list)
-  {
-    OSPF_TRACE(D_EVENTS, "LSA graph dump for area \"%I\" start:", oa->areaid);
-    ospf_top_dump(oa->gr, p);
-    OSPF_TRACE(D_EVENTS, "LSA graph dump for area \"%I\" finished",
-              oa->areaid);
-  }
+  OSPF_TRACE(D_EVENTS, "LSA graph dump start:");
+  ospf_top_dump(po->gr, p);
+  OSPF_TRACE(D_EVENTS, "LSA graph dump finished");
   neigh_dump_all();
 }
 
@@ -293,9 +295,9 @@ schedule_rtcalc(struct proto_ospf *po)
 }
 
 /**
- * area_disp - invokes link-state database aging, origination of
- * router LSA and routing table calculation
- * @timer: it's called every @ospf_area->tick seconds
+ * area_disp - invokes origination of
+ * router LSA and routing table cleanup
+ * @oa: ospf area
  *
  * It invokes aging and when @ospf_area->origrt is set to 1, start
  * function for origination of router LSA and network LSAs.
@@ -316,11 +318,13 @@ area_disp(struct ospf_area *oa)
     if (ifa->orignet && (ifa->oa == oa))
       originate_net_lsa(ifa);
   }
-
-  /* Age LSA DB */
-  ospf_age(oa);
 }
 
+/**
+ * ospf_disp - invokes routing table calctulation, aging and also area_disp()
+ * @timer: timer usually called every @proto_ospf->tick second, @timer->data
+ * point to @proto_ospf
+ */
 void
 ospf_disp(timer * timer)
 {
@@ -330,10 +334,12 @@ ospf_disp(timer * timer)
   WALK_LIST(oa, po->area_list)
     area_disp(oa);
 
+  /* Age LSA DB */
+  ospf_age(po);
+
   /* Calculate routing table */
   if (po->calcrt)
     ospf_rt_spf (po);
-  po->calcrt = 0;
 }
 
 
@@ -425,19 +431,19 @@ ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED,
     int max = max_ext_lsa(n->n.pxlen);
 
     /* Flush old external LSA */
-    WALK_LIST(oa, po->area_list)
+    for (i = 0; i < max; i++, pr++)
     {
-      for (i = 0; i < max; i++, pr++)
+      if (en = ospf_hash_find(po->gr, 0, pr, rtid, LSA_T_EXT))
       {
-       if (en = ospf_hash_find(oa->gr, pr, rtid, LSA_T_EXT))
+        ext = en->lsa_body;
+       if (ipa_compare(ext->netmask, ipa_mkmask(n->n.pxlen)) == 0)
        {
-         ext = en->lsa_body;
-         if (ipa_compare(ext->netmask, ipa_mkmask(n->n.pxlen)) == 0)
-         {
+          WALK_LIST(oa, po->area_list)
+          {
            ospf_lsupd_flush_nlsa(en, oa);
-           break;
          }
        }
+        break;
       }
     }
   }
@@ -830,6 +836,7 @@ ospf_sh(struct proto *p)
   cli_msg(-1014, "RFC1583 compatibility: %s", (po->rfc1583 ? "enable" : "disabled"));
   cli_msg(-1014, "RT scheduler tick: %d", po->tick);
   cli_msg(-1014, "Number of areas: %u", po->areano);
+  cli_msg(-1014, "Number of LSAs in DB:\t%u", po->gr->hash_entries);
 
   WALK_LIST(oa, po->area_list)
   {
@@ -854,7 +861,6 @@ ospf_sh(struct proto *p)
     cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No");
     cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No");
     cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano);
-    cli_msg(-1014, "\t\tNumber of LSAs in DB:\t%u", oa->gr->hash_entries);
     cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
     cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno);
 
index 40452c2b932d526f55789f16d58ab06e095c5712..8f0b49837d83c3cab5598b9eca97bac32f211cf5 100644 (file)
@@ -125,7 +125,6 @@ union options
 struct ospf_iface
 {
   node n;
-  struct proto_ospf *proto;
   struct iface *iface;         /* Nest's iface */
   struct ospf_area *oa;
   struct object_lock *lock;
@@ -507,10 +506,7 @@ struct ospf_area
 {
   node n;
   u32 areaid;
-  timer *disp_timer;           /* Area's dispatcher hear beat */
   int origrt;                  /* Rt lsa origination scheduled? */
-  struct top_graph *gr;                /* LSA graph */
-  slist lsal;                  /* List of all LSA's */
   struct top_hash_entry *rt;   /* My own router LSA */
   list cand;                   /* List of candidates for RT calc. */
   struct fib net_fib;          /* Networks to advertise or not */
@@ -526,7 +522,10 @@ struct proto_ospf
   struct proto proto;
   timer *disp_timer;           /* OSPF proto dispatcher */
   unsigned tick;
+  struct top_graph *gr;                /* LSA graph */
+  slist lsal;                  /* List of all LSA's */
   int calcrt;                  /* Routing table calculation scheduled? */
+  int cleanup;                  /* Should I cleanup after RT calculation? */
   list iface_list;             /* Interfaces we really use */
   list area_list;
   int areano;                  /* Number of area I belong to */
index 92e052260e7610fa0f09ddac4a55d004b73ca00d..5b0ad807362af17af430696868eecad65fbb8d83 100644 (file)
@@ -14,9 +14,7 @@ void
 ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
 {
   struct ospf_packet *pkt;
-  struct proto *p;
-
-  p = (struct proto *) (ifa->proto);
+  struct proto *p = (struct proto *) (ifa->oa->po);
 
   pkt = (struct ospf_packet *) buf;
 
@@ -40,7 +38,7 @@ ospf_pkt_maxsize(struct ospf_iface *ifa)
 void
 ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
 {
-  struct proto_ospf *po = ifa->proto;
+  struct proto_ospf *po = ifa->oa->po;
   struct proto *p = &po->proto;
   struct password_item *passwd = password_find (ifa->passwords);
   void *tail;
@@ -97,7 +95,7 @@ static int
 ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
 {
   int i;
-  struct proto_ospf *po = ifa->proto;
+  struct proto_ospf *po = ifa->oa->po;
   struct proto *p = &po->proto;
   struct password_item *pass = NULL, *ptmp;
   void *tail;
@@ -219,8 +217,8 @@ ospf_rx_hook(sock * sk, int size)
 {
   struct ospf_packet *ps;
   struct ospf_iface *ifa = (struct ospf_iface *) (sk->data);
-  struct proto_ospf *po = ifa->proto;
-  struct proto *p = (struct proto *) (ifa->proto);
+  struct proto_ospf *po = ifa->oa->po;
+  struct proto *p = &po->proto;
   struct ospf_neighbor *n;
   int osize;
   char *mesg = "Bad OSPF packet from ";
@@ -356,24 +354,16 @@ ospf_rx_hook(sock * sk, int size)
 void
 ospf_tx_hook(sock * sk)
 {
-  struct ospf_iface *ifa;
-  struct proto *p;
-
-  ifa = (struct ospf_iface *) (sk->data);
-
-  p = (struct proto *) (ifa->proto);
+  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);
 }
 
 void
 ospf_err_hook(sock * sk, int err UNUSED)
 {
-  struct ospf_iface *ifa;
-  struct proto *p;
-
-  ifa = (struct ospf_iface *) (sk->data);
-
-  p = (struct proto *) (ifa->proto);
+  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);
 }
 
index ef3d44da4c6b4405942113e941cc92816b225f88..a6db9ca494dcc23a96ecd79f75b9bba6a5b2df4a 100644 (file)
@@ -13,7 +13,7 @@ add_cand(list * l, struct top_hash_entry *en,
 static void
 calc_next_hop(struct top_hash_entry *en,
              struct top_hash_entry *par, struct ospf_area *oa);
-static void ospf_ext_spfa(struct ospf_area *oa);
+static void ospf_ext_spf(struct proto_ospf *po);
 static void rt_sync(struct proto_ospf *po);
 
 static void
@@ -231,7 +231,7 @@ ospf_rt_spfa(struct ospf_area *oa)
          break;
 
        case LSART_NET:
-         tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET);
+         tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET);
          if (tmp == NULL)
            DBG("Not found!\n");
          else
@@ -241,7 +241,7 @@ ospf_rt_spfa(struct ospf_area *oa)
        case LSART_VLNK:
           vlink = 1;
        case LSART_PTP:
-         tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT);
+         tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
          DBG("PTP found.\n");
          break;
        default:
@@ -272,7 +272,7 @@ ospf_rt_spfa(struct ospf_area *oa)
                       sizeof(struct ospf_lsa_net)) / sizeof(u32); i++)
       {
        DBG("     Working on router %I ", *(rts + i));
-       tmp = ospf_hash_find(oa->gr, *(rts + i), *(rts + i), LSA_T_RT);
+       tmp = ospf_hash_find(po->gr, oa->areaid, *(rts + i), *(rts + i), LSA_T_RT);
        if (tmp != NULL)
          DBG("Found :-)\n");
        else
@@ -288,7 +288,7 @@ ospf_rt_spfa(struct ospf_area *oa)
   {
     if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
     {
-      if ((tmp = ospf_hash_find(oa->gr, iface->vid, iface->vid, LSA_T_RT)) &&
+      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)))
@@ -319,6 +319,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
   struct ospf_lsa_net *ln;
   struct ospf_lsa_rt *rt;
   struct ospf_lsa_rt_link *rtl, *rr;
+  struct proto_ospf *po = oa->po;
 
   if(!pre) return 0;
   if(!fol) return 0;
@@ -335,7 +336,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
        case LSART_STUB:
          break;
        case LSART_NET:
-         if (ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET) == pre)
+         if (ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_NET) == pre)
           {
             fol->lb = ipa_from_u32(rtl->data);
             return 1;
@@ -343,7 +344,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
          break;
        case LSART_VLNK:
        case LSART_PTP:
-         if (ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT) == pre)
+         if (ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT) == pre)
           {
             fol->lb = ipa_from_u32(rtl->data);
             return 1;
@@ -361,7 +362,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
       for (i = 0; i < (fol->lsa.length - sizeof(struct ospf_lsa_header) -
                       sizeof(struct ospf_lsa_net)) / sizeof(u32); i++)
       {
-       if (ospf_hash_find(oa->gr, *(rts + i), *(rts + i), LSA_T_RT) == pre)
+       if (ospf_hash_find(po->gr, oa->areaid, *(rts + i), *(rts + i), LSA_T_RT) == pre)
         {
           return 1;
         }
@@ -388,8 +389,10 @@ ospf_rt_sum_tr(struct ospf_area *oa)
 
   if(!bb) return;
 
-  WALK_SLIST(en, oa->lsal)
+  WALK_SLIST(en, po->lsal)
   {
+    if (en->oa != oa)
+      continue;
     if (en->lsa.age == LSA_MAXAGE)
       continue;
     if (en->dist == LSINFINITY)
@@ -398,7 +401,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
     if (en->lsa.rt == p->cf->global->router_id)
       continue;
 
-    if((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
+    if ((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
       continue;
 
     mask = (ip_addr *)en->lsa_body;
@@ -457,8 +460,10 @@ ospf_rt_sum(struct ospf_area *oa)
 
   OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area routes");
 
-  WALK_SLIST(en, oa->lsal)
+  WALK_SLIST(en, po->lsal)
   {
+    if (en->oa != oa)
+      continue;
     /* Page 169 (1) */
     if (en->lsa.age == LSA_MAXAGE)
       continue;
@@ -528,6 +533,8 @@ ospf_rt_spf(struct proto_ospf *po)
 
   if (po->areano == 0) return;
 
+  po->cleanup = 1;
+
   OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
 
   /* Invalidate old routing table */
@@ -580,20 +587,16 @@ ospf_rt_spf(struct proto_ospf *po)
     }
   }
 
-  WALK_LIST(oa, po->area_list)
-  {
-    if (!oa->stub)
-    {
-      ospf_ext_spfa(oa);
-      break;
-    }
-  }
+  ospf_ext_spf(po);
+
   rt_sync(po);
+
+  po->calcrt = 0;
 }
 
 
 /**
- * ospf_ext_spfa - calculate external paths
+ * ospf_ext_spf - calculate external paths
  * @po: protocol
  *
  * After routing table for any area is calculated, calculation of external
@@ -601,9 +604,8 @@ ospf_rt_spf(struct proto_ospf *po)
  * Inter- and Intra-area paths are always prefered over externals.
  */
 static void
-ospf_ext_spfa(struct ospf_area *oa)
+ospf_ext_spf(struct proto_ospf *po)
 {
-  struct proto_ospf *po = oa->po;
   ort *nf1, *nf2, *nfh;
   orta nfa;
   struct top_hash_entry *en;
@@ -621,7 +623,7 @@ ospf_ext_spfa(struct ospf_area *oa)
 
   OSPF_TRACE(D_EVENTS, "Starting routing table calculation for ext routes");
 
-  WALK_SLIST(en, oa->lsal)
+  WALK_SLIST(en, po->lsal)
   {
     if (en->lsa.type != LSA_T_EXT)
       continue;
@@ -729,7 +731,7 @@ ospf_ext_spfa(struct ospf_area *oa)
     nfa.capa = 0;
     nfa.metric1 = met1;
     nfa.metric2 = met2;
-    nfa.oa = oa;
+    nfa.oa = NULL;
     nfa.ar = nf1->n.ar;
     nfa.nh = nh;
     nfa.ifa = nhi;
@@ -941,7 +943,7 @@ again1:
         {
           if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
           {
-            if ((en = ospf_hash_find(ifa->voa->gr, ifa->vid, ifa->vid, LSA_T_RT)) &&
+            if ((en = ospf_hash_find(po->gr, ifa->voa->areaid, ifa->vid, ifa->vid, LSA_T_RT)) &&
               (!ipa_equal(en->nh, IPA_NONE)))
             {
               a0.gw = en->nh;
index 48547214c0c5b3f186016459acf67a3124cfbf1d..b0c97b332abf2021b05d9987d3342781a83007b7 100644 (file)
@@ -159,7 +159,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
       default:
         ln--;
        i--;            /* No link added */
-        log("Unknown interface type");
+        log("Unknown interface type %s", ifa->iface->name);
         break;
       }
     }
@@ -217,7 +217,6 @@ originate_rt_lsa(struct ospf_area *oa)
   lsasum_calculate(&lsa, body);
   en = lsa_install_new(&lsa, body, oa);
   oa->rt = en;
-  en->dist = 0; /* Force area aging */
   ospf_lsupd_flood(NULL, NULL, &oa->rt->lsa, NULL, oa, 1);
   schedule_rtcalc(po);
   oa->origrt = 0;
@@ -264,7 +263,7 @@ originate_net_lsa_body(struct ospf_iface *ifa, u16 * length,
 void
 originate_net_lsa(struct ospf_iface *ifa)
 {
-  struct proto_ospf *po = ifa->proto;
+  struct proto_ospf *po = ifa->oa->po;
   struct ospf_lsa_header lsa;
   u32 rtid = po->proto.cf->global->router_id;
   struct proto *p = &po->proto;
@@ -291,7 +290,7 @@ originate_net_lsa(struct ospf_iface *ifa)
     if (ifa->nlsa->lsa_body != NULL)
       mb_free(ifa->nlsa->lsa_body);
     ifa->nlsa->lsa_body = NULL;
-    ospf_hash_delete(ifa->oa->gr, ifa->nlsa);
+    ospf_hash_delete(po->gr, ifa->nlsa);
     schedule_rtcalc(po);
     ifa->nlsa = NULL;
     return;
@@ -411,7 +410,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
   for (i = 0; i < max; i++)
   {
     lsa.id = ipa_to_u32(fn->prefix) + i;
-    if ((en = ospf_hash_find_header(oa->gr, &lsa)) != NULL)
+    if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
     {
       sum = en->lsa_body;
       if (fn->pxlen == ipa_mklen(sum->netmask))
@@ -421,7 +420,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
         lsasum_calculate(&en->lsa, sum);
         OSPF_TRACE(D_EVENTS, "Flushing summary lsa. (id=%I, type=%d)", en->lsa.id, en->lsa.type);
         ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
-        if (can_flush_lsa(oa)) flush_lsa(en, oa);
+        if (can_flush_lsa(po)) flush_lsa(en, po);
         break;
       }
     }
@@ -458,7 +457,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
   for (i = 0; i < max; i++)
   {
     lsa.id = ipa_to_u32(fn->prefix) + i;
-    if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL)
+    if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) == NULL)
     {
       if (!free) free = lsa.id;
     }
@@ -590,11 +589,9 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
   ext1 = body;
   max = max_ext_lsa(n->n.pxlen);
 
-  oa = HEAD(po->area_list);
-
   for (i = 0; i < max; i++)
   {
-    if ((en = ospf_hash_find_header(oa->gr, &lsa)) != NULL)
+    if ((en = ospf_hash_find_header(po->gr, 0 , &lsa)) != NULL)
     {
       ext2 = en->lsa_body;
       if (ipa_compare(ext1->netmask, ext2->netmask) != 0)
@@ -672,16 +669,16 @@ ospf_top_hash_u32(u32 a)
 }
 
 static inline unsigned
-ospf_top_hash(struct top_graph *f, u32 lsaid, u32 rtrid, u32 type)
+ospf_top_hash(struct top_graph *f, u32 areaid, u32 lsaid, u32 rtrid, u32 type)
 {
 #if 1                          /* Dirty patch to make rt table calculation work. */
   return (ospf_top_hash_u32(lsaid) +
          ospf_top_hash_u32((type ==
-                            LSA_T_NET) ? lsaid : rtrid) +
-         type) & f->hash_mask;
+                            LSA_T_NET) ? lsaid : rtrid) + type +
+          (type == LSA_T_EXT ? 0 : areaid)) & f->hash_mask;
 #else
   return (ospf_top_hash_u32(lsaid) + ospf_top_hash_u32(rtrid) +
-         type) & f->hash_mask;
+         type + areaid) & f->hash_mask;
 #endif
 }
 
@@ -735,7 +732,7 @@ ospf_top_rehash(struct top_graph *f, int step)
     while (e)
     {
       x = e->next;
-      n = newt + ospf_top_hash(f, e->lsa.id, e->lsa.rt, e->lsa.type);
+      n = newt + ospf_top_hash(f, e->oa->areaid, e->lsa.id, e->lsa.rt, e->lsa.type);
       e->next = *n;
       *n = e;
       e = x;
@@ -745,49 +742,65 @@ ospf_top_rehash(struct top_graph *f, int step)
 }
 
 struct top_hash_entry *
-ospf_hash_find_header(struct top_graph *f, struct ospf_lsa_header *h)
+ospf_hash_find_header(struct top_graph *f, u32 areaid, struct ospf_lsa_header *h)
 {
-  return ospf_hash_find(f, h->id, h->rt, h->type);
+  return ospf_hash_find(f, areaid, h->id, h->rt, h->type);
 }
 
 struct top_hash_entry *
-ospf_hash_get_header(struct top_graph *f, struct ospf_lsa_header *h)
+ospf_hash_get_header(struct top_graph *f, struct ospf_area *oa, struct ospf_lsa_header *h)
 {
-  return ospf_hash_get(f, h->id, h->rt, h->type);
+  return ospf_hash_get(f, oa, h->id, h->rt, h->type);
 }
 
 struct top_hash_entry *
-ospf_hash_find(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
+ospf_hash_find(struct top_graph *f, u32 areaid, u32 lsa, u32 rtr, u32 type)
 {
-  struct top_hash_entry *e = f->hash_table[ospf_top_hash(f, lsa, rtr, type)];
+  struct top_hash_entry *e;
 
-#if 1                          /* Dirty patch to make rt table calculation work. */
+  e = f->hash_table[ospf_top_hash(f, areaid, lsa, rtr, type)];
+
+  /* Dirty patch to make rt table calculation work. */
   if (type == LSA_T_NET)
   {
-    while (e && (e->lsa.id != lsa || e->lsa.type != LSA_T_NET))
+    while (e && (e->lsa.id != lsa || e->lsa.type != LSA_T_NET || e->oa->areaid != areaid))
       e = e->next;
   }
-  else
+  else if (type == LSA_T_EXT)
   {
     while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr))
       e = e->next;
   }
-#else
-  while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type))
-    e = e->next;
-#endif
+  else
+  {
+    while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr || e->oa->areaid != areaid))
+      e = e->next;
+  }
+
   return e;
 }
 
 struct top_hash_entry *
-ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
+ospf_hash_get(struct top_graph *f, struct ospf_area *oa, u32 lsa, u32 rtr, u32 type)
 {
-  struct top_hash_entry **ee =
-    f->hash_table + ospf_top_hash(f, lsa, rtr, type);
-  struct top_hash_entry *e = *ee;
+  struct top_hash_entry **ee;
+  struct top_hash_entry *e;
+  u32 nareaid = (type == LSA_T_EXT ? 0 : oa->areaid);
+
+  ee = f->hash_table + ospf_top_hash(f, nareaid, lsa, rtr, type);
+  e = *ee;
+
+  if (type == LSA_T_EXT)
+  {
+    while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type))
+      e = e->next;
+  }
+  else
+  {
+    while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type || e->oa->areaid != nareaid))
+      e = e->next;
+  }
 
-  while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type))
-    e = e->next;
   if (e)
     return e;
 
@@ -802,6 +815,7 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
   e->lsa.type = type;
   e->lsa_body = NULL;
   e->nhi = NULL;
+  e->oa = oa;
   e->next = *ee;
   *ee = e;
   if (f->hash_entries++ > f->hash_entries_max)
@@ -812,8 +826,8 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
 void
 ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
 {
-  unsigned int h = ospf_top_hash(f, e->lsa.id, e->lsa.rt, e->lsa.type);
-  struct top_hash_entry **ee = f->hash_table + h;
+  struct top_hash_entry **ee = f->hash_table + 
+    ospf_top_hash(f, e->oa->areaid, e->lsa.id, e->lsa.rt, e->lsa.type);
 
   while (*ee)
   {
@@ -833,7 +847,7 @@ ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
 void
 ospf_top_dump(struct top_graph *f, struct proto *p)
 {
-  unsigned int i;
+  unsigned int i;       /* FIXME: Print areaids */
   OSPF_TRACE(D_EVENTS, "Hash entries: %d", f->hash_entries);
 
   for (i = 0; i < f->hash_size; i++)
@@ -856,22 +870,18 @@ ospf_top_dump(struct top_graph *f, struct proto *p)
  */
 
 int
-can_flush_lsa(struct ospf_area *oa)
+can_flush_lsa(struct proto_ospf *po)
 {
   struct ospf_iface *ifa;
   struct ospf_neighbor *n;
 
-  WALK_LIST(ifa, iface_list)
+  WALK_LIST(ifa, po->iface_list)
   {
-    if (ifa->oa == oa)
+    WALK_LIST(n, ifa->neigh_list)
     {
-      WALK_LIST(n, ifa->neigh_list)
-      {
-       if ((n->state == NEIGHBOR_EXCHANGE) || (n->state == NEIGHBOR_LOADING))
-       {
-         return 0;
-       }
-      }
+      if ((n->state == NEIGHBOR_EXCHANGE) || (n->state == NEIGHBOR_LOADING))
+        return 0;
+
       break;
     }
   }
index c6031c5e22b0285e7df8ceed39232bdca5fc5e57..bccff056154ace833d3fcc93708a7497497aeb81 100644 (file)
@@ -18,6 +18,7 @@ struct top_hash_entry
                                 */
   struct top_hash_entry *next; /* Next in hash chain */
   struct ospf_lsa_header lsa;
+  struct ospf_area *oa;
   void *lsa_body;
   bird_clock_t inst_t;         /* Time of installation into DB */
   ip_addr nh;                  /* Next hop */
@@ -47,18 +48,18 @@ struct top_graph
 struct top_graph *ospf_top_new(pool *);
 void ospf_top_free(struct top_graph *);
 void ospf_top_dump(struct top_graph *, struct proto *);
-struct top_hash_entry *ospf_hash_find_header(struct top_graph *f,
+struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, u32 areaid,
                                             struct ospf_lsa_header *h);
-struct top_hash_entry *ospf_hash_get_header(struct top_graph *f,
+struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, struct ospf_area *oa,
                                            struct ospf_lsa_header *h);
-struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 lsa, u32 rtr,
+struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 areaid, u32 lsa, u32 rtr,
                                      u32 type);
-struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 lsa, u32 rtr,
+struct top_hash_entry *ospf_hash_get(struct top_graph *, struct ospf_area *oa, u32 lsa, u32 rtr,
                                     u32 type);
 void ospf_hash_delete(struct top_graph *, struct top_hash_entry *);
 void originate_rt_lsa(struct ospf_area *oa);
 void originate_net_lsa(struct ospf_iface *ifa);
-int can_flush_lsa(struct ospf_area *oa);
+int can_flush_lsa(struct proto_ospf *po);
 int max_ext_lsa(unsigned pxlen);
 void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
                       struct ea_list *attrs);