]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Temporary OSPFv3 development commit
authorOndrej Zajicek <santiago@crfreenet.org>
Tue, 25 Aug 2009 14:42:14 +0000 (16:42 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 25 Aug 2009 14:42:14 +0000 (16:42 +0200)
23 files changed:
filter/filter.h
filter/trie.c
lib/ipv6.c
lib/ipv6.h
nest/a-path.c
nest/rt-attr.c
proto/bgp/attrs.c
proto/bgp/packets.c
proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsack.c
proto/ospf/lsalib.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/rt.c
proto/ospf/topology.c
proto/ospf/topology.h
sysdep/linux/netlink/netlink.c

index 2277f51919003cd35547d974028d52b1ef8bbdcd..8e0d17934d219f382bc0ae551465c690b235efac 100644 (file)
@@ -86,6 +86,7 @@ int filter_same(struct filter *new, struct filter *old);
 
 int i_same(struct f_inst *f1, struct f_inst *f2);
 
+void f_prefix_get_bounds(struct f_prefix *px, int *l, int *h);
 int val_compare(struct f_val v1, struct f_val v2);
 void val_print(struct f_val v);
 
index ffb9b99fbd99415905a1982633bcbfb24603df51..2257c8b64aba1c851190f2f7fe640df7f8add89a 100644 (file)
@@ -272,7 +272,7 @@ static int
 trie_node_print(struct f_trie_node *t, char *buf, int blen)
 {
   if (t == NULL)
-    return;
+    return 0;
 
   int old_blen = blen;
   int wb = 0; // bsnprintf(buf, blen, "%I/%d accept %I\n", t->addr, t->plen, t->accept);
index 88c54eb6e733550a3ecbfa9640bc46dca3c4f953..3334b976ce6ccf39f6545026784531e1a8a7d982 100644 (file)
@@ -136,6 +136,60 @@ ipv6_compare(ip_addr X, ip_addr Y)
   return 0;
 }
 
+/* From Linux include/net/ipv6.h */
+#define NEXTHDR_HOP             0       /* Hop-by-hop option header. */
+#define NEXTHDR_ROUTING         43      /* Routing header. */
+#define NEXTHDR_FRAGMENT        44      /* Fragmentation/reassembly header. */
+#define NEXTHDR_DEST            60      /* Destination options header. */
+#define NEXTHDR_NONE            59      /* No next header */
+
+#define NEXTHDR_ESP             50      /* Encapsulating security payload. */
+#define NEXTHDR_AUTH            51      /* Authentication header. */
+
+
+byte *
+ipv6_skip_header(byte *pkt, int *len)
+{
+  int l = *len;
+  int q;
+  u8 nh;
+
+  if (l < 40 || (*pkt & 0xf0) != 0x60)
+    return NULL;
+
+  /* Skip IPv6 header */
+  nh = pkt[6];
+  pkt += 40;
+
+  while ()
+    {
+      switch (nw)
+       {
+       case NEXTHDR_FRAGMENT:
+
+       case NEXTHDR_HOP:
+       case NEXTHDR_ROUTING:
+       case NEXTHDR_DEST:
+
+       case NEXTHDR_AUTH:
+         break;
+
+       case NEXTHDR_NONE:
+         return NULL;
+
+       default:
+         return pkt;
+       }
+    }
+
+  q = (*pkt & 0x0f) * 4;
+  if (q > l)
+    return NULL;
+  *len -= q;
+  return pkt + q;
+}
+
+
 /*
  *  Conversion of IPv6 address to presentation format and vice versa.
  *  Heavily inspired by routines written by Paul Vixie for the BIND project
index 9cec86e7a86019161af5d403cca172bf66abefd6..d2b77c01dd5e014029225a567ac7d7ca6112c75d 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  *     BIRD -- IP Addresses et Cetera for IPv6
  *
index dba214d21bed6522e2dd29c67f1412bf20e17e9b..5aacf8f265bf47fbf82323813d2f496d7392567b 100644 (file)
@@ -298,7 +298,7 @@ parse_path(struct adata *path, struct pm_pos *pos)
   u8 *p = path->data;
   u8 *q = p + path->length;
   struct pm_pos *opos = pos;
-  int i, j, len;
+  int i, len;
 
 
   while (p < q)
index 8daebae013062c47134576d1c624028d83206ac0..de63198ee57982b95d9a284a4178a217e3c45f2a 100644 (file)
@@ -71,7 +71,6 @@ ea__find(ea_list *e, unsigned id)
 
   while (e)
     {
-    /*
       if (e->flags & EALF_BISECT)
        {
          l = 0;
@@ -89,7 +88,6 @@ ea__find(ea_list *e, unsigned id)
            }
        }
       else
-      */
        for(m=0; m<e->count; m++)
          if (e->attrs[m].id == id)
            return &e->attrs[m];
index 68f21b97c75b9868c8a17525eb70cd6397ceda4a..d0ec41f986dfdb6b900ea28d3bd993bd0f25161b 100644 (file)
@@ -1131,6 +1131,8 @@ as4_aggregator_valid(struct adata *aggr)
 
   if ((a[0] == 0) || (a[1] == 0))
     return 0;
+
+  return 1;
 }
 
 
index ae4906eec338b8b3df1035ad6c76b3a1eeb1d8de..ac697be1f7d632cb8b0a19ba9b200c7567ba00cd 100644 (file)
@@ -488,7 +488,6 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
 {
   struct bgp_proto *p = conn->bgp;
   int cl;
-  u32 as;
 
   while (len > 0)
     {
index 31075791b16de2d566fec5898795ebc8008d00eb..9be8e61f2d59d97eb00a03a2ad1b4e385d9aa322 100644 (file)
@@ -85,8 +85,9 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
   struct proto *p = &po->proto;
   u16 length, i, j;
 
+  /* FIXME ??? */
   if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal)))
-    originate_rt_lsa(oa);
+    update_rt_lsa(oa);
 
   switch (n->state)
   {
@@ -227,13 +228,14 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
   for (i = 0; i < j; i++)
   {
     ntohlsah(plsa + i, &lsa);
-    if (((he = ospfxx_hash_find_smart(gr, n->ifa, &lsa)) == NULL) ||
+    u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
+    if (((he = ospf_hash_find_header(gr, dom, &lsa)) == NULL) ||
        (lsa_comp(&lsa, &(he->lsa)) == 1))
     {
       /* Is this condition necessary? */
-      if (ospfxx_hash_find_smart(n->lsrqh, n->ifa, &lsa) == NULL)
+      if (ospf_hash_find_header(n->lsrqh, dom, &lsa) == NULL)
       {
-       sn = ospfxx_hash_get_smart(n->lsrqh, n->ifa, &lsa);
+       sn = ospf_hash_get_header(n->lsrqh, dom, &lsa);
        ntohlsah(plsa + i, &(sn->lsa));
        s_add_tail(&(n->lsrql), SNODE sn);
       }
index 7eeee3b3d6119fdcdc4a59acd6377abdfaaf9fdb..cce256fcbadff5e8d3e3b84b8458f85071f92d36 100644 (file)
@@ -48,7 +48,6 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
   struct ospf_hello_packet *ps = (void *) ps_i;
   u32 *pnrid;
   u32 olddr, oldbdr, oldiface_id, tmp;
-  ip_addr mask;
   char *beg = "Bad OSPF hello packet from ", *rec = " received: ";
   struct proto *p = (struct proto *) ifa->oa->po;
   unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers;
index ea3baa23769ee84f0bd57ade3bb80c0a3874d71a..cae36ad38637e85d94496f093ad6ef695b58dfc1 100644 (file)
@@ -420,6 +420,23 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface,
 
 #ifdef OSPFv3
   ifa->instance_id = ip->instance_id;
+
+  ifa->lladdr = IPA_NONE;
+
+  /* Find link-local address */
+  if (ifa->type != OSPF_IT_VLINK)
+    {
+      struct ifa *a;
+      WALK_LIST(a, iface->addrs)
+       if (a->scope == SCOPE_LINK)
+         {
+           ifa->lladdr = a->ip;
+           break;
+         }
+
+      if (! ipa_nonzero(ifa->lladdr))
+       log(L_WARN "%s: Missing link local address on interface %s", p->name,  iface->name);
+    }
 #endif
 
   ifa->rxbuf = ip->rxbuf;
index 7871b8f427818b948f27f2fc8ddd88565ef1ed8c..dc9421973b74380279ad5f07307463ac9f43bb61 100644 (file)
@@ -177,7 +177,8 @@ ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
   for (i = 0; i < nolsa; i++)
   {
     ntohlsah(ps->lsh + i, &lsa);
-    if ((en = ospfxx_hash_find_smart(n->lsrth, n->ifa, &lsa)) == NULL)
+    u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
+    if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
       continue;                        /* pg 155 */
 
     if (lsa_comp(&lsa, &en->lsa) != CMP_SAME)  /* pg 156 */
index 7c4001d96b601bcda0c866c9f4ef1f5a2fd3261f..4cbabcc13f660594da595822f0593165db52c433 100644 (file)
@@ -384,12 +384,11 @@ lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain,
 {
   /* LSA can be temporarrily, but body must be mb_allocated. */
   int change = 0;
-  unsigned i;
   struct top_hash_entry *en;
 
-  if ((en = ospfxx_hash_find_header(po->gr, domain, lsa)) == NULL)
+  if ((en = ospf_hash_find_header(po->gr, domain, lsa)) == NULL)
   {
-    en = ospfxx_hash_get_header(po->gr, domain, lsa);
+    en = ospf_hash_get_header(po->gr, domain, lsa);
     change = 1;
   }
   else
index cc5afa0ffc92173a92e3b14f8d8e7e56a9ff5f1b..aafc190e55027f1ce09b1ed2b78d998a67e25113 100644 (file)
@@ -127,7 +127,7 @@ ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
     llsh->lsh.rt = hrt;
     llsh->lsh.type = htype;
     add_tail(&uplist, NODE llsh);
-    if (ospfxx_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
+    if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
     {
       log(L_WARN
          "Received bad LS req from: %I looking: Type: %u, ID: %R, RT: %R",
index 8c26f5487a83cbe07fa11be62d378b4bae6085f0..efaafe866bee25dee79de1df42c77a2987b234b0 100644 (file)
@@ -156,7 +156,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
       /* 13.3 (1b) */
       if (nn->state < NEIGHBOR_FULL)
       {
-       if ((en = ospfxx_hash_find_header(nn->lsrqh, domain, hh)) != NULL)
+       if ((en = ospf_hash_find_header(nn->lsrqh, domain, hh)) != NULL)
        {
          DBG("That LSA found in lsreq list for neigh %R\n", nn->rid);
 
@@ -203,9 +203,9 @@ ospf_lsupd_flood(struct proto_ospf *po,
           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 = ospfxx_hash_find_header(nn->lsrth, domain, hh)) == NULL)
+       if ((en = ospf_hash_find_header(nn->lsrth, domain, hh)) == NULL)
        {
-         en = ospfxx_hash_get_header(nn->lsrth, domain, hh);
+         en = ospf_hash_get_header(nn->lsrth, domain, hh);
        }
        else
        {
@@ -217,7 +217,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
       }
       else
       {
-       if ((en = ospfxx_hash_find_header(nn->lsrth, domain, hh)) != NULL)
+       if ((en = ospf_hash_find_header(nn->lsrth, domain, hh)) != NULL)
        {
          s_rem_node(SNODE en);
          if (en->lsa_body != NULL)
@@ -274,7 +274,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
 
        htonlsah(hh, lh);
        help = (u8 *) (lh + 1);
-       en = ospfxx_hash_find_header(po->gr, domain, hh);
+       en = ospf_hash_find_header(po->gr, domain, hh);
        htonlsab(en->lsa_body, help, hh->type, hh->length
                 - sizeof(struct ospf_lsa_header));
       }
@@ -347,7 +347,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
   WALK_LIST(llsh, *l)
   {
     u32 domain = ospf_lsa_domain(llsh->lsh.type, n->ifa);
-    if ((en = ospfxx_hash_find(po->gr, domain, llsh->lsh.id,
+    if ((en = ospf_hash_find(po->gr, domain, 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 */
@@ -487,7 +487,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
        lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
 
     u32 domain = ospf_lsa_domain(lsatmp.type, ifa);
-    lsadb = ospfxx_hash_find_header(po->gr, domain, &lsatmp);
+    lsadb = ospf_hash_find_header(po->gr, domain, &lsatmp);
 
 #ifdef LOCAL_DEBUG
     if (lsadb)
@@ -508,7 +508,6 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
     {
       struct ospf_iface *ift = NULL;
       void *body;
-      struct ospf_iface *nifa;
       int self = (lsatmp.rt == p->cf->global->router_id);
 
       DBG("PG143(5): Received LSA is newer\n");
@@ -517,6 +516,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
       /* 13.4 - check self-originated LSAs of NET type */
       if ((!self) && (lsatmp.type == LSA_T_NET))
       {
+       struct ospf_iface *nifa;
        WALK_LIST(nifa, po->iface_list)
        {
          if (!nifa->iface)
@@ -551,7 +551,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
        lsasum_check(lsa, (lsa + 1));   /* It also calculates chsum! */
        lsatmp.checksum = ntohs(lsa->checksum);
        ospf_lsupd_flood(po, NULL, lsa, &lsatmp, domain, 0);
-       if (en = ospfxx_hash_find_header(po->gr, domain, &lsatmp))
+       if (en = ospf_hash_find_header(po->gr, domain, &lsatmp))
        { /* FIXME verify hacks */
          ospf_lsupd_flood(po, NULL, NULL, &en->lsa, domain, 1);
        }
@@ -586,7 +586,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
       {
        struct top_hash_entry *en;
        if (ntmp->state > NEIGHBOR_EXSTART)
-         if ((en = ospfxx_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
+         if ((en = ospf_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
          {
            s_rem_node(SNODE en);
            if (en->lsa_body != NULL)
@@ -622,7 +622,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
     {
       struct top_hash_entry *en;
       DBG("PG145(7) Got the same LSA\n");
-      if ((en = ospfxx_hash_find_header(n->lsrth, lsadb->domain, &lsadb->lsa)) != NULL)
+      if ((en = ospf_hash_find_header(n->lsrth, lsadb->domain, &lsadb->lsa)) != NULL)
       {
        /* pg145 (7a) */
        s_rem_node(SNODE en);
index d86895eddcd971a0eaa0f3c3f3cd4e78d4d47a9a..374da636fc02aa5a5ac35c062ab97e9898b463fa 100644 (file)
@@ -173,16 +173,16 @@ electbdr(list nl)
   struct ospf_neighbor *neigh, *n1, *n2;
   u32 nid;
 
-#ifdef OSPFv2
-  nid = ipa_to_u32(neigh->ip);
-#else /* OSPFv3 */
-  nid = neigh->rid;
-#endif
-
   n1 = NULL;
   n2 = NULL;
   WALK_LIST(neigh, nl)                 /* First try those decl. themselves */
   {
+#ifdef OSPFv2
+    nid = ipa_to_u32(neigh->ip);
+#else /* OSPFv3 */
+    nid = neigh->rid;
+#endif
+
     if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
       if (neigh->priority > 0)         /* Eligible */
        if (neigh->dr != nid)           /* And not decl. itself DR */
@@ -231,15 +231,15 @@ electdr(list nl)
   struct ospf_neighbor *neigh, *n;
   u32 nid;
 
+  n = NULL;
+  WALK_LIST(neigh, nl)                 /* And now DR */
+  {
 #ifdef OSPFv2
-  nid = ipa_to_u32(neigh->ip);
+    nid = ipa_to_u32(neigh->ip);
 #else /* OSPFv3 */
-  nid = neigh->rid;
+    nid = neigh->rid;
 #endif
 
-  n = NULL;
-  WALK_LIST(neigh, nl)                 /* And now DR */
-  {
     if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
       if (neigh->priority > 0)         /* Eligible */
        if (neigh->dr == nid)           /* And declaring itself DR */
index 2ee6e631036dd1a16019aaedcddf39ac12fd9e98..438e9a54bf2c8c8814b2a874d925f836c3858f50 100644 (file)
@@ -337,7 +337,7 @@ schedule_rtcalc(struct proto_ospf *po)
  * @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.
+ * function for origination of router, network LSAs.
  */
 void
 area_disp(struct ospf_area *oa)
@@ -347,13 +347,18 @@ area_disp(struct ospf_area *oa)
 
   /* Now try to originage rt_lsa */
   if (oa->origrt)
-    originate_rt_lsa(oa);
+    update_rt_lsa(oa);
 
   /* Now try to originate network LSA's */
   WALK_LIST(ifa, po->iface_list)
   {
+#ifdef OSPFv3
+    if (ifa->origlink && (ifa->oa == oa))
+      update_link_lsa(ifa);
+#endif
+
     if (ifa->orignet && (ifa->oa == oa))
-      originate_net_lsa(ifa);
+      update_net_lsa(ifa);
   }
 }
 
@@ -376,7 +381,7 @@ ospf_disp(timer * timer)
 
   /* Calculate routing table */
   if (po->calcrt)
-    ospf_rt_spf (po);
+    ospf_rt_spf(po);
 }
 
 
@@ -1019,6 +1024,7 @@ ospf_sh_iface(struct proto *p, char *iff)
  * according to originating router id (to get all LSA needed to represent one
  * router node together). Then, according to LSA type, ID and age.
  */
+/*
 static int
 he_compare(const void *p1, const void *p2)
 {
@@ -1057,6 +1063,7 @@ he_compare(const void *p1, const void *p2)
       return lsa1->age - lsa2->age;
     }
 }
+*/
 /*
 static inline void
 show_lsa_router(struct top_hash_entry *he)
@@ -1074,7 +1081,7 @@ show_lsa_router(struct top_hash_entry *he)
     if (rr[i].type == LSART_NET)
     {
       struct proto_ospf *po = he->oa->po;
-      struct top_hash_entry *net_he = ospfxx_hash_find(po->gr, he->oa->areaid, rr[i].id, rr[i].id, LSA_T_NET);
+      struct top_hash_entry *net_he = ospf_hash_find(po->gr, he->oa->areaid, rr[i].id, rr[i].id, LSA_T_NET);
       if (net_he)
       {
        struct ospf_lsa_header *net_lsa = &(net_he->lsa);
@@ -1152,12 +1159,13 @@ show_lsa_external(struct top_hash_entry *he)
 void
 ospf_sh_state(struct proto *p, int verbose)
 {
+  /*
   struct proto_ospf *po = (struct proto_ospf *) p;
   struct top_graph *f = po->gr;
   unsigned int i, j;
   u32 last_rt = 0xFFFFFFFF;
   u32 last_area = 0xFFFFFFFF;
-  /*
+
   if (p->proto_state != PS_UP)
   {
     cli_msg(-1016, "%s: is not up", p->name);
index 1e46d3be405f5bd02ee828185ad4e39e860bcbdf..da0104de5cdb8fd706e9311af3501594589dd0aa 100644 (file)
@@ -194,6 +194,7 @@ struct ospf_iface
   u32 dr_iface_id;             /* if drid is valid, this is iface_id of DR (for connecting network) */
   u8 instance_id;              /* Used to differentiate between more OSPF
                                   instances on one interface */
+  ip_addr lladdr;              /* Used link-local addr */
 #endif
 
   u8 type;                     /* OSPF view of type */
@@ -371,8 +372,8 @@ struct ospf_lsa_header
   u32 id;
   u32 rt;                      /* Advertising router */
   s32 sn;                      /* LS Sequence number */
-#define LSA_INITSEQNO 0x80000001
-#define LSA_MAXSEQNO 0x7fffffff
+#define LSA_INITSEQNO ((s32) 0x80000001)
+#define LSA_MAXSEQNO ((s32) 0x7fffffff)
   u16 checksum;
   u16 length;
 };
index e3a3115bf7966271fb189d68423583b22f6b0310..200ef958c93b5aba952df520a3afc36c986920ae 100644 (file)
@@ -278,7 +278,7 @@ ospf_rx_hook(sock * sk, int size)
   if (ifa->stub)
     return (1);
 
-  ps = (struct ospf_packet *) ipv4_skip_header(sk->rbuf, &size);
+  ps = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
 
   if (ps == NULL)
   {
index e64e68af5ebbb5dd1c64466bfac8b24265225108..677ce5b448707df6a1f198877cf075a416ef6900 100644 (file)
@@ -8,12 +8,12 @@
 
 #include "ospf.h"
 
-static void
-add_cand(list * l, struct top_hash_entry *en,
-        struct top_hash_entry *par, u32 dist, struct ospf_area *oa);
-static void
-calc_next_hop(struct top_hash_entry *en,
-             struct top_hash_entry *par, struct ospf_area *oa);
+static void add_cand(list * l, struct top_hash_entry *en, 
+                    struct top_hash_entry *par, u32 dist,
+                    struct ospf_area *oa);
+static void calc_next_hop(struct ospf_area *oa,
+                         struct top_hash_entry *en,
+                         struct top_hash_entry *par);
 static void ospf_ext_spf(struct proto_ospf *po);
 static void rt_sync(struct proto_ospf *po);
 
@@ -27,10 +27,11 @@ static void rt_sync(struct proto_ospf *po);
 
 
 static inline u32 *
-get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts)
+get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest)
 {
   u8 pxl = (*buf >> 24);
   *pxopts = (*buf >> 16);
+  *rest = *buf;
   *pxlen = pxl;
   buf++;
 
@@ -174,6 +175,79 @@ ri_install(struct proto_ospf *po, ip_addr prefix, int pxlen, int dest,
   }
 }
 
+static void
+add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_hash_entry *en)
+{
+  orta nf;
+  nf.type = RTS_OSPF;
+  nf.options = 0;
+  nf.metric1 = metric;
+  nf.metric2 = LSINFINITY;
+  nf.tag = 0;
+  nf.oa = oa;
+  nf.ar = en;
+  nf.nh = en->nh;
+  nf.ifa = en->nhi;
+
+  /* FIXME check nf.ifa on stubs */
+  ri_install(oa->po, px, pxlen, ORT_NET, &nf, NULL);
+}
+
+#ifdef OSPFv3
+static void
+process_prefixes(struct ospf_area *oa)
+{
+  struct proto_ospf *po = oa->po;
+  struct proto *p = &po->proto;
+  struct top_hash_entry *en, *src;
+  struct ospf_lsa_prefix *px;
+  ip_addr pxa;
+  int pxlen;
+  u8 pxopts;
+  u16 metric;
+  u32 *buf;
+  int i;
+
+  WALK_SLIST(en, po->lsal)
+  {
+    if (en->lsa.type != LSA_T_PREFIX)
+      continue;
+
+    if (en->domain != oa->areaid)
+      continue;
+
+    if (en->lsa.age == LSA_MAXAGE)
+      continue;
+
+    px = en->lsa_body;
+    /* FIXME: for router LSA, we should find the first one */
+    src = ospf_hash_find(po->gr, oa->areaid,
+                        ((px->ref_type == LSA_T_RT) ? px->ref_rt : px->ref_id),
+                        px->ref_rt, px->ref_type);
+
+    if (!src)
+      continue;
+
+    if (src->lsa.age == LSA_MAXAGE)
+      continue;
+
+    if ((src->lsa.type != LSA_T_RT) && (src->lsa.type != LSA_T_NET))
+      continue;
+
+    buf = px->rest;
+    for (i = 0; i < px->pxcount; i++)
+      {
+       buf = get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric);
+
+       if (pxopts & OPT_PX_NU)
+         continue;
+
+       add_network(oa, pxa, pxlen, src->dist + metric, src);
+      }
+  }
+}
+#endif
+
 static void
 ospf_rt_spfa(struct ospf_area *oa)
 {
@@ -188,7 +262,6 @@ ospf_rt_spfa(struct ospf_area *oa)
   struct top_hash_entry *act, *tmp;
   node *n;
 
-
   if (oa->rt == NULL)
     return;
 
@@ -226,20 +299,22 @@ ospf_rt_spfa(struct ospf_area *oa)
       rt = (struct ospf_lsa_rt *) act->lsa_body;
       if (rt->options & OPT_RT_V)
        oa->trcap = 1;
+
       /* FIXME - in OSPFv3, should we add all routers, or just ABRs an ASBRs? */
       if ((rt->options & OPT_RT_V) || (rt->options & OPT_RT_E))
-      {
-       nf.type = RTS_OSPF;
-       nf.options = rt->options;
-       nf.metric1 = act->dist;
-       nf.metric2 = LSINFINITY;
-       nf.tag = 0;
-       nf.oa = oa;
-       nf.ar = act;
-       nf.nh = act->nh;
-       nf.ifa = act->nhi;
-       ri_install(po, ipa_from_rid(act->lsa.rt), 32, ORT_ROUTER, &nf, NULL);
-      }
+       {
+         nf.type = RTS_OSPF;
+         nf.options = rt->options;
+         nf.metric1 = act->dist;
+         nf.metric2 = LSINFINITY;
+         nf.tag = 0;
+         nf.oa = oa;
+         nf.ar = act;
+         nf.nh = act->nh;
+         nf.ifa = act->nhi;
+         ri_install(po, ipa_from_rid(act->lsa.rt), 32, ORT_ROUTER, &nf, NULL);
+       }
+
       rr = (struct ospf_lsa_rt_link *) (rt + 1);
       DBG("  Number of links: %u\n", rt->links);
       for (i = 0; i < lsa_rt_count(&act->lsa); i++)
@@ -253,7 +328,6 @@ ospf_rt_spfa(struct ospf_area *oa)
        case LSART_STUB:
          /*
           * This violates rfc2328! But it is mostly harmless.
-          * But it causes that the cost of the stub is ignored.
           */
          DBG("\n");
 
@@ -293,9 +367,9 @@ ospf_rt_spfa(struct ospf_area *oa)
        case LSART_NET:
 #ifdef OSPFv2
          /* In OSPFv2, rtl->id is IP addres of DR, router ID is not known */
-         tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->id, 0, LSA_T_NET);
+         tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, 0, LSA_T_NET);
 #else /* OSPFv3 */
-         tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->nif, rtl->id, LSA_T_NET);
+         tmp = ospf_hash_find(po->gr, oa->areaid, rtl->nif, rtl->id, LSA_T_NET);
 #endif
          if (tmp == NULL)
            DBG("Not found!\n");
@@ -305,8 +379,9 @@ ospf_rt_spfa(struct ospf_area *oa)
 
        case LSART_VLNK:
        case LSART_PTP:
-         /* FIXME - in OSPFv3, find any LSA ID */
-         tmp = ospfxx_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
+         /* FIXME - in OSPFv3, find lowest LSA ID */
+         tmp = ospf_hash_find(po->gr, oa->areaid, rtl->id, rtl->id, LSA_T_RT);
+
          DBG("PTP found.\n");
          break;
        default:
@@ -321,24 +396,18 @@ ospf_rt_spfa(struct ospf_area *oa)
       break;
     case LSA_T_NET:
       ln = act->lsa_body;
-      nf.type = RTS_OSPF;
-      nf.options = 0;
-      nf.metric1 = act->dist;
-      nf.metric2 = LSINFINITY;
-      nf.tag = 0;
-      nf.oa = oa;
-      nf.ar = act;
-      nf.nh = act->nh;
-      nf.ifa = act->nhi;
-      ri_install(po, ipa_and(ipa_from_u32(act->lsa.id), ln->netmask),
-                ipa_mklen(ln->netmask), ORT_NET, &nf, NULL);
+
+#ifdef OSPFv2
+      add_network(oa, ipa_and(ipa_from_u32(act->lsa.id), ln->netmask),
+                 ipa_mklen(ln->netmask), act->dist, act);
+#endif
 
       rts = (u32 *) (ln + 1);
       for (i = 0; i < lsa_net_count(&act->lsa); i++)
       {
        DBG("     Working on router %R ", rts[i]);
        /* FIXME - in OSPFv3, find any LSA ID */
-       tmp = ospfxx_hash_find(po->gr, oa->areaid, 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
@@ -349,13 +418,17 @@ ospf_rt_spfa(struct ospf_area *oa)
     }
   }
 
+#ifdef OSPFv3
+  process_prefixes(oa);
+#endif
+
   /* Find new/lost VLINK peers */
   WALK_LIST(iface, po->iface_list)
   {
     if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
     {
       /* FIXME in OSPFv3, different LSAID */
-      if ((tmp = ospfxx_hash_find(po->gr, oa->areaid, 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->iface) || (!ipa_equal(iface->vip, tmp->lb)))
@@ -379,6 +452,7 @@ ospf_rt_spfa(struct ospf_area *oa)
   }
 }
 
+#if 0
 static int
 link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entry *pre)
 {
@@ -403,7 +477,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
        case LSART_STUB:
          break;
        case LSART_NET:
-         if (ospfxx_hash_find(po->gr, oa->areaid, 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;
@@ -411,7 +485,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
          break;
        case LSART_VLNK:
        case LSART_PTP:
-         if (ospfxx_hash_find(po->gr, oa->areaid, 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;
@@ -428,7 +502,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
       rts = (u32 *) (ln + 1);
       for (i = 0; i < lsa_net_count(&fol->lsa); i++)
       {
-       if (ospfxx_hash_find(po->gr, oa->areaid, *(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;
         }
@@ -439,6 +513,7 @@ link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entr
   }
   return 0;
 }
+#endif
 
 static void
 ospf_rt_sum_tr(struct ospf_area *oa)
@@ -481,8 +556,10 @@ ospf_rt_sum_tr(struct ospf_area *oa)
       ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
 #else /* OSPFv3 */
       u8 pxopts;
+      u16 rest;
       struct ospf_lsa_sum_net *ls = en->lsa_body;
-      get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts);
+      get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
+
       if (pxopts & OPT_PX_NU)
        continue;
 #endif
@@ -578,8 +655,10 @@ ospf_rt_sum(struct ospf_area *oa)
       ip = ipa_and(ipa_from_u32(en->lsa.id), ls->netmask);
 #else /* OSPFv3 */
       u8 pxopts;
+      u16 rest;
       struct ospf_lsa_sum_net *ls = en->lsa_body;
-      get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts);
+      get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
+
       if (pxopts & OPT_PX_NU)
        continue;
 #endif
@@ -779,8 +858,9 @@ ospf_ext_spf(struct proto_ospf *po)
     rt_tag = le->tag;
 #else /* OSPFv3 */
     u8 pxopts;
+    u16 rest;
     u32 *buf = le->rest;
-    buf = get_ipv6_prefix(buf, &ip, &pxlen, &pxopts);
+    buf = get_ipv6_prefix(buf, &ip, &pxlen, &pxopts, &rest);
 
     if (pxopts & OPT_PX_NU)
       continue;
@@ -893,11 +973,21 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
   int added = 0;
   struct top_hash_entry *act;
 
+  /* 16.1. (2b) */
   if (en == NULL)
     return;
   if (en->lsa.age == LSA_MAXAGE)
     return;
 
+#ifdef OSPFv3
+  if (en->lsa.type == LSA_T_RT)
+    {
+      struct ospf_lsa_rt *rt = en->lsa_body;
+      if (!(rt->options & OPT_V6) || !(rt->options & OPT_R))
+       return;
+    }
+#endif
+
   /* 16.1. (2c) */
   if (en->color == INSPF)
     return;
@@ -910,16 +1000,15 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
    * next hops. I'll start as soon as nest will
    */
 
+  /* FIXME - fix link_back()
   if (!link_back(oa, en, par))
     return;
+  */
 
   DBG("     Adding candidate: rt: %R, id: %R, type: %u\n",
       en->lsa.rt, en->lsa.id, en->lsa.type);
 
-  en->nhi = NULL;
-  en->nh = IPA_NONE;
-
-  calc_next_hop(en, par, oa);
+  calc_next_hop(oa, en, par);
 
   if (!en->nhi)
     return;                    /* We cannot find next hop, ignore it */
@@ -963,21 +1052,33 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
   }
 }
 
+
+static inline int
+match_dr(struct ospf_iface *ifa, struct top_hash_entry *en)
+{
+#ifdef OSPFv2
+  return (ifa->drid == en->lsa.rt) && (ifa->drip == ipa_from_u32(en->lsa.id));
+#else /* OSPFv3 */
+  return (ifa->drid == en->lsa.rt) && (ifa->dr_iface_id == en->lsa.id);
+#endif
+}
+
 static void
-calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
-             struct ospf_area *oa)
+calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
+             struct top_hash_entry *par)
 {
   struct ospf_neighbor *neigh;
   struct proto *p = &oa->po->proto;
   struct proto_ospf *po = oa->po;
   struct ospf_iface *ifa;
-  u32 myrid = p->cf->global->router_id;
+
+  en->nhi = NULL;
+  en->nh = IPA_NONE;
 
   /* 16.1.1. The next hop calculation */
   DBG("     Next hop called.\n");
   if (ipa_equal(par->nh, IPA_NONE))
   {
-    neighbor *nn;
     DBG("     Next hop calculating for id: %R rt: %R type: %u\n",
        en->lsa.id, en->lsa.rt, en->lsa.type);
 
@@ -986,36 +1087,21 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
     {
       if (en->lsa.type == LSA_T_NET)
       {
-       if (en->lsa.rt == myrid)
-       {
-         WALK_LIST(ifa, po->iface_list)
-           if (ifa->iface && (ipa_compare
-               (ifa->iface->addr->ip, ipa_from_u32(en->lsa.id)) == 0))
+       WALK_LIST(ifa, po->iface_list)
+         if (match_dr(ifa, en))
          {
-           en->nhi = ifa;
-           return;
+             en->nhi = ifa;
+             return;
          }
-         log(L_ERR "I didn't find interface for my self originated LSA!\n");
-         /* This could sometimes happen */
-         return;
-       }
-       else
-       {
-         ip_addr ip = ipa_from_u32(en->lsa.id);
-         nn = neigh_find(p, &ip, 0);
-         if (nn)
-           en->nhi = ospf_iface_find(po, nn->iface);
-         return;
-       }
+       return;
       }
       else
       {
        if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
          return;
        en->nhi = neigh->ifa;
-       if (ipa_equal(en->nh, IPA_NONE))
-         en->nh = neigh->ip;   /* Yes, neighbor is it's
-                                * own next hop */
+       en->nh = neigh->ip;
+       /* Yes, neighbor is it's own next hop */
        return;
       }
     }
@@ -1028,11 +1114,12 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
        bug("Parent for net is net?");
       if ((en->nhi = par->nhi) == NULL)
        bug("Did not find next hop interface for INSPF lsa!");
+
       if ((neigh = find_neigh_noifa(po, en->lsa.rt)) == NULL)
        return;
       en->nhi = neigh->ifa;
-      en->nh = neigh->ip;      /* Yes, neighbor is it's own
-                                * next hop */
+      en->nh = neigh->ip;
+      /* Yes, neighbor is it's own next hop */
       return;
     }
     else
@@ -1043,8 +1130,8 @@ calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par,
       return;
     }
   }
-  en->nh = par->nh;
   en->nhi = par->nhi;
+  en->nh = par->nh;
   DBG("     Next hop calculated: %I.\n", en->nh);
 }
 
@@ -1098,7 +1185,7 @@ again1:
           if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
           {
            /* FIXME in OSPFv3, may be different LSA ID */
-            if ((en = ospfxx_hash_find(po->gr, ifa->voa->areaid, 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 21627f05943263826b65343906f83209072b112b..360e36278c58234a76ea8e0514baa59d2fba3e18 100644 (file)
 #define HASH_LO_STEP 2
 #define HASH_LO_MIN 8
 
+void originate_prefix_rt_lsa(struct ospf_area *oa);
+void originate_prefix_net_lsa(struct ospf_iface *ifa);
+
+#ifdef OSPFv2
+#define ipa_to_rid(x) _I(x)
+#else /* OSPFv3 */
+#define ipa_to_rid(x) _I3(x)
+#endif
+
+/* FIXME very ugly hack */
+#ifdef OSPFv2
+#define ipa_to_lsaid(x) _I(x)
+#else /* OSPFv3 */
+#define ipa_to_lsaid(x) _I0(x) ^ _I1(x) ^ _I2(x) ^ _I3(x)
+#endif
+
+
 static void *
 lsab_alloc(struct proto_ospf *po, unsigned size)
 {
@@ -300,7 +317,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
 {
   struct proto_ospf *po = oa->po;
   struct ospf_iface *ifa;
-  int i = 0, j = 0, k = 0, bitv = 0;
+  int bitv = 0;
   struct ospf_lsa_rt *rt;
   struct ospf_neighbor *neigh;
 
@@ -390,18 +407,9 @@ originate_rt_lsa(struct ospf_area *oa)
   struct ospf_lsa_header lsa;
   struct proto_ospf *po = oa->po;
   struct proto *p = &po->proto;
-  u32 rtid = po->proto.cf->global->router_id;
-  struct top_hash_entry *en;
+  u32 rid = po->proto.cf->global->router_id;
   void *body;
 
-  if ((oa->rt) && ((oa->rt->inst_t + MINLSINTERVAL)) > now)
-    return;
-  /*
-   * Tick is probably set to very low value. We cannot
-   * originate new LSA before MINLSINTERVAL. We will
-   * try to do it next tick.
-   */
-
   OSPF_TRACE(D_EVENTS, "Originating RT_lsa for area %R.", oa->areaid);
 
   lsa.age = 0;
@@ -411,16 +419,33 @@ originate_rt_lsa(struct ospf_area *oa)
   lsa.options = oa->options;
 #endif
   
-  lsa.id = rtid;
-  lsa.rt = rtid;
+  lsa.id = rid;
+  lsa.rt = rid;
   lsa.sn = oa->rt ? (oa->rt->lsa.sn + 1) : LSA_INITSEQNO;
   u32 dom = oa->areaid;
 
   body = originate_rt_lsa_body(oa, &lsa.length);
   lsasum_calculate(&lsa, body);
-  en = lsa_install_new(po, &lsa, dom, body);
-  oa->rt = en;
-  ospf_lsupd_flood(po, NULL, NULL, &oa->rt->lsa, dom, 1);
+  oa->rt = lsa_install_new(po, &lsa, dom, body);
+  ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
+}
+
+void
+update_rt_lsa(struct ospf_area *oa)
+{
+  struct proto_ospf *po = oa->po;
+
+  if ((oa->rt) && ((oa->rt->inst_t + MINLSINTERVAL)) > now)
+    return;
+  /*
+   * Tick is probably set to very low value. We cannot
+   * originate new LSA before MINLSINTERVAL. We will
+   * try to do it next tick.
+   */
+
+  originate_rt_lsa(oa);
+  originate_prefix_rt_lsa(oa);
+
   schedule_rtcalc(po);
   oa->origrt = 0;
 }
@@ -454,7 +479,7 @@ originate_net_lsa_body(struct ospf_iface *ifa, u16 *length,
     if (n->state == NEIGHBOR_FULL)
     {
 #ifdef OSPFv3
-      en = ospfxx_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK);
+      en = ospf_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK);
       if (en)
        options |= ((struct ospf_lsa_link *) en->lsa_body)->options;
 #endif
@@ -474,6 +499,7 @@ originate_net_lsa_body(struct ospf_iface *ifa, u16 *length,
   return net;
 }
 
+
 /**
  * originate_net_lsa - originates of deletes network LSA
  * @ifa: interface which is LSA originated for
@@ -488,39 +514,11 @@ originate_net_lsa(struct ospf_iface *ifa)
 {
   struct proto_ospf *po = ifa->oa->po;
   struct ospf_lsa_header lsa;
-  u32 rtid = po->proto.cf->global->router_id;
+  u32 rid = po->proto.cf->global->router_id;
   u32 dom = ifa->oa->areaid;
   struct proto *p = &po->proto;
   void *body;
 
-  if (ifa->net_lsa && ((ifa->net_lsa->inst_t + MINLSINTERVAL) > now))
-    return;
-  /*
-   * It's too early to originate new network LSA. We will
-   * try to do it next tick
-   */
-
-  if ((ifa->state != OSPF_IS_DR) || (ifa->fadj == 0))
-  {
-    if (ifa->net_lsa == NULL)
-      return;
-
-    OSPF_TRACE(D_EVENTS, "Deleting Net lsa for iface \"%s\".",
-              ifa->iface->name);
-    ifa->net_lsa->lsa.sn += 1;
-    ifa->net_lsa->lsa.age = LSA_MAXAGE;
-    lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
-    ospf_lsupd_flood(po, NULL, NULL, &ifa->net_lsa->lsa, dom, 0);
-    s_rem_node(SNODE ifa->net_lsa);
-    if (ifa->net_lsa->lsa_body != NULL)
-      mb_free(ifa->net_lsa->lsa_body);
-    ifa->net_lsa->lsa_body = NULL;
-    ospf_hash_delete(po->gr, ifa->net_lsa);
-    schedule_rtcalc(po);
-    ifa->net_lsa = NULL;
-    return;
-  }
-
   OSPF_TRACE(D_EVENTS, "Originating Net lsa for iface \"%s\".",
             ifa->iface->name);
 
@@ -534,16 +532,63 @@ originate_net_lsa(struct ospf_iface *ifa)
   lsa.id = ifa->iface->index;
 #endif
 
-  lsa.rt = rtid;
+  lsa.rt = rid;
   lsa.sn = ifa->net_lsa ? (ifa->net_lsa->lsa.sn + 1) : LSA_INITSEQNO;
 
   body = originate_net_lsa_body(ifa, &lsa.length, po);
   lsasum_calculate(&lsa, body);
   ifa->net_lsa = lsa_install_new(po, &lsa, dom, body);
   ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
-  ifa->orignet = 0;
 }
 
+void
+flush_net_lsa(struct ospf_iface *ifa)
+{
+  struct proto_ospf *po = ifa->oa->po;
+  struct proto *p = &po->proto;
+  u32 dom = ifa->oa->areaid;
+
+  if (ifa->net_lsa == NULL)
+    return;
+
+  OSPF_TRACE(D_EVENTS, "Deleting Net lsa for iface \"%s\".",
+            ifa->iface->name);
+  ifa->net_lsa->lsa.sn += 1;
+  ifa->net_lsa->lsa.age = LSA_MAXAGE;
+  lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
+  ospf_lsupd_flood(po, NULL, NULL, &ifa->net_lsa->lsa, dom, 0);
+
+
+  flush_lsa(ifa->net_lsa, po);
+  ifa->net_lsa = NULL;
+}
+
+void
+update_net_lsa(struct ospf_iface *ifa)
+{
+  struct proto_ospf *po = ifa->oa->po;
+  if (ifa->net_lsa && ((ifa->net_lsa->inst_t + MINLSINTERVAL) > now))
+    return;
+  /*
+   * It's too early to originate new network LSA. We will
+   * try to do it next tick
+   */
+
+  if ((ifa->state != OSPF_IS_DR) || (ifa->fadj == 0))
+    {
+      flush_net_lsa(ifa);
+      flush_prefix_net_lsa(ifa);
+    }
+  else
+    {
+      originate_net_lsa(ifa);
+      originate_prefix_net_lsa(ifa);
+    }
+
+  schedule_rtcalc(po);
+  ifa->orignet = 0;
+}
 
 #ifdef OSPFv2
 
@@ -630,7 +675,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri
   u32 dom = oa->areaid;  
 
   /* FIXME check for the same LSA */
-  if ((en = ospfxx_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
+  if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
     lsa.sn = en->lsa.sn + 1;
 
   if (type == ORT_NET)
@@ -677,7 +722,7 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
       lsa.type = LSA_T_SUM_RT;
     }
 
-  if ((en = ospfxx_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
+  if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL)
     {
       struct ospf_lsa_sum *sum = en->lsa_body;
       en->lsa.age = LSA_MAXAGE;
@@ -733,10 +778,12 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
     mlen = nf->fn.pxlen;
     ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen));
 
-    if ((oa == po->backbone) && (nf->n.type == RTS_OSPF_IA)) flush = 1;        /* Only intra-area can go to the backbone */
+    if ((oa == po->backbone) && (nf->n.type == RTS_OSPF_IA))
+      flush = 1;       /* Only intra-area can go to the backbone */
 
-    if ((!flush) && (dest == ORT_NET) && fib_route(&nf->n.oa->net_fib, ip, mlen))      /* The route fits into area networks */
+    if ((!flush) && (dest == ORT_NET) && fib_route(&nf->n.oa->net_fib, ip, mlen))
     {
+      /* The route fits into area networks */
       flush = 1;
       if ((nf->n.oa == po->backbone) && (oa->trcap)) flush = 0;
     }
@@ -833,8 +880,6 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
   void *body;
   struct proto *p = &po->proto;
   struct ospf_area *oa;
-  struct ospf_lsa_ext *ext1, *ext2;
-  int i, max;
 
   OSPF_TRACE(D_EVENTS, "Originating Ext lsa for %I/%d.", n->n.prefix,
             n->n.pxlen);
@@ -850,7 +895,7 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
   /* FIXME proper handling of LSA IDs and check for the same network */
   lsa.id = ipa_to_lsaid(n->n.prefix);
 
-  if ((en = ospfxx_hash_find_header(po->gr, 0, &lsa)) != NULL)
+  if ((en = ospf_hash_find_header(po->gr, 0, &lsa)) != NULL)
     {
       lsa.sn = en->lsa.sn + 1;
     }
@@ -877,13 +922,11 @@ flush_ext_lsa(net *n, struct proto_ospf *po)
   u32 rid = po->proto.cf->global->router_id;
   struct ospf_area *oa;
   struct top_hash_entry *en;
-  struct ospf_lsa_ext *ext;
-  int i;
 
   /* FIXME proper handling of LSA IDs and check for the same network */
   u32 lsaid = ipa_to_lsaid(n->n.prefix);
 
-  if (en = ospfxx_hash_find(po->gr, 0, lsaid, rid, LSA_T_EXT))
+  if (en = ospf_hash_find(po->gr, 0, lsaid, rid, LSA_T_EXT))
     {
       /* FIXME this is nonsense */
       WALK_LIST(oa, po->area_list)
@@ -907,7 +950,7 @@ originate_link_lsa_body(struct ospf_iface *ifa, u16 *length)
   ASSERT(po->lsab_used == 0);
   ll = lsab_allocz(po, sizeof(struct ospf_lsa_link));
   ll->options = ifa->oa->options | (ifa->priority << 24);
-  ll->lladdr = FIX;
+  ll->lladdr = ifa->lladdr;
   ll = NULL; /* buffer might be reallocated later */
 
   struct ifa *a;
@@ -935,23 +978,16 @@ originate_link_lsa(struct ospf_iface *ifa)
   struct ospf_lsa_header lsa;
   struct proto_ospf *po = ifa->oa->po;
   struct proto *p = &po->proto;
-  u32 rtid = po->proto.cf->global->router_id;
+  u32 rid = po->proto.cf->global->router_id;
   void *body;
 
-  if (ifa->link_lsa && ((ifa->link_lsa->inst_t + MINLSINTERVAL) > now))
-    return;
-  /*
-   * It's too early to originate new link LSA. We will
-   * try to do it next tick
-   */
-
   /* 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 = LSA_T_LINK;
   lsa.id = ifa->iface->index;
-  lsa.rt = rtid;
+  lsa.rt = rid;
   lsa.sn = ifa->link_lsa ? (ifa->link_lsa->lsa.sn + 1) : LSA_INITSEQNO;
   u32 dom = ifa->iface->index;
 
@@ -959,9 +995,20 @@ originate_link_lsa(struct ospf_iface *ifa)
   lsasum_calculate(&lsa, body);
   ifa->link_lsa = lsa_install_new(po, &lsa, dom, body);
   ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
-  ifa->origlink = 0;
 }
 
+void
+update_link_lsa(struct ospf_iface *ifa)
+{
+  if (ifa->link_lsa && ((ifa->link_lsa->inst_t + MINLSINTERVAL) > now))
+    return;
+  /*
+   * It's too early to originate new link LSA. We will
+   * try to do it next tick
+   */
+  originate_link_lsa(ifa);
+  ifa->origlink = 0;
+}
 
 static void *
 originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
@@ -1129,7 +1176,7 @@ originate_prefix_net_lsa_body(struct ospf_iface *ifa, u16 *length)
   /* Find all Link LSA associated with the link and merge their prefixes */
   WALK_LIST(n, ifa->neigh_list)
     if ((n->state == NEIGHBOR_FULL) &&
-       (en = ospfxx_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK)))
+       (en = ospf_hash_find(po->gr, ifa->iface->index, n->iface_id, n->rid, LSA_T_LINK)))
       {
        ll = en->lsa_body;
        pxb = ll->rest;
@@ -1170,6 +1217,7 @@ originate_prefix_net_lsa(struct ospf_iface *ifa)
 
 #endif
 
+
 static void
 ospf_top_ht_alloc(struct top_graph *f)
 {
@@ -1263,7 +1311,7 @@ ospf_top_rehash(struct top_graph *f, int step)
 
   oldn = f->hash_size;
   oldt = f->hash_table;
-  dbg("re-hashing topology hash from order %d to %d\n", f->hash_order,
+  DBG("re-hashing topology hash from order %d to %d\n", f->hash_order,
       f->hash_order + step);
   f->hash_order += step;
   ospf_top_ht_alloc(f);
@@ -1284,20 +1332,37 @@ ospf_top_rehash(struct top_graph *f, int step)
   ospf_top_ht_free(oldt);
 }
 
+u32
+ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
+{
+  switch (type & LSA_SCOPE_MASK)
+    {
+    case LSA_SCOPE_LINK:
+      return ifa->iface->index;
+
+    case LSA_SCOPE_AREA:
+      return ifa->oa->areaid;
+
+    case LSA_SCOPE_AS:
+    default:
+      return 0;
+    }
+}
+
 struct top_hash_entry *
-ospfxx_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
+ospf_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
 {
-  return ospfxx_hash_find(f, domain, h->id, h->rt, h->type);
+  return ospf_hash_find(f, domain, h->id, h->rt, h->type);
 }
 
 struct top_hash_entry *
-ospfxx_hash_get_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
+ospf_hash_get_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
 {
-  return ospfxx_hash_get(f, domain, h->id, h->rt, h->type);
+  return ospf_hash_get(f, domain, h->id, h->rt, h->type);
 }
 
 struct top_hash_entry *
-ospfxx_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
+ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
 {
   struct top_hash_entry *e;
 
@@ -1322,7 +1387,7 @@ ospfxx_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
 }
 
 struct top_hash_entry *
-ospfxx_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
+ospf_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
 {
   struct top_hash_entry **ee;
   struct top_hash_entry *e;
@@ -1379,6 +1444,7 @@ ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
 static void
 ospf_dump_lsa(struct top_hash_entry *he, struct proto *p)
 {
+  /*
   struct ospf_lsa_rt *rt = NULL;
   struct ospf_lsa_rt_link *rr = NULL;
   struct ospf_lsa_net *ln = NULL;
@@ -1389,7 +1455,7 @@ ospf_dump_lsa(struct top_hash_entry *he, struct proto *p)
             he->lsa.type, he->lsa.id, he->lsa.rt, he->lsa.age, he->lsa.sn,
             he->lsa.checksum, he->domain);
 
-  /*
+
   switch (he->lsa.type)
     {
     case LSA_T_RT:
index 4555bea2855a274ee53eb041f7f0557b44b6e5d3..5bb3397a05f5267ca513f5b8cfdff18f983a2097 100644 (file)
@@ -47,27 +47,27 @@ 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 *ospfxx_hash_find_header(struct top_graph *f, u32 areaid,
+u32 ospf_lsa_domain(u32 type, struct ospf_iface *ifa);
+struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, u32 domain,
                                             struct ospf_lsa_header *h);
-struct top_hash_entry *ospfxx_hash_get_header(struct top_graph *f, u32 domain,
+struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, u32 domain,
                                            struct ospf_lsa_header *h);
 
-struct top_hash_entry *ospfxx_hash_find_smart(struct top_graph *f, struct ospf_iface *ifa,
-                                            struct ospf_lsa_header *h);
-struct top_hash_entry *ospfxx_hash_get_smart(struct top_graph *f, struct ospf_iface *ifa,
-                                           struct ospf_lsa_header *h);
-
-struct top_hash_entry *ospfxx_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
+struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
                                      u32 type);
-struct top_hash_entry *ospfxx_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
+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);
+void update_net_lsa(struct ospf_iface *ifa);
+void update_link_lsa(struct ospf_iface *ifa);
 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);
+void flush_ext_lsa(net *n, struct proto_ospf *po);
 void check_sum_lsa(struct proto_ospf *po, ort *nf, int);
 void originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric, u32 options);
 void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
index 2e85f54b8176b8d8692adbdfb928d8b064069342..b7fd479b0696c08ff025e70e8c273cef67a26705 100644 (file)
@@ -390,7 +390,6 @@ nl_parse_addr(struct nlmsghdr *h)
   else
     {
       ip_addr netmask = ipa_mkmask(ifa.pxlen);
-      ip_addr xbrd;
       ifa.prefix = ipa_and(ifa.ip, netmask);
       ifa.brd = ipa_or(ifa.ip, ipa_not(netmask));
 #ifndef IPV6
@@ -398,6 +397,7 @@ nl_parse_addr(struct nlmsghdr *h)
        ifa.opposite = ipa_opposite(ifa.ip, i->ifa_prefixlen);
       if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
        {
+         ip_addr xbrd;
          memcpy(&xbrd, RTA_DATA(a[IFA_BROADCAST]), sizeof(xbrd));
          ipa_ntoh(xbrd);
          if (ipa_equal(xbrd, ifa.prefix) || ipa_equal(xbrd, ifa.brd))