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;
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,
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);
/* 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)
{
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 */
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 */
"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;
}
}
}
-
DEFUN (debug_ospf6_flooding,
debug_ospf6_flooding_cmd,
"debug ospf6 flooding",
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 */
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 *
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);
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;
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); \
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,
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);
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. */
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 */
}
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);
/*
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;
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
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))
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)