From 046460a1e0e13476bbf7a8118fb2ee1a71c9e563 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Mon, 6 Nov 2017 18:17:19 -0800 Subject: [PATCH] ospfd: flush self-originated lsa upon restart frr Router-ID change or ospf instance going down, send LS-Upd with MAXAGE to self origintated LSAs to all ospf neighbors. Ticket:CM-1576 Testing Done: Bring R1 - R2, Change Router-ID on R2, restart frr on R2 Validated R1 ospf LSDB for max aged 3600 LSA from R2. Signed-off-by: Chirag Shah --- ospfd/ospf_flood.c | 7 +++-- ospfd/ospf_lsa.c | 2 ++ ospfd/ospf_packet.c | 63 +++++++++++++++++++++++++++++++++++---------- ospfd/ospf_packet.h | 2 +- ospfd/ospfd.c | 3 +-- ospfd/ospfd.h | 4 +++ 6 files changed, 63 insertions(+), 18 deletions(-) diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index aac2f3ee92..facce9aafd 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -361,9 +361,9 @@ static int ospf_flood_through_interface(struct ospf_interface *oi, if (IS_DEBUG_OSPF_EVENT) zlog_debug( "ospf_flood_through_interface(): " - "considering int %s, INBR(%s), LSA[%s]", + "considering int %s, INBR(%s), LSA[%s] AGE %u", IF_NAME(oi), inbr ? inet_ntoa(inbr->router_id) : "NULL", - dump_lsa_key(lsa)); + dump_lsa_key(lsa), ntohs(lsa->data->ls_age)); if (!ospf_if_is_enable(oi)) return 0; @@ -958,6 +958,9 @@ void ospf_lsa_flush_area(struct ospf_lsa *lsa, struct ospf_area *area) more time for the ACK to be received and avoid retransmissions */ lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: MAXAGE set to LSA %s", __PRETTY_FUNCTION__, + inet_ntoa(lsa->data->id)); monotime(&lsa->tv_recv); lsa->tv_orig = lsa->tv_recv; ospf_flood_through_area(area, NULL, lsa); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 4e67694059..fc866df965 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -3302,6 +3302,8 @@ void ospf_flush_self_originated_lsas_now(struct ospf *ospf) struct route_node *rn; int need_to_flush_ase = 0; + ospf->inst_shutdown = 1; + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { if ((lsa = area->router_lsa_self) != NULL) { if (IS_DEBUG_OSPF_EVENT) diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 633c3deeaf..33792bbff3 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -518,7 +518,8 @@ int ospf_ls_upd_timer(struct thread *thread) } if (listcount(update) > 0) - ospf_ls_upd_send(nbr, update, OSPF_SEND_PACKET_DIRECT); + ospf_ls_upd_send(nbr, update, + OSPF_SEND_PACKET_DIRECT, 0); list_delete_and_null(&update); } @@ -1609,10 +1610,10 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh, if (length + ntohs(find->data->length) > ospf_packet_max(oi)) { if (oi->type == OSPF_IFTYPE_NBMA) ospf_ls_upd_send(nbr, ls_upd, - OSPF_SEND_PACKET_DIRECT); + OSPF_SEND_PACKET_DIRECT, 0); else ospf_ls_upd_send(nbr, ls_upd, - OSPF_SEND_PACKET_INDIRECT); + OSPF_SEND_PACKET_INDIRECT, 0); /* Only remove list contents. Keep ls_upd. */ list_delete_all_node(ls_upd); @@ -1630,10 +1631,11 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh, /* Send rest of Link State Update. */ if (listcount(ls_upd) > 0) { if (oi->type == OSPF_IFTYPE_NBMA) - ospf_ls_upd_send(nbr, ls_upd, OSPF_SEND_PACKET_DIRECT); + ospf_ls_upd_send(nbr, ls_upd, + OSPF_SEND_PACKET_DIRECT, 0); else ospf_ls_upd_send(nbr, ls_upd, - OSPF_SEND_PACKET_INDIRECT); + OSPF_SEND_PACKET_INDIRECT, 0); list_delete_and_null(&ls_upd); } else @@ -3792,7 +3794,13 @@ void ospf_ls_upd_send_lsa(struct ospf_neighbor *nbr, struct ospf_lsa *lsa, update = list_new(); listnode_add(update, lsa); - ospf_ls_upd_send(nbr, update, flag); + + /*ospf instance is going down, send self originated + * MAXAGE LSA update to neighbors to remove from LSDB */ + if (nbr->oi->ospf->inst_shutdown && IS_LSA_MAXAGE(lsa)) + ospf_ls_upd_send(nbr, update, flag, 1); + else + ospf_ls_upd_send(nbr, update, flag, 0); list_delete_and_null(&update); } @@ -3875,7 +3883,8 @@ static struct ospf_packet *ospf_ls_upd_packet_new(struct list *update, } static void ospf_ls_upd_queue_send(struct ospf_interface *oi, - struct list *update, struct in_addr addr) + struct list *update, struct in_addr addr, + int send_lsupd_now) { struct ospf_packet *op; u_int16_t length = OSPF_HEADER_SIZE; @@ -3908,9 +3917,20 @@ static void ospf_ls_upd_queue_send(struct ospf_interface *oi, /* Add packet to the interface output queue. */ ospf_packet_add(oi, op); - - /* Hook thread to write packet. */ - OSPF_ISM_WRITE_ON(oi->ospf); + /* Call ospf_write() right away to send ospf packets to neighbors */ + if (send_lsupd_now) { + struct thread os_packet_thd; + + os_packet_thd.arg = (void *)oi->ospf; + if (oi->on_write_q == 0) { + listnode_add(oi->ospf->oi_write_q, oi); + oi->on_write_q = 1; + } + ospf_write(&os_packet_thd); + } else { + /* Hook thread to write packet. */ + OSPF_ISM_WRITE_ON(oi->ospf); + } } static int ospf_ls_upd_send_queue_event(struct thread *thread) @@ -3934,7 +3954,7 @@ static int ospf_ls_upd_send_queue_event(struct thread *thread) update = (struct list *)rn->info; - ospf_ls_upd_queue_send(oi, update, rn->p.u.prefix4); + ospf_ls_upd_queue_send(oi, update, rn->p.u.prefix4, 0); /* list might not be empty. */ if (listcount(update) == 0) { @@ -3961,7 +3981,8 @@ static int ospf_ls_upd_send_queue_event(struct thread *thread) return 0; } -void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag) +void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag, + int send_lsupd_now) { struct ospf_interface *oi; struct ospf_lsa *lsa; @@ -4006,8 +4027,24 @@ void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag) for (ALL_LIST_ELEMENTS_RO(update, node, lsa)) listnode_add(rn->info, ospf_lsa_lock(lsa)); /* oi->ls_upd_queue */ + if (send_lsupd_now) { + struct list *send_update_list; + struct route_node *rn, *rnext; - thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0, + for (rn = route_top(oi->ls_upd_queue); rn; rn = rnext) { + rnext = route_next(rn); + + if (rn->info == NULL) + continue; + + send_update_list = (struct list *)rn->info; + + ospf_ls_upd_queue_send(oi, send_update_list, + rn->p.u.prefix4, 1); + + } + } else + thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0, &oi->t_ls_upd_event); } diff --git a/ospfd/ospf_packet.h b/ospfd/ospf_packet.h index a3617c7bda..78b2b81e50 100644 --- a/ospfd/ospf_packet.h +++ b/ospfd/ospf_packet.h @@ -152,7 +152,7 @@ extern void ospf_db_desc_resend(struct ospf_neighbor *); extern void ospf_ls_req_send(struct ospf_neighbor *); extern void ospf_ls_upd_send_lsa(struct ospf_neighbor *, struct ospf_lsa *, int); -extern void ospf_ls_upd_send(struct ospf_neighbor *, struct list *, int); +extern void ospf_ls_upd_send(struct ospf_neighbor *, struct list *, int, int); extern void ospf_ls_ack_send(struct ospf_neighbor *, struct ospf_lsa *); extern void ospf_ls_ack_send_delayed(struct ospf_interface *); extern void ospf_ls_retransmit(struct ospf_interface *, struct ospf_lsa *); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index b0646495a5..a37867fe23 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -596,8 +596,7 @@ static void ospf_finish_final(struct ospf *ospf) ospf_opaque_type11_lsa_term(ospf); - /* be nice if this worked, but it doesn't */ - /*ospf_flush_self_originated_lsas_now (ospf);*/ + ospf_flush_self_originated_lsas_now(ospf); /* Unregister redistribution */ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index df318cf2c0..6cccccc649 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -310,6 +310,10 @@ struct ospf { 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(ospf) -- 2.39.5