Annotation of embedaddon/quagga/ospfd/ospf_flood.c, revision 1.1
1.1 ! misho 1: /*
! 2: * OSPF Flooding -- RFC2328 Section 13.
! 3: * Copyright (C) 1999, 2000 Toshiaki Takada
! 4: *
! 5: * This file is part of GNU Zebra.
! 6: *
! 7: * GNU Zebra is free software; you can redistribute it and/or modify
! 8: * it under the terms of the GNU General Public License as published
! 9: * by the Free Software Foundation; either version 2, or (at your
! 10: * option) any later version.
! 11: *
! 12: * GNU Zebra is distributed in the hope that it will be useful, but
! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of
! 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 15: * General Public License for more details.
! 16: *
! 17: * You should have received a copy of the GNU General Public License
! 18: * along with GNU Zebra; see the file COPYING. If not, write to the
! 19: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
! 20: * Boston, MA 02111-1307, USA.
! 21: */
! 22:
! 23: #include <zebra.h>
! 24:
! 25: #include "linklist.h"
! 26: #include "prefix.h"
! 27: #include "if.h"
! 28: #include "command.h"
! 29: #include "table.h"
! 30: #include "thread.h"
! 31: #include "memory.h"
! 32: #include "log.h"
! 33: #include "zclient.h"
! 34:
! 35: #include "ospfd/ospfd.h"
! 36: #include "ospfd/ospf_interface.h"
! 37: #include "ospfd/ospf_ism.h"
! 38: #include "ospfd/ospf_asbr.h"
! 39: #include "ospfd/ospf_lsa.h"
! 40: #include "ospfd/ospf_lsdb.h"
! 41: #include "ospfd/ospf_neighbor.h"
! 42: #include "ospfd/ospf_nsm.h"
! 43: #include "ospfd/ospf_spf.h"
! 44: #include "ospfd/ospf_flood.h"
! 45: #include "ospfd/ospf_packet.h"
! 46: #include "ospfd/ospf_abr.h"
! 47: #include "ospfd/ospf_route.h"
! 48: #include "ospfd/ospf_zebra.h"
! 49: #include "ospfd/ospf_dump.h"
! 50:
! 51: extern struct zclient *zclient;
! 52:
! 53: /* Do the LSA acking specified in table 19, Section 13.5, row 2
! 54: * This get called from ospf_flood_out_interface. Declared inline
! 55: * for speed. */
! 56: static void
! 57: ospf_flood_delayed_lsa_ack (struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
! 58: {
! 59: /* LSA is more recent than database copy, but was not
! 60: flooded back out receiving interface. Delayed
! 61: acknowledgment sent. If interface is in Backup state
! 62: delayed acknowledgment sent only if advertisement
! 63: received from Designated Router, otherwise do nothing See
! 64: RFC 2328 Section 13.5 */
! 65:
! 66: /* Whether LSA is more recent or not, and whether this is in
! 67: response to the LSA being sent out recieving interface has been
! 68: worked out previously */
! 69:
! 70: /* Deal with router as BDR */
! 71: if (inbr->oi->state == ISM_Backup && ! NBR_IS_DR (inbr))
! 72: return;
! 73:
! 74: /* Schedule a delayed LSA Ack to be sent */
! 75: listnode_add (inbr->oi->ls_ack, ospf_lsa_lock (lsa)); /* delayed LSA Ack */
! 76: }
! 77:
! 78: /* Check LSA is related to external info. */
! 79: struct external_info *
! 80: ospf_external_info_check (struct ospf_lsa *lsa)
! 81: {
! 82: struct as_external_lsa *al;
! 83: struct prefix_ipv4 p;
! 84: struct route_node *rn;
! 85: int type;
! 86:
! 87: al = (struct as_external_lsa *) lsa->data;
! 88:
! 89: p.family = AF_INET;
! 90: p.prefix = lsa->data->id;
! 91: p.prefixlen = ip_masklen (al->mask);
! 92:
! 93: for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
! 94: {
! 95: int redist_type = is_prefix_default (&p) ? DEFAULT_ROUTE : type;
! 96: if (ospf_is_type_redistributed (redist_type))
! 97: if (EXTERNAL_INFO (type))
! 98: {
! 99: rn = route_node_lookup (EXTERNAL_INFO (type),
! 100: (struct prefix *) &p);
! 101: if (rn)
! 102: {
! 103: route_unlock_node (rn);
! 104: if (rn->info != NULL)
! 105: return (struct external_info *) rn->info;
! 106: }
! 107: }
! 108: }
! 109:
! 110: return NULL;
! 111: }
! 112:
! 113: static void
! 114: ospf_process_self_originated_lsa (struct ospf *ospf,
! 115: struct ospf_lsa *new, struct ospf_area *area)
! 116: {
! 117: struct ospf_interface *oi;
! 118: struct external_info *ei;
! 119: struct listnode *node;
! 120:
! 121: if (IS_DEBUG_OSPF_EVENT)
! 122: zlog_debug ("LSA[Type%d:%s]: Process self-originated LSA seq 0x%x",
! 123: new->data->type, inet_ntoa (new->data->id),
! 124: ntohl(new->data->ls_seqnum));
! 125:
! 126: /* If we're here, we installed a self-originated LSA that we received
! 127: from a neighbor, i.e. it's more recent. We must see whether we want
! 128: to originate it.
! 129: If yes, we should use this LSA's sequence number and reoriginate
! 130: a new instance.
! 131: if not --- we must flush this LSA from the domain. */
! 132: switch (new->data->type)
! 133: {
! 134: case OSPF_ROUTER_LSA:
! 135: /* Originate a new instance and schedule flooding */
! 136: if (area->router_lsa_self)
! 137: area->router_lsa_self->data->ls_seqnum = new->data->ls_seqnum;
! 138: ospf_router_lsa_update_area (area);
! 139: return;
! 140: case OSPF_NETWORK_LSA:
! 141: #ifdef HAVE_OPAQUE_LSA
! 142: case OSPF_OPAQUE_LINK_LSA:
! 143: #endif /* HAVE_OPAQUE_LSA */
! 144: /* We must find the interface the LSA could belong to.
! 145: If the interface is no more a broadcast type or we are no more
! 146: the DR, we flush the LSA otherwise -- create the new instance and
! 147: schedule flooding. */
! 148:
! 149: /* Look through all interfaces, not just area, since interface
! 150: could be moved from one area to another. */
! 151: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
! 152: /* These are sanity check. */
! 153: if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &new->data->id))
! 154: {
! 155: if (oi->area != area ||
! 156: oi->type != OSPF_IFTYPE_BROADCAST ||
! 157: !IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)))
! 158: {
! 159: ospf_schedule_lsa_flush_area (area, new);
! 160: return;
! 161: }
! 162:
! 163: #ifdef HAVE_OPAQUE_LSA
! 164: if (new->data->type == OSPF_OPAQUE_LINK_LSA)
! 165: {
! 166: ospf_opaque_lsa_refresh (new);
! 167: return;
! 168: }
! 169: #endif /* HAVE_OPAQUE_LSA */
! 170:
! 171: if (oi->network_lsa_self)
! 172: oi->network_lsa_self->data->ls_seqnum = new->data->ls_seqnum;
! 173: /* Schedule network-LSA origination. */
! 174: ospf_network_lsa_update (oi);
! 175: return;
! 176: }
! 177: break;
! 178: case OSPF_SUMMARY_LSA:
! 179: case OSPF_ASBR_SUMMARY_LSA:
! 180: ospf_schedule_abr_task (ospf);
! 181: break;
! 182: case OSPF_AS_EXTERNAL_LSA :
! 183: case OSPF_AS_NSSA_LSA:
! 184: if ( (new->data->type == OSPF_AS_EXTERNAL_LSA)
! 185: && CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT))
! 186: {
! 187: ospf_translated_nssa_refresh (ospf, NULL, new);
! 188: return;
! 189: }
! 190: ei = ospf_external_info_check (new);
! 191: if (ei)
! 192: ospf_external_lsa_refresh (ospf, new, ei, LSA_REFRESH_FORCE);
! 193: else
! 194: ospf_lsa_flush_as (ospf, new);
! 195: break;
! 196: #ifdef HAVE_OPAQUE_LSA
! 197: case OSPF_OPAQUE_AREA_LSA:
! 198: ospf_opaque_lsa_refresh (new);
! 199: break;
! 200: case OSPF_OPAQUE_AS_LSA:
! 201: ospf_opaque_lsa_refresh (new); /* Reconsideration may needed. *//* XXX */
! 202: break;
! 203: #endif /* HAVE_OPAQUE_LSA */
! 204: default:
! 205: break;
! 206: }
! 207: }
! 208:
! 209: /* OSPF LSA flooding -- RFC2328 Section 13.(5). */
! 210:
! 211: /* Now Updated for NSSA operation, as follows:
! 212:
! 213:
! 214: Type-5's have no change. Blocked to STUB or NSSA.
! 215:
! 216: Type-7's can be received, and if a DR
! 217: they will also flood the local NSSA Area as Type-7's
! 218:
! 219: If a Self-Originated LSA (now an ASBR),
! 220: The LSDB will be updated as Type-5's, (for continual re-fresh)
! 221:
! 222: If an NSSA-IR it is installed/flooded as Type-7, P-bit on.
! 223: if an NSSA-ABR it is installed/flooded as Type-7, P-bit off.
! 224:
! 225: Later, during the ABR TASK, if the ABR is the Elected NSSA
! 226: translator, then All Type-7s (with P-bit ON) are Translated to
! 227: Type-5's and flooded to all non-NSSA/STUB areas.
! 228:
! 229: During ASE Calculations,
! 230: non-ABRs calculate external routes from Type-7's
! 231: ABRs calculate external routes from Type-5's and non-self Type-7s
! 232: */
! 233: int
! 234: ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr,
! 235: struct ospf_lsa *current, struct ospf_lsa *new)
! 236: {
! 237: struct ospf_interface *oi;
! 238: int lsa_ack_flag;
! 239:
! 240: /* Type-7 LSA's will be flooded throughout their native NSSA area,
! 241: but will also be flooded as Type-5's into ABR capable links. */
! 242:
! 243: if (IS_DEBUG_OSPF_EVENT)
! 244: zlog_debug ("LSA[Flooding]: start, NBR %s (%s), cur(%p), New-LSA[%s]",
! 245: inet_ntoa (nbr->router_id),
! 246: LOOKUP (ospf_nsm_state_msg, nbr->state),
! 247: current,
! 248: dump_lsa_key (new));
! 249:
! 250: lsa_ack_flag = 0;
! 251: oi = nbr->oi;
! 252:
! 253: /* If there is already a database copy, and if the
! 254: database copy was received via flooding and installed less
! 255: than MinLSArrival seconds ago, discard the new LSA
! 256: (without acknowledging it). */
! 257: if (current != NULL) /* -- endo. */
! 258: {
! 259: if (IS_LSA_SELF (current)
! 260: && (ntohs (current->data->ls_age) == 0
! 261: && ntohl (current->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER))
! 262: {
! 263: if (IS_DEBUG_OSPF_EVENT)
! 264: zlog_debug ("LSA[Flooding]: Got a self-originated LSA, "
! 265: "while local one is initial instance.");
! 266: ; /* Accept this LSA for quick LSDB resynchronization. */
! 267: }
! 268: else if (tv_cmp (tv_sub (recent_relative_time (), current->tv_recv),
! 269: int2tv (OSPF_MIN_LS_ARRIVAL)) < 0)
! 270: {
! 271: if (IS_DEBUG_OSPF_EVENT)
! 272: zlog_debug ("LSA[Flooding]: LSA is received recently.");
! 273: return -1;
! 274: }
! 275: }
! 276:
! 277: /* Flood the new LSA out some subset of the router's interfaces.
! 278: In some cases (e.g., the state of the receiving interface is
! 279: DR and the LSA was received from a router other than the
! 280: Backup DR) the LSA will be flooded back out the receiving
! 281: interface. */
! 282: lsa_ack_flag = ospf_flood_through (ospf, nbr, new);
! 283:
! 284: #ifdef HAVE_OPAQUE_LSA
! 285: /* Remove the current database copy from all neighbors' Link state
! 286: retransmission lists. AS_EXTERNAL and AS_EXTERNAL_OPAQUE does
! 287: ^^^^^^^^^^^^^^^^^^^^^^^
! 288: not have area ID.
! 289: All other (even NSSA's) do have area ID. */
! 290: #else /* HAVE_OPAQUE_LSA */
! 291: /* Remove the current database copy from all neighbors' Link state
! 292: retransmission lists. Only AS_EXTERNAL does not have area ID.
! 293: All other (even NSSA's) do have area ID. */
! 294: #endif /* HAVE_OPAQUE_LSA */
! 295: if (current)
! 296: {
! 297: switch (current->data->type)
! 298: {
! 299: case OSPF_AS_EXTERNAL_LSA:
! 300: #ifdef HAVE_OPAQUE_LSA
! 301: case OSPF_OPAQUE_AS_LSA:
! 302: #endif /* HAVE_OPAQUE_LSA */
! 303: ospf_ls_retransmit_delete_nbr_as (ospf, current);
! 304: break;
! 305: default:
! 306: ospf_ls_retransmit_delete_nbr_area (nbr->oi->area, current);
! 307: break;
! 308: }
! 309: }
! 310:
! 311: /* Do some internal house keeping that is needed here */
! 312: SET_FLAG (new->flags, OSPF_LSA_RECEIVED);
! 313: ospf_lsa_is_self_originated (ospf, new); /* Let it set the flag */
! 314:
! 315: /* Install the new LSA in the link state database
! 316: (replacing the current database copy). This may cause the
! 317: routing table calculation to be scheduled. In addition,
! 318: timestamp the new LSA with the current time. The flooding
! 319: procedure cannot overwrite the newly installed LSA until
! 320: MinLSArrival seconds have elapsed. */
! 321:
! 322: if (! (new = ospf_lsa_install (ospf, nbr->oi, new)))
! 323: return 0; /* unknown LSA type */
! 324:
! 325: /* Acknowledge the receipt of the LSA by sending a Link State
! 326: Acknowledgment packet back out the receiving interface. */
! 327: if (lsa_ack_flag)
! 328: ospf_flood_delayed_lsa_ack (nbr, new);
! 329:
! 330: /* If this new LSA indicates that it was originated by the
! 331: receiving router itself, the router must take special action,
! 332: either updating the LSA or in some cases flushing it from
! 333: the routing domain. */
! 334: if (ospf_lsa_is_self_originated (ospf, new))
! 335: ospf_process_self_originated_lsa (ospf, new, oi->area);
! 336: else
! 337: /* Update statistics value for OSPF-MIB. */
! 338: ospf->rx_lsa_count++;
! 339:
! 340: return 0;
! 341: }
! 342:
! 343: /* OSPF LSA flooding -- RFC2328 Section 13.3. */
! 344: static int
! 345: ospf_flood_through_interface (struct ospf_interface *oi,
! 346: struct ospf_neighbor *inbr,
! 347: struct ospf_lsa *lsa)
! 348: {
! 349: struct ospf_neighbor *onbr;
! 350: struct route_node *rn;
! 351: int retx_flag;
! 352:
! 353: if (IS_DEBUG_OSPF_EVENT)
! 354: zlog_debug ("ospf_flood_through_interface(): "
! 355: "considering int %s, INBR(%s), LSA[%s]",
! 356: IF_NAME (oi), inbr ? inet_ntoa (inbr->router_id) : "NULL",
! 357: dump_lsa_key (lsa));
! 358:
! 359: if (!ospf_if_is_enable (oi))
! 360: return 0;
! 361:
! 362: /* Remember if new LSA is aded to a retransmit list. */
! 363: retx_flag = 0;
! 364:
! 365: /* Each of the neighbors attached to this interface are examined,
! 366: to determine whether they must receive the new LSA. The following
! 367: steps are executed for each neighbor: */
! 368: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
! 369: {
! 370: struct ospf_lsa *ls_req;
! 371:
! 372: if (rn->info == NULL)
! 373: continue;
! 374:
! 375: onbr = rn->info;
! 376: if (IS_DEBUG_OSPF_EVENT)
! 377: zlog_debug ("ospf_flood_through_interface(): considering nbr %s (%s)",
! 378: inet_ntoa (onbr->router_id),
! 379: LOOKUP (ospf_nsm_state_msg, onbr->state));
! 380:
! 381: /* If the neighbor is in a lesser state than Exchange, it
! 382: does not participate in flooding, and the next neighbor
! 383: should be examined. */
! 384: if (onbr->state < NSM_Exchange)
! 385: continue;
! 386:
! 387: /* If the adjacency is not yet full (neighbor state is
! 388: Exchange or Loading), examine the Link state request
! 389: list associated with this adjacency. If there is an
! 390: instance of the new LSA on the list, it indicates that
! 391: the neighboring router has an instance of the LSA
! 392: already. Compare the new LSA to the neighbor's copy: */
! 393: if (onbr->state < NSM_Full)
! 394: {
! 395: if (IS_DEBUG_OSPF_EVENT)
! 396: zlog_debug ("ospf_flood_through_interface(): nbr adj is not Full");
! 397: ls_req = ospf_ls_request_lookup (onbr, lsa);
! 398: if (ls_req != NULL)
! 399: {
! 400: int ret;
! 401:
! 402: ret = ospf_lsa_more_recent (ls_req, lsa);
! 403: /* The new LSA is less recent. */
! 404: if (ret > 0)
! 405: continue;
! 406: /* The two copies are the same instance, then delete
! 407: the LSA from the Link state request list. */
! 408: else if (ret == 0)
! 409: {
! 410: ospf_ls_request_delete (onbr, ls_req);
! 411: ospf_check_nbr_loading (onbr);
! 412: continue;
! 413: }
! 414: /* The new LSA is more recent. Delete the LSA
! 415: from the Link state request list. */
! 416: else
! 417: {
! 418: ospf_ls_request_delete (onbr, ls_req);
! 419: ospf_check_nbr_loading (onbr);
! 420: }
! 421: }
! 422: }
! 423:
! 424: #ifdef HAVE_OPAQUE_LSA
! 425: if (IS_OPAQUE_LSA (lsa->data->type))
! 426: {
! 427: if (! CHECK_FLAG (onbr->options, OSPF_OPTION_O))
! 428: {
! 429: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 430: zlog_debug ("Skip this neighbor: Not Opaque-capable.");
! 431: continue;
! 432: }
! 433:
! 434: if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (oi->ospf->opaque)
! 435: && IS_LSA_SELF (lsa)
! 436: && onbr->state == NSM_Full)
! 437: {
! 438: /* Small attempt to reduce unnecessary retransmission. */
! 439: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 440: zlog_debug ("Skip this neighbor: Initial flushing done.");
! 441: continue;
! 442: }
! 443: }
! 444: #endif /* HAVE_OPAQUE_LSA */
! 445:
! 446: /* If the new LSA was received from this neighbor,
! 447: examine the next neighbor. */
! 448: #ifdef ORIGINAL_CODING
! 449: if (inbr)
! 450: if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id))
! 451: continue;
! 452: #else /* ORIGINAL_CODING */
! 453: if (inbr)
! 454: {
! 455: /*
! 456: * Triggered by LSUpd message parser "ospf_ls_upd ()".
! 457: * E.g., all LSAs handling here is received via network.
! 458: */
! 459: if (IPV4_ADDR_SAME (&inbr->router_id, &onbr->router_id))
! 460: {
! 461: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 462: zlog_debug ("Skip this neighbor: inbr == onbr");
! 463: continue;
! 464: }
! 465: }
! 466: else
! 467: {
! 468: /*
! 469: * Triggered by MaxAge remover, so far.
! 470: * NULL "inbr" means flooding starts from this node.
! 471: */
! 472: if (IPV4_ADDR_SAME (&lsa->data->adv_router, &onbr->router_id))
! 473: {
! 474: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 475: zlog_debug ("Skip this neighbor: lsah->adv_router == onbr");
! 476: continue;
! 477: }
! 478: }
! 479: #endif /* ORIGINAL_CODING */
! 480:
! 481: /* Add the new LSA to the Link state retransmission list
! 482: for the adjacency. The LSA will be retransmitted
! 483: at intervals until an acknowledgment is seen from
! 484: the neighbor. */
! 485: ospf_ls_retransmit_add (onbr, lsa);
! 486: retx_flag = 1;
! 487: }
! 488:
! 489: /* If in the previous step, the LSA was NOT added to any of
! 490: the Link state retransmission lists, there is no need to
! 491: flood the LSA out the interface. */
! 492: if (retx_flag == 0)
! 493: {
! 494: return (inbr && inbr->oi == oi);
! 495: }
! 496:
! 497: /* if we've received the lsa on this interface we need to perform
! 498: additional checking */
! 499: if (inbr && (inbr->oi == oi))
! 500: {
! 501: /* If the new LSA was received on this interface, and it was
! 502: received from either the Designated Router or the Backup
! 503: Designated Router, chances are that all the neighbors have
! 504: received the LSA already. */
! 505: if (NBR_IS_DR (inbr) || NBR_IS_BDR (inbr))
! 506: {
! 507: if (IS_DEBUG_OSPF_NSSA)
! 508: zlog_debug ("ospf_flood_through_interface(): "
! 509: "DR/BDR NOT SEND to int %s", IF_NAME (oi));
! 510: return 1;
! 511: }
! 512:
! 513: /* If the new LSA was received on this interface, and the
! 514: interface state is Backup, examine the next interface. The
! 515: Designated Router will do the flooding on this interface.
! 516: However, if the Designated Router fails the router will
! 517: end up retransmitting the updates. */
! 518:
! 519: if (oi->state == ISM_Backup)
! 520: {
! 521: if (IS_DEBUG_OSPF_NSSA)
! 522: zlog_debug ("ospf_flood_through_interface(): "
! 523: "ISM_Backup NOT SEND to int %s", IF_NAME (oi));
! 524: return 1;
! 525: }
! 526: }
! 527:
! 528: /* The LSA must be flooded out the interface. Send a Link State
! 529: Update packet (including the new LSA as contents) out the
! 530: interface. The LSA's LS age must be incremented by InfTransDelay
! 531: (which must be > 0) when it is copied into the outgoing Link
! 532: State Update packet (until the LS age field reaches the maximum
! 533: value of MaxAge). */
! 534: /* XXX HASSO: Is this IS_DEBUG_OSPF_NSSA really correct? */
! 535: if (IS_DEBUG_OSPF_NSSA)
! 536: zlog_debug ("ospf_flood_through_interface(): "
! 537: "DR/BDR sending upd to int %s", IF_NAME (oi));
! 538:
! 539: /* RFC2328 Section 13.3
! 540: On non-broadcast networks, separate Link State Update
! 541: packets must be sent, as unicasts, to each adjacent neighbor
! 542: (i.e., those in state Exchange or greater). The destination
! 543: IP addresses for these packets are the neighbors' IP
! 544: addresses. */
! 545: if (oi->type == OSPF_IFTYPE_NBMA)
! 546: {
! 547: struct route_node *rn;
! 548: struct ospf_neighbor *nbr;
! 549:
! 550: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
! 551: if ((nbr = rn->info) != NULL)
! 552: if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
! 553: ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT);
! 554: }
! 555: else
! 556: ospf_ls_upd_send_lsa (oi->nbr_self, lsa, OSPF_SEND_PACKET_INDIRECT);
! 557:
! 558: return 0;
! 559: }
! 560:
! 561: int
! 562: ospf_flood_through_area (struct ospf_area *area,
! 563: struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
! 564: {
! 565: struct listnode *node, *nnode;
! 566: struct ospf_interface *oi;
! 567: int lsa_ack_flag = 0;
! 568:
! 569: /* All other types are specific to a single area (Area A). The
! 570: eligible interfaces are all those interfaces attaching to the
! 571: Area A. If Area A is the backbone, this includes all the virtual
! 572: links. */
! 573: for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
! 574: {
! 575: if (area->area_id.s_addr != OSPF_AREA_BACKBONE &&
! 576: oi->type == OSPF_IFTYPE_VIRTUALLINK)
! 577: continue;
! 578:
! 579: #ifdef HAVE_OPAQUE_LSA
! 580: if ((lsa->data->type == OSPF_OPAQUE_LINK_LSA) && (lsa->oi != oi))
! 581: {
! 582: /*
! 583: * Link local scoped Opaque-LSA should only be flooded
! 584: * for the link on which the LSA has received.
! 585: */
! 586: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 587: zlog_debug ("Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", lsa->oi, oi);
! 588: continue;
! 589: }
! 590: #endif /* HAVE_OPAQUE_LSA */
! 591:
! 592: if (ospf_flood_through_interface (oi, inbr, lsa))
! 593: lsa_ack_flag = 1;
! 594: }
! 595:
! 596: return (lsa_ack_flag);
! 597: }
! 598:
! 599: int
! 600: ospf_flood_through_as (struct ospf *ospf, struct ospf_neighbor *inbr,
! 601: struct ospf_lsa *lsa)
! 602: {
! 603: struct listnode *node;
! 604: struct ospf_area *area;
! 605: int lsa_ack_flag;
! 606:
! 607: lsa_ack_flag = 0;
! 608:
! 609: /* The incoming LSA is type 5 or type 7 (AS-EXTERNAL or AS-NSSA )
! 610:
! 611: Divert the Type-5 LSA's to all non-NSSA/STUB areas
! 612:
! 613: Divert the Type-7 LSA's to all NSSA areas
! 614:
! 615: AS-external-LSAs are flooded throughout the entire AS, with the
! 616: exception of stub areas (see Section 3.6). The eligible
! 617: interfaces are all the router's interfaces, excluding virtual
! 618: links and those interfaces attaching to stub areas. */
! 619:
! 620: if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)) /* Translated from 7 */
! 621: if (IS_DEBUG_OSPF_NSSA)
! 622: zlog_debug ("Flood/AS: NSSA TRANSLATED LSA");
! 623:
! 624: for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
! 625: {
! 626: int continue_flag = 0;
! 627: struct listnode *if_node;
! 628: struct ospf_interface *oi;
! 629:
! 630: switch (area->external_routing)
! 631: {
! 632: /* Don't send AS externals into stub areas. Various types
! 633: of support for partial stub areas can be implemented
! 634: here. NSSA's will receive Type-7's that have areas
! 635: matching the originl LSA. */
! 636: case OSPF_AREA_NSSA: /* Sending Type 5 or 7 into NSSA area */
! 637: /* Type-7, flood NSSA area */
! 638: if (lsa->data->type == OSPF_AS_NSSA_LSA
! 639: && area == lsa->area)
! 640: /* We will send it. */
! 641: continue_flag = 0;
! 642: else
! 643: continue_flag = 1; /* Skip this NSSA area for Type-5's et al */
! 644: break;
! 645:
! 646: case OSPF_AREA_TYPE_MAX:
! 647: case OSPF_AREA_STUB:
! 648: continue_flag = 1; /* Skip this area. */
! 649: break;
! 650:
! 651: case OSPF_AREA_DEFAULT:
! 652: default:
! 653: /* No Type-7 into normal area */
! 654: if (lsa->data->type == OSPF_AS_NSSA_LSA)
! 655: continue_flag = 1; /* skip Type-7 */
! 656: else
! 657: continue_flag = 0; /* Do this area. */
! 658: break;
! 659: }
! 660:
! 661: /* Do continue for above switch. Saves a big if then mess */
! 662: if (continue_flag)
! 663: continue; /* main for-loop */
! 664:
! 665: /* send to every interface in this area */
! 666:
! 667: for (ALL_LIST_ELEMENTS_RO (area->oiflist, if_node, oi))
! 668: {
! 669: /* Skip virtual links */
! 670: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
! 671: if (ospf_flood_through_interface (oi, inbr, lsa)) /* lsa */
! 672: lsa_ack_flag = 1;
! 673: }
! 674: } /* main area for-loop */
! 675:
! 676: return (lsa_ack_flag);
! 677: }
! 678:
! 679: int
! 680: ospf_flood_through (struct ospf *ospf,
! 681: struct ospf_neighbor *inbr, struct ospf_lsa *lsa)
! 682: {
! 683: int lsa_ack_flag = 0;
! 684:
! 685: /* Type-7 LSA's for NSSA are flooded throughout the AS here, and
! 686: upon return are updated in the LSDB for Type-7's. Later,
! 687: re-fresh will re-send them (and also, if ABR, packet code will
! 688: translate to Type-5's)
! 689:
! 690: As usual, Type-5 LSA's (if not DISCARDED because we are STUB or
! 691: NSSA) are flooded throughout the AS, and are updated in the
! 692: global table. */
! 693: #ifdef ORIGINAL_CODING
! 694: switch (lsa->data->type)
! 695: {
! 696: case OSPF_ROUTER_LSA:
! 697: case OSPF_NETWORK_LSA:
! 698: case OSPF_SUMMARY_LSA:
! 699: case OSPF_ASBR_SUMMARY_LSA:
! 700: #ifdef HAVE_OPAQUE_LSA
! 701: case OSPF_OPAQUE_LINK_LSA: /* ospf_flood_through_interface ? */
! 702: case OSPF_OPAQUE_AREA_LSA:
! 703: #endif /* HAVE_OPAQUE_LSA */
! 704: lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa);
! 705: break;
! 706: case OSPF_AS_EXTERNAL_LSA: /* Type-5 */
! 707: #ifdef HAVE_OPAQUE_LSA
! 708: case OSPF_OPAQUE_AS_LSA:
! 709: #endif /* HAVE_OPAQUE_LSA */
! 710: lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa);
! 711: break;
! 712: /* Type-7 Only received within NSSA, then flooded */
! 713: case OSPF_AS_NSSA_LSA:
! 714: /* Any P-bit was installed with the Type-7. */
! 715: lsa_ack_flag = ospf_flood_through_area (inbr->oi->area, inbr, lsa);
! 716:
! 717: if (IS_DEBUG_OSPF_NSSA)
! 718: zlog_debug ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7.");
! 719: break;
! 720: default:
! 721: break;
! 722: }
! 723: #else /* ORIGINAL_CODING */
! 724: /*
! 725: * At the common sub-sub-function "ospf_flood_through_interface()",
! 726: * a parameter "inbr" will be used to distinguish the called context
! 727: * whether the given LSA was received from the neighbor, or the
! 728: * flooding for the LSA starts from this node (e.g. the LSA was self-
! 729: * originated, or the LSA is going to be flushed from routing domain).
! 730: *
! 731: * So, for consistency reasons, this function "ospf_flood_through()"
! 732: * should also allow the usage that the given "inbr" parameter to be
! 733: * NULL. If we do so, corresponding AREA parameter should be referred
! 734: * by "lsa->area", instead of "inbr->oi->area".
! 735: */
! 736: switch (lsa->data->type)
! 737: {
! 738: case OSPF_AS_EXTERNAL_LSA: /* Type-5 */
! 739: #ifdef HAVE_OPAQUE_LSA
! 740: case OSPF_OPAQUE_AS_LSA:
! 741: #endif /* HAVE_OPAQUE_LSA */
! 742: lsa_ack_flag = ospf_flood_through_as (ospf, inbr, lsa);
! 743: break;
! 744: /* Type-7 Only received within NSSA, then flooded */
! 745: case OSPF_AS_NSSA_LSA:
! 746: /* Any P-bit was installed with the Type-7. */
! 747:
! 748: if (IS_DEBUG_OSPF_NSSA)
! 749: zlog_debug ("ospf_flood_through: LOCAL NSSA FLOOD of Type-7.");
! 750: /* Fallthrough */
! 751: default:
! 752: lsa_ack_flag = ospf_flood_through_area (lsa->area, inbr, lsa);
! 753: break;
! 754: }
! 755: #endif /* ORIGINAL_CODING */
! 756:
! 757: return (lsa_ack_flag);
! 758: }
! 759:
! 760:
! 761:
! 762: /* Management functions for neighbor's Link State Request list. */
! 763: void
! 764: ospf_ls_request_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
! 765: {
! 766: /*
! 767: * We cannot make use of the newly introduced callback function
! 768: * "lsdb->new_lsa_hook" to replace debug output below, just because
! 769: * it seems no simple and smart way to pass neighbor information to
! 770: * the common function "ospf_lsdb_add()" -- endo.
! 771: */
! 772: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 773: zlog_debug ("RqstL(%lu)++, NBR(%s), LSA[%s]",
! 774: ospf_ls_request_count (nbr),
! 775: inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
! 776:
! 777: ospf_lsdb_add (&nbr->ls_req, lsa);
! 778: }
! 779:
! 780: unsigned long
! 781: ospf_ls_request_count (struct ospf_neighbor *nbr)
! 782: {
! 783: return ospf_lsdb_count_all (&nbr->ls_req);
! 784: }
! 785:
! 786: int
! 787: ospf_ls_request_isempty (struct ospf_neighbor *nbr)
! 788: {
! 789: return ospf_lsdb_isempty (&nbr->ls_req);
! 790: }
! 791:
! 792: /* Remove LSA from neighbor's ls-request list. */
! 793: void
! 794: ospf_ls_request_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
! 795: {
! 796: if (nbr->ls_req_last == lsa)
! 797: {
! 798: ospf_lsa_unlock (&nbr->ls_req_last);
! 799: nbr->ls_req_last = NULL;
! 800: }
! 801:
! 802: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) /* -- endo. */
! 803: zlog_debug ("RqstL(%lu)--, NBR(%s), LSA[%s]",
! 804: ospf_ls_request_count (nbr),
! 805: inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
! 806:
! 807: ospf_lsdb_delete (&nbr->ls_req, lsa);
! 808: }
! 809:
! 810: /* Remove all LSA from neighbor's ls-requenst list. */
! 811: void
! 812: ospf_ls_request_delete_all (struct ospf_neighbor *nbr)
! 813: {
! 814: ospf_lsa_unlock (&nbr->ls_req_last);
! 815: nbr->ls_req_last = NULL;
! 816: ospf_lsdb_delete_all (&nbr->ls_req);
! 817: }
! 818:
! 819: /* Lookup LSA from neighbor's ls-request list. */
! 820: struct ospf_lsa *
! 821: ospf_ls_request_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
! 822: {
! 823: return ospf_lsdb_lookup (&nbr->ls_req, lsa);
! 824: }
! 825:
! 826: struct ospf_lsa *
! 827: ospf_ls_request_new (struct lsa_header *lsah)
! 828: {
! 829: struct ospf_lsa *new;
! 830:
! 831: new = ospf_lsa_new ();
! 832: new->data = ospf_lsa_data_new (OSPF_LSA_HEADER_SIZE);
! 833: memcpy (new->data, lsah, OSPF_LSA_HEADER_SIZE);
! 834:
! 835: return new;
! 836: }
! 837:
! 838:
! 839: /* Management functions for neighbor's ls-retransmit list. */
! 840: unsigned long
! 841: ospf_ls_retransmit_count (struct ospf_neighbor *nbr)
! 842: {
! 843: return ospf_lsdb_count_all (&nbr->ls_rxmt);
! 844: }
! 845:
! 846: unsigned long
! 847: ospf_ls_retransmit_count_self (struct ospf_neighbor *nbr, int lsa_type)
! 848: {
! 849: return ospf_lsdb_count_self (&nbr->ls_rxmt, lsa_type);
! 850: }
! 851:
! 852: int
! 853: ospf_ls_retransmit_isempty (struct ospf_neighbor *nbr)
! 854: {
! 855: return ospf_lsdb_isempty (&nbr->ls_rxmt);
! 856: }
! 857:
! 858: /* Add LSA to be retransmitted to neighbor's ls-retransmit list. */
! 859: void
! 860: ospf_ls_retransmit_add (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
! 861: {
! 862: struct ospf_lsa *old;
! 863:
! 864: old = ospf_ls_retransmit_lookup (nbr, lsa);
! 865:
! 866: if (ospf_lsa_more_recent (old, lsa) < 0)
! 867: {
! 868: if (old)
! 869: {
! 870: old->retransmit_counter--;
! 871: ospf_lsdb_delete (&nbr->ls_rxmt, old);
! 872: }
! 873: lsa->retransmit_counter++;
! 874: /*
! 875: * We cannot make use of the newly introduced callback function
! 876: * "lsdb->new_lsa_hook" to replace debug output below, just because
! 877: * it seems no simple and smart way to pass neighbor information to
! 878: * the common function "ospf_lsdb_add()" -- endo.
! 879: */
! 880: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 881: zlog_debug ("RXmtL(%lu)++, NBR(%s), LSA[%s]",
! 882: ospf_ls_retransmit_count (nbr),
! 883: inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
! 884: ospf_lsdb_add (&nbr->ls_rxmt, lsa);
! 885: }
! 886: }
! 887:
! 888: /* Remove LSA from neibghbor's ls-retransmit list. */
! 889: void
! 890: ospf_ls_retransmit_delete (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
! 891: {
! 892: if (ospf_ls_retransmit_lookup (nbr, lsa))
! 893: {
! 894: lsa->retransmit_counter--;
! 895: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) /* -- endo. */
! 896: zlog_debug ("RXmtL(%lu)--, NBR(%s), LSA[%s]",
! 897: ospf_ls_retransmit_count (nbr),
! 898: inet_ntoa (nbr->router_id), dump_lsa_key (lsa));
! 899: ospf_lsdb_delete (&nbr->ls_rxmt, lsa);
! 900: }
! 901: }
! 902:
! 903: /* Clear neighbor's ls-retransmit list. */
! 904: void
! 905: ospf_ls_retransmit_clear (struct ospf_neighbor *nbr)
! 906: {
! 907: struct ospf_lsdb *lsdb;
! 908: int i;
! 909:
! 910: lsdb = &nbr->ls_rxmt;
! 911:
! 912: for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
! 913: {
! 914: struct route_table *table = lsdb->type[i].db;
! 915: struct route_node *rn;
! 916: struct ospf_lsa *lsa;
! 917:
! 918: for (rn = route_top (table); rn; rn = route_next (rn))
! 919: if ((lsa = rn->info) != NULL)
! 920: ospf_ls_retransmit_delete (nbr, lsa);
! 921: }
! 922:
! 923: ospf_lsa_unlock (&nbr->ls_req_last);
! 924: nbr->ls_req_last = NULL;
! 925: }
! 926:
! 927: /* Lookup LSA from neighbor's ls-retransmit list. */
! 928: struct ospf_lsa *
! 929: ospf_ls_retransmit_lookup (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
! 930: {
! 931: return ospf_lsdb_lookup (&nbr->ls_rxmt, lsa);
! 932: }
! 933:
! 934: static void
! 935: ospf_ls_retransmit_delete_nbr_if (struct ospf_interface *oi,
! 936: struct ospf_lsa *lsa)
! 937: {
! 938: struct route_node *rn;
! 939: struct ospf_neighbor *nbr;
! 940: struct ospf_lsa *lsr;
! 941:
! 942: if (ospf_if_is_enable (oi))
! 943: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
! 944: /* If LSA find in LS-retransmit list, then remove it. */
! 945: if ((nbr = rn->info) != NULL)
! 946: {
! 947: lsr = ospf_ls_retransmit_lookup (nbr, lsa);
! 948:
! 949: /* If LSA find in ls-retransmit list, remove it. */
! 950: if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
! 951: ospf_ls_retransmit_delete (nbr, lsr);
! 952: }
! 953: }
! 954:
! 955: void
! 956: ospf_ls_retransmit_delete_nbr_area (struct ospf_area *area,
! 957: struct ospf_lsa *lsa)
! 958: {
! 959: struct listnode *node, *nnode;
! 960: struct ospf_interface *oi;
! 961:
! 962: for (ALL_LIST_ELEMENTS (area->oiflist, node, nnode, oi))
! 963: ospf_ls_retransmit_delete_nbr_if (oi, lsa);
! 964: }
! 965:
! 966: void
! 967: ospf_ls_retransmit_delete_nbr_as (struct ospf *ospf, struct ospf_lsa *lsa)
! 968: {
! 969: struct listnode *node, *nnode;
! 970: struct ospf_interface *oi;
! 971:
! 972: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
! 973: ospf_ls_retransmit_delete_nbr_if (oi, lsa);
! 974: }
! 975:
! 976:
! 977: /* Sets ls_age to MaxAge and floods throu the area.
! 978: When we implement ASE routing, there will be anothe function
! 979: flushing an LSA from the whole domain. */
! 980: void
! 981: ospf_lsa_flush_area (struct ospf_lsa *lsa, struct ospf_area *area)
! 982: {
! 983: lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
! 984: ospf_flood_through_area (area, NULL, lsa);
! 985: ospf_lsa_maxage (area->ospf, lsa);
! 986: }
! 987:
! 988: void
! 989: ospf_lsa_flush_as (struct ospf *ospf, struct ospf_lsa *lsa)
! 990: {
! 991: lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
! 992: ospf_flood_through_as (ospf, NULL, lsa);
! 993: ospf_lsa_maxage (ospf, lsa);
! 994: }
! 995:
! 996: void
! 997: ospf_lsa_flush (struct ospf *ospf, struct ospf_lsa *lsa)
! 998: {
! 999: lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
! 1000:
! 1001: switch (lsa->data->type)
! 1002: {
! 1003: case OSPF_ROUTER_LSA:
! 1004: case OSPF_NETWORK_LSA:
! 1005: case OSPF_SUMMARY_LSA:
! 1006: case OSPF_ASBR_SUMMARY_LSA:
! 1007: case OSPF_AS_NSSA_LSA:
! 1008: #ifdef HAVE_OPAQUE_LSA
! 1009: case OSPF_OPAQUE_LINK_LSA:
! 1010: case OSPF_OPAQUE_AREA_LSA:
! 1011: #endif /* HAVE_OPAQUE_LSA */
! 1012: ospf_lsa_flush_area (lsa, lsa->area);
! 1013: break;
! 1014: case OSPF_AS_EXTERNAL_LSA:
! 1015: #ifdef HAVE_OPAQUE_LSA
! 1016: case OSPF_OPAQUE_AS_LSA:
! 1017: #endif /* HAVE_OPAQUE_LSA */
! 1018: ospf_lsa_flush_as (ospf, lsa);
! 1019: break;
! 1020: default:
! 1021: zlog_info ("%s: Unknown LSA type %u", __func__, lsa->data->type);
! 1022: break;
! 1023: }
! 1024: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>