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