diff options
-rw-r--r-- | proto/ospf/config.Y | 4 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 5 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 8 | ||||
-rw-r--r-- | proto/ospf/rt.c | 72 | ||||
-rw-r--r-- | proto/ospf/topology.c | 6 |
5 files changed, 93 insertions, 2 deletions
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 35060aa7..1099b729 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -101,7 +101,7 @@ CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP) CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK) CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY) -CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA) +CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY) %type <t> opttext @@ -159,6 +159,8 @@ ospf_area_item: | STUB bool { this_area->type = $2 ? 0 : OPT_E; /* We should remove the option */ } | NSSA { this_area->type = OPT_N; } | SUMMARY bool { this_area->summary = $2; } + | TRANSLATOR bool { this_area->translator = $2; } + | TRANSLATOR STABILITY bool { this_area->transint = $3; } | NETWORKS '{' pref_list '}' | STUBNET ospf_stubnet | INTERFACE ospf_iface diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 320f4577..83bcad75 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -178,6 +178,9 @@ ospf_area_remove(struct ospf_area *oa) fib_free(&oa->rtr); fib_free(&oa->net_fib); + if (oa->translator_timer) + rfree(oa->translator_timer); + oa->po->areano--; rem_node(NODE oa); mb_free(oa); @@ -803,6 +806,8 @@ ospf_sh(struct proto *p) } // FIXME NSSA: // cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No"); + cli_msg(-1014, "\t\tNSSA translation:\t%s%s", oa->translate ? "Yes" : "No", + oa->translate == TRANS_WAIT ? " (run down)" : ""); cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No"); cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano); cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno); diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index a8b4a980..68c19424 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -127,6 +127,8 @@ struct ospf_area_config u8 type; /* Area type (standard, stub, NSSA), represented by option flags (OPT_E, OPT_N) */ u8 summary; /* Import summaries to this stub/NSSA area, valid for ABR */ + u8 translator; /* Translator role, for NSSA ABR */ + u32 transint; /* Translator stability interval */ list patt_list; list net_list; /* List of aggregate networks for that area */ list stubnet_list; /* List of stub networks added to Router LSA */ @@ -736,10 +738,16 @@ struct ospf_area byte origrt; /* Rt lsa origination scheduled? */ byte trcap; /* Transit capability? */ byte marked; /* Used in OSPF reconfigure */ + byte translate; /* Translator state (TRANS_*), for NSSA ABR */ + timer *translator_timer; /* For NSSA translator switch */ struct proto_ospf *po; struct fib rtr; /* Routing tables for routers */ }; +#define TRANS_OFF 0 +#define TRANS_ON 1 +#define TRANS_WAIT 2 /* Waiting before the end of translation */ + struct proto_ospf { struct proto proto; diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index e8d661cd..71acd8be 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -1000,12 +1000,26 @@ ospf_check_vlinks(struct proto_ospf *po) } } +static void +translator_timer_hook(timer *timer) +{ + struct ospf_area *oa = timer->data; + + if (oa->translate != TRANS_WAIT) + return; + + oa->translate = TRANS_OFF; + schedule_rtcalc(oa->po); +} + + /* Miscellaneous route processing that needs to be done by ABRs */ static void ospf_rt_abr(struct proto_ospf *po) { + struct top_hash_entry *en; struct area_net *anet; - ort *nf, *default_nf; + ort *nf, *nf2, *default_nf; FIB_WALK(&po->rtf, nftmp) { @@ -1073,6 +1087,62 @@ ospf_rt_abr(struct proto_ospf *po) } + /* RFC 3103 3.1 - type-7 translator election */ + struct ospf_area *bb = oa->po->backbone; + WALK_LIST(oa, po->area_list) + if (oa_is_nssa(oa)) + { + int translate = 1; + + if (oa->ac->translator) + goto decided; + + FIB_WALK(&oa->rtr, nftmp) + { + nf = (ort *) nftmp; + if (!nf->n.type || !(nf->n.options & ORTA_ABR)) + continue; + + nf2 = fib_find(&bb->rtr, &nf->fn.prefix, MAX_PREFIX_LENGTH); + if (!nf2 || !nf2->n.type || !(nf2->n.options & ORTA_ABR)) + continue; + + en = ospf_hash_find_rt(po->gr, oa->areaid, nf->n.rid); + if (!en || (en->color != INSPF)) + continue; + + struct ospf_lsa_rt *rt = en->lsa_body; + /* There is better candidate - Nt-bit or higher Router ID */ + if ((rt->options & OPT_RT_NT) || (po->router_id < nf->n.rid)) + { + translate = 0; + goto decided; + break; + } + } + FIB_WALK_END; + + decided: + if (translate && (oa->translate != TRANS_ON)) + { + if (oa->translate == TRANS_WAIT) + tm_stop(oa->translator_timer); + + oa->translate = TRANS_ON; + } + + if (!translate && (oa->translate == TRANS_ON)) + { + if (oa->translator_timer == NULL) + oa->translator_timer = tm_new_set(po->proto.pool, translator_timer_hook, oa, 0, 0); + + /* Schedule the end of translation */ + tm_start(oa->translator_timer, oa->ac->transint); + oa->translate = TRANS_WAIT; + } + } + + /* Originate or flush ASBR summary LSAs */ FIB_WALK(&po->backbone->rtr, nftmp) { diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 54bc09cb..f5f041eb 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -222,6 +222,9 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length) if (po->areano > 1) rt->options |= OPT_RT_B; + if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator) + rt->options |= OPT_RT_NT; + if (po->ebit && !oa_is_stub(oa)) rt->options |= OPT_RT_E; @@ -388,6 +391,9 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length) if (po->areano > 1) rt->options |= OPT_RT_B; + if ((po->areano > 1) && oa_is_nssa(oa) && oa->ac->translator) + rt->options |= OPT_RT_NT; + if (po->ebit && !oa_is_stub(oa)) rt->options |= OPT_RT_E; |