diff options
Diffstat (limited to 'ospf6d/ospf6_flood.c')
| -rw-r--r-- | ospf6d/ospf6_flood.c | 1727 |
1 files changed, 845 insertions, 882 deletions
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index f816c6f48d..42716fbc7f 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -43,963 +43,933 @@ unsigned char conf_debug_ospf6_flooding; -struct ospf6_lsdb * -ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa) +struct ospf6_lsdb *ospf6_get_scoped_lsdb(struct ospf6_lsa *lsa) { - struct ospf6_lsdb *lsdb = NULL; - switch (OSPF6_LSA_SCOPE (lsa->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb; - break; - case OSPF6_SCOPE_AREA: - lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb; - break; - case OSPF6_SCOPE_AS: - lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb; - break; - default: - assert (0); - break; - } - return lsdb; + struct ospf6_lsdb *lsdb = NULL; + switch (OSPF6_LSA_SCOPE(lsa->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + lsdb = OSPF6_INTERFACE(lsa->lsdb->data)->lsdb; + break; + case OSPF6_SCOPE_AREA: + lsdb = OSPF6_AREA(lsa->lsdb->data)->lsdb; + break; + case OSPF6_SCOPE_AS: + lsdb = OSPF6_PROCESS(lsa->lsdb->data)->lsdb; + break; + default: + assert(0); + break; + } + return lsdb; } -struct ospf6_lsdb * -ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa) +struct ospf6_lsdb *ospf6_get_scoped_lsdb_self(struct ospf6_lsa *lsa) { - struct ospf6_lsdb *lsdb_self = NULL; - switch (OSPF6_LSA_SCOPE (lsa->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self; - break; - case OSPF6_SCOPE_AREA: - lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self; - break; - case OSPF6_SCOPE_AS: - lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self; - break; - default: - assert (0); - break; - } - return lsdb_self; + struct ospf6_lsdb *lsdb_self = NULL; + switch (OSPF6_LSA_SCOPE(lsa->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + lsdb_self = OSPF6_INTERFACE(lsa->lsdb->data)->lsdb_self; + break; + case OSPF6_SCOPE_AREA: + lsdb_self = OSPF6_AREA(lsa->lsdb->data)->lsdb_self; + break; + case OSPF6_SCOPE_AS: + lsdb_self = OSPF6_PROCESS(lsa->lsdb->data)->lsdb_self; + break; + default: + assert(0); + break; + } + return lsdb_self; } -void -ospf6_lsa_originate (struct ospf6_lsa *lsa) +void ospf6_lsa_originate(struct ospf6_lsa *lsa) { - struct ospf6_lsa *old; - struct ospf6_lsdb *lsdb_self; - - /* find previous LSA */ - old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsa->lsdb); - - /* if the new LSA does not differ from previous, - suppress this update of the LSA */ - if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old)) - { - if (IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type)) - zlog_debug ("Suppress updating LSA: %s", lsa->name); - ospf6_lsa_delete (lsa); - return; - } - - /* store it in the LSDB for self-originated LSAs */ - lsdb_self = ospf6_get_scoped_lsdb_self (lsa); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self); - - lsa->refresh = NULL; - thread_add_timer(master, ospf6_lsa_refresh, lsa, OSPF_LS_REFRESH_TIME, - &lsa->refresh); - - if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) || - IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type)) - { - zlog_debug ("LSA Originate:"); - ospf6_lsa_header_print (lsa); - } - - ospf6_install_lsa (lsa); - ospf6_flood (NULL, lsa); + struct ospf6_lsa *old; + struct ospf6_lsdb *lsdb_self; + + /* find previous LSA */ + old = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsa->lsdb); + + /* if the new LSA does not differ from previous, + suppress this update of the LSA */ + if (old && !OSPF6_LSA_IS_DIFFER(lsa, old)) { + if (IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type)) + zlog_debug("Suppress updating LSA: %s", lsa->name); + ospf6_lsa_delete(lsa); + return; + } + + /* store it in the LSDB for self-originated LSAs */ + lsdb_self = ospf6_get_scoped_lsdb_self(lsa); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), lsdb_self); + + lsa->refresh = NULL; + thread_add_timer(master, ospf6_lsa_refresh, lsa, OSPF_LS_REFRESH_TIME, + &lsa->refresh); + + if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type) + || IS_OSPF6_DEBUG_ORIGINATE_TYPE(lsa->header->type)) { + zlog_debug("LSA Originate:"); + ospf6_lsa_header_print(lsa); + } + + ospf6_install_lsa(lsa); + ospf6_flood(NULL, lsa); } -void -ospf6_lsa_originate_process (struct ospf6_lsa *lsa, - struct ospf6 *process) +void ospf6_lsa_originate_process(struct ospf6_lsa *lsa, struct ospf6 *process) { - lsa->lsdb = process->lsdb; - ospf6_lsa_originate (lsa); + lsa->lsdb = process->lsdb; + ospf6_lsa_originate(lsa); } -void -ospf6_lsa_originate_area (struct ospf6_lsa *lsa, - struct ospf6_area *oa) +void ospf6_lsa_originate_area(struct ospf6_lsa *lsa, struct ospf6_area *oa) { - lsa->lsdb = oa->lsdb; - ospf6_lsa_originate (lsa); + lsa->lsdb = oa->lsdb; + ospf6_lsa_originate(lsa); } -void -ospf6_lsa_originate_interface (struct ospf6_lsa *lsa, - struct ospf6_interface *oi) +void ospf6_lsa_originate_interface(struct ospf6_lsa *lsa, + struct ospf6_interface *oi) { - lsa->lsdb = oi->lsdb; - ospf6_lsa_originate (lsa); + lsa->lsdb = oi->lsdb; + ospf6_lsa_originate(lsa); } -void -ospf6_lsa_purge (struct ospf6_lsa *lsa) +void ospf6_lsa_purge(struct ospf6_lsa *lsa) { - struct ospf6_lsa *self; - struct ospf6_lsdb *lsdb_self; - - /* remove it from the LSDB for self-originated LSAs */ - lsdb_self = ospf6_get_scoped_lsdb_self (lsa); - self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsdb_self); - if (self) - { - THREAD_OFF (self->expire); - THREAD_OFF (self->refresh); - ospf6_lsdb_remove (self, lsdb_self); - } - - ospf6_lsa_premature_aging (lsa); + struct ospf6_lsa *self; + struct ospf6_lsdb *lsdb_self; + + /* remove it from the LSDB for self-originated LSAs */ + lsdb_self = ospf6_get_scoped_lsdb_self(lsa); + self = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsdb_self); + if (self) { + THREAD_OFF(self->expire); + THREAD_OFF(self->refresh); + ospf6_lsdb_remove(self, lsdb_self); + } + + ospf6_lsa_premature_aging(lsa); } -void -ospf6_increment_retrans_count (struct ospf6_lsa *lsa) +void ospf6_increment_retrans_count(struct ospf6_lsa *lsa) { - /* The LSA must be the original one (see the description - in ospf6_decrement_retrans_count () below) */ - lsa->retrans_count++; + /* The LSA must be the original one (see the description + in ospf6_decrement_retrans_count () below) */ + lsa->retrans_count++; } -void -ospf6_decrement_retrans_count (struct ospf6_lsa *lsa) +void ospf6_decrement_retrans_count(struct ospf6_lsa *lsa) { - struct ospf6_lsdb *lsdb; - struct ospf6_lsa *orig; - - /* The LSA must be on the retrans-list of a neighbor. It means - the "lsa" is a copied one, and we have to decrement the - retransmission count of the original one (instead of this "lsa"'s). - In order to find the original LSA, first we have to find - appropriate LSDB that have the original LSA. */ - lsdb = ospf6_get_scoped_lsdb (lsa); - - /* Find the original LSA of which the retrans_count should be decremented */ - orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsdb); - if (orig) - { - orig->retrans_count--; - assert (orig->retrans_count >= 0); - } + struct ospf6_lsdb *lsdb; + struct ospf6_lsa *orig; + + /* The LSA must be on the retrans-list of a neighbor. It means + the "lsa" is a copied one, and we have to decrement the + retransmission count of the original one (instead of this "lsa"'s). + In order to find the original LSA, first we have to find + appropriate LSDB that have the original LSA. */ + lsdb = ospf6_get_scoped_lsdb(lsa); + + /* Find the original LSA of which the retrans_count should be + * decremented */ + orig = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsdb); + if (orig) { + orig->retrans_count--; + assert(orig->retrans_count >= 0); + } } /* RFC2328 section 13.2 Installing LSAs in the database */ -void -ospf6_install_lsa (struct ospf6_lsa *lsa) +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, - lsa->header->adv_router, lsa->lsdb); - if (old) - { - THREAD_OFF (old->expire); - THREAD_OFF (old->refresh); - ospf6_flood_clear (old); - } - - monotime(&now); - if (! OSPF6_LSA_IS_MAXAGE (lsa)) { - lsa->expire = NULL; - thread_add_timer(master, ospf6_lsa_expire, lsa, OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec, - &lsa->expire); - } - else - lsa->expire = NULL; - - if (OSPF6_LSA_IS_SEQWRAP(lsa) && - ! (CHECK_FLAG(lsa->flag,OSPF6_LSA_SEQWRAPPED) && - lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))) - { - if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type)) - zlog_debug("lsa install wrapping: sequence 0x%x", - ntohl(lsa->header->seqnum)); - SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); - /* in lieu of premature_aging, since we do not want to recreate this lsa - * and/or mess with timers etc, we just want to wrap the sequence number - * and reflood the lsa before continuing. - * NOTE: Flood needs to be called right after this function call, by the - * caller - */ - lsa->header->seqnum = htonl (OSPF_MAX_SEQUENCE_NUMBER); - lsa->header->age = htons (OSPF_LSA_MAXAGE); - ospf6_lsa_checksum (lsa->header); - } - - /* actually install */ - lsa->installed = now; - ospf6_lsdb_add (lsa, lsa->lsdb); - - return; + 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, + lsa->header->adv_router, lsa->lsdb); + if (old) { + THREAD_OFF(old->expire); + THREAD_OFF(old->refresh); + ospf6_flood_clear(old); + } + + monotime(&now); + if (!OSPF6_LSA_IS_MAXAGE(lsa)) { + lsa->expire = NULL; + thread_add_timer(master, ospf6_lsa_expire, lsa, + OSPF_LSA_MAXAGE + lsa->birth.tv_sec + - now.tv_sec, + &lsa->expire); + } else + lsa->expire = NULL; + + if (OSPF6_LSA_IS_SEQWRAP(lsa) + && !(CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED) + && lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))) { + if (IS_OSPF6_DEBUG_EXAMIN_TYPE(lsa->header->type)) + zlog_debug("lsa install wrapping: sequence 0x%x", + ntohl(lsa->header->seqnum)); + SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED); + /* in lieu of premature_aging, since we do not want to recreate + * this lsa + * and/or mess with timers etc, we just want to wrap the + * sequence number + * and reflood the lsa before continuing. + * NOTE: Flood needs to be called right after this function + * call, by the + * caller + */ + lsa->header->seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER); + lsa->header->age = htons(OSPF_LSA_MAXAGE); + ospf6_lsa_checksum(lsa->header); + } + + /* actually install */ + lsa->installed = now; + ospf6_lsdb_add(lsa, lsa->lsdb); + + return; } /* 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, - struct ospf6_lsa *lsa, struct ospf6_interface *oi) +static void ospf6_flood_interface(struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, + struct ospf6_interface *oi) { - struct listnode *node, *nnode; - struct ospf6_neighbor *on; - struct ospf6_lsa *req; - int retrans_added = 0; - int is_debug = 0; - - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - { - is_debug++; - zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); - } - - /* (1) For each neighbor */ - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - if (is_debug) - zlog_debug ("To neighbor %s", on->name); - - /* (a) if neighbor state < Exchange, examin next */ - if (on->state < OSPF6_NEIGHBOR_EXCHANGE) - { - if (is_debug) - zlog_debug ("Neighbor state less than ExChange, next neighbor"); - continue; - } - - /* (b) if neighbor not yet Full, check request-list */ - if (on->state != OSPF6_NEIGHBOR_FULL) - { - if (is_debug) - zlog_debug ("Neighbor not yet Full"); - - req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, on->request_list); - if (req == NULL) - { - if (is_debug) - zlog_debug ("Not on request-list for this neighbor"); - /* fall through */ - } - else - { - /* If new LSA less recent, examin next neighbor */ - if (ospf6_lsa_compare (lsa, req) > 0) - { - if (is_debug) - zlog_debug ("Requesting is older, next neighbor"); - continue; - } - - /* If the same instance, delete from request-list and - examin next neighbor */ - if (ospf6_lsa_compare (lsa, req) == 0) - { - if (is_debug) - zlog_debug ("Requesting the same, remove it, next neighbor"); - if (req == on->last_ls_req) - { - ospf6_lsa_unlock (req); - on->last_ls_req = NULL; - } - ospf6_lsdb_remove (req, on->request_list); - ospf6_check_nbr_loading (on); - continue; - } - - /* If the new LSA is more recent, delete from request-list */ - if (ospf6_lsa_compare (lsa, req) < 0) - { - if (is_debug) - zlog_debug ("Received is newer, remove requesting"); - if (req == on->last_ls_req) - { - ospf6_lsa_unlock (req); - on->last_ls_req = NULL; - } - ospf6_lsdb_remove (req, on->request_list); - ospf6_check_nbr_loading (on); - /* fall through */ - } - } - } - - /* (c) If the new LSA was received from this neighbor, - examin next neighbor */ - if (from == on) - { - if (is_debug) - zlog_debug ("Received is from the neighbor, next neighbor"); - 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++; - } - - /* (2) examin next interface if not added to retrans-list */ - if (retrans_added == 0) - { - if (is_debug) - zlog_debug ("No retransmission scheduled, next interface"); - return; - } - - /* (3) If the new LSA was received on this interface, - and it was from DR or BDR, examin next interface */ - if (from && from->ospf6_if == oi && - (from->router_id == oi->drouter || from->router_id == oi->bdrouter)) - { - if (is_debug) - zlog_debug ("Received is from the I/F's DR or BDR, next interface"); - return; - } - - /* (4) If the new LSA was received on this interface, - and the interface state is BDR, examin next interface */ - if (from && from->ospf6_if == oi) - { - if (oi->state == OSPF6_INTERFACE_BDR) - { - if (is_debug) - zlog_debug ("Received is from the I/F, itself BDR, next interface"); - return; + struct listnode *node, *nnode; + struct ospf6_neighbor *on; + struct ospf6_lsa *req; + int retrans_added = 0; + int is_debug = 0; + + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) { + is_debug++; + zlog_debug("Flooding on %s: %s", oi->interface->name, + lsa->name); + } + + /* (1) For each neighbor */ + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + if (is_debug) + zlog_debug("To neighbor %s", on->name); + + /* (a) if neighbor state < Exchange, examin next */ + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { + if (is_debug) + zlog_debug( + "Neighbor state less than ExChange, next neighbor"); + continue; + } + + /* (b) if neighbor not yet Full, check request-list */ + if (on->state != OSPF6_NEIGHBOR_FULL) { + if (is_debug) + zlog_debug("Neighbor not yet Full"); + + req = ospf6_lsdb_lookup( + lsa->header->type, lsa->header->id, + lsa->header->adv_router, on->request_list); + if (req == NULL) { + if (is_debug) + zlog_debug( + "Not on request-list for this neighbor"); + /* fall through */ + } else { + /* If new LSA less recent, examin next neighbor + */ + if (ospf6_lsa_compare(lsa, req) > 0) { + if (is_debug) + zlog_debug( + "Requesting is older, next neighbor"); + continue; + } + + /* If the same instance, delete from + request-list and + examin next neighbor */ + if (ospf6_lsa_compare(lsa, req) == 0) { + if (is_debug) + zlog_debug( + "Requesting the same, remove it, next neighbor"); + if (req == on->last_ls_req) { + ospf6_lsa_unlock(req); + on->last_ls_req = NULL; + } + ospf6_lsdb_remove(req, + on->request_list); + ospf6_check_nbr_loading(on); + continue; + } + + /* If the new LSA is more recent, delete from + * request-list */ + if (ospf6_lsa_compare(lsa, req) < 0) { + if (is_debug) + zlog_debug( + "Received is newer, remove requesting"); + if (req == on->last_ls_req) { + ospf6_lsa_unlock(req); + on->last_ls_req = NULL; + } + ospf6_lsdb_remove(req, + on->request_list); + ospf6_check_nbr_loading(on); + /* fall through */ + } + } + } + + /* (c) If the new LSA was received from this neighbor, + examin next neighbor */ + if (from == on) { + if (is_debug) + zlog_debug( + "Received is from the neighbor, next neighbor"); + 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++; + } + + /* (2) examin next interface if not added to retrans-list */ + if (retrans_added == 0) { + if (is_debug) + zlog_debug( + "No retransmission scheduled, next interface"); + return; + } + + /* (3) If the new LSA was received on this interface, + and it was from DR or BDR, examin next interface */ + if (from && from->ospf6_if == oi + && (from->router_id == oi->drouter + || from->router_id == oi->bdrouter)) { + if (is_debug) + zlog_debug( + "Received is from the I/F's DR or BDR, next interface"); + return; + } + + /* (4) If the new LSA was received on this interface, + and the interface state is BDR, examin next interface */ + if (from && from->ospf6_if == oi) { + if (oi->state == OSPF6_INTERFACE_BDR) { + if (is_debug) + zlog_debug( + "Received is from the I/F, itself BDR, next interface"); + return; + } + SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK); + } + + /* (5) flood the LSA out the interface. */ + if (is_debug) + zlog_debug("Schedule flooding for the interface"); + if ((oi->type == OSPF_IFTYPE_BROADCAST) + || (oi->type == OSPF_IFTYPE_POINTOPOINT)) { + ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsupdate_list); + thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, + &oi->thread_send_lsupdate); + } else { + /* reschedule retransmissions to all neighbors */ + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + THREAD_OFF(on->thread_send_lsupdate); + on->thread_send_lsupdate = NULL; + thread_add_event(master, ospf6_lsupdate_send_neighbor, + on, 0, &on->thread_send_lsupdate); + } } - SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK); - } - - /* (5) flood the LSA out the interface. */ - if (is_debug) - zlog_debug ("Schedule flooding for the interface"); - if ((oi->type == OSPF_IFTYPE_BROADCAST) || - (oi->type == OSPF_IFTYPE_POINTOPOINT)) - { - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); - thread_add_event(master, ospf6_lsupdate_send_interface, oi, 0, - &oi->thread_send_lsupdate); - } - else - { - /* reschedule retransmissions to all neighbors */ - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - THREAD_OFF (on->thread_send_lsupdate); - on->thread_send_lsupdate = NULL; - thread_add_event(master, ospf6_lsupdate_send_neighbor, on, 0, - &on->thread_send_lsupdate); - } - } } -void -ospf6_flood_area (struct ospf6_neighbor *from, - struct ospf6_lsa *lsa, struct ospf6_area *oa) +void ospf6_flood_area(struct ospf6_neighbor *from, struct ospf6_lsa *lsa, + struct ospf6_area *oa) { - struct listnode *node, *nnode; - struct ospf6_interface *oi; + struct listnode *node, *nnode; + struct ospf6_interface *oi; - for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) - { - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && - oi != OSPF6_INTERFACE (lsa->lsdb->data)) - continue; + for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL + && oi != OSPF6_INTERFACE(lsa->lsdb->data)) + continue; #if 0 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && ospf6_is_interface_virtual_link (oi)) continue; -#endif/*0*/ +#endif /*0*/ - ospf6_flood_interface (from, lsa, oi); - } + ospf6_flood_interface(from, lsa, oi); + } } -static void -ospf6_flood_process (struct ospf6_neighbor *from, - struct ospf6_lsa *lsa, struct ospf6 *process) +static void ospf6_flood_process(struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, struct ospf6 *process) { - struct listnode *node, *nnode; - struct ospf6_area *oa; - - for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa)) - { - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA && - oa != OSPF6_AREA (lsa->lsdb->data)) - continue; - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && - oa != OSPF6_INTERFACE (lsa->lsdb->data)->area) - continue; - - if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && - IS_AREA_STUB (oa)) - continue; - - ospf6_flood_area (from, lsa, oa); - } + struct listnode *node, *nnode; + struct ospf6_area *oa; + + for (ALL_LIST_ELEMENTS(process->area_list, node, nnode, oa)) { + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_AREA + && oa != OSPF6_AREA(lsa->lsdb->data)) + continue; + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL + && oa != OSPF6_INTERFACE(lsa->lsdb->data)->area) + continue; + + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL + && IS_AREA_STUB(oa)) + continue; + + ospf6_flood_area(from, lsa, oa); + } } -void -ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa) +void ospf6_flood(struct ospf6_neighbor *from, struct ospf6_lsa *lsa) { - ospf6_flood_process (from, lsa, ospf6); + ospf6_flood_process(from, lsa, ospf6); } -static void -ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi) +static void ospf6_flood_clear_interface(struct ospf6_lsa *lsa, + struct ospf6_interface *oi) { - struct listnode *node, *nnode; - struct ospf6_neighbor *on; - struct ospf6_lsa *rem; - - for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) - { - rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, on->retrans_list); - if (rem && ! ospf6_lsa_compare (rem, lsa)) - { - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - zlog_debug ("Remove %s from retrans_list of %s", - rem->name, on->name); - ospf6_decrement_retrans_count (rem); - ospf6_lsdb_remove (rem, on->retrans_list); - } - } + struct listnode *node, *nnode; + struct ospf6_neighbor *on; + struct ospf6_lsa *rem; + + for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { + rem = ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, + on->retrans_list); + if (rem && !ospf6_lsa_compare(rem, lsa)) { + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) + zlog_debug("Remove %s from retrans_list of %s", + rem->name, on->name); + ospf6_decrement_retrans_count(rem); + ospf6_lsdb_remove(rem, on->retrans_list); + } + } } -static void -ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa) +static void ospf6_flood_clear_area(struct ospf6_lsa *lsa, struct ospf6_area *oa) { - struct listnode *node, *nnode; - struct ospf6_interface *oi; + struct listnode *node, *nnode; + struct ospf6_interface *oi; - for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi)) - { - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && - oi != OSPF6_INTERFACE (lsa->lsdb->data)) - continue; + for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL + && oi != OSPF6_INTERFACE(lsa->lsdb->data)) + continue; #if 0 if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && ospf6_is_interface_virtual_link (oi)) continue; -#endif/*0*/ +#endif /*0*/ - ospf6_flood_clear_interface (lsa, oi); - } + ospf6_flood_clear_interface(lsa, oi); + } } -static void -ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process) +static void ospf6_flood_clear_process(struct ospf6_lsa *lsa, + struct ospf6 *process) { - struct listnode *node, *nnode; - struct ospf6_area *oa; - - for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa)) - { - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA && - oa != OSPF6_AREA (lsa->lsdb->data)) - continue; - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL && - oa != OSPF6_INTERFACE (lsa->lsdb->data)->area) - continue; - - if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL && - IS_AREA_STUB (oa)) - continue; - - ospf6_flood_clear_area (lsa, oa); - } + struct listnode *node, *nnode; + struct ospf6_area *oa; + + for (ALL_LIST_ELEMENTS(process->area_list, node, nnode, oa)) { + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_AREA + && oa != OSPF6_AREA(lsa->lsdb->data)) + continue; + if (OSPF6_LSA_SCOPE(lsa->header->type) == OSPF6_SCOPE_LINKLOCAL + && oa != OSPF6_INTERFACE(lsa->lsdb->data)->area) + continue; + + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL + && IS_AREA_STUB(oa)) + continue; + + ospf6_flood_clear_area(lsa, oa); + } } -void -ospf6_flood_clear (struct ospf6_lsa *lsa) +void ospf6_flood_clear(struct ospf6_lsa *lsa) { - ospf6_flood_clear_process (lsa, ospf6); + ospf6_flood_clear_process(lsa, ospf6); } /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */ -static void -ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent, - struct ospf6_neighbor *from) +static void ospf6_acknowledge_lsa_bdrouter(struct ospf6_lsa *lsa, + int ismore_recent, + struct ospf6_neighbor *from) { - struct ospf6_interface *oi; - int is_debug = 0; - - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - is_debug++; - - assert (from && from->ospf6_if); - oi = from->ospf6_if; - - /* LSA is more recent than database copy, but was not flooded - back out receiving interface. Delayed acknowledgement sent - if advertisement received from Designated Router, - otherwide do nothing. */ - if (ismore_recent < 0) - { - if (oi->drouter == from->router_id) - { - if (is_debug) - zlog_debug ("Delayed acknowledgement (BDR & MoreRecent & from DR)"); - /* Delayed acknowledgement */ - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); - thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, - &oi->thread_send_lsack); - } - else - { - if (is_debug) - zlog_debug ("No acknowledgement (BDR & MoreRecent & ! from DR)"); - } - return; - } - - /* LSA is a duplicate, and was treated as an implied acknowledgement. - Delayed acknowledgement sent if advertisement received from - Designated Router, otherwise do nothing */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && - CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) - { - if (oi->drouter == from->router_id) - { - if (is_debug) - zlog_debug ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)"); - /* Delayed acknowledgement */ - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); - thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, - &oi->thread_send_lsack); - } - else - { - if (is_debug) - zlog_debug ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)"); - } - return; - } - - /* LSA is a duplicate, and was not treated as an implied acknowledgement. - Direct acknowledgement sent */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && - ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) - { - if (is_debug) - zlog_debug ("Direct acknowledgement (BDR & Duplicate)"); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); - thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, - &from->thread_send_lsack); - return; - } - - /* LSA's LS age is equal to Maxage, and there is no current instance - of the LSA in the link state database, and none of router's - neighbors are in states Exchange or Loading */ - /* Direct acknowledgement sent, but this case is handled in - early of ospf6_receive_lsa () */ + struct ospf6_interface *oi; + int is_debug = 0; + + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) + is_debug++; + + assert(from && from->ospf6_if); + oi = from->ospf6_if; + + /* LSA is more recent than database copy, but was not flooded + back out receiving interface. Delayed acknowledgement sent + if advertisement received from Designated Router, + otherwide do nothing. */ + if (ismore_recent < 0) { + if (oi->drouter == from->router_id) { + if (is_debug) + zlog_debug( + "Delayed acknowledgement (BDR & MoreRecent & from DR)"); + /* Delayed acknowledgement */ + ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list); + thread_add_timer(master, ospf6_lsack_send_interface, oi, + 3, &oi->thread_send_lsack); + } else { + if (is_debug) + zlog_debug( + "No acknowledgement (BDR & MoreRecent & ! from DR)"); + } + return; + } + + /* LSA is a duplicate, and was treated as an implied acknowledgement. + Delayed acknowledgement sent if advertisement received from + Designated Router, otherwise do nothing */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE) + && CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) { + if (oi->drouter == from->router_id) { + if (is_debug) + zlog_debug( + "Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)"); + /* Delayed acknowledgement */ + ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list); + thread_add_timer(master, ospf6_lsack_send_interface, oi, + 3, &oi->thread_send_lsack); + } else { + if (is_debug) + zlog_debug( + "No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)"); + } + return; + } + + /* LSA is a duplicate, and was not treated as an implied + acknowledgement. + Direct acknowledgement sent */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE) + && !CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) { + if (is_debug) + zlog_debug("Direct acknowledgement (BDR & Duplicate)"); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), from->lsack_list); + thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, + &from->thread_send_lsack); + return; + } + + /* LSA's LS age is equal to Maxage, and there is no current instance + of the LSA in the link state database, and none of router's + neighbors are in states Exchange or Loading */ + /* Direct acknowledgement sent, but this case is handled in + early of ospf6_receive_lsa () */ } -static void -ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, - struct ospf6_neighbor *from) +static void ospf6_acknowledge_lsa_allother(struct ospf6_lsa *lsa, + int ismore_recent, + struct ospf6_neighbor *from) { - struct ospf6_interface *oi; - int is_debug = 0; - - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - is_debug++; - - assert (from && from->ospf6_if); - oi = from->ospf6_if; - - /* LSA has been flood back out receiving interface. - No acknowledgement sent. */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK)) - { - if (is_debug) - zlog_debug ("No acknowledgement (AllOther & FloodBack)"); - return; - } - - /* LSA is more recent than database copy, but was not flooded - back out receiving interface. Delayed acknowledgement sent. */ - if (ismore_recent < 0) - { - if (is_debug) - zlog_debug ("Delayed acknowledgement (AllOther & MoreRecent)"); - /* Delayed acknowledgement */ - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); - thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, - &oi->thread_send_lsack); - return; - } - - /* LSA is a duplicate, and was treated as an implied acknowledgement. - No acknowledgement sent. */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && - CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) - { - if (is_debug) - zlog_debug ("No acknowledgement (AllOther & Duplicate & ImpliedAck)"); - return; - } - - /* LSA is a duplicate, and was not treated as an implied acknowledgement. - Direct acknowledgement sent */ - if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && - ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) - { - if (is_debug) - zlog_debug ("Direct acknowledgement (AllOther & Duplicate)"); - ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); - thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, - &from->thread_send_lsack); - return; - } - - /* LSA's LS age is equal to Maxage, and there is no current instance - of the LSA in the link state database, and none of router's - neighbors are in states Exchange or Loading */ - /* Direct acknowledgement sent, but this case is handled in - early of ospf6_receive_lsa () */ + struct ospf6_interface *oi; + int is_debug = 0; + + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(lsa->header->type)) + is_debug++; + + assert(from && from->ospf6_if); + oi = from->ospf6_if; + + /* LSA has been flood back out receiving interface. + No acknowledgement sent. */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK)) { + if (is_debug) + zlog_debug("No acknowledgement (AllOther & FloodBack)"); + return; + } + + /* LSA is more recent than database copy, but was not flooded + back out receiving interface. Delayed acknowledgement sent. */ + if (ismore_recent < 0) { + if (is_debug) + zlog_debug( + "Delayed acknowledgement (AllOther & MoreRecent)"); + /* Delayed acknowledgement */ + ospf6_lsdb_add(ospf6_lsa_copy(lsa), oi->lsack_list); + thread_add_timer(master, ospf6_lsack_send_interface, oi, 3, + &oi->thread_send_lsack); + return; + } + + /* LSA is a duplicate, and was treated as an implied acknowledgement. + No acknowledgement sent. */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE) + && CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) { + if (is_debug) + zlog_debug( + "No acknowledgement (AllOther & Duplicate & ImpliedAck)"); + return; + } + + /* LSA is a duplicate, and was not treated as an implied + acknowledgement. + Direct acknowledgement sent */ + if (CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE) + && !CHECK_FLAG(lsa->flag, OSPF6_LSA_IMPLIEDACK)) { + if (is_debug) + zlog_debug( + "Direct acknowledgement (AllOther & Duplicate)"); + ospf6_lsdb_add(ospf6_lsa_copy(lsa), from->lsack_list); + thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, + &from->thread_send_lsack); + return; + } + + /* LSA's LS age is equal to Maxage, and there is no current instance + of the LSA in the link state database, and none of router's + neighbors are in states Exchange or Loading */ + /* Direct acknowledgement sent, but this case is handled in + early of ospf6_receive_lsa () */ } -static void -ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent, - struct ospf6_neighbor *from) +static void ospf6_acknowledge_lsa(struct ospf6_lsa *lsa, int ismore_recent, + struct ospf6_neighbor *from) { - struct ospf6_interface *oi; + struct ospf6_interface *oi; - assert (from && from->ospf6_if); - oi = from->ospf6_if; + assert(from && from->ospf6_if); + oi = from->ospf6_if; - if (oi->state == OSPF6_INTERFACE_BDR) - ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from); - else - ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from); + if (oi->state == OSPF6_INTERFACE_BDR) + ospf6_acknowledge_lsa_bdrouter(lsa, ismore_recent, from); + else + ospf6_acknowledge_lsa_allother(lsa, ismore_recent, from); } /* RFC2328 section 13 (4): if MaxAge LSA and if we have no instance, and no neighbor is in states Exchange or Loading returns 1 if match this case, else returns 0 */ -static int -ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from) +static int ospf6_is_maxage_lsa_drop(struct ospf6_lsa *lsa, + struct ospf6_neighbor *from) { - struct ospf6_neighbor *on; - struct ospf6_interface *oi; - struct ospf6_area *oa; - struct ospf6 *process = NULL; - struct listnode *i, *j, *k; - int count = 0; - - if (! OSPF6_LSA_IS_MAXAGE (lsa)) - return 0; - - if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, - lsa->header->adv_router, lsa->lsdb)) - return 0; - - process = from->ospf6_if->area->ospf6; - - for (ALL_LIST_ELEMENTS_RO (process->area_list, i, oa)) - for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi)) - for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on)) - if (on->state == OSPF6_NEIGHBOR_EXCHANGE || - on->state == OSPF6_NEIGHBOR_LOADING) - count++; - - if (count == 0) - return 1; - return 0; + struct ospf6_neighbor *on; + struct ospf6_interface *oi; + struct ospf6_area *oa; + struct ospf6 *process = NULL; + struct listnode *i, *j, *k; + int count = 0; + + if (!OSPF6_LSA_IS_MAXAGE(lsa)) + return 0; + + if (ospf6_lsdb_lookup(lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsa->lsdb)) + return 0; + + process = from->ospf6_if->area->ospf6; + + for (ALL_LIST_ELEMENTS_RO(process->area_list, i, oa)) + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) + if (on->state == OSPF6_NEIGHBOR_EXCHANGE + || on->state == OSPF6_NEIGHBOR_LOADING) + count++; + + if (count == 0) + return 1; + return 0; } /* RFC2328 section 13 The Flooding Procedure */ -void -ospf6_receive_lsa (struct ospf6_neighbor *from, - struct ospf6_lsa_header *lsa_header) +void ospf6_receive_lsa(struct ospf6_neighbor *from, + struct ospf6_lsa_header *lsa_header) { - struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; - int ismore_recent; - int is_debug = 0; - unsigned int time_delta_ms; - - ismore_recent = 1; - assert (from); - - /* make lsa structure for received lsa */ - new = ospf6_lsa_create (lsa_header); - - if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type)) - { - is_debug++; - zlog_debug ("LSA Receive from %s", from->name); - ospf6_lsa_header_print (new); - } - - /* (1) LSA Checksum */ - if (! ospf6_lsa_checksum_valid (new->header)) - { - if (is_debug) - zlog_debug ("Wrong LSA Checksum, discard"); - ospf6_lsa_delete (new); - return; - } - - /* (2) Examine the LSA's LS type. - RFC2470 3.5.1. Receiving Link State Update packets */ - if (IS_AREA_STUB (from->ospf6_if->area) && - OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS) - { - if (is_debug) - zlog_debug ("AS-External-LSA (or AS-scope LSA) in stub area, discard"); - ospf6_lsa_delete (new); - return; - } - - /* (3) LSA which have reserved scope is discarded - RFC2470 3.5.1. Receiving Link State Update packets */ - /* Flooding scope check. LSAs with unknown scope are discarded here. - Set appropriate LSDB for the LSA */ - switch (OSPF6_LSA_SCOPE (new->header->type)) - { - case OSPF6_SCOPE_LINKLOCAL: - new->lsdb = from->ospf6_if->lsdb; - break; - case OSPF6_SCOPE_AREA: - new->lsdb = from->ospf6_if->area->lsdb; - break; - case OSPF6_SCOPE_AS: - new->lsdb = from->ospf6_if->area->ospf6->lsdb; - break; - default: - if (is_debug) - zlog_debug ("LSA has reserved scope, discard"); - ospf6_lsa_delete (new); - return; - } - - /* (4) if MaxAge LSA and if we have no instance, and no neighbor - is in states Exchange or Loading */ - if (ospf6_is_maxage_lsa_drop (new, from)) - { - /* log */ - if (is_debug) - zlog_debug ("Drop MaxAge LSA with direct acknowledgement."); - - /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */ - ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list); - thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, - &from->thread_send_lsack); - - /* b) Discard */ - ospf6_lsa_delete (new); - return; - } - - /* (5) */ - /* lookup the same database copy in lsdb */ - old = ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, new->lsdb); - if (old) - { - ismore_recent = ospf6_lsa_compare (new, old); - if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum)) - { - if (is_debug) - zlog_debug ("Received is duplicated LSA"); - SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE); - } - } - - /* if no database copy or received is more recent */ - if (old == NULL || ismore_recent < 0) - { - /* in case we have no database copy */ - ismore_recent = -1; - - /* (a) MinLSArrival check */ - if (old) - { - struct timeval now, res; - monotime(&now); - timersub (&now, &old->installed, &res); - time_delta_ms = (res.tv_sec * 1000) + (int)(res.tv_usec/1000); - if (time_delta_ms < from->ospf6_if->area->ospf6->lsa_minarrival) - { - if (is_debug) - zlog_debug ("LSA can't be updated within MinLSArrival, %dms < %dms, discard", - time_delta_ms, from->ospf6_if->area->ospf6->lsa_minarrival); - ospf6_lsa_delete (new); - return; /* examin next lsa */ - } - } - - monotime(&new->received); - - if (is_debug) - zlog_debug ("Install, Flood, Possibly acknowledge the received LSA"); - - /* Remove older copies of this LSA from retx lists */ - if (old) - ospf6_flood_clear (old); - - /* (b) immediately flood and (c) remove from all retrans-list */ - /* Prevent self-originated LSA to be flooded. this is to make - reoriginated instance of the LSA not to be rejected by other routers - due to MinLSArrival. */ - if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id) - ospf6_flood (from, new); - - /* (d), installing lsdb, which may cause routing - table calculation (replacing database copy) */ - ospf6_install_lsa (new); - - if (OSPF6_LSA_IS_MAXAGE (new)) - ospf6_maxage_remove (from->ospf6_if->area->ospf6); - - /* (e) possibly acknowledge */ - ospf6_acknowledge_lsa (new, ismore_recent, from); - - /* (f) Self Originated LSA, section 13.4 */ - if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id) - { - /* Self-originated LSA (newer than ours) is received from - another router. We have to make a new instance of the LSA - or have to flush this LSA. */ - if (is_debug) - { - zlog_debug ("Newer instance of the self-originated LSA"); - zlog_debug ("Schedule reorigination"); - } - new->refresh = NULL; - thread_add_event(master, ospf6_lsa_refresh, new, 0, &new->refresh); - } - - return; - } - - /* (6) if there is instance on sending neighbor's request list */ - if (ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, from->request_list)) - { - /* if no database copy, should go above state (5) */ - assert (old); - - if (is_debug) - { - zlog_debug ("Received is not newer, on the neighbor's request-list"); - zlog_debug ("BadLSReq, discard the received LSA"); - } - - /* BadLSReq */ - thread_add_event(master, bad_lsreq, from, 0, NULL); - - ospf6_lsa_delete (new); - return; - } - - /* (7) if neither one is more recent */ - if (ismore_recent == 0) - { - if (is_debug) - zlog_debug ("The same instance as database copy (neither recent)"); - - /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */ - rem = ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, from->retrans_list); - if (rem) - { - if (is_debug) - { - zlog_debug ("It is on the neighbor's retrans-list."); - zlog_debug ("Treat as an Implied acknowledgement"); - } - SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK); - ospf6_decrement_retrans_count (rem); - ospf6_lsdb_remove (rem, from->retrans_list); - } - - if (is_debug) - zlog_debug ("Possibly acknowledge and then discard"); - - /* (b) possibly acknowledge */ - ospf6_acknowledge_lsa (new, ismore_recent, from); - - ospf6_lsa_delete (new); - return; - } - - /* (8) previous database copy is more recent */ - { - assert (old); - - /* If database copy is in 'Seqnumber Wrapping', - simply discard the received LSA */ - if (OSPF6_LSA_IS_MAXAGE (old) && - old->header->seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER)) - { - if (is_debug) - { - zlog_debug ("The LSA is in Seqnumber Wrapping"); - zlog_debug ("MaxAge & MaxSeqNum, discard"); - } - ospf6_lsa_delete (new); - return; - } - - /* Otherwise, Send database copy of this LSA to this neighbor */ - { - if (is_debug) - { - zlog_debug ("Database copy is more recent."); - zlog_debug ("Send back directly and then discard"); - } - - /* 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; - } - return; - } + struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; + int ismore_recent; + int is_debug = 0; + unsigned int time_delta_ms; + + ismore_recent = 1; + assert(from); + + /* make lsa structure for received lsa */ + new = ospf6_lsa_create(lsa_header); + + if (IS_OSPF6_DEBUG_FLOODING + || IS_OSPF6_DEBUG_FLOOD_TYPE(new->header->type)) { + is_debug++; + zlog_debug("LSA Receive from %s", from->name); + ospf6_lsa_header_print(new); + } + + /* (1) LSA Checksum */ + if (!ospf6_lsa_checksum_valid(new->header)) { + if (is_debug) + zlog_debug("Wrong LSA Checksum, discard"); + ospf6_lsa_delete(new); + return; + } + + /* (2) Examine the LSA's LS type. + RFC2470 3.5.1. Receiving Link State Update packets */ + if (IS_AREA_STUB(from->ospf6_if->area) + && OSPF6_LSA_SCOPE(new->header->type) == OSPF6_SCOPE_AS) { + if (is_debug) + zlog_debug( + "AS-External-LSA (or AS-scope LSA) in stub area, discard"); + ospf6_lsa_delete(new); + return; + } + + /* (3) LSA which have reserved scope is discarded + RFC2470 3.5.1. Receiving Link State Update packets */ + /* Flooding scope check. LSAs with unknown scope are discarded here. + Set appropriate LSDB for the LSA */ + switch (OSPF6_LSA_SCOPE(new->header->type)) { + case OSPF6_SCOPE_LINKLOCAL: + new->lsdb = from->ospf6_if->lsdb; + break; + case OSPF6_SCOPE_AREA: + new->lsdb = from->ospf6_if->area->lsdb; + break; + case OSPF6_SCOPE_AS: + new->lsdb = from->ospf6_if->area->ospf6->lsdb; + break; + default: + if (is_debug) + zlog_debug("LSA has reserved scope, discard"); + ospf6_lsa_delete(new); + return; + } + + /* (4) if MaxAge LSA and if we have no instance, and no neighbor + is in states Exchange or Loading */ + if (ospf6_is_maxage_lsa_drop(new, from)) { + /* log */ + if (is_debug) + zlog_debug( + "Drop MaxAge LSA with direct acknowledgement."); + + /* a) Acknowledge back to neighbor (Direct acknowledgement, + * 13.5) */ + ospf6_lsdb_add(ospf6_lsa_copy(new), from->lsack_list); + thread_add_event(master, ospf6_lsack_send_neighbor, from, 0, + &from->thread_send_lsack); + + /* b) Discard */ + ospf6_lsa_delete(new); + return; + } + + /* (5) */ + /* lookup the same database copy in lsdb */ + old = ospf6_lsdb_lookup(new->header->type, new->header->id, + new->header->adv_router, new->lsdb); + if (old) { + ismore_recent = ospf6_lsa_compare(new, old); + if (ntohl(new->header->seqnum) == ntohl(old->header->seqnum)) { + if (is_debug) + zlog_debug("Received is duplicated LSA"); + SET_FLAG(new->flag, OSPF6_LSA_DUPLICATE); + } + } + + /* if no database copy or received is more recent */ + if (old == NULL || ismore_recent < 0) { + /* in case we have no database copy */ + ismore_recent = -1; + + /* (a) MinLSArrival check */ + if (old) { + struct timeval now, res; + monotime(&now); + timersub(&now, &old->installed, &res); + time_delta_ms = + (res.tv_sec * 1000) + (int)(res.tv_usec / 1000); + if (time_delta_ms + < from->ospf6_if->area->ospf6->lsa_minarrival) { + if (is_debug) + zlog_debug( + "LSA can't be updated within MinLSArrival, %dms < %dms, discard", + time_delta_ms, + from->ospf6_if->area->ospf6 + ->lsa_minarrival); + ospf6_lsa_delete(new); + return; /* examin next lsa */ + } + } + + monotime(&new->received); + + if (is_debug) + zlog_debug( + "Install, Flood, Possibly acknowledge the received LSA"); + + /* Remove older copies of this LSA from retx lists */ + if (old) + ospf6_flood_clear(old); + + /* (b) immediately flood and (c) remove from all retrans-list */ + /* Prevent self-originated LSA to be flooded. this is to make + reoriginated instance of the LSA not to be rejected by other + routers + due to MinLSArrival. */ + if (new->header->adv_router + != from->ospf6_if->area->ospf6->router_id) + ospf6_flood(from, new); + + /* (d), installing lsdb, which may cause routing + table calculation (replacing database copy) */ + ospf6_install_lsa(new); + + if (OSPF6_LSA_IS_MAXAGE(new)) + ospf6_maxage_remove(from->ospf6_if->area->ospf6); + + /* (e) possibly acknowledge */ + ospf6_acknowledge_lsa(new, ismore_recent, from); + + /* (f) Self Originated LSA, section 13.4 */ + if (new->header->adv_router + == from->ospf6_if->area->ospf6->router_id) { + /* Self-originated LSA (newer than ours) is received + from + another router. We have to make a new instance of the + LSA + or have to flush this LSA. */ + if (is_debug) { + zlog_debug( + "Newer instance of the self-originated LSA"); + zlog_debug("Schedule reorigination"); + } + new->refresh = NULL; + thread_add_event(master, ospf6_lsa_refresh, new, 0, + &new->refresh); + } + + return; + } + + /* (6) if there is instance on sending neighbor's request list */ + if (ospf6_lsdb_lookup(new->header->type, new->header->id, + new->header->adv_router, from->request_list)) { + /* if no database copy, should go above state (5) */ + assert(old); + + if (is_debug) { + zlog_debug( + "Received is not newer, on the neighbor's request-list"); + zlog_debug("BadLSReq, discard the received LSA"); + } + + /* BadLSReq */ + thread_add_event(master, bad_lsreq, from, 0, NULL); + + ospf6_lsa_delete(new); + return; + } + + /* (7) if neither one is more recent */ + if (ismore_recent == 0) { + if (is_debug) + zlog_debug( + "The same instance as database copy (neither recent)"); + + /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack + */ + rem = ospf6_lsdb_lookup(new->header->type, new->header->id, + new->header->adv_router, + from->retrans_list); + if (rem) { + if (is_debug) { + zlog_debug( + "It is on the neighbor's retrans-list."); + zlog_debug( + "Treat as an Implied acknowledgement"); + } + SET_FLAG(new->flag, OSPF6_LSA_IMPLIEDACK); + ospf6_decrement_retrans_count(rem); + ospf6_lsdb_remove(rem, from->retrans_list); + } + + if (is_debug) + zlog_debug("Possibly acknowledge and then discard"); + + /* (b) possibly acknowledge */ + ospf6_acknowledge_lsa(new, ismore_recent, from); + + ospf6_lsa_delete(new); + return; + } + + /* (8) previous database copy is more recent */ + { + assert(old); + + /* If database copy is in 'Seqnumber Wrapping', + simply discard the received LSA */ + if (OSPF6_LSA_IS_MAXAGE(old) + && old->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)) { + if (is_debug) { + zlog_debug("The LSA is in Seqnumber Wrapping"); + zlog_debug("MaxAge & MaxSeqNum, discard"); + } + ospf6_lsa_delete(new); + return; + } + + /* Otherwise, Send database copy of this LSA to this neighbor */ + { + if (is_debug) { + zlog_debug("Database copy is more recent."); + zlog_debug( + "Send back directly and then discard"); + } + + /* 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; + } + return; + } } @@ -1011,8 +981,8 @@ DEFUN (debug_ospf6_flooding, "Debug OSPFv3 flooding function\n" ) { - OSPF6_DEBUG_FLOODING_ON (); - return CMD_SUCCESS; + OSPF6_DEBUG_FLOODING_ON(); + return CMD_SUCCESS; } DEFUN (no_debug_ospf6_flooding, @@ -1024,28 +994,21 @@ DEFUN (no_debug_ospf6_flooding, "Debug OSPFv3 flooding function\n" ) { - OSPF6_DEBUG_FLOODING_OFF (); - return CMD_SUCCESS; + OSPF6_DEBUG_FLOODING_OFF(); + return CMD_SUCCESS; } -int -config_write_ospf6_debug_flood (struct vty *vty) +int config_write_ospf6_debug_flood(struct vty *vty) { - if (IS_OSPF6_DEBUG_FLOODING) - vty_out (vty, "debug ospf6 flooding\n"); - return 0; + if (IS_OSPF6_DEBUG_FLOODING) + vty_out(vty, "debug ospf6 flooding\n"); + return 0; } -void -install_element_ospf6_debug_flood (void) +void install_element_ospf6_debug_flood(void) { - install_element (ENABLE_NODE, &debug_ospf6_flooding_cmd); - install_element (ENABLE_NODE, &no_debug_ospf6_flooding_cmd); - install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd); - install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd); + install_element(ENABLE_NODE, &debug_ospf6_flooding_cmd); + install_element(ENABLE_NODE, &no_debug_ospf6_flooding_cmd); + install_element(CONFIG_NODE, &debug_ospf6_flooding_cmd); + install_element(CONFIG_NODE, &no_debug_ospf6_flooding_cmd); } - - - - - |
