diff options
Diffstat (limited to 'proto')
-rw-r--r-- | proto/ospf/config.Y | 30 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 23 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 10 | ||||
-rw-r--r-- | proto/ospf/topology.c | 36 |
4 files changed, 97 insertions, 2 deletions
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 <t> 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; |