📄 ospf_flood.c
字号:
return 0;}/* OSPF LSA flooding -- RFC2328 Section 13.3. */intospf_flood_through_interface (struct ospf_interface *oi, struct ospf_neighbor *inbr, struct ospf_lsa *lsa){ struct ospf *ospf = oi->ospf; struct ospf_neighbor *onbr; struct route_node *rn; int retx_flag; if (IS_DEBUG_OSPF_EVENT) zlog_info ("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_info ("ospf_flood_through_interface(): considering nbr %s (%s)", inet_ntoa (onbr->router_id), LOOKUP (ospf_nsm_state_msg, onbr->state)); /* 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_info ("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); } } }#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsa->data->type)) { if (! CHECK_FLAG (onbr->options, OSPF_OPTION_O)) { if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_info ("Skip this neighbor: Not Opaque-capable."); continue; } if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (ospf->opaque) && IS_LSA_SELF (lsa) && onbr->state == NSM_Full) { /* Small attempt to reduce unnecessary retransmission. */ if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_info ("Skip this neighbor: Initial flushing done."); continue; } }#endif /* HAVE_OPAQUE_LSA */ /* 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_info ("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_info ("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)) {#ifdef HAVE_NSSA if (IS_DEBUG_OSPF_NSSA) zlog_info ("ospf_flood_through_interface(): " "DR/BDR NOT SEND to int %s", IF_NAME (oi));#endif /* HAVE_NSSA */ 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) {#ifdef HAVE_NSSA if (IS_DEBUG_OSPF_NSSA) zlog_info ("ospf_flood_through_interface(): " "ISM_Backup NOT SEND to int %s", IF_NAME (oi));#endif /* HAVE_NSSA */ 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). */#ifdef HAVE_NSSA if (IS_DEBUG_OSPF_NSSA) zlog_info ("ospf_flood_through_interface(): " "DR/BDR sending upd to int %s", IF_NAME (oi));#else /* ! HAVE_NSSA */ if (IS_DEBUG_OSPF_EVENT) zlog_info ("ospf_flood_through_interface(): " "sending upd to int %s", IF_NAME (oi));#endif /* HAVE_NSSA */ /* 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;}intospf_flood_through_area (struct ospf_area *area, struct ospf_neighbor *inbr, struct ospf_lsa *lsa){ listnode node; 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 (node = listhead (area->oiflist); node; nextnode (node)) { struct ospf_interface *oi = getdata (node); if (area->area_id.s_addr != OSPF_AREA_BACKBONE && oi->type == OSPF_IFTYPE_VIRTUALLINK) continue;#ifdef HAVE_OPAQUE_LSA 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_info ("Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", lsa->oi, oi); continue; }#endif /* HAVE_OPAQUE_LSA */ if (ospf_flood_through_interface (oi, inbr, lsa)) lsa_ack_flag = 1; } return (lsa_ack_flag);}intospf_flood_through_as (struct ospf *ospf, struct ospf_neighbor *inbr, struct ospf_lsa *lsa){ listnode node; 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. */#ifdef HAVE_NSSA if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) /* Translated from 7 */ if (IS_DEBUG_OSPF_NSSA) zlog_info ("Flood/AS: NSSA TRANSLATED LSA");#endif /* HAVE_NSSA */ for (node = listhead (ospf->areas); node; nextnode (node)) { int continue_flag = 0; struct ospf_area *area = getdata (node); listnode if_node; 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 */#ifdef HAVE_NSSA /* Type-7, flood NSSA area */ if (lsa->data->type == OSPF_AS_NSSA_LSA && area == lsa->area) continue_flag = 0; else continue_flag = 1; /* Skip this NSSA area for Type-5's et al */ break;#endif /* HAVE_NSSA */ case OSPF_AREA_TYPE_MAX: case OSPF_AREA_STUB: continue_flag = 1; /* Skip this area. */ break; case OSPF_AREA_DEFAULT: default:#ifdef HAVE_NSSA /* No Type-7 into normal area */ if (lsa->data->type == OSPF_AS_NSSA_LSA) continue_flag = 1; /* skip Type-7 */ else#endif /* HAVE_NSSA */ continue_flag = 0; /* Do this area. */ break; } /* Do continue for above switch. Saves a big if then mess */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -