summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ospf6d/ospf6_asbr.c26
-rw-r--r--ospf6d/ospf6_flood.c74
-rw-r--r--ospf6d/ospf6_flood.h5
-rw-r--r--ospf6d/ospf6_interface.c2
-rw-r--r--ospf6d/ospf6_interface.h1
-rw-r--r--ospf6d/ospf6_intra.h17
-rw-r--r--ospf6d/ospf6_lsa.c31
-rw-r--r--ospf6d/ospf6_lsa.h1
-rw-r--r--ospf6d/ospf6_lsdb.c1
-rw-r--r--ospf6d/ospf6_message.c34
-rw-r--r--ospf6d/ospf6_neighbor.c5
-rw-r--r--ospf6d/ospf6_top.c2
-rw-r--r--ospf6d/ospf6_top.h4
13 files changed, 187 insertions, 16 deletions
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)