summaryrefslogtreecommitdiff
path: root/ospfd/ospf_spf.c
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2022-10-12 09:30:36 -0400
committerGitHub <noreply@github.com>2022-10-12 09:30:36 -0400
commit984eb32b588186ac946733c5c3fe8032bae28ebc (patch)
treefadbfb00938fbd06eb92909bfe628857b7b3d00f /ospfd/ospf_spf.c
parent87d54383c520799a90457e84e2242b6fa2024f73 (diff)
parent80f6ea8b99188b9d8e79fe4fc1740cc92375d7bc (diff)
Merge pull request #11159 from maduri111/bgpd-orr
bgpd: optimal route reflection
Diffstat (limited to 'ospfd/ospf_spf.c')
-rw-r--r--ospfd/ospf_spf.c201
1 files changed, 175 insertions, 26 deletions
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index 4edc1de811..74213d7de2 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -53,6 +53,8 @@
#include "ospfd/ospf_apiserver.h"
#endif
+#include "ospfd/ospf_orr.h"
+
/* Variables to ensure a SPF scheduled log message is printed only once */
static unsigned int spf_reason_flags = 0;
@@ -1824,6 +1826,36 @@ void ospf_spf_calculate_areas(struct ospf *ospf, struct route_table *new_table,
all_rtrs, new_rtrs);
}
+/* Print Reason for SPF calculation */
+static void ospf_spf_calculation_reason2str(char *rbuf)
+{
+ rbuf[0] = '\0';
+ if (spf_reason_flags) {
+ if (spf_reason_flags & (1 << SPF_FLAG_ROUTER_LSA_INSTALL))
+ strlcat(rbuf, "R, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_NETWORK_LSA_INSTALL))
+ strlcat(rbuf, "N, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_SUMMARY_LSA_INSTALL))
+ strlcat(rbuf, "S, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL))
+ strlcat(rbuf, "AS, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ABR_STATUS_CHANGE))
+ strlcat(rbuf, "ABR, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ASBR_STATUS_CHANGE))
+ strlcat(rbuf, "ASBR, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_MAXAGE))
+ strlcat(rbuf, "M, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ORR_ROOT_CHANGE))
+ strlcat(rbuf, "ORR, ", sizeof(rbuf));
+
+ size_t rbuflen = strlen(rbuf);
+ if (rbuflen >= 2)
+ rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
+ else
+ rbuf[0] = '\0';
+ }
+}
+
/* Worker for SPF calculation scheduler. */
static void ospf_spf_calculate_schedule_worker(struct thread *thread)
{
@@ -1879,6 +1911,8 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
ospf_ase_calculate_schedule(ospf);
ospf_ase_calculate_timer_add(ospf);
+ ospf_orr_spf_calculate_schedule(ospf);
+
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"%s: ospf install new route, vrf %s id %u new_table count %lu",
@@ -1901,7 +1935,6 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
#ifdef SUPPORT_OSPF_API
ospf_apiserver_notify_reachable(ospf->oall_rtrs, ospf->all_rtrs);
#endif
-
/* Free old ABR/ASBR routing table */
if (ospf->old_rtrs)
/* ospf_route_delete (ospf->old_rtrs); */
@@ -1926,31 +1959,7 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
total_spf_time =
monotime_since(&spf_start_time, &ospf->ts_spf_duration);
- rbuf[0] = '\0';
- if (spf_reason_flags) {
- if (spf_reason_flags & (1 << SPF_FLAG_ROUTER_LSA_INSTALL))
- strlcat(rbuf, "R, ", sizeof(rbuf));
- if (spf_reason_flags & (1 << SPF_FLAG_NETWORK_LSA_INSTALL))
- strlcat(rbuf, "N, ", sizeof(rbuf));
- if (spf_reason_flags & (1 << SPF_FLAG_SUMMARY_LSA_INSTALL))
- strlcat(rbuf, "S, ", sizeof(rbuf));
- if (spf_reason_flags & (1 << SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL))
- strlcat(rbuf, "AS, ", sizeof(rbuf));
- if (spf_reason_flags & (1 << SPF_FLAG_ABR_STATUS_CHANGE))
- strlcat(rbuf, "ABR, ", sizeof(rbuf));
- if (spf_reason_flags & (1 << SPF_FLAG_ASBR_STATUS_CHANGE))
- strlcat(rbuf, "ASBR, ", sizeof(rbuf));
- if (spf_reason_flags & (1 << SPF_FLAG_MAXAGE))
- strlcat(rbuf, "M, ", sizeof(rbuf));
- if (spf_reason_flags & (1 << SPF_FLAG_GR_FINISH))
- strlcat(rbuf, "GR, ", sizeof(rbuf));
-
- size_t rbuflen = strlen(rbuf);
- if (rbuflen >= 2)
- rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
- else
- rbuf[0] = '\0';
- }
+ ospf_spf_calculation_reason2str(rbuf);
if (IS_DEBUG_OSPF_EVENT) {
zlog_info("SPF Processing Time(usecs): %ld", total_spf_time);
@@ -1967,6 +1976,145 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
ospf_clear_spf_reason_flags();
}
+/* Worker for ORR SPF calculation scheduler. */
+void ospf_orr_spf_calculate_schedule_worker(struct thread *thread)
+{
+ afi_t afi;
+ safi_t safi;
+ struct ospf *ospf = THREAD_ARG(thread);
+ struct route_table *new_table, *new_rtrs;
+ struct route_table *all_rtrs = NULL;
+ struct timeval start_time, spf_start_time;
+ unsigned long ia_time, rt_time;
+ unsigned long abr_time, total_spf_time, spf_time;
+ struct listnode *rnode;
+ struct list *orr_root_list;
+ struct orr_root *root;
+ char rbuf[32]; /* reason_buf */
+
+ ospf_orr_debug("%s: SPF: Timer (SPF calculation expire)", __func__);
+
+ ospf->t_orr_calc = NULL;
+
+ /* Execute SPF for each ORR Root node */
+ FOREACH_AFI_SAFI (afi, safi) {
+ orr_root_list = ospf->orr_root[afi][safi];
+ if (!orr_root_list)
+ continue;
+ for (ALL_LIST_ELEMENTS_RO(orr_root_list, rnode, root)) {
+ if (!root || !root->router_lsa_rcvd)
+ continue;
+ ospf_orr_debug(
+ "%s: For %s %s, MPLS TE Router address %pI4 advertised by %pI4",
+ __func__, afi2str(afi), safi2str(safi),
+ &root->router_id, &root->adv_router);
+
+ ospf_vl_unapprove(ospf);
+
+ /*
+ * Execute SPF for each area including backbone, see RFC
+ * 2328 16.1.
+ */
+ monotime(&spf_start_time);
+ new_table = route_table_init(); /* routing table */
+ new_rtrs =
+ route_table_init(); /* ABR/ASBR routing table */
+
+ /*
+ * If we have opaque enabled then track all router
+ * reachability
+ */
+ if (CHECK_FLAG(ospf->opaque,
+ OPAQUE_OPERATION_READY_BIT))
+ all_rtrs = route_table_init();
+ ospf_orr_spf_calculate_areas(ospf, new_table, all_rtrs,
+ new_rtrs,
+ root->router_lsa_rcvd);
+
+ spf_time = monotime_since(&spf_start_time, NULL);
+
+ ospf_vl_shut_unapproved(ospf);
+
+ /* Calculate inter-area routes, see RFC 2328 16.2. */
+ monotime(&start_time);
+ ospf_ia_routing(ospf, new_table, new_rtrs);
+ ia_time = monotime_since(&start_time, NULL);
+
+ /*
+ * REVISIT :
+ * Pruning of unreachable networks, routers skipped.
+ */
+
+ /* Note: RFC 2328 16.3. is apparently missing. */
+ /* Calculate AS external routes, see RFC 2328 16.4.
+ * There is a dedicated routing table for external
+ * routes which is not handled here directly
+ */
+ ospf_ase_calculate_schedule(ospf);
+ ospf_ase_calculate_timer_add(ospf);
+
+ ospf_orr_debug(
+ "%s: ospf install new route, vrf %s id %u new_table count %lu",
+ __func__, ospf_vrf_id_to_name(ospf->vrf_id),
+ ospf->vrf_id, new_table->count);
+
+ /* Update routing table. */
+ monotime(&start_time);
+ ospf_orr_route_install(root, new_table, ospf->instance);
+ rt_time = monotime_since(&start_time, NULL);
+
+ /*
+ * REVISIT :
+ * Freeing up and Updating old all routers routing table
+ * skipped.
+ */
+
+ /* Free old ABR/ASBR routing table */
+ if (root->old_rtrs)
+ /* ospf_route_delete (ospf->old_rtrs); */
+ ospf_rtrs_free(root->old_rtrs);
+
+ /* Update ABR/ASBR routing table */
+ root->old_rtrs = root->new_rtrs;
+ root->new_rtrs = new_rtrs;
+
+ /*
+ * ABRs may require additional changes, see RFC
+ * 2328 16.7.
+ */
+ monotime(&start_time);
+ if (IS_OSPF_ABR(ospf)) {
+ if (ospf->anyNSSA)
+ ospf_abr_nssa_check_status(ospf);
+ ospf_abr_task(ospf);
+ }
+ abr_time = monotime_since(&start_time, NULL);
+
+ /* Schedule Segment Routing update */
+ ospf_sr_update_task(ospf);
+
+ total_spf_time = monotime_since(&spf_start_time,
+ &ospf->ts_spf_duration);
+
+ ospf_spf_calculation_reason2str(rbuf);
+
+ if (IS_DEBUG_OSPF_ORR) {
+ zlog_info("SPF Processing Time(usecs): %ld",
+ total_spf_time);
+ zlog_info(" SPF Time: %ld",
+ spf_time);
+ zlog_info(" InterArea: %ld", ia_time);
+ zlog_info(" RouteInstall: %ld", rt_time);
+ if (IS_OSPF_ABR(ospf))
+ zlog_info(
+ " ABR: %ld (%d areas)",
+ abr_time, ospf->areas->count);
+ zlog_info("Reason(s) for SPF: %s", rbuf);
+ }
+ } /* ALL_LIST_ELEMENTS_RO() */
+ } /* FOREACH_AFI_SAFI() */
+}
+
/*
* Add schedule for SPF calculation. To avoid frequenst SPF calc, we set timer
* for SPF calc.
@@ -2025,6 +2173,7 @@ void ospf_spf_calculate_schedule(struct ospf *ospf, ospf_spf_reason_t reason)
zlog_debug("SPF: calculation timer delay = %ld msec", delay);
ospf->t_spf_calc = NULL;
+
thread_add_timer_msec(master, ospf_spf_calculate_schedule_worker, ospf,
delay, &ospf->t_spf_calc);
}