Annotation of embedaddon/quagga/ospf6d/ospf6_flood.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2003 Yasuhiro Ohara
! 3: *
! 4: * This file is part of GNU Zebra.
! 5: *
! 6: * GNU Zebra is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2, or (at your option) any
! 9: * later version.
! 10: *
! 11: * GNU Zebra is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 14: * General Public License for more details.
! 15: *
! 16: * You should have received a copy of the GNU General Public License
! 17: * along with GNU Zebra; see the file COPYING. If not, write to the
! 18: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
! 19: * Boston, MA 02111-1307, USA.
! 20: */
! 21:
! 22: #include <zebra.h>
! 23:
! 24: #include "log.h"
! 25: #include "thread.h"
! 26: #include "linklist.h"
! 27: #include "vty.h"
! 28: #include "command.h"
! 29:
! 30: #include "ospf6d.h"
! 31: #include "ospf6_proto.h"
! 32: #include "ospf6_lsa.h"
! 33: #include "ospf6_lsdb.h"
! 34: #include "ospf6_message.h"
! 35: #include "ospf6_route.h"
! 36: #include "ospf6_spf.h"
! 37:
! 38: #include "ospf6_top.h"
! 39: #include "ospf6_area.h"
! 40: #include "ospf6_interface.h"
! 41: #include "ospf6_neighbor.h"
! 42:
! 43: #include "ospf6_flood.h"
! 44:
! 45: unsigned char conf_debug_ospf6_flooding;
! 46:
! 47: struct ospf6_lsdb *
! 48: ospf6_get_scoped_lsdb (struct ospf6_lsa *lsa)
! 49: {
! 50: struct ospf6_lsdb *lsdb = NULL;
! 51: switch (OSPF6_LSA_SCOPE (lsa->header->type))
! 52: {
! 53: case OSPF6_SCOPE_LINKLOCAL:
! 54: lsdb = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb;
! 55: break;
! 56: case OSPF6_SCOPE_AREA:
! 57: lsdb = OSPF6_AREA (lsa->lsdb->data)->lsdb;
! 58: break;
! 59: case OSPF6_SCOPE_AS:
! 60: lsdb = OSPF6_PROCESS (lsa->lsdb->data)->lsdb;
! 61: break;
! 62: default:
! 63: assert (0);
! 64: break;
! 65: }
! 66: return lsdb;
! 67: }
! 68:
! 69: struct ospf6_lsdb *
! 70: ospf6_get_scoped_lsdb_self (struct ospf6_lsa *lsa)
! 71: {
! 72: struct ospf6_lsdb *lsdb_self = NULL;
! 73: switch (OSPF6_LSA_SCOPE (lsa->header->type))
! 74: {
! 75: case OSPF6_SCOPE_LINKLOCAL:
! 76: lsdb_self = OSPF6_INTERFACE (lsa->lsdb->data)->lsdb_self;
! 77: break;
! 78: case OSPF6_SCOPE_AREA:
! 79: lsdb_self = OSPF6_AREA (lsa->lsdb->data)->lsdb_self;
! 80: break;
! 81: case OSPF6_SCOPE_AS:
! 82: lsdb_self = OSPF6_PROCESS (lsa->lsdb->data)->lsdb_self;
! 83: break;
! 84: default:
! 85: assert (0);
! 86: break;
! 87: }
! 88: return lsdb_self;
! 89: }
! 90:
! 91: void
! 92: ospf6_lsa_originate (struct ospf6_lsa *lsa)
! 93: {
! 94: struct ospf6_lsa *old;
! 95: struct ospf6_lsdb *lsdb_self;
! 96:
! 97: /* find previous LSA */
! 98: old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
! 99: lsa->header->adv_router, lsa->lsdb);
! 100:
! 101: /* if the new LSA does not differ from previous,
! 102: suppress this update of the LSA */
! 103: if (old && ! OSPF6_LSA_IS_DIFFER (lsa, old))
! 104: {
! 105: if (IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
! 106: zlog_debug ("Suppress updating LSA: %s", lsa->name);
! 107: ospf6_lsa_delete (lsa);
! 108: return;
! 109: }
! 110:
! 111: /* store it in the LSDB for self-originated LSAs */
! 112: lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
! 113: ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
! 114:
! 115: lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
! 116: LS_REFRESH_TIME);
! 117:
! 118: if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
! 119: IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
! 120: {
! 121: zlog_debug ("LSA Originate:");
! 122: ospf6_lsa_header_print (lsa);
! 123: }
! 124:
! 125: if (old)
! 126: ospf6_flood_clear (old);
! 127: ospf6_flood (NULL, lsa);
! 128: ospf6_install_lsa (lsa);
! 129: }
! 130:
! 131: void
! 132: ospf6_lsa_originate_process (struct ospf6_lsa *lsa,
! 133: struct ospf6 *process)
! 134: {
! 135: lsa->lsdb = process->lsdb;
! 136: ospf6_lsa_originate (lsa);
! 137: }
! 138:
! 139: void
! 140: ospf6_lsa_originate_area (struct ospf6_lsa *lsa,
! 141: struct ospf6_area *oa)
! 142: {
! 143: lsa->lsdb = oa->lsdb;
! 144: ospf6_lsa_originate (lsa);
! 145: }
! 146:
! 147: void
! 148: ospf6_lsa_originate_interface (struct ospf6_lsa *lsa,
! 149: struct ospf6_interface *oi)
! 150: {
! 151: lsa->lsdb = oi->lsdb;
! 152: ospf6_lsa_originate (lsa);
! 153: }
! 154:
! 155: void
! 156: ospf6_lsa_purge (struct ospf6_lsa *lsa)
! 157: {
! 158: struct ospf6_lsa *self;
! 159: struct ospf6_lsdb *lsdb_self;
! 160:
! 161: /* remove it from the LSDB for self-originated LSAs */
! 162: lsdb_self = ospf6_get_scoped_lsdb_self (lsa);
! 163: self = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
! 164: lsa->header->adv_router, lsdb_self);
! 165: if (self)
! 166: {
! 167: THREAD_OFF (self->expire);
! 168: THREAD_OFF (self->refresh);
! 169: ospf6_lsdb_remove (self, lsdb_self);
! 170: }
! 171:
! 172: ospf6_lsa_premature_aging (lsa);
! 173: }
! 174:
! 175:
! 176: void
! 177: ospf6_increment_retrans_count (struct ospf6_lsa *lsa)
! 178: {
! 179: /* The LSA must be the original one (see the description
! 180: in ospf6_decrement_retrans_count () below) */
! 181: lsa->retrans_count++;
! 182: }
! 183:
! 184: void
! 185: ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
! 186: {
! 187: struct ospf6_lsdb *lsdb;
! 188: struct ospf6_lsa *orig;
! 189:
! 190: /* The LSA must be on the retrans-list of a neighbor. It means
! 191: the "lsa" is a copied one, and we have to decrement the
! 192: retransmission count of the original one (instead of this "lsa"'s).
! 193: In order to find the original LSA, first we have to find
! 194: appropriate LSDB that have the original LSA. */
! 195: lsdb = ospf6_get_scoped_lsdb (lsa);
! 196:
! 197: /* Find the original LSA of which the retrans_count should be decremented */
! 198: orig = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
! 199: lsa->header->adv_router, lsdb);
! 200: if (orig)
! 201: {
! 202: orig->retrans_count--;
! 203: assert (orig->retrans_count >= 0);
! 204: }
! 205: }
! 206:
! 207: /* RFC2328 section 13.2 Installing LSAs in the database */
! 208: void
! 209: ospf6_install_lsa (struct ospf6_lsa *lsa)
! 210: {
! 211: struct ospf6_lsa *old;
! 212: struct timeval now;
! 213:
! 214: if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
! 215: IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
! 216: zlog_debug ("Install LSA: %s", lsa->name);
! 217:
! 218: /* Remove the old instance from all neighbors' Link state
! 219: retransmission list (RFC2328 13.2 last paragraph) */
! 220: old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
! 221: lsa->header->adv_router, lsa->lsdb);
! 222: if (old)
! 223: {
! 224: THREAD_OFF (old->expire);
! 225: ospf6_flood_clear (old);
! 226: }
! 227:
! 228: quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
! 229: if (! OSPF6_LSA_IS_MAXAGE (lsa))
! 230: lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
! 231: MAXAGE + lsa->birth.tv_sec - now.tv_sec);
! 232: else
! 233: lsa->expire = NULL;
! 234:
! 235: /* actually install */
! 236: lsa->installed = now;
! 237: ospf6_lsdb_add (lsa, lsa->lsdb);
! 238:
! 239: return;
! 240: }
! 241:
! 242: /* RFC2740 section 3.5.2. Sending Link State Update packets */
! 243: /* RFC2328 section 13.3 Next step in the flooding procedure */
! 244: static void
! 245: ospf6_flood_interface (struct ospf6_neighbor *from,
! 246: struct ospf6_lsa *lsa, struct ospf6_interface *oi)
! 247: {
! 248: struct listnode *node, *nnode;
! 249: struct ospf6_neighbor *on;
! 250: struct ospf6_lsa *req;
! 251: int retrans_added = 0;
! 252: int is_debug = 0;
! 253:
! 254: if (IS_OSPF6_DEBUG_FLOODING ||
! 255: IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
! 256: {
! 257: is_debug++;
! 258: zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name);
! 259: }
! 260:
! 261: /* (1) For each neighbor */
! 262: for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
! 263: {
! 264: if (is_debug)
! 265: zlog_debug ("To neighbor %s", on->name);
! 266:
! 267: /* (a) if neighbor state < Exchange, examin next */
! 268: if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
! 269: {
! 270: if (is_debug)
! 271: zlog_debug ("Neighbor state less than ExChange, next neighbor");
! 272: continue;
! 273: }
! 274:
! 275: /* (b) if neighbor not yet Full, check request-list */
! 276: if (on->state != OSPF6_NEIGHBOR_FULL)
! 277: {
! 278: if (is_debug)
! 279: zlog_debug ("Neighbor not yet Full");
! 280:
! 281: req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
! 282: lsa->header->adv_router, on->request_list);
! 283: if (req == NULL)
! 284: {
! 285: if (is_debug)
! 286: zlog_debug ("Not on request-list for this neighbor");
! 287: /* fall through */
! 288: }
! 289: else
! 290: {
! 291: /* If new LSA less recent, examin next neighbor */
! 292: if (ospf6_lsa_compare (lsa, req) > 0)
! 293: {
! 294: if (is_debug)
! 295: zlog_debug ("Requesting is newer, next neighbor");
! 296: continue;
! 297: }
! 298:
! 299: /* If the same instance, delete from request-list and
! 300: examin next neighbor */
! 301: if (ospf6_lsa_compare (lsa, req) == 0)
! 302: {
! 303: if (is_debug)
! 304: zlog_debug ("Requesting the same, remove it, next neighbor");
! 305: ospf6_lsdb_remove (req, on->request_list);
! 306: continue;
! 307: }
! 308:
! 309: /* If the new LSA is more recent, delete from request-list */
! 310: if (ospf6_lsa_compare (lsa, req) < 0)
! 311: {
! 312: if (is_debug)
! 313: zlog_debug ("Received is newer, remove requesting");
! 314: ospf6_lsdb_remove (req, on->request_list);
! 315: /* fall through */
! 316: }
! 317: }
! 318: }
! 319:
! 320: /* (c) If the new LSA was received from this neighbor,
! 321: examin next neighbor */
! 322: if (from == on)
! 323: {
! 324: if (is_debug)
! 325: zlog_debug ("Received is from the neighbor, next neighbor");
! 326: continue;
! 327: }
! 328:
! 329: /* (d) add retrans-list, schedule retransmission */
! 330: if (is_debug)
! 331: zlog_debug ("Add retrans-list of this neighbor");
! 332: ospf6_increment_retrans_count (lsa);
! 333: ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
! 334: if (on->thread_send_lsupdate == NULL)
! 335: on->thread_send_lsupdate =
! 336: thread_add_timer (master, ospf6_lsupdate_send_neighbor,
! 337: on, on->ospf6_if->rxmt_interval);
! 338: retrans_added++;
! 339: }
! 340:
! 341: /* (2) examin next interface if not added to retrans-list */
! 342: if (retrans_added == 0)
! 343: {
! 344: if (is_debug)
! 345: zlog_debug ("No retransmission scheduled, next interface");
! 346: return;
! 347: }
! 348:
! 349: /* (3) If the new LSA was received on this interface,
! 350: and it was from DR or BDR, examin next interface */
! 351: if (from && from->ospf6_if == oi &&
! 352: (from->router_id == oi->drouter || from->router_id == oi->bdrouter))
! 353: {
! 354: if (is_debug)
! 355: zlog_debug ("Received is from the I/F's DR or BDR, next interface");
! 356: return;
! 357: }
! 358:
! 359: /* (4) If the new LSA was received on this interface,
! 360: and the interface state is BDR, examin next interface */
! 361: if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
! 362: {
! 363: if (is_debug)
! 364: zlog_debug ("Received is from the I/F, itself BDR, next interface");
! 365: return;
! 366: }
! 367:
! 368: /* (5) flood the LSA out the interface. */
! 369: if (is_debug)
! 370: zlog_debug ("Schedule flooding for the interface");
! 371: if (if_is_broadcast (oi->interface))
! 372: {
! 373: ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
! 374: if (oi->thread_send_lsupdate == NULL)
! 375: oi->thread_send_lsupdate =
! 376: thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
! 377: }
! 378: else
! 379: {
! 380: /* reschedule retransmissions to all neighbors */
! 381: for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
! 382: {
! 383: THREAD_OFF (on->thread_send_lsupdate);
! 384: on->thread_send_lsupdate =
! 385: thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
! 386: }
! 387: }
! 388: }
! 389:
! 390: static void
! 391: ospf6_flood_area (struct ospf6_neighbor *from,
! 392: struct ospf6_lsa *lsa, struct ospf6_area *oa)
! 393: {
! 394: struct listnode *node, *nnode;
! 395: struct ospf6_interface *oi;
! 396:
! 397: for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
! 398: {
! 399: if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
! 400: oi != OSPF6_INTERFACE (lsa->lsdb->data))
! 401: continue;
! 402:
! 403: #if 0
! 404: if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
! 405: ospf6_is_interface_virtual_link (oi))
! 406: continue;
! 407: #endif/*0*/
! 408:
! 409: ospf6_flood_interface (from, lsa, oi);
! 410: }
! 411: }
! 412:
! 413: static void
! 414: ospf6_flood_process (struct ospf6_neighbor *from,
! 415: struct ospf6_lsa *lsa, struct ospf6 *process)
! 416: {
! 417: struct listnode *node, *nnode;
! 418: struct ospf6_area *oa;
! 419:
! 420: for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa))
! 421: {
! 422: if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
! 423: oa != OSPF6_AREA (lsa->lsdb->data))
! 424: continue;
! 425: if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
! 426: oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
! 427: continue;
! 428:
! 429: if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
! 430: IS_AREA_STUB (oa))
! 431: continue;
! 432:
! 433: ospf6_flood_area (from, lsa, oa);
! 434: }
! 435: }
! 436:
! 437: void
! 438: ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa)
! 439: {
! 440: ospf6_flood_process (from, lsa, ospf6);
! 441: }
! 442:
! 443: static void
! 444: ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi)
! 445: {
! 446: struct listnode *node, *nnode;
! 447: struct ospf6_neighbor *on;
! 448: struct ospf6_lsa *rem;
! 449:
! 450: for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
! 451: {
! 452: rem = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
! 453: lsa->header->adv_router, on->retrans_list);
! 454: if (rem && ! ospf6_lsa_compare (rem, lsa))
! 455: {
! 456: if (IS_OSPF6_DEBUG_FLOODING ||
! 457: IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
! 458: zlog_debug ("Remove %s from retrans_list of %s",
! 459: rem->name, on->name);
! 460: ospf6_decrement_retrans_count (rem);
! 461: ospf6_lsdb_remove (rem, on->retrans_list);
! 462: }
! 463: }
! 464: }
! 465:
! 466: static void
! 467: ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa)
! 468: {
! 469: struct listnode *node, *nnode;
! 470: struct ospf6_interface *oi;
! 471:
! 472: for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
! 473: {
! 474: if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
! 475: oi != OSPF6_INTERFACE (lsa->lsdb->data))
! 476: continue;
! 477:
! 478: #if 0
! 479: if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS &&
! 480: ospf6_is_interface_virtual_link (oi))
! 481: continue;
! 482: #endif/*0*/
! 483:
! 484: ospf6_flood_clear_interface (lsa, oi);
! 485: }
! 486: }
! 487:
! 488: static void
! 489: ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process)
! 490: {
! 491: struct listnode *node, *nnode;
! 492: struct ospf6_area *oa;
! 493:
! 494: for (ALL_LIST_ELEMENTS (process->area_list, node, nnode, oa))
! 495: {
! 496: if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AREA &&
! 497: oa != OSPF6_AREA (lsa->lsdb->data))
! 498: continue;
! 499: if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_LINKLOCAL &&
! 500: oa != OSPF6_INTERFACE (lsa->lsdb->data)->area)
! 501: continue;
! 502:
! 503: if (ntohs (lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
! 504: IS_AREA_STUB (oa))
! 505: continue;
! 506:
! 507: ospf6_flood_clear_area (lsa, oa);
! 508: }
! 509: }
! 510:
! 511: void
! 512: ospf6_flood_clear (struct ospf6_lsa *lsa)
! 513: {
! 514: ospf6_flood_clear_process (lsa, ospf6);
! 515: }
! 516:
! 517:
! 518: /* RFC2328 13.5 (Table 19): Sending link state acknowledgements. */
! 519: static void
! 520: ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
! 521: struct ospf6_neighbor *from)
! 522: {
! 523: struct ospf6_interface *oi;
! 524: int is_debug = 0;
! 525:
! 526: if (IS_OSPF6_DEBUG_FLOODING ||
! 527: IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
! 528: is_debug++;
! 529:
! 530: assert (from && from->ospf6_if);
! 531: oi = from->ospf6_if;
! 532:
! 533: /* LSA has been flood back out receiving interface.
! 534: No acknowledgement sent. */
! 535: if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
! 536: {
! 537: if (is_debug)
! 538: zlog_debug ("No acknowledgement (BDR & FloodBack)");
! 539: return;
! 540: }
! 541:
! 542: /* LSA is more recent than database copy, but was not flooded
! 543: back out receiving interface. Delayed acknowledgement sent
! 544: if advertisement received from Designated Router,
! 545: otherwide do nothing. */
! 546: if (ismore_recent < 0)
! 547: {
! 548: if (oi->drouter == from->router_id)
! 549: {
! 550: if (is_debug)
! 551: zlog_debug ("Delayed acknowledgement (BDR & MoreRecent & from DR)");
! 552: /* Delayed acknowledgement */
! 553: ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
! 554: if (oi->thread_send_lsack == NULL)
! 555: oi->thread_send_lsack =
! 556: thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
! 557: }
! 558: else
! 559: {
! 560: if (is_debug)
! 561: zlog_debug ("No acknowledgement (BDR & MoreRecent & ! from DR)");
! 562: }
! 563: return;
! 564: }
! 565:
! 566: /* LSA is a duplicate, and was treated as an implied acknowledgement.
! 567: Delayed acknowledgement sent if advertisement received from
! 568: Designated Router, otherwise do nothing */
! 569: if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
! 570: CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
! 571: {
! 572: if (oi->drouter == from->router_id)
! 573: {
! 574: if (is_debug)
! 575: zlog_debug ("Delayed acknowledgement (BDR & Duplicate & ImpliedAck & from DR)");
! 576: /* Delayed acknowledgement */
! 577: ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
! 578: if (oi->thread_send_lsack == NULL)
! 579: oi->thread_send_lsack =
! 580: thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
! 581: }
! 582: else
! 583: {
! 584: if (is_debug)
! 585: zlog_debug ("No acknowledgement (BDR & Duplicate & ImpliedAck & ! from DR)");
! 586: }
! 587: return;
! 588: }
! 589:
! 590: /* LSA is a duplicate, and was not treated as an implied acknowledgement.
! 591: Direct acknowledgement sent */
! 592: if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
! 593: ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
! 594: {
! 595: if (is_debug)
! 596: zlog_debug ("Direct acknowledgement (BDR & Duplicate)");
! 597: ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
! 598: if (from->thread_send_lsack == NULL)
! 599: from->thread_send_lsack =
! 600: thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
! 601: return;
! 602: }
! 603:
! 604: /* LSA's LS age is equal to Maxage, and there is no current instance
! 605: of the LSA in the link state database, and none of router's
! 606: neighbors are in states Exchange or Loading */
! 607: /* Direct acknowledgement sent, but this case is handled in
! 608: early of ospf6_receive_lsa () */
! 609: }
! 610:
! 611: static void
! 612: ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent,
! 613: struct ospf6_neighbor *from)
! 614: {
! 615: struct ospf6_interface *oi;
! 616: int is_debug = 0;
! 617:
! 618: if (IS_OSPF6_DEBUG_FLOODING ||
! 619: IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type))
! 620: is_debug++;
! 621:
! 622: assert (from && from->ospf6_if);
! 623: oi = from->ospf6_if;
! 624:
! 625: /* LSA has been flood back out receiving interface.
! 626: No acknowledgement sent. */
! 627: if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
! 628: {
! 629: if (is_debug)
! 630: zlog_debug ("No acknowledgement (AllOther & FloodBack)");
! 631: return;
! 632: }
! 633:
! 634: /* LSA is more recent than database copy, but was not flooded
! 635: back out receiving interface. Delayed acknowledgement sent. */
! 636: if (ismore_recent < 0)
! 637: {
! 638: if (is_debug)
! 639: zlog_debug ("Delayed acknowledgement (AllOther & MoreRecent)");
! 640: /* Delayed acknowledgement */
! 641: ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list);
! 642: if (oi->thread_send_lsack == NULL)
! 643: oi->thread_send_lsack =
! 644: thread_add_timer (master, ospf6_lsack_send_interface, oi, 3);
! 645: return;
! 646: }
! 647:
! 648: /* LSA is a duplicate, and was treated as an implied acknowledgement.
! 649: No acknowledgement sent. */
! 650: if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
! 651: CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
! 652: {
! 653: if (is_debug)
! 654: zlog_debug ("No acknowledgement (AllOther & Duplicate & ImpliedAck)");
! 655: return;
! 656: }
! 657:
! 658: /* LSA is a duplicate, and was not treated as an implied acknowledgement.
! 659: Direct acknowledgement sent */
! 660: if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) &&
! 661: ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK))
! 662: {
! 663: if (is_debug)
! 664: zlog_debug ("Direct acknowledgement (AllOther & Duplicate)");
! 665: ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list);
! 666: if (from->thread_send_lsack == NULL)
! 667: from->thread_send_lsack =
! 668: thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
! 669: return;
! 670: }
! 671:
! 672: /* LSA's LS age is equal to Maxage, and there is no current instance
! 673: of the LSA in the link state database, and none of router's
! 674: neighbors are in states Exchange or Loading */
! 675: /* Direct acknowledgement sent, but this case is handled in
! 676: early of ospf6_receive_lsa () */
! 677: }
! 678:
! 679: static void
! 680: ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent,
! 681: struct ospf6_neighbor *from)
! 682: {
! 683: struct ospf6_interface *oi;
! 684:
! 685: assert (from && from->ospf6_if);
! 686: oi = from->ospf6_if;
! 687:
! 688: if (oi->state == OSPF6_INTERFACE_BDR)
! 689: ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from);
! 690: else
! 691: ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from);
! 692: }
! 693:
! 694: /* RFC2328 section 13 (4):
! 695: if MaxAge LSA and if we have no instance, and no neighbor
! 696: is in states Exchange or Loading
! 697: returns 1 if match this case, else returns 0 */
! 698: static int
! 699: ospf6_is_maxage_lsa_drop (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
! 700: {
! 701: struct ospf6_neighbor *on;
! 702: struct ospf6_interface *oi;
! 703: struct ospf6_area *oa;
! 704: struct ospf6 *process = NULL;
! 705: struct listnode *i, *j, *k;
! 706: int count = 0;
! 707:
! 708: if (! OSPF6_LSA_IS_MAXAGE (lsa))
! 709: return 0;
! 710:
! 711: if (ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
! 712: lsa->header->adv_router, lsa->lsdb))
! 713: return 0;
! 714:
! 715: process = from->ospf6_if->area->ospf6;
! 716:
! 717: for (ALL_LIST_ELEMENTS_RO (process->area_list, i, oa))
! 718: for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
! 719: for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, k, on))
! 720: if (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
! 721: on->state == OSPF6_NEIGHBOR_LOADING)
! 722: count++;
! 723:
! 724: if (count == 0)
! 725: return 1;
! 726: return 0;
! 727: }
! 728:
! 729: /* RFC2328 section 13 The Flooding Procedure */
! 730: void
! 731: ospf6_receive_lsa (struct ospf6_neighbor *from,
! 732: struct ospf6_lsa_header *lsa_header)
! 733: {
! 734: struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL;
! 735: int ismore_recent;
! 736: unsigned short cksum;
! 737: int is_debug = 0;
! 738:
! 739: ismore_recent = 1;
! 740: assert (from);
! 741:
! 742: /* make lsa structure for received lsa */
! 743: new = ospf6_lsa_create (lsa_header);
! 744:
! 745: if (IS_OSPF6_DEBUG_FLOODING ||
! 746: IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type))
! 747: {
! 748: is_debug++;
! 749: zlog_debug ("LSA Receive from %s", from->name);
! 750: ospf6_lsa_header_print (new);
! 751: }
! 752:
! 753: /* (1) LSA Checksum */
! 754: cksum = ntohs (new->header->checksum);
! 755: if (ntohs (ospf6_lsa_checksum (new->header)) != cksum)
! 756: {
! 757: if (is_debug)
! 758: zlog_debug ("Wrong LSA Checksum, discard");
! 759: ospf6_lsa_delete (new);
! 760: return;
! 761: }
! 762:
! 763: /* (2) Examine the LSA's LS type.
! 764: RFC2470 3.5.1. Receiving Link State Update packets */
! 765: if (IS_AREA_STUB (from->ospf6_if->area) &&
! 766: OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS)
! 767: {
! 768: if (is_debug)
! 769: zlog_debug ("AS-External-LSA (or AS-scope LSA) in stub area, discard");
! 770: ospf6_lsa_delete (new);
! 771: return;
! 772: }
! 773:
! 774: /* (3) LSA which have reserved scope is discarded
! 775: RFC2470 3.5.1. Receiving Link State Update packets */
! 776: /* Flooding scope check. LSAs with unknown scope are discarded here.
! 777: Set appropriate LSDB for the LSA */
! 778: switch (OSPF6_LSA_SCOPE (new->header->type))
! 779: {
! 780: case OSPF6_SCOPE_LINKLOCAL:
! 781: new->lsdb = from->ospf6_if->lsdb;
! 782: break;
! 783: case OSPF6_SCOPE_AREA:
! 784: new->lsdb = from->ospf6_if->area->lsdb;
! 785: break;
! 786: case OSPF6_SCOPE_AS:
! 787: new->lsdb = from->ospf6_if->area->ospf6->lsdb;
! 788: break;
! 789: default:
! 790: if (is_debug)
! 791: zlog_debug ("LSA has reserved scope, discard");
! 792: ospf6_lsa_delete (new);
! 793: return;
! 794: }
! 795:
! 796: /* (4) if MaxAge LSA and if we have no instance, and no neighbor
! 797: is in states Exchange or Loading */
! 798: if (ospf6_is_maxage_lsa_drop (new, from))
! 799: {
! 800: /* log */
! 801: if (is_debug)
! 802: zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
! 803:
! 804: /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
! 805: ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
! 806: if (from->thread_send_lsack == NULL)
! 807: from->thread_send_lsack =
! 808: thread_add_event (master, ospf6_lsack_send_neighbor, from, 0);
! 809:
! 810: /* b) Discard */
! 811: ospf6_lsa_delete (new);
! 812: return;
! 813: }
! 814:
! 815: /* (5) */
! 816: /* lookup the same database copy in lsdb */
! 817: old = ospf6_lsdb_lookup (new->header->type, new->header->id,
! 818: new->header->adv_router, new->lsdb);
! 819: if (old)
! 820: {
! 821: ismore_recent = ospf6_lsa_compare (new, old);
! 822: if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum))
! 823: {
! 824: if (is_debug)
! 825: zlog_debug ("Received is duplicated LSA");
! 826: SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE);
! 827: }
! 828: }
! 829:
! 830: /* if no database copy or received is more recent */
! 831: if (old == NULL || ismore_recent < 0)
! 832: {
! 833: /* in case we have no database copy */
! 834: ismore_recent = -1;
! 835:
! 836: /* (a) MinLSArrival check */
! 837: if (old)
! 838: {
! 839: struct timeval now, res;
! 840: quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
! 841: timersub (&now, &old->installed, &res);
! 842: if (res.tv_sec < MIN_LS_ARRIVAL)
! 843: {
! 844: if (is_debug)
! 845: zlog_debug ("LSA can't be updated within MinLSArrival, discard");
! 846: ospf6_lsa_delete (new);
! 847: return; /* examin next lsa */
! 848: }
! 849: }
! 850:
! 851: quagga_gettime (QUAGGA_CLK_MONOTONIC, &new->received);
! 852:
! 853: if (is_debug)
! 854: zlog_debug ("Flood, Install, Possibly acknowledge the received LSA");
! 855:
! 856: /* (b) immediately flood and (c) remove from all retrans-list */
! 857: /* Prevent self-originated LSA to be flooded. this is to make
! 858: reoriginated instance of the LSA not to be rejected by other routers
! 859: due to MinLSArrival. */
! 860: if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id)
! 861: ospf6_flood (from, new);
! 862:
! 863: /* (c) Remove the current database copy from all neighbors' Link
! 864: state retransmission lists. */
! 865: /* XXX, flood_clear ? */
! 866:
! 867: /* (d), installing lsdb, which may cause routing
! 868: table calculation (replacing database copy) */
! 869: ospf6_install_lsa (new);
! 870:
! 871: /* (e) possibly acknowledge */
! 872: ospf6_acknowledge_lsa (new, ismore_recent, from);
! 873:
! 874: /* (f) Self Originated LSA, section 13.4 */
! 875: if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id)
! 876: {
! 877: /* Self-originated LSA (newer than ours) is received from
! 878: another router. We have to make a new instance of the LSA
! 879: or have to flush this LSA. */
! 880: if (is_debug)
! 881: {
! 882: zlog_debug ("Newer instance of the self-originated LSA");
! 883: zlog_debug ("Schedule reorigination");
! 884: }
! 885: new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0);
! 886: }
! 887:
! 888: return;
! 889: }
! 890:
! 891: /* (6) if there is instance on sending neighbor's request list */
! 892: if (ospf6_lsdb_lookup (new->header->type, new->header->id,
! 893: new->header->adv_router, from->request_list))
! 894: {
! 895: /* if no database copy, should go above state (5) */
! 896: assert (old);
! 897:
! 898: if (is_debug)
! 899: {
! 900: zlog_debug ("Received is not newer, on the neighbor's request-list");
! 901: zlog_debug ("BadLSReq, discard the received LSA");
! 902: }
! 903:
! 904: /* BadLSReq */
! 905: thread_add_event (master, bad_lsreq, from, 0);
! 906:
! 907: ospf6_lsa_delete (new);
! 908: return;
! 909: }
! 910:
! 911: /* (7) if neither one is more recent */
! 912: if (ismore_recent == 0)
! 913: {
! 914: if (is_debug)
! 915: zlog_debug ("The same instance as database copy (neither recent)");
! 916:
! 917: /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */
! 918: rem = ospf6_lsdb_lookup (new->header->type, new->header->id,
! 919: new->header->adv_router, from->retrans_list);
! 920: if (rem)
! 921: {
! 922: if (is_debug)
! 923: {
! 924: zlog_debug ("It is on the neighbor's retrans-list.");
! 925: zlog_debug ("Treat as an Implied acknowledgement");
! 926: }
! 927: SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK);
! 928: ospf6_decrement_retrans_count (rem);
! 929: ospf6_lsdb_remove (rem, from->retrans_list);
! 930: }
! 931:
! 932: if (is_debug)
! 933: zlog_debug ("Possibly acknowledge and then discard");
! 934:
! 935: /* (b) possibly acknowledge */
! 936: ospf6_acknowledge_lsa (new, ismore_recent, from);
! 937:
! 938: ospf6_lsa_delete (new);
! 939: return;
! 940: }
! 941:
! 942: /* (8) previous database copy is more recent */
! 943: {
! 944: assert (old);
! 945:
! 946: /* If database copy is in 'Seqnumber Wrapping',
! 947: simply discard the received LSA */
! 948: if (OSPF6_LSA_IS_MAXAGE (old) &&
! 949: old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
! 950: {
! 951: if (is_debug)
! 952: {
! 953: zlog_debug ("The LSA is in Seqnumber Wrapping");
! 954: zlog_debug ("MaxAge & MaxSeqNum, discard");
! 955: }
! 956: ospf6_lsa_delete (new);
! 957: return;
! 958: }
! 959:
! 960: /* Otherwise, Send database copy of this LSA to this neighbor */
! 961: {
! 962: if (is_debug)
! 963: {
! 964: zlog_debug ("Database copy is more recent.");
! 965: zlog_debug ("Send back directly and then discard");
! 966: }
! 967:
! 968: /* XXX, MinLSArrival check !? RFC 2328 13 (8) */
! 969:
! 970: ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list);
! 971: if (from->thread_send_lsupdate == NULL)
! 972: from->thread_send_lsupdate =
! 973: thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
! 974: ospf6_lsa_delete (new);
! 975: return;
! 976: }
! 977: return;
! 978: }
! 979: }
! 980:
! 981:
! 982: DEFUN (debug_ospf6_flooding,
! 983: debug_ospf6_flooding_cmd,
! 984: "debug ospf6 flooding",
! 985: DEBUG_STR
! 986: OSPF6_STR
! 987: "Debug OSPFv3 flooding function\n"
! 988: )
! 989: {
! 990: OSPF6_DEBUG_FLOODING_ON ();
! 991: return CMD_SUCCESS;
! 992: }
! 993:
! 994: DEFUN (no_debug_ospf6_flooding,
! 995: no_debug_ospf6_flooding_cmd,
! 996: "no debug ospf6 flooding",
! 997: NO_STR
! 998: DEBUG_STR
! 999: OSPF6_STR
! 1000: "Debug OSPFv3 flooding function\n"
! 1001: )
! 1002: {
! 1003: OSPF6_DEBUG_FLOODING_OFF ();
! 1004: return CMD_SUCCESS;
! 1005: }
! 1006:
! 1007: int
! 1008: config_write_ospf6_debug_flood (struct vty *vty)
! 1009: {
! 1010: if (IS_OSPF6_DEBUG_FLOODING)
! 1011: vty_out (vty, "debug ospf6 flooding%s", VNL);
! 1012: return 0;
! 1013: }
! 1014:
! 1015: void
! 1016: install_element_ospf6_debug_flood (void)
! 1017: {
! 1018: install_element (ENABLE_NODE, &debug_ospf6_flooding_cmd);
! 1019: install_element (ENABLE_NODE, &no_debug_ospf6_flooding_cmd);
! 1020: install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd);
! 1021: install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd);
! 1022: }
! 1023:
! 1024:
! 1025:
! 1026:
! 1027:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>