From 690df17787c759d36cf57ba1070c961ac87b4b1a Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Fri, 2 Mar 2018 14:20:26 -0800 Subject: [PATCH] ospf6d: Intra-prefix LSA update after frr restart Initially INP LSA is originated, when connected interface comes up. As neighbor is not up, LSA is not transmitted but stored in DB. As NSM transition to FULL, INP is scheduled but ospf6_flood() would not originate the LSA as current DB and new INP LSA same so it discards the new LSA. When Neighor becomes FULL, originate INP via flushing current DB copy and generate new. This is introduced as PR 1738 introduce, premature aging of LSAs in nbr table as R1 going down. upon neigbor coming up, INP was not updated to new age. Ticket:CM-19926,CM-19945 Testing Done: Topology R3 --- R1 -- R2, R1 have INP LSA. After frr restart R2 and R3 re learnt R1's INP LSA as new neighbor(s) come up. Signed-off-by: Chirag Shah --- ospf6d/ospf6_area.h | 1 + ospf6d/ospf6_flood.c | 22 ++++++++++++++++++++++ ospf6d/ospf6_flood.h | 3 +++ ospf6d/ospf6_intra.c | 14 ++++++++++++++ ospf6d/ospf6_neighbor.c | 3 +++ 5 files changed, 43 insertions(+) diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h index e162d21cd2..a44a432a0a 100644 --- a/ospf6d/ospf6_area.h +++ b/ospf6d/ospf6_area.h @@ -101,6 +101,7 @@ struct ospf6_area { struct timeval ts_spf; /* SPF calculation time stamp. */ uint32_t full_nbrs; /* Fully adjacent neighbors. */ + uint8_t intra_prefix_originate; /* Force intra_prefix lsa originate */ }; #define OSPF6_AREA_ENABLE 0x01 diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index dae10dce0d..6040c53dce 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -156,6 +156,28 @@ void ospf6_lsa_purge(struct ospf6_lsa *lsa) ospf6_lsa_premature_aging(lsa); } +/* Puring Multi Link-State IDs LSAs: + * Same Advertising Router with Multiple Link-State IDs + * LSAs, purging require to traverse all Link-State IDs + */ +void ospf6_lsa_purge_multi_ls_id(struct ospf6_area *oa, struct ospf6_lsa *lsa) +{ + int ls_id = 0; + struct ospf6_lsa *lsa_next; + uint16_t type; + + type = lsa->header->type; + + ospf6_lsa_purge(lsa); + + lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id), + oa->ospf6->router_id, oa->lsdb); + while (lsa_next) { + ospf6_lsa_purge(lsa_next); + lsa_next = ospf6_lsdb_lookup(type, htonl(++ls_id), + oa->ospf6->router_id, oa->lsdb); + } +} void ospf6_increment_retrans_count(struct ospf6_lsa *lsa) { diff --git a/ospf6d/ospf6_flood.h b/ospf6d/ospf6_flood.h index f5d33e2843..6931024fff 100644 --- a/ospf6d/ospf6_flood.h +++ b/ospf6d/ospf6_flood.h @@ -41,6 +41,9 @@ extern void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa, struct ospf6_interface *oi); extern void ospf6_lsa_purge(struct ospf6_lsa *lsa); +extern void ospf6_lsa_purge_multi_ls_id(struct ospf6_area *oa, + struct ospf6_lsa *lsa); + /* access method to retrans_count */ extern void ospf6_increment_retrans_count(struct ospf6_lsa *lsa); extern void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa); diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 14f12d6b6a..c9e2ff9eb5 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -1015,6 +1015,20 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) return 0; } + /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA + * has not change, Flush old LSA and Re-Originate INP, + * as ospf6_flood() checks if LSA is same as DB, + * it won't be updated to neighbor's DB. + */ + if (oa->intra_prefix_originate) { + if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) + zlog_debug("%s: Re-originate intra prefix LSA, Current full nbrs %u", + __PRETTY_FUNCTION__, oa->full_nbrs); + if (old) + ospf6_lsa_purge_multi_ls_id(oa, old); + oa->intra_prefix_originate = 0; + } + /* put prefixes to advertise */ prefix_num = 0; op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 542a24bfc9..16bf2fd8e7 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -188,6 +188,9 @@ static void ospf6_neighbor_state_change(u_char next_state, OSPF6_NETWORK_LSA_SCHEDULE(on->ospf6_if); OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(on->ospf6_if); } + if (next_state == OSPF6_NEIGHBOR_FULL) + on->ospf6_if->area->intra_prefix_originate = 1; + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area); if (prev_state == OSPF6_NEIGHBOR_LOADING -- 2.39.5