]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Temporary integrated commit (OSPF), unfinished.
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 19 Oct 2012 14:26:51 +0000 (16:26 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Fri, 19 Oct 2012 14:26:51 +0000 (16:26 +0200)
proto/ospf/config.Y
proto/ospf/iface.c
proto/ospf/iface.h
proto/ospf/lsalib.c
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/packet.h
proto/ospf/rt.c
proto/ospf/topology.c
proto/ospf/topology.h

index 46e78761332ea91f6a0014962f47aeb144b371d1..bf27bb40fa7a084ecf50ff4b6aff1892e70e2b4b 100644 (file)
@@ -21,7 +21,9 @@ static list *this_nets;
 static struct area_net_config *this_pref;
 static struct ospf_stubnet_config *this_stubnet; 
 
-#ifdef OSPFv2
+static inline int ospf_cfg_is_v2(void) { return OSPF_CFG->ospf2; }
+static inline int ospf_cfg_is_v3(void) { return ! OSPF_CFG->ospf2; }
+
 static void
 ospf_iface_finish(void)
 {
@@ -38,21 +40,6 @@ ospf_iface_finish(void)
   if ((ip->autype == OSPF_AUTH_NONE) && (ip->passwords != NULL))
     log(L_WARN "Password option without authentication option does not make sense");
 }
-#endif
-
-#ifdef OSPFv3
-static void
-ospf_iface_finish(void)
-{
-  struct ospf_iface_patt *ip = OSPF_PATT;
-
-  if (ip->deadint == 0)
-    ip->deadint = ip->deadc * ip->helloint;
-
-  if ((ip->autype != OSPF_AUTH_NONE) || (get_passwords() != NULL))
-    cf_error("Authentication not supported in OSPFv3");
-}
-#endif
 
 static void
 ospf_area_finish(void)
@@ -104,25 +91,23 @@ ospf_proto_finish(void)
 }
 
 static inline void
-check_defcost(int cost)
+ospf_check_defcost(int cost)
 {
   if ((cost <= 0) || (cost >= LSINFINITY))
    cf_error("Default cost must be in range 1-%d", LSINFINITY-1);
 }
 
 static inline void
-set_instance_id(unsigned id)
+ospf_check_auth(void)
 {
-#ifdef OSPFv3
-  OSPF_PATT->instance_id = id;
-#else
-  cf_error("Instance ID requires OSPFv3");
-#endif
+  if (ospf_cfg_is_v3())
+    cf_error("Authentication not supported in OSPFv3");
 }
 
+
 CF_DECLS
 
-CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
+CF_KEYWORDS(OSPF, OSPF2, OSPF3, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
 CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, COST2, RETRANSMIT)
 CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
 CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
@@ -134,16 +119,23 @@ CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL)
 
 %type <t> opttext
 %type <ld> lsadb_args
+%type <i> ospf_proto_key
 
 CF_GRAMMAR
 
 CF_ADDTO(proto, ospf_proto '}' { ospf_proto_finish(); } )
 
-ospf_proto_start: proto_start OSPF {
+ospf_proto_key: 
+   OSPF2 { $$ = 1; }
+ | OSPF3 { $$ = 0; }
+ ;
+
+ospf_proto_start: proto_start ospf_proto_key {
      this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config), $1);
      init_list(&OSPF_CFG->area_list);
      init_list(&OSPF_CFG->vlink_list);
      OSPF_CFG->tick = OSPF_DEFAULT_TICK;
+     OSPF_CFG->ospf2 = $2;
   }
  ;
 
@@ -155,7 +147,7 @@ ospf_proto:
 ospf_proto_item:
    proto_item
  | RFC1583COMPAT bool { OSPF_CFG->rfc1583 = $2; }
- | ECMP bool { OSPF_CFG->ecmp = $2 ? DEFAULT_ECMP_LIMIT : 0; }
+ | ECMP bool { OSPF_CFG->ecmp = $2 ? OSPF_DEFAULT_ECMP_LIMIT : 0; }
  | ECMP bool LIMIT expr { OSPF_CFG->ecmp = $2 ? $4 : 0; if ($4 < 0) cf_error("ECMP limit cannot be negative"); }
  | TICK expr { OSPF_CFG->tick = $2; if($2<=0) cf_error("Tick must be greater than zero"); }
  | ospf_area
@@ -189,9 +181,9 @@ ospf_area_item:
  | NSSA { this_area->type = OPT_N; }
  | SUMMARY bool { this_area->summary = $2; }
  | DEFAULT NSSA bool { this_area->default_nssa = $3; }
- | DEFAULT COST expr { this_area->default_cost = $3; check_defcost($3); }
- | DEFAULT COST2 expr { this_area->default_cost = $3 | LSA_EXT_EBIT; check_defcost($3); }
- | STUB COST expr { this_area->default_cost = $3;  check_defcost($3); }
+ | DEFAULT COST expr { this_area->default_cost = $3; ospf_check_defcost($3); }
+ | DEFAULT COST2 expr { this_area->default_cost = $3 | LSA_EXT_EBIT; ospf_check_defcost($3); }
+ | STUB COST expr { this_area->default_cost = $3; ospf_check_defcost($3); }
  | TRANSLATOR bool { this_area->translator = $2; }
  | TRANSLATOR STABILITY expr { this_area->transint = $3; }
  | NETWORKS { this_nets = &this_area->net_list; } '{' pref_list '}'
@@ -243,10 +235,10 @@ ospf_vlink_item:
  | WAIT expr { OSPF_PATT->waitint = $2 ; }
  | DEAD expr { OSPF_PATT->deadint = $2 ; if ($2<=1) cf_error("Dead interval must be greater than one"); }
  | DEAD COUNT expr { OSPF_PATT->deadc = $3 ; if ($3<=1) cf_error("Dead count must be greater than one"); }
- | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
- | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
- | AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
- | password_list 
+ | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE }
+ | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE; ospf_check_auth(); }
+ | AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT; ospf_check_auth(); }
+ | password_list { ospf_check_auth(); }
  ;
 
 ospf_vlink_start: VIRTUAL LINK idval
@@ -286,7 +278,7 @@ ospf_iface_item:
  | TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; }
  | TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; }
  | TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; }
- | REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (OSPF_VERSION != 2) cf_error("Real broadcast option requires OSPFv2"); }
+ | REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (!ospf_cfg_is_v2()) cf_error("Real broadcast option requires OSPFv2"); }
  | TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
  | PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); }
  | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
@@ -294,13 +286,13 @@ ospf_iface_item:
  | CHECK LINK bool { OSPF_PATT->check_link = $3; }
  | ECMP WEIGHT expr { OSPF_PATT->ecmp_weight = $3 - 1; if (($3<1) || ($3>256)) cf_error("ECMP weight must be in range 1-256"); }
  | NEIGHBORS '{' ipa_list '}'
- | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
- | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
- | AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
+ | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE; }
+ | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE; ospf_check_auth(); }
+ | AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT; ospf_check_auth(); }
  | RX BUFFER LARGE { OSPF_PATT->rxbuf = OSPF_RXBUF_LARGE ; } 
  | RX BUFFER NORMAL { OSPF_PATT->rxbuf = OSPF_RXBUF_NORMAL ; } 
  | RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if (($3 < OSPF_RXBUF_MINSIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); } 
- | password_list
+ | password_list { ospf_check_auth(); }
  ;
 
 pref_list:
@@ -376,7 +368,10 @@ ospf_iface_start:
 
 ospf_instance_id:
    /* empty */
- | INSTANCE expr { set_instance_id($2); }
+ | INSTANCE expr {
+     if (ospf_cfg_is_v2()) cf_error("Instance ID requires OSPFv3");
+     OSPF_PATT->instance_id = $2;
+   }
  ;
 
 ospf_iface_opts:
index d029545b972ea0b8c0cb4a35afa22652bc224099..10f87e51fb3f47815d1c8dce2d4c28f747116bdd 100644 (file)
@@ -505,7 +505,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
   else if (ospf_is_v3(po))
     OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
               iface->name, ip->instance_id, oa->areaid);
-  else if (ifa->addr->flags & IA_PEER)
+  else if (addr->flags & IA_PEER)
     OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R",
               iface->name, addr->opposite, oa->areaid);
   else
@@ -801,16 +801,60 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
 }
 
 
-#ifdef OSPFv2
+/*
+ * Matching ifaces and addresses to OSPF ifaces/patterns
+ * ospfX_ifa_notify(), ospfX_ifaces_reconfigure()
+ *
+ * This is significantly different in OSPFv2 and OSPFv3.
+ * In OSPFv2, OSPF ifaces are created for each IP prefix (struct ifa)
+ * In OSPFv3, OSPF ifaces are created based on real iface (struct iface),
+ * but there may be several ones with different instance_id
+ */
 
 static inline struct ospf_iface_patt *
-ospf_iface_patt_find(struct ospf_area_config *ac, struct ifa *a)
+ospf_iface_patt_find2(struct ospf_area_config *ac, struct ifa *a)
 {
   return (struct ospf_iface_patt *) iface_patt_find(&ac->patt_list, a->iface, a);
 }
 
+struct ospf_iface_patt *
+ospf_iface_patt_find3(struct ospf_area_config *ac, struct iface *iface, int iid)
+{
+  struct ospf_iface_patt *pt, *res = NULL;
+
+  WALK_LIST(pt, ac->patt_list)
+    if ((pt->instance_id >= iid) && (iface_patt_match(&pt->i, iface, NULL)) &&
+       (!res || (pt->instance_id < res->instance_id)))
+      res = pt;
+
+  return res;
+}
+
+static struct ospf_iface *
+ospf_iface_find_by_key2(struct ospf_area *oa, struct ifa *a)
+{
+  struct ospf_iface *ifa;
+  WALK_LIST(ifa, oa->po->iface_list)
+    if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->type != OSPF_IT_VLINK))
+      return ifa;
+
+  return NULL;
+}
+
+static struct ospf_iface *
+ospf_iface_find_by_key3(struct ospf_area *oa, struct ifa *a, int iid)
+{
+  struct ospf_iface *ifa;
+  WALK_LIST(ifa, oa->po->iface_list)
+    if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->instance_id == iid) && (ifa->type != OSPF_IT_VLINK))
+      return ifa;
+
+  return NULL;
+}
+
+
 void
-ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
+ospf_ifa_notify2(struct proto *p, unsigned flags, struct ifa *a)
 {
   struct proto_ospf *po = (struct proto_ospf *) p;
 
@@ -828,7 +872,7 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
     WALK_LIST(oa, po->area_list)
     {
       struct ospf_iface_patt *ip;
-      if (ip = ospf_iface_patt_find(oa->ac, a))
+      if (ip = ospf_iface_patt_find2(oa->ac, a))
       {
        if (!done)
          ospf_iface_new(oa, a, ip);
@@ -852,70 +896,8 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
   }
 }
 
-static struct ospf_iface *
-ospf_iface_find_by_key(struct ospf_area *oa, struct ifa *a)
-{
-  struct ospf_iface *ifa;
-  WALK_LIST(ifa, oa->po->iface_list)
-    if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->type != OSPF_IT_VLINK))
-      return ifa;
-
-  return NULL;
-}
-
-void
-ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
-{
-  struct ospf_iface_patt *ip;
-  struct iface *iface;
-  struct ifa *a;
-
-  WALK_LIST(iface, iface_list)
-    WALK_LIST(a, iface->addrs)
-    {
-      if (a->flags & IA_SECONDARY)
-       continue;
-
-      if (a->scope <= SCOPE_LINK)
-       continue;
-
-      if (ip = ospf_iface_patt_find(oa->ac, a))
-      {
-       /* Main inner loop */
-       struct ospf_iface *ifa = ospf_iface_find_by_key(oa, a);
-       if (ifa)
-       {
-         if (ospf_iface_reconfigure(ifa, ip))
-           continue;
-
-         /* Hard restart */
-         ospf_iface_shutdown(ifa);
-         ospf_iface_remove(ifa);
-       }
-       
-       ospf_iface_new(oa, a, ip);
-      }
-    }
-}
-
-
-#else /* OSPFv3 */
-
-struct ospf_iface_patt *
-ospf_iface_patt_find(struct ospf_area_config *ac, struct iface *iface, int iid)
-{
-  struct ospf_iface_patt *pt, *res = NULL;
-
-  WALK_LIST(pt, ac->patt_list)
-    if ((pt->instance_id >= iid) && (iface_patt_match(&pt->i, iface, NULL)) &&
-       (!res || (pt->instance_id < res->instance_id)))
-      res = pt;
-
-  return res;
-}
-
 void
-ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
+ospf_ifa_notify3(struct proto *p, unsigned flags, struct ifa *a)
 {
   struct proto_ospf *po = (struct proto_ospf *) p;
 
@@ -939,7 +921,7 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
        int iid = 0;
 
        struct ospf_iface_patt *ip;
-       while (ip = ospf_iface_patt_find(oa->ac, a->iface, iid))
+       while (ip = ospf_iface_patt_find3(oa->ac, a->iface, iid))
        {
          ospf_iface_new(oa, a, ip);
          if (ip->instance_id == 0)
@@ -980,19 +962,44 @@ ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
   }
 }
 
-static struct ospf_iface *
-ospf_iface_find_by_key(struct ospf_area *oa, struct ifa *a, int iid)
+
+static void
+ospf_ifaces_reconfigure2(struct ospf_area *oa, struct ospf_area_config *nac)
 {
-  struct ospf_iface *ifa;
-  WALK_LIST(ifa, oa->po->iface_list)
-    if ((ifa->addr == a) && (ifa->oa == oa) && (ifa->instance_id == iid) && (ifa->type != OSPF_IT_VLINK))
-      return ifa;
+  struct ospf_iface_patt *ip;
+  struct iface *iface;
+  struct ifa *a;
 
-  return NULL;
+  WALK_LIST(iface, iface_list)
+    WALK_LIST(a, iface->addrs)
+    {
+      if (a->flags & IA_SECONDARY)
+       continue;
+
+      if (a->scope <= SCOPE_LINK)
+       continue;
+
+      if (ip = ospf_iface_patt_find2(oa->ac, a))
+      {
+       /* Main inner loop */
+       struct ospf_iface *ifa = ospf_iface_find_by_key2(oa, a);
+       if (ifa)
+       {
+         if (ospf_iface_reconfigure(ifa, ip))
+           continue;
+
+         /* Hard restart */
+         ospf_iface_shutdown(ifa);
+         ospf_iface_remove(ifa);
+       }
+       
+       ospf_iface_new(oa, a, ip);
+      }
+    }
 }
 
-void
-ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
+static void
+ospf_ifaces_reconfigure3(struct ospf_area *oa, struct ospf_area_config *nac)
 {
   struct ospf_iface_patt *ip;
   struct iface *iface;
@@ -1008,12 +1015,12 @@ ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
        continue;
 
       int iid = 0;
-      while (ip = ospf_iface_patt_find(nac, iface, iid))
+      while (ip = ospf_iface_patt_find3(nac, iface, iid))
       {
        iid = ip->instance_id + 1;
 
        /* Main inner loop */
-       struct ospf_iface *ifa = ospf_iface_find_by_key(oa, a, ip->instance_id);
+       struct ospf_iface *ifa = ospf_iface_find_by_key3(oa, a, ip->instance_id);
        if (ifa)
        {
          if (ospf_iface_reconfigure(ifa, ip))
@@ -1029,7 +1036,15 @@ ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
     }
 }
 
-#endif
+void
+ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
+{
+  if (ospf_is_v2(oa->po))
+    ospf_ifaces_reconfigure2(oa, nac);
+  else
+    ospf_ifaces_reconfigure3(oa, nac);
+}
+
 
 static void
 ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
index 3f887728e27b252edfb1727f2973be9bf3b624fa..751105ff2bc9c067a543a81450275a1ad538db00 100644 (file)
@@ -14,7 +14,8 @@ void ospf_iface_chstate(struct ospf_iface *ifa, u8 state);
 void ospf_iface_sm(struct ospf_iface *ifa, int event);
 struct ospf_iface *ospf_iface_find(struct proto_ospf *p, struct iface *what);
 void ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface);
-void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
+void ospf_ifa_notify2(struct proto *p, unsigned flags, struct ifa *a);
+void ospf_ifa_notify3(struct proto *p, unsigned flags, struct ifa *a);
 void ospf_iface_info(struct ospf_iface *ifa);
 void ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip);
 void ospf_iface_remove(struct ospf_iface *ifa);
index aa3dc7411e66a15d4071594c35cbf09155b37c30..51a407459af1ab603a098b6853ee861bbd2c8ad7 100644 (file)
@@ -394,7 +394,7 @@ lsa_walk_rt3(struct ospf_lsa_rt_walk *rt)
 {
   while (rt->buf >= rt->bufend)
   {
-    rt->en = ospf_hash_find_rt_next(rt->en);
+    rt->en = ospf_hash_find_rt3_next(rt->en);
     if (!rt->en)
       return 0;
 
@@ -423,7 +423,7 @@ lsa_walk_rt_init(struct proto_ospf *po, struct top_hash_entry *act, struct ospf_
   if (rt->ospf2)
     rt->en = act;
   else
-    rt->en = ospf_hash_find_rt_first(po->gr, act->domain, act->lsa.rt);
+    rt->en = ospf_hash_find_rt3_first(po->gr, act->domain, act->lsa.rt);
 
   rt->buf = rt->en->lsa_body;
   rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
@@ -779,7 +779,7 @@ lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body)
 struct top_hash_entry *
 lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body)
 {
-  /* LSA can be temporarrily, but body must be mb_allocated. */
+  /* LSA can be temporary, but body must be mb_allocated. */
   int change = 0;
   struct top_hash_entry *en;
 
@@ -790,13 +790,11 @@ lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain,
   }
   else
   {
-    if ((en->lsa.length != lsa->length)
-#ifdef OSPFv2       
-       || (en->lsa.options != lsa->options)
-#endif
-       || (en->lsa.age == LSA_MAXAGE)
-       || (lsa->age == LSA_MAXAGE)
-       || memcmp(en->lsa_body, body, lsa->length - sizeof(struct ospf_lsa_header)))
+    if ((en->lsa.length != lsa->length) ||
+       (en->lsa.type_raw != lsa->type_raw) ||  /* check for OSPFv2 options */
+       (en->lsa.age == LSA_MAXAGE) ||
+       (lsa->age == LSA_MAXAGE) ||
+       memcmp(en->lsa_body, body, lsa->length - sizeof(struct ospf_lsa_header)))
       change = 1;
 
     s_rem_node(SNODE en);
index d8296b9eba24cdfc5e20abcb94cb0ac8d745cdd1..598867588594a66a0cb099d6ec5aab5af88a75cc 100644 (file)
@@ -292,6 +292,7 @@ ospf_dump(struct proto *p)
 static struct proto *
 ospf_init(struct proto_config *c)
 {
+  struct ospf_config *oc = (struct ospf_config *) c;  
   struct proto *p = proto_new(c, sizeof(struct proto_ospf));
 
   p->make_tmp_attrs = ospf_make_tmp_attrs;
@@ -301,7 +302,7 @@ ospf_init(struct proto_config *c)
   p->accept_ra_types = RA_OPTIMAL;
   p->rt_notify = ospf_rt_notify;
   p->if_notify = ospf_if_notify;
-  p->ifa_notify = ospf_ifa_notify;
+  p->ifa_notify = oc->ospf2 ? ospf_ifa_notify2 : ospf_ifa_notify3;
   p->rte_better = ospf_rte_better;
   p->rte_same = ospf_rte_same;
 
@@ -915,14 +916,12 @@ ospf_sh_iface(struct proto *p, char *iff)
  * values
  */
 
-#ifdef OSPFv3
-
 static struct ospf_lsa_header *
 fake_lsa_from_prefix_lsa(struct ospf_lsa_header *dst, struct ospf_lsa_header *src,
                         struct ospf_lsa_prefix *px)
 {
   dst->age = src->age;
-  dst->type = px->ref_type;
+  dst->type_raw = px->ref_type;
   dst->id = px->ref_id;
   dst->rt = px->ref_rt;
   dst->sn = src->sn;
@@ -930,9 +929,8 @@ fake_lsa_from_prefix_lsa(struct ospf_lsa_header *dst, struct ospf_lsa_header *sr
   return dst;
 }
 
-#endif
 
-static int lsa_compare_ospf3; // XXXX fixme
+static int lsa_compare_ospf3;
 
 static int
 lsa_compare_for_state(const void *p1, const void *p2)
@@ -944,27 +942,25 @@ lsa_compare_for_state(const void *p1, const void *p2)
   struct ospf_lsa_header lsatmp1, lsatmp2;
   u16 lsa1_type = he1->lsa_type;
   u16 lsa2_type = he2->lsa_type;
-  int px1 = 0;
-  int px2 = 0;
 
   if (he1->domain != he2->domain)
     return he1->domain - he2->domain;
 
-  if (lsa_compare_ospf3)
-  {
-    px1 = (lsa1_type == LSA_T_PREFIX);
-    px2 = (lsa2_type == LSA_T_PREFIX);
-    xxxx();
 
-    if (px1)
-    {
-      lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
-      lsa1_type = lsa1->type;
-      px1 = 1;
-    }
+  /* px1 or px2 assumes OSPFv3 */
+  int px1 = (lsa1_type == LSA_T_PREFIX);
+  int px2 = (lsa2_type == LSA_T_PREFIX);
+
+  if (px1)
+  {
+    lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
+    lsa1_type = lsa1->type_raw;        /* FIXME: handle unknown ref_type */
+  }
 
-    if (px2)
-      lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
+  if (px2)
+  {
+    lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
+    lsa2_type = lsa2->type_raw;
   }
 
 
@@ -976,11 +972,9 @@ lsa_compare_for_state(const void *p1, const void *p2)
 
   if (nt1)
   {
-#ifdef OSPFv3
     /* In OSPFv3, networks are named based on ID of DR */
-    if (lsa1->rt != lsa2->rt)
+    if (lsa_compare_ospf3 && (lsa1->rt != lsa2->rt))
       return lsa1->rt - lsa2->rt;
-#endif
 
     /* For OSPFv2, this is IP of the network,
        for OSPFv3, this is interface ID */
@@ -1062,7 +1056,7 @@ show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he, int verbose)
       if (ospf_is_v2(po))
       {
        /* In OSPFv2, we try to find network-LSA to get prefix/pxlen */
-       struct top_hash_entry *net_he = ospf_hash_find_net(po->gr, he->domain, rtl.id, 0);
+       struct top_hash_entry *net_he = ospf_hash_find_net2(po->gr, he->domain, rtl.id);
 
        if (net_he)
        {
@@ -1163,7 +1157,7 @@ show_lsa_external(struct top_hash_entry *he, int ospf2)
 }
 
 static inline void
-show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
+show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode)
 {
   struct ospf_lsa_prefix *px = he->lsa_body;
   ip_addr pxa;
@@ -1174,13 +1168,13 @@ show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
   int i;
 
   /* We check whether given prefix-LSA is related to the current node */
-  if ((px->ref_type != cnode->type_raw) || (px->ref_rt != cnode->rt))
+  if ((px->ref_type != cnode->lsa.type_raw) || (px->ref_rt != cnode->lsa.rt))
     return;
 
   if ((px->ref_type == LSA_T_RT) && (px->ref_id != 0))
     return;
 
-  if ((px->ref_type == LSA_T_NET) && (px->ref_id != cnode->id))
+  if ((px->ref_type == LSA_T_NET) && (px->ref_id != cnode->lsa.id))
     return;
 
   buf = px->rest;
@@ -1199,7 +1193,6 @@ void
 ospf_sh_state(struct proto *p, int verbose, int reachable)
 {
   struct proto_ospf *po = (struct proto_ospf *) p;
-  struct ospf_lsa_header *cnode = NULL;
   int ospf2 = ospf_is_v2(po);
   int num = po->gr->hash_entries;
   unsigned int i, ix, j1, j2, jx;
@@ -1218,6 +1211,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
   struct top_hash_entry *hea[num];
   struct top_hash_entry *hex[verbose ? num : 0];
   struct top_hash_entry *he;
+  struct top_hash_entry *cnode = NULL;
 
   j1 = j2 = jx = 0;
   WALK_SLIST(he, po->lsal)
@@ -1257,6 +1251,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
   if ((j1 + j2) != num)
     die("Fatal mismatch");
 
+  lsa_compare_ospf3 = !ospf2;
   qsort(hea, j1, sizeof(struct top_hash_entry *), lsa_compare_for_state);
   qsort(hex, jx, sizeof(struct top_hash_entry *), ext_compare_for_state);
 
@@ -1290,7 +1285,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
       if (((he->lsa_type == LSA_T_RT) || (he->lsa_type == LSA_T_NET))
          && ((he->color == INSPF) || !reachable))
       {
-       cnode = &(he->lsa);
+       cnode = he;
 
        if (he->domain != last_area)
        {
@@ -1304,12 +1299,12 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
        continue;
     }
 
-    ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->rt));
+    ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->lsa.rt));
 
     switch (he->lsa_type)
     {
       case LSA_T_RT:
-       if (he->lsa.id == cnode->id)
+       if (he->lsa.id == cnode->lsa.id)
          show_lsa_router(po, he, verbose);
        break;
 
@@ -1318,12 +1313,12 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
        break;
 
       case LSA_T_SUM_NET:
-       if (cnode->type == LSA_T_RT)
+       if (cnode->lsa_type == LSA_T_RT)
          show_lsa_sum_net(he, ospf2);
        break;
 
       case LSA_T_SUM_RT:
-       if (cnode->type == LSA_T_RT)
+       if (cnode->lsa_type == LSA_T_RT)
          show_lsa_sum_rt(he, ospf2);
        break;
 
@@ -1340,13 +1335,13 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
     /* In these cases, we close the current node */
     if ((i+1 == j1)
        || (hea[i+1]->domain != last_area)
-       || (hea[i+1]->lsa.rt != cnode->rt)
+       || (hea[i+1]->lsa.rt != cnode->lsa.rt)
        || (hea[i+1]->lsa_type == LSA_T_NET))
     {
-      while ((ix < jx) && (hex[ix]->lsa.rt < cnode->rt))
+      while ((ix < jx) && (hex[ix]->lsa.rt < cnode->lsa.rt))
        ix++;
 
-      while ((ix < jx) && (hex[ix]->lsa.rt == cnode->rt))
+      while ((ix < jx) && (hex[ix]->lsa.rt == cnode->lsa.rt))
        show_lsa_external(hex[ix++], ospf2);
 
       cnode = NULL;
@@ -1426,6 +1421,7 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
   unsigned int i, j;
   int last_dscope = -1;
   u32 last_domain = 0;
+  u16 type_mask = ospf_is_v2(po) ?  0x00ff : 0xffff;   /* see lsa_get_type() */
 
   if (p->proto_state != PS_UP)
   {
@@ -1452,17 +1448,18 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
   for (i = 0; i < j; i++)
   {
     struct ospf_lsa_header *lsa = &(hea[i]->lsa);
-    int dscope = LSA_SCOPE(hea[i]->lsa_type);
-
+    u16 lsa_type = lsa->type_raw & type_mask;
+    u16 dscope = LSA_SCOPE(hea[i]->lsa_type);
+    
+    /* Hack: 1 is used for LSA_SCOPE_LINK, fixed by & 0xf000 */
     if (ld->scope && (dscope != (ld->scope & 0xf000)))
       continue;
 
     if ((ld->scope == LSA_SCOPE_AREA) && (hea[i]->domain != ld->area))
       continue;
 
-    /* Ignore high nibble */
-    // XXXX check
-    if (ld->type && ((lsa->type & 0x0fff) != (ld->type & 0x0fff)))
+    /* For user convenience ignore high nibble */
+    if (ld->type && ((lsa_type & 0x0fff) != (ld->type & 0x0fff)))
       continue;
 
     if (ld->lsid && (lsa->id != ld->lsid))
@@ -1499,24 +1496,24 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
     }
 
     cli_msg(-1017," %04x  %-15R %-15R %5u  %08x    %04x",
-           lsa->type, lsa->id, lsa->rt, lsa->age, lsa->sn, lsa->checksum);
+           lsa_type, lsa->id, lsa->rt, lsa->age, lsa->sn, lsa->checksum);
   }
   cli_msg(0, "");
 }
 
 
 struct protocol proto_ospf = {
-  name:                        "OSPF",
-  template:            "ospf%d",
-  attr_class:          EAP_OSPF,
-  preference:          DEF_PREF_OSPF,
-  init:                        ospf_init,
-  dump:                        ospf_dump,
-  start:               ospf_start,
-  shutdown:            ospf_shutdown,
-  reconfigure:         ospf_reconfigure,
-  get_status:          ospf_get_status,
-  get_attr:            ospf_get_attr,
-  get_route_info:      ospf_get_route_info
-  // show_proto_info:  ospf_sh
+  .name =              "OSPF",
+  .template =          "ospf%d",
+  .attr_class =                EAP_OSPF,
+  .preference =                DEF_PREF_OSPF,
+  .init =              ospf_init,
+  .dump =              ospf_dump,
+  .start =             ospf_start,
+  .shutdown =          ospf_shutdown,
+  .reconfigure =       ospf_reconfigure,
+  .get_status =                ospf_get_status,
+  .get_attr =          ospf_get_attr,
+  .get_route_info =    ospf_get_route_info
 };
+
index 0c12a506e55eb3648f658a2f6b0719be1ea2366f..b8188870feae53d5be9db7b5f2444a3857731887 100644 (file)
@@ -2,6 +2,8 @@
  *     BIRD -- OSPF
  *
  *     (c) 1999--2005 Ondrej Filip <feela@network.cz>
+ *     (c) 2009--2012 Ondrej Zajicek <santiago@crfreenet.org>
+ *     (c) 2009--2012 CZ.NIC z.s.p.o.
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -53,13 +55,6 @@ do { if ((po->proto.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
 
 #define OSPF_PROTO 89
 
-
-// XXXX
-#define OSPFv3 1
-#define OSPF_VERSION 3
-
-
-
 #define LSREFRESHTIME 1800     /* 30 minutes */
 #define MINLSINTERVAL 5
 #define MINLSARRIVAL 1
@@ -75,9 +70,10 @@ struct ospf_config
 {
   struct proto_config c;
   unsigned tick;
+  byte ospf2;
   byte rfc1583;
   byte abr;
-  int ecmp;
+  byte ecmp;
   list area_list;              /* list of struct ospf_area_config */
   list vlink_list;             /* list of struct ospf_iface_patt */
 };
@@ -314,16 +310,6 @@ static inline void ospf_pkt_set_instance_id(struct ospf_packet *pkt, u16 val)
 { pkt->vdep = htons(val << 8); }
 
 
-// XXXX
-/*
-#define LSA_T_RT       1
-#define LSA_T_NET      2
-#define LSA_T_SUM_NET  3
-#define LSA_T_SUM_RT   4
-#define LSA_T_EXT      5
-#define LSA_T_NSSA     7
-*/
-
 #define LSA_T_RT       0x2001
 #define LSA_T_NET      0x2002
 #define LSA_T_SUM_NET  0x2003
@@ -524,6 +510,12 @@ lsa_net_count(struct ospf_lsa_header *lsa)
     / sizeof(u32);
 }
 
+/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
+   as index, so we need to encapsulate RID to IP address */
+
+#define ipa_from_rid(x) ipa_from_u32(x)
+#define ipa_to_rid(x) ipa_to_u32(x)
+
 
 #define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4)
 #define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32)
@@ -723,6 +715,7 @@ struct proto_ospf
   list area_list;
   int areano;                  /* Number of area I belong to */
   struct fib rtf;              /* Routing table */
+  byte ospf2;                  /* OSPF v2 or v3 */
   byte rfc1583;                        /* RFC1583 compatibility */
   byte ebit;                   /* Did I originate any ext lsa? */
   byte ecmp;                   /* Maximal number of nexthops in ECMP route, or 0 */
@@ -776,26 +769,32 @@ void schedule_rtcalc(struct proto_ospf *po);
 void schedule_net_lsa(struct ospf_iface *ifa);
 
 static inline int ospf_is_v2(struct proto_ospf *po)
-{ return 0; } // XXXX fixme
+{ return po->ospf2; }
+
 static inline int ospf_is_v3(struct proto_ospf *po)
-{ return 1; } // XXXX fixme
+{ return ! po->ospf2; }
+
+static inline int ospf_get_version(struct proto_ospf *po)
+{ return ospf_is_v2(po) ? 2 : 3; }
 
 static inline void lsa_fix_options(struct proto_ospf *po, struct ospf_lsa_header *lsa, u8 options)
 { if (ospf_is_v2(po)) lsa_set_options(lsa, options); }
 
 struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
+
 static inline struct ospf_area *ospf_main_area(struct proto_ospf *po)
 { return (po->areano == 1) ? HEAD(po->area_list) : po->backbone; }
 
 static inline int oa_is_stub(struct ospf_area *oa)
 { return (oa->options & (OPT_E | OPT_N)) == 0; }
+
 static inline int oa_is_ext(struct ospf_area *oa)
 { return oa->options & OPT_E; }
+
 static inline int oa_is_nssa(struct ospf_area *oa)
 { return oa->options & OPT_N; }
 
 
-
 void schedule_link_lsa(struct ospf_iface *ifa); // XXXX caller ?? 
 
 void ospf_sh_neigh(struct proto *p, char *iff);
index c097a46757cf5a082e190a9cadc658e2bd534b29..d22a27138218dc6eae133e7f41fc15c7174c0e91 100644 (file)
@@ -2,6 +2,8 @@
  *     BIRD -- OSPF
  *
  *     (c) 1999--2005 Ondrej Filip <feela@network.cz>
+ *     (c) 2009--2012 Ondrej Zajicek <santiago@crfreenet.org>
+ *     (c) 2009--2012 CZ.NIC z.s.p.o.
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -18,7 +20,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
 
   pkt = (struct ospf_packet *) buf;
 
-  pkt->version = OSPF_VERSION;
+  pkt->version = ospf_get_version(po);
 
   pkt->type = h_type;
 
@@ -334,7 +336,7 @@ ospf_rx_hook(sock *sk, int size)
     return 1;
   }
 
-  if (pkt->version != OSPF_VERSION)
+  if (pkt->version != ospf_get_version(po))
   {
     log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version);
     return 1;
index 863a0293bcfd5024bf60d283a66441df7df08a30..5cd7bcc482f27f9e7f3c861ccb5c708198f93d8f 100644 (file)
@@ -21,9 +21,7 @@ void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
 void ospf_send_to_bdr(struct ospf_iface *ifa);
 
 static inline void ospf_send_to_all(struct ospf_iface *ifa)
-{
-  ospf_send_to(ifa, ifa->all_routers);
-}
+{ ospf_send_to(ifa, ifa->all_routers); }
 
 static inline void ospf_send_to_des(struct ospf_iface *ifa)
 {
@@ -33,14 +31,22 @@ static inline void ospf_send_to_des(struct ospf_iface *ifa)
     ospf_send_to_bdr(ifa);
 }
 
-static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; }
+static inline unsigned ospf_pkt_hdrlen(struct proto_ospf *po)
+{
+  return ospf_is_v2(po) ?
+    (sizeof(struct ospf_packet) + sizeof(union ospf_auth)) :
+    sizeof(struct ospf_packet);
+}
+
+
+static inline void * ospf_tx_buffer(struct ospf_iface *ifa)
+{ return ifa->sk->tbuf; }
 
-static inline unsigned
-ospf_pkt_bufsize(struct ospf_iface *ifa)
+static inline unsigned ospf_pkt_bufsize(struct ospf_iface *ifa)
 {
   /* Reserve buffer space for authentication footer */
-  return ifa->sk->tbsize - 
-    (ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
+  unsigned res_size = (ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
+  return ifa->sk->tbsize - res_size;
 }
 
 
index 68a577bd08f84444a4094e682c5654c0543ada94..e3ad9d1af449444d8ad299fc2bb530215d3ecc0c 100644 (file)
@@ -1,9 +1,11 @@
 /*
- * BIRD -- OSPF
+ *     BIRD -- OSPF
  * 
- * (c) 2000--2004 Ondrej Filip <feela@network.cz>
+ *     (c) 2000--2004 Ondrej Filip <feela@network.cz>
+ *     (c) 2009--2012 Ondrej Zajicek <santiago@crfreenet.org>
+ *     (c) 2009--2012 CZ.NIC z.s.p.o.
  * 
- * Can be freely distributed and used under the terms of the GNU GPL.
+ *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 
 #include "ospf.h"
@@ -13,10 +15,6 @@ static void add_cand(list * l, struct top_hash_entry *en,
                     struct ospf_area *oa, int i);
 static void rt_sync(struct proto_ospf *po);
 
-/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
-   as index, so we need to encapsulate RID to IP address */
-
-#define ipa_from_rid(x) ipa_from_u32(x)
 
 static inline void reset_ri(ort *ort)
 {
index fd4e9cd898afd26f840a038413c7f6dcd5540e30..fe0caf9d84a409fd73d3340981e4a711b738c95d 100644 (file)
@@ -3,6 +3,8 @@
  *
  *     (c) 1999       Martin Mares <mj@ucw.cz>
  *     (c) 1999--2004 Ondrej Filip <feela@network.cz>
+ *     (c) 2009--2012 Ondrej Zajicek <santiago@crfreenet.org>
+ *     (c) 2009--2012 CZ.NIC z.s.p.o.
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -24,12 +26,6 @@ void originate_prefix_rt_lsa(struct ospf_area *oa);
 void originate_prefix_net_lsa(struct ospf_iface *ifa);
 void flush_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
-
 
 static inline u32
 fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
@@ -75,7 +71,7 @@ fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
   if (ospf_is_v3(po))
     return fn->uid;
 
-  u32 id = _I(fn->prefix);
+  u32 id = ipa_to_u32(fn->prefix);
 
   if ((po->rfc1583) || (fn->pxlen == 0) || (fn->pxlen == 32))
     return id;
@@ -760,7 +756,6 @@ originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric)
   OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)",
             fn->prefix, fn->pxlen, metric);
 
-  /* options argument is used in ORT_NET and OSPFv3 only */
   lsa.age = 0;
   lsa.type_raw = LSA_T_SUM_NET;
   lsa.id = fibnode_to_lsaid(po, fn);
@@ -999,24 +994,10 @@ find_surrogate_fwaddr(struct ospf_area *oa)
        (ifa->type == OSPF_IT_VLINK))
       continue;
 
-#ifdef OSPFv2
-    a = ifa->addr;
-    if (a->flags & IA_PEER)
-      continue;
-
-    np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
-    if (np > cur_np)
-    {
-      cur_addr = a;
-      cur_np = np;
-    }
-
-#else /* OSPFv3 */
-    WALK_LIST(a, ifa->iface->addrs)
+    if (ospf_is_v2(po))
     {
-      if ((a->flags & IA_SECONDARY) ||
-         (a->flags & IA_PEER) ||
-         (a->scope <= SCOPE_LINK))
+      a = ifa->addr;
+      if (a->flags & IA_PEER)
        continue;
 
       np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
@@ -1026,7 +1007,23 @@ find_surrogate_fwaddr(struct ospf_area *oa)
        cur_np = np;
       }
     }
-#endif
+    else /* OSPFv3 */
+    {
+      WALK_LIST(a, ifa->iface->addrs)
+      {
+       if ((a->flags & IA_SECONDARY) ||
+           (a->flags & IA_PEER) ||
+           (a->scope <= SCOPE_LINK))
+         continue;
+
+       np = ((a->flags & IA_HOST) || ifa->stub) ? 2 : 1;
+       if (np > cur_np)
+       {
+         cur_addr = a;
+         cur_np = np;
+       }
+      }
+    }
   }
 
   return cur_addr ? cur_addr->ip : IPA_NONE;
@@ -1637,71 +1634,66 @@ ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
   return e;
 }
 
-
-#ifdef OSPFv2
-
-/* In OSPFv2, sometimes we don't know Router ID when looking for network LSAs.
-   There should be just one, so we find any match. */
-struct top_hash_entry *
-ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif)
-{
-  struct top_hash_entry *e;
-  e = f->hash_table[ospf_top_hash(f, domain, id, 0, LSA_T_NET)];
-
-  while (e && (e->lsa.id != id || e->lsa.type != LSA_T_NET || e->domain != domain))
-    e = e->next;
-
-  return e;
-}
-
-#endif
-
-
-#ifdef OSPFv3
-
-/* In OSPFv3, usually we don't know LSA ID when looking for router
-   LSAs. We return matching LSA with smallest LSA ID. */
+/* In OSPFv2, lsa.id is the same as lsa.rt for router LSA. In OSPFv3, we don't know
+   lsa.id when looking for router LSAs. We return matching LSA with smallest lsa.id. */
 struct top_hash_entry *
 ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
 {
   struct top_hash_entry *rv = NULL;
   struct top_hash_entry *e;
-  e = f->hash_table[ospf_top_hash(f, domain, 0, rtr, LSA_T_RT)];
-  
+  /* We can put rtr for lsa.id to hash fn, it is ignored in OSPFv3 */
+  e = f->hash_table[ospf_top_hash(f, domain, rtr, rtr, LSA_T_RT)];
+
   while (e)
+  {
+    if (e->lsa.rt == rtr && e->lsa_type == LSA_T_RT && e->domain == domain)
     {
-      if (e->lsa.rt == rtr && e->lsa.type == LSA_T_RT && e->domain == domain)
-       if (!rv || e->lsa.id < rv->lsa.id)
-         rv = e;
-      e = e->next;
+      if (f->ospf2 && (e->lsa.id == rtr))
+       return e;
+      if (!f->ospf2 && (!rv || e->lsa.id < rv->lsa.id))
+       rv = e;
     }
+    e = e->next;
+  }
 
   return rv;
 }
 
 static inline struct top_hash_entry *
-find_matching_rt(struct top_hash_entry *e, u32 domain, u32 rtr)
+find_matching_rt3(struct top_hash_entry *e, u32 domain, u32 rtr)
 {
-  while (e && (e->lsa.rt != rtr || e->lsa.type != LSA_T_RT || e->domain != domain))
+  while (e && (e->lsa.rt != rtr || e->lsa_type != LSA_T_RT || e->domain != domain))
     e = e->next;
   return e;
 }
 
 struct top_hash_entry *
-ospf_hash_find_rt_first(struct top_graph *f, u32 domain, u32 rtr)
+ospf_hash_find_rt3_first(struct top_graph *f, u32 domain, u32 rtr)
 {
   struct top_hash_entry *e;
   e = f->hash_table[ospf_top_hash(f, domain, 0, rtr, LSA_T_RT)];
-  return find_matching_rt(e, domain, rtr);
+  return find_matching_rt3(e, domain, rtr);
 }
 
 struct top_hash_entry *
-ospf_hash_find_rt_next(struct top_hash_entry *e)
+ospf_hash_find_rt3_next(struct top_hash_entry *e)
 {
-  return find_matching_rt(e->next, e->domain, e->lsa.rt);
+  return find_matching_rt3(e->next, e->domain, e->lsa.rt);
 }
 
-#endif
+/* In OSPFv2, we don't know Router ID when looking for network LSAs.
+   There should be just one, so we find any match. */
+struct top_hash_entry *
+ospf_hash_find_net2(struct top_graph *f, u32 domain, u32 id)
+{
+  struct top_hash_entry *e;
+  e = f->hash_table[ospf_top_hash(f, domain, id, 0, LSA_T_NET)];
+
+  while (e && (e->lsa.id != id || e->lsa_type != LSA_T_NET || e->domain != domain))
+    e = e->next;
+
+  return e;
+}
 
 
 struct top_hash_entry *
index 4d7a17560a60850750c0e81003007d027ff3652a..3b5047206e25b10e5b92f1650a5d741ccbd06d8d 100644 (file)
@@ -39,6 +39,7 @@ struct top_graph
   pool *pool;                  /* Pool we allocate from */
   slab *hash_slab;             /* Slab for hash entries */
   struct top_hash_entry **hash_table;  /* Hashing (modelled a`la fib) */
+  unsigned int ospf2;          /* Whether it is for OSPFv2 or OSPFv3 */
   unsigned int hash_size;
   unsigned int hash_order;
   unsigned int hash_mask;
@@ -71,28 +72,21 @@ void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
 void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, u32 metric, ip_addr fwaddr, u32 tag, int pbit);
 void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src);
 
+struct top_hash_entry * ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr);
+struct top_hash_entry * ospf_hash_find_rt3_first(struct top_graph *f, u32 domain, u32 rtr);
+struct top_hash_entry * ospf_hash_find_rt3_next(struct top_hash_entry *e);
 
-#ifdef OSPFv2
-struct top_hash_entry * ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif);
-
-static inline struct top_hash_entry *
-ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
-{
-  return ospf_hash_find(f, domain, rtr, rtr, LSA_T_RT);
-}
+struct top_hash_entry * ospf_hash_find_net2(struct top_graph *f, u32 domain, u32 id);
 
-#else /* OSPFv3 */
+/* In OSPFv2, id is network IP prefix (lsa.id) while lsa.rt field is unknown
+   In OSPFv3, id is lsa.rt of DR while nif is neighbor iface id (lsa.id) */
 static inline struct top_hash_entry *
 ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif)
 {
-  return ospf_hash_find(f, domain, nif, id, LSA_T_NET);
+  return f->ospf2 ?
+    ospf_hash_find_net2(f, domain, id) :
+    ospf_hash_find(f, domain, nif, id, LSA_T_NET);
 }
 
 
-struct top_hash_entry * ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr);
-struct top_hash_entry * ospf_hash_find_rt_first(struct top_graph *f, u32 domain, u32 rtr);
-struct top_hash_entry * ospf_hash_find_rt_next(struct top_hash_entry *e);
-#endif
-
-
 #endif /* _BIRD_OSPF_TOPOLOGY_H_ */