]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
A lot of changes:
authorOndrej Filip <feela@network.cz>
Fri, 25 Jun 2004 16:39:53 +0000 (16:39 +0000)
committerOndrej Filip <feela@network.cz>
Fri, 25 Jun 2004 16:39:53 +0000 (16:39 +0000)
- metric is 3 byte long now
- summary lsa originating
- more OSPF areas possible
- virtual links
- better E1/E2 routes handling
- some bug fixes..

I have to do:
- md5 auth (last mandatory item from rfc2328)
- !!!!DEBUG!!!!! (mainly virtual link system has probably a lot of bugs)
- 2328 appendig E

23 files changed:
TODO
doc/bird.sgml
nest/config.Y
nest/route.h
nest/rt-attr.c
proto/bgp/attrs.c
proto/ospf/config.Y
proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/iface.h
proto/ospf/lsack.c
proto/ospf/lsalib.c
proto/ospf/lsreq.c
proto/ospf/lsupd.c
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/packet.h
proto/ospf/rt.c
proto/ospf/rt.h
proto/ospf/topology.c
proto/ospf/topology.h

diff --git a/TODO b/TODO
index 6b74e758a9e7a0b337a51062aa63444f3f139e69..0945aac44c1a5ba50092919d210362ee75eed911 100644 (file)
--- a/TODO
+++ b/TODO
@@ -51,7 +51,5 @@ OSPF
        - automatic generation of external route tags (RFC1403)
        - RFC1587 NSSA areas
        - RFC2370 opaque LSA's
-       - respect interface MTU and try not to create larger packets unless unavoidable
         - AS external LSAs are in topology database of every OSPF Area
         - Limit export rate of external LSAs (like Gated does)
-        - Maximal distance is just 0xffff, but 2328 requires 0xffffff
index 92db29219d3dd48df2791badeb8e6c3f157d38b5..00b449daa99c5eef77f2a7448998d3aa6506de9f 100644 (file)
@@ -1034,6 +1034,16 @@ protocol ospf &lt;name&gt; {
                                &lt;ip&gt; eligible;
                        };
                };
+               virtual link &lt;id&gt;
+               {
+                       hello &lt;num&gt;;
+                       poll &lt;num&gt;;
+                       retransmit &lt;num&gt;;
+                       wait &lt;num&gt;;
+                       dead count &lt;num&gt;;
+                       authentication [none|simple];
+                       password "&lt;text&gt;";
+               };
        };
 }
 </code>
@@ -1068,6 +1078,10 @@ protocol ospf &lt;name&gt; {
        <tag>interface <M>pattern</M></tag>
         Defines that the specified interfaces belong to the area being defined.
 
+       <tag>virtual link <M>id</M></tag>
+        Virtual link to router with the router id. This item cannot be in the
+         backbone area (ID 0).
+
        <tag>cost <M>num</M></tag>
         Specifies output cost (metric) of an interface. Default value is 10.
 
@@ -1163,7 +1177,7 @@ protocol ospf MyOSPF {
                        ospf_metric1 = 100;
                        accept;
                }
-       reject;
+               reject;
        };                                                                      
        area 0.0.0.0 {
                tick 8;
@@ -1185,6 +1199,10 @@ protocol ospf MyOSPF {
        };
        area 120 {
                stub yes;
+               networks {
+                       172.16.1.0/24;
+                       172.16.2.0/24 hidden;
+               }
                interface "-arc0" , "arc*" {
                        type nonbroadcast;
                        authentication none;
index fa8b5e660c147c394d6dd8653df7000217899471..4f9b46b6483bcee57cb9398a17661600dcdcf693 100644 (file)
@@ -25,7 +25,7 @@ CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFA
 CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREIMPORT)
 
 CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
-       RIP, OSPF, OSPF_EXT, OSPF_IA, BGP, PIPE)
+       RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
 CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE)
 CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST)
 CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT)
index 14ac9e7013499397edec1fa9bbadeec68013e79c..0de0e0f7593e913ab8d18c0622312dfb20274201 100644 (file)
@@ -253,9 +253,10 @@ typedef struct rta {
 #define RTS_RIP 6                      /* RIP route */
 #define RTS_OSPF 7                     /* OSPF route */
 #define RTS_OSPF_IA 8                  /* OSPF inter-area route */
-#define RTS_OSPF_EXT 9                 /* OSPF external route */
-#define RTS_BGP 10                     /* BGP route */
-#define RTS_PIPE 11                    /* Inter-table wormhole */
+#define RTS_OSPF_EXT1 9                        /* OSPF external route type 1 */
+#define RTS_OSPF_EXT2 10               /* OSPF external route type 2 */
+#define RTS_BGP 11                     /* BGP route */
+#define RTS_PIPE 12                    /* Inter-table wormhole */
 
 #define RTC_UNICAST 0
 #define RTC_BROADCAST 1
index 14a2480f4b4da82ab62d8164ebfb18ba1a605e85..cbece881931fd4818f326b52268be994dc19d105 100644 (file)
@@ -705,7 +705,8 @@ rta_dump(rta *a)
 {
   static char *rts[] = { "RTS_DUMMY", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE",
                         "RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP",
-                        "RTS_OSPF", "RTS_OSPF_EXT", "RTS_OSPF_IA", "RTS_BGP" };
+                        "RTS_OSPF", "RTS_OSPF_IA", "RTS_OSPF_EXT1",
+                         "RTS_OSPF_EXT2", "RTS_BGP" };
   static char *rtc[] = { "", " BC", " MC", " AC" };
   static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
 
index 3cb99e008abfc95b77d3765f0ad9c9d6f4e9365a..459335fac04e95944c4b4140a2b7d303da1383a0 100644 (file)
@@ -560,7 +560,7 @@ bgp_create_attrs(struct bgp_proto *p, rte *e, ea_list **attrs, struct linpool *p
   ea->count = 4;
 
   bgp_set_attr(ea->attrs, pool, BA_ORIGIN,
-       (rta->source == RTS_OSPF_EXT) ? ORIGIN_INCOMPLETE : ORIGIN_IGP);
+       ((rta->source == RTS_OSPF_EXT1) || (rta->source == RTS_OSPF_EXT2)) ? ORIGIN_INCOMPLETE : ORIGIN_IGP);
 
   if (p->is_internal)
     bgp_set_attr(ea->attrs+1, pool, BA_AS_PATH, 0);
index 3a9904fb5cad05859cdba63183210ab5e85c186b..b484d79c34afbf666f2984615e6b3cc12207cc54 100644 (file)
@@ -17,7 +17,7 @@ static struct ospf_area_config *this_area;
 static struct iface_patt *this_ipatt;
 #define OSPF_PATT ((struct ospf_iface_patt *) this_ipatt)
 static struct nbma_node *this_nbma;
-static struct area_net *this_pref;
+static struct area_net_config *this_pref;
 
 CF_DECLS
 
@@ -25,7 +25,7 @@ CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG)
 CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
 CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE)
 CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, PASSWORD, STRICT)
-CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN)
+CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, LINK)
 
 %type <t> opttext
 
@@ -78,8 +78,46 @@ ospf_area_item:
  | TICK expr { this_area->tick = $2 ; if($2<=0) cf_error("Tick must be greater than zero"); }
  | NETWORKS '{' pref_list '}'
  | INTERFACE ospf_iface_list
+ | ospf_vlink '}'
  ;
 
+ospf_vlink: ospf_vlink_start ospf_vlink_opts
+ ;
+
+ospf_vlink_opts:
+   /* empty */
+ | ospf_vlink_opts ospf_vlink_item ';'
+ ;
+
+ospf_vlink_item:
+   HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); }
+ | POLL expr { OSPF_PATT->pollint = $2 ; if ($2<=0) cf_error("Poll int must be greater than zero"); }
+ | RETRANSMIT expr { OSPF_PATT->rxmtint = $2 ; if ($2<=0) cf_error("Retransmit int must be greater than zero"); }
+ | TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
+ | WAIT expr { OSPF_PATT->waitint = $2 ; }
+ | DEAD COUNT expr { OSPF_PATT->deadc = $3 ; if ($3<=1) cf_error("Dead count must be greater than one"); }
+ | AUTHENTICATION NONE { OSPF_PATT->autype = AU_NONE ; }
+ | AUTHENTICATION SIMPLE { OSPF_PATT->autype = AU_SIMPLE ; }
+ | PASSWORD TEXT { memcpy(OSPF_PATT->password, $2, 8); }
+ ;
+
+ospf_vlink_start: VIRTUAL LINK '{'
+ {
+  if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone");
+  this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt));
+  add_tail(&this_area->patt_list, NODE this_ipatt);
+  OSPF_PATT->cost = COST_D;
+  OSPF_PATT->helloint = HELLOINT_D;
+  OSPF_PATT->pollint = POLLINT_D;
+  OSPF_PATT->rxmtint = RXMTINT_D;
+  OSPF_PATT->inftransdelay = INFTRANSDELAY_D;
+  OSPF_PATT->waitint = WAIT_DMH*HELLOINT_D;
+  OSPF_PATT->deadc = DEADC_D;
+  OSPF_PATT->type = OSPF_IT_VLINK;
+  OSPF_PATT->autype = AU_NONE;
+ }
+;
+
 ospf_iface_item:
    COST expr { OSPF_PATT->cost = $2 ; if (($2<=0) || ($2>65535)) cf_error("Cost must be in range 1-65535"); }
  | HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); }
@@ -95,8 +133,8 @@ ospf_iface_item:
  | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
  | STUB bool { OSPF_PATT->stub = $2 ; }
  | NEIGHBORS '{' ipa_list '}'
- | AUTHENTICATION NONE { OSPF_PATT->autype=AU_NONE ; }
- | AUTHENTICATION SIMPLE { OSPF_PATT->autype=AU_SIMPLE ; }
+ | AUTHENTICATION NONE { OSPF_PATT->autype = AU_NONE ; }
+ | AUTHENTICATION SIMPLE { OSPF_PATT->autype = AU_SIMPLE ; }
  | PASSWORD TEXT { memcpy(OSPF_PATT->password, $2, 8); }
  ;
 
@@ -111,7 +149,7 @@ pref_item:
 
 pref_el: prefix ';'
  {
-   this_pref = cfg_allocz(sizeof(struct area_net));
+   this_pref = cfg_allocz(sizeof(struct area_net_config));
    add_tail(&this_area->net_list, NODE this_pref);
    this_pref->px.addr = $1.addr;
    this_pref->px.len = $1.len;
@@ -120,7 +158,7 @@ pref_el: prefix ';'
 
 pref_hid: prefix HIDDEN ';'
  {
-   this_pref = cfg_allocz(sizeof(struct area_net));
+   this_pref = cfg_allocz(sizeof(struct area_net_config));
    add_tail(&this_area->net_list, NODE this_pref);
    this_pref->px.addr = $1.addr;
    this_pref->px.len = $1.len;
@@ -172,7 +210,7 @@ ospf_iface_start:
   OSPF_PATT->strictnbma = 0;
   OSPF_PATT->stub = 0;
   init_list(&OSPF_PATT->nbma_list);
-  OSPF_PATT->autype=AU_NONE;
+  OSPF_PATT->autype = AU_NONE;
  }
 ;
 
index bff8beff87fc758250b7258e34ae2712e6752e9d..c345858bb4272f8db714384ca56ecf21eaaf3f52 100644 (file)
@@ -39,14 +39,14 @@ ospf_dbdes_send(struct ospf_neighbor *n)
     pkt = (struct ospf_dbdes_packet *) (ifa->ip_sk->tbuf);
     op = (struct ospf_packet *) pkt;
     fill_ospf_pkt_hdr(ifa, pkt, DBDES_P);
-    pkt->iface_mtu = htons(ifa->iface->mtu);   /* FIXME NOT for VLINK! */
+    pkt->iface_mtu = htons(ifa->iface->mtu);
     pkt->options = ifa->options;
     pkt->imms = n->myimms;
     pkt->ddseq = htonl(n->dds);
     length = sizeof(struct ospf_dbdes_packet);
     op->length = htons(length);
     ospf_pkt_finalize(ifa, op);
-    sk_send_to(ifa->ip_sk, length, n->ip, OSPF_PROTO);
+    ospf_send_to(ifa->ip_sk, length, n->ip);
     OSPF_TRACE(D_PACKETS, "DB_DES (I) sent to %I via %s.", n->ip,
               ifa->iface->name);
     break;
@@ -79,20 +79,26 @@ ospf_dbdes_send(struct ospf_neighbor *n)
        for (; i > 0; i--)
        {
          struct top_hash_entry *en;
-
          en = (struct top_hash_entry *) sn;
-         htonlsah(&(en->lsa), lsa);
-         DBG("Working on: %d\n", i);
-         DBG("\tX%01x %-1I %-1I %p\n", en->lsa.type, en->lsa.id,
-             en->lsa.rt, en->lsa_body);
+
+          if ((n->ifa->type != OSPF_IT_VLINK) && (en->lsa.type != LSA_T_EXT))
+          {
+           htonlsah(&(en->lsa), lsa);
+           DBG("Working on: %d\n", i);
+           DBG("\tX%01x %-1I %-1I %p\n", en->lsa.type, en->lsa.id,
+               en->lsa.rt, en->lsa_body);
+
+           lsa++;
+          }
+          else i++;    /* No lsa added */
 
          if (sn == STAIL(n->ifa->oa->lsal))
-         {
-           i--;
-           break;              /* Should set some flag? */
-         }
+          {
+            i--;
+           break;
+          }
+
          sn = sn->next;
-         lsa++;
        }
 
        if (sn == STAIL(n->ifa->oa->lsal))
@@ -130,7 +136,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
     memcpy(ifa->ip_sk->tbuf, n->ldbdes, length);
     /* Copy last sent packet again */
 
-    sk_send_to(ifa->ip_sk, length, n->ip, OSPF_PROTO);
+    ospf_send_to(ifa->ip_sk, length, n->ip);
 
     if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint);             /* Restart timer */
 
@@ -245,8 +251,6 @@ ospf_dbdes_receive(struct ospf_dbdes_packet *ps,
           ps->imms.byte);
       break;
     }
-    if(ps->imms.bit.i) log("FUCK");
-
   case NEIGHBOR_EXCHANGE:
     if ((ps->imms.byte == n->imms.byte) && (ps->options == n->options) &&
        (ntohl(ps->ddseq) == n->ddr))
index a318a674e62589fae6c54926e1d7ca26b3f4c22a..c805973092cfdb8ec8e2b590284405981e8c0bd5 100644 (file)
@@ -166,16 +166,20 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
   struct ospf_hello_packet *pkt;
   struct ospf_packet *op;
   struct proto *p;
-  struct ospf_neighbor *neigh;
+  struct ospf_neighbor *neigh, *n1;
   u16 length;
   u32 *pp;
-  int i;
+  int i, send;
+  struct nbma_node *nb;
 
   if (timer == NULL)
     ifa = dirn->ifa;
   else
     ifa = (struct ospf_iface *) timer->data;
 
+  if (ifa->state == OSPF_IS_DOWN)
+    return;
+
   if (ifa->stub)
     return;                    /* Don't send any packet on stub iface */
 
@@ -184,13 +188,13 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
       p->name, ifa->iface->name);
   /* Now we should send a hello packet */
   /* First a common packet header */
-  if (ifa->type != OSPF_IT_NBMA)
+  if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
   {
-    pkt = (struct ospf_hello_packet *) (ifa->hello_sk->tbuf);
+    pkt = (struct ospf_hello_packet *) (ifa->ip_sk->tbuf);
   }
   else
   {
-    pkt = (struct ospf_hello_packet *) (ifa->ip_sk->tbuf);
+    pkt = (struct ospf_hello_packet *) (ifa->hello_sk->tbuf);
   }
 
   /* Now fill ospf_hello header */
@@ -224,56 +228,55 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
   ospf_pkt_finalize(ifa, op);
 
   /* And finally send it :-) */
-  if (ifa->type != OSPF_IT_NBMA)
-  {
-    sk_send(ifa->hello_sk, length);
-  }
-  else                         /* NBMA */
+  switch(ifa->type)
   {
-    struct ospf_neighbor *n1;
-    struct nbma_node *nb;
-    int send;
-
-    if (timer == NULL)         /* Response to received hello */
-    {
-      sk_send_to(ifa->ip_sk, length, dirn->ip, OSPF_PROTO);
-    }
-    else
-    {
-      int toall = 0;
-      int meeli = 0;
-      if (ifa->state > OSPF_IS_DROTHER)
-       toall = 1;
-      if (ifa->priority > 0)
-       meeli = 1;
-
-      WALK_LIST(nb, ifa->nbma_list)
+    case OSPF_IT_NBMA:
+      if (timer == NULL)               /* Response to received hello */
       {
-       send = 1;
-       WALK_LIST(n1, ifa->neigh_list)
-       {
-         if (ipa_compare(nb->ip, n1->ip) == 0)
-         {
-           send = 0;
-           break;
-         }
-       }
-       if ((poll == 1) && (send))
-       {
-         if (toall || (meeli && nb->eligible))
-           sk_send_to(ifa->ip_sk, length, nb->ip, OSPF_PROTO);
-       }
+        ospf_send_to(ifa->ip_sk, length, dirn->ip);
       }
-      if (poll == 0)
+      else
       {
-       WALK_LIST(n1, ifa->neigh_list)
-       {
-         if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
-             (meeli && (n1->priority > 0)))
-           sk_send_to(ifa->ip_sk, length, n1->ip, OSPF_PROTO);
-       }
+        int toall = 0;
+        int meeli = 0;
+        if (ifa->state > OSPF_IS_DROTHER)
+          toall = 1;
+        if (ifa->priority > 0)
+          meeli = 1;
+        WALK_LIST(nb, ifa->nbma_list)
+        {
+          send = 1;
+          WALK_LIST(n1, ifa->neigh_list)
+          {
+            if (ipa_compare(nb->ip, n1->ip) == 0)
+            {
+              send = 0;
+              break;
+            }
+          }
+          if ((poll == 1) && (send))
+          {
+            if (toall || (meeli && nb->eligible))
+              ospf_send_to(ifa->ip_sk, length, nb->ip);
+          }
+        }
+        if (poll == 0)
+        {
+          WALK_LIST(n1, ifa->neigh_list)
+          {
+            if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
+                (meeli && (n1->priority > 0)))
+              ospf_send_to(ifa->ip_sk, length, n1->ip);
+          }
+        }
       }
-    }
+      break;
+    case OSPF_IT_VLINK:
+      ospf_send_to(ifa->ip_sk, length, ifa->vip);
+      break;
+    default:
+      sk_send(ifa->hello_sk, length);
   }
   OSPF_TRACE(D_PACKETS, "Hello sent via %s", ifa->iface->name);
 }
index 71b907ac6d60e91b84ad176754f2fbb2777dfec6..bd8cddd96044eac64f0c25c26588b118569b82e4 100644 (file)
@@ -117,24 +117,34 @@ ospf_iface_down(struct ospf_iface *ifa)
 {
   struct ospf_neighbor *n, *nx;
   struct proto *p = &ifa->proto->proto;
+  struct proto_ospf *po = ifa->proto;
+  struct ospf_iface *iff;
 
   WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
   {
     OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
     ospf_neigh_remove(n);
   }
-  rem_node(NODE ifa);
-
   rfree(ifa->hello_sk);
   rfree(ifa->dr_sk);
   rfree(ifa->ip_sk);
 
-  rfree(ifa->wait_timer);
-  rfree(ifa->hello_timer);
-  rfree(ifa->poll_timer);
-
-  rfree(ifa->lock);
-  mb_free(ifa);
+  if(ifa->type == OSPF_IT_VLINK)
+  {
+    ifa->ip_sk = NULL;
+    ifa->iface = NULL;
+    return;
+  }
+  else
+  {
+    rfree(ifa->wait_timer);
+    rfree(ifa->hello_timer);
+    rfree(ifa->poll_timer);
+    rfree(ifa->lock);
+    rem_node(NODE ifa);
+    mb_free(ifa);
+  }
+  /* FIXME: Should I down related VLINK also? */
 }
 
 /**
@@ -142,7 +152,7 @@ ospf_iface_down(struct ospf_iface *ifa)
  * @ifa: OSPF interface
  * @event: event comming to state machine
  *
- * This fully respect 9.3 of RFC 2328 except we don't use %LOOP state of
+ * This fully respects 9.3 of RFC 2328 except we don't use %LOOP state of
  * interface.
  */
 void
@@ -260,6 +270,7 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
   ipsk->saddr = ifa->iface->addr->ip;
   ipsk->tos = IP_PREC_INTERNET_CONTROL;
   ipsk->ttl = 1;
+  if (ifa->type == OSPF_IT_VLINK) ipsk->ttl = 255;
   ipsk->rx_hook = ospf_rx_hook;
   ipsk->tx_hook = ospf_tx_hook;
   ipsk->err_hook = ospf_err_hook;
@@ -307,6 +318,8 @@ ospf_iface_add(struct object_lock *lock)
   struct iface *iface = lock->iface;
   struct proto *p = &po->proto;
 
+  ifa->lock = lock;
+
   ifa->ioprob = OSPF_I_OK;
 
   if (ifa->type != OSPF_IT_NBMA)
@@ -330,12 +343,113 @@ ospf_iface_add(struct object_lock *lock)
     ifa->stub = 1;
     ifa->ioprob += OSPF_I_IP;
   }
-  ifa->lock = lock;
 
   ifa->state = OSPF_IS_DOWN;
   ospf_iface_sm(ifa, ISM_UP);
 }
 
+void
+ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip)
+{
+  struct proto *p = &po->proto;
+  struct ospf_iface *ifa;
+  struct nbma_node *nbma, *nb;
+  struct object_lock *lock;
+  struct ospf_area *oa;
+
+  ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
+  ifa->proto = po;
+  ifa->iface = iface;
+
+  ifa->an = ac->areaid;
+  ifa->cost = ip->cost;
+  ifa->rxmtint = ip->rxmtint;
+  ifa->inftransdelay = ip->inftransdelay;
+  ifa->priority = ip->priority;
+  ifa->helloint = ip->helloint;
+  ifa->pollint = ip->pollint;
+  ifa->strictnbma = ip->strictnbma;
+  ifa->waitint = ip->waitint;
+  ifa->deadc = ip->deadc;
+  ifa->stub = ip->stub;
+  ifa->autype = ip->autype;
+  memcpy(ifa->aukey, ip->password, 8);
+  ifa->options = 2;            /* FIXME what options? */
+
+  if (ip->type == OSPF_IT_UNDEF)
+    ifa->type = ospf_iface_clasify(ifa->iface);
+  else
+    ifa->type = ip->type;
+
+  init_list(&ifa->neigh_list);
+  init_list(&ifa->nbma_list);
+  WALK_LIST(nb, ip->nbma_list)
+  {
+    nbma = mb_alloc(p->pool, sizeof(struct nbma_node));
+    nbma->ip = nb->ip;
+    nbma->eligible = nb->eligible;
+    add_tail(&ifa->nbma_list, NODE nbma);
+  }
+
+  /* Add hello timer */
+  ifa->hello_timer = tm_new(p->pool);
+  ifa->hello_timer->data = ifa;
+  ifa->hello_timer->randomize = 0;
+  ifa->hello_timer->hook = hello_timer_hook;
+  ifa->hello_timer->recurrent = ifa->helloint;
+  DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
+
+  if (ifa->type == OSPF_IT_NBMA)
+  {
+    ifa->poll_timer = tm_new(p->pool);
+    ifa->poll_timer->data = ifa;
+    ifa->poll_timer->randomize = 0;
+    ifa->poll_timer->hook = poll_timer_hook;
+    ifa->poll_timer->recurrent = ifa->pollint;
+    DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
+  }
+  else
+    ifa->poll_timer = NULL;
+
+  ifa->wait_timer = tm_new(p->pool);
+  ifa->wait_timer->data = ifa;
+  ifa->wait_timer->randomize = 0;
+  ifa->wait_timer->hook = wait_timer_hook;
+  ifa->wait_timer->recurrent = 0;
+  DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
+  add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
+  ifa->state = OSPF_IS_DOWN;
+
+  WALK_LIST(oa, po->area_list)
+  {
+    if (oa->areaid == ifa->an)
+      break;
+  }
+
+  if (EMPTY_LIST(po->area_list) || (oa->areaid != ifa->an))    /* New area */
+    bug("Cannot add any area to accepted Interface");
+  else
+    ifa->oa = oa;
+
+  if (ifa->type == OSPF_IT_VLINK)
+  {
+    ifa->oa = po->backbone;
+    ifa->voa = oa;
+    ifa->vid = ip->vid;
+    return;    /* Don't lock, don't add sockets */
+  }
+
+  lock = olock_new(p->pool);
+  lock->addr = AllSPFRouters;
+  lock->type = OBJLOCK_IP;
+  lock->port = OSPF_PROTO;
+  lock->iface = iface;
+  lock->data = ifa;
+  lock->hook = ospf_iface_add;
+
+  olock_acquire(lock);
+}
+
 void
 ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
 {
@@ -344,8 +458,6 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
   struct ospf_area_config *ac;
   struct ospf_iface_patt *ip = NULL;
   struct ospf_iface *ifa;
-  struct object_lock *lock;
-  struct nbma_node *nbma, *nb;
   struct ospf_area *oa;
 
   DBG("%s: If notify called\n", p->name);
@@ -364,90 +476,7 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
     if (ip)
     {
       OSPF_TRACE(D_EVENTS, "Using interface %s.", iface->name);
-
-      ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
-      ifa->proto = po;
-      ifa->iface = iface;
-
-      ifa->an = ac->areaid;
-      ifa->cost = ip->cost;
-      ifa->rxmtint = ip->rxmtint;
-      ifa->inftransdelay = ip->inftransdelay;
-      ifa->priority = ip->priority;
-      ifa->helloint = ip->helloint;
-      ifa->pollint = ip->pollint;
-      ifa->strictnbma = ip->strictnbma;
-      ifa->waitint = ip->waitint;
-      ifa->deadc = ip->deadc;
-      ifa->stub = ip->stub;
-      ifa->autype = ip->autype;
-      memcpy(ifa->aukey, ip->password, 8);
-      ifa->options = 2;                /* FIXME what options? */
-
-      if (ip->type == OSPF_IT_UNDEF)
-       ifa->type = ospf_iface_clasify(ifa->iface);
-      else
-       ifa->type = ip->type;
-
-      init_list(&ifa->neigh_list);
-      init_list(&ifa->nbma_list);
-      WALK_LIST(nb, ip->nbma_list)
-      {
-       nbma = mb_alloc(p->pool, sizeof(struct nbma_node));
-       nbma->ip = nb->ip;
-       nbma->eligible = nb->eligible;
-       add_tail(&ifa->nbma_list, NODE nbma);
-      }
-
-      /* Add hello timer */
-      ifa->hello_timer = tm_new(p->pool);
-      ifa->hello_timer->data = ifa;
-      ifa->hello_timer->randomize = 0;
-      ifa->hello_timer->hook = hello_timer_hook;
-      ifa->hello_timer->recurrent = ifa->helloint;
-      DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
-
-      if (ifa->type == OSPF_IT_NBMA)
-      {
-       ifa->poll_timer = tm_new(p->pool);
-       ifa->poll_timer->data = ifa;
-       ifa->poll_timer->randomize = 0;
-       ifa->poll_timer->hook = poll_timer_hook;
-       ifa->poll_timer->recurrent = ifa->pollint;
-       DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
-      }
-      else
-       ifa->poll_timer = NULL;
-
-      ifa->wait_timer = tm_new(p->pool);
-      ifa->wait_timer->data = ifa;
-      ifa->wait_timer->randomize = 0;
-      ifa->wait_timer->hook = wait_timer_hook;
-      ifa->wait_timer->recurrent = 0;
-      DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
-      add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
-      ifa->state = OSPF_IS_DOWN;
-
-      lock = olock_new(p->pool);
-      lock->addr = AllSPFRouters;
-      lock->type = OBJLOCK_IP;
-      lock->port = OSPF_PROTO;
-      lock->iface = iface;
-      lock->data = ifa;
-      lock->hook = ospf_iface_add;
-
-      WALK_LIST(NODE oa, po->area_list)
-      {
-       if (oa->areaid == ifa->an)
-         break;
-      }
-
-      if (EMPTY_LIST(po->area_list) || (oa->areaid != ifa->an))        /* New area */
-       bug("Cannot add any area to accepted Interface");
-      else
-       ifa->oa = oa;
-
-      olock_acquire(lock);
+      ospf_iface_new(po, iface, ac, ip);
     }
   }
 
index 2c03d2a769dc900e23cc0d63b1211c8c440b5e52..556024b5987ec6b5a8900efb1759c32b2954fe8f 100644 (file)
@@ -16,5 +16,6 @@ struct ospf_iface *ospf_iface_find(struct proto_ospf *p, struct iface *what);
 void ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface);
 void ospf_iface_info(struct ospf_iface *ifa);
 void ospf_iface_shutdown(struct ospf_iface *ifa);
+void ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip);
 
 #endif /* _BIRD_OSPF_IFACE_H_ */
index 7d7238c2169df37141b3c0a7b8d1b4d5469a149b..bdad8665986b07004ba0d2a1ba3272aa96f54453 100644 (file)
@@ -78,16 +78,16 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
        if (ifa->type == OSPF_IT_BCAST)
        {
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-           sk_send_to(sk, len, AllSPFRouters, OSPF_PROTO);
+           ospf_send_to(sk, len, AllSPFRouters);
          else
-           sk_send_to(sk, len, AllDRouters, OSPF_PROTO);
+           ospf_send_to(sk, len, AllDRouters);
        }
        else
        {
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-           sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
+           ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
          else
-           sk_send_to_bdr(sk, len, ifa);
+           ospf_send_to_bdr(sk, len, ifa);
        }
 
        fill_ospf_pkt_hdr(n->ifa, pk, LSACK_P);
@@ -104,16 +104,16 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
   {
     if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
     {
-      sk_send_to(sk, len, AllSPFRouters, OSPF_PROTO);
+      ospf_send_to(sk, len, AllSPFRouters);
     }
     else
     {
-      sk_send_to(sk, len, AllDRouters, OSPF_PROTO);
+      ospf_send_to(sk, len, AllDRouters);
     }
   }
   else
   {
-    sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
+    ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
   }
 }
 
index e0871c888a32bbdb9414a46b14264a43fe945d15..02718da8129630d5aa798bc29fb447b80f80f1f2 100644 (file)
@@ -13,8 +13,8 @@ flush_lsa(struct top_hash_entry *en, struct ospf_area *oa)
 {
   struct proto *p = &oa->po->proto;
   OSPF_TRACE(D_EVENTS,
-            "Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u",
-            en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age);
+            "Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u, SN: 0x%x",
+            en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
   s_rem_node(SNODE en);
   if (en->lsa_body != NULL)
     mb_free(en->lsa_body);
@@ -56,6 +56,7 @@ ospf_age(struct ospf_area *oa)
       en->dist = LSINFINITY;
       en->nhi = NULL;
       en->nh = ipa_from_u32(0);
+      en->lb = ipa_from_u32(0);
       DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id,
          en->lsa.rt);
     }
@@ -164,8 +165,8 @@ htonlsab(void *h, void *n, u8 type, u16 len)
   case LSA_T_SUM_NET:
   case LSA_T_SUM_RT:
     {
-      struct ospf_lsa_summ *hs, *ns;
-      struct ospf_lsa_summ_net *hn, *nn;
+      struct ospf_lsa_sum *hs, *ns;
+      union ospf_lsa_sum_tm *hn, *nn;
 
       hs = h;
       ns = n;
@@ -173,15 +174,16 @@ htonlsab(void *h, void *n, u8 type, u16 len)
       ns->netmask = hs->netmask;
       ipa_hton(ns->netmask);
 
-      hn = (struct ospf_lsa_summ_net *) (hs + 1);
-      nn = (struct ospf_lsa_summ_net *) (ns + 1);
+      hn = (union ospf_lsa_sum_tm *) (hs + 1);
+      nn = (union ospf_lsa_sum_tm *) (ns + 1);
 
-      for (i = 0; i < ((len - sizeof(struct ospf_lsa_summ)) /
-                      sizeof(struct ospf_lsa_summ_net)); i++)
+      for (i = 0; i < ((len - sizeof(struct ospf_lsa_sum)) /
+                      sizeof(union ospf_lsa_sum_tm)); i++)
       {
-       (nn + i)->tos = (hn + i)->tos;
-       (nn + i)->metric = htons((hn + i)->metric);
-       (nn + i)->padding = 0;
+       (nn + i)->metric = htonl((hn + i)->metric);
+       //(nn + i)->tos = (hn + i)->tos;
+       //(nn + i)->metric = htons((hn + i)->metric);
+       //(nn + i)->padding = 0;
       }
       break;
     }
@@ -202,9 +204,10 @@ htonlsab(void *h, void *n, u8 type, u16 len)
       for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) /
                       sizeof(struct ospf_lsa_ext_tos)); i++)
       {
-       (nt + i)->etos = (ht + i)->etos;
-       (nt + i)->padding = 0;
-       (nt + i)->metric = htons((ht + i)->metric);
+       (nt + i)->etm.metric = htonl((ht + i)->etm.metric);
+       //(nt + i)->tos = (ht + i)->tos;
+       //(nt + i)->padding = 0;
+       //(nt + i)->metric = htons((ht + i)->metric);
        (nt + i)->fwaddr = (ht + i)->fwaddr;
        ipa_hton((nt + i)->fwaddr);
        (nt + i)->tag = htonl((ht + i)->tag);
@@ -262,8 +265,8 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
   case LSA_T_SUM_NET:
   case LSA_T_SUM_RT:
     {
-      struct ospf_lsa_summ *hs, *ns;
-      struct ospf_lsa_summ_net *hn, *nn;
+      struct ospf_lsa_sum *hs, *ns;
+      union ospf_lsa_sum_tm *hn, *nn;
 
       hs = h;
       ns = n;
@@ -271,15 +274,16 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
       hs->netmask = ns->netmask;
       ipa_ntoh(hs->netmask);
 
-      hn = (struct ospf_lsa_summ_net *) (hs + 1);
-      nn = (struct ospf_lsa_summ_net *) (ns + 1);
+      hn = (union ospf_lsa_sum_tm *) (hs + 1);
+      nn = (union ospf_lsa_sum_tm *) (ns + 1);
 
-      for (i = 0; i < ((len - sizeof(struct ospf_lsa_summ)) /
-                      sizeof(struct ospf_lsa_summ_net)); i++)
+      for (i = 0; i < ((len - sizeof(struct ospf_lsa_sum)) /
+                      sizeof(union ospf_lsa_sum_tm)); i++)
       {
-       (hn + i)->tos = (nn + i)->tos;
-       (hn + i)->metric = ntohs((nn + i)->metric);
-       (hn + i)->padding = 0;
+       (hn + i)->metric = ntohl((nn + i)->metric);
+       //(hn + i)->tos = (nn + i)->tos;
+       //(hn + i)->metric = ntohs((nn + i)->metric);
+       //(hn + i)->padding = 0;
       }
       break;
     }
@@ -300,9 +304,10 @@ ntohlsab(void *n, void *h, u8 type, u16 len)
       for (i = 0; i < ((len - sizeof(struct ospf_lsa_ext)) /
                       sizeof(struct ospf_lsa_ext_tos)); i++)
       {
-       (ht + i)->etos = (nt + i)->etos;
-       (ht + i)->padding = 0;
-       (ht + i)->metric = ntohs((nt + i)->metric);
+       (ht + i)->etm.metric = ntohl((nt + i)->etm.metric);
+       //(ht + i)->etos = (nt + i)->etos;
+       //(ht + i)->padding = 0;
+       //(ht + i)->metric = ntohs((nt + i)->metric);
        (ht + i)->fwaddr = (nt + i)->fwaddr;
        ipa_ntoh((ht + i)->fwaddr);
        (ht + i)->tag = ntohl((nt + i)->tag);
index 98d2d06c9d525564aaaa9482bf1b83ea7f2f624c..23622fc45bff9d7e3549c22146ae5c43b0b6e3e8 100644 (file)
@@ -60,7 +60,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
                                        i) * sizeof(struct ospf_lsreq_header);
   op->length = htons(length);
   ospf_pkt_finalize(n->ifa, op);
-  sk_send_to(n->ifa->ip_sk, length, n->ip, OSPF_PROTO);
+  ospf_send_to(n->ifa->ip_sk, length, n->ip);
   OSPF_TRACE(D_PACKETS, "LS request sent to: %I", n->rid);
 }
 
index 2211891f4fac3683eb3591483e2e7ff71df01aa6..0cefdd132bdb9d8acd2d2132b3474d4a86eea426 100644 (file)
@@ -197,17 +197,17 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
       if (ifa->type == OSPF_IT_NBMA)
       {
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
-         sk_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
+         ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
        else
-         sk_send_to_bdr(sk, len, ifa);
+         ospf_send_to_bdr(sk, len, ifa);
       }
       else
       {
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
            (ifa->type == OSPF_IT_PTP))
-         sk_send_to(sk, len, AllSPFRouters, OSPF_PROTO);
+         ospf_send_to(sk, len, AllSPFRouters);
        else
-         sk_send_to(sk, len, AllDRouters, OSPF_PROTO);
+         ospf_send_to(sk, len, AllDRouters);
       }
     }
   }
@@ -253,7 +253,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
       op->length = htons(len - SIPH);
       ospf_pkt_finalize(n->ifa, op);
 
-      sk_send_to(n->ifa->ip_sk, len - SIPH, n->ip, OSPF_PROTO);
+      ospf_send_to(n->ifa->ip_sk, len - SIPH, n->ip);
       OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano);
 
       DBG("LSupd: next packet\n");
@@ -277,7 +277,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
     ospf_pkt_finalize(n->ifa, op);
 
     OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano);
-    sk_send_to(n->ifa->ip_sk, len - SIPH, n->ip, OSPF_PROTO);
+    ospf_send_to(n->ifa->ip_sk, len - SIPH, n->ip);
   }
 }
 
index aca74cb2384364d2faa5cd89a009fea5f7df5ecd..a1049e1be7c66d3ffdf2dc93d5a56dbb86d636a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- OSPF
  *
- *     (c) 1999 - 2000 Ondrej Filip <feela@network.cz>
+ *     (c) 1999--2004 Ondrej Filip <feela@network.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -75,6 +75,31 @@ static int ospf_rte_same(struct rte *new, struct rte *old);
 static void area_disp(timer *timer);
 static void ospf_disp(timer *timer);
 
+static void
+ospf_area_initfib(struct fib_node *fn)
+{
+  struct area_net *an = (struct area_net *) fn;
+  an->hidden = 0;
+  an->active = -1;     /* Force to regenerate summary lsa */
+       /* ac->oldactive will be rewritten by ospf_rt_spf() */
+}
+
+static void
+add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac)
+{
+    struct proto_ospf *po = oa->po;
+    struct proto *p = &po->proto;
+    struct area_net_config *anet;
+    struct area_net *antmp;
+
+    fib_init(&oa->net_fib, p->pool, sizeof(struct area_net), 16, ospf_area_initfib);
+
+    WALK_LIST(anet, ac->net_list)
+    {
+      antmp = (struct area_net *) fib_get(&oa->net_fib, &anet->px.addr, anet->px.len);
+      antmp->hidden = anet->hidden;
+    }
+}
 
 static int
 ospf_start(struct proto *p)
@@ -83,13 +108,12 @@ ospf_start(struct proto *p)
   struct ospf_config *c = (struct ospf_config *) (p->cf);
   struct ospf_area_config *ac;
   struct ospf_area *oa;
-  struct area_net *anet, *antmp;
 
   po->rfc1583 = c->rfc1583;
   po->ebit = 0;
 
   po->tick = c->tick;
-  po->disp_timer = tm_new(po->proto.pool);
+  po->disp_timer = tm_new(p->pool);
   po->disp_timer->data = po;
   po->disp_timer->randomize = 0;
   po->disp_timer->hook = ospf_disp;
@@ -97,8 +121,7 @@ ospf_start(struct proto *p)
   tm_start(po->disp_timer, 1);
   init_list(&(po->iface_list));
   init_list(&(po->area_list));
-  fib_init(&po->rtf[0], p->pool, sizeof(ort), 16, ospf_rt_initort);
-  fib_init(&po->rtf[1], p->pool, sizeof(ort), 16, ospf_rt_initort);
+  fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
   po->areano = 0;
   if (EMPTY_LIST(c->area_list))
   {
@@ -108,7 +131,7 @@ ospf_start(struct proto *p)
 
   WALK_LIST(ac, c->area_list)
   {
-    oa = mb_allocz(po->proto.pool, sizeof(struct ospf_area));
+    oa = mb_allocz(p->pool, sizeof(struct ospf_area));
     add_tail(&po->area_list, NODE oa);
     po->areano++;
     oa->stub = ac->stub;
@@ -118,20 +141,27 @@ ospf_start(struct proto *p)
     s_init_list(&(oa->lsal));
     oa->rt = NULL;
     oa->po = po;
-    oa->disp_timer = tm_new(po->proto.pool);
+    oa->disp_timer = tm_new(p->pool);
     oa->disp_timer->data = oa;
     oa->disp_timer->randomize = 0;
     oa->disp_timer->hook = area_disp;
     oa->disp_timer->recurrent = oa->tick;
     tm_start(oa->disp_timer, 2);
-    init_list(&oa->net_list);
-    WALK_LIST(anet, ac->net_list)
+    add_area_nets(oa, ac);
+    fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
+    if (oa->areaid == 0) po->backbone = oa;
+  }
+
+  /* Add all virtual links as interfaces */
+  if(po->backbone)
+  {
+    struct ospf_iface_patt *ipatt;
+    WALK_LIST(ac, c->area_list)
     {
-      antmp = mb_allocz(po->proto.pool, sizeof(struct area_net));
-      antmp->px.addr = anet->px.addr;
-      antmp->px.len = anet->px.len;
-      antmp->hidden = anet->hidden;
-      add_tail(&oa->net_list, NODE antmp);
+      WALK_LIST(ipatt, ac->patt_list)
+      {
+        if (ipatt->type == OSPF_IT_VLINK) ospf_iface_new(po, NULL, ac, ipatt);
+      }
     }
   }
   return PS_UP;
@@ -189,42 +219,21 @@ ospf_init(struct proto_config *c)
 static int
 ospf_rte_better(struct rte *new, struct rte *old)
 {
-  /* FIXME this is wrong */
   if (new->u.ospf.metric1 == LSINFINITY)
     return 0;
 
-  /* External paths are always longer that internal */
-  if (((new->attrs->source == RTS_OSPF)
-       || (new->attrs->source == RTS_OSPF_IA))
-      && (old->attrs->source == RTS_OSPF_EXT))
-    return 1;
-  if (((old->attrs->source == RTS_OSPF)
-       || (old->attrs->source == RTS_OSPF_IA))
-      && (new->attrs->source == RTS_OSPF_EXT))
-    return 0;
-
-  if (new->u.ospf.metric2 < old->u.ospf.metric2)
-  {
-    if (old->u.ospf.metric2 == LSINFINITY)
-      return 0;                        /* Old is E1, new is E2 */
-    return 1;                  /* Both are E2 */
-  }
+  if(new->attrs->source < old->attrs->source) return 1;
+  if(new->attrs->source > old->attrs->source) return 0;
 
-  if (new->u.ospf.metric2 > old->u.ospf.metric2)
+  if(new->attrs->source == RTS_OSPF_EXT2)
   {
-    if (new->u.ospf.metric2 == LSINFINITY)
-      return 1;                        /* New is E1, old is E2 */
-    return 0;                  /* Both are E2 */
+    if(new->u.ospf.metric2 < old->u.ospf.metric2) return 1;
+    if(new->u.ospf.metric2 > old->u.ospf.metric2) return 0;
   }
 
-  /* 
-   * E2 metrics are the same. It means that:
-   * 1) Paths are E2 with same metric
-   * 2) Paths are E1.
-   */
-
   if (new->u.ospf.metric1 < old->u.ospf.metric1)
     return 1;
+
   return 0;                    /* Old is shorter or same */
 }
 
@@ -466,29 +475,30 @@ ospf_get_status(struct proto *p, byte * buf)
 static void
 ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED)
 {
-  char met = ' ';
-  char type = ' ';
+  char *type = "<bug>";
 
-  if (rte->attrs->source == RTS_OSPF_EXT)
+  switch(rte->attrs->source)
   {
-    met = '1';
-    type = 'E';
-
+    case RTS_OSPF:
+      type = "I";
+      break;
+    case RTS_OSPF_IA:
+      type = "IA";
+      break;
+    case RTS_OSPF_EXT1:
+      type = "E1";
+      break;
+    case RTS_OSPF_EXT2:
+      type = "E2";
+      break;
   }
-  if (rte->u.ospf.metric2 != LSINFINITY)
-    met = '2';
-  if (rte->attrs->source == RTS_OSPF_IA)
-    type = 'A';
-  if (rte->attrs->source == RTS_OSPF)
-    type = 'I';
-  buf += bsprintf(buf, " %c", type);
-  if (met != ' ')
-    buf += bsprintf(buf, "%c", met);
+
+  buf += bsprintf(buf, " %s", type);
   buf += bsprintf(buf, " (%d/%d", rte->pref, rte->u.ospf.metric1);
-  if (rte->u.ospf.metric2 != LSINFINITY)
+  if (rte->attrs->source == RTS_OSPF_EXT2)
     buf += bsprintf(buf, "/%d", rte->u.ospf.metric2);
   buf += bsprintf(buf, ")");
-  if (rte->attrs->source == RTS_OSPF_EXT && rte->u.ospf.tag)
+  if ((rte->attrs->source == RTS_OSPF_EXT2 || rte->attrs->source == RTS_OSPF_EXT1) && rte->u.ospf.tag)
   {
     buf += bsprintf(buf, " [%x]", rte->u.ospf.tag);
   }
@@ -578,19 +588,8 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
     }
 
     /* Change net_list */
-    WALK_LIST_DELSAFE(anet, antmp, oa->net_list)
-    {
-      rem_node(NODE anet);
-      mb_free(anet);
-    }
-    WALK_LIST(anet, ac2->net_list)
-    {
-      antmp = mb_alloc(p->pool, sizeof(struct area_net));
-      antmp->px.addr = anet->px.addr;
-      antmp->px.len = anet->px.len;
-      antmp->hidden = anet->hidden;
-      add_tail(&oa->net_list, NODE antmp);
-    }
+    fib_free(&oa->net_fib);
+    add_area_nets(oa, ac2);
 
     if (!iface_patts_equal(&ac1->patt_list, &ac2->patt_list,
                           (void *) ospf_patt_compare))
@@ -833,9 +832,8 @@ ospf_sh(struct proto *p)
   struct proto_ospf *po = (struct proto_ospf *) p;
   struct ospf_iface *ifa;
   struct ospf_neighbor *n;
-  int ifano;
-  int nno;
-  int adjno;
+  int ifano, nno, adjno, firstfib;
+  struct area_net *anet;
 
   if (p->proto_state != PS_UP)
   {
@@ -871,16 +869,20 @@ ospf_sh(struct proto *p)
     cli_msg(-1014, "\t\tNumber of LSAs in DB:\t%u", oa->gr->hash_entries);
     cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
     cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno);
-    if (!EMPTY_LIST(oa->net_list))
+
+    firstfib = 1;
+    FIB_WALK(&oa->net_fib, nftmp)
     {
-      struct area_net *anet;
-      cli_msg(-1014, "\t\tArea networks:");
-      WALK_LIST(anet, oa->net_list)
+      anet = (struct area_net *) nftmp;
+      if(firstfib)
       {
-       cli_msg(-1014, "\t\t\t%1I/%u\t%s", anet->px.addr, anet->px.len,
-               anet->hidden ? "Hidden" : "Advertise");
+        cli_msg(-1014, "\t\tArea networks:");
+        firstfib = 0;
       }
+      cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen,
+               anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
     }
+    FIB_WALK_END;
   }
   cli_msg(0, "");
 }
index 8c7eaa053c1bf770e59680b6cdb13b4605e718ca..d1de12adfe7cb378c198a7ed08d14e3f54bc6caf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- OSPF
  *
- *     (c) 1999 - 2000 Ondrej Filip <feela@network.cz>
+ *     (c) 1999--2004 Ondrej Filip <feela@network.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -50,7 +50,7 @@
 #define LSREFRESHTIME 1800     /* 30 minutes */
 #define MINLSINTERVAL 5
 #define MINLSARRIVAL 1
-#define LSINFINITY 0xffff      /* RFC says 0xffffff ??? */
+#define LSINFINITY 0xffffff
 
 #define DEFAULT_OSPFTICK 5
 #define DEFAULT_AREATICK 4
@@ -72,13 +72,18 @@ struct nbma_node
   int eligible;
 };
 
-struct area_net
+struct area_net_config
 {
   node n;
   struct prefix px;
   int hidden;
+};
+
+struct area_net
+{
+  struct fib_node fn;
+  int hidden;
   int active;
-  int oldactive;
 };
 
 struct ospf_area_config
@@ -113,6 +118,9 @@ struct ospf_iface
   u32 rxmtint;                 /* number of seconds between LSA retransmissions */
   u32 pollint;                 /* Poll interval */
   u32 deadc;                   /* after "deadint" missing hellos is router dead */
+  u32 vid;                     /* Id of peer of virtual link */
+  ip_addr vip;                 /* IP of peer of virtual link */
+  struct ospf_area *voa;       /* Area wich the vlink goes through */
   u16 autype;
   u8 aukey[8];
   u8 options;
@@ -299,28 +307,61 @@ struct ospf_lsa_net
   ip_addr netmask;
 };
 
-struct ospf_lsa_summ
+struct ospf_lsa_sum
 {
   ip_addr netmask;
 };
 
-struct ospf_lsa_summ_net
+
+struct ospf_lsa_ext
 {
+  ip_addr netmask;
+};
+
+struct ospf_lsa_ext_etos 
+{
+#ifdef _BIG_ENDIAN
+  u8 ebit:1;
+  u8 tos:7;
+  u8 padding1;
+  u16 padding2;
+#else
+  u16 padding2;
+  u8 padding1;
+  u8 tos:7;
+  u8 ebit:1;
+#endif
+};
+
+#define METRIC_MASK 0x00FFFFFF
+struct ospf_lsa_sum_tos 
+{
+#ifdef _BIG_ENDIAN
   u8 tos;
-  u8 padding;
-  u16 metric;
+  u8 padding1;
+  u16 padding2;
+#else
+  u16 padding2;
+  u8 padding1;
+  u8 tos;
+#endif
 };
 
-struct ospf_lsa_ext
+union ospf_lsa_sum_tm
 {
-  ip_addr netmask;
+  struct ospf_lsa_sum_tos tos;
+  u32 metric;
+};
+
+union ospf_lsa_ext_etm
+{
+  struct ospf_lsa_ext_etos etos;
+  u32 metric;
 };
 
 struct ospf_lsa_ext_tos
 {
-  u8 etos;
-  u8 padding;
-  u16 metric;
+  union ospf_lsa_ext_etm etm;
   ip_addr fwaddr;
   u32 tag;
 };
@@ -432,11 +473,12 @@ struct ospf_area
   slist lsal;                  /* List of all LSA's */
   struct top_hash_entry *rt;   /* My own router LSA */
   list cand;                   /* List of candidates for RT calc. */
-  list net_list;               /* Networks to advertise or not */
+  struct fib net_fib;          /* Networks to advertise or not */
   int stub;
   int trcap;                   /* Transit capability? */
   struct proto_ospf *po;
   unsigned tick;
+  struct fib rtr;              /* Routing tables for routers */
 };
 
 struct proto_ospf
@@ -448,9 +490,10 @@ struct proto_ospf
   list iface_list;             /* Interfaces we really use */
   list area_list;
   int areano;                  /* Number of area I belong to */
-  struct fib rtf[2];           /* Routing tables */
+  struct fib rtf;              /* Routing table */
   int rfc1583;                 /* RFC1583 compatibility */
   int ebit;                    /* Did I originate any ext lsa? */
+  struct ospf_area *backbone;  /* If exists */
 };
 
 struct ospf_iface_patt
@@ -468,6 +511,7 @@ struct ospf_iface_patt
   u32 autype;
   u32 strictnbma;
   u32 stub;
+  u32 vid;
 /* must be in network byte order */
 #define AU_NONE htons(0)
 #define AU_SIMPLE htons(1)
@@ -493,6 +537,7 @@ void ospf_sh_iface(struct proto *p, char *iff);
 #define EA_OSPF_METRIC2        EA_CODE(EAP_OSPF, 1)
 #define EA_OSPF_TAG    EA_CODE(EAP_OSPF, 2)
 
+#include "proto/ospf/rt.h"
 #include "proto/ospf/hello.h"
 #include "proto/ospf/packet.h"
 #include "proto/ospf/iface.h"
@@ -503,6 +548,5 @@ void ospf_sh_iface(struct proto *p, char *iff);
 #include "proto/ospf/lsupd.h"
 #include "proto/ospf/lsack.h"
 #include "proto/ospf/lsalib.h"
-#include "proto/ospf/rt.h"
 
 #endif /* _BIRD_OSPF_H_ */
index 26cc4d436df595d8b83615a1e137e969b7727746..4f5db664762e99785b71c458f4d5d99833f2823e 100644 (file)
@@ -226,19 +226,26 @@ ospf_err_hook(sock * sk, int err UNUSED)
 }
 
 void
-sk_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state)
+ospf_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state)
 {
   struct ospf_neighbor *n;
 
   WALK_LIST(NODE n, ifa->neigh_list) if (n->state >= state)
-    sk_send_to(sk, len, n->ip, OSPF_PROTO);
+    ospf_send_to(sk, len, n->ip);
 }
 
 void
-sk_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa)
+ospf_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa)
 {
   if (ipa_compare(ifa->drip, ipa_from_u32(0)) != 0)
-    sk_send_to(sk, len, ifa->drip, OSPF_PROTO);
+    ospf_send_to(sk, len, ifa->drip);
   if (ipa_compare(ifa->bdrip, ipa_from_u32(0)) != 0)
-    sk_send_to(sk, len, ifa->bdrip, OSPF_PROTO);
+    ospf_send_to(sk, len, ifa->bdrip);
 }
+
+void
+ospf_send_to(sock *sk, u16 len, ip_addr ip)
+{
+  sk_send_to(sk, len, ip, OSPF_PROTO);
+}
+
index fa2c85d216eed2e4b5daaecd6e57d1e5fbfa92d2..0742adfa42b22dd9a76cdab90a82f3b1a1d0a3c6 100644 (file)
@@ -16,7 +16,9 @@ void ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt);
 int ospf_rx_hook(sock * sk, int size);
 void ospf_tx_hook(sock * sk);
 void ospf_err_hook(sock * sk, int err);
-void sk_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state);
-void sk_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa);
+void ospf_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state);
+void ospf_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa);
+void ospf_send_to(sock *sk, u16 len, ip_addr ip);
+
 
 #endif /* _BIRD_OSPF_PACKET_H_ */
index 417aa7e6a6d88202e54dd74bf8aed5865b0b88f2..0360f8b6d7ada38b8ccc642fd2bae3c3399a4f1e 100644 (file)
@@ -21,8 +21,6 @@ fill_ri(orta * orta)
 {
   orta->type = RTS_DUMMY;
   orta->capa = 0;
-#define ORTA_ASBR 1
-#define ORTA_ABR 2
   orta->oa = NULL;
   orta->metric1 = LSINFINITY;
   orta->metric2 = LSINFINITY;
@@ -37,13 +35,20 @@ ospf_rt_initort(struct fib_node *fn)
 {
   ort *ri = (ort *) fn;
   fill_ri(&ri->n);
-  ri->dest = ORT_UNDEF;
   memcpy(&ri->o, &ri->n, sizeof(orta));
+  ri->efn = NULL;
 }
 
 /* If new is better return 1 */
+
+/* 
+ * This is hard to understand:
+ * If rfc1583 is set to 1, it work likes normal route_better()
+ * But if it is set to 0, it prunes number of AS bondary
+ * routes before it starts the router decision
+ */
 static int
-ri_better(struct proto_ospf *po, orta * new, orta * old)
+ri_better(struct proto_ospf *po, orta * new, ort *nefn, orta * old, ort *oefn, int rfc1583)
 {
   int newtype = new->type;
   int oldtype = old->type;
@@ -54,41 +59,44 @@ ri_better(struct proto_ospf *po, orta * new, orta * old)
   if (old->metric1 == LSINFINITY)
     return 1;
 
-  if (po->rfc1583)
+  if(!rfc1583)
   {
-    if ((newtype == RTS_OSPF) && (new->oa->areaid == 0)) newtype = RTS_OSPF_IA;
-    if ((oldtype == RTS_OSPF) && (old->oa->areaid == 0)) oldtype = RTS_OSPF_IA;
-  }
+    if(new->oa->areaid == 0) newtype = RTS_OSPF_IA;
+    if(old->oa->areaid == 0) oldtype = RTS_OSPF_IA;
   
+}
+
   if (new->type < old->type)
     return 1;
 
-  if (new->metric2 < old->metric2)
-  {
-    if (old->metric2 == LSINFINITY)
-      return 0;                        /* Old is E1, new is E2 */
+  if (new->type > old->type)
+    return 0;
 
-    return 1;                  /* Both are E2 */
+  /* Same type */
+  if(new->type == RTS_OSPF_EXT2)
+  {
+    if (new->metric2 < old->metric2) return 1;
+    if (new->metric2 > old->metric2) return 0;
   }
-  if (new->metric2 > old->metric2)
+
+  if(((new->type == RTS_OSPF_EXT2) || (new->type == RTS_OSPF_EXT1)) && (!po->rfc1583))
   {
-    if (new->metric2 == LSINFINITY)
-      return 1;                        /* New is E1, old is E2 */
+    int newtype = nefn->n.type;
+    int oldtype = oefn->n.type;
+
+    if(nefn->n.oa->areaid == 0) newtype = RTS_OSPF_IA;
+    if(oefn->n.oa->areaid == 0) oldtype = RTS_OSPF_IA;
 
-    return 0;                  /* Both are E2 */
+    if(newtype < oldtype) return 1;
+    if(newtype > oldtype) return 0;
   }
 
-  /*
-   * E2 metrics are the same. It means that: 1) Paths are E2 with same
-   * metric 2) Paths are E1.
-   */
   if (new->metric1 < old->metric1)
     return 1;
 
   if (new->metric1 > old->metric1)
     return 0;
 
-  /* Metric 1 are the same */
   if (new->oa->areaid > old->oa->areaid) return 1;     /* Larger AREAID is preffered */
 
   return 0;                    /* Old is shorter or same */
@@ -96,26 +104,35 @@ ri_better(struct proto_ospf *po, orta * new, orta * old)
 
 static void
 ri_install(struct proto_ospf *po, ip_addr prefix, int pxlen, int dest,
-          orta * new)
+          orta * new, ort * ipath)
 {
-  ort *old = (ort *) fib_get(&po->rtf[dest], &prefix, pxlen);
+  struct ospf_area *oa = new->oa;
+  ort *old;
 
-  if (ri_better(po, new, &old->n))
+  if (dest == ORT_NET)
   {
-    memcpy(&old->n, new, sizeof(orta));
+    struct area_net *anet;
+    old = (ort *) fib_get(&po->rtf, &prefix, pxlen);
+    if (ri_better(po, new, ipath, &old->n, old->efn, 1))
+    {
+      memcpy(&old->n, new, sizeof(orta));
+      old->efn = ipath;
+    }
+    if ((new->type == RTS_OSPF) && (anet = (struct area_net *)fib_route(&oa->net_fib, prefix, pxlen)))
+       anet->active = 1;
+  }
+  else
+  {
+    old = (ort *) fib_get(&oa->rtr, &prefix, pxlen);
+
+    if (ri_better(po, new, ipath, &old->n, old->efn, 1))
+    {
+      memcpy(&old->n, new, sizeof(orta));
+      old->efn = ipath;
+    }
   }
 }
 
-/**
- * ospf_rt_spf - calculate internal routes
- * @po: OSPF protocol
- *
- * Calculation of internal paths in an area is described in 16.1 of RFC 2328.
- * It's based on Dijkstra's shortest path tree algorithms.
- * RFC recommends to add ASBR routers into routing table. I don't do this
- * and latter parts of routing table calculation look directly into LSA
- * Database. This function is invoked from ospf_disp().
- */
 static void
 ospf_rt_spfa(struct ospf_area *oa)
 {
@@ -126,6 +143,10 @@ ospf_rt_spfa(struct ospf_area *oa)
   struct proto_ospf *po = oa->po;
   struct ospf_lsa_net *ln;
   orta nf;
+  struct ospf_iface *iface;
+  struct top_hash_entry *act, *tmp;
+  node *n;
+
 
   if (oa->rt == NULL)
     return;
@@ -149,9 +170,6 @@ ospf_rt_spfa(struct ospf_area *oa)
 
   while (!EMPTY_LIST(oa->cand))
   {
-    struct top_hash_entry *act, *tmp;
-    node *n;
-
     n = HEAD(oa->cand);
     act = SKIP_BACK(struct top_hash_entry, cn, n);
     rem_node(n);
@@ -178,7 +196,7 @@ ospf_rt_spfa(struct ospf_area *oa)
        nf.ar = act;
        nf.nh = act->nh;
        nf.ifa = act->nhi;
-       ri_install(po, ipa_from_u32(act->lsa.id), 32, ORT_ROUTER, &nf);
+       ri_install(po, ipa_from_u32(act->lsa.id), 32, ORT_ROUTER, &nf, NULL);
       }
       rr = (struct ospf_lsa_rt_link *) (rt + 1);
       DBG("  Number of links: %u\n", rt->links);
@@ -208,13 +226,9 @@ ospf_rt_spfa(struct ospf_area *oa)
          nf.nh = act->nh;
          nf.ifa = act->nhi;
          ri_install(po, ipa_from_u32(rtl->id),
-                    ipa_mklen(ipa_from_u32(rtl->data)), ORT_NET, &nf);
+                    ipa_mklen(ipa_from_u32(rtl->data)), ORT_NET, &nf, NULL);
          break;
 
-       case LSART_VLNK:        /* FIXME !!!!!!!! */
-         DBG("Ignoring\n");
-         continue;
-         break;
        case LSART_NET:
          tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET);
          if (tmp == NULL)
@@ -222,6 +236,8 @@ ospf_rt_spfa(struct ospf_area *oa)
          else
            DBG("Found. :-)\n");
          break;
+
+       case LSART_VLNK:
        case LSART_PTP:
          tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT);
          DBG("PTP found.\n");
@@ -247,7 +263,7 @@ ospf_rt_spfa(struct ospf_area *oa)
       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);
+                ipa_mklen(ln->netmask), ORT_NET, &nf, NULL);
 
       rts = (u32 *) (ln + 1);
       for (i = 0; i < (act->lsa.length - sizeof(struct ospf_lsa_header) -
@@ -264,9 +280,244 @@ ospf_rt_spfa(struct ospf_area *oa)
       break;
     }
   }
+
+  /* Find new/lost VLINK peers */
+  WALK_LIST(iface, po->iface_list)
+  {
+    if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa))
+    {
+      if ((tmp = ospf_hash_find(oa->gr, iface->vid, iface->vid, LSA_T_RT)) &&
+        ipa_equal(tmp->lb, IPA_NONE))
+      {
+        DBG("Vlink peer found\n");
+        ospf_iface_sm(iface, ISM_UP);  /* FIXME: Add slave iface! */
+      }
+      else
+      {
+        DBG("Vlink peer not found\n");
+        ospf_iface_sm(iface, ISM_DOWN);
+      }
+    }
+  }
+}
+
+static int
+link_back(struct ospf_area *oa, struct top_hash_entry *fol, struct top_hash_entry *pre)
+{
+  u32 i, *rts;
+  struct ospf_lsa_net *ln;
+  struct ospf_lsa_rt *rt;
+  struct ospf_lsa_rt_link *rtl, *rr;
+
+  if(!pre) return 0;
+  if(!fol) return 0;
+  switch (fol->lsa.type)
+  {
+    case LSA_T_RT:
+      rt = (struct ospf_lsa_rt *) fol->lsa_body;
+      rr = (struct ospf_lsa_rt_link *) (rt + 1);
+      for (i = 0; i < rt->links; i++)
+      {
+       rtl = (rr + i);
+       switch (rtl->type)
+       {
+       case LSART_STUB:
+         break;
+       case LSART_NET:
+         if (ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_NET) == pre)
+          {
+            fol->lb = ipa_from_u32(rtl->data);
+            return 1;
+          }
+         break;
+       case LSART_VLNK:
+       case LSART_PTP:
+         if (ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT) == pre)
+          {
+            fol->lb = ipa_from_u32(rtl->data);
+            return 1;
+          }
+         break;
+       default:
+         log("Unknown link type in router lsa.");
+         break;
+       }
+      }
+      break;
+    case LSA_T_NET:
+      ln = fol->lsa_body;
+      rts = (u32 *) (ln + 1);
+      for (i = 0; i < (fol->lsa.length - sizeof(struct ospf_lsa_header) -
+                      sizeof(struct ospf_lsa_net)) / sizeof(u32); i++)
+      {
+       if (ospf_hash_find(oa->gr, *(rts + i), *(rts + i), LSA_T_RT) == pre)
+        {
+          return 1;
+        }
+      }
+      break;
+    default:
+      log("Unknown link type in router lsa.");
+  }
+  return 0;
+}
+
+static void
+ospf_rt_sum_tr(struct ospf_area *oa)
+{
+  struct proto *p = &oa->po->proto;
+  struct proto_ospf *po = oa->po;
+  struct ospf_area *bb, *atmp;
+  ip_addr *mask, ip, abrip;
+  struct top_hash_entry *en;
+  int mlen = -1, type = -1;
+  union ospf_lsa_sum_tm *tm;
+  ort *re = NULL, *abr;
+  orta nf;
+
+  bb = NULL;
+
+  WALK_LIST(atmp, po->area_list)
+  {
+    if(atmp->areaid == 0)
+    {
+      bb = atmp;
+      break;
+    }
+  }
+
+  if(!bb) return;
+
+  WALK_SLIST(en, oa->lsal)
+  {
+    if (en->lsa.age == LSA_MAXAGE)
+      continue;
+    if (en->dist == LSINFINITY)
+      continue;
+
+    if (en->lsa.rt == p->cf->global->router_id)
+      continue;
+
+    if((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
+      continue;
+
+    mask = (ip_addr *)en->lsa_body;
+
+    if (en->lsa.type == LSA_T_SUM_NET)
+    {
+      mlen = ipa_mklen(*mask);
+      ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
+      type = ORT_NET;
+      re = (ort *) fib_find(&po->rtf, &ip, 32);
+    }
+
+    if (en->lsa.type == LSA_T_SUM_RT)
+    {
+      ip = ipa_from_u32(en->lsa.id);
+      mlen = 32;
+      type = ORT_ROUTER;
+      re = (ort *) fib_find(&bb->rtr, &ip, 32);
+    }
+    if(!re) continue;
+    if(re->n.oa->areaid != 0) continue;
+    if((re->n.type != RTS_OSPF) && (re->n.type != RTS_OSPF_IA)) continue;
+
+    abrip = ipa_from_u32(en->lsa.rt);
+
+    abr = fib_find(&oa->rtr, &abrip, 32);
+    if(!abr) continue;
+
+    tm = (union ospf_lsa_sum_tm *)(mask + 1);
+
+    nf.type = re->n.type;
+    nf.capa = ORTA_ABR;
+    nf.metric1 = abr->n.metric1 + (tm->metric & METRIC_MASK);
+    nf.metric2 = LSINFINITY;
+    nf.oa = oa;
+    nf.ar = abr->n.ar;
+    nf.nh = abr->n.nh;
+    nf.ifa = abr->n.ifa;
+    ri_install(po, ip, mlen, type, &nf, NULL);
+  }
 }
+  
+
+static void
+ospf_rt_sum(struct ospf_area *oa)
+{
+  struct proto_ospf *po = oa->po;
+  struct proto *p = &po->proto;
+  struct top_hash_entry *en;
+  ip_addr *mask, ip, abrip;
+  struct area_net *anet;
+  orta nf;
+  ort *re, *abr;
+  int mlen = -1, type = -1;
+  union ospf_lsa_sum_tm *tm;
 
+  OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area routes");
 
+  WALK_SLIST(en, oa->lsal)
+  {
+    /* Page 169 (1) */
+    if (en->lsa.age == LSA_MAXAGE)
+      continue;
+    if (en->dist == LSINFINITY)
+      continue;
+
+    /* Page 169 (2) */
+    if (en->lsa.rt == p->cf->global->router_id)
+      continue;
+
+    if((en->lsa.type != LSA_T_SUM_RT) && (en->lsa.type != LSA_T_SUM_NET))
+      continue;
+
+    mask = (ip_addr *)en->lsa_body;
+
+    if (en->lsa.type == LSA_T_SUM_NET)
+    {
+      mlen = ipa_mklen(*mask);
+      ip = ipa_and(ipa_from_u32(en->lsa.id), *mask);
+      /* Page 169 (3) */
+      if ((anet = fib_route(&oa->net_fib, ip, mlen)) && anet->active)
+        continue;
+      type = ORT_NET;
+    }
+
+    if (en->lsa.type == LSA_T_SUM_RT)
+    {
+      ip = ipa_from_u32(en->lsa.id);
+      mlen = 32;
+      type = ORT_ROUTER;
+    }
+    abrip = ipa_from_u32(en->lsa.rt);
+
+    if (!(abr = (ort *) fib_find(&oa->rtr, &abrip, 32))) continue;
+    if (abr->n.metric1 == LSINFINITY) continue;
+    if (!(abr->n.capa & ORTA_ABR)) continue;
+
+    tm = (union ospf_lsa_sum_tm *)(mask + 1);
+
+    nf.type = RTS_OSPF_IA;
+    nf.capa = ORTA_ABR;
+    nf.metric1 = abr->n.metric1 + (tm->metric & METRIC_MASK);
+    nf.metric2 = LSINFINITY;
+    nf.oa = oa;
+    nf.ar = abr->n.ar;
+    nf.nh = abr->n.nh;
+    nf.ifa = abr->n.ifa;
+    ri_install(po, ip, mlen, type, &nf, NULL);
+  }
+}
+
+/**
+ * ospf_rt_spf - calculate internal routes
+ * @po: OSPF protocol
+ *
+ * Calculation of internal paths in an area is described in 16.1 of RFC 2328.
+ * It's based on Dijkstra's shortest path tree algorithms.
+ * This function is invoked from ospf_disp().
+ */
 void
 ospf_rt_spf(struct proto_ospf *po)
 {
@@ -274,12 +525,14 @@ ospf_rt_spf(struct proto_ospf *po)
   struct ospf_area *oa;
   int i;
   ort *ri;
+  struct area_net *anet;
+
+  if (po->areano == 0) return;
 
   OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
 
   /* Invalidate old routing table */
-  for (i = 0; i < 2; i++)
-    FIB_WALK(&po->rtf[i], nftmp)
+  FIB_WALK(&po->rtf, nftmp)
   {
     ri = (ort *) nftmp;
     memcpy(&ri->o, &ri->n, sizeof(orta));      /* Backup old data */
@@ -290,25 +543,44 @@ ospf_rt_spf(struct proto_ospf *po)
 
   WALK_LIST(oa, po->area_list)
   {
+    FIB_WALK(&oa->rtr, nftmp)
+    {
+      ri = (ort *) nftmp;
+      memcpy(&ri->o, &ri->n, sizeof(orta));    /* Backup old data */
+      fill_ri(&ri->n);
+    }
+    FIB_WALK_END;
+
+    fib_free(&oa->rtr);
+    fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort);
+
+    FIB_WALK(&oa->net_fib, nftmp)
+    {
+      anet = (struct area_net *) nftmp;
+      anet->active = 0;
+    }
+    FIB_WALK_END;
     ospf_rt_spfa(oa);
   }
 
-  if (po->areano > 1)
+  if (po->areano == 1)
   {
-    //ospf_rt_sum(oa);
+    ospf_rt_sum(HEAD(po->area_list));
   }
   else
   {
-    WALK_LIST(oa, po->area_list)
-    {
-      //if (oa->id == 0) ospf_rt_sum(oa);
-    }
+    if (po->backbone) ospf_rt_sum(po->backbone);       /* And if backbone is not connected? */
+  }
 
-    WALK_LIST(oa, po->area_list)
+  WALK_LIST(oa, po->area_list)
+  {
+    if (oa->trcap && (oa->areaid != 0))
     {
-      //if (oa->trcap == 1) ospf_rt_sum(oa);
+      ospf_rt_sum_tr(oa);
+      break;
     }
   }
+
   WALK_LIST(oa, po->area_list)
   {
     if (!oa->stub)
@@ -333,7 +605,7 @@ static void
 ospf_ext_spfa(struct ospf_area *oa)
 {
   struct proto_ospf *po = oa->po;
-  ort *nf1, *nf2;
+  ort *nf1, *nf2, *nfh;
   orta nfa;
   struct top_hash_entry *en;
   struct proto *p = &po->proto;
@@ -345,6 +617,7 @@ ospf_ext_spfa(struct ospf_area *oa)
   int met1, met2;
   neighbor *nn;
   struct ospf_lsa_rt *rt;
+  struct ospf_area *atmp;
 
 
   OSPF_TRACE(D_EVENTS, "Starting routing table calculation for ext routes");
@@ -364,7 +637,7 @@ ospf_ext_spfa(struct ospf_area *oa)
     DBG("%s: Working on LSA. ID: %I, RT: %I, Type: %u, Mask %I\n",
        p->name, en->lsa.id, en->lsa.rt, en->lsa.type, le->netmask);
 
-    if (lt->metric == LSINFINITY)
+    if ((lt->etm.metric & METRIC_MASK) == LSINFINITY)
       continue;
     ip = ipa_and(ipa_from_u32(en->lsa.id), le->netmask);
     mlen = ipa_mklen(le->netmask);
@@ -382,7 +655,16 @@ ospf_ext_spfa(struct ospf_area *oa)
 
     rtid = ipa_from_u32(en->lsa.rt);
 
-    if (!(nf1 = fib_find(&po->rtf[ORT_ROUTER], &rtid, 32)))
+    nf1 = NULL;
+    WALK_LIST(atmp, po->area_list)
+    {
+      nfh = fib_find(&atmp->rtr, &rtid, 32);
+      if(nfh == NULL) continue;
+      if(nf1 == NULL) nf1 = nfh;
+      else if(ri_better(po, &nfh->n, NULL, &nf1->n, NULL, po->rfc1583)) nf1 = nfh;
+    }
+
+    if (!nf1)
       continue;                        /* No AS boundary router found */
 
     if (nf1->n.metric1 == LSINFINITY)
@@ -393,34 +675,39 @@ ospf_ext_spfa(struct ospf_area *oa)
 
     if (ipa_compare(lt->fwaddr, ipa_from_u32(0)) == 0)
     {
-      if (lt->etos > 0)
+      if (lt->etm.etos.ebit)
       {                                /* FW address == 0 */
        met1 = nf1->n.metric1;
-       met2 = lt->metric;
+       met2 = (lt->etm.metric & METRIC_MASK);
       }
       else
       {
-       met1 = nf1->n.metric1 + lt->metric;
+       met1 = nf1->n.metric1 + (lt->etm.metric & METRIC_MASK);
        met2 = LSINFINITY;
       }
+
       nh = nf1->n.nh;
       nhi = nf1->n.ifa;
+      nfh = nf1;
     }
     else
     {                          /* FW address !=0 */
-      if (!(nf2 = fib_route(&po->rtf[ORT_NET], lt->fwaddr, 32)))
+      nf2 = fib_route(&po->rtf, lt->fwaddr, 32);
+
+      if (!nf2)
       {
        DBG("Cannot find network route (GW=%I)\n", lt->fwaddr);
        continue;
       }
-      if (lt->etos > 0)
+
+      if (lt->etm.etos.ebit)
       {
        met1 = nf2->n.metric1;
-       met2 = lt->metric;
+       met2 = (lt->etm.metric & METRIC_MASK);
       }
       else
       {
-       met1 = nf2->n.metric1 + lt->metric;
+       met1 = nf2->n.metric1 + (lt->etm.metric & METRIC_MASK);
        met2 = LSINFINITY;
       }
 
@@ -434,9 +721,12 @@ ospf_ext_spfa(struct ospf_area *oa)
        nh = nf2->n.nh;
        nhi = nf2->n.ifa;
       }
+
+      nfh = nf2;
     }
 
-    nfa.type = RTS_OSPF_EXT;
+    nfa.type = RTS_OSPF_EXT2;
+    if(met2 == LSINFINITY) nfa.type = RTS_OSPF_EXT1;
     nfa.capa = 0;
     nfa.metric1 = met1;
     nfa.metric2 = met2;
@@ -445,7 +735,7 @@ ospf_ext_spfa(struct ospf_area *oa)
     nfa.nh = nh;
     nfa.ifa = nhi;
     nfa.tag = lt->tag;
-    ri_install(po, ip, mlen, ORT_NET, &nfa);
+    ri_install(po, ip, mlen, ORT_NET, &nfa, nfh);
   }
 
 }
@@ -463,16 +753,20 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
     return;
   if (en->lsa.age == LSA_MAXAGE)
     return;
-  /* FIXME Does it have link back? Test it! */
+
   if (en->color == INSPF)
     return;
 
   if (dist >= en->dist)
     return;
   /*
-   * FIXME The line above is not a bug, but we don't support multiple
+   * FIXME The line above (=) is not a bug, but we don't support multiple
    * next hops. I'll start as soon as nest will
    */
+
+  if (!link_back(oa, en, par))
+    return;
+
   DBG("     Adding candidate: rt: %I, id: %I, type: %u\n", en->lsa.rt,
       en->lsa.id, en->lsa.type);
 
@@ -520,7 +814,6 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
       add_tail(l, &en->cn);
     }
   }
-  /* FIXME Some VLINK stuff should be here */
 }
 
 static void
@@ -607,30 +900,20 @@ rt_sync(struct proto_ospf *po)
 {
   struct proto *p = &po->proto;
   struct fib_iterator fit;
-  struct fib *fib = &po->rtf[ORT_NET];
+  struct fib *fib = &po->rtf;
   ort *nf;
+  struct ospf_area *oa;
+  struct area_net *anet;
+
+  OSPF_TRACE(D_EVENTS, "Starting routing table synchronisation");
 
   DBG("Now syncing my rt table with nest's\n");
   FIB_ITERATE_INIT(&fit, fib);
-again:
+again1:
   FIB_ITERATE_START(fib, &fit, nftmp)
   {
     nf = (ort *) nftmp;
-    if (nf->n.metric1 == LSINFINITY)
-    {
-      net *ne;
-
-      ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
-      DBG("Deleting rt entry %I\n     (IP: %I, GW: %I)\n",
-         nf->fn.prefix, ip, nf->nh);
-      rte_update(p->table, ne, p, NULL);
-
-      /* Now delete my fib */
-      FIB_ITERATE_PUT(&fit, nftmp);
-      fib_delete(fib, nftmp);
-      goto again;
-    }
-    else if (memcmp(&nf->n, &nf->o, sizeof(orta)))
+    if (memcmp(&nf->n, &nf->o, sizeof(orta)))
     {                          /* Some difference */
       net *ne;
       rta a0;
@@ -648,17 +931,59 @@ again:
       a0.iface = nf->n.ifa;
       a0.gw = nf->n.nh;
       ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen);
-      e = rte_get_temp(&a0);
-      e->u.ospf.metric1 = nf->n.metric1;
-      e->u.ospf.metric2 = nf->n.metric2;
-      e->u.ospf.tag = nf->n.tag;
-      e->pflags = 0;
-      e->net = ne;
-      e->pref = p->preference;
-      DBG("Modifying rt entry %I\n     (IP: %I, GW: %I)\n",
+      check_sum_lsa(po, nf, ORT_NET);
+      if (nf->n.metric1 < LSINFINITY)
+      {
+        e = rte_get_temp(&a0);
+        e->u.ospf.metric1 = nf->n.metric1;
+        e->u.ospf.metric2 = nf->n.metric2;
+        e->u.ospf.tag = nf->n.tag;
+        e->pflags = 0;
+        e->net = ne;
+        e->pref = p->preference;
+        DBG("Modifying rt entry %I\n     (IP: %I, GW: %I)\n",
          nf->fn.prefix, ip, nf->nh);
-      rte_update(p->table, ne, p, e);
+       rte_update(p->table, ne, p, e);
+      }
+      else
+      {
+        rte_update(p->table, ne, p, NULL);
+        FIB_ITERATE_PUT(&fit, nftmp);
+        fib_delete(fib, nftmp);
+        goto again1;
+      }
     }
   }
   FIB_ITERATE_END(nftmp);
+
+  WALK_LIST(oa, po->area_list)
+  {
+    FIB_ITERATE_INIT(&fit, &oa->rtr);
+again2:
+    FIB_ITERATE_START(&oa->rtr, &fit, nftmp)
+    {
+      nf = (ort *) nftmp;
+      if (memcmp(&nf->n, &nf->o, sizeof(orta)))
+      {                                /* Some difference */
+        check_sum_lsa(po, nf, ORT_ROUTER);
+        if(nf->n.metric1 >= LSINFINITY)
+        {
+          FIB_ITERATE_PUT(&fit, nftmp);
+          fib_delete(&oa->rtr, nftmp);
+          goto again2;
+        }
+      }
+    }
+    FIB_ITERATE_END(nftmp);
+
+    /* Check condensed summary LSAs */
+    FIB_WALK(&oa->net_fib, nftmp)
+    {
+      anet = (struct area_net *) nftmp;
+      if((!anet->hidden) && anet->active && (!oa->trcap))
+        originate_sum_lsa(oa, &anet->fn, ORT_NET, 1);
+      else flush_sum_lsa(oa, &anet->fn, ORT_NET);
+    }
+    FIB_WALK_END;
+  }
 }
index ca3d057282ae26c2720c69eeb5d1d76fdfa25525..f7b33303ed57512269e1c8573df95f7c40f84121 100644 (file)
 #ifndef _BIRD_OSPF_RT_H_
 #define _BIRD_OSPF_RT_H_
 
+#define ORT_UNDEF -1
+#define ORT_ROUTER 1
+#define ORT_NET 0
+
 typedef struct orta
 {
   int type;
   int capa;
+#define ORTA_ASBR 1
+#define ORTA_ABR 2
   struct ospf_area *oa;
   int metric1;
   int metric2;
@@ -27,12 +33,9 @@ orta;
 typedef struct ort
 {
   struct fib_node fn;
-  int dest;
-#define ORT_UNDEF -1
-#define ORT_ROUTER 1
-#define ORT_NET 0
   orta n;
   orta o;
+  struct ort *efn;             /* For RFC1583 */
 }
 ort;
 
index f1e691ccc59ddbbb253194e4a0e75a56e9888202..215765e640cb9217c9cd61cf9e4e4fed10a93ce5 100644 (file)
@@ -1,8 +1,8 @@
 /*
  *     BIRD -- OSPF Topological Database
  *
- *     (c) 1999        Martin Mares <mj@ucw.cz>
- *     (c) 1999 - 2004 Ondrej Filip <feela@network.cz>
+ *     (c) 1999       Martin Mares <mj@ucw.cz>
+ *     (c) 1999--2004 Ondrej Filip <feela@network.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -25,7 +25,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
 {
   struct proto_ospf *po = oa->po;
   struct ospf_iface *ifa;
-  int j = 0, k = 0, v = 0;
+  int j = 0, k = 0;
   u16 i = 0;
   struct ospf_lsa_rt *rt;
   struct ospf_lsa_rt_link *ln;
@@ -39,8 +39,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
     if ((ifa->an == oa->areaid) && (ifa->state != OSPF_IS_DOWN))
     {
       i++;
-      if (ifa->type == OSPF_IT_VLINK)
-       v = 1;
     }
   }
   rt = mb_allocz(po->proto.pool, sizeof(struct ospf_lsa_rt) +
@@ -49,7 +47,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
     rt->veb.bit.b = 1;
   if ((po->ebit) && (!oa->stub))
     rt->veb.bit.e = 1;
-  rt->veb.bit.v = v;
   ln = (struct ospf_lsa_rt_link *) (rt + 1);
 
   WALK_LIST(ifa, po->iface_list)
@@ -83,7 +80,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
          }
          else
          {
-           ln->id = ipa_to_u32(ifa->iface->addr->ip);
+           ln->data = ipa_to_u32(ifa->iface->addr->ip);
          }
        }
        else
@@ -97,9 +94,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
            ln->data = 0xffffffff;
          }
          else
-         {
            i--;                /* No link added */
-         }
        }
        break;
       case OSPF_IT_BCAST:
@@ -140,14 +135,21 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
          }
        }
        break;
-      case OSPF_IT_VLINK:      /* FIXME Add virtual links! */
-       i--;
-       break;
+      case OSPF_IT_VLINK:
+       neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
+       if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
+       {
+         ln->type = LSART_VLNK;
+         ln->id = neigh->rid;
+         ln->metric = ifa->cost;
+         ln->notos = 0;
+          rt->veb.bit.v = 1;
+        }
+       else
+         i--;          /* No link added */
+        break;
       }
     }
-    if (ifa->type == OSPF_IT_VLINK)
-      v = 1;
-    ln = (ln + 1);
   }
   rt->links = i;
   *length = i * sizeof(struct ospf_lsa_rt_link) + sizeof(struct ospf_lsa_rt) +
@@ -305,6 +307,7 @@ originate_net_lsa(struct ospf_iface *ifa)
   ifa->orignet = 0;
 }
 
+
 static void *
 originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
                       struct ea_list *attrs)
@@ -325,15 +328,16 @@ originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po,
 
   if (m1 != LSINFINITY)
   {
-    et->etos = 0;
-    et->metric = m1;
+    et->etm.metric = m1;
+    et->etm.etos.tos = 0;
+    et->etm.etos.ebit = 0;
   }
   else
   {
-    et->etos = 0x80;
-    et->metric = m2;
+    et->etm.metric = m2;
+    et->etm.etos.tos = 0;
+    et->etm.etos.ebit = 1;
   }
-  et->padding = 0;
   et->tag = tag;
   if (ipa_compare(e->attrs->gw, ipa_from_u32(0)) != 0)
   {
@@ -371,6 +375,175 @@ max_ext_lsa(unsigned pxlen)
   return i;
 }
 
+void
+flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type)
+{
+  struct proto_ospf *po = oa->po;
+  struct proto *p = &po->proto;
+  struct top_hash_entry *en;
+  u32 rtid = po->proto.cf->global->router_id;
+  struct ospf_lsa_header lsa;
+  int max, i;
+  struct ospf_lsa_sum *sum = NULL;
+  union ospf_lsa_sum_tm *tm;
+
+  lsa.rt = rtid;
+  lsa.type = LSA_T_SUM_NET;
+  if (type == ORT_ROUTER)
+    lsa.type = LSA_T_SUM_RT;
+
+  max = max_ext_lsa(fn->pxlen);
+
+  for (i = 0; i < max; i++)
+  {
+    lsa.id = ipa_to_u32(fn->prefix) + i;
+    if ((en = ospf_hash_find_header(oa->gr, &lsa)) != NULL)
+    {
+      sum = en->lsa_body;
+      if (fn->pxlen == ipa_mklen(sum->netmask))
+      {
+        en->lsa.age = LSA_MAXAGE;
+        en->lsa.sn = LSA_MAXSEQNO;
+        OSPF_TRACE(D_EVENTS, "Flushing summary lsa.");
+        ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
+        if (can_flush_lsa(oa)) flush_lsa(en, oa);
+        break;
+      }
+    }
+  }
+}
+
+  
+
+
+void
+originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric)
+{
+  struct proto_ospf *po = oa->po;
+  struct proto *p = &po->proto;
+  struct top_hash_entry *en;
+  u32 rtid = po->proto.cf->global->router_id;
+  struct ospf_lsa_header lsa;
+  void *body = NULL;
+  int i, max, mlen = fn->pxlen, found = 0, free = -1;
+  struct ospf_lsa_sum *sum = NULL;
+  union ospf_lsa_sum_tm *tm;
+  lsa.type = LSA_T_SUM_NET;
+
+  if (type == ORT_ROUTER)
+  {
+    lsa.type = LSA_T_SUM_RT;
+    mlen = 0;
+  }
+
+  lsa.age = 0;
+  lsa.rt = rtid;
+  lsa.sn = LSA_INITSEQNO;
+  lsa.length = sizeof(struct ospf_lsa_sum) + sizeof(union ospf_lsa_sum_tm) +
+    sizeof(struct ospf_lsa_header);
+
+  max = max_ext_lsa(fn->pxlen);
+  for (i = 0; i < max; i++)
+  {
+    lsa.id = ipa_to_u32(fn->prefix) + i;
+    if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL)
+    {
+      if (free < 0) free = i;
+    }
+    else
+    {
+      sum = en->lsa_body;
+      if (mlen == ipa_mklen(sum->netmask))
+      {
+        tm = (union ospf_lsa_sum_tm *) (sum + 1);
+        if (tm->metric == (unsigned)metric) return;    /* No reason for origination */
+        lsa.sn = en->lsa.sn + 1;
+        free = en->lsa.id;
+        break;
+      }
+    }
+  }
+
+  if(free < 0)
+  {
+    log("%s: got more routes for one /%d network then %d, ignoring", p->name,
+        fn->pxlen, max);
+    return;
+  }
+  lsa.id = free;
+  
+  sum = en->lsa_body;
+  tm = (union ospf_lsa_sum_tm *) (sum + 1);
+
+  OSPF_TRACE(D_EVENTS, "Originating summary (type %d) lsa for %I/%d.", lsa.type, fn->prefix,
+             fn->pxlen);
+
+  sum = mb_alloc(p->pool, sizeof(struct ospf_lsa_sum) + sizeof(union ospf_lsa_sum_tm));
+  sum->netmask = ipa_mkmask(mlen);
+  tm = (union ospf_lsa_sum_tm *) (sum + 1);
+  tm->metric = metric;
+  tm->tos.tos = 0;
+
+  lsasum_calculate(&lsa, body);
+  en = lsa_install_new(&lsa, body, oa);
+  ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
+}
+
+void
+check_sum_lsa(struct proto_ospf *po, ort *nf, int dest)
+{
+  struct proto *p = &po->proto;
+  struct ospf_area *oa;
+  struct area_net *anet;
+  int flush, mlen;
+  ip_addr ip;
+
+  if (po->areano < 2) return;
+
+  if ((nf->n.type > RTS_OSPF_IA) && (nf->o.type > RTS_OSPF_IA)) return;
+
+  WALK_LIST(oa, po->area_list)
+  {
+    flush = 0;
+    if ((nf->n.metric1 >= LSINFINITY) || (nf->n.type > RTS_OSPF_IA))
+      flush = 1;
+    if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR)))
+      flush = 1;
+    if (nf->n.oa->areaid == oa->areaid)
+      flush = 1;
+    /* FIXME: Test next hop - is it in actual area? */
+    if ((dest == ORT_ROUTER) && oa->stub)
+      flush = 1;
+    /* FIXME stub for networks? */
+
+    mlen = nf->fn.pxlen;
+    ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen));
+    if((!oa->trcap) && fib_route(&oa->net_fib, ip, mlen))      /* The route fits into some area */
+      flush = 1;
+
+    if(flush)          /* FIXME Go on... */
+    {
+      flush_sum_lsa(oa, &nf->fn, dest);
+      continue;
+    }
+    originate_sum_lsa(oa, &nf->fn, dest, nf->n.metric1);
+  }
+}
+
+void
+check_sum_areas(struct proto_ospf *po)
+{
+  struct proto *p = &po->proto;
+  struct ospf_area *oa;
+  struct area_net *anet;
+
+  WALK_LIST(oa, po->area_list)
+  {
+    ;  /* FIXME */
+  }
+}
+
+
 /**
  * originate_ext_lsa - new route received from nest and filters
  * @n: network prefix and mask
@@ -397,8 +570,7 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
   struct proto *p = &po->proto;
   struct ospf_area *oa;
   struct ospf_lsa_ext *ext1, *ext2;
-  int i;
-  int max;
+  int i, max;
 
   OSPF_TRACE(D_EVENTS, "Originating Ext lsa for %I/%d.", n->n.prefix,
             n->n.pxlen);
@@ -408,6 +580,7 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
   lsa.type = LSA_T_EXT;
   lsa.rt = rtid;
   lsa.sn = LSA_INITSEQNO;
+
   body = originate_ext_lsa_body(n, e, po, attrs);
   lsa.length = sizeof(struct ospf_lsa_ext) + sizeof(struct ospf_lsa_ext_tos) +
     sizeof(struct ospf_lsa_header);
@@ -440,9 +613,12 @@ originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
   lsasum_calculate(&lsa, body);
   WALK_LIST(oa, po->area_list)
   {
-    en = lsa_install_new(&lsa, body, oa);
-    ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
-    body = originate_ext_lsa_body(n, e, po, attrs);
+    if (!oa->stub)
+    {
+      en = lsa_install_new(&lsa, body, oa);
+      ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1);
+      body = originate_ext_lsa_body(n, e, po, attrs);
+    }
   }
   mb_free(body);
 
@@ -617,6 +793,7 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type)
   e->dist = LSINFINITY;
   e->nhi = NULL;
   e->nh = ipa_from_u32(0);
+  e->lb = ipa_from_u32(0);
   e->lsa.id = lsa;
   e->lsa.rt = rtr;
   e->lsa.type = type;
index 55ecb4fed667b5f23e4ece03ff813f28ae93ea02..c6031c5e22b0285e7df8ceed39232bdca5fc5e57 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- OSPF
  *
- *     (c) 1999 - 2004 Ondrej Filip <feela@network.cz>
+ *     (c) 1999--2004 Ondrej Filip <feela@network.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -21,15 +21,15 @@ struct top_hash_entry
   void *lsa_body;
   bird_clock_t inst_t;         /* Time of installation into DB */
   ip_addr nh;                  /* Next hop */
+  ip_addr lb;                  /* Link back */
   struct iface *nhi;
-  u16 dist;                    /* Distance from the root */
+  u32 dist;                    /* Distance from the root */
   u16 ini_age;
   u8 color;
 #define OUTSPF 0
 #define CANDIDATE 1
 #define INSPF 2
   u8 padding;
-  u16 padding2;
 };
 
 struct top_graph
@@ -62,5 +62,11 @@ int can_flush_lsa(struct ospf_area *oa);
 int max_ext_lsa(unsigned pxlen);
 void originate_ext_lsa(net * n, rte * e, struct proto_ospf *po,
                       struct ea_list *attrs);
+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);
+void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
+
+
+
 
 #endif /* _BIRD_OSPF_TOPOLOGY_H_ */