diff --git a/doc/bird.sgml b/doc/bird.sgml index 136ff251..e8ccd430 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1195,8 +1195,13 @@ protocol ospf <name> { <prefix>; <prefix> hidden; } - interface <interface pattern> - { + stubnet <prefix>; + stubnet <prefix> { + hidden <switch>; + summary <switch>; + cost <num>; + } + interface <interface pattern> { cost <num>; stub <switch>; hello <num>; @@ -1223,8 +1228,7 @@ protocol ospf <name> { <ip> eligible; }; }; - virtual link <id> - { + virtual link <id> { hello <num>; retransmit <num>; wait <num>; @@ -1265,6 +1269,24 @@ protocol ospf <name> { Definition of area IP ranges. This is used in summary lsa origination. Hidden networks are not propagated into other areas. + stubnet + Stub networks are networks that are not transit networks + between OSPF routers. They are also propagated through an + OSPF area as a part of a link state database. By default, + BIRD generates a stub network record for each primary network + address on each OSPF interface that does not have any OSPF + neighbors, and also for each non-primary network address on + each OSPF interface. This option allows to alter a set of + stub networks propagated by this router. + + Each instance of this option adds a stub network with given + network prefix to the set of propagated stub network, unless + option Defines that the specified interfaces belong to the area being defined. See common option for detailed description. diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 7f7d6a31..0f688a7e 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -18,6 +18,7 @@ CF_DEFINES static struct ospf_area_config *this_area; static struct nbma_node *this_nbma; static struct area_net_config *this_pref; +static struct ospf_stubnet_config *this_stubnet; static void finish_iface_config(struct ospf_iface_patt *ip) @@ -38,7 +39,7 @@ CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT) CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE) CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, LINK) -CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL) +CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY) %type opttext @@ -75,6 +76,7 @@ ospf_area_start: AREA idval '{' { init_list(&this_area->patt_list); init_list(&this_area->vlink_list); init_list(&this_area->net_list); + init_list(&this_area->stubnet_list); } ; @@ -90,10 +92,36 @@ ospf_area_item: STUB COST expr { this_area->stub = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); } | STUB bool {if($2) { if(!this_area->stub) this_area->stub=DEFAULT_STUB_COST;}else{ this_area->stub=0;}} | NETWORKS '{' pref_list '}' + | STUBNET ospf_stubnet | INTERFACE ospf_iface | ospf_vlink ; +ospf_stubnet: + ospf_stubnet_start '{' ospf_stubnet_opts '}' + | ospf_stubnet_start + ; + +ospf_stubnet_start: + prefix { + this_stubnet = cfg_allocz(sizeof(struct stubnet_config)); + add_tail(&this_area->stubnet_list, NODE this_stubnet); + this_stubnet->px = $1; + this_stubnet->cost = COST_D; + } + ; + +ospf_stubnet_opts: + /* empty */ + | ospf_stubnet_opts ospf_stubnet_item ';' + ; + +ospf_stubnet_item: + HIDDEN bool { this_stubnet->hidden = $2; } + | SUMMARY bool { this_stubnet->summary = $2; } + | COST expr { this_stubnet->cost = $2; } + ; + ospf_vlink: ospf_vlink_start '{' ospf_vlink_opts '}' { finish_iface_config(OSPF_PATT); } | ospf_vlink_start diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 4ad6ef46..c9b5f430 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -148,6 +148,7 @@ ospf_start(struct proto *p) oa = mb_allocz(p->pool, sizeof(struct ospf_area)); add_tail(&po->area_list, NODE oa); po->areano++; + oa->ac = ac; oa->stub = ac->stub; oa->areaid = ac->areaid; oa->rt = NULL; @@ -629,9 +630,31 @@ ospf_reconfigure(struct proto *p, struct proto_config *c) if (!oa) return 0; + oa->ac = newac; oa->stub = newac->stub; if (newac->stub && (oa->areaid == 0)) oa->stub = 0; + /* Check stubnet_list */ + struct ospf_stubnet_config *oldsn = HEAD(oldac->stubnet_list); + struct ospf_stubnet_config *newsn = HEAD(newac->stubnet_list); + + while (((NODE(oldsn))->next != NULL) && ((NODE(newsn))->next != NULL)) + { + if (!ipa_equal(oldsn->px.addr, newsn->px.addr) || + (oldsn->px.len != newsn->px.len) || + (oldsn->hidden != newsn->hidden) || + (oldsn->summary != newsn->summary) || + (oldsn->cost != newsn->cost)) + break; + + oldsn = (struct ospf_stubnet_config *)(NODE(oldsn))->next; + newsn = (struct ospf_stubnet_config *)(NODE(newsn))->next; + } + + /* If there is no change, both pointers should be NULL */ + if (((NODE(oldsn))->next) != ((NODE(newsn))->next)) + schedule_rt_lsa(oa); + /* Change net_list */ FIB_WALK(&oa->net_fib, nf) /* First check if some networks are deleted */ { diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 71f99d34..23f21b8e 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -99,6 +99,14 @@ struct area_net u32 metric; }; +struct ospf_stubnet_config +{ + node n; + struct prefix px; + int hidden, summary; + u32 cost; +}; + struct ospf_area_config { node n; @@ -107,6 +115,7 @@ struct ospf_area_config list patt_list; list vlink_list; list net_list; + list stubnet_list; }; struct obits @@ -523,6 +532,7 @@ struct ospf_area { node n; u32 areaid; + struct ospf_area_config *ac; /* Related area config */ int origrt; /* Rt lsa origination scheduled? */ struct top_hash_entry *rt; /* My own router LSA */ list cand; /* List of candidates for RT calc. */ diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 18100f7e..371856f9 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -52,6 +52,25 @@ lsab_flush(struct proto_ospf *po) return r; } +static int +configured_stubnet(struct ospf_area *oa, struct ifa *a) +{ + struct ospf_stubnet_config *sn; + WALK_LIST(sn, oa->ac->stubnet_list) + { + if (sn->summary) + { + if (ipa_in_net(a->prefix, sn->px.addr, sn->px.len) && (a->pxlen >= sn->px.len)) + return 1; + } + else + { + if (ipa_equal(a->prefix, sn->px.addr) && (a->pxlen == sn->px.len)) + return 1; + } + } + return 0; +} static void * originate_rt_lsa_body(struct ospf_area *oa, u16 * length) @@ -163,9 +182,11 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length) { if (((a == ifa->iface->addr) && master) || (a->flags & IA_SECONDARY) || - (a->flags & IA_UNNUMBERED)) + (a->flags & IA_UNNUMBERED) || + configured_stubnet(oa, a)) continue; + ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link)); ln->type = LSART_STUB; ln->id = ipa_to_u32(a->prefix); @@ -176,6 +197,19 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length) } } + struct ospf_stubnet_config *sn; + WALK_LIST(sn, oa->ac->stubnet_list) + if (!sn->hidden) + { + ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link)); + ln->type = LSART_STUB; + ln->id = ipa_to_u32(sn->px.addr); + ln->data = ipa_to_u32(ipa_mkmask(sn->px.len)); + ln->metric = sn->cost; + ln->notos = 0; + i++; + } + rt = po->lsab; rt->links = i; rt->veb.bit.v = bitv;