diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 46e78761..bf27bb40 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -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 opttext %type lsadb_args +%type 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: diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index d029545b..10f87e51 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -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) -{ - 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; +static void +ospf_ifaces_reconfigure2(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_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) diff --git a/proto/ospf/iface.h b/proto/ospf/iface.h index 3f887728..751105ff 100644 --- a/proto/ospf/iface.h +++ b/proto/ospf/iface.h @@ -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); diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index aa3dc741..51a40745 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -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); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index d8296b9e..59886758 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -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 or px2 assumes OSPFv3 */ + int px1 = (lsa1_type == LSA_T_PREFIX); + int px2 = (lsa2_type == LSA_T_PREFIX); + + if (px1) { - px1 = (lsa1_type == LSA_T_PREFIX); - px2 = (lsa2_type == LSA_T_PREFIX); - xxxx(); + lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body); + lsa1_type = lsa1->type_raw; /* FIXME: handle unknown ref_type */ + } - if (px1) - { - lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body); - lsa1_type = lsa1->type; - px1 = 1; - } - - 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 }; + diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 0c12a506..b8188870 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -2,6 +2,8 @@ * BIRD -- OSPF * * (c) 1999--2005 Ondrej Filip + * (c) 2009--2012 Ondrej Zajicek + * (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); diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index c097a467..d22a2713 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -2,6 +2,8 @@ * BIRD -- OSPF * * (c) 1999--2005 Ondrej Filip + * (c) 2009--2012 Ondrej Zajicek + * (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; diff --git a/proto/ospf/packet.h b/proto/ospf/packet.h index 863a0293..5cd7bcc4 100644 --- a/proto/ospf/packet.h +++ b/proto/ospf/packet.h @@ -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 unsigned -ospf_pkt_bufsize(struct ospf_iface *ifa) + +static inline void * ospf_tx_buffer(struct ospf_iface *ifa) +{ return ifa->sk->tbuf; } + +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; } diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 68a577bd..e3ad9d1a 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -1,9 +1,11 @@ /* - * BIRD -- OSPF + * BIRD -- OSPF * - * (c) 2000--2004 Ondrej Filip + * (c) 2000--2004 Ondrej Filip + * (c) 2009--2012 Ondrej Zajicek + * (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) { diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index fd4e9cd8..fe0caf9d 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -3,6 +3,8 @@ * * (c) 1999 Martin Mares * (c) 1999--2004 Ondrej Filip + * (c) 2009--2012 Ondrej Zajicek + * (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) + if (ospf_is_v2(po)) { - cur_addr = a; - cur_np = np; - } - -#else /* OSPFv3 */ - WALK_LIST(a, ifa->iface->addrs) - { - 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 * diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index 4d7a1756..3b504720 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -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); +struct top_hash_entry * ospf_hash_find_net2(struct top_graph *f, u32 domain, u32 id); -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); -} - -#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_ */