]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fininshing integrated OSPF.
authorOndrej Zajicek <santiago@crfreenet.org>
Mon, 3 Nov 2014 09:42:55 +0000 (10:42 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 3 Nov 2014 09:42:55 +0000 (10:42 +0100)
14 files changed:
lib/event.c
lib/event.h
proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsack.c
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/topology.c
sysdep/unix/timer.h

index 916cf55c3ac8c5301ac73d57240481c0ebbaf9dc..b429c205820f887061ac1acecb0db5e8ba4a5824 100644 (file)
@@ -27,7 +27,7 @@ event_list global_event_list;
 inline void
 ev_postpone(event *e)
 {
-  if (e->n.next)
+  if (ev_active(e))
     {
       rem_node(&e->n);
       e->n.next = NULL;
index d85004137dbfdf60fa1bbac62b79886a95ddc582..d59752220d00241296e5916157d5a548fc3c0e98 100644 (file)
@@ -30,4 +30,11 @@ void ev_schedule(event *);
 void ev_postpone(event *);
 int ev_run_list(event_list *);
 
+static inline int
+ev_active(event *e)
+{
+  return e->n.next != NULL;
+}
+
+
 #endif
index 88c871641a3d7deea2c6da208813f17a6ae976bd..65bdb3ecc4c5834b9acf0b1d9a4d06c9fc803319 100644 (file)
@@ -212,17 +212,6 @@ ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
 
   ospf_prepare_dbdes(p, n);
   ospf_do_send_dbdes(p, n);
-
-  if (n->state == NEIGHBOR_EXSTART)
-    return;
-
-  /* Master should restart RXMT timer for each DBDES exchange */
-  if (n->myimms & DBDES_MS)
-    tm_start(n->rxmt_timer, n->ifa->rxmtint);
-
-  if (!(n->myimms & DBDES_MS))
-    if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
-      ospf_neigh_sm(n, INM_EXDONE);
 }
 
 void
@@ -277,13 +266,20 @@ ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_ne
     en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
     if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
     {
+      /* This should be splitted to ospf_lsa_lsrq_up() */
       req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
 
       if (!SNODE_VALID(req))
        s_add_tail(&n->lsrql, SNODE req);
 
+      if (!SNODE_VALID(n->lsrqi))
+       n->lsrqi = req;
+
       req->lsa = lsa;
       req->lsa_body = LSA_BODY_DUMMY;
+
+      if (!tm_active(n->lsrq_timer))
+       tm_start(n->lsrq_timer, 0);
     }
   }
 
@@ -306,13 +302,16 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
   u32 rcv_ddseq, rcv_options;
   u16 rcv_iface_mtu;
   u8 rcv_imms;
-  uint plen, err_val = 0, err_seqmis = 0;
+  uint plen, err_val = 0;
 
   /* RFC 2328 10.6 */
 
   plen = ntohs(pkt->length);
   if (plen < ospf_dbdes_hdrlen(p))
-    DROP("too short", plen);
+  {
+    LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
+    return;
+  }
 
   OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname);
 
@@ -366,6 +365,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
       n->options = rcv_options;
       n->myimms &= ~DBDES_MS;
       n->imms = rcv_imms;
+      tm_stop(n->dbdes_timer);
       ospf_neigh_sm(n, INM_NEGDONE);
       ospf_send_dbdes(p, n);
       break;
@@ -381,6 +381,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
       n->ddr = rcv_ddseq - 1;  /* It will be set corectly a few lines down */
       n->imms = rcv_imms;
       ospf_neigh_sm(n, INM_NEGDONE);
+      /* Continue to the NEIGHBOR_EXCHANGE case */
     }
     else
     {
@@ -394,9 +395,6 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
        (rcv_ddseq == n->ddr))
       goto duplicate;
 
-    /* Do INM_SEQMIS during packet error */
-    err_seqmis = 1;
-
     if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
       DROP("MS-bit mismatch", rcv_imms);
 
@@ -422,9 +420,14 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
        return;
 
       if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
+      {
+       tm_stop(n->dbdes_timer);
        ospf_neigh_sm(n, INM_EXDONE);
-      else
-       ospf_send_dbdes(p, n);
+       break;
+      }
+
+      ospf_send_dbdes(p, n);
+      tm_start(n->dbdes_timer, n->ifa->rxmtint);
     }
     else
     {
@@ -440,6 +443,9 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
        return;
 
       ospf_send_dbdes(p, n);
+
+      if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
+       ospf_neigh_sm(n, INM_EXDONE);
     }
     break;
 
@@ -450,8 +456,6 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
        (rcv_ddseq == n->ddr))
       goto duplicate;
 
-    err_seqmis = 1;
-
     DROP("too late for DD exchange", n->state);
 
   default:
@@ -471,7 +475,6 @@ drop:
   LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)",
          n->rid, ifa->ifname, err_dsc, err_val);
 
-  if (err_seqmis)
-    ospf_neigh_sm(n, INM_SEQMIS);
+  ospf_neigh_sm(n, INM_SEQMIS);
   return;
 }
index e8b1c70261756f723723ce25d5225de3186ee20b..50cf1407e88126490883c9fdb6e5b6a7d10c219d 100644 (file)
@@ -304,11 +304,8 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
        nn->found = 1;
     }
 
-    // XXXX format
-    // "ospf1: New neighbor found: 192.168.1.1/fe80:1234:1234:1234:1234 on eth0";
-    // "ospf1: New neighbor found: 192.168.1.1 on eth0 at fe80:1234:1234:1234:1234";
-    // "ospf1: Neighbor 192.168.1.1 on eth0 found, IP adress fe80:1234:1234:1234:1234";
-    OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, ifa->ifname);
+    OSPF_TRACE(D_EVENTS, "New neighbor %R on %s, IP address %I",
+              rcv_rid, ifa->ifname, faddr);
 
     n = ospf_neighbor_new(ifa);
 
index e14f09cb11e46a46015c0c7811662eb21f546bee..4dfb74fb64ccf83aabccae8f580b19b32c424670 100644 (file)
@@ -58,6 +58,12 @@ ifa_bufsize(struct ospf_iface *ifa)
   return MAX(bsize, ifa->tx_length);
 }
 
+static inline uint
+ifa_flood_queue_size(struct ospf_iface *ifa)
+{
+  return ifa->tx_length / 24;
+}
+
 int
 ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
 {
@@ -476,6 +482,9 @@ ospf_iface_add(struct object_lock *lock)
 
     if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
       ifa->wait_timer = tm_new_set(ifa->pool, wait_timer_hook, ifa, 0, 0);
+
+    ifa->flood_queue_size = ifa_flood_queue_size(ifa);
+    ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
   }
 
   /* Do iface UP, unless there is no link and we use link detection */
@@ -679,6 +688,9 @@ ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
   add_tail(&p->iface_list, NODE ifa);
 
   ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
+
+  ifa->flood_queue_size = ifa_flood_queue_size(ifa);
+  ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
 }
 
 static void
@@ -693,6 +705,20 @@ ospf_iface_change_timer(timer *tm, uint val)
     tm_start(tm, val);
 }
 
+static inline void
+ospf_iface_update_flood_queue_size(struct ospf_iface *ifa)
+{
+  uint old_size = ifa->flood_queue_size;
+  uint new_size = ifa_flood_queue_size(ifa);
+
+  if (new_size <= old_size)
+    return;
+
+  ifa->flood_queue_size = new_size;
+  ifa->flood_queue = mb_realloc(ifa->flood_queue, new_size * sizeof(void *));
+  bzero(ifa->flood_queue + old_size, (new_size - old_size) * sizeof(void *));
+}
+
 int
 ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
 {
@@ -739,6 +765,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
               ifname, ifa->rxmtint, new->rxmtint);
 
     ifa->rxmtint = new->rxmtint;
+    /* FIXME: Update neighbors' timers */
   }
 
   /* POLL TIMER */
@@ -874,6 +901,9 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
     /* ifa cannot be vlink */
     ifa->tx_length = ifa_tx_length(ifa);
     update_buffers = 1;
+
+    if (!ifa->stub)
+      ospf_iface_update_flood_queue_size(ifa);
   }
 
   /* RX BUFFER */
@@ -1211,6 +1241,9 @@ ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa)
     sk_set_rbsize(ifa->sk, bsize);
   if (bsize > ifa->sk->tbsize)
     sk_set_tbsize(ifa->sk, bsize);
+
+  if (!ifa->stub)
+    ospf_iface_update_flood_queue_size(ifa);
 }
 
 static void
index e590817e190a21afac5e9b6a557661298f5f9d33..251b5e47c6ff077f2496cd91db7b9b698bc6c224 100644 (file)
@@ -162,23 +162,20 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
     if (lsa_comp(&lsa, &ret->lsa) != CMP_SAME)
     {
-      OSPF_TRACE(D_PACKETS, "Strange LSACK from %I", n->ip);
-      OSPF_TRACE(D_PACKETS, "Type: %04x, Id: %R, Rt: %R",
+      OSPF_TRACE(D_PACKETS, "Strange LSACK from nbr %R on %s", n->rid, ifa->ifname);
+      OSPF_TRACE(D_PACKETS, "    Type: %04x, Id: %R, Rt: %R",
                 lsa_type, lsa.id, lsa.rt);
-      OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seq: %08x, Sum: %04x",
-                ret->lsa.age, ret->lsa.sn, ret->lsa.checksum);
-      OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seq: %08x, Sum: %04x",
-                lsa.age, lsa.sn, lsa.checksum);
+      OSPF_TRACE(D_PACKETS, "    I have: Seq: %08x, Age: %4u, Sum: %04x",
+                ret->lsa.sn, ret->lsa.age, ret->lsa.checksum);
+      OSPF_TRACE(D_PACKETS, "    It has: Seq: %08x, Age: %4u, Sum: %04x",
+                lsa.sn, lsa.age, lsa.checksum);
       continue;
     }
 
-    en = ospf_hash_find_entry(p->gr, ret);
-    if (en)
-      en->ret_count--;
-
     DBG("Deleting LSA (Type: %04x Id: %R Rt: %R) from lsrtl for neighbor %R\n",
        lsa_type, lsa.id, lsa.rt, n->rid);
-    s_rem_node(SNODE ret);
-    ospf_hash_delete(n->lsrth, ret);
+
+    en = ospf_hash_find_entry(p->gr, ret);
+    ospf_lsa_lsrt_down_(en, n, ret);
   }
 }
index 067ad79b2543bb68d2801d1bfd0d24b1f1038eb8..657c024785bb634289c28dca7ed88ec8d73f5d3e 100644 (file)
@@ -54,42 +54,37 @@ ospf_send_lsreq(struct ospf_proto *p, struct ospf_neighbor *n)
 {
   struct ospf_iface *ifa = n->ifa;
   struct ospf_lsreq_header *lsrs;
-  struct top_hash_entry *en;
+  struct top_hash_entry *req;
   struct ospf_packet *pkt;
   uint i, lsr_max, length;
 
   /* RFC 2328 10.9 */
 
-  if (EMPTY_SLIST(n->lsrql))
-  {
-    if (n->state == NEIGHBOR_LOADING)
-      ospf_neigh_sm(n, INM_LOADDONE);
-    return;
-  }
+  /* ASSERT((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql)); */
 
   pkt = ospf_tx_buffer(ifa);
   ospf_pkt_fill_hdr(ifa, pkt, LSREQ_P);
   ospf_lsreq_body(p, pkt, &lsrs, &lsr_max);
 
-  /* We send smaller LSREQ to prevent multiple LSACKs as answer */
-  lsr_max = lsr_max / 4;
-
   i = 0;
-  WALK_SLIST(en, n->lsrql)
+  WALK_SLIST(req, n->lsrql)
   {
     if (i == lsr_max)
       break;
 
     DBG("Requesting %uth LSA: Type: %04u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
-       i, en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
+       i, req->lsa_type, req->lsa.id, req->lsa.rt, req->lsa.sn, req->lsa.age);
 
-    u32 etype = lsa_get_etype(&en->lsa, p);
+    u32 etype = lsa_get_etype(&req->lsa, p);
     lsrs[i].type = htonl(etype);
-    lsrs[i].rt = htonl(en->lsa.rt);
-    lsrs[i].id = htonl(en->lsa.id);
+    lsrs[i].rt = htonl(req->lsa.rt);
+    lsrs[i].id = htonl(req->lsa.id);
     i++;
   }
 
+  /* We store the position to see whether requested LSAs have been received */
+  n->lsrqi = req;
+
   length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsreq_header);
   pkt->length = htons(length);
 
index 0aa45f6a5dde20bec62856e66b5cc1b424a8a805..ea32923ad536ddcafaa675a4f7a84d0527a3f7ad 100644 (file)
@@ -32,8 +32,8 @@ ospf_dump_lsahdr(struct ospf_proto *p, struct ospf_lsa_header *lsa_n)
   lsa_ntoh_hdr(lsa_n, &lsa);
   lsa_etype = lsa_get_etype(&lsa, p);
 
-  log(L_TRACE "%s:     LSA      Type: %04x, Id: %R, Rt: %R, Age: %u, Seq: %08x, Sum: %04x",
-      p->p.name, lsa_etype, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
+  log(L_TRACE "%s:     LSA      Type: %04x, Id: %R, Rt: %R, Seq: %08x, Age: %u, Sum: %04x",
+      p->p.name, lsa_etype, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum);
 }
 
 void
@@ -65,45 +65,63 @@ ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, uint hdrlen, u32 val)
 
 static inline void
 ospf_lsupd_body(struct ospf_proto *p, struct ospf_packet *pkt,
-               uint *offset, uint *bound, uint *lsa_count)
+               uint *offset, uint *lsa_count)
 {
   uint hlen = ospf_lsupd_hdrlen(p);
   *offset = hlen;
-  *bound = ntohs(pkt->length) - sizeof(struct ospf_lsa_header);
   *lsa_count = ospf_lsupd_get_lsa_count(pkt, hlen);
 }
 
 static void
 ospf_dump_lsupd(struct ospf_proto *p, struct ospf_packet *pkt)
 {
-  uint offset, bound, i, lsa_count, lsalen;
+  uint offset, plen, i, lsa_count, lsa_len;
 
   ASSERT(pkt->type == LSUPD_P);
   ospf_dump_common(p, pkt);
 
-  ospf_lsupd_body(p, pkt, &offset, &bound, &lsa_count);
+  plen = ntohs(pkt->length);
+  ospf_lsupd_body(p, pkt, &offset, &lsa_count);
   for (i = 0; i < lsa_count; i++)
   {
-    if (offset > bound)
-    {
-      log(L_TRACE "%s:     LSA      invalid", p->p.name);
-      return;
-    }
+    if ((offset + sizeof(struct ospf_lsa_header)) > plen)
+      goto invalid;
 
     struct ospf_lsa_header *lsa = ((void *) pkt) + offset;
-    ospf_dump_lsahdr(p, lsa);
-    lsalen = ntohs(lsa->length);
-    offset += lsalen;
+    lsa_len = ntohs(lsa->length);
 
-    if (((lsalen % 4) != 0) || (lsalen <= sizeof(struct ospf_lsa_header)))
-    {
-      log(L_TRACE "%s:     LSA      invalid", p->p.name);
-      return;
-    }
+    if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header)))
+      goto invalid;
+
+    ospf_dump_lsahdr(p, lsa);
+    offset += lsa_len;
   }
+  return;
+
+invalid:
+  log(L_TRACE "%s:     LSA      invalid", p->p.name);
+  return;
 }
 
 
+static inline void
+ospf_lsa_lsrq_down(struct top_hash_entry *req, struct ospf_neighbor *n, struct ospf_neighbor *from)
+{
+  if (req == n->lsrqi)
+    n->lsrqi = SNODE_NEXT(req);
+
+  s_rem_node(SNODE req);
+  ospf_hash_delete(n->lsrqh, req);
+
+  if (EMPTY_SLIST(n->lsrql))
+  {
+    tm_stop(n->lsrq_timer);
+
+    if (n->state == NEIGHBOR_LOADING)
+      ospf_neigh_sm(n, INM_LOADDONE);
+  }
+}
+
 static inline void
 ospf_lsa_lsrt_up(struct top_hash_entry *en, struct ospf_neighbor *n)
 {
@@ -117,6 +135,22 @@ ospf_lsa_lsrt_up(struct top_hash_entry *en, struct ospf_neighbor *n)
 
   ret->lsa = en->lsa;
   ret->lsa_body = LSA_BODY_DUMMY;
+
+  if (!tm_active(n->lsrt_timer))
+    tm_start(n->lsrt_timer, n->ifa->rxmtint);
+}
+
+void
+ospf_lsa_lsrt_down_(struct top_hash_entry *en, struct ospf_neighbor *n, struct top_hash_entry *ret)
+{
+  if (en)
+    en->ret_count--;
+
+  s_rem_node(SNODE ret);
+  ospf_hash_delete(n->lsrth, ret);
+
+  if (EMPTY_SLIST(n->lsrtl))
+    tm_stop(n->lsrt_timer);
 }
 
 static inline int
@@ -125,14 +159,9 @@ ospf_lsa_lsrt_down(struct top_hash_entry *en, struct ospf_neighbor *n)
   struct top_hash_entry *ret = ospf_hash_find_entry(n->lsrth, en);
 
   if (ret)
-  {
-    en->ret_count--;
-    s_rem_node(SNODE ret);
-    ospf_hash_delete(n->lsrth, ret);
-    return 1;
-  }
+    ospf_lsa_lsrt_down_(en, n, ret);
 
-  return 0;
+  return ret != NULL;
 }
 
 void
@@ -144,10 +173,61 @@ ospf_add_flushed_to_lsrt(struct ospf_proto *p, struct ospf_neighbor *n)
     if ((en->lsa.age == LSA_MAXAGE) && (en->lsa_body != NULL) &&
        lsa_flooding_allowed(en->lsa_type, en->domain, n->ifa))
       ospf_lsa_lsrt_up(en, n);
+
+  /* If we found any flushed LSA, we send them ASAP */
+  if (tm_active(n->lsrt_timer))
+    tm_start(n->lsrt_timer, 0);
 }
 
+static int ospf_flood_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, uint lsa_min_count, struct ospf_iface *ifa);
+
+static void
+ospf_enqueue_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa)
+{
+  if (ifa->flood_queue_used == ifa->flood_queue_size)
+  {
+    /* If we already have full queue, we send some packets */
+    uint sent = ospf_flood_lsupd(p, ifa->flood_queue, ifa->flood_queue_used, ifa->flood_queue_used / 2, ifa);
+    int i;
+
+    for (i = 0; i < sent; i++)
+      ifa->flood_queue[i]->ret_count--;
 
-static void ospf_send_lsupd_to_ifa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa);
+    ifa->flood_queue_used -= sent;
+    memmove(ifa->flood_queue, ifa->flood_queue + sent, ifa->flood_queue_used * sizeof(void *));
+    bzero(ifa->flood_queue + ifa->flood_queue_used, sent * sizeof(void *));
+  }
+
+  en->ret_count++;
+  ifa->flood_queue[ifa->flood_queue_used] = en;
+  ifa->flood_queue_used++;
+
+  if (!ev_active(p->flood_event))
+    ev_schedule(p->flood_event);
+}
+
+void
+ospf_flood_event(void *ptr)
+{
+  struct ospf_proto *p = ptr;
+  struct ospf_iface *ifa;
+  int i, count;
+
+  WALK_LIST(ifa, p->iface_list)
+  {
+    if (ifa->flood_queue_used == 0)
+      continue;
+
+    count = ifa->flood_queue_used;
+    ospf_flood_lsupd(p, ifa->flood_queue, count, count, ifa);
+
+    for (i = 0; i < count; i++)
+      ifa->flood_queue[i]->ret_count--;
+
+    ifa->flood_queue_used = 0;
+    bzero(ifa->flood_queue, count * sizeof(void *));
+  }
+}
 
 
 /**
@@ -195,14 +275,7 @@ ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neig
 
          /* 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);
-           n->want_lsreq = 1;
-
-           if ((EMPTY_SLIST(n->lsrql)) && (n->state == NEIGHBOR_LOADING))
-             ospf_neigh_sm(n, INM_LOADDONE);
-         }
+           ospf_lsa_lsrq_down(req, n, from);
 
          /* If older or same, skip processing of this neighbor */
          if (cmp < CMP_NEWER)
@@ -242,7 +315,7 @@ ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neig
     }
 
     /* 13.3 (5) - finally flood the packet */
-    ospf_send_lsupd_to_ifa(p, en, ifa);
+    ospf_enqueue_lsa(p, en, ifa);
   }
 
   return back;
@@ -302,26 +375,33 @@ ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa,
 }
 
 
-static void
-ospf_send_lsupd_to_ifa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa)
+static int
+ospf_flood_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, uint lsa_min_count, struct ospf_iface *ifa)
 {
-  uint c = ospf_prepare_lsupd(p, ifa, &en, 1);
+  uint i, c;
 
-  if (!c)      /* Too large LSA */
-    return;
+  for (i = 0; i < lsa_min_count; i += c)
+  {
+    c = ospf_prepare_lsupd(p, ifa, lsa_list + i, lsa_count - i);
 
-  OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa),
-             "LSUPD packet flooded via %s", ifa->ifname);
+    if (!c)    /* Too large LSA */
+      { i++; continue; }
 
-  if (ifa->type == OSPF_IT_BCAST)
-  {
-    if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-      ospf_send_to_all(ifa);
+    OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa),
+               "LSUPD packet flooded via %s", ifa->ifname);
+
+    if (ifa->type == OSPF_IT_BCAST)
+    {
+      if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
+       ospf_send_to_all(ifa);
+      else
+       ospf_send_to_des(ifa);
+    }
     else
-      ospf_send_to_des(ifa);
+      ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
   }
-  else
-    ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
+
+  return i;
 }
 
 int
@@ -343,17 +423,19 @@ ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa
     ospf_send_to(ifa, n->ip);
   }
 
-  return lsa_count;
+  return i;
 }
 
 void
 ospf_rxmt_lsupd(struct ospf_proto *p, struct ospf_neighbor *n)
 {
-  const uint max = 128;
+  uint max = 2 * n->ifa->flood_queue_size;
   struct top_hash_entry *entries[max];
   struct top_hash_entry *ret, *nxt, *en;
   uint i = 0;
 
+  /* ASSERT((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl)); */
+
   WALK_SLIST_DELSAFE(ret, nxt, n->lsrtl)
   {
     if (i == max)
@@ -398,14 +480,15 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
   struct ospf_proto *p = ifa->oa->po;
   const char *err_dsc = NULL;
   uint plen, err_val = 0;
-  int skip_lsreq = 0;
-  n->want_lsreq = 0;
 
   /* RFC 2328 13. */
 
   plen = ntohs(pkt->length);
-  if (plen < (ospf_lsupd_hdrlen(p) + sizeof(struct ospf_lsa_header)))
-    DROP("too short", plen);
+  if (plen < ospf_lsupd_hdrlen(p))
+  {
+    LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
+    return;
+  }
 
   OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from nbr %R on %s", n->rid, ifa->ifname);
 
@@ -417,8 +500,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
   ospf_neigh_sm(n, INM_HELLOREC);      /* Questionable */
 
-  uint offset, bound, i, lsa_count;
-  ospf_lsupd_body(p, pkt, &offset, &bound, &lsa_count);
+  uint offset, i, lsa_count;
+  ospf_lsupd_body(p, pkt, &offset, &lsa_count);
 
   for (i = 0; i < lsa_count; i++)
   {
@@ -426,7 +509,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
     struct top_hash_entry *en;
     u32 lsa_len, lsa_type, lsa_domain;
 
-    if (offset > bound)
+    if ((offset + sizeof(struct ospf_lsa_header)) > plen)
       DROP("too short", plen);
 
     /* LSA header in network order */
@@ -492,7 +575,6 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
       if (en && ((now - en->inst_time) < MINLSARRIVAL))
       {
        OSPF_TRACE(D_EVENTS, "Skipping LSA received in less that MinLSArrival");
-       skip_lsreq = 1;
        continue;
       }
 
@@ -559,7 +641,9 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
       continue;
     }
 
-    /* FIXME pg145 (6) */
+    /* 13. (6) - received LSA is in Link state request list (but not newer) */
+    if (ospf_hash_find_entry(n->lsrqh, en) != NULL)
+      DROP1("error in LSA database exchange");
 
     /* 13. (7) - received LSA is same */
     if (lsa_comp(&lsa, &en->lsa) == CMP_SAME)
@@ -576,7 +660,6 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
       else
        ospf_enqueue_lsack(n, lsa_n, ACKL_DIRECT);
 
-      skip_lsreq = 1;
       continue;
     }
 
@@ -601,15 +684,24 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
   /* Send direct LSACKs */
   ospf_send_lsack(p, n, ACKL_DIRECT);
 
+  /* Send enqueued LSAs immediately, do not wait for flood_event */
+  if (ev_active(p->flood_event))
+  {
+    ev_postpone(p->flood_event);
+    ospf_flood_event(p);
+  }
+
   /*
-   * In loading state, we should ask for another batch of LSAs. This is only
-   * vaguely mentioned in RFC 2328. We send a new LSREQ only if the current
-   * LSUPD actually removed some entries from LSA request list (want_lsreq) and
-   * did not contain duplicate or early LSAs (skip_lsreq). The first condition
-   * prevents endless floods, the second condition helps with flow control.
+   * During loading, we should ask for another batch of LSAs. This is only
+   * vaguely mentioned in RFC 2328. We send a new LSREQ if all requests sent in
+   * the last packet were already answered and/or removed from the LS request
+   * list and therefore lsrqi is pointing to the first node of the list.
    */
-  if ((n->state == NEIGHBOR_LOADING) && n->want_lsreq && !skip_lsreq)
+  if (!EMPTY_SLIST(n->lsrql) && (n->lsrqi == SHEAD(n->lsrql)))
+  {
     ospf_send_lsreq(p, n);
+    tm_start(n->lsrq_timer, n->ifa->rxmtint);
+  }
 
   return;
 
@@ -617,7 +709,7 @@ drop:
   LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)",
          n->rid, ifa->ifname, err_dsc, err_val);
 
-  // XXXX realy?
-  ospf_neigh_sm(n, INM_SEQMIS);
+  /* Malformed LSUPD - there is no defined error event, we abuse BadLSReq */
+  ospf_neigh_sm(n, INM_BADLSREQ);
   return;
 }
index c75b1b9370400cf6b1d7a6d747fc79814fa1fcd4..c5d44dec85093be5c3e1919d81c9156ba5ae42fd 100644 (file)
@@ -23,14 +23,18 @@ const char *ospf_inm_names[] = {
 
 
 static int can_do_adj(struct ospf_neighbor *n);
-static void neighbor_timer_hook(timer * timer);
-static void rxmt_timer_hook(timer * timer);
-static void ackd_timer_hook(timer * t);
+static void inactivity_timer_hook(timer * timer);
+static void dbdes_timer_hook(timer *t);
+static void lsrq_timer_hook(timer *t);
+static void lsrt_timer_hook(timer *t);
+static void ackd_timer_hook(timer *t);
+
 
 static void
 init_lists(struct ospf_proto *p, struct ospf_neighbor *n)
 {
   s_init_list(&(n->lsrql));
+  n->lsrqi = SHEAD(n->lsrql);
   n->lsrqh = ospf_top_new(p, n->pool);
 
   s_init_list(&(n->lsrtl));
@@ -57,9 +61,16 @@ release_lsrtl(struct ospf_proto *p, struct ospf_neighbor *n)
 static void
 reset_lists(struct ospf_proto *p, struct ospf_neighbor *n)
 {
-  release_lsrtl(p,n);
+  release_lsrtl(p, n);
   ospf_top_free(n->lsrqh);
   ospf_top_free(n->lsrth);
+  ospf_reset_lsack_queue(n);
+
+  tm_stop(n->dbdes_timer);
+  tm_stop(n->lsrq_timer);
+  tm_stop(n->lsrt_timer);
+  tm_stop(n->ackd_timer);
+
   init_lists(p, n);
 }
 
@@ -80,30 +91,14 @@ ospf_neighbor_new(struct ospf_iface *ifa)
   init_lists(p, n);
   s_init(&(n->dbsi), &(p->lsal));
 
-  n->inactim = tm_new(pool);
-  n->inactim->data = n;
-  n->inactim->randomize = 0;
-  n->inactim->hook = neighbor_timer_hook;
-  n->inactim->recurrent = 0;
-  DBG("%s: Installing inactivity timer.\n", p->p.name);
-
-  n->rxmt_timer = tm_new(pool);
-  n->rxmt_timer->data = n;
-  n->rxmt_timer->randomize = 0;
-  n->rxmt_timer->hook = rxmt_timer_hook;
-  n->rxmt_timer->recurrent = ifa->rxmtint;
-  tm_start(n->rxmt_timer, n->ifa->rxmtint);
-  DBG("%s: Installing rxmt timer.\n", p->p.name);
-
-  n->ackd_timer = tm_new(pool);
-  n->ackd_timer->data = n;
-  n->ackd_timer->randomize = 0;
-  n->ackd_timer->hook = ackd_timer_hook;
-  n->ackd_timer->recurrent = ifa->rxmtint / 2;
   init_list(&n->ackl[ACKL_DIRECT]);
   init_list(&n->ackl[ACKL_DELAY]);
-  tm_start(n->ackd_timer, n->ifa->rxmtint / 2);
-  DBG("%s: Installing ackd timer.\n", p->p.name);
+
+  n->inactim = tm_new_set(pool, inactivity_timer_hook, n, 0, 0);
+  n->dbdes_timer = tm_new_set(pool, dbdes_timer_hook, n, 0, ifa->rxmtint);
+  n->lsrq_timer = tm_new_set(pool, lsrq_timer_hook, n, 0, ifa->rxmtint);
+  n->lsrt_timer = tm_new_set(pool, lsrt_timer_hook, n, 0, ifa->rxmtint);
+  n->ackd_timer = tm_new_set(pool, ackd_timer_hook, n, 0, ifa->rxmtint / 2);
 
   return (n);
 }
@@ -188,6 +183,9 @@ ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
 
     n->dds++;
     n->myimms = DBDES_IMMS;
+
+    tm_start(n->dbdes_timer, 0);
+    tm_start(n->ackd_timer, ifa->rxmtint / 2);
   }
 
   if (state > NEIGHBOR_EXSTART)
@@ -253,16 +251,16 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
 
       /* Add MaxAge LSA entries to retransmission list */
       ospf_add_flushed_to_lsrt(p, n);
-
-      /* FIXME: Why is this here ? */
-      ospf_reset_lsack_queue(n);
     }
     else
       bug("NEGDONE and I'm not in EXSTART?");
     break;
 
   case INM_EXDONE:
-    ospf_neigh_chstate(n, NEIGHBOR_LOADING);
+    if (!EMPTY_SLIST(n->lsrql))
+      ospf_neigh_chstate(n, NEIGHBOR_LOADING);
+    else
+      ospf_neigh_chstate(n, NEIGHBOR_FULL);
     break;
 
   case INM_LOADDONE:
@@ -270,23 +268,15 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
     break;
 
   case INM_ADJOK:
-    switch (n->state)
+    /* Can In build adjacency? */
+    if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
     {
-    case NEIGHBOR_2WAY:
-      /* Can In build adjacency? */
-      if (can_do_adj(n))
-      {
-       ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
-      }
-      break;
-    default:
-      if (n->state >= NEIGHBOR_EXSTART)
-       if (!can_do_adj(n))
-       {
-         reset_lists(p, n);
-         ospf_neigh_chstate(n, NEIGHBOR_2WAY);
-       }
-      break;
+      ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
+    }
+    else if ((n->state >= NEIGHBOR_EXSTART) && !can_do_adj(n))
+    {
+      reset_lists(p, n);
+      ospf_neigh_chstate(n, NEIGHBOR_2WAY);
     }
     break;
 
@@ -566,12 +556,12 @@ find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
 }
 
 static void
-neighbor_timer_hook(timer * timer)
+inactivity_timer_hook(timer * timer)
 {
   struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
   struct ospf_proto *p = n->ifa->oa->po;
 
-  OSPF_TRACE(D_EVENTS, "Inactivity timer expired for neighbor %R on %s",
+  OSPF_TRACE(D_EVENTS, "Inactivity timer expired for nbr %R on %s",
             n->rid, n->ifa->ifname);
   ospf_neigh_sm(n, INM_INACTTIM);
 }
@@ -584,7 +574,7 @@ ospf_neigh_bfd_hook(struct bfd_request *req)
 
   if (req->down)
   {
-    OSPF_TRACE(D_EVENTS, "BFD session down for neighbor %R on %s",
+    OSPF_TRACE(D_EVENTS, "BFD session down for nbr %R on %s",
               n->rid, n->ifa->ifname);
     ospf_neigh_sm(n, INM_INACTTIM);
   }
@@ -605,11 +595,60 @@ ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
 }
 
 
+static void
+dbdes_timer_hook(timer *t)
+{
+  struct ospf_neighbor *n = t->data;
+  struct ospf_proto *p = n->ifa->oa->po;
+
+  // OSPF_TRACE(D_EVENTS, "DBDES timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
+
+  if (n->state == NEIGHBOR_EXSTART)
+    ospf_send_dbdes(p, n);
+
+  if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS))
+    ospf_rxmt_dbdes(p, n);
+}
+
+static void
+lsrq_timer_hook(timer *t)
+{
+  struct ospf_neighbor *n = t->data;
+  struct ospf_proto *p = n->ifa->oa->po;
+
+  // OSPF_TRACE(D_EVENTS, "LSRQ timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
+
+  if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrql))
+    ospf_send_lsreq(p, n);
+}
+
+static void
+lsrt_timer_hook(timer *t)
+{
+  struct ospf_neighbor *n = t->data;
+  struct ospf_proto *p = n->ifa->oa->po;
+
+  // OSPF_TRACE(D_EVENTS, "LSRT timer expired for nbr %R on %s", n->rid, n->ifa->ifname);
+
+  if ((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl))
+    ospf_rxmt_lsupd(p, n);
+}
+
+static void
+ackd_timer_hook(timer *t)
+{
+  struct ospf_neighbor *n = t->data;
+  struct ospf_proto *p = n->ifa->oa->po;
+
+  ospf_send_lsack(p, n, ACKL_DELAY);
+}
+
+
 void
 ospf_sh_neigh_info(struct ospf_neighbor *n)
 {
   struct ospf_iface *ifa = n->ifa;
-  char *pos = "ptp  ";
+  char *pos = "PtP  ";
   char etime[6];
   int exp, sec, min;
 
@@ -628,55 +667,13 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
   if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
   {
     if (n->rid == ifa->drid)
-      pos = "dr   ";
+      pos = "DR   ";
     else if (n->rid == ifa->bdrid)
-      pos = "bdr  ";
+      pos = "BDR  ";
     else
-      pos = "other";
+      pos = "Other";
   }
 
   cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
          ospf_ns_names[n->state], pos, etime, ifa->ifname, n->ip);
 }
-
-static void
-rxmt_timer_hook(timer *t)
-{
-  struct ospf_neighbor *n = t->data;
-  struct ospf_proto *p = n->ifa->oa->po;
-
-  DBG("%s: RXMT timer fired on %s for neigh %I\n",
-      p->p.name, n->ifa->ifname, n->ip);
-
-  switch (n->state)
-  {
-  case NEIGHBOR_EXSTART:
-    ospf_send_dbdes(p, n);
-    return;
-
-  case NEIGHBOR_EXCHANGE:
-    if (n->myimms & DBDES_MS)
-      ospf_rxmt_dbdes(p, n);
-  case NEIGHBOR_LOADING:
-    ospf_send_lsreq(p, n);
-    return;
-
-  case NEIGHBOR_FULL:
-    /* LSA retransmissions */
-    if (!EMPTY_SLIST(n->lsrtl))
-      ospf_rxmt_lsupd(p, n);
-    return;
-  }
-}
-
-static void
-ackd_timer_hook(timer *t)
-{
-  struct ospf_neighbor *n = t->data;
-  struct ospf_proto *p = n->ifa->oa->po;
-
-  DBG("%s: ACKD timer fired on %s for neigh %I\n",
-      p->p.name, n->ifa->ifname, n->ip);
-
-  ospf_send_lsack(p, n, ACKL_DELAY);
-}
index 01e53922606c8127ffabaf1669885a41631c9584..dab7aab88da181a58028efac6457102c7ffefc14 100644 (file)
@@ -235,11 +235,7 @@ ospf_start(struct proto *P)
   p->asbr = c->asbr;
   p->ecmp = c->ecmp;
   p->tick = c->tick;
-  p->disp_timer = tm_new(P->pool);
-  p->disp_timer->data = p;
-  p->disp_timer->randomize = 0;
-  p->disp_timer->hook = ospf_disp;
-  p->disp_timer->recurrent = p->tick;
+  p->disp_timer = tm_new_set(P->pool, ospf_disp, p, 0, p->tick);
   tm_start(p->disp_timer, 1);
   p->lsab_size = 256;
   p->lsab_used = 0;
@@ -252,6 +248,10 @@ ospf_start(struct proto *P)
   p->gr = ospf_top_new(p, P->pool);
   s_init_list(&(p->lsal));
 
+  p->flood_event = ev_new(P->pool);
+  p->flood_event->hook = ospf_flood_event;
+  p->flood_event->data = p;
+
   p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
   p->log_lsa_tbf = (struct tbf){ .rate = 4, .burst = 20 };
 
@@ -1439,14 +1439,14 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
        break;
       }
       cli_msg(-1017, "");
-      cli_msg(-1017," Type   LS ID           Router           Age  Sequence  Checksum");
+      cli_msg(-1017," Type   LS ID           Router          Sequence   Age  Checksum");
 
       last_dscope = dscope;
       last_domain = hea[i]->domain;
     }
 
-    cli_msg(-1017," %04x  %-15R %-15R %5u  %08x    %04x",
-           lsa_type, lsa->id, lsa->rt, lsa->age, lsa->sn, lsa->checksum);
+    cli_msg(-1017," %04x  %-15R %-15R  %08x %5u    %04x",
+           lsa_type, lsa->id, lsa->rt, lsa->sn, lsa->age, lsa->checksum);
   }
   cli_msg(0, "");
 }
index e535287c682c762bf1bf7b68fadba64b0c91f340..c324f431def47c3600884f116ec21eb5c5439360 100644 (file)
@@ -231,6 +231,7 @@ struct ospf_proto
   byte asbr;                   /* May i originate any ext/NSSA lsa? */
   byte ecmp;                   /* Maximal number of nexthops in ECMP route, or 0 */
   struct ospf_area *backbone;  /* If exists */
+  event *flood_event;          /* Event for flooding LS updates */
   void *lsab;                  /* LSA buffer used when originating router LSAs */
   int lsab_size, lsab_used;
   linpool *nhpool;             /* Linpool used for next hops computed in SPF */
@@ -317,8 +318,11 @@ struct ospf_iface
   struct top_hash_entry *link_lsa;     /* Originated link LSA */
   struct top_hash_entry *net_lsa;      /* Originated network LSA */
   struct top_hash_entry *pxn_lsa;      /* Originated prefix LSA */
+  struct top_hash_entry **flood_queue; /* LSAs queued for LSUPD */
   u8 update_link_lsa;
   u8 update_net_lsa;
+  u16 flood_queue_used;                /* The current number of LSAs in flood_queue */
+  u16 flood_queue_size;                /* The maximum number of LSAs in flood_queue */
   int fadj;                    /* Number of fully adjacent neighbors */
   list nbma_list;
   u8 priority;                 /* A router priority for DR election */
@@ -354,7 +358,6 @@ struct ospf_neighbor
   ip_addr ip;                  /* IP of it's interface */
   u8 priority;                 /* Priority */
   u8 adj;                      /* built adjacency? */
-  u8 want_lsreq;               /* Set to 1 when lsrql was shortened during LSUPD */
   u32 options;                 /* Options received */
 
   /* Entries dr and bdr store IP addresses in OSPFv2 and router IDs in
@@ -373,6 +376,7 @@ struct ospf_neighbor
    */
   slist lsrql;                 /* slist of struct top_hash_entry from n->lsrqh */
   struct top_graph *lsrqh;
+  struct top_hash_entry *lsrqi;        /* Pointer to the first unsent node in lsrql */
 
   /* Link state retransmission list, controls LSA retransmission during flood.
    * Entries added as sent in lsupd packets, removed when received in lsack packets.
@@ -380,7 +384,9 @@ struct ospf_neighbor
    */
   slist lsrtl;                 /* slist of struct top_hash_entry from n->lsrth */
   struct top_graph *lsrth;
-  timer *rxmt_timer;           /* RXMT timer */
+  timer *dbdes_timer;          /* DBDES exchange timer */
+  timer *lsrq_timer;           /* LSA request timer */
+  timer *lsrt_timer;           /* LSA retransmission timer */
   list ackl[2];
 #define ACKL_DIRECT 0
 #define ACKL_DELAY 1
@@ -940,7 +946,9 @@ void ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa, struct
 /* lsupd.c */
 void ospf_dump_lsahdr(struct ospf_proto *p, struct ospf_lsa_header *lsa_n);
 void ospf_dump_common(struct ospf_proto *p, struct ospf_packet *pkt);
+void ospf_lsa_lsrt_down_(struct top_hash_entry *en, struct ospf_neighbor *n, struct top_hash_entry *ret);
 void ospf_add_flushed_to_lsrt(struct ospf_proto *p, struct ospf_neighbor *n);
+void ospf_flood_event(void *ptr);
 int ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neighbor *from);
 int ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, struct ospf_neighbor *n);
 void ospf_rxmt_lsupd(struct ospf_proto *p, struct ospf_neighbor *n);
index a545c7fd7620df7532bcacdd6829fc506f1f60ef..fb63e61c497733270c52ff6c3fea59c62e0fd76f 100644 (file)
@@ -260,7 +260,7 @@ ospf_rx_hook(sock *sk, int len)
      * link-local src address, but does not enforce it. Strange.
      */
     if (dst_mcast && !src_local)
-      LOG_PKT_WARN("Multicast packet received from not-link-local %I via %s",
+      LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s",
                   sk->faddr, ifa->ifname);
   }
 
@@ -396,8 +396,7 @@ found:
 
   if (!n && (pkt->type != HELLO_P))
   {
-    // XXXX format
-    OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown neighbor %R on %s (%I)",
+    OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
               rid, ifa->ifname, sk->faddr);
     return 1;
   }
index 42bf9c4555a60424c7df8b89ec3bc017c20a0ac4..c21c23d52be6b2cd80985f85d2db490886e28e54 100644 (file)
@@ -404,9 +404,6 @@ ospf_refresh_lsa(struct ospf_proto *p, struct top_hash_entry *en)
 void
 ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en)
 {
-  OSPF_TRACE(D_EVENTS, "Flushing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
-            en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
-
   if (en->next_lsa_body)
   {
     mb_free(en->next_lsa_body);
@@ -418,6 +415,9 @@ ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en)
   if (en->lsa.age == LSA_MAXAGE)
     return;
 
+  OSPF_TRACE(D_EVENTS, "Flushing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
+            en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
+
   en->lsa.age = LSA_MAXAGE;
   ospf_flood_lsa(p, en, NULL);
 
@@ -433,8 +433,12 @@ ospf_clear_lsa(struct ospf_proto *p, struct top_hash_entry *en)
   /*
    * Called by ospf_update_lsadb() as part of LSA flushing process.
    * Flushed LSA was acknowledged by neighbors and we can free its content.
+   * The log message is for 'remove' - we hide empty LSAs from users.
    */
 
+  OSPF_TRACE(D_EVENTS, "Removing LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x",
+            en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn);
+
   if (en->lsa.sn == LSA_MAXSEQNO)
     en->lsa.sn = LSA_ZEROSEQNO;
 
@@ -1143,6 +1147,9 @@ ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 m
   ospf_originate_lsa(p, &lsa);
 }
 
+static struct top_hash_entry *
+ospf_hash_find_(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type);
+
 static void
 ospf_flush_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf)
 {
@@ -1152,7 +1159,7 @@ ospf_flush_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf)
   u32 dom = oa ? oa->areaid : 0;
   u32 id = ort_to_lsaid(p, nf);
 
-  en = ospf_hash_find(p->gr, dom, id, p->router_id, type);
+  en = ospf_hash_find_(p->gr, dom, id, p->router_id, type);
 
   if (!en || (en->nf != nf))
     return;
@@ -1795,8 +1802,8 @@ ospf_top_rehash(struct top_graph *f, int step)
   ospf_top_ht_free(oldt);
 }
 
-struct top_hash_entry *
-ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
+static struct top_hash_entry *
+ospf_hash_find_(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
 {
   struct top_hash_entry *e;
   e = f->hash_table[ospf_top_hash(f, domain, lsa, rtr, type)];
@@ -1805,6 +1812,14 @@ ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
               e->lsa_type != type || e->domain != domain))
     e = e->next;
 
+  return e;
+}
+
+struct top_hash_entry *
+ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
+{
+  struct top_hash_entry *e = ospf_hash_find_(f, domain, lsa, rtr, type);
+
   /* Hide hash entry with empty lsa_body */
   return (e && e->lsa_body) ? e : NULL;
 }
index 17450322a73beaed7c466f43517f4aeccd292ff6..99d43932884b93c242c6df2dceeb6306078e06b6 100644 (file)
@@ -34,6 +34,12 @@ extern bird_clock_t now;             /* Relative, monotonic time in seconds */
 extern bird_clock_t now_real;          /* Time in seconds since fixed known epoch */
 extern bird_clock_t boot_time;
 
+static inline int
+tm_active(timer *t)
+{
+  return t->expires != 0;
+}
+
 static inline bird_clock_t
 tm_remains(timer *t)
 {