diff options
Diffstat (limited to 'proto/ospf')
-rw-r--r-- | proto/ospf/Makefile | 9 | ||||
-rw-r--r-- | proto/ospf/config.Y | 49 | ||||
-rw-r--r-- | proto/ospf/dbdes.c | 2 | ||||
-rw-r--r-- | proto/ospf/hello.c | 6 | ||||
-rw-r--r-- | proto/ospf/iface.c | 48 | ||||
-rw-r--r-- | proto/ospf/lsalib.c | 30 | ||||
-rw-r--r-- | proto/ospf/lsalib.h | 4 | ||||
-rw-r--r-- | proto/ospf/neighbor.c | 7 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 114 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 108 | ||||
-rw-r--r-- | proto/ospf/packet.c | 8 | ||||
-rw-r--r-- | proto/ospf/rt.c | 323 | ||||
-rw-r--r-- | proto/ospf/rt.h | 4 | ||||
-rw-r--r-- | proto/ospf/topology.c | 116 | ||||
-rw-r--r-- | proto/ospf/topology.h | 4 |
15 files changed, 432 insertions, 400 deletions
diff --git a/proto/ospf/Makefile b/proto/ospf/Makefile index f90222cf..fe52ed30 100644 --- a/proto/ospf/Makefile +++ b/proto/ospf/Makefile @@ -1,5 +1,4 @@ -source=ospf.c topology.c packet.c hello.c neighbor.c iface.c dbdes.c lsreq.c lsupd.c lsack.c lsalib.c rt.c -root-rel=../../ -dir-name=proto/ospf - -include ../../Rules +src := dbdes.c hello.c iface.c lsack.c lsalib.c lsreq.c lsupd.c neighbor.c ospf.c packet.c rt.c topology.c +obj := $(src-o-files) +$(all-daemon) +$(cf-local) diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 7b35b191..72928875 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -82,6 +82,10 @@ ospf_proto_finish(void) if (EMPTY_LIST(cf->area_list)) cf_error( "No configured areas in OSPF"); + /* Define default channel */ + if (EMPTY_LIST(this_proto->channels)) + channel_config_new(NULL, this_proto->net_type, this_proto); + int areano = 0; int backbone = 0; int nssa = 0; @@ -98,7 +102,7 @@ ospf_proto_finish(void) cf->abr = areano > 1; /* Route export or NSSA translation (RFC 3101 3.1) */ - cf->asbr = (this_proto->out_filter != FILTER_REJECT) || (nssa && cf->abr); + cf->asbr = (proto_cf_main_channel(this_proto)->out_filter != FILTER_REJECT) || (nssa && cf->abr); if (cf->abr && !backbone) { @@ -144,25 +148,32 @@ CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK, ONLY, BFD) CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL) CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY) CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH) -CF_KEYWORDS(SECONDARY, MERGE, LSA, SUPPRESSION) +CF_KEYWORDS(SECONDARY, MERGE, LSA, SUPPRESSION, OSPF2, OSPF3) -%type <t> opttext %type <ld> lsadb_args -%type <i> nbma_eligible +%type <i> ospf_variant nbma_eligible CF_GRAMMAR CF_ADDTO(proto, ospf_proto '}' { ospf_proto_finish(); } ) -ospf_proto_start: proto_start OSPF { - this_proto = proto_config_new(&proto_ospf, $1); - init_list(&OSPF_CFG->area_list); - init_list(&OSPF_CFG->vlink_list); - OSPF_CFG->tick = OSPF_DEFAULT_TICK; - OSPF_CFG->ospf2 = OSPF_IS_V2; - } +ospf_variant: + OSPF { $$ = 1; } + | OSPF2 { $$ = 1; } + | OSPF3 { $$ = 0; } ; +ospf_proto_start: proto_start ospf_variant +{ + this_proto = proto_config_new(&proto_ospf, $1); + this_proto->net_type = $2 ? NET_IP4 : NET_IP6; + + init_list(&OSPF_CFG->area_list); + init_list(&OSPF_CFG->vlink_list); + OSPF_CFG->tick = OSPF_DEFAULT_TICK; + OSPF_CFG->ospf2 = $2; +}; + ospf_proto: ospf_proto_start proto_name '{' | ospf_proto ospf_proto_item ';' @@ -170,6 +181,7 @@ ospf_proto: ospf_proto_item: proto_item + | proto_channel | RFC1583COMPAT bool { OSPF_CFG->rfc1583 = $2; } | STUB ROUTER bool { OSPF_CFG->stub_router = $3; } | ECMP bool { OSPF_CFG->ecmp = $2 ? OSPF_DEFAULT_ECMP_LIMIT : 0; } @@ -226,10 +238,10 @@ ospf_stubnet: ; ospf_stubnet_start: - prefix { + net_ip { this_stubnet = cfg_allocz(sizeof(struct ospf_stubnet_config)); add_tail(&this_area->stubnet_list, NODE this_stubnet); - this_stubnet->px = $1; + this_stubnet->prefix = $1; this_stubnet->cost = COST_D; } ; @@ -325,7 +337,6 @@ ospf_iface_item: | TTL SECURITY bool { OSPF_PATT->ttl_security = $3; } | TTL SECURITY TX ONLY { OSPF_PATT->ttl_security = 2; } | BFD bool { OSPF_PATT->bfd = $2; cf_check_bfd($2); } - | SECONDARY bool { OSPF_PATT->bsd_secondary = $2; } | password_list { ospf_check_auth(); } ; @@ -336,12 +347,11 @@ pref_list: pref_item: pref_base pref_opt ';' ; -pref_base: prefix +pref_base: net_ip { this_pref = cfg_allocz(sizeof(struct area_net_config)); add_tail(this_nets, NODE this_pref); - this_pref->px.addr = $1.addr; - this_pref->px.len = $1.len; + this_pref->prefix = $1; } ; @@ -415,11 +425,6 @@ ospf_iface: ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); } ; -opttext: - TEXT - | /* empty */ { $$ = NULL; } - ; - CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC1); }) CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC2); }) CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_TAG); }) diff --git a/proto/ospf/dbdes.c b/proto/ospf/dbdes.c index d6904343..195b03ad 100644 --- a/proto/ospf/dbdes.c +++ b/proto/ospf/dbdes.c @@ -39,7 +39,7 @@ struct ospf_dbdes3_packet static inline uint -ospf_dbdes_hdrlen(struct ospf_proto *p UNUSED4 UNUSED6) +ospf_dbdes_hdrlen(struct ospf_proto *p) { return ospf_is_v2(p) ? sizeof(struct ospf_dbdes2_packet) : sizeof(struct ospf_dbdes3_packet); diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index e00487dc..2c55155d 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -74,7 +74,7 @@ ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn) ((ifa->type == OSPF_IT_PTP) && !ifa->ptp_netmask)) ps->netmask = 0; else - ps->netmask = htonl(u32_mkmask(ifa->addr->pxlen)); + ps->netmask = htonl(u32_mkmask(ifa->addr->prefix.pxlen)); ps->helloint = ntohs(ifa->helloint); ps->options = ifa->oa->options; @@ -198,7 +198,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, /* RFC 2328 10.5 */ /* - * We may not yet havethe associate neighbor, so we use Router ID from the + * We may not yet have the associate neighbor, so we use Router ID from the * packet instead of one from the neighbor structure for log messages. */ u32 rcv_rid = ntohl(pkt->routerid); @@ -227,7 +227,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, if ((ifa->type != OSPF_IT_VLINK) && (ifa->type != OSPF_IT_PTP) && - ((uint) pxlen != ifa->addr->pxlen)) + ((uint) pxlen != ifa->addr->prefix.pxlen)) DROP("prefix length mismatch", pxlen); neighbors = ps->neighbors; diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 280fa4c1..675cf76d 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -55,7 +55,9 @@ ifa_tx_length(struct ospf_iface *ifa) static inline uint ifa_tx_hdrlen(struct ospf_iface *ifa) { - uint hlen = SIZE_OF_IP_HEADER; + struct ospf_proto *p = ifa->oa->po; + + uint hlen = ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH; /* Relevant just for OSPFv2 */ if (ifa->autype == OSPF_AUTH_CRYPT) @@ -115,6 +117,7 @@ ospf_sk_open(struct ospf_iface *ifa) sock *sk = sk_new(ifa->pool); sk->type = SK_IP; + sk->subtype = ospf_is_v2(p) ? SK_IPV4 : SK_IPV6; sk->dport = OSPF_PROTO; sk->saddr = ifa->addr->ip; sk->iface = ifa->iface; @@ -199,6 +202,7 @@ ospf_open_vlink_sk(struct ospf_proto *p) { sock *sk = sk_new(p->p.pool); sk->type = SK_IP; + sk->subtype = ospf_is_v2(p) ? SK_IPV4 : SK_IPV6; sk->dport = OSPF_PROTO; /* FIXME: configurable tos/priority ? */ @@ -244,8 +248,8 @@ ospf_iface_down(struct ospf_iface *ifa) OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R", ifa->ifname, ifa->addr->opposite, ifa->oa->areaid); else - OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R", - ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid); + OSPF_TRACE(D_EVENTS, "Removing interface %s (%N) from area %R", + ifa->ifname, &ifa->addr->prefix, ifa->oa->areaid); /* First of all kill all the related vlinks */ WALK_LIST(iff, p->iface_list) @@ -530,15 +534,6 @@ ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr) if (addr->iface->flags & IF_LOOPBACK) return 1; - /* - * For compatibility reasons on BSD systems, we force OSPF - * interfaces with non-primary IP prefixes to be stub. - */ -#if defined(OSPFv2) && !defined(CONFIG_MC_PROPER_SRC) - if (!ip->bsd_secondary && !(addr->flags & IA_PRIMARY)) - return 1; -#endif - return ip->stub; } @@ -557,8 +552,8 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R", iface->name, addr->opposite, oa->areaid); else - OSPF_TRACE(D_EVENTS, "Adding interface %s (%I/%d) to area %R", - iface->name, addr->prefix, addr->pxlen, oa->areaid); + OSPF_TRACE(D_EVENTS, "Adding interface %s (%N) to area %R", + iface->name, &addr->prefix, oa->areaid); pool = rp_new(p->p.pool, "OSPF Interface"); ifa = mb_allocz(pool, sizeof(struct ospf_iface)); @@ -596,6 +591,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i if (ip->ptp_netmask < 2) ifa->ptp_netmask = ip->ptp_netmask; + ifa->drip = ifa->bdrip = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6; ifa->type = ospf_iface_classify(ip->type, addr); @@ -635,7 +631,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i should be used). Because OSPFv3 iface is not subnet-specific, there is no need for ipa_in_net() check */ - if (ospf_is_v2(p) && !ipa_in_net(nb->ip, addr->prefix, addr->pxlen)) + if (ospf_is_v2(p) && !ipa_in_netX(nb->ip, &addr->prefix)) continue; if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip)) @@ -648,7 +644,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i add_tail(&oa->po->iface_list, NODE ifa); struct object_lock *lock = olock_new(pool); - lock->addr = ospf_is_v2(p) ? ifa->addr->prefix : IPA_NONE; + lock->addr = ospf_is_v2(p) ? ipa_from_ip4(net4_prefix(&ifa->addr->prefix)) : IPA_NONE; lock->type = OBJLOCK_IP; lock->port = OSPF_PROTO; lock->inst = ifa->instance_id; @@ -898,7 +894,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) WALK_LIST(nb, new->nbma_list) { /* See related note in ospf_iface_new() */ - if (ospf_is_v2(p) && !ipa_in_net(nb->ip, ifa->addr->prefix, ifa->addr->pxlen)) + if (ospf_is_v2(p) && !ipa_in_netX(nb->ip, &ifa->addr->prefix)) continue; if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip)) @@ -1085,6 +1081,9 @@ ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a) { struct ospf_proto *p = (struct ospf_proto *) P; + if (a->prefix.type != NET_IP4) + return; + if (a->flags & IA_SECONDARY) return; @@ -1114,6 +1113,9 @@ ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a) { struct ospf_proto *p = (struct ospf_proto *) P; + if (a->prefix.type != NET_IP6) + return; + if (a->flags & IA_SECONDARY) return; @@ -1166,6 +1168,9 @@ ospf_reconfigure_ifaces2(struct ospf_proto *p) WALK_LIST(a, iface->addrs) { + if (a->prefix.type != NET_IP4) + continue; + if (a->flags & IA_SECONDARY) continue; @@ -1184,8 +1189,8 @@ ospf_reconfigure_ifaces2(struct ospf_proto *p) continue; /* Hard restart */ - log(L_INFO "%s: Restarting interface %s (%I/%d) in area %R", - p->p.name, ifa->ifname, a->prefix, a->pxlen, s.oa->areaid); + log(L_INFO "%s: Restarting interface %s (%N) in area %R", + p->p.name, ifa->ifname, &a->prefix, s.oa->areaid); ospf_iface_shutdown(ifa); ospf_iface_remove(ifa); } @@ -1209,6 +1214,9 @@ ospf_reconfigure_ifaces3(struct ospf_proto *p) WALK_LIST(a, iface->addrs) { + if (a->prefix.type != NET_IP6) + continue; + if (a->flags & IA_SECONDARY) continue; @@ -1340,7 +1348,7 @@ ospf_iface_info(struct ospf_iface *ifa) else if (ifa->addr->flags & IA_PEER) cli_msg(-1015, "Interface %s (peer %I)", ifa->ifname, ifa->addr->opposite); else - cli_msg(-1015, "Interface %s (%I/%d)", ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen); + cli_msg(-1015, "Interface %s (%N)", ifa->ifname, &ifa->addr->prefix); cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more); cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid); diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index cb7b186a..b88a114d 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -280,21 +280,19 @@ lsa_walk_rt(struct ospf_lsa_rt_walk *rt) void -lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric) +lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, net_addr *net, u8 *pxopts, u32 *metric) { if (ospf2) { struct ospf_lsa_sum2 *ls = en->lsa_body; - *ip = ipa_from_u32(en->lsa.id & ls->netmask); - *pxlen = u32_masklen(ls->netmask); + net_fill_ip4(net, ip4_from_u32(en->lsa.id & ls->netmask), u32_masklen(ls->netmask)); *pxopts = 0; *metric = ls->metric & LSA_METRIC_MASK; } else { struct ospf_lsa_sum3_net *ls = en->lsa_body; - u16 rest; - lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest); + ospf_get_ipv6_prefix(ls->prefix, net, pxopts, NULL); *metric = ls->metric & LSA_METRIC_MASK; } } @@ -324,8 +322,9 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r if (ospf2) { struct ospf_lsa_ext2 *ext = en->lsa_body; - rt->ip = ipa_from_u32(en->lsa.id & ext->netmask); - rt->pxlen = u32_masklen(ext->netmask); + net_fill_ip4(&rt->net, + ip4_from_u32(en->lsa.id & ext->netmask), + u32_masklen(ext->netmask)); rt->pxopts = 0; rt->metric = ext->metric & LSA_METRIC_MASK; rt->ebit = ext->metric & LSA_EXT2_EBIT; @@ -339,14 +338,13 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r else { struct ospf_lsa_ext3 *ext = en->lsa_body; - u16 rest; - u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest); + u32 *buf = ospf_get_ipv6_prefix(ext->rest, &rt->net, &rt->pxopts, NULL); rt->metric = ext->metric & LSA_METRIC_MASK; rt->ebit = ext->metric & LSA_EXT3_EBIT; rt->fbit = ext->metric & LSA_EXT3_FBIT; if (rt->fbit) - buf = lsa_get_ipv6_addr(buf, &rt->fwaddr); + buf = ospf_get_ipv6_addr(buf, &rt->fwaddr); else rt->fwaddr = IPA_NONE; @@ -452,7 +450,7 @@ lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *bod return 0; u8 pxl = pxlen(body->prefix); - if (pxl > MAX_PREFIX_LENGTH) + if (pxl > IP6_MAX_PREFIX_LENGTH) return 0; if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + @@ -491,11 +489,11 @@ lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body) return 0; u8 pxl = pxlen(body->rest); - if (pxl > MAX_PREFIX_LENGTH) + if (pxl > IP6_MAX_PREFIX_LENGTH) return 0; int len = IPV6_PREFIX_SPACE(pxl); - if (body->metric & LSA_EXT3_FBIT) // forwardinf address + if (body->metric & LSA_EXT3_FBIT) // forwarding address len += 16; if (body->metric & LSA_EXT3_TBIT) // route tag len += 4; @@ -520,7 +518,7 @@ lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, uint offset, u8 *p return 0; u8 pxl = pxlen((u32 *) (pbuf + offset)); - if (pxl > MAX_PREFIX_LENGTH) + if (pxl > IP6_MAX_PREFIX_LENGTH) return 0; offset += IPV6_PREFIX_SPACE(pxl); @@ -554,8 +552,8 @@ lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body) /** * lsa_validate - check whether given LSA is valid * @lsa: LSA header - * @lsa_type: one of %LSA_T_xxx - * @ospf2: %true means OSPF version 2, %false means OSPF version 3 + * @lsa_type: internal LSA type (%LSA_T_xxx) + * @ospf2: %true for OSPFv2, %false for OSPFv3 * @body: pointer to LSA body * * Checks internal structure of given LSA body (minimal length, diff --git a/proto/ospf/lsalib.h b/proto/ospf/lsalib.h index 638b3525..c93f0295 100644 --- a/proto/ospf/lsalib.h +++ b/proto/ospf/lsalib.h @@ -41,7 +41,7 @@ void lsa_get_type_domain_(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *do static inline void lsa_get_type_domain(struct ospf_lsa_header *lsa, struct ospf_iface *ifa, u32 *otype, u32 *domain) { lsa_get_type_domain_(lsa->type_raw, ifa, otype, domain); } -static inline u32 lsa_get_etype(struct ospf_lsa_header *h, struct ospf_proto *p UNUSED4 UNUSED6) +static inline u32 lsa_get_etype(struct ospf_lsa_header *h, struct ospf_proto *p) { return ospf_is_v2(p) ? (h->type_raw & LSA_T_V2_MASK) : h->type_raw; } @@ -55,7 +55,7 @@ u16 lsa_verify_checksum(const void *lsa_n, int lsa_len); int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2); void lsa_walk_rt_init(struct ospf_proto *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt); int lsa_walk_rt(struct ospf_lsa_rt_walk *rt); -void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric); +void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, net_addr *net, u8 *pxopts, u32 *metric); void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options); void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt); int lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body); diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index 9fe3c028..b68ba6f4 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -359,7 +359,7 @@ can_do_adj(struct ospf_neighbor *n) } -static inline u32 neigh_get_id(struct ospf_proto *p UNUSED4 UNUSED6, struct ospf_neighbor *n) +static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n) { return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; } static struct ospf_neighbor * @@ -507,13 +507,14 @@ ospf_dr_election(struct ospf_iface *ifa) u32 old_drid = ifa->drid; u32 old_bdrid = ifa->bdrid; + ip_addr none = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6; ifa->drid = ndr ? ndr->rid : 0; - ifa->drip = ndr ? ndr->ip : IPA_NONE; + ifa->drip = ndr ? ndr->ip : none; ifa->dr_iface_id = ndr ? ndr->iface_id : 0; ifa->bdrid = nbdr ? nbdr->rid : 0; - ifa->bdrip = nbdr ? nbdr->ip : IPA_NONE; + ifa->bdrip = nbdr ? nbdr->ip : none; DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index d5d5d354..d074600a 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -102,18 +102,11 @@ static int ospf_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool); static struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool); static void ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs); -static int ospf_reload_routes(struct proto *P); +static void ospf_reload_routes(struct channel *C); static int ospf_rte_better(struct rte *new, struct rte *old); static int ospf_rte_same(struct rte *new, struct rte *old); 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 = 0; -} static void add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac) @@ -122,18 +115,20 @@ add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac) struct area_net_config *anc; struct area_net *an; - fib_init(&oa->net_fib, p->p.pool, sizeof(struct area_net), 0, ospf_area_initfib); - fib_init(&oa->enet_fib, p->p.pool, sizeof(struct area_net), 0, ospf_area_initfib); + fib_init(&oa->net_fib, p->p.pool, ospf_is_v2(p) ? NET_IP4 : NET_IP6, + sizeof(struct area_net), OFFSETOF(struct area_net, fn), 0, NULL); + fib_init(&oa->enet_fib, p->p.pool, ospf_is_v2(p) ? NET_IP4 : NET_IP6, + sizeof(struct area_net), OFFSETOF(struct area_net, fn), 0, NULL); WALK_LIST(anc, ac->net_list) { - an = (struct area_net *) fib_get(&oa->net_fib, &anc->px.addr, anc->px.len); + an = fib_get(&oa->net_fib, &anc->prefix); an->hidden = anc->hidden; } WALK_LIST(anc, ac->enet_list) { - an = (struct area_net *) fib_get(&oa->enet_fib, &anc->px.addr, anc->px.len); + an = fib_get(&oa->enet_fib, &anc->prefix); an->hidden = anc->hidden; an->tag = anc->tag; } @@ -154,7 +149,7 @@ ospf_area_add(struct ospf_proto *p, struct ospf_area_config *ac) oa->areaid = ac->areaid; oa->rt = NULL; oa->po = p; - fib_init(&oa->rtr, p->p.pool, sizeof(ort), 0, ospf_rt_initort); + fib_init(&oa->rtr, p->p.pool, NET_IP4, sizeof(ort), OFFSETOF(ort, fn), 0, NULL); add_area_nets(oa, ac); if (oa->areaid == 0) @@ -243,7 +238,10 @@ ospf_start(struct proto *P) p->nhpool = lp_new(P->pool, 12*sizeof(struct mpnh)); init_list(&(p->iface_list)); init_list(&(p->area_list)); - fib_init(&p->rtf, P->pool, sizeof(ort), 0, ospf_rt_initort); + fib_init(&p->rtf, P->pool, p->ospf2 ? NET_IP4 : NET_IP6, + sizeof(ort), OFFSETOF(ort, fn), 0, NULL); + if (ospf_is_v3(p)) + idm_init(&p->idm, P->pool, 16); p->areano = 0; p->gr = ospf_top_new(p, P->pool); s_init_list(&(p->lsal)); @@ -299,15 +297,16 @@ ospf_dump(struct proto *P) } static struct proto * -ospf_init(struct proto_config *c) +ospf_init(struct proto_config *CF) { - struct ospf_config *oc = (struct ospf_config *) c; - struct proto *P = proto_new(c, sizeof(struct ospf_proto)); + struct ospf_config *cf = (struct ospf_config *) CF; + struct proto *P = proto_new(CF); + + P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); - P->accept_ra_types = RA_OPTIMAL; P->rt_notify = ospf_rt_notify; P->if_notify = ospf_if_notify; - P->ifa_notify = oc->ospf2 ? ospf_ifa_notify2 : ospf_ifa_notify3; + P->ifa_notify = cf->ospf2 ? ospf_ifa_notify2 : ospf_ifa_notify3; P->import_control = ospf_import_control; P->reload_routes = ospf_reload_routes; P->make_tmp_attrs = ospf_make_tmp_attrs; @@ -391,17 +390,16 @@ ospf_schedule_rtcalc(struct ospf_proto *p) p->calcrt = 1; } -static int -ospf_reload_routes(struct proto *P) +static void +ospf_reload_routes(struct channel *C) { - struct ospf_proto *p = (struct ospf_proto *) P; + struct ospf_proto *p = (struct ospf_proto *) C->proto; - if (p->calcrt != 2) - OSPF_TRACE(D_EVENTS, "Scheduling routing table calculation with route reload"); + if (p->calcrt == 2) + return; + OSPF_TRACE(D_EVENTS, "Scheduling routing table calculation with route reload"); p->calcrt = 2; - - return 1; } @@ -506,9 +504,9 @@ ospf_shutdown(struct proto *P) ospf_iface_shutdown(ifa); /* Cleanup locked rta entries */ - FIB_WALK(&p->rtf, nftmp) + FIB_WALK(&p->rtf, ort, nf) { - rta_free(((ort *) nftmp)->old_rta); + rta_free(nf->old_rta); } FIB_WALK_END; @@ -639,17 +637,20 @@ ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac) * nonbroadcast network, cost of interface, etc. */ static int -ospf_reconfigure(struct proto *P, struct proto_config *c) +ospf_reconfigure(struct proto *P, struct proto_config *CF) { struct ospf_proto *p = (struct ospf_proto *) P; struct ospf_config *old = (struct ospf_config *) (P->cf); - struct ospf_config *new = (struct ospf_config *) c; + struct ospf_config *new = (struct ospf_config *) CF; struct ospf_area_config *nac; struct ospf_area *oa, *oax; struct ospf_iface *ifa, *ifx; struct ospf_iface_patt *ip; - if (proto_get_router_id(c) != p->router_id) + if (proto_get_router_id(CF) != p->router_id) + return 0; + + if (p->ospf2 != new->ospf2) return 0; if (p->rfc1583 != new->rfc1583) @@ -658,6 +659,9 @@ ospf_reconfigure(struct proto *P, struct proto_config *c) if (old->abr != new->abr) return 0; + if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF))) + return 0; + p->stub_router = new->stub_router; p->merge_external = new->merge_external; p->asbr = new->asbr; @@ -746,7 +750,6 @@ ospf_sh(struct proto *P) struct ospf_iface *ifa; struct ospf_neighbor *n; int ifano, nno, adjno, firstfib; - struct area_net *anet; if (p->p.proto_state != PS_UP) { @@ -795,29 +798,27 @@ ospf_sh(struct proto *P) cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno); firstfib = 1; - FIB_WALK(&oa->net_fib, nftmp) + FIB_WALK(&oa->net_fib, struct area_net, anet) { - anet = (struct area_net *) nftmp; if(firstfib) { 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, + cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr, anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : ""); } FIB_WALK_END; firstfib = 1; - FIB_WALK(&oa->enet_fib, nftmp) + FIB_WALK(&oa->enet_fib, struct area_net, anet) { - anet = (struct area_net *) nftmp; if(firstfib) { cli_msg(-1014, "\t\tArea external networks:"); firstfib = 0; } - cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen, + cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr, anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : ""); } FIB_WALK_END; @@ -1074,13 +1075,12 @@ show_lsa_network(struct top_hash_entry *he, int ospf2) static inline void show_lsa_sum_net(struct top_hash_entry *he, int ospf2) { - ip_addr ip; - int pxlen; + net_addr net; u8 pxopts; u32 metric; - lsa_parse_sum_net(he, ospf2, &ip, &pxlen, &pxopts, &metric); - cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, metric); + lsa_parse_sum_net(he, ospf2, &net, &pxopts, &metric); + cli_msg(-1016, "\t\txnetwork %N metric %u", &net, metric); } static inline void @@ -1099,7 +1099,7 @@ static inline void show_lsa_external(struct top_hash_entry *he, int ospf2) { struct ospf_lsa_ext_local rt; - char str_via[STD_ADDRESS_P_LENGTH + 8] = ""; + char str_via[IPA_MAX_TEXT_LENGTH + 8] = ""; char str_tag[16] = ""; if (he->lsa_type == LSA_T_EXT) @@ -1113,19 +1113,15 @@ show_lsa_external(struct top_hash_entry *he, int ospf2) if (rt.tag) bsprintf(str_tag, " tag %08x", rt.tag); - cli_msg(-1016, "\t\t%s %I/%d metric%s %u%s%s", + cli_msg(-1016, "\t\t%s %N metric%s %u%s%s", (he->lsa_type == LSA_T_NSSA) ? "nssa-ext" : "external", - rt.ip, rt.pxlen, rt.ebit ? "2" : "", rt.metric, str_via, str_tag); + &rt.net, rt.ebit ? "2" : "", rt.metric, str_via, str_tag); } static inline void show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode) { struct ospf_lsa_prefix *px = he->lsa_body; - ip_addr pxa; - int pxlen; - u8 pxopts; - u16 metric; u32 *buf; int i; @@ -1141,14 +1137,18 @@ show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode) buf = px->rest; for (i = 0; i < px->pxcount; i++) - { - buf = lsa_get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric); + { + net_addr net; + u8 pxopts; + u16 metric; - if (px->ref_type == LSA_T_RT) - cli_msg(-1016, "\t\tstubnet %I/%d metric %u", pxa, pxlen, metric); - else - cli_msg(-1016, "\t\taddress %I/%d", pxa, pxlen); - } + buf = ospf_get_ipv6_prefix(buf, &net, &pxopts, &metric); + + if (px->ref_type == LSA_T_RT) + cli_msg(-1016, "\t\tstubnet %N metric %u", &net, metric); + else + cli_msg(-1016, "\t\taddress %N", &net); + } } void @@ -1468,6 +1468,8 @@ struct protocol proto_ospf = { .template = "ospf%d", .attr_class = EAP_OSPF, .preference = DEF_PREF_OSPF, + .channel_mask = NB_IP, + .proto_size = sizeof(struct ospf_proto), .config_size = sizeof(struct ospf_config), .init = ospf_init, .dump = ospf_dump, diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 81c610d5..e3eae2b5 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -14,11 +14,11 @@ #include "nest/bird.h" #include "lib/checksum.h" -#include "lib/ip.h" +#include "lib/idm.h" #include "lib/lists.h" #include "lib/slists.h" #include "lib/socket.h" -#include "lib/timer.h" +#include "sysdep/unix/timer.h" #include "lib/resource.h" #include "nest/protocol.h" #include "nest/iface.h" @@ -37,14 +37,6 @@ #endif -#ifdef IPV6 -#define OSPF_IS_V2 0 -#else -#define OSPF_IS_V2 1 -#endif - -// FIXME: MAX_PREFIX_LENGTH - #define OSPF_TRACE(flags, msg, args...) \ do { if ((p->p.debug & flags) || OSPF_FORCE_DEBUG) \ log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0) @@ -87,7 +79,6 @@ #define OSPF_VLINK_ID_OFFSET 0x80000000 - struct ospf_config { struct proto_config c; @@ -125,24 +116,24 @@ struct ospf_area_config struct area_net_config { node n; - struct prefix px; + net_addr prefix; u32 tag; u8 hidden; }; struct area_net { - struct fib_node fn; u32 metric; /* With possible LSA_EXT3_EBIT for NSSA area nets */ u32 tag; u8 hidden; u8 active; + struct fib_node fn; }; struct ospf_stubnet_config { node n; - struct prefix px; + net_addr prefix; u32 cost; u8 hidden; u8 summary; @@ -189,7 +180,6 @@ struct ospf_iface_patt u8 ptp_netmask; /* bool + 2 for unspecified */ u8 ttl_security; /* bool + 2 for TX only */ u8 bfd; - u8 bsd_secondary; list *passwords; }; @@ -220,6 +210,7 @@ struct ospf_proto int areano; /* Number of area I belong to */ int padj; /* Number of neighbors in Exchange or Loading state */ struct fib rtf; /* Routing table */ + struct idm idm; /* OSPFv3 LSA ID map */ byte ospf2; /* OSPF v2 or v3 */ byte rfc1583; /* RFC1583 compatibility */ byte stub_router; /* Do not forward transit traffic */ @@ -682,8 +673,8 @@ struct ospf_lsa_ext3 struct ospf_lsa_ext_local { - ip_addr ip, fwaddr; - int pxlen; + net_addr net; + ip_addr fwaddr; u32 metric, ebit, fbit, tag, propagate; u8 pxopts; }; @@ -721,73 +712,80 @@ lsa_net_count(struct ospf_lsa_header *lsa) /* 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 net_from_rid(x) NET_ADDR_IP4(ip4_from_u32(x), IP4_MAX_PREFIX_LENGTH) +#define rid_from_net(x) ip4_to_u32(((net_addr_ip4 *) x)->prefix) #define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4) #define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32) -/* FIXME: these four functions should be significantly redesigned w.r.t. integration, +/* FIXME: these functions should be significantly redesigned w.r.t. integration, also should be named as ospf3_* instead of *_ipv6_* */ +static inline int +ospf_valid_prefix(net_addr *n) +{ + /* In OSPFv2, prefix is stored as netmask; ip4_masklen() returns 255 for invalid one */ + return n->pxlen <= IP6_MAX_PREFIX_LENGTH; +} + static inline u32 * -lsa_get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest) +ospf_get_ipv6_prefix(u32 *buf, net_addr *N, u8 *pxopts, u16 *rest) { - u8 pxl = (*buf >> 24); - *pxopts = (*buf >> 16); - *rest = *buf; - *pxlen = pxl; + net_addr_ip6 *net = (void *) N; + u8 pxlen = (*buf >> 24); + *pxopts = (*buf >> 16) & 0xff; + if (rest) *rest = *buf & 0xffff; buf++; - *addr = IPA_NONE; + *net = NET_ADDR_IP6(IP6_NONE, pxlen); -#ifdef IPV6 - if (pxl > 0) - _I0(*addr) = *buf++; - if (pxl > 32) - _I1(*addr) = *buf++; - if (pxl > 64) - _I2(*addr) = *buf++; - if (pxl > 96) - _I3(*addr) = *buf++; + if (pxlen > 0) + _I0(net->prefix) = *buf++; + if (pxlen > 32) + _I1(net->prefix) = *buf++; + if (pxlen > 64) + _I2(net->prefix) = *buf++; + if (pxlen > 96) + _I3(net->prefix) = *buf++; /* Clean up remaining bits */ - if (pxl < 128) - addr->addr[pxl / 32] &= u32_mkmask(pxl % 32); -#endif + if (pxlen < 128) + net->prefix.addr[pxlen / 32] &= u32_mkmask(pxlen % 32); return buf; } static inline u32 * -lsa_get_ipv6_addr(u32 *buf, ip_addr *addr) +ospf_get_ipv6_addr(u32 *buf, ip_addr *addr) { - *addr = *(ip_addr *) buf; + *addr = ipa_from_ip6(*(ip6_addr *) buf); return buf + 4; } static inline u32 * -put_ipv6_prefix(u32 *buf, ip_addr addr UNUSED4, u8 pxlen UNUSED4, u8 pxopts UNUSED4, u16 lh UNUSED4) +ospf_put_ipv6_prefix(u32 *buf, net_addr *N, u8 pxopts, u16 rest) { -#ifdef IPV6 - *buf++ = ((pxlen << 24) | (pxopts << 16) | lh); + net_addr_ip6 *net = (void *) N; + u32 pxlen = net->pxlen; + + *buf++ = ((pxlen << 24) | (pxopts << 16) | rest); if (pxlen > 0) - *buf++ = _I0(addr); + *buf++ = _I0(net->prefix); if (pxlen > 32) - *buf++ = _I1(addr); + *buf++ = _I1(net->prefix); if (pxlen > 64) - *buf++ = _I2(addr); + *buf++ = _I2(net->prefix); if (pxlen > 96) - *buf++ = _I3(addr); -#endif + *buf++ = _I3(net->prefix); + return buf; } static inline u32 * -put_ipv6_addr(u32 *buf, ip_addr addr) +ospf_put_ipv6_addr(u32 *buf, ip_addr addr) { - *(ip_addr *) buf = addr; + *(ip6_addr *) buf = ipa_to_ip6(addr); return buf + 4; } @@ -831,17 +829,13 @@ static inline void ospf_notify_net_lsa(struct ospf_iface *ifa) static inline void ospf_notify_link_lsa(struct ospf_iface *ifa) { ifa->update_link_lsa = 1; } - -#define ospf_is_v2(X) OSPF_IS_V2 -#define ospf_is_v3(X) (!OSPF_IS_V2) -/* static inline int ospf_is_v2(struct ospf_proto *p) { return p->ospf2; } static inline int ospf_is_v3(struct ospf_proto *p) { return ! p->ospf2; } -*/ -static inline int ospf_get_version(struct ospf_proto *p UNUSED4 UNUSED6) + +static inline int ospf_get_version(struct ospf_proto *p) { return ospf_is_v2(p) ? 2 : 3; } struct ospf_area *ospf_find_area(struct ospf_proto *p, u32 aid); @@ -925,7 +919,7 @@ static inline void ospf_send_to_des(struct ospf_iface *ifa) #define SKIP(DSC) do { err_dsc = DSC; goto skip; } while(0) #endif -static inline uint ospf_pkt_hdrlen(struct ospf_proto *p UNUSED4 UNUSED6) +static inline uint ospf_pkt_hdrlen(struct ospf_proto *p) { return ospf_is_v2(p) ? (sizeof(struct ospf_packet) + sizeof(union ospf_auth)) : sizeof(struct ospf_packet); } static inline void * ospf_tx_buffer(struct ospf_iface *ifa) diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index 6b6a97a4..b84780d3 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -203,7 +203,7 @@ drop: /** * ospf_rx_hook * @sk: socket we received the packet. - * @len: size of the packet + * @len: length of the packet * * This is the entry point for messages from neighbors. Many checks (like * authentication, checksums, size) are done before the packet is passed to @@ -231,7 +231,7 @@ ospf_rx_hook(sock *sk, uint len) return 1; int src_local, dst_local, dst_mcast; - src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen); + src_local = ipa_in_netX(sk->faddr, &ifa->addr->prefix); dst_local = ipa_equal(sk->laddr, ifa->addr->ip); dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers); @@ -491,8 +491,8 @@ ospf_send_to_agt(struct ospf_iface *ifa, u8 state) void ospf_send_to_bdr(struct ospf_iface *ifa) { - if (ipa_nonzero(ifa->drip)) + if (ipa_nonzero2(ifa->drip)) ospf_send_to(ifa, ifa->drip); - if (ipa_nonzero(ifa->bdrip)) + if (ipa_nonzero2(ifa->bdrip)) ospf_send_to(ifa, ifa->bdrip); } diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 19f2d074..c5c54783 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -21,15 +21,6 @@ static inline void reset_ri(ort *ort) bzero(&ort->n, sizeof(orta)); } -void -ospf_rt_initort(struct fib_node *fn) -{ - ort *ri = (ort *) fn; - reset_ri(ri); - ri->old_rta = NULL; - ri->fn.flags = 0; -} - static inline int nh_is_vlink(struct mpnh *nhs) { @@ -334,9 +325,9 @@ ort_merge_ext(struct ospf_proto *p, ort *o, const orta *new) static inline void -ri_install_net(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new) +ri_install_net(struct ospf_proto *p, net_addr *net, const orta *new) { - ort *old = (ort *) fib_get(&p->rtf, &prefix, pxlen); + ort *old = fib_get(&p->rtf, net); int cmp = orta_compare(p, new, &old->n); if (cmp > 0) @@ -348,8 +339,8 @@ ri_install_net(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new) static inline void ri_install_rt(struct ospf_area *oa, u32 rid, const orta *new) { - ip_addr addr = ipa_from_rid(rid); - ort *old = (ort *) fib_get(&oa->rtr, &addr, MAX_PREFIX_LENGTH); + net_addr_ip4 nrid = net_from_rid(rid); + ort *old = fib_get(&oa->rtr, (net_addr *) &nrid); int cmp = orta_compare(oa->po, new, &old->n); if (cmp > 0) @@ -359,17 +350,19 @@ ri_install_rt(struct ospf_area *oa, u32 rid, const orta *new) } static inline void -ri_install_asbr(struct ospf_proto *p, ip_addr *addr, const orta *new) +ri_install_asbr(struct ospf_proto *p, u32 rid, const orta *new) { - ort *old = (ort *) fib_get(&p->backbone->rtr, addr, MAX_PREFIX_LENGTH); + net_addr_ip4 nrid = net_from_rid(rid); + ort *old = fib_get(&p->backbone->rtr, (net_addr *) &nrid); + if (orta_compare_asbr(p, new, &old->n) > 0) ort_replace(old, new); } static inline void -ri_install_ext(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new) +ri_install_ext(struct ospf_proto *p, net_addr *net, const orta *new) { - ort *old = (ort *) fib_get(&p->rtf, &prefix, pxlen); + ort *old = fib_get(&p->rtf, net); int cmp = orta_compare_ext(p, new, &old->n); if (cmp > 0) @@ -404,7 +397,7 @@ px_pos_to_ifa(struct ospf_area *oa, int pos) static void -add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_hash_entry *en, int pos) +add_network(struct ospf_area *oa, net_addr *net, int metric, struct top_hash_entry *en, int pos) { struct ospf_proto *p = oa->po; @@ -419,7 +412,7 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_ .nhs = en->nhs }; - if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) + if (!ospf_valid_prefix(net)) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); @@ -441,7 +434,7 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_ nf.nhs = ifa ? new_nexthop(p, IPA_NONE, ifa->iface, ifa->ecmp_weight) : NULL; } - ri_install_net(p, px, pxlen, &nf); + ri_install_net(p, net, &nf); } @@ -452,8 +445,7 @@ spfa_process_rt(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_entr struct ospf_lsa_rt *rt = act->lsa_body; struct ospf_lsa_rt_walk rtl; struct top_hash_entry *tmp; - ip_addr prefix; - int pxlen, i; + int i; if (rt->options & OPT_RT_V) oa->trcap = 1; @@ -503,9 +495,10 @@ spfa_process_rt(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_entr * the same result by handing them here because add_network() * will keep the best (not the first) found route. */ - prefix = ipa_from_u32(rtl.id & rtl.data); - pxlen = u32_masklen(rtl.data); - add_network(oa, prefix, pxlen, act->dist + rtl.metric, act, i); + net_addr_ip4 net = + NET_ADDR_IP4(ip4_from_u32(rtl.id & rtl.data), u32_masklen(rtl.data)); + + add_network(oa, (net_addr *) &net, act->dist + rtl.metric, act, i); break; case LSART_NET: @@ -527,14 +520,14 @@ spfa_process_net(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_ent { struct ospf_lsa_net *ln = act->lsa_body; struct top_hash_entry *tmp; - ip_addr prefix; - int pxlen, i, cnt; + int i, cnt; if (ospf_is_v2(p)) { - prefix = ipa_from_u32(act->lsa.id & ln->optx); - pxlen = u32_masklen(ln->optx); - add_network(oa, prefix, pxlen, act->dist, act, -1); + net_addr_ip4 net = + NET_ADDR_IP4(ip4_from_u32(act->lsa.id & ln->optx), u32_masklen(ln->optx)); + + add_network(oa, (net_addr *) &net, act->dist, act, -1); } cnt = lsa_net_count(&act->lsa); @@ -550,10 +543,6 @@ spfa_process_prefixes(struct ospf_proto *p, struct ospf_area *oa) { struct top_hash_entry *en, *src; struct ospf_lsa_prefix *px; - ip_addr pxa; - int pxlen; - u8 pxopts; - u16 metric; u32 *buf; int i; @@ -588,18 +577,22 @@ spfa_process_prefixes(struct ospf_proto *p, struct ospf_area *oa) buf = px->rest; for (i = 0; i < px->pxcount; i++) - { - buf = lsa_get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric); + { + net_addr_ip6 net; + u8 pxopts; + u16 metric; - if (pxopts & OPT_PX_NU) - continue; + buf = ospf_get_ipv6_prefix(buf, (net_addr *) &net, &pxopts, &metric); - /* Store the first global address to use it later as a vlink endpoint */ - if ((pxopts & OPT_PX_LA) && ipa_zero(src->lb)) - src->lb = pxa; + if (pxopts & OPT_PX_NU) + continue; - add_network(oa, pxa, pxlen, src->dist + metric, src, i); - } + /* Store the first global address to use it later as a vlink endpoint */ + if ((pxopts & OPT_PX_LA) && ipa_zero(src->lb)) + src->lb = ipa_from_ip6(net.prefix); + + add_network(oa, (net_addr *) &net, src->dist + metric, src, i); + } } } @@ -742,13 +735,12 @@ ospf_rt_sum(struct ospf_area *oa) { struct ospf_proto *p = oa->po; struct top_hash_entry *en; - ip_addr ip, abrip; + net_addr net; u32 dst_rid, metric, options; ort *abr; - int pxlen = -1, type = -1; + int type; u8 pxopts; - OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid); WALK_SLIST(en, p->lsal) @@ -771,18 +763,18 @@ ospf_rt_sum(struct ospf_area *oa) if (en->lsa_type == LSA_T_SUM_NET) { - lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric); + lsa_parse_sum_net(en, ospf_is_v2(p), &net, &pxopts, &metric); - if (pxopts & OPT_PX_NU) - continue; - - if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) + if (!ospf_valid_prefix(&net)) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); continue; } + if (pxopts & OPT_PX_NU) + continue; + options = 0; type = ORT_NET; } @@ -803,8 +795,8 @@ ospf_rt_sum(struct ospf_area *oa) continue; /* 16.2. (4) */ - abrip = ipa_from_rid(en->lsa.rt); - abr = (ort *) fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH); + net_addr_ip4 nrid = net_from_rid(en->lsa.rt); + abr = fib_find(&oa->rtr, (net_addr *) &nrid); if (!abr || !abr->n.type) continue; @@ -828,7 +820,7 @@ ospf_rt_sum(struct ospf_area *oa) }; if (type == ORT_NET) - ri_install_net(p, ip, pxlen, &nf); + ri_install_net(p, &net, &nf); else ri_install_rt(oa, dst_rid, &nf); } @@ -842,11 +834,7 @@ ospf_rt_sum_tr(struct ospf_area *oa) struct ospf_area *bb = p->backbone; struct top_hash_entry *en; ort *re, *abr; - ip_addr ip, abrip; - u32 dst_rid, metric, options; - int pxlen; - u8 pxopts; - + u32 metric; if (!bb) return; @@ -869,26 +857,31 @@ ospf_rt_sum_tr(struct ospf_area *oa) if (en->lsa_type == LSA_T_SUM_NET) { - lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric); + net_addr net; + u8 pxopts; - if (pxopts & OPT_PX_NU) - continue; + lsa_parse_sum_net(en, ospf_is_v2(p), &net, &pxopts, &metric); - if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) + if (!ospf_valid_prefix(&net)) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); continue; } - re = fib_find(&p->rtf, &ip, pxlen); + if (pxopts & OPT_PX_NU) + continue; + + re = fib_find(&p->rtf, &net); } else // en->lsa_type == LSA_T_SUM_RT { + u32 dst_rid, options; + lsa_parse_sum_rt(en, ospf_is_v2(p), &dst_rid, &metric, &options); - ip = ipa_from_rid(dst_rid); - re = fib_find(&bb->rtr, &ip, MAX_PREFIX_LENGTH); + net_addr_ip4 nrid = net_from_rid(dst_rid); + re = fib_find(&bb->rtr, (net_addr *) &nrid); } /* 16.3 (1b) */ @@ -906,8 +899,8 @@ ospf_rt_sum_tr(struct ospf_area *oa) continue; /* 16.3. (4) */ - abrip = ipa_from_rid(en->lsa.rt); - abr = fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH); + net_addr_ip4 nrid = net_from_rid(en->lsa.rt); + abr = fib_find(&oa->rtr, (net_addr *) &nrid); if (!abr || !abr->n.type) continue; @@ -998,7 +991,7 @@ decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest) return 1; struct area_net *anet = (struct area_net *) - fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen); + fib_route(&nf->n.oa->net_fib, nf->fn.addr); /* Condensed area network found */ if (anet) @@ -1017,13 +1010,13 @@ check_sum_net_lsa(struct ospf_proto *p, ort *nf) if (nf->area_net) { /* It is a default route for stub areas, handled entirely in ospf_rt_abr() */ - if (nf->fn.pxlen == 0) + if (nf->fn.addr->pxlen == 0) return; /* Find that area network */ WALK_LIST(anet_oa, p->area_list) { - anet = (struct area_net *) fib_find(&anet_oa->net_fib, &nf->fn.prefix, nf->fn.pxlen); + anet = fib_find(&anet_oa->net_fib, nf->fn.addr); if (anet) break; } @@ -1042,14 +1035,16 @@ check_sum_net_lsa(struct ospf_proto *p, ort *nf) static inline void check_sum_rt_lsa(struct ospf_proto *p, ort *nf) { + u32 rid = rid_from_net(nf->fn.addr); + struct ospf_area *oa; WALK_LIST(oa, p->area_list) if (decide_sum_lsa(oa, nf, ORT_ROUTER)) - ospf_originate_sum_rt_lsa(p, oa, nf, nf->n.metric1, nf->n.options); + ospf_originate_sum_rt_lsa(p, oa, rid, nf->n.metric1, nf->n.options); } static inline int -decide_nssa_lsa(struct ospf_proto *p UNUSED4 UNUSED6, ort *nf, struct ospf_lsa_ext_local *rt) +decide_nssa_lsa(struct ospf_proto *p, ort *nf, struct ospf_lsa_ext_local *rt) { struct ospf_area *oa = nf->n.oa; struct top_hash_entry *en = nf->n.en; @@ -1058,7 +1053,7 @@ decide_nssa_lsa(struct ospf_proto *p UNUSED4 UNUSED6, ort *nf, struct ospf_lsa_e return 0; /* Condensed area network found */ - if (fib_route(&oa->enet_fib, nf->fn.prefix, nf->fn.pxlen)) + if (fib_route(&oa->enet_fib, nf->fn.addr)) return 0; if (!en || (en->lsa_type != LSA_T_NSSA)) @@ -1093,7 +1088,7 @@ check_nssa_lsa(struct ospf_proto *p, ort *nf) /* Find that area network */ WALK_LIST(oa, p->area_list) { - anet = (struct area_net *) fib_find(&oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen); + anet = fib_find(&oa->enet_fib, nf->fn.addr); if (anet) break; } @@ -1163,24 +1158,20 @@ static void ospf_rt_abr1(struct ospf_proto *p) { struct area_net *anet; - ort *nf, *default_nf; + ort *default_nf; + net_addr default_net; /* RFC 2328 G.3 - incomplete resolution of virtual next hops - routers */ - FIB_WALK(&p->backbone->rtr, nftmp) + FIB_WALK(&p->backbone->rtr, ort, nf) { - nf = (ort *) nftmp; - if (nf->n.type && unresolved_vlink(nf)) reset_ri(nf); } FIB_WALK_END; - FIB_WALK(&p->rtf, nftmp) + FIB_WALK(&p->rtf, ort, nf) { - nf = (ort *) nftmp; - - /* RFC 2328 G.3 - incomplete resolution of virtual next hops - networks */ if (nf->n.type && unresolved_vlink(nf)) reset_ri(nf); @@ -1189,7 +1180,7 @@ ospf_rt_abr1(struct ospf_proto *p) /* Compute condensed area networks */ if (nf->n.type == RTS_OSPF) { - anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen); + anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, nf->fn.addr); if (anet) { if (!anet->active) @@ -1197,7 +1188,7 @@ ospf_rt_abr1(struct ospf_proto *p) anet->active = 1; /* Get a RT entry and mark it to know that it is an area network */ - ort *nfi = (ort *) fib_get(&p->rtf, &anet->fn.prefix, anet->fn.pxlen); + ort *nfi = fib_get(&p->rtf, anet->fn.addr); nfi->area_net = 1; /* 16.2. (3) */ @@ -1212,8 +1203,13 @@ ospf_rt_abr1(struct ospf_proto *p) } FIB_WALK_END; - ip_addr addr = IPA_NONE; - default_nf = (ort *) fib_get(&p->rtf, &addr, 0); + + if (ospf_is_v2(p)) + net_fill_ip4(&default_net, IP4_NONE, 0); + else + net_fill_ip6(&default_net, IP6_NONE, 0); + + default_nf = fib_get(&p->rtf, &default_net); default_nf->area_net = 1; struct ospf_area *oa; @@ -1240,11 +1236,10 @@ ospf_rt_abr1(struct ospf_proto *p) /* RFC 2328 16.4. (3) - precompute preferred ASBR entries */ if (oa_is_ext(oa)) { - FIB_WALK(&oa->rtr, nftmp) + FIB_WALK(&oa->rtr, ort, nf) { - nf = (ort *) nftmp; if (nf->n.options & ORTA_ASBR) - ri_install_asbr(p, &nf->fn.prefix, &nf->n); + ri_install_asbr(p, rid_from_net(nf->fn.addr), &nf->n); } FIB_WALK_END; } @@ -1252,9 +1247,9 @@ ospf_rt_abr1(struct ospf_proto *p) /* Originate or flush ASBR summary LSAs */ - FIB_WALK(&p->backbone->rtr, nftmp) + FIB_WALK(&p->backbone->rtr, ort, nf) { - check_sum_rt_lsa(p, (ort *) nftmp); + check_sum_rt_lsa(p, nf); } FIB_WALK_END; @@ -1281,8 +1276,6 @@ ospf_rt_abr2(struct ospf_proto *p) { struct ospf_area *oa; struct top_hash_entry *en; - ort *nf, *nf2; - /* RFC 3103 3.1 - type-7 translator election */ struct ospf_area *bb = p->backbone; @@ -1294,13 +1287,12 @@ ospf_rt_abr2(struct ospf_proto *p) if (oa->ac->translator) goto decided; - FIB_WALK(&oa->rtr, nftmp) + FIB_WALK(&oa->rtr, ort, nf) { - nf = (ort *) nftmp; if (!nf->n.type || !(nf->n.options & ORTA_ABR)) continue; - nf2 = fib_find(&bb->rtr, &nf->fn.prefix, MAX_PREFIX_LENGTH); + ort *nf2 = fib_find(&bb->rtr, nf->fn.addr); if (!nf2 || !nf2->n.type || !(nf2->n.options & ORTA_ABR)) continue; @@ -1340,13 +1332,11 @@ ospf_rt_abr2(struct ospf_proto *p) /* Compute condensed external networks */ - FIB_WALK(&p->rtf, nftmp) + FIB_WALK(&p->rtf, ort, nf) { - nf = (ort *) nftmp; if (rt_is_nssa(nf) && (nf->n.options & ORTA_PROP)) { - struct area_net *anet = (struct area_net *) - fib_route(&nf->n.oa->enet_fib, nf->fn.prefix, nf->fn.pxlen); + struct area_net *anet = fib_route(&nf->n.oa->enet_fib, nf->fn.addr); if (anet) { @@ -1355,7 +1345,7 @@ ospf_rt_abr2(struct ospf_proto *p) anet->active = 1; /* Get a RT entry and mark it to know that it is an area network */ - nf2 = (ort *) fib_get(&p->rtf, &anet->fn.prefix, anet->fn.pxlen); + ort *nf2 = fib_get(&p->rtf, anet->fn.addr); nf2->area_net = 1; } @@ -1370,10 +1360,8 @@ ospf_rt_abr2(struct ospf_proto *p) FIB_WALK_END; - FIB_WALK(&p->rtf, nftmp) + FIB_WALK(&p->rtf, ort, nf) { - nf = (ort *) nftmp; - check_sum_net_lsa(p, nf); check_nssa_lsa(p, nf); } @@ -1383,22 +1371,57 @@ ospf_rt_abr2(struct ospf_proto *p) /* Like fib_route(), but ignores dummy rt entries */ static void * -ospf_fib_route(struct fib *f, ip_addr a, int len) +ospf_fib_route_ip4(struct fib *f, ip4_addr a, int len) +{ + net_addr_ip4 net = NET_ADDR_IP4(a, len); + ort *nf; + +loop: + nf = fib_find(f, (net_addr *) &net); + if (nf && nf->n.type) + return nf; + + if (net.pxlen > 0) + { + net.pxlen--; + ip4_clrbit(&net.prefix, net.pxlen); + goto loop; + } + + return NULL; +} + +static void * +ospf_fib_route_ip6(struct fib *f, ip6_addr a, int len) { - ip_addr a0; + net_addr_ip6 net = NET_ADDR_IP6(a, len); ort *nf; - while (len >= 0) +loop: + nf = fib_find(f, (net_addr *) &net); + if (nf && nf->n.type) + return nf; + + if (net.pxlen > 0) { - a0 = ipa_and(a, ipa_mkmask(len)); - nf = fib_find(f, &a0, len); - if (nf && nf->n.type) - return nf; - len--; + net.pxlen--; + ip6_clrbit(&net.prefix, net.pxlen); + goto loop; } + return NULL; } +static void * +ospf_fib_route(struct fib *f, ip_addr a) +{ + if (f->addr_type == NET_IP4) + return ospf_fib_route_ip4(f, ipa_to_ip4(a), IP4_MAX_PREFIX_LENGTH); + else + return ospf_fib_route_ip6(f, ipa_to_ip6(a), IP6_MAX_PREFIX_LENGTH); +} + + /* RFC 2328 16.4. calculating external routes */ static void ospf_ext_spf(struct ospf_proto *p) @@ -1407,7 +1430,6 @@ ospf_ext_spf(struct ospf_proto *p) struct ospf_lsa_ext_local rt; ort *nf1, *nf2; orta nfa = {}; - ip_addr rtid; u32 br_metric; struct ospf_area *atmp; @@ -1431,19 +1453,18 @@ ospf_ext_spf(struct ospf_proto *p) lsa_parse_ext(en, ospf_is_v2(p), &rt); - if (rt.metric == LSINFINITY) - continue; - - if (rt.pxopts & OPT_PX_NU) - continue; - - if (rt.pxlen < 0 || rt.pxlen > MAX_PREFIX_LENGTH) + if (!ospf_valid_prefix(&rt.net)) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); continue; } + if (rt.metric == LSINFINITY) + continue; + + if (rt.pxopts & OPT_PX_NU) + continue; /* 16.4. (3) */ /* If there are more areas, we already precomputed preferred ASBR @@ -1457,8 +1478,8 @@ ospf_ext_spf(struct ospf_proto *p) if (!atmp) continue; /* Should not happen */ - rtid = ipa_from_rid(en->lsa.rt); - nf1 = fib_find(&atmp->rtr, &rtid, MAX_PREFIX_LENGTH); + net_addr_ip4 nrid = net_from_rid(en->lsa.rt); + nf1 = fib_find(&atmp->rtr, (net_addr *) &nrid); if (!nf1 || !nf1->n.type) continue; /* No AS boundary router found */ @@ -1468,7 +1489,7 @@ ospf_ext_spf(struct ospf_proto *p) /* 16.4. (3) NSSA - special rule for default routes */ /* ABR should use default only if P-bit is set and summaries are active */ - if ((en->lsa_type == LSA_T_NSSA) && ipa_zero(rt.ip) && (rt.pxlen == 0) && + if ((en->lsa_type == LSA_T_NSSA) && (rt.net.pxlen == 0) && (p->areano > 1) && !(rt.propagate && atmp->ac->summary)) continue; @@ -1480,7 +1501,7 @@ ospf_ext_spf(struct ospf_proto *p) } else { - nf2 = ospf_fib_route(&p->rtf, rt.fwaddr, MAX_PREFIX_LENGTH); + nf2 = ospf_fib_route(&p->rtf, rt.fwaddr); if (!nf2) continue; @@ -1542,7 +1563,7 @@ ospf_ext_spf(struct ospf_proto *p) nfa.oa = atmp; /* undefined in RFC 2328 */ nfa.en = en; /* store LSA for later (NSSA processing) */ - ri_install_ext(p, rt.ip, rt.pxlen, &nfa); + ri_install_ext(p, &rt.net, &nfa); } } @@ -1552,13 +1573,10 @@ ospf_rt_reset(struct ospf_proto *p) { struct ospf_area *oa; struct top_hash_entry *en; - struct area_net *anet; - ort *ri; /* Reset old routing table */ - FIB_WALK(&p->rtf, nftmp) + FIB_WALK(&p->rtf, ort, ri) { - ri = (ort *) nftmp; ri->area_net = 0; reset_ri(ri); } @@ -1579,9 +1597,8 @@ ospf_rt_reset(struct ospf_proto *p) WALK_LIST(oa, p->area_list) { /* Reset ASBR routing tables */ - FIB_WALK(&oa->rtr, nftmp) + FIB_WALK(&oa->rtr, ort, ri) { - ri = (ort *) nftmp; reset_ri(ri); } FIB_WALK_END; @@ -1589,17 +1606,15 @@ ospf_rt_reset(struct ospf_proto *p) /* Reset condensed area networks */ if (p->areano > 1) { - FIB_WALK(&oa->net_fib, nftmp) + FIB_WALK(&oa->net_fib, struct area_net, anet) { - anet = (struct area_net *) nftmp; anet->active = 0; anet->metric = 0; } FIB_WALK_END; - FIB_WALK(&oa->enet_fib, nftmp) + FIB_WALK(&oa->enet_fib, struct area_net, anet) { - anet = (struct area_net *) nftmp; anet->active = 0; anet->metric = 0; } @@ -1901,7 +1916,6 @@ rt_sync(struct ospf_proto *p) struct top_hash_entry *en; struct fib_iterator fit; struct fib *fib = &p->rtf; - ort *nf; struct ospf_area *oa; /* This is used for forced reload of routes */ @@ -1912,10 +1926,8 @@ rt_sync(struct ospf_proto *p) DBG("Now syncing my rt table with nest's\n"); FIB_ITERATE_INIT(&fit, fib); again1: - FIB_ITERATE_START(fib, &fit, nftmp) + FIB_ITERATE_START(fib, &fit, ort, nf) { - nf = (ort *) nftmp; - /* Sanity check of next-hop addresses, failure should not happen */ if (nf->n.type) { @@ -1961,7 +1973,6 @@ again1: if (reload || ort_changed(nf, &a0)) { - net *ne = net_get(p->p.table, nf->fn.prefix, nf->fn.pxlen); rta *a = rta_lookup(&a0); rte *e = rte_get_temp(a); @@ -1972,12 +1983,10 @@ again1: e->u.ospf.tag = nf->old_tag = nf->n.tag; e->u.ospf.router_id = nf->old_rid = nf->n.rid; e->pflags = 0; - e->net = ne; - e->pref = p->p.preference; - DBG("Mod rte type %d - %I/%d via %I on iface %s, met %d\n", - a0.source, nf->fn.prefix, nf->fn.pxlen, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1); - rte_update(&p->p, ne, e); + DBG("Mod rte type %d - %N via %I on iface %s, met %d\n", + a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1); + rte_update(&p->p, nf->fn.addr, e); } } else if (nf->old_rta) @@ -1986,19 +1995,21 @@ again1: rta_free(nf->old_rta); nf->old_rta = NULL; - net *ne = net_get(p->p.table, nf->fn.prefix, nf->fn.pxlen); - rte_update(&p->p, ne, NULL); + rte_update(&p->p, nf->fn.addr, NULL); } /* Remove unused rt entry, some special entries are persistent */ if (!nf->n.type && !nf->external_rte && !nf->area_net) { - FIB_ITERATE_PUT(&fit, nftmp); - fib_delete(fib, nftmp); + if (nf->lsa_id) + idm_free(&p->idm, nf->lsa_id); + + FIB_ITERATE_PUT(&fit); + fib_delete(fib, nf); goto again1; } } - FIB_ITERATE_END(nftmp); + FIB_ITERATE_END; WALK_LIST(oa, p->area_list) @@ -2006,18 +2017,16 @@ again1: /* Cleanup ASBR hash tables */ FIB_ITERATE_INIT(&fit, &oa->rtr); again2: - FIB_ITERATE_START(&oa->rtr, &fit, nftmp) + FIB_ITERATE_START(&oa->rtr, &fit, ort, nf) { - nf = (ort *) nftmp; - if (!nf->n.type) { - FIB_ITERATE_PUT(&fit, nftmp); - fib_delete(&oa->rtr, nftmp); + FIB_ITERATE_PUT(&fit); + fib_delete(&oa->rtr, nf); goto again2; } } - FIB_ITERATE_END(nftmp); + FIB_ITERATE_END; } /* Cleanup stale LSAs */ diff --git a/proto/ospf/rt.h b/proto/ospf/rt.h index 30332f3b..959d12e9 100644 --- a/proto/ospf/rt.h +++ b/proto/ospf/rt.h @@ -78,12 +78,14 @@ typedef struct ort * route was not in the last update, in that case other old_* values are not * valid. */ - struct fib_node fn; orta n; u32 old_metric1, old_metric2, old_tag, old_rid; rta *old_rta; + u32 lsa_id; u8 external_rte; u8 area_net; + + struct fib_node fn; } ort; diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 341eff87..aaaf2e8e 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -283,8 +283,8 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa) if (en->nf != lsa->nf) { - log(L_ERR "%s: LSA ID collision for %I/%d", - p->p.name, lsa->nf->fn.prefix, lsa->nf->fn.pxlen); + log(L_ERR "%s: LSA ID collision for %N", + p->p.name, lsa->nf->fn.addr); en = NULL; goto drop; @@ -514,14 +514,14 @@ ospf_update_lsadb(struct ospf_proto *p) } -static inline u32 -ort_to_lsaid(struct ospf_proto *p UNUSED4 UNUSED6, ort *nf) +static u32 +ort_to_lsaid(struct ospf_proto *p, ort *nf) { /* * In OSPFv2, We have to map IP prefixes to u32 in such manner that resulting * u32 interpreted as IP address is a member of given prefix. Therefore, /32 - * prefix have to be mapped on itself. All received prefixes have to be - * mapped on different u32s. + * prefix has to be mapped on itself. All received prefixes have to be mapped + * on different u32s. * * We have an assumption that if there is nontrivial (non-/32) network prefix, * then there is not /32 prefix for the first and the last IP address of the @@ -542,17 +542,21 @@ ort_to_lsaid(struct ospf_proto *p UNUSED4 UNUSED6, ort *nf) * network appeared, we choose a different way. * * In OSPFv3, it is simpler. There is not a requirement for membership of the - * result in the input network, so we just use a hash-based unique ID of a - * routing table entry for a route that originated given LSA. For ext-LSA, it - * is an imported route in the nest's routing table (p->table). For summary-LSA, - * it is a 'source' route in the protocol internal routing table (p->rtf). + * result in the input network, so we just allocate a unique ID from ID map + * and store it in nf->lsa_id for further reference. */ if (ospf_is_v3(p)) - return nf->fn.uid; + { + if (!nf->lsa_id) + nf->lsa_id = idm_alloc(&p->idm); - u32 id = ipa_to_u32(nf->fn.prefix); - int pxlen = nf->fn.pxlen; + return nf->lsa_id; + } + + net_addr_ip4 *net = (void *) nf->fn.addr; + u32 id = ip4_to_u32(net->prefix); + int pxlen = net->pxlen; if ((pxlen == 0) || (pxlen == 32)) return id; @@ -628,12 +632,12 @@ configured_stubnet(struct ospf_area *oa, struct ifa *a) { if (sn->summary) { - if (ipa_in_net(a->prefix, sn->px.addr, sn->px.len) && (a->pxlen >= sn->px.len)) + if (net_in_netX(&a->prefix, &sn->prefix)) return 1; } else { - if (ipa_equal(a->prefix, sn->px.addr) && (a->pxlen == sn->px.len)) + if (net_equal(&a->prefix, &sn->prefix)) return 1; } } @@ -781,7 +785,8 @@ prepare_rt2_lsa_body(struct ospf_proto *p, struct ospf_area *oa) (ifa->type == OSPF_IT_PTMP)) add_rt2_lsa_link(p, LSART_STUB, ipa_to_u32(ifa->addr->ip), 0xffffffff, 0); else - add_rt2_lsa_link(p, LSART_STUB, ipa_to_u32(ifa->addr->prefix), u32_mkmask(ifa->addr->pxlen), ifa->cost); + add_rt2_lsa_link(p, LSART_STUB, ip4_to_u32(net4_prefix(&ifa->addr->prefix)), + u32_mkmask(net4_pxlen(&ifa->addr->prefix)), ifa->cost); i++; ifa->rt_pos_end = i; @@ -790,7 +795,8 @@ prepare_rt2_lsa_body(struct ospf_proto *p, struct ospf_area *oa) struct ospf_stubnet_config *sn; WALK_LIST(sn, oa->ac->stubnet_list) if (!sn->hidden) - add_rt2_lsa_link(p, LSART_STUB, ipa_to_u32(sn->px.addr), u32_mkmask(sn->px.len), sn->cost), i++; + add_rt2_lsa_link(p, LSART_STUB, ip4_to_u32(net4_prefix(&sn->prefix)), + u32_mkmask(net4_pxlen(&sn->prefix)), sn->cost), i++; struct ospf_lsa_rt *rt = p->lsab; /* Store number of links in lower half of options */ @@ -907,7 +913,7 @@ prepare_net2_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa) ASSERT(p->lsab_used == 0); net = lsab_alloc(p, sizeof(struct ospf_lsa_net) + 4 * nodes); - net->optx = u32_mkmask(ifa->addr->pxlen); + net->optx = u32_mkmask(ifa->addr->prefix.pxlen); net->routers[0] = p->router_id; WALK_LIST(n, ifa->neigh_list) @@ -999,9 +1005,10 @@ prepare_sum3_net_lsa_body(struct ospf_proto *p, ort *nf, u32 metric) { struct ospf_lsa_sum3_net *sum; - sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) + IPV6_PREFIX_SPACE(nf->fn.pxlen)); + sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) + + IPV6_PREFIX_SPACE(nf->fn.addr->pxlen)); sum->metric = metric; - put_ipv6_prefix(sum->prefix, nf->fn.prefix, nf->fn.pxlen, 0, 0); + ospf_put_ipv6_prefix(sum->prefix, nf->fn.addr, 0, 0); } static inline void @@ -1028,7 +1035,7 @@ ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, }; if (ospf_is_v2(p)) - prepare_sum2_lsa_body(p, nf->fn.pxlen, metric); + prepare_sum2_lsa_body(p, nf->fn.addr->pxlen, metric); else prepare_sum3_net_lsa_body(p, nf, metric); @@ -1036,20 +1043,20 @@ ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, } void -ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric, u32 options) +ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options) { struct ospf_new_lsa lsa = { .type = LSA_T_SUM_RT, .mode = LSA_M_RTCALC, .dom = oa->areaid, - .id = ipa_to_rid(nf->fn.prefix), /* Router ID of ASBR, irrelevant for OSPFv3 */ + .id = drid, /* Router ID of ASBR, irrelevant for OSPFv3 */ .opts = oa->options }; if (ospf_is_v2(p)) prepare_sum2_lsa_body(p, 0, metric); else - prepare_sum3_rt_lsa_body(p, lsa.id, metric, options & LSA_OPTIONS_MASK); + prepare_sum3_rt_lsa_body(p, drid, metric, options & LSA_OPTIONS_MASK); ospf_originate_lsa(p, &lsa); } @@ -1082,7 +1089,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf, { struct ospf_lsa_ext3 *ext; int bsize = sizeof(struct ospf_lsa_ext3) - + IPV6_PREFIX_SPACE(nf->fn.pxlen) + + IPV6_PREFIX_SPACE(nf->fn.addr->pxlen) + (ipa_nonzero(fwaddr) ? 16 : 0) + (tag ? 4 : 0); @@ -1090,7 +1097,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf, ext->metric = metric & LSA_METRIC_MASK; u32 *buf = ext->rest; - buf = put_ipv6_prefix(buf, nf->fn.prefix, nf->fn.pxlen, pbit ? OPT_PX_P : 0, 0); + buf = ospf_put_ipv6_prefix(buf, nf->fn.addr, pbit ? OPT_PX_P : 0, 0); if (ebit) ext->metric |= LSA_EXT3_EBIT; @@ -1098,7 +1105,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf, if (ipa_nonzero(fwaddr)) { ext->metric |= LSA_EXT3_FBIT; - buf = put_ipv6_addr(buf, fwaddr); + buf = ospf_put_ipv6_addr(buf, fwaddr); } if (tag) @@ -1140,7 +1147,7 @@ ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 m }; if (ospf_is_v2(p)) - prepare_ext2_lsa_body(p, nf->fn.pxlen, metric, ebit, fwaddr, tag); + prepare_ext2_lsa_body(p, nf->fn.addr->pxlen, metric, ebit, fwaddr, tag); else prepare_ext3_lsa_body(p, nf, metric, ebit, fwaddr, tag, oa && pbit); @@ -1177,7 +1184,7 @@ use_gw_for_fwaddr(struct ospf_proto *p, ip_addr gw, struct iface *iface) WALK_LIST(ifa, p->iface_list) if ((ifa->iface == iface) && - (!ospf_is_v2(p) || ipa_in_net(gw, ifa->addr->prefix, ifa->addr->pxlen))) + (!ospf_is_v2(p) || ipa_in_netX(gw, &ifa->addr->prefix))) return 1; return 0; @@ -1215,7 +1222,8 @@ find_surrogate_fwaddr(struct ospf_proto *p, struct ospf_area *oa) { WALK_LIST(a, ifa->iface->addrs) { - if ((a->flags & IA_SECONDARY) || + if ((a->prefix.type != NET_IP6) || + (a->flags & IA_SECONDARY) || (a->flags & IA_PEER) || (a->scope <= SCOPE_LINK)) continue; @@ -1234,7 +1242,7 @@ find_surrogate_fwaddr(struct ospf_proto *p, struct ospf_area *oa) } void -ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *ea) +ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *ea) { struct ospf_proto *p = (struct ospf_proto *) P; struct ospf_area *oa = NULL; /* non-NULL for NSSA-LSA */ @@ -1253,7 +1261,7 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U if (!new) { - nf = (ort *) fib_find(&p->rtf, &n->n.prefix, n->n.pxlen); + nf = fib_find(&p->rtf, n->n.addr); if (!nf || !nf->external_rte) return; @@ -1290,13 +1298,13 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U if (ipa_zero(fwd)) { - log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %I/%d", - p->p.name, n->n.prefix, n->n.pxlen); + log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %N", + p->p.name, n->n.addr); return; } } - nf = (ort *) fib_get(&p->rtf, &n->n.prefix, n->n.pxlen); + nf = fib_get(&p->rtf, n->n.addr); ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1); nf->external_rte = 1; } @@ -1308,11 +1316,11 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U */ static inline void -lsab_put_prefix(struct ospf_proto *p, ip_addr prefix, u32 pxlen, u32 cost) +lsab_put_prefix(struct ospf_proto *p, net_addr *net, u32 cost) { - void *buf = lsab_alloc(p, IPV6_PREFIX_SPACE(pxlen)); - u8 flags = (pxlen < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA; - put_ipv6_prefix(buf, prefix, pxlen, flags, cost); + void *buf = lsab_alloc(p, IPV6_PREFIX_SPACE(net6_pxlen(net))); + u8 flags = (net6_pxlen(net) < IP6_MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA; + ospf_put_ipv6_prefix(buf, net, flags, cost); } static void @@ -1330,11 +1338,12 @@ prepare_link_lsa_body(struct ospf_proto *p, struct ospf_iface *ifa) struct ifa *a; WALK_LIST(a, ifa->iface->addrs) { - if ((a->flags & IA_SECONDARY) || - (a->scope < SCOPE_SITE)) + if ((a->prefix.type != NET_IP6) || + (a->flags & IA_SECONDARY) || + (a->scope <= SCOPE_LINK)) continue; - lsab_put_prefix(p, a->prefix, a->pxlen, 0); + lsab_put_prefix(p, &a->prefix, 0); i++; } @@ -1401,12 +1410,13 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa) struct ifa *a; WALK_LIST(a, ifa->iface->addrs) { - if ((a->flags & IA_SECONDARY) || + if ((a->prefix.type != NET_IP6) || + (a->flags & IA_SECONDARY) || (a->flags & IA_PEER) || (a->scope <= SCOPE_LINK)) continue; - if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) || + if (((a->prefix.pxlen < IP6_MAX_PREFIX_LENGTH) && net_lsa) || configured_stubnet(oa, a)) continue; @@ -1414,11 +1424,12 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa) (ifa->state == OSPF_IS_LOOP) || (ifa->type == OSPF_IT_PTMP)) { - lsab_put_prefix(p, a->ip, MAX_PREFIX_LENGTH, 0); + net_addr_ip6 net = NET_ADDR_IP6(a->ip, IP6_MAX_PREFIX_LENGTH); + lsab_put_prefix(p, (net_addr *) &net, 0); host_addr = 1; } else - lsab_put_prefix(p, a->prefix, a->pxlen, ifa->cost); + lsab_put_prefix(p, &a->prefix, ifa->cost); i++; } @@ -1429,8 +1440,8 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa) WALK_LIST(sn, oa->ac->stubnet_list) if (!sn->hidden) { - lsab_put_prefix(p, sn->px.addr, sn->px.len, sn->cost); - if (sn->px.len == MAX_PREFIX_LENGTH) + lsab_put_prefix(p, &sn->prefix, sn->cost); + if (sn->prefix.pxlen == IP6_MAX_PREFIX_LENGTH) host_addr = 1; i++; } @@ -1447,11 +1458,14 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa) struct ifa *a; WALK_LIST(a, ifa->iface->addrs) { - if ((a->flags & IA_SECONDARY) || (a->scope <= SCOPE_LINK)) + if ((a->prefix.type != NET_IP6) || + (a->flags & IA_SECONDARY) || + (a->scope <= SCOPE_LINK)) continue; /* Found some IP */ - lsab_put_prefix(p, a->ip, MAX_PREFIX_LENGTH, 0); + net_addr_ip6 net = NET_ADDR_IP6(a->ip, IP6_MAX_PREFIX_LENGTH); + lsab_put_prefix(p, (net_addr *) &net, 0); i++; goto done; } @@ -1748,7 +1762,7 @@ ospf_top_hash(struct top_graph *f, u32 domain, u32 lsaid, u32 rtrid, u32 type) * and request lists of OSPF neighbors. */ struct top_graph * -ospf_top_new(struct ospf_proto *p UNUSED4 UNUSED6, pool *pool) +ospf_top_new(struct ospf_proto *p, pool *pool) { struct top_graph *f; diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index 5652ced0..38447fdf 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -185,10 +185,10 @@ static inline void ospf_flush2_lsa(struct ospf_proto *p, struct top_hash_entry * { if (*en) { ospf_flush_lsa(p, *en); *en = NULL; } } void ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric); -void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric, u32 options); +void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options); void ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode, u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit); -void ospf_rt_notify(struct proto *P, rtable *tbl, net *n, rte *new, rte *old, ea_list *attrs); +void ospf_rt_notify(struct proto *P, struct channel *ch, net *n, rte *new, rte *old, ea_list *attrs); void ospf_update_topology(struct ospf_proto *p); struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type); |