diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 02f8eb0b09..11f9e7c7b6 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -148,6 +148,32 @@ static void ospf6_as_external_lsa_originate(struct ospf6_route *route) ospf6_lsa_originate_process(lsa, ospf6); } +int ospf6_orig_as_external_lsa(struct thread *thread) +{ + struct ospf6_interface *oi; + struct ospf6_lsa *lsa; + uint32_t type, adv_router; + + oi = (struct ospf6_interface *)THREAD_ARG(thread); + oi->thread_as_extern_lsa = NULL; + + if (oi->state == OSPF6_INTERFACE_DOWN) + return 0; + + type = htons(OSPF6_LSTYPE_AS_EXTERNAL); + adv_router = oi->area->ospf6->router_id; + for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) { + if (IS_OSPF6_DEBUG_ASBR) + zlog_debug("%s: Send update of AS-External LSA %s seq 0x%x", + __PRETTY_FUNCTION__, lsa->name, + ntohl(lsa->header->seqnum)); + + ospf6_flood_interface(NULL, lsa, oi); + } + + return 0; +} + static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa) { struct ospf6_as_external_lsa *external; diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 42716fbc7f..17733d6099 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -192,10 +192,6 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) struct timeval now; struct ospf6_lsa *old; - if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type) - || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) - zlog_debug("Install LSA: %s", lsa->name); - /* Remove the old instance from all neighbors' Link state retransmission list (RFC2328 13.2 last paragraph) */ old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, @@ -237,6 +233,13 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) ospf6_lsa_checksum(lsa->header); } + if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type) + || IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) + zlog_debug("%s Install LSA: %s age %d seqnum %x in LSDB.", + __PRETTY_FUNCTION__, lsa->name, + ntohs(lsa->header->age), + ntohl(lsa->header->seqnum)); + /* actually install */ lsa->installed = now; ospf6_lsdb_add(lsa, lsa->lsdb); @@ -246,7 +249,7 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa) /* RFC2740 section 3.5.2. Sending Link State Update packets */ /* RFC2328 section 13.3 Next step in the flooding procedure */ -static void ospf6_flood_interface(struct ospf6_neighbor *from, +void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa, struct ospf6_interface *oi) { @@ -343,15 +346,24 @@ static void ospf6_flood_interface(struct ospf6_neighbor *from, continue; } - /* (d) add retrans-list, schedule retransmission */ - if (is_debug) - zlog_debug("Add retrans-list of this neighbor"); - ospf6_increment_retrans_count(lsa); - ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); - thread_add_timer(master, ospf6_lsupdate_send_neighbor, on, - on->ospf6_if->rxmt_interval, - &on->thread_send_lsupdate); - retrans_added++; + if (ospf6->inst_shutdown) { + if (is_debug) + zlog_debug("%s: Send LSA %s (age %d) update now", + __PRETTY_FUNCTION__, lsa->name, + ntohs(lsa->header->age)); + ospf6_lsupdate_send_neighbor_now(on, lsa); + continue; + } else { + /* (d) add retrans-list, schedule retransmission */ + if (is_debug) + zlog_debug("Add retrans-list of this neighbor"); + ospf6_increment_retrans_count(lsa); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); + thread_add_timer(master, ospf6_lsupdate_send_neighbor, + on, on->ospf6_if->rxmt_interval, + &on->thread_send_lsupdate); + retrans_added++; + } } /* (2) examin next interface if not added to retrans-list */ @@ -806,6 +818,17 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, zlog_debug("Received is duplicated LSA"); SET_FLAG(new->flag, OSPF6_LSA_DUPLICATE); } + if (old->header->adv_router == + from->ospf6_if->area->ospf6->router_id + && OSPF6_LSA_IS_MAXAGE(new)) { + ospf6_acknowledge_lsa(new, ismore_recent, from); + ospf6_lsa_delete(new); + if (is_debug) + zlog_debug("%s: Received is self orig MAXAGE LSA %s, discard (ismore_recent %d)", + __PRETTY_FUNCTION__, old->name, + ismore_recent); + return; + } } /* if no database copy or received is more recent */ @@ -959,12 +982,34 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, "Send back directly and then discard"); } + /* Neighbor router sent recent age for LSA, + * Router could be restarted while current copy is + * MAXAGEd and not removed.*/ + if (OSPF6_LSA_IS_MAXAGE(old) && + !OSPF6_LSA_IS_MAXAGE(new)) { + + if (is_debug) + zlog_debug("%s: Current copy of LSA %s is MAXAGE, but new has recent Age.", + old->name, + __PRETTY_FUNCTION__); + + ospf6_lsa_purge(old); + if (new->header->adv_router + != from->ospf6_if->area-> + ospf6->router_id) + ospf6_flood(from, new); + + ospf6_install_lsa(new); + return; + } + /* XXX, MinLSArrival check !? RFC 2328 13 (8) */ ospf6_lsdb_add(ospf6_lsa_copy(old), from->lsupdate_list); thread_add_event(master, ospf6_lsupdate_send_neighbor, from, 0, &from->thread_send_lsupdate); + ospf6_lsa_delete(new); return; } @@ -972,7 +1017,6 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from, } } - DEFUN (debug_ospf6_flooding, debug_ospf6_flooding_cmd, "debug ospf6 flooding", diff --git a/ospf6d/ospf6_flood.h b/ospf6d/ospf6_flood.h index 610eefc803..f5d33e2843 100644 --- a/ospf6d/ospf6_flood.h +++ b/ospf6d/ospf6_flood.h @@ -58,5 +58,10 @@ extern void ospf6_install_lsa(struct ospf6_lsa *lsa); extern int config_write_ospf6_debug_flood(struct vty *vty); extern void install_element_ospf6_debug_flood(void); +extern void ospf6_flood_interface(struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, + struct ospf6_interface *oi); +extern int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on, + struct ospf6_lsa *lsa); #endif /* OSPF6_FLOOD_H */ diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index fc6c46c7e7..5eaf617702 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -301,6 +301,7 @@ void ospf6_interface_disable(struct ospf6_interface *oi) THREAD_OFF(oi->thread_network_lsa); THREAD_OFF(oi->thread_link_lsa); THREAD_OFF(oi->thread_intra_prefix_lsa); + THREAD_OFF(oi->thread_as_extern_lsa); } static struct in6_addr * @@ -532,6 +533,7 @@ static void ospf6_interface_state_change(u_char next_state, OSPF6_NETWORK_LSA_EXECUTE(oi); OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi); OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); + OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi); } else if (prev_state == OSPF6_INTERFACE_DR || next_state == OSPF6_INTERFACE_DR) { OSPF6_NETWORK_LSA_SCHEDULE(oi); diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index b67d9a9f2e..9b9952beb6 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -108,6 +108,7 @@ struct ospf6_interface { struct thread *thread_network_lsa; struct thread *thread_link_lsa; struct thread *thread_intra_prefix_lsa; + struct thread *thread_as_extern_lsa; struct ospf6_route_table *route_connected; diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h index b511a92005..2ae17f0700 100644 --- a/ospf6d/ospf6_intra.h +++ b/ospf6d/ospf6_intra.h @@ -185,11 +185,21 @@ struct ospf6_intra_prefix_lsa { 0, &(oi)->thread_intra_prefix_lsa); \ } while (0) +#define OSPF6_AS_EXTERN_LSA_SCHEDULE(oi) \ + do { \ + if (!CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \ + thread_add_event( \ + master, \ + ospf6_orig_as_external_lsa, oi, \ + 0, &(oi)->thread_as_extern_lsa); \ + } while (0) + #define OSPF6_NETWORK_LSA_EXECUTE(oi) \ do { \ THREAD_OFF((oi)->thread_network_lsa); \ thread_execute(master, ospf6_network_lsa_originate, oi, 0); \ } while (0) + #define OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi) \ do { \ THREAD_OFF((oi)->thread_intra_prefix_lsa); \ @@ -198,6 +208,11 @@ struct ospf6_intra_prefix_lsa { 0); \ } while (0) +#define OSPF6_AS_EXTERN_LSA_EXECUTE(oi) \ + do { \ + THREAD_OFF((oi)->thread_as_extern_lsa); \ + thread_execute(master, ospf6_orig_as_external_lsa, oi, 0); \ + } while (0) /* Function Prototypes */ extern char *ospf6_router_lsdesc_lookup(u_char type, u_int32_t interface_id, @@ -215,7 +230,7 @@ extern int ospf6_intra_prefix_lsa_originate_transit(struct thread *); extern int ospf6_intra_prefix_lsa_originate_stub(struct thread *); extern void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa); extern void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa); - +extern int ospf6_orig_as_external_lsa(struct thread *thread); extern void ospf6_intra_route_calculation(struct ospf6_area *oa); extern void ospf6_intra_brouter_calculation(struct ospf6_area *oa); diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index cca4616c16..4a1ba992e3 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -706,6 +706,37 @@ int ospf6_lsa_refresh(struct thread *thread) return 0; } +void ospf6_flush_self_originated_lsas_now(void) +{ + struct listnode *node; + struct ospf6_area *oa; + struct ospf6_lsa *lsa; + const struct route_node *end = NULL; + uint32_t type, adv_router; + + ospf6->inst_shutdown = 1; + + for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { + end = ospf6_lsdb_head(oa->lsdb_self, 0, 0, + ospf6->router_id, &lsa); + while (lsa) { + /* RFC 2328 (14.1): Set MAXAGE */ + lsa->header->age = htons(OSPF_LSA_MAXAGE); + /* Flood MAXAGE LSA*/ + ospf6_flood(NULL, lsa); + + lsa = ospf6_lsdb_next(end, lsa); + } + } + + type = htons(OSPF6_LSTYPE_AS_EXTERNAL); + adv_router = ospf6->router_id; + for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) { + /* RFC 2328 (14.1): Set MAXAGE */ + lsa->header->age = htons(OSPF_LSA_MAXAGE); + ospf6_flood(NULL, lsa); + } +} /* Fletcher Checksum -- Refer to RFC1008. */ diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index db446a3287..369b381faa 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -253,5 +253,6 @@ extern void ospf6_lsa_terminate(void); extern int config_write_ospf6_debug_lsa(struct vty *vty); extern void install_element_ospf6_debug_lsa(void); extern void ospf6_lsa_age_set(struct ospf6_lsa *lsa); +extern void ospf6_flush_self_originated_lsas_now(void); #endif /* OSPF6_LSA_H */ diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c index 418f858a32..152702391b 100644 --- a/ospf6d/ospf6_lsdb.c +++ b/ospf6d/ospf6_lsdb.c @@ -334,6 +334,7 @@ int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb) } if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) zlog_debug("Remove MaxAge %s", lsa->name); + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED)) { UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); /* diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index d76438ea50..fe74ddc982 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -2163,6 +2163,40 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread) return 0; } +int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on, + struct ospf6_lsa *lsa) +{ + struct ospf6_header *oh; + struct ospf6_lsupdate *lsupdate; + u_char *p; + int lsa_cnt = 0; + + memset(sendbuf, 0, iobuflen); + oh = (struct ospf6_header *)sendbuf; + lsupdate = (struct ospf6_lsupdate *)((caddr_t)oh + + sizeof(struct ospf6_header)); + + p = (u_char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); + ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay); + memcpy(p, lsa->header, OSPF6_LSA_SIZE(lsa->header)); + p += OSPF6_LSA_SIZE(lsa->header); + lsa_cnt++; + + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons(p - sendbuf); + lsupdate->lsa_number = htonl(lsa_cnt); + + if (IS_OSPF6_DEBUG_FLOODING || + IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_debug("%s: Send lsupdate with lsa %s (age %u)", + __PRETTY_FUNCTION__, lsa->name, + ntohs(lsa->header->age)); + + ospf6_send_lsupdate(on, NULL, oh); + + return 0; +} + int ospf6_lsupdate_send_interface(struct thread *thread) { struct ospf6_interface *oi; diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index bde89f54a6..35d0b0a646 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -189,6 +189,11 @@ static void ospf6_neighbor_state_change(u_char next_state, OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(on->ospf6_if); } OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area); + + if (prev_state == OSPF6_NEIGHBOR_LOADING && + next_state == OSPF6_NEIGHBOR_FULL) { + OSPF6_AS_EXTERN_LSA_SCHEDULE(on->ospf6_if); + } } if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 749873bcf8..db39420548 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -180,6 +180,8 @@ void ospf6_delete(struct ospf6 *o) struct ospf6_area *oa; QOBJ_UNREG(o); + + ospf6_flush_self_originated_lsas_now(); ospf6_disable(ospf6); for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index b39c25ba84..8f99cc33f4 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -94,6 +94,10 @@ struct ospf6 { struct route_table *distance_table; + /* Used during ospf instance going down send LSDB + * update to neighbors immediatly */ + uint8_t inst_shutdown; + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(ospf6)