]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Temporary OSPF commit.
authorOndrej Zajicek <santiago@crfreenet.org>
Mon, 15 Apr 2013 23:14:57 +0000 (01:14 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 15 Apr 2013 23:14:57 +0000 (01:14 +0200)
proto/ospf/dbdes.c
proto/ospf/lsreq.c
proto/ospf/lsupd.c
proto/ospf/lsupd.h
proto/ospf/neighbor.c
proto/ospf/ospf.h
proto/ospf/topology.c
proto/ospf/topology.h

index 120c20e8501024a91a3e9810fc05662b4095f6f8..d0d8e306c5fbb678f78a1bb8df9a1ab6c3cf0baf 100644 (file)
@@ -268,7 +268,7 @@ ospf_dbdes_process(struct ospf_neighbor *n, struct ospf_packet *pkt, unsigned pl
       if (ospf_hash_is_new(req))
        s_add_tail(&(n->lsrql), SNODE req);
 
-      en->lsa = lsa;
+      en->lsa = lsa; // XXXX ??? should be req->lsa ?
     }
   }
 }
index 721e0379e3d1c3bdbca1cf9e29fd15a37f65eb4c..e0270b9ff256deb479026a20d1a839a7a1d394c5 100644 (file)
@@ -91,6 +91,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
   ospf_send_to(ifa, n->ip);
 }
 
+
 void
 ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
                   struct ospf_neighbor *n)
@@ -99,11 +100,6 @@ ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
   struct ospf_lsreq_header *lsrs;
   unsigned i, lsr_count;
 
-  struct ospf_lsreq_item *lsr_head, *lsr;
-  struct ospf_lsreq_item **lsr_pos = &lsr_head;
-  slab *upslab;
-
-
   /* No need to check length, lsreq has only basic header */
 
   OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet received from %I via %s",
@@ -114,9 +110,10 @@ ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
   ospf_neigh_sm(n, INM_HELLOREC);      /* Not in RFC */
 
-  upslab = sl_new(n->pool, sizeof(struct ospf_lsreq_item));
-
   ospf_lsreq_body(po, pkt, ntohs(pkt->length), &lsrs, &lsr_count);
+
+  struct top_hash_entry *en, *entries[lsr_count];
+
   for (i = 0; i < lsr_count; i++)
   {
     u32 id, rt, type, dom;
@@ -127,26 +124,17 @@ ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
     DBG("Processing requested LSA: Type: %04x, Id: %R, Rt: %R\n", type, id, rt);
 
-    if (ospf_hash_find(po->gr, dom, id, rt, type) == NULL)
+    en = ospf_hash_find(po->gr, dom, id, rt, type); 
+    if (!en)
     {
-      log(L_WARN "Received bad LSREQ from %I: Type: %04x, Id: %R, Rt: %R",
-         n->ip, type, id, rt);
+      log(L_WARN "%s: Received LSREQ from %I for missing LSA (Type: %04x, Id: %R, Rt: %R)",
+         po->proto.name, n->ip, type, id, rt);
       ospf_neigh_sm(n, INM_BADLSREQ);
-      rfree(upslab);
       return;
     }
 
-    lsr = sl_alloc(upslab);
-    lsr->domain = dom;
-    lsr->type = type;
-    lsr->id = id;
-    lsr->rt = rt;
-
-    *lsr_pos = lsr;
-    lsr_pos = &(lsr->next);
+    entries[i] = en;
   }
-  *lsr_pos = NULL;
 
-  ospf_lsupd_send_list(n, lsr_head);
-  rfree(upslab);
+  ospf_lsupd_send(n, entries, lsr_count);
 }
index 94e1b743b113dc8d70aa48982e1de45706e559b7..86e1b1af8110d13488de478b43528cab43eed079 100644 (file)
@@ -47,9 +47,19 @@ ospf_lsupd_hdrlen(struct proto_ospf *po)
   return ospf_pkt_hdrlen(po) + 4; /* + u32 lsa count field */
 }
 
-static inline u32 *
-ospf_lsupd_lsa_count(struct ospf_packet *pkt, unsigned hdrlen)
-{ return ((void *) pkt) + hdrlen - 4; }
+static inline u32
+ospf_lsupd_get_lsa_count(struct ospf_packet *pkt, unsigned hdrlen)
+{
+  u32 *c = ((void *) pkt) + hdrlen - 4;
+  return ntohl(*c);
+}
+
+static inline void
+ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, unsigned hdrlen, u32 val)
+{
+  u32 *c = ((void *) pkt) + hdrlen - 4;
+  *c = htonl(val);
+}
 
 static inline void
 ospf_lsupd_body(struct proto_ospf *po, struct ospf_packet *pkt,
@@ -58,7 +68,7 @@ ospf_lsupd_body(struct proto_ospf *po, struct ospf_packet *pkt,
   unsigned hlen = ospf_lsupd_hdrlen(po);
   *offset = hlen;
   *bound = ntohs(pkt->length) - sizeof(struct ospf_lsa_header);
-  *lsa_count = ntohl(*ospf_lsupd_lsa_count(pkt, hlen));
+  *lsa_count = ospf_lsupd_get_lsa_count(pkt, hlen);
 }
 
 static void ospf_lsupd_dump(struct proto_ospf *po, struct ospf_packet *pkt)
@@ -93,291 +103,19 @@ static void ospf_lsupd_dump(struct proto_ospf *po, struct ospf_packet *pkt)
     }
 }
 
-/**
- * ospf_lsupd_flood - send received or generated lsa to the neighbors
- * @po: OSPF protocol
- * @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)
- * @domain: domain of LSA (must be filled)
- * @rtl: add this LSA into retransmission list
- *
- *
- * return value - was the LSA flooded back?
- */
-
-int
-ospf_lsupd_flood(struct proto_ospf *po,
-                struct ospf_neighbor *n, struct ospf_lsa_header *hn,
-                struct ospf_lsa_header *hh, u32 domain, int rtl)
-{
-  struct ospf_iface *ifa;
-  struct ospf_neighbor *nn;
-  struct top_hash_entry *en;
-  int ret, retval = 0;
-
-  /* pg 148 */
-  WALK_LIST(ifa, po->iface_list)
-  {
-    if (ifa->stub)
-      continue;
-
-    if (! ospf_lsa_flooding_allowed(hh, domain, ifa))
-      continue;
-
-    DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
-       hh->type, hh->id, hh->rt, hh->sn, hh->age);
-
-    ret = 0;
-    WALK_LIST(nn, ifa->neigh_list)
-    {
-      /* 13.3 (1a) */
-      if (nn->state < NEIGHBOR_EXCHANGE)
-       continue;
-
-      /* 13.3 (1b) */
-      if (nn->state < NEIGHBOR_FULL)
-      {
-       if ((en = ospf_hash_find_header(nn->lsrqh, domain, hh)) != NULL)
-       {
-         DBG("That LSA found in lsreq list for neigh %R\n", nn->rid);
-
-         switch (lsa_comp(hh, &en->lsa))
-         {
-         case CMP_OLDER:
-           continue;
-           break;
-         case CMP_SAME:
-           s_rem_node(SNODE en);
-           if (en->lsa_body != NULL)
-             mb_free(en->lsa_body);
-           en->lsa_body = NULL;
-           DBG("Removing from lsreq list for neigh %R\n", nn->rid);
-           ospf_hash_delete(nn->lsrqh, en);
-           if (EMPTY_SLIST(nn->lsrql))
-             ospf_neigh_sm(nn, INM_LOADDONE);
-           continue;
-           break;
-         case CMP_NEWER:
-           s_rem_node(SNODE en);
-           if (en->lsa_body != NULL)
-             mb_free(en->lsa_body);
-           en->lsa_body = NULL;
-           DBG("Removing from lsreq list for neigh %R\n", nn->rid);
-           ospf_hash_delete(nn->lsrqh, en);
-           if (EMPTY_SLIST(nn->lsrql))
-             ospf_neigh_sm(nn, INM_LOADDONE);
-           break;
-         default:
-           bug("Bug in lsa_comp?");
-         }
-       }
-      }
-
-      /* 13.3 (1c) */
-      if (nn == n)
-       continue;
-
-      /* 13.3 (1d) */
-      if (rtl)
-      {
-       /* In OSPFv3, there should be check whether receiving router understand
-          that type of LSA (for LSA types with U-bit == 0). But as we does not support
-          any optional LSA types, this is not needed yet */
-
-       if ((en = ospf_hash_find_header(nn->lsrth, domain, hh)) == NULL)
-       {
-         en = ospf_hash_get_header(nn->lsrth, domain, hh);
-       }
-       else
-       {
-         s_rem_node(SNODE en);
-       }
-       s_add_tail(&nn->lsrtl, SNODE en);
-       memcpy(&en->lsa, hh, sizeof(struct ospf_lsa_header));
-       DBG("Adding that LSA for flood to %I\n", nn->ip);
-      }
-      else
-      {
-       if ((en = ospf_hash_find_header(nn->lsrth, domain, hh)) != NULL)
-       {
-         s_rem_node(SNODE en);
-         ospf_hash_delete(nn->lsrth, en);
-       }
-      }
-
-      ret = 1;
-    }
-
-    if (ret == 0)
-      continue;                        /* pg 150 (2) */
-
-    if (n && (n->ifa == ifa))
-    {
-      if ((n->rid == ifa->drid) || n->rid == ifa->bdrid)
-       continue;               /* pg 150 (3) */
-      if (ifa->state == OSPF_IS_BACKUP)
-       continue;               /* pg 150 (4) */
-      retval = 1;
-    }
-
-    {
-      u16 len, age;
-      unsigned hlen;
-      struct ospf_packet *pkt;
-      struct ospf_lsa_header *lh;
-
-      pkt = ospf_tx_buffer(ifa);
-      hlen = ospf_lsupd_hdrlen(po);
-
-      ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
-      *ospf_lsupd_lsa_count(pkt, hlen) = htonl(1);
-      lh = (((void *) pkt) + hlen);
-
-      /* Copy LSA into the packet */
-      if (hn)
-      {
-       memcpy(lh, hn, ntohs(hn->length));
-      }
-      else
-      {
-       u8 *help;
-       struct top_hash_entry *en;
-
-       lsa_hton_hdr(hh, lh);
-       help = (u8 *) (lh + 1);
-       en = ospf_hash_find_header(po->gr, domain, hh);
-       lsa_hton_body(en->lsa_body, help, hh->length - sizeof(struct ospf_lsa_header));
-      }
-
-      age = ntohs(lh->age);
-      age += ifa->inftransdelay;
-      if (age > LSA_MAXAGE)
-       age = LSA_MAXAGE;
-      lh->age = htons(age);
-
-      len = hlen + ntohs(lh->length);
-      pkt->length = htons(len);
-
-      OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet flooded via %s", ifa->iface->name);
-
-      switch (ifa->type)
-      {
-      case OSPF_IT_BCAST:
-       if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
-         ospf_send_to_all(ifa);
-       else
-         ospf_send_to_des(ifa);
-       break;
-
-      case OSPF_IT_NBMA:
-       if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
-         ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
-       else
-         ospf_send_to_bdr(ifa);
-       break;
-
-      case OSPF_IT_PTP:
-       ospf_send_to_all(ifa);
-       break;
-
-      case OSPF_IT_PTMP:
-       ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
-       break;
-
-      case OSPF_IT_VLINK:
-       ospf_send_to(ifa, ifa->vip);
-       break;
-
-      default:
-       bug("Bug in ospf_lsupd_flood()");
-      }
-    }
-  }
-  return retval;
-}
-
-void                           /* I send all I received in LSREQ */
-ospf_lsupd_send_list(struct ospf_neighbor *n, struct ospf_lsreq_item *lsr)
-{
-  struct ospf_area *oa = n->ifa->oa;
-  struct proto_ospf *po = oa->po;
-  struct top_hash_entry *en;
-  struct ospf_packet *pkt;
-  unsigned hlen, pos, pos2, maxsize, lsano;
-
-  pkt = ospf_tx_buffer(n->ifa);
-  hlen = ospf_lsupd_hdrlen(po);
-  maxsize = ospf_pkt_maxsize(n->ifa);
+static void ospf_lsupd_flood_ifa(struct proto_ospf *po, struct ospf_iface *ifa, struct top_hash_entry *en);
 
-  while (lsr)
-  {
-    /* Prepare the packet */
-    ospf_pkt_fill_hdr(n->ifa, pkt, LSUPD_P);
-    pos = hlen;
-    lsano = 0;
 
-    /* Fill the packet with LSAs */
-    while (lsr)
-    {
-      en = ospf_hash_find(oa->po->gr, lsr->domain, lsr->id, lsr->rt, lsr->type);
-      if (!en)
-      {
-       /* Probably flushed LSA, this should not happen */
-       log(L_WARN "OSPF: LSA disappeared (Type: %04x, Id: %R, Rt: %R)", 
-           lsr->type, lsr->id, lsr->rt);
-       lsr = lsr->next;
-       continue;
-      }
-
-      pos2 = pos + en->lsa.length;
-      if (pos2 > maxsize)
-      {
-       /* The packet if full, stop adding LSAs and sent it */
-       if (lsano > 0)
-         break;
-
-       /* LSA is larger than MTU, check buffer size */
-       if (pos2 > ospf_pkt_bufsize(n->ifa))
-       {
-         /* Cannot fit in a tx buffer, skip that */
-         log(L_WARN "OSPF: LSA too large to send (Type: %04x, Id: %R, Rt: %R)", 
-             lsr->type, lsr->id, lsr->rt);
-         lsr = lsr->next;
-         continue;
-       }
-      }
-
-      /* Copy the LSA to the packet */
-      void *lsabuf = ((void *) pkt) + pos;
-      lsa_hton_hdr(&(en->lsa), (struct ospf_lsa_header *) lsabuf);
-      lsa_hton_body(en->lsa_body, lsabuf + sizeof(struct ospf_lsa_header),
-                   en->lsa.length - sizeof(struct ospf_lsa_header));
-      pos = pos2;
-      lsano++;
-      lsr = lsr->next;
-    }
-
-    if (lsano == 0)
-      break;
-
-    /* Send the packet */
-    pkt->length = htons(pos);
-    *ospf_lsupd_lsa_count(pkt, hlen) = htonl(lsano);
-    OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet sent to %I via %s",
-               n->ip, n->ifa->iface->name);
-    ospf_send_to(n->ifa, n->ip);
-  }
-}
 
 void
 ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
                   struct ospf_neighbor *n)
 {
-
-  struct ospf_neighbor *ntmp;
   struct proto_ospf *po = ifa->oa->po;
   struct proto *p = &po->proto;
+  struct ospf_neighbor *ntmp;
+
+
   unsigned sendreq = 1;
 
   unsigned plen = ntohs(pkt->length);
@@ -402,8 +140,9 @@ ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
   for (i = 0; i < lsa_count; i++)
   {
-    struct ospf_lsa_header lsatmp;
-    struct top_hash_entry *lsadb;
+    struct ospf_lsa_header lsa, *lsa_n;
+    struct top_hash_entry *en, *ret;
+    u32 lsa_len, lsa_type, lsa_domain;
 
     if (offset > bound)
     {
@@ -412,78 +151,79 @@ ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
       return;
     }
 
-    struct ospf_lsa_header *lsa = ((void *) pkt) + offset;
-    unsigned int lsalen = ntohs(lsa->length);
-    offset += lsalen;
+    /* LSA header in network order */
+    lsa_n = ((void *) pkt) + offset;
+    lsa_len = ntohs(lsa_n->length);
+    offset += lsa_len;
  
-    if ((offset > plen) || ((lsalen % 4) != 0) ||
-       (lsalen <= sizeof(struct ospf_lsa_header)))
+    if ((offset > plen) || ((lsa_len % 4) != 0) ||
+       (lsa_len <= sizeof(struct ospf_lsa_header)))
     {
-      log(L_WARN "OSPF: Received LSA from %I with bad length", n->ip);
+      log(L_WARN "%s: Received LSA from %I with bad length", p->name, n->ip);
       ospf_neigh_sm(n, INM_BADLSREQ);
       break;
     }
 
-    /* pg 143 (1) */
-    u16 chsum = lsa->checksum;
-    if (chsum != lsasum_check(lsa, NULL))
+    /* RFC 2328 13. (1) - validate LSA checksum */
+    u16 chsum = lsa_n->checksum;
+    if (chsum != lsasum_check(lsa_n, NULL))
     {
-      log(L_WARN "OSPF: Received LSA from %I with bad checskum: %x %x",
-         n->ip, chsum, lsa->checksum);
+      log(L_WARN "%s: Received LSA from %I with bad checskum: %x %x",
+         p->name, n->ip, chsum, lsa_n->checksum);
       continue;
     }
 
-    u32 lsa_type, lsa_domain;
-    lsa_ntoh_hdr(lsa, &lsatmp);
-    lsa_xxxxtype(lsatmp.type_raw, ifa, &lsa_type, &lsa_domain);
+    /* LSA header in host order */
+    lsa_ntoh_hdr(lsa_n, &lsa);
+    lsa_xxxxtype(lsa.type_raw, ifa, &lsa_type, &lsa_domain);
+
+    DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
+       lsa_type, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum);
 
-    /* pg 143 (2) */
+    /* RFC 2328 13. (2) */
     if (!lsa_type)
     {
-      log(L_WARN "OSPF: Received unknown LSA type from %I", n->ip);
+      log(L_WARN "%s: Received unknown LSA type from %I", p->name, n->ip);
       continue;
     }
 
-    /* 4.5.1 (2) */
+    /* RFC 5340 4.5.1 (2) and RFC 2328 13. (3) */
     if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
     {
-      log(L_WARN "OSPF: Received LSA with AS scope in stub area from %I", n->ip);
+      log(L_WARN "%s: Received LSA with AS scope in stub area from %I", p->name, n->ip);
       continue;
     }
 
-    /* 4.5.1 (3) */
+    /* RFC 5340 4.5.1 (3) */
     if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
     {
-      log(L_WARN "OSPF: Received LSA with invalid scope from %I", n->ip);
+      log(L_WARN "%s: Received LSA with invalid scope from %I", p->name, n->ip);
       continue;
     }
 
-    DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
-       lsa_type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
-
-    lsadb = ospf_hash_find(po->gr, lsa_domain, lsatmp.id, lsatmp.rt, lsa_type);
+    /* Find local copy of LSA in link state database */
+    en = ospf_hash_find(po->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
 
 #ifdef LOCAL_DEBUG
-    if (lsadb)
+    if (en)
       DBG("I have Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
-         lsadb->lsa_type, lsadb->lsa.id, lsadb->lsa.rt,
-         lsadb->lsa.sn, lsadb->lsa.age, lsadb->lsa.checksum);
+         en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age, en->lsa.checksum);
 #endif
 
-    /* pg 143 (4) */
-    if ((lsatmp.age == LSA_MAXAGE) && (lsadb == NULL) && can_flush_lsa(po))
+    /* 13. (4) - ignore maxage LSA if i have no local copy */
+    if ((lsa.age == LSA_MAXAGE) && !en && can_flush_lsa(po))
     {
-      ospf_lsack_enqueue(n, lsa, ACKL_DIRECT);
+      ospf_lsack_enqueue(n, lsa_n, ACKL_DIRECT);
       continue;
     }
 
-    /* pg 144 (5) */
-    if ((lsadb == NULL) || (lsa_comp(&lsatmp, &lsadb->lsa) == CMP_NEWER))
+    int cmp =  : CMP_NEWER;
+
+    /* 13. (5) - received LSA is newer (or no local copy) */
+    if (!en || (lsa_comp(&lsa, &en->lsa) == CMP_NEWER))
     {
       struct ospf_iface *ift = NULL;
-      int self = (lsatmp.rt == po->router_id);
-
-      DBG("PG143(5): Received LSA is newer\n");
+      int self = (lsa.rt == po->router_id);
 
 #ifdef OSPFv2
       /* 13.4 - check self-originated LSAs of NET type */
@@ -494,7 +234,7 @@ ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
        {
          if (!nifa->iface)
            continue;
-         if (ipa_equal(nifa->addr->ip, ipa_from_u32(lsatmp.id)))
+         if (ipa_equal(nifa->addr->ip, ipa_from_u32(lsa.id)))
          {
            self = 1;
            break;
@@ -506,102 +246,101 @@ ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
       /* pg 145 (5f) - premature aging of self originated lsa */
       if (self)
       {
-       if ((lsatmp.age == LSA_MAXAGE) && (lsatmp.sn == LSA_MAXSEQNO))
+       if ((lsa.age == LSA_MAXAGE) && (lsa.sn == LSA_MAXSEQNO))
        {
-         ospf_lsack_enqueue(n, lsa, ACKL_DIRECT);
+         ospf_lsack_enqueue(n, lsa_n, ACKL_DIRECT);
          continue;
        }
 
        OSPF_TRACE(D_EVENTS, "Received old self-originated LSA (Type: %04x, Id: %R, Rt: %R)",
-                  lsa_type, lsatmp.id, lsatmp.rt);
+                  lsa_type, lsa.id, lsa.rt);
 
-       if (lsadb)
+       if (en)
        {
          OSPF_TRACE(D_EVENTS, "Reflooding new self-originated LSA with newer sequence number");
-         lsadb->lsa.sn = lsatmp.sn + 1;
-         lsadb->lsa.age = 0;
-         lsadb->inst_t = now;
-         lsadb->ini_age = 0;
-         lsasum_calculate(&lsadb->lsa, lsadb->lsa_body);
-         ospf_lsupd_flood(po, NULL, NULL, &lsadb->lsa, lsa_domain, 1);
+         en->lsa.sn = lsa.sn + 1;
+         en->lsa.age = 0;
+         en->inst_t = now;
+         en->ini_age = 0;
+         lsasum_calculate(&en->lsa, en->lsa_body);
+         ospf_lsupd_flood(po, NULL, NULL, &en->lsa, lsa_domain, 1);
        }
        else
        {
          OSPF_TRACE(D_EVENTS, "Premature aging it");
-         lsatmp.age = LSA_MAXAGE;
-         lsatmp.sn = LSA_MAXSEQNO;
-         lsa->age = htons(LSA_MAXAGE);
-         lsa->sn = htonl(LSA_MAXSEQNO);
-         lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
-         lsatmp.checksum = ntohs(lsa->checksum);
-         ospf_lsupd_flood(po, NULL, lsa, &lsatmp, lsa_domain, 0);
+         lsa.age = LSA_MAXAGE;
+         lsa.sn = LSA_MAXSEQNO;
+         lsa_n->age = htons(LSA_MAXAGE);
+         lsa_n->sn = htonl(LSA_MAXSEQNO);
+         lsasum_check(lsa_n, (lsa_n + 1));     /* It also calculates chsum! */
+         lsa.checksum = ntohs(lsa_n->checksum);
+         ospf_lsupd_flood(po, NULL, lsa_n, &lsa, lsa_domain, 0);
        }
        continue;
       }
 
       /* pg 144 (5a) */
-      if (lsadb && ((now - lsadb->inst_t) <= MINLSARRIVAL))    /* FIXME: test for flooding? */
+      if (en && ((now - en->inst_t) <= MINLSARRIVAL))  /* FIXME: test for flooding? */
       {
        OSPF_TRACE(D_EVENTS, "Skipping LSA received in less that MINLSARRIVAL");
        sendreq = 0;
        continue;
       }
 
-      /* Remove old from all ret lists */
-      /* pg 144 (5c) */
+      /* 13. (5c) - remove old LSA from all retransmission lists */
       /* Must be done before (5b), otherwise it also removes the new entries from (5b) */
-      if (lsadb)
+      if (en)
        WALK_LIST(ift, po->iface_list)
          WALK_LIST(ntmp, ift->neigh_list)
       {
-       struct top_hash_entry *en;
+       struct top_hash_entry *ret;
        if (ntmp->state > NEIGHBOR_EXSTART)
-         if ((en = ospf_hash_find_header(ntmp->lsrth, lsa_domain, &lsadb->lsa)) != NULL)
+         if ((ret = ospf_hash_find_header(ntmp->lsrth, lsa_domain, &en->lsa)) != NULL)
          {
-           s_rem_node(SNODE en);
-           ospf_hash_delete(ntmp->lsrth, en);
+           s_rem_node(SNODE ret);
+           ospf_hash_delete(ntmp->lsrth, ret);
          }
       }
 
       /* pg 144 (5b) */
-      if (ospf_lsupd_flood(po, n, lsa, &lsatmp, lsa_domain, 1) == 0)
+      if (ospf_lsupd_flood(po, n, lsa_n, &lsa, lsa_domain, 1) == 0)
       {
        DBG("Wasn't flooded back\n");   /* ps 144(5e), pg 153 */
        if (ifa->state == OSPF_IS_BACKUP)
        {
          if (ifa->drid == n->rid)
-           ospf_lsack_enqueue(n, lsa, ACKL_DELAY);
+           ospf_lsack_enqueue(n, lsa_n, ACKL_DELAY);
        }
        else
-         ospf_lsack_enqueue(n, lsa, ACKL_DELAY);
+         ospf_lsack_enqueue(n, lsa_n, ACKL_DELAY);
       }
 
-      if ((lsatmp.age == LSA_MAXAGE) && (lsatmp.sn == LSA_MAXSEQNO)
-         && lsadb && can_flush_lsa(po))
+      if ((lsa.age == LSA_MAXAGE) && (lsa.sn == LSA_MAXSEQNO)
+         && en && can_flush_lsa(po))
       {
-       flush_lsa(lsadb, po);
+       flush_lsa(en, po);
        schedule_rtcalc(po);
        continue;
       }                                /* FIXME lsack? */
 
       /* pg 144 (5d) */
-      void *body = mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
-      lsa_ntoh_body(lsa + 1, body, lsatmp.length - sizeof(struct ospf_lsa_header));
+      void *body = mb_alloc(p->pool, lsa.length - sizeof(struct ospf_lsa_header));
+      lsa_ntoh_body(lsa_n + 1, body, lsa.length - sizeof(struct ospf_lsa_header));
 
       /* We will do validation check after flooding and
         acknowledging given LSA to minimize problems
         when communicating with non-validating peer */
-      if (lsa_validate(&lsatmp, lsa_type, ospf_is_v2(po), body) == 0)
+      if (lsa_validate(&lsa, lsa_type, ospf_is_v2(po), body) == 0)
       {
        log(L_WARN "Received invalid LSA from %I", n->ip);
        mb_free(body);
        continue;       
       }
 
-      lsadb = lsa_install_new(po, &lsatmp, lsa_domain, body);
+      en = lsa_install_new(po, &lsa, lsa_domain, body);
       DBG("New LSA installed in DB\n");
 
-      /* Events 6,7 from RFC5340 4.4.3. */
+      /* Events 6,7 from RFC 5340 4.4.3. */
       if ((lsa_type == LSA_T_LINK) && (ifa->state == OSPF_IS_DR))
        schedule_net_lsa(ifa);
 
@@ -610,45 +349,41 @@ ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
     /* FIXME pg145 (6) */
 
-    /* pg145 (7) */
-    if (lsa_comp(&lsatmp, &lsadb->lsa) == CMP_SAME)
+    /* 13. (7) - received LSA is same */
+    if (lsa_comp(&lsa, &en->lsa) == CMP_SAME)
     {
-      struct top_hash_entry *en;
-      DBG("PG145(7) Got the same LSA\n");
-      if ((en = ospf_hash_find_header(n->lsrth, lsadb->domain, &lsadb->lsa)) != NULL)
+      ret = ospf_hash_find_entry(n->lsrth, en);
+      if (ret)
       {
        /* pg145 (7a) */
-       s_rem_node(SNODE en);
-       ospf_hash_delete(n->lsrth, en);
+       s_rem_node(SNODE ret);
+       ospf_hash_delete(n->lsrth, ret);
 
        if (ifa->state == OSPF_IS_BACKUP)
        {
          if (n->rid == ifa->drid)
-           ospf_lsack_enqueue(n, lsa, ACKL_DELAY);
+           ospf_lsack_enqueue(n, lsa_n, ACKL_DELAY);
        }
       }
       else
       {
        /* pg145 (7b) */
-       ospf_lsack_enqueue(n, lsa, ACKL_DIRECT);
+       ospf_lsack_enqueue(n, lsa_n, ACKL_DIRECT);
       }
       sendreq = 0;
       continue;
     }
 
-    /* pg145 (8) */
-    if ((lsadb->lsa.age == LSA_MAXAGE) && (lsadb->lsa.sn == LSA_MAXSEQNO))
+    /* 13. (8) - received LSA is older */
     {
-      continue;
-    }
+      /* Seqnum is wrapping, wait until it is flushed */
+      if ((en->lsa.age == LSA_MAXAGE) && (en->lsa.sn == LSA_MAXSEQNO))
+       continue;
 
-    struct ospf_lsreq_item lsr = {
-      .domain = lsadb->domain,
-      .type = lsadb->lsa_type,
-      .id = lsadb->lsa.id,
-      .rt = lsadb->lsa.rt
-    };
-    ospf_lsupd_send_list(n, &lsr);
+      /* Send newer local copy back to neighbor */
+      /* FIXME - check for MinLSArrival ? */
+      ospf_lsupd_send(n, &en, 1);
+    }
   }
 
   /* Send direct LSAs */
@@ -660,15 +395,251 @@ ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
   }
 }
 
+
+/**
+ * ospf_lsupd_flood - send received or generated LSA to the neighbors
+ * @po: OSPF protocol
+ * @en: LSA entry
+ * @from: neighbor than sent this LSA (or NULL if LSI is local)
+ *
+ * return value - was the LSA flooded back?
+ */
+
+int
+ospf_lsupd_flood(struct proto_ospf *po, struct top_hash_entry *en, struct ospf_neighbor *from)
+{
+  struct ospf_iface *ifa;
+  struct ospf_neighbor *n;
+
+  int back = 0;
+  WALK_LIST(ifa, po->iface_list)
+  {
+    if (ifa->stub)
+      continue;
+
+    if (! lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
+      continue;
+
+    DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
+       hh->type, hh->id, hh->rt, hh->sn, hh->age);
+
+    int used = 0;
+    WALK_LIST(n, ifa->neigh_list)
+    {
+      /* 13.3 (1a) */
+      if (n->state < NEIGHBOR_EXCHANGE)
+       continue;
+
+      /* 13.3 (1b) */
+      if (n->state < NEIGHBOR_FULL)
+      {
+       struct top_hash_entry *req = ospf_hash_find_entry(n->lsrqh, en);
+       if (req != NULL)
+       {
+         int cmp = lsa_comp(&en->lsa, &req->lsa);
+
+         /* If same or newer, remove LSA from the link state request list */
+         if (cmp > CMP_OLDER)
+         {
+           s_rem_node(SNODE req);
+           ospf_hash_delete(n->lsrqh, req);
+           if (EMPTY_SLIST(n->lsrql))
+             ospf_neigh_sm(n, INM_LOADDONE);
+         }
+
+         /* If older or same, skip processing of this LSA */
+         if (cmp < CMP_NEWER)
+           continue;
+       }
+      }
+
+      /* 13.3 (1c) */
+      if (n == from)
+       continue;
+
+      /* In OSPFv3, there should be check whether receiving router understand
+        that type of LSA (for LSA types with U-bit == 0). But as we do not support
+        any optional LSA types, this is not needed yet */
+
+      /* 13.3 (1d) - add LSA to the link state retransmission list */
+      {
+       struct top_hash_entry *ret = ospf_hash_get_entry(n->lsrth, en);
+       if (! ospf_hash_is_new(ret))
+         s_rem_node(SNODE ret);
+
+       s_add_tail(&n->lsrtl, SNODE ret);
+       memcpy(&ret->lsa, hh, sizeof(struct ospf_lsa_header));
+      }
+
+      used = 1;
+    }
+
+    /* 13.3 (2) */
+    if (!used)
+      continue;
+
+    if (from && (from->ifa == ifa))
+    {
+      /* 13.3 (3) */
+      if ((from->rid == ifa->drid) || from->rid == ifa->bdrid)
+       continue;
+
+      /* 13.3 (4) */
+      if (ifa->state == OSPF_IS_BACKUP)
+       continue;
+
+      back = 1;
+    }
+
+    /* 13.3 (5) - finally flood the packet */
+    ospf_lsupd_flood_ifa(po, ifa, en);
+  }
+
+  return back;
+}
+
+static int
+ospf_lsupd_prepare(struct proto_ospf *po, struct ospf_iface *ifa,
+                  struct top_hash_entry **lsa_list, unsigned lsa_count)
+{
+  struct ospf_packet *pkt;
+  unsigned hlen, pos, i, maxsize;
+
+  pkt = ospf_tx_buffer(ifa);
+  hlen = ospf_lsupd_hdrlen(po);
+  maxsize = ospf_pkt_maxsize(ifa);
+
+  ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
+  pos = hlen;
+
+  for (i = 0; i < lsa_count; i++)
+  {
+    struct top_hash_entry *en = lsa_list[i];
+    unsigned len = en->lsa.length;
+
+    if ((pos + len) > maxsize)
+    {
+      /* The packet if full, stop adding LSAs and sent it */
+      if (i > 0)
+       break;
+
+      /* LSA is larger than MTU, check buffer size */
+      if ((pos + len) > ospf_pkt_bufsize(ifa))
+      {
+       /* Cannot fit in a tx buffer, skip that */
+       log(L_WARN "OSPF: LSA too large to send (Type: %04x, Id: %R, Rt: %R)", 
+           en->lsa_type, en->lsa.id, en->lsa.rt);
+       XXXX();
+       continue;
+      }
+    }
+
+    struct ospf_lsa_header *buf = ((void *) pkt) + pos;
+    lsa_hton_hdr(&en->lsa, buf);
+    lsa_hton_body(en->lsa_body, ((void *) buf) + sizeof(struct ospf_lsa_header),
+                 len - sizeof(struct ospf_lsa_header));
+    buf->age = htons(MIN(en->lsa.age + ifa->inftransdelay, LSA_MAXAGE));
+
+    pos += len;
+  }
+   
+  ospf_lsupd_set_lsa_count(pkt, hlen, i);
+  pkt->length = htons(pos);
+
+  return i;
+}
+
+
+static void
+ospf_lsupd_flood_ifa(struct proto_ospf *po, struct ospf_iface *ifa, struct top_hash_entry *en)
+{
+  ospf_lsupd_prepare(po, ifa, &en, 1);
+
+  OSPF_PACKET(ospf_lsupd_dump, ospf_tx_buffer(ifa),
+             "LSUPD packet flooded via %s", ifa->iface->name);
+
+  switch (ifa->type)
+  {
+  case OSPF_IT_BCAST:
+    if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
+      ospf_send_to_all(ifa);
+    else
+      ospf_send_to_des(ifa);
+    break;
+
+  case OSPF_IT_NBMA:
+    if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
+      ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
+    else
+      ospf_send_to_bdr(ifa);
+    break;
+
+  case OSPF_IT_PTP:
+    ospf_send_to_all(ifa);
+    break;
+
+  case OSPF_IT_PTMP:
+    ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
+    break;
+
+  case OSPF_IT_VLINK:
+    ospf_send_to(ifa, ifa->vip);
+    break;
+
+  default:
+    bug("Bug in ospf_lsupd_flood()");
+  }
+}
+
+int
+ospf_lsupd_send(struct ospf_neighbor *n, struct top_hash_entry **lsa_list, unsigned lsa_count)
+{
+  struct ospf_iface *ifa = n->ifa;
+  struct proto_ospf *po = ifa->oa->po;
+  unsigned i, c;
+
+  for (i = 0; i < lsa_count; i += c)
+  {
+    c = ospf_lsupd_prepare(po, ifa, lsa_list + i, lsa_count - i);
+
+    OSPF_PACKET(ospf_lsupd_dump, ospf_tx_buffer(ifa),
+               "LSUPD packet sent to %I via %s", n->ip, ifa->iface->name);
+
+    ospf_send_to(ifa, n->ip);
+  }
+
+  return lsa_count;
+}
+
 void
-ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en)
+ospf_lsupd_rxmt(struct ospf_neighbor *n)
 {
-  struct ospf_lsa_header *lsa = &en->lsa;
-
-  lsa->age = LSA_MAXAGE;
-  lsa->sn = LSA_MAXSEQNO;
-  lsasum_calculate(lsa, en->lsa_body);
-  OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!");
-  OSPF_TRACE(D_EVENTS, "Type: %04x, Id: %R, Rt: %R", en->lsa_type, lsa->id, lsa->rt);
-  ospf_lsupd_flood(po, NULL, NULL, lsa, en->domain, 0);
+  struct proto_ospf *po = n->ifa->oa->po;
+
+  const unsigned max = 128;
+  struct top_hash_entry *entries[max];
+  struct top_hash_entry *ret, *en;
+  unsigned i = 0;
+
+  WALK_SLIST(ret, n->lsrtl)
+  {
+    en = ospf_hash_find_entry(po->gr, ret);
+    if (!en)
+    {
+      /* Probably flushed LSA, this should not happen */
+      log(L_WARN "%s: LSA disappeared (Type: %04x, Id: %R, Rt: %R)",
+         po->proto.name, ret->lsa_type, ret->lsa.id, ret->lsa.rt);
+
+      XXXX(); /* remove entry */
+      continue;
+    }
+
+    entries[i] = en;
+    i++;
+
+    if (i == max)
+      break;
+  }
+
+  ospf_lsupd_send(n, entries, i);
 }
index 476775e28185c6948426e2b8640e258db286615a..0c7a1ef17585ffc623ce5b1d1f297126032746df 100644 (file)
 
 void ospf_dump_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n);
 void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt);
-void ospf_lsupd_send_list(struct ospf_neighbor *n, struct ospf_lsreq_item *lsr);
-void ospf_lsupd_receive(struct ospf_packet *ps_i,
-                       struct ospf_iface *ifa, struct ospf_neighbor *n);
-int ospf_lsupd_flood(struct proto_ospf *po,
-                    struct ospf_neighbor *n, struct ospf_lsa_header *hn,
-                    struct ospf_lsa_header *hh, u32 domain, int rtl);
-void ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en);
-int ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa);
+void ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, struct ospf_neighbor *n);
+int ospf_lsupd_flood(struct proto_ospf *po, struct top_hash_entry *en, struct ospf_neighbor *from);
+int ospf_lsupd_send(struct ospf_neighbor *n, struct top_hash_entry **lsa_list, unsigned lsa_count);
 
 
 #endif /* _BIRD_OSPF_LSUPD_H_ */
index 228e02d282aab5edd7d194eb8565f90dd16e3f5c..8d7abc9518a87ab280adbc91c8a420c6fe8ab3e6 100644 (file)
@@ -600,51 +600,30 @@ rxmt_timer_hook(timer * timer)
   // struct proto *p = &n->ifa->oa->po->proto;
   struct top_hash_entry *en;
 
-  DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
+  DBG("%s: RXMT timer fired on interface %s for neigh %I\n",
       p->name, n->ifa->iface->name, n->ip);
 
-  if(n->state < NEIGHBOR_EXSTART) return;
-
-  if (n->state == NEIGHBOR_EXSTART)
+  switch (n->state)
   {
+  case NEIGHBOR_EXSTART:
     ospf_dbdes_send(n, 1);
     return;
-  }
 
-  if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS))       /* I'm master */
+  case NEIGHBOR_EXCHANGE:
+  if (n->myimms & DBDES_MS)
     ospf_dbdes_send(n, 0);
+  case NEIGHBOR_LOADING:
+    ospf_lsreq_send(n);
+    return;
 
+  case NEIGHBOR_FULL:
+    /* LSA retransmissions */
+    if (!EMPTY_SLIST(n->lsrtl))
+      ospf_lsupd_rxmt(n);
+    return;
 
-  if (n->state < NEIGHBOR_FULL)        
-    ospf_lsreq_send(n);        /* EXCHANGE or LOADING */
-  else
-  {
-    if (!EMPTY_SLIST(n->lsrtl))        /* FULL */
-    {
-      struct ospf_lsreq_item *lsr_head, *lsr;
-      struct ospf_lsreq_item **lsr_pos = &lsr_head;
-
-      slab *upslab = sl_new(n->pool, sizeof(struct ospf_lsreq_item));
-
-      WALK_SLIST(en, n->lsrtl)
-      {
-       if ((SNODE en)->next == (SNODE en))
-         bug("RTList is cycled");
-
-       lsr = sl_alloc(upslab);
-       lsr->domain = en->domain;
-       lsr->type = en->lsa_type;
-       lsr->id = en->lsa.id;
-       lsr->rt = en->lsa.rt;
-
-       *lsr_pos = lsr;
-       lsr_pos = &(lsr->next);
-      }
-      *lsr_pos = NULL;
-
-      ospf_lsupd_send_list(n, lsr_head);
-      rfree(upslab);
-    }
+  default:
+    return;
   }
 }
 
index 4dbf27c5bc2b2d8e7a9cda17626c90b3396a289e..146d07f61b76fa196e5cd886a9c833b8bcfe6702 100644 (file)
@@ -586,15 +586,6 @@ struct ospf_lsreq_header
   u32 rt;
 };
 
-struct ospf_lsreq_item
-{
-  struct ospf_lsreq_item *next;
-  u32 domain;
-  u32 type;
-  u32 id;
-  u32 rt;
-};
-
 
 struct ospf_neighbor
 {
index cb5b4e96d80713b572e3ed13e5bc67a250b02e16..f02ddc7b5de7de33557591893fa613fb40fd0d78 100644 (file)
@@ -429,23 +429,23 @@ void
 originate_rt_lsa(struct ospf_area *oa)
 {
   struct proto_ospf *po = oa->po;
-  struct ospf_lsa_header lsa;
-  u32 dom = oa->areaid;
-  void *body;
+  struct ospf_lsa_new lsa;
 
   OSPF_TRACE(D_EVENTS, "Originating router-LSA for area %R", oa->areaid);
 
-  lsa.age = 0;
-  lsa.type_raw = LSA_T_RT;
-  lsa.id = ospf_is_v2(po) ? po->router_id : 0;
-  lsa.rt = po->router_id;
-  lsa.sn = get_seqnum(oa->rt);
-  lsa_fix_options(po, &lsa, oa->options);
+  lsa.type = LSA_T_RT;
+  lsa.dom  = oa->areaid;
+  lsa.id   = ospf_is_v2(po) ? po->router_id : 0;
+  lsa.opts = oa->options;
+  lsa.body = originate_rt_lsa_body(po, oa, &lsa.length);
 
-  body = originate_rt_lsa_body(po, oa, &lsa.length);
-  lsasum_calculate(&lsa, body);
-  oa->rt = lsa_install_new(po, &lsa, dom, body);
-  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  ospf_originate_lsa(po, &lsa, &oa->rt);
+
+  // lsa.rt   = po->router_id;
+  // lsa_fix_options(po, &lsa, oa->options);
+  // lsasum_calculate(&lsa, body);
+  // ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  // lsa_install_new(po, &lsa, oa->rt);
 }
 
 void
@@ -559,24 +559,17 @@ void
 originate_net_lsa(struct ospf_iface *ifa)
 {
   struct proto_ospf *po = ifa->oa->po;
-  struct ospf_lsa_header lsa;
-  u32 dom = ifa->oa->areaid;
-  void *body;
+  struct ospf_lsa_new lsa;
 
-  OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s",
-            ifa->iface->name);
+  OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s", ifa->iface->name);
 
-  lsa.age = 0;
-  lsa.type_raw = LSA_T_NET;
-  lsa.id = ospf_is_v2(po) ? ipa_to_u32(ifa->addr->ip) : ifa->iface_id;
-  lsa.rt = po->router_id;
-  lsa.sn = get_seqnum(ifa->net_lsa);
-  lsa_fix_options(po, &lsa, ifa->oa->options);
+  lsa.type = LSA_T_NET;
+  lsa.dom  = ifa->oa->areaid;
+  lsa.id   = ospf_is_v2(po) ? ipa_to_u32(ifa->addr->ip) : ifa->iface_id;
+  lsa.opts = ifa->oa->options;
+  lsa.body = originate_net_lsa_body(po, ifa, &lsa.length);
 
-  body = originate_net_lsa_body(po, ifa, &lsa.length);
-  lsasum_calculate(&lsa, body);
-  ifa->net_lsa = lsa_install_new(po, &lsa, dom, body);
-  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  ifa->net_lsa = ospf_originate_lsa(po, &lsa, ifa->net_lsa);
 }
 
 void
@@ -755,89 +748,76 @@ void
 originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric)
 {
   struct proto_ospf *po = oa->po;
-  struct ospf_lsa_header lsa;
+  struct ospf_lsa_new lsa;
   struct top_hash_entry *en;
-  u32 dom = oa->areaid;
-  void *body;
 
-  OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)",
-            fn->prefix, fn->pxlen, metric);
+  OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)", fn->prefix, fn->pxlen, metric);
 
-  lsa.age = 0;
-  lsa.type_raw = LSA_T_SUM_NET;
-  lsa.id = fibnode_to_lsaid(po, fn);
-  lsa.rt = po->router_id;
-  lsa_fix_options(po, &lsa, oa->options);
+  lsa.type = LSA_T_SUM_NET;
+  lsa.dom  = oa->areaid;
+  lsa.id   = fibnode_to_lsaid(po, fn);
+  lsa.opts = oa->options;
 
-  en = ospf_hash_find_header(po->gr, dom, &lsa);
+  en = ospf_hash_find(po->gr, lsa.dom, lsa.id, po->router_id, lsa.type);
   if (en && check_sum_net_lsa(po, en, fn, metric))
     return;
-  lsa.sn = get_seqnum(en);
 
-  body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
-  lsasum_calculate(&lsa, body);
-  lsa_install_new(po, &lsa, dom, body);
-  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  lsa.body = originate_sum_net_lsa_body(po, &lsa.length, fn, metric);
+
+  ospf_originate_lsa(po, &lsa, en);
 }
 
 void
 originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options)
 {
   struct proto_ospf *po = oa->po;
-  struct ospf_lsa_header lsa;
+  struct ospf_lsa_new lsa;
   struct top_hash_entry *en;
   u32 rid = ipa_to_rid(fn->prefix);
-  u32 dom = oa->areaid;
-  void *body;
 
-  OSPF_TRACE(D_EVENTS, "Originating rt-summary-LSA for %R (metric %d)",
-            rid, metric);
+  OSPF_TRACE(D_EVENTS, "Originating rt-summary-LSA for %R (metric %d)", rid, metric);
 
-  lsa.age = 0;
-  lsa.type_raw = LSA_T_SUM_RT;
-  lsa.id = rid;                /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
-  lsa.rt = po->router_id;
-  lsa_fix_options(po, &lsa, oa->options);
+  lsa.type = LSA_T_SUM_RT;
+  lsa.dom  = oa->areaid;
+  lsa.id   = rid;      /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
+  lsa.opts = oa->options;
 
   options &= OPTIONS_MASK;
 
-  en = ospf_hash_find_header(po->gr, dom, &lsa);
+  en = ospf_hash_find(po->gr, lsa.dom, lsa.id, po->router_id, lsa.type);
   if (en && check_sum_rt_lsa(po, en, rid, metric, options))
     return;
-  lsa.sn = get_seqnum(en);
 
-  body = originate_sum_rt_lsa_body(po, &lsa.length, rid, metric, options);
-  lsasum_calculate(&lsa, body);
-  lsa_install_new(po, &lsa, dom, body);
-  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  lsa.body = originate_sum_rt_lsa_body(po, &lsa.length, rid, metric, options);
+
+  ospf_originate_lsa(po, &lsa, en);
 }
 
 void
 flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
 {
   struct proto_ospf *po = oa->po;
-  struct ospf_lsa_header lsa;
   struct top_hash_entry *en;
-  u32 dom = oa->areaid;
+  u32 dom, lsid, type;
 
-  lsa.rt = po->router_id;
   if (type == ORT_NET)
-    {
-      lsa.id = fibnode_to_lsaid(po, fn);
-      lsa.type_raw = LSA_T_SUM_NET;
-    }
+  {
+    dom  = oa->areaid;
+    type = LSA_T_SUM_NET;
+    lsid = fibnode_to_lsaid(po, fn);
+  }
   else
-    {
-      /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
-      lsa.id = ipa_to_rid(fn->prefix);
-      lsa.type_raw = LSA_T_SUM_RT;
-    }
+  {
+    /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */
+    dom  = oa->areaid;
+    type = LSA_T_SUM_RT;
+    lsid = ipa_to_rid(fn->prefix);
+  }
 
-  en = ospf_hash_find_header(po->gr, dom, &lsa);
+  en = ospf_hash_find(po->gr, dom, lsid, po->router_id, type);
   if (en)
     {
-      OSPF_TRACE(D_EVENTS, "Flushing summary-LSA (id=%R, type=%d)",
-                en->lsa.id, en->lsa.type_raw);
+      OSPF_TRACE(D_EVENTS, "Flushing summary-LSA (id=%R, type=%x)", lsid, type);
 
       if ((type == ORT_NET) && (check_sum_net_lsa(po, en, fn, 0) < 0))
        return;
@@ -1061,42 +1041,45 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
                  u32 metric, ip_addr fwaddr, u32 tag, int pbit)
 {
   struct proto_ospf *po = oa->po;
-  struct proto *p = &po->proto;
-  struct ospf_lsa_header lsa;
+  struct ospf_lsa_new lsa;
   struct top_hash_entry *en;
   int nssa = oa_is_nssa(oa);
-  u32 dom = nssa ? oa->areaid : 0;
-  void *body;
 
   OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
             nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
 
-  lsa.age = 0;
-  lsa.type_raw = nssa ? LSA_T_NSSA : LSA_T_EXT;
-  lsa.id = fibnode_to_lsaid(po, fn);
-  lsa.rt = po->router_id;
-  lsa_fix_options(po, &lsa, nssa ? (pbit ? OPT_P : 0) : OPT_E);
-
-  if (nssa && pbit && ipa_zero(fwaddr))
+  if (! nssa)
   {
-    /* NSSA-LSA with P-bit set must have non-zero forwarding address */
+    lsa.type = LSA_T_EXT;
+    lsa.dom  = 0;
+    lsa.id   = fibnode_to_lsaid(po, fn);
+    lsa.opts = OPT_E;
+  }
+  else
+  {
+    lsa.type = LSA_T_NSSA;
+    lsa.dom  = oa->areaid;
+    lsa.id   = fibnode_to_lsaid(po, fn);
+    lsa.opts = pbit ? OPT_P : 0;
 
-    fwaddr = find_surrogate_fwaddr(oa);
-    if (ipa_zero(fwaddr))
+    /* NSSA-LSA with P-bit set must have non-zero forwarding address */
+    if (pbit && ipa_zero(fwaddr))
     {
-      log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %I/%d",
-         p->name, fn->prefix, fn->pxlen);
-      return;
+      fwaddr = find_surrogate_fwaddr(oa);
+      if (ipa_zero(fwaddr))
+      {
+       log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %I/%d",
+           po->proto.name, fn->prefix, fn->pxlen);
+       return;
+      }
     }
   }
 
-  en = ospf_hash_find_header(po->gr, dom, &lsa);
+  en = ospf_hash_find(po->gr, lsa.dom, lsa.id, po->router_id, lsa.type);
   if (en && check_ext_lsa(po, en, fn, metric, fwaddr, tag))
     return;
-  lsa.sn = get_seqnum(en);
 
-  body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit);
-  lsasum_calculate(&lsa, body);
+  lsa.body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit);
 
   if (src)
   {
@@ -1104,8 +1087,7 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
     fn->flags |= src;
   }
 
-  lsa_install_new(po, &lsa, dom, body);
-  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  ospf_originate_lsa(po, &lsa, en);
 
   if (po->ebit == 0)
   {
@@ -1126,20 +1108,16 @@ flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, int nssa)
 
   u32 dom = nssa ? oa->areaid : 0;
   u32 type = nssa ? LSA_T_NSSA : LSA_T_EXT;
-  u32 lsaid = fibnode_to_lsaid(po, fn);
+  u32 lsid = fibnode_to_lsaid(po, fn);
 
-  en = ospf_hash_find(po->gr, dom, lsaid, po->router_id, type);
+  en = ospf_hash_find(po->gr, dom, lsid, po->router_id, type);
   if (en)
     {
       OSPF_TRACE(D_EVENTS, "Flushing %s-LSA for %I/%d",
                 nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
 
       if (check_ext_lsa(po, en, fn, 0, IPA_NONE, 0) < 0)
-       {
-         log(L_ERR "%s: LSAID collision for %I/%d",
-             p->name, fn->prefix, fn->pxlen);
-         return;
-       }
+       return;
 
       /* Clean up source bits */
       if (src) // XXXX ???
@@ -1192,22 +1170,17 @@ originate_link_lsa(struct ospf_iface *ifa)
 {
   struct proto_ospf *po = ifa->oa->po;
   struct ospf_lsa_header lsa;
-  u32 dom = ifa->iface_id;
-  void *body;
 
   /* FIXME check for vlink and skip that? */
   OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->iface->name);
 
-  lsa.age = 0;
-  lsa.type_raw = LSA_T_LINK;
-  lsa.id = ifa->iface_id;
-  lsa.rt = po->router_id;
-  lsa.sn = get_seqnum(ifa->link_lsa);
+  lsa.type = LSA_T_LINK;
+  lsa.dom  = ifa->iface_id;
+  lsa.id   = ifa->iface_id;
+  lsa.opts = 0;
+  lsa.body = originate_link_lsa_body(ifa, &lsa.length);
 
-  body = originate_link_lsa_body(ifa, &lsa.length);
-  lsasum_calculate(&lsa, body);
-  ifa->link_lsa = lsa_install_new(po, &lsa, dom, body);
-  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  ifa->link_lsa = ospf_originate_lsa(po, &lsa, ifa->link_lsa);
 
   /* Just to be sure to not forget on our link LSA */
   if (ifa->state == OSPF_IS_DR)
@@ -1344,21 +1317,16 @@ originate_prefix_rt_lsa(struct ospf_area *oa)
 {
   struct proto_ospf *po = oa->po;
   struct ospf_lsa_header lsa;
-  u32 dom = oa->areaid;
-  void *body;
 
   OSPF_TRACE(D_EVENTS, "Originating router prefix-LSA for area %R", oa->areaid);
 
-  lsa.age = 0;
-  lsa.type_raw = LSA_T_PREFIX;
-  lsa.id = 0;
-  lsa.rt = po->router_id;
-  lsa.sn = get_seqnum(oa->pxr_lsa);
+  lsa.type = LSA_T_PREFIX;
+  lsa.dom  = oa->areaid;
+  lsa.id   = 0;
+  lsa.opts = 0;
+  lsa.body = originate_prefix_rt_lsa_body(oa, &lsa.length);
 
-  body = originate_prefix_rt_lsa_body(oa, &lsa.length);
-  lsasum_calculate(&lsa, body);
-  oa->pxr_lsa = lsa_install_new(po, &lsa, dom, body);
-  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  oa->pxr_lsa = ospf_originate_lsa(po, &lsa, oa->pxr_lsa);
 }
 
 
@@ -1485,23 +1453,17 @@ void
 originate_prefix_net_lsa(struct ospf_iface *ifa)
 {
   struct proto_ospf *po = ifa->oa->po;
-  struct ospf_lsa_header lsa;
-  u32 dom = ifa->oa->areaid;
-  void *body;
+  struct ospf_lsa_new lsa;
 
-  OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s",
-            ifa->iface->name);
+  OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s", ifa->iface->name);
 
-  lsa.age = 0;
-  lsa.type_raw = LSA_T_PREFIX;
-  lsa.id = ifa->iface_id;
-  lsa.rt = po->router_id;
-  lsa.sn = get_seqnum(ifa->pxn_lsa);
+  lsa.type = LSA_T_PREFIX;
+  lsa.dom  = ifa->oa->areaid;
+  lsa.id   = ifa->iface_id;
+  lsa.opts = 0;
+  lsa.body = originate_prefix_net_lsa_body(ifa, &lsa.length);
 
-  body = originate_prefix_net_lsa_body(ifa, &lsa.length);
-  lsasum_calculate(&lsa, body);
-  ifa->pxn_lsa = lsa_install_new(po, &lsa, dom, body);
-  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+  ifa->pxn_lsa = ospf_originate_lsa(po, &lsa, ifa->pxn_lsa);
 }
 
 void
@@ -1638,18 +1600,6 @@ ospf_top_rehash(struct top_graph *f, int step)
   ospf_top_ht_free(oldt);
 }
 
-struct top_hash_entry *
-ospf_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
-{
-  return ospf_hash_find(f, domain, h->id, h->rt, h->type);
-}
-
-struct top_hash_entry *
-ospf_hash_get_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
-{
-  return ospf_hash_get(f, domain, h->id, h->rt, h->type);
-}
-
 struct top_hash_entry *
 ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
 {
@@ -1861,3 +1811,13 @@ can_flush_lsa(struct proto_ospf *po)
 
   return 1;
 }
+
+ospf_originate_lsa(struct proto_ospf *po, struct ospf_lsa_header *lsa)
+{
+  struct ospf_lsa_header hdr;
+
+  lsasum_calculate(&lsa, body);
+  xx = lsa_install_new(po, &lsa, dom, body);
+  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+
+}
index 5858e11a948d843045200cb200d801b568b9df5a..a3c6ffeff7be0955aa8b4bda01d5aa3bda17609c 100644 (file)
@@ -47,18 +47,22 @@ struct top_graph
   unsigned int hash_entries_min, hash_entries_max;
 };
 
+struct ospf_lsa_new
+{
+  u16 type;
+  u32 dom;
+  u32 id;
+  u16 opts;
+  u16 length;
+  void *body;
+
+};
+
 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, u32 domain,
-                                            struct ospf_lsa_header *h);
-struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, u32 domain,
-                                           struct ospf_lsa_header *h);
 
-struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
-struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 domain, 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 update_rt_lsa(struct ospf_area *oa);
 void originate_net_lsa(struct ospf_iface *ifa);
@@ -72,6 +76,17 @@ void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
 void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, u32 metric, ip_addr fwaddr, u32 tag, int pbit);
 void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, int nssa);
 
+
+struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
+struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
+void ospf_hash_delete(struct top_graph *, struct top_hash_entry *);
+
+static inline struct top_hash_entry * ospf_hash_find_entry(struct top_graph *f, struct top_hash_entry *en)
+{ return ospf_hash_find(f, en->domain, en->lsa.id, en->lsa.rt, en->lsa_type); }
+
+static inline struct top_hash_entry * ospf_hash_get_entry(struct top_graph *f, struct top_hash_entry *en)
+{ return ospf_hash_get(f, en->domain, en->lsa.id, en->lsa.rt, en->lsa_type); }
+
 struct top_hash_entry * ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr);
 struct top_hash_entry * ospf_hash_find_rt3_first(struct top_graph *f, u32 domain, u32 rtr);
 struct top_hash_entry * ospf_hash_find_rt3_next(struct top_hash_entry *e);