diff options
Diffstat (limited to 'ospfd/ospf_flood.c')
| -rw-r--r-- | ospfd/ospf_flood.c | 1610 |
1 files changed, 798 insertions, 812 deletions
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index ba3d9e3249..c775f2ea2e 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -51,171 +51,177 @@ extern struct zclient *zclient; /* Do the LSA acking specified in table 19, Section 13.5, row 2 - * This get called from ospf_flood_out_interface. Declared inline + * This get called from ospf_flood_out_interface. Declared inline * for speed. */ -static void -ospf_flood_delayed_lsa_ack (struct ospf_neighbor *inbr, struct ospf_lsa *lsa) +static void ospf_flood_delayed_lsa_ack(struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) { - /* LSA is more recent than database copy, but was not - flooded back out receiving interface. Delayed - acknowledgment sent. If interface is in Backup state - delayed acknowledgment sent only if advertisement - received from Designated Router, otherwise do nothing See - RFC 2328 Section 13.5 */ - - /* Whether LSA is more recent or not, and whether this is in - response to the LSA being sent out recieving interface has been - worked out previously */ - - /* Deal with router as BDR */ - if (inbr->oi->state == ISM_Backup && ! NBR_IS_DR (inbr)) - return; - - /* Schedule a delayed LSA Ack to be sent */ - listnode_add (inbr->oi->ls_ack, ospf_lsa_lock (lsa)); /* delayed LSA Ack */ + /* LSA is more recent than database copy, but was not + flooded back out receiving interface. Delayed + acknowledgment sent. If interface is in Backup state + delayed acknowledgment sent only if advertisement + received from Designated Router, otherwise do nothing See + RFC 2328 Section 13.5 */ + + /* Whether LSA is more recent or not, and whether this is in + response to the LSA being sent out recieving interface has been + worked out previously */ + + /* Deal with router as BDR */ + if (inbr->oi->state == ISM_Backup && !NBR_IS_DR(inbr)) + return; + + /* Schedule a delayed LSA Ack to be sent */ + listnode_add(inbr->oi->ls_ack, + ospf_lsa_lock(lsa)); /* delayed LSA Ack */ } /* Check LSA is related to external info. */ -struct external_info * -ospf_external_info_check (struct ospf_lsa *lsa) +struct external_info *ospf_external_info_check(struct ospf_lsa *lsa) { - struct as_external_lsa *al; - struct prefix_ipv4 p; - struct route_node *rn; - int type; - - al = (struct as_external_lsa *) lsa->data; - - p.family = AF_INET; - p.prefix = lsa->data->id; - p.prefixlen = ip_masklen (al->mask); - - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) - { - int redist_on = 0; - - redist_on = is_prefix_default (&p) ? - vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : - (zclient->mi_redist[AFI_IP][type].enabled || - vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT)); - //Pending: check for MI above. - if (redist_on) - { - struct list *ext_list; - struct listnode *node; - struct ospf_external *ext; - - ext_list = om->external[type]; - if (!ext_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) - { - rn = NULL; - if (ext->external_info) - rn = route_node_lookup (ext->external_info, - (struct prefix *) &p); - if (rn) - { - route_unlock_node (rn); - if (rn->info != NULL) - return (struct external_info *) rn->info; - } - } - } - } - - return NULL; + struct as_external_lsa *al; + struct prefix_ipv4 p; + struct route_node *rn; + int type; + + al = (struct as_external_lsa *)lsa->data; + + p.family = AF_INET; + p.prefix = lsa->data->id; + p.prefixlen = ip_masklen(al->mask); + + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + int redist_on = 0; + + redist_on = + is_prefix_default(&p) + ? vrf_bitmap_check(zclient->default_information, + VRF_DEFAULT) + : (zclient->mi_redist[AFI_IP][type].enabled + || vrf_bitmap_check( + zclient->redist[AFI_IP][type], + VRF_DEFAULT)); + // Pending: check for MI above. + if (redist_on) { + struct list *ext_list; + struct listnode *node; + struct ospf_external *ext; + + ext_list = om->external[type]; + if (!ext_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { + rn = NULL; + if (ext->external_info) + rn = route_node_lookup( + ext->external_info, + (struct prefix *)&p); + if (rn) { + route_unlock_node(rn); + if (rn->info != NULL) + return (struct external_info *) + rn->info; + } + } + } + } + + return NULL; } -static void -ospf_process_self_originated_lsa (struct ospf *ospf, - struct ospf_lsa *new, struct ospf_area *area) +static void ospf_process_self_originated_lsa(struct ospf *ospf, + struct ospf_lsa *new, + struct ospf_area *area) { - struct ospf_interface *oi; - struct external_info *ei; - struct listnode *node; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type%d:%s]: Process self-originated LSA seq 0x%x", - new->data->type, inet_ntoa (new->data->id), - ntohl(new->data->ls_seqnum)); - - /* If we're here, we installed a self-originated LSA that we received - from a neighbor, i.e. it's more recent. We must see whether we want - to originate it. - If yes, we should use this LSA's sequence number and reoriginate - a new instance. - if not --- we must flush this LSA from the domain. */ - switch (new->data->type) - { - case OSPF_ROUTER_LSA: - /* Originate a new instance and schedule flooding */ - if (area->router_lsa_self) - area->router_lsa_self->data->ls_seqnum = new->data->ls_seqnum; - ospf_router_lsa_update_area (area); - return; - case OSPF_NETWORK_LSA: - case OSPF_OPAQUE_LINK_LSA: - /* We must find the interface the LSA could belong to. - If the interface is no more a broadcast type or we are no more - the DR, we flush the LSA otherwise -- create the new instance and - schedule flooding. */ - - /* Look through all interfaces, not just area, since interface - could be moved from one area to another. */ - for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) - /* These are sanity check. */ - if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &new->data->id)) - { - if (oi->area != area || - oi->type != OSPF_IFTYPE_BROADCAST || - !IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) - { - ospf_schedule_lsa_flush_area (area, new); - return; - } - - if (new->data->type == OSPF_OPAQUE_LINK_LSA) - { - ospf_opaque_lsa_refresh (new); - return; - } - - if (oi->network_lsa_self) - oi->network_lsa_self->data->ls_seqnum = new->data->ls_seqnum; - /* Schedule network-LSA origination. */ - ospf_network_lsa_update (oi); - return; - } - break; - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - ospf_schedule_abr_task (ospf); - break; - case OSPF_AS_EXTERNAL_LSA : - case OSPF_AS_NSSA_LSA: - if ( (new->data->type == OSPF_AS_EXTERNAL_LSA) - && CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT)) - { - ospf_translated_nssa_refresh (ospf, NULL, new); - return; - } - ei = ospf_external_info_check (new); - if (ei) - ospf_external_lsa_refresh (ospf, new, ei, LSA_REFRESH_FORCE); - else - ospf_lsa_flush_as (ospf, new); - break; - case OSPF_OPAQUE_AREA_LSA: - ospf_opaque_lsa_refresh (new); - break; - case OSPF_OPAQUE_AS_LSA: - ospf_opaque_lsa_refresh (new); /* Reconsideration may needed. *//* XXX */ - break; - default: - break; - } + struct ospf_interface *oi; + struct external_info *ei; + struct listnode *node; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Type%d:%s]: Process self-originated LSA seq 0x%x", + new->data->type, inet_ntoa(new->data->id), + ntohl(new->data->ls_seqnum)); + + /* If we're here, we installed a self-originated LSA that we received + from a neighbor, i.e. it's more recent. We must see whether we want + to originate it. + If yes, we should use this LSA's sequence number and reoriginate + a new instance. + if not --- we must flush this LSA from the domain. */ + switch (new->data->type) { + case OSPF_ROUTER_LSA: + /* Originate a new instance and schedule flooding */ + if (area->router_lsa_self) + area->router_lsa_self->data->ls_seqnum = + new->data->ls_seqnum; + ospf_router_lsa_update_area(area); + return; + case OSPF_NETWORK_LSA: + case OSPF_OPAQUE_LINK_LSA: + /* We must find the interface the LSA could belong to. + If the interface is no more a broadcast type or we are no + more + the DR, we flush the LSA otherwise -- create the new instance + and + schedule flooding. */ + + /* Look through all interfaces, not just area, since interface + could be moved from one area to another. */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + /* These are sanity check. */ + if (IPV4_ADDR_SAME(&oi->address->u.prefix4, + &new->data->id)) { + if (oi->area != area + || oi->type != OSPF_IFTYPE_BROADCAST + || !IPV4_ADDR_SAME(&oi->address->u.prefix4, + &DR(oi))) { + ospf_schedule_lsa_flush_area(area, new); + return; + } + + if (new->data->type == OSPF_OPAQUE_LINK_LSA) { + ospf_opaque_lsa_refresh(new); + return; + } + + if (oi->network_lsa_self) + oi->network_lsa_self->data->ls_seqnum = + new->data->ls_seqnum; + /* Schedule network-LSA origination. */ + ospf_network_lsa_update(oi); + return; + } + break; + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + ospf_schedule_abr_task(ospf); + break; + case OSPF_AS_EXTERNAL_LSA: + case OSPF_AS_NSSA_LSA: + if ((new->data->type == OSPF_AS_EXTERNAL_LSA) + && CHECK_FLAG(new->flags, OSPF_LSA_LOCAL_XLT)) { + ospf_translated_nssa_refresh(ospf, NULL, new); + return; + } + ei = ospf_external_info_check(new); + if (ei) + ospf_external_lsa_refresh(ospf, new, ei, + LSA_REFRESH_FORCE); + else + ospf_lsa_flush_as(ospf, new); + break; + case OSPF_OPAQUE_AREA_LSA: + ospf_opaque_lsa_refresh(new); + break; + case OSPF_OPAQUE_AS_LSA: + ospf_opaque_lsa_refresh(new); + /* Reconsideration may needed. */ /* XXX */ + break; + default: + break; + } } /* OSPF LSA flooding -- RFC2328 Section 13.(5). */ @@ -228,7 +234,7 @@ ospf_process_self_originated_lsa (struct ospf *ospf, Type-7's can be received, and if a DR they will also flood the local NSSA Area as Type-7's - If a Self-Originated LSA (now an ASBR), + If a Self-Originated LSA (now an ASBR), The LSDB will be updated as Type-5's, (for continual re-fresh) If an NSSA-IR it is installed/flooded as Type-7, P-bit on. @@ -238,777 +244,757 @@ ospf_process_self_originated_lsa (struct ospf *ospf, translator, then All Type-7s (with P-bit ON) are Translated to Type-5's and flooded to all non-NSSA/STUB areas. - During ASE Calculations, + During ASE Calculations, non-ABRs calculate external routes from Type-7's ABRs calculate external routes from Type-5's and non-self Type-7s */ -int -ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr, - struct ospf_lsa *current, struct ospf_lsa *new) +int ospf_flood(struct ospf *ospf, struct ospf_neighbor *nbr, + struct ospf_lsa *current, struct ospf_lsa *new) { - struct ospf_interface *oi; - int lsa_ack_flag; - - /* Type-7 LSA's will be flooded throughout their native NSSA area, - but will also be flooded as Type-5's into ABR capable links. */ - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Flooding]: start, NBR %s (%s), cur(%p), New-LSA[%s]", - inet_ntoa (nbr->router_id), - lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), - (void *)current, - dump_lsa_key (new)); - - oi = nbr->oi; - - /* If there is already a database copy, and if the - database copy was received via flooding and installed less - than MinLSArrival seconds ago, discard the new LSA - (without acknowledging it). */ - if (current != NULL) /* -- endo. */ - { - if (IS_LSA_SELF (current) - && (ntohs (current->data->ls_age) == 0 - && ntohl (current->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Flooding]: Got a self-originated LSA, " - "while local one is initial instance."); - ; /* Accept this LSA for quick LSDB resynchronization. */ - } - else if (monotime_since (¤t->tv_recv, NULL) - < ospf->min_ls_arrival * 1000LL) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Flooding]: LSA is received recently."); - return -1; - } - } - - /* Flood the new LSA out some subset of the router's interfaces. - In some cases (e.g., the state of the receiving interface is - DR and the LSA was received from a router other than the - Backup DR) the LSA will be flooded back out the receiving - interface. */ - lsa_ack_flag = ospf_flood_through (ospf, nbr, new); - - /* Remove the current database copy from all neighbors' Link state - retransmission lists. AS_EXTERNAL and AS_EXTERNAL_OPAQUE does - ^^^^^^^^^^^^^^^^^^^^^^^ - not have area ID. - All other (even NSSA's) do have area ID. */ - if (current) - { - switch (current->data->type) - { - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - ospf_ls_retransmit_delete_nbr_as (ospf, current); - break; - default: - ospf_ls_retransmit_delete_nbr_area (nbr->oi->area, current); - break; - } - } - - /* Do some internal house keeping that is needed here */ - SET_FLAG (new->flags, OSPF_LSA_RECEIVED); - ospf_lsa_is_self_originated (ospf, new); /* Let it set the flag */ - - /* Install the new LSA in the link state database - (replacing the current database copy). This may cause the - routing table calculation to be scheduled. In addition, - timestamp the new LSA with the current time. The flooding - procedure cannot overwrite the newly installed LSA until - MinLSArrival seconds have elapsed. */ - - if (! (new = ospf_lsa_install (ospf, nbr->oi, new))) - return -1; /* unknown LSA type or any other error condition */ - - /* Acknowledge the receipt of the LSA by sending a Link State - Acknowledgment packet back out the receiving interface. */ - if (lsa_ack_flag) - ospf_flood_delayed_lsa_ack (nbr, new); - - /* If this new LSA indicates that it was originated by the - receiving router itself, the router must take special action, - either updating the LSA or in some cases flushing it from - the routing domain. */ - if (ospf_lsa_is_self_originated (ospf, new)) - ospf_process_self_originated_lsa (ospf, new, oi->area); - else - /* Update statistics value for OSPF-MIB. */ - ospf->rx_lsa_count++; - - return 0; + struct ospf_interface *oi; + int lsa_ack_flag; + + /* Type-7 LSA's will be flooded throughout their native NSSA area, + but will also be flooded as Type-5's into ABR capable links. */ + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Flooding]: start, NBR %s (%s), cur(%p), New-LSA[%s]", + inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL), + (void *)current, dump_lsa_key(new)); + + oi = nbr->oi; + + /* If there is already a database copy, and if the + database copy was received via flooding and installed less + than MinLSArrival seconds ago, discard the new LSA + (without acknowledging it). */ + if (current != NULL) /* -- endo. */ + { + if (IS_LSA_SELF(current) + && (ntohs(current->data->ls_age) == 0 + && ntohl(current->data->ls_seqnum) + == OSPF_INITIAL_SEQUENCE_NUMBER)) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Flooding]: Got a self-originated LSA, " + "while local one is initial instance."); + ; /* Accept this LSA for quick LSDB resynchronization. + */ + } else if (monotime_since(¤t->tv_recv, NULL) + < ospf->min_ls_arrival * 1000LL) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "LSA[Flooding]: LSA is received recently."); + return -1; + } + } + + /* Flood the new LSA out some subset of the router's interfaces. + In some cases (e.g., the state of the receiving interface is + DR and the LSA was received from a router other than the + Backup DR) the LSA will be flooded back out the receiving + interface. */ + lsa_ack_flag = ospf_flood_through(ospf, nbr, new); + + /* Remove the current database copy from all neighbors' Link state + retransmission lists. AS_EXTERNAL and AS_EXTERNAL_OPAQUE does + ^^^^^^^^^^^^^^^^^^^^^^^ + not have area ID. + All other (even NSSA's) do have area ID. */ + if (current) { + switch (current->data->type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + ospf_ls_retransmit_delete_nbr_as(ospf, current); + break; + default: + ospf_ls_retransmit_delete_nbr_area(nbr->oi->area, + current); + break; + } + } + + /* Do some internal house keeping that is needed here */ + SET_FLAG(new->flags, OSPF_LSA_RECEIVED); + ospf_lsa_is_self_originated(ospf, new); /* Let it set the flag */ + + /* Install the new LSA in the link state database + (replacing the current database copy). This may cause the + routing table calculation to be scheduled. In addition, + timestamp the new LSA with the current time. The flooding + procedure cannot overwrite the newly installed LSA until + MinLSArrival seconds have elapsed. */ + + if (!(new = ospf_lsa_install(ospf, nbr->oi, new))) + return -1; /* unknown LSA type or any other error condition */ + + /* Acknowledge the receipt of the LSA by sending a Link State + Acknowledgment packet back out the receiving interface. */ + if (lsa_ack_flag) + ospf_flood_delayed_lsa_ack(nbr, new); + + /* If this new LSA indicates that it was originated by the + receiving router itself, the router must take special action, + either updating the LSA or in some cases flushing it from + the routing domain. */ + if (ospf_lsa_is_self_originated(ospf, new)) + ospf_process_self_originated_lsa(ospf, new, oi->area); + else + /* Update statistics value for OSPF-MIB. */ + ospf->rx_lsa_count++; + + return 0; } /* OSPF LSA flooding -- RFC2328 Section 13.3. */ -static int -ospf_flood_through_interface (struct ospf_interface *oi, - struct ospf_neighbor *inbr, - struct ospf_lsa *lsa) +static int ospf_flood_through_interface(struct ospf_interface *oi, + struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) { - struct ospf_neighbor *onbr; - struct route_node *rn; - int retx_flag; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_flood_through_interface(): " - "considering int %s, INBR(%s), LSA[%s]", - IF_NAME (oi), inbr ? inet_ntoa (inbr->router_id) : "NULL", - dump_lsa_key (lsa)); - - if (!ospf_if_is_enable (oi)) - return 0; - - /* Remember if new LSA is aded to a retransmit list. */ - retx_flag = 0; - - /* Each of the neighbors attached to this interface are examined, - to determine whether they must receive the new LSA. The following - steps are executed for each neighbor: */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - { - struct ospf_lsa *ls_req; - - if (rn->info == NULL) - continue; - - onbr = rn->info; - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_flood_through_interface(): considering nbr %s (%s)", - inet_ntoa (onbr->router_id), - lookup_msg(ospf_nsm_state_msg, onbr->state, NULL)); - - /* If the neighbor is in a lesser state than Exchange, it - does not participate in flooding, and the next neighbor - should be examined. */ - if (onbr->state < NSM_Exchange) - continue; - - /* If the adjacency is not yet full (neighbor state is - Exchange or Loading), examine the Link state request - list associated with this adjacency. If there is an - instance of the new LSA on the list, it indicates that - the neighboring router has an instance of the LSA - already. Compare the new LSA to the neighbor's copy: */ - if (onbr->state < NSM_Full) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_flood_through_interface(): nbr adj is not Full"); - ls_req = ospf_ls_request_lookup (onbr, lsa); - if (ls_req != NULL) - { - int ret; - - ret = ospf_lsa_more_recent (ls_req, lsa); - /* The new LSA is less recent. */ - if (ret > 0) - continue; - /* The two copies are the same instance, then delete - the LSA from the Link state request list. */ - else if (ret == 0) - { - ospf_ls_request_delete (onbr, ls_req); - ospf_check_nbr_loading (onbr); - continue; + struct ospf_neighbor *onbr; + struct route_node *rn; + int retx_flag; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_flood_through_interface(): " + "considering int %s, INBR(%s), LSA[%s]", + IF_NAME(oi), inbr ? inet_ntoa(inbr->router_id) : "NULL", + dump_lsa_key(lsa)); + + if (!ospf_if_is_enable(oi)) + return 0; + + /* Remember if new LSA is aded to a retransmit list. */ + retx_flag = 0; + + /* Each of the neighbors attached to this interface are examined, + to determine whether they must receive the new LSA. The following + steps are executed for each neighbor: */ + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + struct ospf_lsa *ls_req; + + if (rn->info == NULL) + continue; + + onbr = rn->info; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_flood_through_interface(): considering nbr %s (%s)", + inet_ntoa(onbr->router_id), + lookup_msg(ospf_nsm_state_msg, onbr->state, + NULL)); + + /* If the neighbor is in a lesser state than Exchange, it + does not participate in flooding, and the next neighbor + should be examined. */ + if (onbr->state < NSM_Exchange) + continue; + + /* If the adjacency is not yet full (neighbor state is + Exchange or Loading), examine the Link state request + list associated with this adjacency. If there is an + instance of the new LSA on the list, it indicates that + the neighboring router has an instance of the LSA + already. Compare the new LSA to the neighbor's copy: */ + if (onbr->state < NSM_Full) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_flood_through_interface(): nbr adj is not Full"); + ls_req = ospf_ls_request_lookup(onbr, lsa); + if (ls_req != NULL) { + int ret; + + ret = ospf_lsa_more_recent(ls_req, lsa); + /* The new LSA is less recent. */ + if (ret > 0) + continue; + /* The two copies are the same instance, then + delete + the LSA from the Link state request list. */ + else if (ret == 0) { + ospf_ls_request_delete(onbr, ls_req); + ospf_check_nbr_loading(onbr); + continue; + } + /* The new LSA is more recent. Delete the LSA + from the Link state request list. */ + else { + ospf_ls_request_delete(onbr, ls_req); + ospf_check_nbr_loading(onbr); + } + } } - /* The new LSA is more recent. Delete the LSA - from the Link state request list. */ - else - { - ospf_ls_request_delete (onbr, ls_req); - ospf_check_nbr_loading (onbr); + + if (IS_OPAQUE_LSA(lsa->data->type)) { + if (!CHECK_FLAG(onbr->options, OSPF_OPTION_O)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "Skip this neighbor: Not Opaque-capable."); + continue; + } } - } - } - if (IS_OPAQUE_LSA (lsa->data->type)) - { - if (! CHECK_FLAG (onbr->options, OSPF_OPTION_O)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Skip this neighbor: Not Opaque-capable."); - continue; - } - } - - /* If the new LSA was received from this neighbor, - examine the next neighbor. */ +/* If the new LSA was received from this neighbor, + examine the next neighbor. */ #ifdef ORIGINAL_CODING - if (inbr) - if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id)) - continue; -#else /* ORIGINAL_CODING */ - if (inbr) - { - /* - * Triggered by LSUpd message parser "ospf_ls_upd ()". - * E.g., all LSAs handling here is received via network. - */ - if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Skip this neighbor: inbr == onbr"); - continue; - } - } - else - { - /* - * Triggered by MaxAge remover, so far. - * NULL "inbr" means flooding starts from this node. - */ - if (IPV4_ADDR_SAME (&lsa->data->adv_router, &onbr->router_id)) - { - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Skip this neighbor: lsah->adv_router == onbr"); - continue; - } - } + if (inbr) + if (IPV4_ADDR_SAME(&inbr->router_id, &onbr->router_id)) + continue; +#else /* ORIGINAL_CODING */ + if (inbr) { + /* + * Triggered by LSUpd message parser "ospf_ls_upd ()". + * E.g., all LSAs handling here is received via network. + */ + if (IPV4_ADDR_SAME(&inbr->router_id, + &onbr->router_id)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "Skip this neighbor: inbr == onbr"); + continue; + } + } else { + /* + * Triggered by MaxAge remover, so far. + * NULL "inbr" means flooding starts from this node. + */ + if (IPV4_ADDR_SAME(&lsa->data->adv_router, + &onbr->router_id)) { + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "Skip this neighbor: lsah->adv_router == onbr"); + continue; + } + } #endif /* ORIGINAL_CODING */ - /* Add the new LSA to the Link state retransmission list - for the adjacency. The LSA will be retransmitted - at intervals until an acknowledgment is seen from - the neighbor. */ - ospf_ls_retransmit_add (onbr, lsa); - retx_flag = 1; - } - - /* If in the previous step, the LSA was NOT added to any of - the Link state retransmission lists, there is no need to - flood the LSA out the interface. */ - if (retx_flag == 0) - { - return (inbr && inbr->oi == oi); - } - - /* if we've received the lsa on this interface we need to perform - additional checking */ - if (inbr && (inbr->oi == oi)) - { - /* If the new LSA was received on this interface, and it was - received from either the Designated Router or the Backup - Designated Router, chances are that all the neighbors have - received the LSA already. */ - if (NBR_IS_DR (inbr) || NBR_IS_BDR (inbr)) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through_interface(): " - "DR/BDR NOT SEND to int %s", IF_NAME (oi)); - return 1; + /* Add the new LSA to the Link state retransmission list + for the adjacency. The LSA will be retransmitted + at intervals until an acknowledgment is seen from + the neighbor. */ + ospf_ls_retransmit_add(onbr, lsa); + retx_flag = 1; } - - /* If the new LSA was received on this interface, and the - interface state is Backup, examine the next interface. The - Designated Router will do the flooding on this interface. - However, if the Designated Router fails the router will - end up retransmitting the updates. */ - - if (oi->state == ISM_Backup) - { - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through_interface(): " - "ISM_Backup NOT SEND to int %s", IF_NAME (oi)); - return 1; + + /* If in the previous step, the LSA was NOT added to any of + the Link state retransmission lists, there is no need to + flood the LSA out the interface. */ + if (retx_flag == 0) { + return (inbr && inbr->oi == oi); + } + + /* if we've received the lsa on this interface we need to perform + additional checking */ + if (inbr && (inbr->oi == oi)) { + /* If the new LSA was received on this interface, and it was + received from either the Designated Router or the Backup + Designated Router, chances are that all the neighbors have + received the LSA already. */ + if (NBR_IS_DR(inbr) || NBR_IS_BDR(inbr)) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through_interface(): " + "DR/BDR NOT SEND to int %s", + IF_NAME(oi)); + return 1; + } + + /* If the new LSA was received on this interface, and the + interface state is Backup, examine the next interface. The + Designated Router will do the flooding on this interface. + However, if the Designated Router fails the router will + end up retransmitting the updates. */ + + if (oi->state == ISM_Backup) { + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through_interface(): " + "ISM_Backup NOT SEND to int %s", + IF_NAME(oi)); + return 1; + } } - } - - /* The LSA must be flooded out the interface. Send a Link State - Update packet (including the new LSA as contents) out the - interface. The LSA's LS age must be incremented by InfTransDelay - (which must be > 0) when it is copied into the outgoing Link - State Update packet (until the LS age field reaches the maximum - value of MaxAge). */ - /* XXX HASSO: Is this IS_DEBUG_OSPF_NSSA really correct? */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through_interface(): " - "DR/BDR sending upd to int %s", IF_NAME (oi)); - - /* RFC2328 Section 13.3 - On non-broadcast networks, separate Link State Update - packets must be sent, as unicasts, to each adjacent neighbor - (i.e., those in state Exchange or greater). The destination - IP addresses for these packets are the neighbors' IP - addresses. */ - if (oi->type == OSPF_IFTYPE_NBMA) - { - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) - ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT); - } - else - ospf_ls_upd_send_lsa (oi->nbr_self, lsa, OSPF_SEND_PACKET_INDIRECT); - - return 0; + + /* The LSA must be flooded out the interface. Send a Link State + Update packet (including the new LSA as contents) out the + interface. The LSA's LS age must be incremented by InfTransDelay + (which must be > 0) when it is copied into the outgoing Link + State Update packet (until the LS age field reaches the maximum + value of MaxAge). */ + /* XXX HASSO: Is this IS_DEBUG_OSPF_NSSA really correct? */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through_interface(): " + "DR/BDR sending upd to int %s", + IF_NAME(oi)); + + /* RFC2328 Section 13.3 + On non-broadcast networks, separate Link State Update + packets must be sent, as unicasts, to each adjacent neighbor + (i.e., those in state Exchange or greater). The destination + IP addresses for these packets are the neighbors' IP + addresses. */ + if (oi->type == OSPF_IFTYPE_NBMA) { + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + if ((nbr = rn->info) != NULL) + if (nbr != oi->nbr_self + && nbr->state >= NSM_Exchange) + ospf_ls_upd_send_lsa( + nbr, lsa, + OSPF_SEND_PACKET_DIRECT); + } else + ospf_ls_upd_send_lsa(oi->nbr_self, lsa, + OSPF_SEND_PACKET_INDIRECT); + + return 0; } -int -ospf_flood_through_area (struct ospf_area *area, - struct ospf_neighbor *inbr, struct ospf_lsa *lsa) +int ospf_flood_through_area(struct ospf_area *area, struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct ospf_interface *oi; - int lsa_ack_flag = 0; - - /* All other types are specific to a single area (Area A). The - eligible interfaces are all those interfaces attaching to the - Area A. If Area A is the backbone, this includes all the virtual - links. */ - for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi)) - { - if (area->area_id.s_addr != OSPF_AREA_BACKBONE && - oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - - if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) && (lsa->oi != oi)) - { - /* - * Link local scoped Opaque-LSA should only be flooded - * for the link on which the LSA has received. - */ - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", - (void *)lsa->oi, (void *)oi); - continue; - } - - if (ospf_flood_through_interface (oi, inbr, lsa)) - lsa_ack_flag = 1; - } - - return (lsa_ack_flag); + struct listnode *node, *nnode; + struct ospf_interface *oi; + int lsa_ack_flag = 0; + + /* All other types are specific to a single area (Area A). The + eligible interfaces are all those interfaces attaching to the + Area A. If Area A is the backbone, this includes all the virtual + links. */ + for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) { + if (area->area_id.s_addr != OSPF_AREA_BACKBONE + && oi->type == OSPF_IFTYPE_VIRTUALLINK) + continue; + + if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) + && (lsa->oi != oi)) { + /* + * Link local scoped Opaque-LSA should only be flooded + * for the link on which the LSA has received. + */ + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug( + "Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", + (void *)lsa->oi, (void *)oi); + continue; + } + + if (ospf_flood_through_interface(oi, inbr, lsa)) + lsa_ack_flag = 1; + } + + return (lsa_ack_flag); } -int -ospf_flood_through_as (struct ospf *ospf, struct ospf_neighbor *inbr, - struct ospf_lsa *lsa) +int ospf_flood_through_as(struct ospf *ospf, struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) { - struct listnode *node; - struct ospf_area *area; - int lsa_ack_flag; - - lsa_ack_flag = 0; + struct listnode *node; + struct ospf_area *area; + int lsa_ack_flag; + + lsa_ack_flag = 0; + + /* The incoming LSA is type 5 or type 7 (AS-EXTERNAL or AS-NSSA ) + + Divert the Type-5 LSA's to all non-NSSA/STUB areas + + Divert the Type-7 LSA's to all NSSA areas + + AS-external-LSAs are flooded throughout the entire AS, with the + exception of stub areas (see Section 3.6). The eligible + interfaces are all the router's interfaces, excluding virtual + links and those interfaces attaching to stub areas. */ + + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) /* Translated from 7 */ + if (IS_DEBUG_OSPF_NSSA) + zlog_debug("Flood/AS: NSSA TRANSLATED LSA"); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + int continue_flag = 0; + struct listnode *if_node; + struct ospf_interface *oi; + + switch (area->external_routing) { + /* Don't send AS externals into stub areas. Various types + of support for partial stub areas can be implemented + here. NSSA's will receive Type-7's that have areas + matching the originl LSA. */ + case OSPF_AREA_NSSA: /* Sending Type 5 or 7 into NSSA area */ + /* Type-7, flood NSSA area */ + if (lsa->data->type == OSPF_AS_NSSA_LSA + && area == lsa->area) + /* We will send it. */ + continue_flag = 0; + else + continue_flag = 1; /* Skip this NSSA area for + Type-5's et al */ + break; + + case OSPF_AREA_TYPE_MAX: + case OSPF_AREA_STUB: + continue_flag = 1; /* Skip this area. */ + break; + + case OSPF_AREA_DEFAULT: + default: + /* No Type-7 into normal area */ + if (lsa->data->type == OSPF_AS_NSSA_LSA) + continue_flag = 1; /* skip Type-7 */ + else + continue_flag = 0; /* Do this area. */ + break; + } - /* The incoming LSA is type 5 or type 7 (AS-EXTERNAL or AS-NSSA ) + /* Do continue for above switch. Saves a big if then mess */ + if (continue_flag) + continue; /* main for-loop */ - Divert the Type-5 LSA's to all non-NSSA/STUB areas + /* send to every interface in this area */ - Divert the Type-7 LSA's to all NSSA areas + for (ALL_LIST_ELEMENTS_RO(area->oiflist, if_node, oi)) { + /* Skip virtual links */ + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) + if (ospf_flood_through_interface(oi, inbr, + lsa)) /* lsa */ + lsa_ack_flag = 1; + } + } /* main area for-loop */ - AS-external-LSAs are flooded throughout the entire AS, with the - exception of stub areas (see Section 3.6). The eligible - interfaces are all the router's interfaces, excluding virtual - links and those interfaces attaching to stub areas. */ + return (lsa_ack_flag); +} - if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) /* Translated from 7 */ - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("Flood/AS: NSSA TRANSLATED LSA"); +int ospf_flood_through(struct ospf *ospf, struct ospf_neighbor *inbr, + struct ospf_lsa *lsa) +{ + int lsa_ack_flag = 0; - for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) - { - int continue_flag = 0; - struct listnode *if_node; - struct ospf_interface *oi; +/* Type-7 LSA's for NSSA are flooded throughout the AS here, and + upon return are updated in the LSDB for Type-7's. Later, + re-fresh will re-send them (and also, if ABR, packet code will + translate to Type-5's) - switch (area->external_routing) - { - /* Don't send AS externals into stub areas. Various types - of support for partial stub areas can be implemented - here. NSSA's will receive Type-7's that have areas - matching the originl LSA. */ - case OSPF_AREA_NSSA: /* Sending Type 5 or 7 into NSSA area */ - /* Type-7, flood NSSA area */ - if (lsa->data->type == OSPF_AS_NSSA_LSA - && area == lsa->area) - /* We will send it. */ - continue_flag = 0; - else - continue_flag = 1; /* Skip this NSSA area for Type-5's et al */ - break; - - case OSPF_AREA_TYPE_MAX: - case OSPF_AREA_STUB: - continue_flag = 1; /* Skip this area. */ - break; - - case OSPF_AREA_DEFAULT: + As usual, Type-5 LSA's (if not DISCARDED because we are STUB or + NSSA) are flooded throughout the AS, and are updated in the + global table. */ +#ifdef ORIGINAL_CODING + switch (lsa->data->type) { + case OSPF_ROUTER_LSA: + case OSPF_NETWORK_LSA: + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */ + case OSPF_OPAQUE_AREA_LSA: + lsa_ack_flag = + ospf_flood_through_area(inbr->oi->area, inbr, lsa); + break; + case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ + case OSPF_OPAQUE_AS_LSA: + lsa_ack_flag = ospf_flood_through_as(ospf, inbr, lsa); + break; + /* Type-7 Only received within NSSA, then flooded */ + case OSPF_AS_NSSA_LSA: + /* Any P-bit was installed with the Type-7. */ + lsa_ack_flag = + ospf_flood_through_area(inbr->oi->area, inbr, lsa); + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through: LOCAL NSSA FLOOD of Type-7."); + break; default: - /* No Type-7 into normal area */ - if (lsa->data->type == OSPF_AS_NSSA_LSA) - continue_flag = 1; /* skip Type-7 */ - else - continue_flag = 0; /* Do this area. */ - break; + break; } - - /* Do continue for above switch. Saves a big if then mess */ - if (continue_flag) - continue; /* main for-loop */ - - /* send to every interface in this area */ - - for (ALL_LIST_ELEMENTS_RO (area->oiflist, if_node, oi)) - { - /* Skip virtual links */ - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (ospf_flood_through_interface (oi, inbr, lsa)) /* lsa */ - lsa_ack_flag = 1; +#else /* ORIGINAL_CODING */ + /* + * At the common sub-sub-function "ospf_flood_through_interface()", + * a parameter "inbr" will be used to distinguish the called context + * whether the given LSA was received from the neighbor, or the + * flooding for the LSA starts from this node (e.g. the LSA was self- + * originated, or the LSA is going to be flushed from routing domain). + * + * So, for consistency reasons, this function "ospf_flood_through()" + * should also allow the usage that the given "inbr" parameter to be + * NULL. If we do so, corresponding AREA parameter should be referred + * by "lsa->area", instead of "inbr->oi->area". + */ + switch (lsa->data->type) { + case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ + case OSPF_OPAQUE_AS_LSA: + lsa_ack_flag = ospf_flood_through_as(ospf, inbr, lsa); + break; + /* Type-7 Only received within NSSA, then flooded */ + case OSPF_AS_NSSA_LSA: + /* Any P-bit was installed with the Type-7. */ + + if (IS_DEBUG_OSPF_NSSA) + zlog_debug( + "ospf_flood_through: LOCAL NSSA FLOOD of Type-7."); + /* Fallthrough */ + default: + lsa_ack_flag = ospf_flood_through_area(lsa->area, inbr, lsa); + break; } - } /* main area for-loop */ - - return (lsa_ack_flag); -} - -int -ospf_flood_through (struct ospf *ospf, - struct ospf_neighbor *inbr, struct ospf_lsa *lsa) -{ - int lsa_ack_flag = 0; - - /* Type-7 LSA's for NSSA are flooded throughout the AS here, and - upon return are updated in the LSDB for Type-7's. Later, - re-fresh will re-send them (and also, if ABR, packet code will - translate to Type-5's) - - As usual, Type-5 LSA's (if not DISCARDED because we are STUB or - NSSA) are flooded throughout the AS, and are updated in the - global table. */ -#ifdef ORIGINAL_CODING - switch (lsa->data->type) - { - case OSPF_ROUTER_LSA: - case OSPF_NETWORK_LSA: - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */ - case OSPF_OPAQUE_AREA_LSA: - lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa); - break; - case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ - case OSPF_OPAQUE_AS_LSA: - lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa); - break; - /* Type-7 Only received within NSSA, then flooded */ - case OSPF_AS_NSSA_LSA: - /* Any P-bit was installed with the Type-7. */ - lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa); - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7."); - break; - default: - break; - } -#else /* ORIGINAL_CODING */ - /* - * At the common sub-sub-function "ospf_flood_through_interface()", - * a parameter "inbr" will be used to distinguish the called context - * whether the given LSA was received from the neighbor, or the - * flooding for the LSA starts from this node (e.g. the LSA was self- - * originated, or the LSA is going to be flushed from routing domain). - * - * So, for consistency reasons, this function "ospf_flood_through()" - * should also allow the usage that the given "inbr" parameter to be - * NULL. If we do so, corresponding AREA parameter should be referred - * by "lsa->area", instead of "inbr->oi->area". - */ - switch (lsa->data->type) - { - case OSPF_AS_EXTERNAL_LSA: /* Type-5 */ - case OSPF_OPAQUE_AS_LSA: - lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa); - break; - /* Type-7 Only received within NSSA, then flooded */ - case OSPF_AS_NSSA_LSA: - /* Any P-bit was installed with the Type-7. */ - - if (IS_DEBUG_OSPF_NSSA) - zlog_debug ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7."); - /* Fallthrough */ - default: - lsa_ack_flag = ospf_flood_through_area (lsa->area, inbr, lsa); - break; - } #endif /* ORIGINAL_CODING */ - - return (lsa_ack_flag); -} + return (lsa_ack_flag); +} /* Management functions for neighbor's Link State Request list. */ -void -ospf_ls_request_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +void ospf_ls_request_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - /* - * We cannot make use of the newly introduced callback function - * "lsdb->new_lsa_hook" to replace debug output below, just because - * it seems no simple and smart way to pass neighbor information to - * the common function "ospf_lsdb_add()" -- endo. - */ - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("RqstL(%lu)++, NBR(%s), LSA[%s]", - ospf_ls_request_count (nbr), - inet_ntoa (nbr->router_id), dump_lsa_key (lsa)); - - ospf_lsdb_add (&nbr->ls_req, lsa); + /* + * We cannot make use of the newly introduced callback function + * "lsdb->new_lsa_hook" to replace debug output below, just because + * it seems no simple and smart way to pass neighbor information to + * the common function "ospf_lsdb_add()" -- endo. + */ + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("RqstL(%lu)++, NBR(%s), LSA[%s]", + ospf_ls_request_count(nbr), + inet_ntoa(nbr->router_id), dump_lsa_key(lsa)); + + ospf_lsdb_add(&nbr->ls_req, lsa); } -unsigned long -ospf_ls_request_count (struct ospf_neighbor *nbr) +unsigned long ospf_ls_request_count(struct ospf_neighbor *nbr) { - return ospf_lsdb_count_all (&nbr->ls_req); + return ospf_lsdb_count_all(&nbr->ls_req); } -int -ospf_ls_request_isempty (struct ospf_neighbor *nbr) +int ospf_ls_request_isempty(struct ospf_neighbor *nbr) { - return ospf_lsdb_isempty (&nbr->ls_req); + return ospf_lsdb_isempty(&nbr->ls_req); } /* Remove LSA from neighbor's ls-request list. */ -void -ospf_ls_request_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +void ospf_ls_request_delete(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - if (nbr->ls_req_last == lsa) - { - ospf_lsa_unlock (&nbr->ls_req_last); - nbr->ls_req_last = NULL; - } - - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) /* -- endo. */ - zlog_debug ("RqstL(%lu)--, NBR(%s), LSA[%s]", - ospf_ls_request_count (nbr), - inet_ntoa (nbr->router_id), dump_lsa_key (lsa)); - - ospf_lsdb_delete (&nbr->ls_req, lsa); + if (nbr->ls_req_last == lsa) { + ospf_lsa_unlock(&nbr->ls_req_last); + nbr->ls_req_last = NULL; + } + + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) /* -- endo. */ + zlog_debug("RqstL(%lu)--, NBR(%s), LSA[%s]", + ospf_ls_request_count(nbr), + inet_ntoa(nbr->router_id), dump_lsa_key(lsa)); + + ospf_lsdb_delete(&nbr->ls_req, lsa); } /* Remove all LSA from neighbor's ls-requenst list. */ -void -ospf_ls_request_delete_all (struct ospf_neighbor *nbr) +void ospf_ls_request_delete_all(struct ospf_neighbor *nbr) { - ospf_lsa_unlock (&nbr->ls_req_last); - nbr->ls_req_last = NULL; - ospf_lsdb_delete_all (&nbr->ls_req); + ospf_lsa_unlock(&nbr->ls_req_last); + nbr->ls_req_last = NULL; + ospf_lsdb_delete_all(&nbr->ls_req); } /* Lookup LSA from neighbor's ls-request list. */ -struct ospf_lsa * -ospf_ls_request_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +struct ospf_lsa *ospf_ls_request_lookup(struct ospf_neighbor *nbr, + struct ospf_lsa *lsa) { - return ospf_lsdb_lookup (&nbr->ls_req, lsa); + return ospf_lsdb_lookup(&nbr->ls_req, lsa); } -struct ospf_lsa * -ospf_ls_request_new (struct lsa_header *lsah) +struct ospf_lsa *ospf_ls_request_new(struct lsa_header *lsah) { - struct ospf_lsa *new; + struct ospf_lsa *new; - new = ospf_lsa_new (); - new->data = ospf_lsa_data_new (OSPF_LSA_HEADER_SIZE); - memcpy (new->data, lsah, OSPF_LSA_HEADER_SIZE); + new = ospf_lsa_new(); + new->data = ospf_lsa_data_new(OSPF_LSA_HEADER_SIZE); + memcpy(new->data, lsah, OSPF_LSA_HEADER_SIZE); - return new; + return new; } /* Management functions for neighbor's ls-retransmit list. */ -unsigned long -ospf_ls_retransmit_count (struct ospf_neighbor *nbr) +unsigned long ospf_ls_retransmit_count(struct ospf_neighbor *nbr) { - return ospf_lsdb_count_all (&nbr->ls_rxmt); + return ospf_lsdb_count_all(&nbr->ls_rxmt); } -unsigned long -ospf_ls_retransmit_count_self (struct ospf_neighbor *nbr, int lsa_type) +unsigned long ospf_ls_retransmit_count_self(struct ospf_neighbor *nbr, + int lsa_type) { - return ospf_lsdb_count_self (&nbr->ls_rxmt, lsa_type); + return ospf_lsdb_count_self(&nbr->ls_rxmt, lsa_type); } -int -ospf_ls_retransmit_isempty (struct ospf_neighbor *nbr) +int ospf_ls_retransmit_isempty(struct ospf_neighbor *nbr) { - return ospf_lsdb_isempty (&nbr->ls_rxmt); + return ospf_lsdb_isempty(&nbr->ls_rxmt); } /* Add LSA to be retransmitted to neighbor's ls-retransmit list. */ -void -ospf_ls_retransmit_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +void ospf_ls_retransmit_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - struct ospf_lsa *old; + struct ospf_lsa *old; - old = ospf_ls_retransmit_lookup (nbr, lsa); + old = ospf_ls_retransmit_lookup(nbr, lsa); - if (ospf_lsa_more_recent (old, lsa) < 0) - { - if (old) - { - old->retransmit_counter--; - ospf_lsdb_delete (&nbr->ls_rxmt, old); + if (ospf_lsa_more_recent(old, lsa) < 0) { + if (old) { + old->retransmit_counter--; + ospf_lsdb_delete(&nbr->ls_rxmt, old); + } + lsa->retransmit_counter++; + /* + * We cannot make use of the newly introduced callback function + * "lsdb->new_lsa_hook" to replace debug output below, just + * because + * it seems no simple and smart way to pass neighbor information + * to + * the common function "ospf_lsdb_add()" -- endo. + */ + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) + zlog_debug("RXmtL(%lu)++, NBR(%s), LSA[%s]", + ospf_ls_retransmit_count(nbr), + inet_ntoa(nbr->router_id), + dump_lsa_key(lsa)); + ospf_lsdb_add(&nbr->ls_rxmt, lsa); } - lsa->retransmit_counter++; - /* - * We cannot make use of the newly introduced callback function - * "lsdb->new_lsa_hook" to replace debug output below, just because - * it seems no simple and smart way to pass neighbor information to - * the common function "ospf_lsdb_add()" -- endo. - */ - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("RXmtL(%lu)++, NBR(%s), LSA[%s]", - ospf_ls_retransmit_count (nbr), - inet_ntoa (nbr->router_id), dump_lsa_key (lsa)); - ospf_lsdb_add (&nbr->ls_rxmt, lsa); - } } /* Remove LSA from neibghbor's ls-retransmit list. */ -void -ospf_ls_retransmit_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +void ospf_ls_retransmit_delete(struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { - if (ospf_ls_retransmit_lookup (nbr, lsa)) - { - lsa->retransmit_counter--; - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) /* -- endo. */ - zlog_debug ("RXmtL(%lu)--, NBR(%s), LSA[%s]", - ospf_ls_retransmit_count (nbr), - inet_ntoa (nbr->router_id), dump_lsa_key (lsa)); - ospf_lsdb_delete (&nbr->ls_rxmt, lsa); - } + if (ospf_ls_retransmit_lookup(nbr, lsa)) { + lsa->retransmit_counter--; + if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) /* -- endo. */ + zlog_debug("RXmtL(%lu)--, NBR(%s), LSA[%s]", + ospf_ls_retransmit_count(nbr), + inet_ntoa(nbr->router_id), + dump_lsa_key(lsa)); + ospf_lsdb_delete(&nbr->ls_rxmt, lsa); + } } /* Clear neighbor's ls-retransmit list. */ -void -ospf_ls_retransmit_clear (struct ospf_neighbor *nbr) +void ospf_ls_retransmit_clear(struct ospf_neighbor *nbr) { - struct ospf_lsdb *lsdb; - int i; + struct ospf_lsdb *lsdb; + int i; - lsdb = &nbr->ls_rxmt; + lsdb = &nbr->ls_rxmt; - for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) - { - struct route_table *table = lsdb->type[i].db; - struct route_node *rn; - struct ospf_lsa *lsa; + for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) { + struct route_table *table = lsdb->type[i].db; + struct route_node *rn; + struct ospf_lsa *lsa; - for (rn = route_top (table); rn; rn = route_next (rn)) - if ((lsa = rn->info) != NULL) - ospf_ls_retransmit_delete (nbr, lsa); - } + for (rn = route_top(table); rn; rn = route_next(rn)) + if ((lsa = rn->info) != NULL) + ospf_ls_retransmit_delete(nbr, lsa); + } - ospf_lsa_unlock (&nbr->ls_req_last); - nbr->ls_req_last = NULL; + ospf_lsa_unlock(&nbr->ls_req_last); + nbr->ls_req_last = NULL; } /* Lookup LSA from neighbor's ls-retransmit list. */ -struct ospf_lsa * -ospf_ls_retransmit_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) +struct ospf_lsa *ospf_ls_retransmit_lookup(struct ospf_neighbor *nbr, + struct ospf_lsa *lsa) { - return ospf_lsdb_lookup (&nbr->ls_rxmt, lsa); + return ospf_lsdb_lookup(&nbr->ls_rxmt, lsa); } -static void -ospf_ls_retransmit_delete_nbr_if (struct ospf_interface *oi, - struct ospf_lsa *lsa) +static void ospf_ls_retransmit_delete_nbr_if(struct ospf_interface *oi, + struct ospf_lsa *lsa) { - struct route_node *rn; - struct ospf_neighbor *nbr; - struct ospf_lsa *lsr; - - if (ospf_if_is_enable (oi)) - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - /* If LSA find in LS-retransmit list, then remove it. */ - if ((nbr = rn->info) != NULL) - { - lsr = ospf_ls_retransmit_lookup (nbr, lsa); - - /* If LSA find in ls-retransmit list, remove it. */ - if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum) - ospf_ls_retransmit_delete (nbr, lsr); - } + struct route_node *rn; + struct ospf_neighbor *nbr; + struct ospf_lsa *lsr; + + if (ospf_if_is_enable(oi)) + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) + /* If LSA find in LS-retransmit list, then remove it. */ + if ((nbr = rn->info) != NULL) { + lsr = ospf_ls_retransmit_lookup(nbr, lsa); + + /* If LSA find in ls-retransmit list, remove it. + */ + if (lsr != NULL + && lsr->data->ls_seqnum + == lsa->data->ls_seqnum) + ospf_ls_retransmit_delete(nbr, lsr); + } } -void -ospf_ls_retransmit_delete_nbr_area (struct ospf_area *area, - struct ospf_lsa *lsa) +void ospf_ls_retransmit_delete_nbr_area(struct ospf_area *area, + struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct ospf_interface *oi; + struct listnode *node, *nnode; + struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi)) - ospf_ls_retransmit_delete_nbr_if (oi, lsa); + for (ALL_LIST_ELEMENTS(area->oiflist, node, nnode, oi)) + ospf_ls_retransmit_delete_nbr_if(oi, lsa); } -void -ospf_ls_retransmit_delete_nbr_as (struct ospf *ospf, struct ospf_lsa *lsa) +void ospf_ls_retransmit_delete_nbr_as(struct ospf *ospf, struct ospf_lsa *lsa) { - struct listnode *node, *nnode; - struct ospf_interface *oi; + struct listnode *node, *nnode; + struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) - ospf_ls_retransmit_delete_nbr_if (oi, lsa); + for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) + ospf_ls_retransmit_delete_nbr_if(oi, lsa); } -/* Sets ls_age to MaxAge and floods throu the area. +/* Sets ls_age to MaxAge and floods throu the area. When we implement ASE routing, there will be anothe function flushing an LSA from the whole domain. */ -void -ospf_lsa_flush_area (struct ospf_lsa *lsa, struct ospf_area *area) +void ospf_lsa_flush_area(struct ospf_lsa *lsa, struct ospf_area *area) { - /* Reset the lsa origination time such that it gives - more time for the ACK to be received and avoid - retransmissions */ - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - monotime(&lsa->tv_recv); - lsa->tv_orig = lsa->tv_recv; - ospf_flood_through_area (area, NULL, lsa); - ospf_lsa_maxage (area->ospf, lsa); + /* Reset the lsa origination time such that it gives + more time for the ACK to be received and avoid + retransmissions */ + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + monotime(&lsa->tv_recv); + lsa->tv_orig = lsa->tv_recv; + ospf_flood_through_area(area, NULL, lsa); + ospf_lsa_maxage(area->ospf, lsa); } -void -ospf_lsa_flush_as (struct ospf *ospf, struct ospf_lsa *lsa) +void ospf_lsa_flush_as(struct ospf *ospf, struct ospf_lsa *lsa) { - /* Reset the lsa origination time such that it gives - more time for the ACK to be received and avoid - retransmissions */ - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - monotime(&lsa->tv_recv); - lsa->tv_orig = lsa->tv_recv; - ospf_flood_through_as (ospf, NULL, lsa); - ospf_lsa_maxage (ospf, lsa); + /* Reset the lsa origination time such that it gives + more time for the ACK to be received and avoid + retransmissions */ + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + monotime(&lsa->tv_recv); + lsa->tv_orig = lsa->tv_recv; + ospf_flood_through_as(ospf, NULL, lsa); + ospf_lsa_maxage(ospf, lsa); } -void -ospf_lsa_flush (struct ospf *ospf, struct ospf_lsa *lsa) +void ospf_lsa_flush(struct ospf *ospf, struct ospf_lsa *lsa) { - lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); - - switch (lsa->data->type) - { - case OSPF_ROUTER_LSA: - case OSPF_NETWORK_LSA: - case OSPF_SUMMARY_LSA: - case OSPF_ASBR_SUMMARY_LSA: - case OSPF_AS_NSSA_LSA: - case OSPF_OPAQUE_LINK_LSA: - case OSPF_OPAQUE_AREA_LSA: - ospf_lsa_flush_area (lsa, lsa->area); - break; - case OSPF_AS_EXTERNAL_LSA: - case OSPF_OPAQUE_AS_LSA: - ospf_lsa_flush_as (ospf, lsa); - break; - default: - zlog_info ("%s: Unknown LSA type %u", __func__, lsa->data->type); - break; - } + lsa->data->ls_age = htons(OSPF_LSA_MAXAGE); + + switch (lsa->data->type) { + case OSPF_ROUTER_LSA: + case OSPF_NETWORK_LSA: + case OSPF_SUMMARY_LSA: + case OSPF_ASBR_SUMMARY_LSA: + case OSPF_AS_NSSA_LSA: + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + ospf_lsa_flush_area(lsa, lsa->area); + break; + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + ospf_lsa_flush_as(ospf, lsa); + break; + default: + zlog_info("%s: Unknown LSA type %u", __func__, lsa->data->type); + break; + } } |
