Annotation of embedaddon/quagga/ospfd/ospf_lsa.c, revision 1.1
1.1 ! misho 1: /*
! 2: * OSPF Link State Advertisement
! 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 it
! 8: * under the terms of the GNU General Public License as published by the
! 9: * Free Software Foundation; either version 2, or (at your option) any
! 10: * 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 Free
! 19: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 20: * 02111-1307, USA.
! 21: */
! 22:
! 23: #include <zebra.h>
! 24:
! 25: #include "linklist.h"
! 26: #include "prefix.h"
! 27: #include "if.h"
! 28: #include "table.h"
! 29: #include "memory.h"
! 30: #include "stream.h"
! 31: #include "log.h"
! 32: #include "thread.h"
! 33: #include "hash.h"
! 34: #include "sockunion.h" /* for inet_aton() */
! 35: #include "checksum.h"
! 36:
! 37: #include "ospfd/ospfd.h"
! 38: #include "ospfd/ospf_interface.h"
! 39: #include "ospfd/ospf_ism.h"
! 40: #include "ospfd/ospf_asbr.h"
! 41: #include "ospfd/ospf_lsa.h"
! 42: #include "ospfd/ospf_lsdb.h"
! 43: #include "ospfd/ospf_neighbor.h"
! 44: #include "ospfd/ospf_nsm.h"
! 45: #include "ospfd/ospf_flood.h"
! 46: #include "ospfd/ospf_packet.h"
! 47: #include "ospfd/ospf_spf.h"
! 48: #include "ospfd/ospf_dump.h"
! 49: #include "ospfd/ospf_route.h"
! 50: #include "ospfd/ospf_ase.h"
! 51: #include "ospfd/ospf_zebra.h"
! 52:
! 53:
! 54: u_int32_t
! 55: get_metric (u_char *metric)
! 56: {
! 57: u_int32_t m;
! 58: m = metric[0];
! 59: m = (m << 8) + metric[1];
! 60: m = (m << 8) + metric[2];
! 61: return m;
! 62: }
! 63:
! 64:
! 65: struct timeval
! 66: tv_adjust (struct timeval a)
! 67: {
! 68: while (a.tv_usec >= 1000000)
! 69: {
! 70: a.tv_usec -= 1000000;
! 71: a.tv_sec++;
! 72: }
! 73:
! 74: while (a.tv_usec < 0)
! 75: {
! 76: a.tv_usec += 1000000;
! 77: a.tv_sec--;
! 78: }
! 79:
! 80: return a;
! 81: }
! 82:
! 83: int
! 84: tv_ceil (struct timeval a)
! 85: {
! 86: a = tv_adjust (a);
! 87:
! 88: return (a.tv_usec ? a.tv_sec + 1 : a.tv_sec);
! 89: }
! 90:
! 91: int
! 92: tv_floor (struct timeval a)
! 93: {
! 94: a = tv_adjust (a);
! 95:
! 96: return a.tv_sec;
! 97: }
! 98:
! 99: struct timeval
! 100: int2tv (int a)
! 101: {
! 102: struct timeval ret;
! 103:
! 104: ret.tv_sec = a;
! 105: ret.tv_usec = 0;
! 106:
! 107: return ret;
! 108: }
! 109:
! 110: struct timeval
! 111: tv_add (struct timeval a, struct timeval b)
! 112: {
! 113: struct timeval ret;
! 114:
! 115: ret.tv_sec = a.tv_sec + b.tv_sec;
! 116: ret.tv_usec = a.tv_usec + b.tv_usec;
! 117:
! 118: return tv_adjust (ret);
! 119: }
! 120:
! 121: struct timeval
! 122: tv_sub (struct timeval a, struct timeval b)
! 123: {
! 124: struct timeval ret;
! 125:
! 126: ret.tv_sec = a.tv_sec - b.tv_sec;
! 127: ret.tv_usec = a.tv_usec - b.tv_usec;
! 128:
! 129: return tv_adjust (ret);
! 130: }
! 131:
! 132: int
! 133: tv_cmp (struct timeval a, struct timeval b)
! 134: {
! 135: return (a.tv_sec == b.tv_sec ?
! 136: a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
! 137: }
! 138:
! 139: int
! 140: ospf_lsa_refresh_delay (struct ospf_lsa *lsa)
! 141: {
! 142: struct timeval delta, now;
! 143: int delay = 0;
! 144:
! 145: quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
! 146: delta = tv_sub (now, lsa->tv_orig);
! 147:
! 148: if (tv_cmp (delta, int2tv (OSPF_MIN_LS_INTERVAL)) < 0)
! 149: {
! 150: delay = tv_ceil (tv_sub (int2tv (OSPF_MIN_LS_INTERVAL), delta));
! 151:
! 152: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 153: zlog_debug ("LSA[Type%d:%s]: Refresh timer delay %d seconds",
! 154: lsa->data->type, inet_ntoa (lsa->data->id), delay);
! 155:
! 156: assert (delay > 0);
! 157: }
! 158:
! 159: return delay;
! 160: }
! 161:
! 162:
! 163: int
! 164: get_age (struct ospf_lsa *lsa)
! 165: {
! 166: int age;
! 167:
! 168: age = ntohs (lsa->data->ls_age)
! 169: + tv_floor (tv_sub (recent_relative_time (), lsa->tv_recv));
! 170:
! 171: return age;
! 172: }
! 173:
! 174:
! 175: /* Fletcher Checksum -- Refer to RFC1008. */
! 176:
! 177: /* All the offsets are zero-based. The offsets in the RFC1008 are
! 178: one-based. */
! 179: u_int16_t
! 180: ospf_lsa_checksum (struct lsa_header *lsa)
! 181: {
! 182: u_char *buffer = (u_char *) &lsa->options;
! 183: int options_offset = buffer - (u_char *) &lsa->ls_age; /* should be 2 */
! 184:
! 185: /* Skip the AGE field */
! 186: u_int16_t len = ntohs(lsa->length) - options_offset;
! 187:
! 188: /* Checksum offset starts from "options" field, not the beginning of the
! 189: lsa_header struct. The offset is 14, rather than 16. */
! 190: int checksum_offset = (u_char *) &lsa->checksum - buffer;
! 191:
! 192: return fletcher_checksum(buffer, len, checksum_offset);
! 193: }
! 194:
! 195:
! 196:
! 197: /* Create OSPF LSA. */
! 198: struct ospf_lsa *
! 199: ospf_lsa_new ()
! 200: {
! 201: struct ospf_lsa *new;
! 202:
! 203: new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa));
! 204:
! 205: new->flags = 0;
! 206: new->lock = 1;
! 207: new->retransmit_counter = 0;
! 208: new->tv_recv = recent_relative_time ();
! 209: new->tv_orig = new->tv_recv;
! 210: new->refresh_list = -1;
! 211:
! 212: return new;
! 213: }
! 214:
! 215: /* Duplicate OSPF LSA. */
! 216: struct ospf_lsa *
! 217: ospf_lsa_dup (struct ospf_lsa *lsa)
! 218: {
! 219: struct ospf_lsa *new;
! 220:
! 221: if (lsa == NULL)
! 222: return NULL;
! 223:
! 224: new = XCALLOC (MTYPE_OSPF_LSA, sizeof (struct ospf_lsa));
! 225:
! 226: memcpy (new, lsa, sizeof (struct ospf_lsa));
! 227: UNSET_FLAG (new->flags, OSPF_LSA_DISCARD);
! 228: new->lock = 1;
! 229: new->retransmit_counter = 0;
! 230: new->data = ospf_lsa_data_dup (lsa->data);
! 231:
! 232: /* kevinm: Clear the refresh_list, otherwise there are going
! 233: to be problems when we try to remove the LSA from the
! 234: queue (which it's not a member of.)
! 235: XXX: Should we add the LSA to the refresh_list queue? */
! 236: new->refresh_list = -1;
! 237:
! 238: if (IS_DEBUG_OSPF (lsa, LSA))
! 239: zlog_debug ("LSA: duplicated %p (new: %p)", lsa, new);
! 240:
! 241: return new;
! 242: }
! 243:
! 244: /* Free OSPF LSA. */
! 245: void
! 246: ospf_lsa_free (struct ospf_lsa *lsa)
! 247: {
! 248: assert (lsa->lock == 0);
! 249:
! 250: if (IS_DEBUG_OSPF (lsa, LSA))
! 251: zlog_debug ("LSA: freed %p", lsa);
! 252:
! 253: /* Delete LSA data. */
! 254: if (lsa->data != NULL)
! 255: ospf_lsa_data_free (lsa->data);
! 256:
! 257: assert (lsa->refresh_list < 0);
! 258:
! 259: memset (lsa, 0, sizeof (struct ospf_lsa));
! 260: XFREE (MTYPE_OSPF_LSA, lsa);
! 261: }
! 262:
! 263: /* Lock LSA. */
! 264: struct ospf_lsa *
! 265: ospf_lsa_lock (struct ospf_lsa *lsa)
! 266: {
! 267: lsa->lock++;
! 268: return lsa;
! 269: }
! 270:
! 271: /* Unlock LSA. */
! 272: void
! 273: ospf_lsa_unlock (struct ospf_lsa **lsa)
! 274: {
! 275: /* This is sanity check. */
! 276: if (!lsa || !*lsa)
! 277: return;
! 278:
! 279: (*lsa)->lock--;
! 280:
! 281: assert ((*lsa)->lock >= 0);
! 282:
! 283: if ((*lsa)->lock == 0)
! 284: {
! 285: assert (CHECK_FLAG ((*lsa)->flags, OSPF_LSA_DISCARD));
! 286: ospf_lsa_free (*lsa);
! 287: *lsa = NULL;
! 288: }
! 289: }
! 290:
! 291: /* Check discard flag. */
! 292: void
! 293: ospf_lsa_discard (struct ospf_lsa *lsa)
! 294: {
! 295: if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
! 296: {
! 297: SET_FLAG (lsa->flags, OSPF_LSA_DISCARD);
! 298: ospf_lsa_unlock (&lsa);
! 299: }
! 300: }
! 301:
! 302: /* Create LSA data. */
! 303: struct lsa_header *
! 304: ospf_lsa_data_new (size_t size)
! 305: {
! 306: return XCALLOC (MTYPE_OSPF_LSA_DATA, size);
! 307: }
! 308:
! 309: /* Duplicate LSA data. */
! 310: struct lsa_header *
! 311: ospf_lsa_data_dup (struct lsa_header *lsah)
! 312: {
! 313: struct lsa_header *new;
! 314:
! 315: new = ospf_lsa_data_new (ntohs (lsah->length));
! 316: memcpy (new, lsah, ntohs (lsah->length));
! 317:
! 318: return new;
! 319: }
! 320:
! 321: /* Free LSA data. */
! 322: void
! 323: ospf_lsa_data_free (struct lsa_header *lsah)
! 324: {
! 325: if (IS_DEBUG_OSPF (lsa, LSA))
! 326: zlog_debug ("LSA[Type%d:%s]: data freed %p",
! 327: lsah->type, inet_ntoa (lsah->id), lsah);
! 328:
! 329: XFREE (MTYPE_OSPF_LSA_DATA, lsah);
! 330: }
! 331:
! 332:
! 333: /* LSA general functions. */
! 334:
! 335: const char *
! 336: dump_lsa_key (struct ospf_lsa *lsa)
! 337: {
! 338: static char buf[] = {
! 339: "Type255,id(255.255.255.255),ar(255.255.255.255)"
! 340: };
! 341: struct lsa_header *lsah;
! 342:
! 343: if (lsa != NULL && (lsah = lsa->data) != NULL)
! 344: {
! 345: char id[INET_ADDRSTRLEN], ar[INET_ADDRSTRLEN];
! 346: strcpy (id, inet_ntoa (lsah->id));
! 347: strcpy (ar, inet_ntoa (lsah->adv_router));
! 348:
! 349: sprintf (buf, "Type%d,id(%s),ar(%s)", lsah->type, id, ar);
! 350: }
! 351: else
! 352: strcpy (buf, "NULL");
! 353:
! 354: return buf;
! 355: }
! 356:
! 357: u_int32_t
! 358: lsa_seqnum_increment (struct ospf_lsa *lsa)
! 359: {
! 360: u_int32_t seqnum;
! 361:
! 362: seqnum = ntohl (lsa->data->ls_seqnum) + 1;
! 363:
! 364: return htonl (seqnum);
! 365: }
! 366:
! 367: void
! 368: lsa_header_set (struct stream *s, u_char options,
! 369: u_char type, struct in_addr id, struct in_addr router_id)
! 370: {
! 371: struct lsa_header *lsah;
! 372:
! 373: lsah = (struct lsa_header *) STREAM_DATA (s);
! 374:
! 375: lsah->ls_age = htons (OSPF_LSA_INITIAL_AGE);
! 376: lsah->options = options;
! 377: lsah->type = type;
! 378: lsah->id = id;
! 379: lsah->adv_router = router_id;
! 380: lsah->ls_seqnum = htonl (OSPF_INITIAL_SEQUENCE_NUMBER);
! 381:
! 382: stream_forward_endp (s, OSPF_LSA_HEADER_SIZE);
! 383: }
! 384:
! 385:
! 386: /* router-LSA related functions. */
! 387: /* Get router-LSA flags. */
! 388: static u_char
! 389: router_lsa_flags (struct ospf_area *area)
! 390: {
! 391: u_char flags;
! 392:
! 393: flags = area->ospf->flags;
! 394:
! 395: /* Set virtual link flag. */
! 396: if (ospf_full_virtual_nbrs (area))
! 397: SET_FLAG (flags, ROUTER_LSA_VIRTUAL);
! 398: else
! 399: /* Just sanity check */
! 400: UNSET_FLAG (flags, ROUTER_LSA_VIRTUAL);
! 401:
! 402: /* Set Shortcut ABR behabiour flag. */
! 403: UNSET_FLAG (flags, ROUTER_LSA_SHORTCUT);
! 404: if (area->ospf->abr_type == OSPF_ABR_SHORTCUT)
! 405: if (!OSPF_IS_AREA_BACKBONE (area))
! 406: if ((area->shortcut_configured == OSPF_SHORTCUT_DEFAULT &&
! 407: area->ospf->backbone == NULL) ||
! 408: area->shortcut_configured == OSPF_SHORTCUT_ENABLE)
! 409: SET_FLAG (flags, ROUTER_LSA_SHORTCUT);
! 410:
! 411: /* ASBR can't exit in stub area. */
! 412: if (area->external_routing == OSPF_AREA_STUB)
! 413: UNSET_FLAG (flags, ROUTER_LSA_EXTERNAL);
! 414: /* If ASBR set External flag */
! 415: else if (IS_OSPF_ASBR (area->ospf))
! 416: SET_FLAG (flags, ROUTER_LSA_EXTERNAL);
! 417:
! 418: /* Set ABR dependent flags */
! 419: if (IS_OSPF_ABR (area->ospf))
! 420: {
! 421: SET_FLAG (flags, ROUTER_LSA_BORDER);
! 422: /* If Area is NSSA and we are both ABR and unconditional translator,
! 423: * set Nt bit to inform other routers.
! 424: */
! 425: if ( (area->external_routing == OSPF_AREA_NSSA)
! 426: && (area->NSSATranslatorRole == OSPF_NSSA_ROLE_ALWAYS))
! 427: SET_FLAG (flags, ROUTER_LSA_NT);
! 428: }
! 429: return flags;
! 430: }
! 431:
! 432: /* Lookup neighbor other than myself.
! 433: And check neighbor count,
! 434: Point-to-Point link must have only 1 neighbor. */
! 435: struct ospf_neighbor *
! 436: ospf_nbr_lookup_ptop (struct ospf_interface *oi)
! 437: {
! 438: struct ospf_neighbor *nbr = NULL;
! 439: struct route_node *rn;
! 440:
! 441: /* Search neighbor, there must be one of two nbrs. */
! 442: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
! 443: if ((nbr = rn->info))
! 444: if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
! 445: if (nbr->state == NSM_Full)
! 446: {
! 447: route_unlock_node (rn);
! 448: break;
! 449: }
! 450:
! 451: /* PtoP link must have only 1 neighbor. */
! 452: if (ospf_nbr_count (oi, 0) > 1)
! 453: zlog_warn ("Point-to-Point link has more than 1 neighobrs.");
! 454:
! 455: return nbr;
! 456: }
! 457:
! 458: /* Determine cost of link, taking RFC3137 stub-router support into
! 459: * consideration
! 460: */
! 461: static u_int16_t
! 462: ospf_link_cost (struct ospf_interface *oi)
! 463: {
! 464: /* RFC3137 stub router support */
! 465: if (!CHECK_FLAG (oi->area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
! 466: return oi->output_cost;
! 467: else
! 468: return OSPF_OUTPUT_COST_INFINITE;
! 469: }
! 470:
! 471: /* Set a link information. */
! 472: static char
! 473: link_info_set (struct stream *s, struct in_addr id,
! 474: struct in_addr data, u_char type, u_char tos, u_int16_t cost)
! 475: {
! 476: /* LSA stream is initially allocated to OSPF_MAX_LSA_SIZE, suits
! 477: * vast majority of cases. Some rare routers with lots of links need more.
! 478: * we try accomodate those here.
! 479: */
! 480: if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE)
! 481: {
! 482: size_t ret = OSPF_MAX_LSA_SIZE;
! 483:
! 484: /* Can we enlarge the stream still? */
! 485: if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE)
! 486: {
! 487: /* we futz the size here for simplicity, really we need to account
! 488: * for just:
! 489: * IP Header - (sizeof (struct ip))
! 490: * OSPF Header - OSPF_HEADER_SIZE
! 491: * LSA Header - OSPF_LSA_HEADER_SIZE
! 492: * MD5 auth data, if MD5 is configured - OSPF_AUTH_MD5_SIZE.
! 493: *
! 494: * Simpler just to subtract OSPF_MAX_LSA_SIZE though.
! 495: */
! 496: ret = stream_resize (s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE);
! 497: }
! 498:
! 499: if (ret == OSPF_MAX_LSA_SIZE)
! 500: {
! 501: zlog_warn ("%s: Out of space in LSA stream, left %zd, size %zd",
! 502: __func__, STREAM_REMAIN (s), STREAM_SIZE (s));
! 503: return 0;
! 504: }
! 505: }
! 506:
! 507: /* TOS based routing is not supported. */
! 508: stream_put_ipv4 (s, id.s_addr); /* Link ID. */
! 509: stream_put_ipv4 (s, data.s_addr); /* Link Data. */
! 510: stream_putc (s, type); /* Link Type. */
! 511: stream_putc (s, tos); /* TOS = 0. */
! 512: stream_putw (s, cost); /* Link Cost. */
! 513:
! 514: return 1;
! 515: }
! 516:
! 517: /* Describe Point-to-Point link (Section 12.4.1.1). */
! 518: static int
! 519: lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
! 520: {
! 521: int links = 0;
! 522: struct ospf_neighbor *nbr;
! 523: struct in_addr id, mask;
! 524: u_int16_t cost = ospf_link_cost (oi);
! 525:
! 526: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 527: zlog_debug ("LSA[Type1]: Set link Point-to-Point");
! 528:
! 529: if ((nbr = ospf_nbr_lookup_ptop (oi)))
! 530: if (nbr->state == NSM_Full)
! 531: {
! 532: /* For unnumbered point-to-point networks, the Link Data field
! 533: should specify the interface's MIB-II ifIndex value. */
! 534: links += link_info_set (s, nbr->router_id, oi->address->u.prefix4,
! 535: LSA_LINK_TYPE_POINTOPOINT, 0, cost);
! 536: }
! 537:
! 538: /* Regardless of the state of the neighboring router, we must
! 539: add a Type 3 link (stub network).
! 540: N.B. Options 1 & 2 share basically the same logic. */
! 541: masklen2ip (oi->address->prefixlen, &mask);
! 542: id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr;
! 543: links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
! 544: oi->output_cost);
! 545: return links;
! 546: }
! 547:
! 548: /* Describe Broadcast Link. */
! 549: static int
! 550: lsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi)
! 551: {
! 552: struct ospf_neighbor *dr;
! 553: struct in_addr id, mask;
! 554: u_int16_t cost = ospf_link_cost (oi);
! 555:
! 556: /* Describe Type 3 Link. */
! 557: if (oi->state == ISM_Waiting)
! 558: {
! 559: masklen2ip (oi->address->prefixlen, &mask);
! 560: id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
! 561: return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
! 562: oi->output_cost);
! 563: }
! 564:
! 565: dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi));
! 566: /* Describe Type 2 link. */
! 567: if (dr && (dr->state == NSM_Full ||
! 568: IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) &&
! 569: ospf_nbr_count (oi, NSM_Full) > 0)
! 570: {
! 571: return link_info_set (s, DR (oi), oi->address->u.prefix4,
! 572: LSA_LINK_TYPE_TRANSIT, 0, cost);
! 573: }
! 574: /* Describe type 3 link. */
! 575: else
! 576: {
! 577: masklen2ip (oi->address->prefixlen, &mask);
! 578: id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
! 579: return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
! 580: oi->output_cost);
! 581: }
! 582: }
! 583:
! 584: static int
! 585: lsa_link_loopback_set (struct stream *s, struct ospf_interface *oi)
! 586: {
! 587: struct in_addr id, mask;
! 588:
! 589: /* Describe Type 3 Link. */
! 590: if (oi->state != ISM_Loopback)
! 591: return 0;
! 592:
! 593: mask.s_addr = 0xffffffff;
! 594: id.s_addr = oi->address->u.prefix4.s_addr;
! 595: return link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost);
! 596: }
! 597:
! 598: /* Describe Virtual Link. */
! 599: static int
! 600: lsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi)
! 601: {
! 602: struct ospf_neighbor *nbr;
! 603: u_int16_t cost = ospf_link_cost (oi);
! 604:
! 605: if (oi->state == ISM_PointToPoint)
! 606: if ((nbr = ospf_nbr_lookup_ptop (oi)))
! 607: if (nbr->state == NSM_Full)
! 608: {
! 609: return link_info_set (s, nbr->router_id, oi->address->u.prefix4,
! 610: LSA_LINK_TYPE_VIRTUALLINK, 0, cost);
! 611: }
! 612:
! 613: return 0;
! 614: }
! 615:
! 616: #define lsa_link_nbma_set(S,O) lsa_link_broadcast_set (S, O)
! 617:
! 618: /* this function add for support point-to-multipoint ,see rfc2328
! 619: 12.4.1.4.*/
! 620: /* from "edward rrr" <edward_rrr@hotmail.com>
! 621: http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */
! 622: static int
! 623: lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
! 624: {
! 625: int links = 0;
! 626: struct route_node *rn;
! 627: struct ospf_neighbor *nbr = NULL;
! 628: struct in_addr id, mask;
! 629: u_int16_t cost = ospf_link_cost (oi);
! 630:
! 631: mask.s_addr = 0xffffffff;
! 632: id.s_addr = oi->address->u.prefix4.s_addr;
! 633: links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0);
! 634:
! 635: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 636: zlog_debug ("PointToMultipoint: running ptomultip_set");
! 637:
! 638: /* Search neighbor, */
! 639: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
! 640: if ((nbr = rn->info) != NULL)
! 641: /* Ignore myself. */
! 642: if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
! 643: if (nbr->state == NSM_Full)
! 644:
! 645: {
! 646: links += link_info_set (s, nbr->router_id, oi->address->u.prefix4,
! 647: LSA_LINK_TYPE_POINTOPOINT, 0, cost);
! 648: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 649: zlog_debug ("PointToMultipoint: set link to %s",
! 650: inet_ntoa(oi->address->u.prefix4));
! 651: }
! 652:
! 653: return links;
! 654: }
! 655:
! 656: /* Set router-LSA link information. */
! 657: static int
! 658: router_lsa_link_set (struct stream *s, struct ospf_area *area)
! 659: {
! 660: struct listnode *node;
! 661: struct ospf_interface *oi;
! 662: int links = 0;
! 663:
! 664: for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
! 665: {
! 666: struct interface *ifp = oi->ifp;
! 667:
! 668: /* Check interface is up, OSPF is enable. */
! 669: if (if_is_operative (ifp))
! 670: {
! 671: if (oi->state != ISM_Down)
! 672: {
! 673: /* Describe each link. */
! 674: switch (oi->type)
! 675: {
! 676: case OSPF_IFTYPE_POINTOPOINT:
! 677: links += lsa_link_ptop_set (s, oi);
! 678: break;
! 679: case OSPF_IFTYPE_BROADCAST:
! 680: links += lsa_link_broadcast_set (s, oi);
! 681: break;
! 682: case OSPF_IFTYPE_NBMA:
! 683: links += lsa_link_nbma_set (s, oi);
! 684: break;
! 685: case OSPF_IFTYPE_POINTOMULTIPOINT:
! 686: links += lsa_link_ptomp_set (s, oi);
! 687: break;
! 688: case OSPF_IFTYPE_VIRTUALLINK:
! 689: links += lsa_link_virtuallink_set (s, oi);
! 690: break;
! 691: case OSPF_IFTYPE_LOOPBACK:
! 692: links += lsa_link_loopback_set (s, oi);
! 693: }
! 694: }
! 695: }
! 696: }
! 697:
! 698: return links;
! 699: }
! 700:
! 701: /* Set router-LSA body. */
! 702: static void
! 703: ospf_router_lsa_body_set (struct stream *s, struct ospf_area *area)
! 704: {
! 705: unsigned long putp;
! 706: u_int16_t cnt;
! 707:
! 708: /* Set flags. */
! 709: stream_putc (s, router_lsa_flags (area));
! 710:
! 711: /* Set Zero fields. */
! 712: stream_putc (s, 0);
! 713:
! 714: /* Keep pointer to # links. */
! 715: putp = stream_get_endp(s);
! 716:
! 717: /* Forward word */
! 718: stream_putw(s, 0);
! 719:
! 720: /* Set all link information. */
! 721: cnt = router_lsa_link_set (s, area);
! 722:
! 723: /* Set # of links here. */
! 724: stream_putw_at (s, putp, cnt);
! 725: }
! 726:
! 727: static int
! 728: ospf_stub_router_timer (struct thread *t)
! 729: {
! 730: struct ospf_area *area = THREAD_ARG (t);
! 731:
! 732: area->t_stub_router = NULL;
! 733:
! 734: SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED);
! 735:
! 736: /* clear stub route state and generate router-lsa refresh, don't
! 737: * clobber an administratively set stub-router state though.
! 738: */
! 739: if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
! 740: return 0;
! 741:
! 742: UNSET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
! 743:
! 744: ospf_router_lsa_update_area (area);
! 745:
! 746: return 0;
! 747: }
! 748:
! 749: inline static void
! 750: ospf_stub_router_check (struct ospf_area *area)
! 751: {
! 752: /* area must either be administratively configured to be stub
! 753: * or startup-time stub-router must be configured and we must in a pre-stub
! 754: * state.
! 755: */
! 756: if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED))
! 757: {
! 758: SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
! 759: return;
! 760: }
! 761:
! 762: /* not admin-stubbed, check whether startup stubbing is configured and
! 763: * whether it's not been done yet
! 764: */
! 765: if (CHECK_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED))
! 766: return;
! 767:
! 768: if (area->ospf->stub_router_startup_time == OSPF_STUB_ROUTER_UNCONFIGURED)
! 769: {
! 770: /* stub-router is hence done forever for this area, even if someone
! 771: * tries configure it (take effect next restart).
! 772: */
! 773: SET_FLAG (area->stub_router_state, OSPF_AREA_WAS_START_STUB_ROUTED);
! 774: return;
! 775: }
! 776:
! 777: /* startup stub-router configured and not yet done */
! 778: SET_FLAG (area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED);
! 779:
! 780: OSPF_AREA_TIMER_ON (area->t_stub_router, ospf_stub_router_timer,
! 781: area->ospf->stub_router_startup_time);
! 782: }
! 783:
! 784: /* Create new router-LSA. */
! 785: static struct ospf_lsa *
! 786: ospf_router_lsa_new (struct ospf_area *area)
! 787: {
! 788: struct ospf *ospf = area->ospf;
! 789: struct stream *s;
! 790: struct lsa_header *lsah;
! 791: struct ospf_lsa *new;
! 792: int length;
! 793:
! 794: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 795: zlog_debug ("LSA[Type1]: Create router-LSA instance");
! 796:
! 797: /* check whether stub-router is desired, and if this is the first
! 798: * router LSA.
! 799: */
! 800: ospf_stub_router_check (area);
! 801:
! 802: /* Create a stream for LSA. */
! 803: s = stream_new (OSPF_MAX_LSA_SIZE);
! 804: /* Set LSA common header fields. */
! 805: lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_OPTIONS_NSSA_GET (area),
! 806: OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);
! 807:
! 808: /* Set router-LSA body fields. */
! 809: ospf_router_lsa_body_set (s, area);
! 810:
! 811: /* Set length. */
! 812: length = stream_get_endp (s);
! 813: lsah = (struct lsa_header *) STREAM_DATA (s);
! 814: lsah->length = htons (length);
! 815:
! 816: /* Now, create OSPF LSA instance. */
! 817: if ( (new = ospf_lsa_new ()) == NULL)
! 818: {
! 819: zlog_err ("%s: Unable to create new lsa", __func__);
! 820: return NULL;
! 821: }
! 822:
! 823: new->area = area;
! 824: SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
! 825:
! 826: /* Copy LSA data to store, discard stream. */
! 827: new->data = ospf_lsa_data_new (length);
! 828: memcpy (new->data, lsah, length);
! 829: stream_free (s);
! 830:
! 831: return new;
! 832: }
! 833:
! 834: /* Originate Router-LSA. */
! 835: static struct ospf_lsa *
! 836: ospf_router_lsa_originate (struct ospf_area *area)
! 837: {
! 838: struct ospf_lsa *new;
! 839:
! 840: /* Create new router-LSA instance. */
! 841: if ( (new = ospf_router_lsa_new (area)) == NULL)
! 842: {
! 843: zlog_err ("%s: ospf_router_lsa_new returned NULL", __func__);
! 844: return NULL;
! 845: }
! 846:
! 847: /* Sanity check. */
! 848: if (new->data->adv_router.s_addr == 0)
! 849: {
! 850: if (IS_DEBUG_OSPF_EVENT)
! 851: zlog_debug ("LSA[Type1]: AdvRouter is 0, discard");
! 852: ospf_lsa_discard (new);
! 853: return NULL;
! 854: }
! 855:
! 856: /* Install LSA to LSDB. */
! 857: new = ospf_lsa_install (area->ospf, NULL, new);
! 858:
! 859: /* Update LSA origination count. */
! 860: area->ospf->lsa_originate_count++;
! 861:
! 862: /* Flooding new LSA through area. */
! 863: ospf_flood_through_area (area, NULL, new);
! 864:
! 865: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 866: {
! 867: zlog_debug ("LSA[Type%d:%s]: Originate router-LSA %p",
! 868: new->data->type, inet_ntoa (new->data->id), new);
! 869: ospf_lsa_header_dump (new->data);
! 870: }
! 871:
! 872: return new;
! 873: }
! 874:
! 875: /* Refresh router-LSA. */
! 876: static struct ospf_lsa *
! 877: ospf_router_lsa_refresh (struct ospf_lsa *lsa)
! 878: {
! 879: struct ospf_area *area = lsa->area;
! 880: struct ospf_lsa *new;
! 881:
! 882: /* Sanity check. */
! 883: assert (lsa->data);
! 884:
! 885: /* Delete LSA from neighbor retransmit-list. */
! 886: ospf_ls_retransmit_delete_nbr_area (area, lsa);
! 887:
! 888: /* Unregister LSA from refresh-list */
! 889: ospf_refresher_unregister_lsa (area->ospf, lsa);
! 890:
! 891: /* Create new router-LSA instance. */
! 892: if ( (new = ospf_router_lsa_new (area)) == NULL)
! 893: {
! 894: zlog_err ("%s: ospf_router_lsa_new returned NULL", __func__);
! 895: return NULL;
! 896: }
! 897:
! 898: new->data->ls_seqnum = lsa_seqnum_increment (lsa);
! 899:
! 900: ospf_lsa_install (area->ospf, NULL, new);
! 901:
! 902: /* Flood LSA through area. */
! 903: ospf_flood_through_area (area, NULL, new);
! 904:
! 905: /* Debug logging. */
! 906: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 907: {
! 908: zlog_debug ("LSA[Type%d:%s]: router-LSA refresh",
! 909: new->data->type, inet_ntoa (new->data->id));
! 910: ospf_lsa_header_dump (new->data);
! 911: }
! 912:
! 913: return NULL;
! 914: }
! 915:
! 916: int
! 917: ospf_router_lsa_update_area (struct ospf_area *area)
! 918: {
! 919: if (IS_DEBUG_OSPF_EVENT)
! 920: zlog_debug ("[router-LSA]: (router-LSA area update)");
! 921:
! 922: /* Now refresh router-LSA. */
! 923: if (area->router_lsa_self)
! 924: ospf_lsa_refresh (area->ospf, area->router_lsa_self);
! 925: /* Newly originate router-LSA. */
! 926: else
! 927: ospf_router_lsa_originate (area);
! 928:
! 929: return 0;
! 930: }
! 931:
! 932: int
! 933: ospf_router_lsa_update (struct ospf *ospf)
! 934: {
! 935: struct listnode *node, *nnode;
! 936: struct ospf_area *area;
! 937:
! 938: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 939: zlog_debug ("Timer[router-LSA Update]: (timer expire)");
! 940:
! 941: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 942: {
! 943: struct ospf_lsa *lsa = area->router_lsa_self;
! 944: struct router_lsa *rl;
! 945: const char *area_str;
! 946:
! 947: /* Keep Area ID string. */
! 948: area_str = AREA_NAME (area);
! 949:
! 950: /* If LSA not exist in this Area, originate new. */
! 951: if (lsa == NULL)
! 952: {
! 953: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 954: zlog_debug("LSA[Type1]: Create router-LSA for Area %s", area_str);
! 955:
! 956: ospf_router_lsa_originate (area);
! 957: }
! 958: /* If router-ID is changed, Link ID must change.
! 959: First flush old LSA, then originate new. */
! 960: else if (!IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id))
! 961: {
! 962: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 963: zlog_debug("LSA[Type%d:%s]: Refresh router-LSA for Area %s",
! 964: lsa->data->type, inet_ntoa (lsa->data->id), area_str);
! 965: ospf_refresher_unregister_lsa (ospf, lsa);
! 966: ospf_lsa_flush_area (lsa, area);
! 967: ospf_lsa_unlock (&area->router_lsa_self);
! 968: area->router_lsa_self = NULL;
! 969:
! 970: /* Refresh router-LSA, (not install) and flood through area. */
! 971: ospf_router_lsa_update_area (area);
! 972: }
! 973: else
! 974: {
! 975: rl = (struct router_lsa *) lsa->data;
! 976: /* Refresh router-LSA, (not install) and flood through area. */
! 977: if (rl->flags != ospf->flags)
! 978: ospf_router_lsa_update_area (area);
! 979: }
! 980: }
! 981:
! 982: return 0;
! 983: }
! 984:
! 985:
! 986: /* network-LSA related functions. */
! 987: /* Originate Network-LSA. */
! 988: static void
! 989: ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi)
! 990: {
! 991: struct in_addr mask;
! 992: struct route_node *rn;
! 993: struct ospf_neighbor *nbr;
! 994:
! 995: masklen2ip (oi->address->prefixlen, &mask);
! 996: stream_put_ipv4 (s, mask.s_addr);
! 997:
! 998: /* The network-LSA lists those routers that are fully adjacent to
! 999: the Designated Router; each fully adjacent router is identified by
! 1000: its OSPF Router ID. The Designated Router includes itself in this
! 1001: list. RFC2328, Section 12.4.2 */
! 1002:
! 1003: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
! 1004: if ((nbr = rn->info) != NULL)
! 1005: if (nbr->state == NSM_Full || nbr == oi->nbr_self)
! 1006: stream_put_ipv4 (s, nbr->router_id.s_addr);
! 1007: }
! 1008:
! 1009: static struct ospf_lsa *
! 1010: ospf_network_lsa_new (struct ospf_interface *oi)
! 1011: {
! 1012: struct stream *s;
! 1013: struct ospf_lsa *new;
! 1014: struct lsa_header *lsah;
! 1015: struct ospf_if_params *oip;
! 1016: int length;
! 1017:
! 1018: /* If there are no neighbours on this network (the net is stub),
! 1019: the router does not originate network-LSA (see RFC 12.4.2) */
! 1020: if (oi->full_nbrs == 0)
! 1021: return NULL;
! 1022:
! 1023: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1024: zlog_debug ("LSA[Type2]: Create network-LSA instance");
! 1025:
! 1026: /* Create new stream for LSA. */
! 1027: s = stream_new (OSPF_MAX_LSA_SIZE);
! 1028: lsah = (struct lsa_header *) STREAM_DATA (s);
! 1029:
! 1030: lsa_header_set (s, (OPTIONS (oi) | LSA_OPTIONS_GET (oi->area)),
! 1031: OSPF_NETWORK_LSA, DR (oi), oi->ospf->router_id);
! 1032:
! 1033: /* Set network-LSA body fields. */
! 1034: ospf_network_lsa_body_set (s, oi);
! 1035:
! 1036: /* Set length. */
! 1037: length = stream_get_endp (s);
! 1038: lsah->length = htons (length);
! 1039:
! 1040: /* Create OSPF LSA instance. */
! 1041: if ( (new = ospf_lsa_new ()) == NULL)
! 1042: {
! 1043: zlog_err ("%s: ospf_lsa_new returned NULL", __func__);
! 1044: return NULL;
! 1045: }
! 1046:
! 1047: new->area = oi->area;
! 1048: SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
! 1049:
! 1050: /* Copy LSA to store. */
! 1051: new->data = ospf_lsa_data_new (length);
! 1052: memcpy (new->data, lsah, length);
! 1053: stream_free (s);
! 1054:
! 1055: /* Remember prior network LSA sequence numbers, even if we stop
! 1056: * originating one for this oi, to try avoid re-originating LSAs with a
! 1057: * prior sequence number, and thus speed up adjency forming & convergence.
! 1058: */
! 1059: if ((oip = ospf_lookup_if_params (oi->ifp, oi->address->u.prefix4)))
! 1060: {
! 1061: new->data->ls_seqnum = oip->network_lsa_seqnum;
! 1062: new->data->ls_seqnum = lsa_seqnum_increment (new);
! 1063: }
! 1064: else
! 1065: {
! 1066: oip = ospf_get_if_params (oi->ifp, oi->address->u.prefix4);
! 1067: ospf_if_update_params (oi->ifp, oi->address->u.prefix4);
! 1068: }
! 1069: oip->network_lsa_seqnum = new->data->ls_seqnum;
! 1070:
! 1071: return new;
! 1072: }
! 1073:
! 1074: /* Originate network-LSA. */
! 1075: void
! 1076: ospf_network_lsa_update (struct ospf_interface *oi)
! 1077: {
! 1078: struct ospf_lsa *new;
! 1079:
! 1080: if (oi->network_lsa_self != NULL)
! 1081: {
! 1082: ospf_lsa_refresh (oi->ospf, oi->network_lsa_self);
! 1083: return;
! 1084: }
! 1085:
! 1086: /* Create new network-LSA instance. */
! 1087: new = ospf_network_lsa_new (oi);
! 1088: if (new == NULL)
! 1089: return;
! 1090:
! 1091: /* Install LSA to LSDB. */
! 1092: new = ospf_lsa_install (oi->ospf, oi, new);
! 1093:
! 1094: /* Update LSA origination count. */
! 1095: oi->ospf->lsa_originate_count++;
! 1096:
! 1097: /* Flooding new LSA through area. */
! 1098: ospf_flood_through_area (oi->area, NULL, new);
! 1099:
! 1100: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1101: {
! 1102: zlog_debug ("LSA[Type%d:%s]: Originate network-LSA %p",
! 1103: new->data->type, inet_ntoa (new->data->id), new);
! 1104: ospf_lsa_header_dump (new->data);
! 1105: }
! 1106:
! 1107: return;
! 1108: }
! 1109:
! 1110: static struct ospf_lsa *
! 1111: ospf_network_lsa_refresh (struct ospf_lsa *lsa)
! 1112: {
! 1113: struct ospf_area *area = lsa->area;
! 1114: struct ospf_lsa *new, *new2;
! 1115: struct ospf_if_params *oip;
! 1116: struct ospf_interface *oi;
! 1117:
! 1118: assert (lsa->data);
! 1119:
! 1120: /* Retrieve the oi for the network LSA */
! 1121: oi = ospf_if_lookup_by_local_addr (area->ospf, NULL, lsa->data->id);
! 1122: if (oi == NULL)
! 1123: {
! 1124: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1125: {
! 1126: zlog_debug ("LSA[Type%d:%s]: network-LSA refresh: "
! 1127: "no oi found, ick, ignoring.",
! 1128: lsa->data->type, inet_ntoa (lsa->data->id));
! 1129: ospf_lsa_header_dump (lsa->data);
! 1130: }
! 1131: return NULL;
! 1132: }
! 1133: /* Delete LSA from neighbor retransmit-list. */
! 1134: ospf_ls_retransmit_delete_nbr_area (area, lsa);
! 1135:
! 1136: /* Unregister LSA from refresh-list */
! 1137: ospf_refresher_unregister_lsa (area->ospf, lsa);
! 1138:
! 1139: /* Create new network-LSA instance. */
! 1140: new = ospf_network_lsa_new (oi);
! 1141: if (new == NULL)
! 1142: return NULL;
! 1143:
! 1144: oip = ospf_lookup_if_params (oi->ifp, oi->address->u.prefix4);
! 1145: assert (oip != NULL);
! 1146: oip->network_lsa_seqnum = new->data->ls_seqnum = lsa_seqnum_increment (lsa);
! 1147:
! 1148: new2 = ospf_lsa_install (area->ospf, oi, new);
! 1149:
! 1150: assert (new2 == new);
! 1151:
! 1152: /* Flood LSA through aera. */
! 1153: ospf_flood_through_area (area, NULL, new);
! 1154:
! 1155: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1156: {
! 1157: zlog_debug ("LSA[Type%d:%s]: network-LSA refresh",
! 1158: new->data->type, inet_ntoa (new->data->id));
! 1159: ospf_lsa_header_dump (new->data);
! 1160: }
! 1161:
! 1162: return new;
! 1163: }
! 1164:
! 1165: static void
! 1166: stream_put_ospf_metric (struct stream *s, u_int32_t metric_value)
! 1167: {
! 1168: u_int32_t metric;
! 1169: char *mp;
! 1170:
! 1171: /* Put 0 metric. TOS metric is not supported. */
! 1172: metric = htonl (metric_value);
! 1173: mp = (char *) &metric;
! 1174: mp++;
! 1175: stream_put (s, mp, 3);
! 1176: }
! 1177:
! 1178: /* summary-LSA related functions. */
! 1179: static void
! 1180: ospf_summary_lsa_body_set (struct stream *s, struct prefix *p,
! 1181: u_int32_t metric)
! 1182: {
! 1183: struct in_addr mask;
! 1184:
! 1185: masklen2ip (p->prefixlen, &mask);
! 1186:
! 1187: /* Put Network Mask. */
! 1188: stream_put_ipv4 (s, mask.s_addr);
! 1189:
! 1190: /* Set # TOS. */
! 1191: stream_putc (s, (u_char) 0);
! 1192:
! 1193: /* Set metric. */
! 1194: stream_put_ospf_metric (s, metric);
! 1195: }
! 1196:
! 1197: static struct ospf_lsa *
! 1198: ospf_summary_lsa_new (struct ospf_area *area, struct prefix *p,
! 1199: u_int32_t metric, struct in_addr id)
! 1200: {
! 1201: struct stream *s;
! 1202: struct ospf_lsa *new;
! 1203: struct lsa_header *lsah;
! 1204: int length;
! 1205:
! 1206: if (id.s_addr == 0xffffffff)
! 1207: {
! 1208: /* Maybe Link State ID not available. */
! 1209: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1210: zlog_debug ("LSA[Type%d]: Link ID not available, can't originate",
! 1211: OSPF_SUMMARY_LSA);
! 1212: return NULL;
! 1213: }
! 1214:
! 1215: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1216: zlog_debug ("LSA[Type3]: Create summary-LSA instance");
! 1217:
! 1218: /* Create new stream for LSA. */
! 1219: s = stream_new (OSPF_MAX_LSA_SIZE);
! 1220: lsah = (struct lsa_header *) STREAM_DATA (s);
! 1221:
! 1222: lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_SUMMARY_LSA,
! 1223: id, area->ospf->router_id);
! 1224:
! 1225: /* Set summary-LSA body fields. */
! 1226: ospf_summary_lsa_body_set (s, p, metric);
! 1227:
! 1228: /* Set length. */
! 1229: length = stream_get_endp (s);
! 1230: lsah->length = htons (length);
! 1231:
! 1232: /* Create OSPF LSA instance. */
! 1233: new = ospf_lsa_new ();
! 1234: new->area = area;
! 1235: SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
! 1236:
! 1237: /* Copy LSA to store. */
! 1238: new->data = ospf_lsa_data_new (length);
! 1239: memcpy (new->data, lsah, length);
! 1240: stream_free (s);
! 1241:
! 1242: return new;
! 1243: }
! 1244:
! 1245: /* Originate Summary-LSA. */
! 1246: struct ospf_lsa *
! 1247: ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
! 1248: struct ospf_area *area)
! 1249: {
! 1250: struct ospf_lsa *new;
! 1251: struct in_addr id;
! 1252:
! 1253: id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p);
! 1254:
! 1255: if (id.s_addr == 0xffffffff)
! 1256: {
! 1257: /* Maybe Link State ID not available. */
! 1258: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1259: zlog_debug ("LSA[Type%d]: Link ID not available, can't originate",
! 1260: OSPF_SUMMARY_LSA);
! 1261: return NULL;
! 1262: }
! 1263:
! 1264: /* Create new summary-LSA instance. */
! 1265: if ( !(new = ospf_summary_lsa_new (area, (struct prefix *) p, metric, id)))
! 1266: return NULL;
! 1267:
! 1268: /* Instlal LSA to LSDB. */
! 1269: new = ospf_lsa_install (area->ospf, NULL, new);
! 1270:
! 1271: /* Update LSA origination count. */
! 1272: area->ospf->lsa_originate_count++;
! 1273:
! 1274: /* Flooding new LSA through area. */
! 1275: ospf_flood_through_area (area, NULL, new);
! 1276:
! 1277: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1278: {
! 1279: zlog_debug ("LSA[Type%d:%s]: Originate summary-LSA %p",
! 1280: new->data->type, inet_ntoa (new->data->id), new);
! 1281: ospf_lsa_header_dump (new->data);
! 1282: }
! 1283:
! 1284: return new;
! 1285: }
! 1286:
! 1287: static struct ospf_lsa*
! 1288: ospf_summary_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
! 1289: {
! 1290: struct ospf_lsa *new;
! 1291: struct summary_lsa *sl;
! 1292: struct prefix p;
! 1293:
! 1294: /* Sanity check. */
! 1295: assert (lsa->data);
! 1296:
! 1297: sl = (struct summary_lsa *)lsa->data;
! 1298: p.prefixlen = ip_masklen (sl->mask);
! 1299: new = ospf_summary_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
! 1300: sl->header.id);
! 1301:
! 1302: if (!new)
! 1303: return NULL;
! 1304:
! 1305: new->data->ls_seqnum = lsa_seqnum_increment (lsa);
! 1306:
! 1307: ospf_lsa_install (ospf, NULL, new);
! 1308:
! 1309: /* Flood LSA through AS. */
! 1310: ospf_flood_through_area (new->area, NULL, new);
! 1311:
! 1312: /* Debug logging. */
! 1313: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1314: {
! 1315: zlog_debug ("LSA[Type%d:%s]: summary-LSA refresh",
! 1316: new->data->type, inet_ntoa (new->data->id));
! 1317: ospf_lsa_header_dump (new->data);
! 1318: }
! 1319:
! 1320: return new;
! 1321: }
! 1322:
! 1323:
! 1324: /* summary-ASBR-LSA related functions. */
! 1325: static void
! 1326: ospf_summary_asbr_lsa_body_set (struct stream *s, struct prefix *p,
! 1327: u_int32_t metric)
! 1328: {
! 1329: struct in_addr mask;
! 1330:
! 1331: masklen2ip (p->prefixlen, &mask);
! 1332:
! 1333: /* Put Network Mask. */
! 1334: stream_put_ipv4 (s, mask.s_addr);
! 1335:
! 1336: /* Set # TOS. */
! 1337: stream_putc (s, (u_char) 0);
! 1338:
! 1339: /* Set metric. */
! 1340: stream_put_ospf_metric (s, metric);
! 1341: }
! 1342:
! 1343: static struct ospf_lsa *
! 1344: ospf_summary_asbr_lsa_new (struct ospf_area *area, struct prefix *p,
! 1345: u_int32_t metric, struct in_addr id)
! 1346: {
! 1347: struct stream *s;
! 1348: struct ospf_lsa *new;
! 1349: struct lsa_header *lsah;
! 1350: int length;
! 1351:
! 1352: if (id.s_addr == 0xffffffff)
! 1353: {
! 1354: /* Maybe Link State ID not available. */
! 1355: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1356: zlog_debug ("LSA[Type%d]: Link ID not available, can't originate",
! 1357: OSPF_ASBR_SUMMARY_LSA);
! 1358: return NULL;
! 1359: }
! 1360:
! 1361: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1362: zlog_debug ("LSA[Type3]: Create summary-LSA instance");
! 1363:
! 1364: /* Create new stream for LSA. */
! 1365: s = stream_new (OSPF_MAX_LSA_SIZE);
! 1366: lsah = (struct lsa_header *) STREAM_DATA (s);
! 1367:
! 1368: lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_ASBR_SUMMARY_LSA,
! 1369: id, area->ospf->router_id);
! 1370:
! 1371: /* Set summary-LSA body fields. */
! 1372: ospf_summary_asbr_lsa_body_set (s, p, metric);
! 1373:
! 1374: /* Set length. */
! 1375: length = stream_get_endp (s);
! 1376: lsah->length = htons (length);
! 1377:
! 1378: /* Create OSPF LSA instance. */
! 1379: new = ospf_lsa_new ();
! 1380: new->area = area;
! 1381: SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED);
! 1382:
! 1383: /* Copy LSA to store. */
! 1384: new->data = ospf_lsa_data_new (length);
! 1385: memcpy (new->data, lsah, length);
! 1386: stream_free (s);
! 1387:
! 1388: return new;
! 1389: }
! 1390:
! 1391: /* Originate summary-ASBR-LSA. */
! 1392: struct ospf_lsa *
! 1393: ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric,
! 1394: struct ospf_area *area)
! 1395: {
! 1396: struct ospf_lsa *new;
! 1397: struct in_addr id;
! 1398:
! 1399: id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, p);
! 1400:
! 1401: if (id.s_addr == 0xffffffff)
! 1402: {
! 1403: /* Maybe Link State ID not available. */
! 1404: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1405: zlog_debug ("LSA[Type%d]: Link ID not available, can't originate",
! 1406: OSPF_ASBR_SUMMARY_LSA);
! 1407: return NULL;
! 1408: }
! 1409:
! 1410: /* Create new summary-LSA instance. */
! 1411: new = ospf_summary_asbr_lsa_new (area, (struct prefix *) p, metric, id);
! 1412: if (!new)
! 1413: return NULL;
! 1414:
! 1415: /* Install LSA to LSDB. */
! 1416: new = ospf_lsa_install (area->ospf, NULL, new);
! 1417:
! 1418: /* Update LSA origination count. */
! 1419: area->ospf->lsa_originate_count++;
! 1420:
! 1421: /* Flooding new LSA through area. */
! 1422: ospf_flood_through_area (area, NULL, new);
! 1423:
! 1424: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1425: {
! 1426: zlog_debug ("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p",
! 1427: new->data->type, inet_ntoa (new->data->id), new);
! 1428: ospf_lsa_header_dump (new->data);
! 1429: }
! 1430:
! 1431: return new;
! 1432: }
! 1433:
! 1434: static struct ospf_lsa*
! 1435: ospf_summary_asbr_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
! 1436: {
! 1437: struct ospf_lsa *new;
! 1438: struct summary_lsa *sl;
! 1439: struct prefix p;
! 1440:
! 1441: /* Sanity check. */
! 1442: assert (lsa->data);
! 1443:
! 1444: sl = (struct summary_lsa *)lsa->data;
! 1445: p.prefixlen = ip_masklen (sl->mask);
! 1446: new = ospf_summary_asbr_lsa_new (lsa->area, &p, GET_METRIC (sl->metric),
! 1447: sl->header.id);
! 1448: if (!new)
! 1449: return NULL;
! 1450:
! 1451: new->data->ls_seqnum = lsa_seqnum_increment (lsa);
! 1452:
! 1453: ospf_lsa_install (ospf, NULL, new);
! 1454:
! 1455: /* Flood LSA through area. */
! 1456: ospf_flood_through_area (new->area, NULL, new);
! 1457:
! 1458: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1459: {
! 1460: zlog_debug ("LSA[Type%d:%s]: summary-ASBR-LSA refresh",
! 1461: new->data->type, inet_ntoa (new->data->id));
! 1462: ospf_lsa_header_dump (new->data);
! 1463: }
! 1464:
! 1465: return new;
! 1466: }
! 1467:
! 1468: /* AS-external-LSA related functions. */
! 1469:
! 1470: /* Get nexthop for AS-external-LSAs. Return nexthop if its interface
! 1471: is connected, else 0*/
! 1472: static struct in_addr
! 1473: ospf_external_lsa_nexthop_get (struct ospf *ospf, struct in_addr nexthop)
! 1474: {
! 1475: struct in_addr fwd;
! 1476: struct prefix nh;
! 1477: struct listnode *node;
! 1478: struct ospf_interface *oi;
! 1479:
! 1480: fwd.s_addr = 0;
! 1481:
! 1482: if (!nexthop.s_addr)
! 1483: return fwd;
! 1484:
! 1485: /* Check whether nexthop is covered by OSPF network. */
! 1486: nh.family = AF_INET;
! 1487: nh.u.prefix4 = nexthop;
! 1488: nh.prefixlen = IPV4_MAX_BITLEN;
! 1489:
! 1490: /* XXX/SCALE: If there were a lot of oi's on an ifp, then it'd be
! 1491: * better to make use of the per-ifp table of ois.
! 1492: */
! 1493: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
! 1494: if (if_is_operative (oi->ifp))
! 1495: if (oi->address->family == AF_INET)
! 1496: if (prefix_match (oi->address, &nh))
! 1497: return nexthop;
! 1498:
! 1499: return fwd;
! 1500: }
! 1501:
! 1502: /* NSSA-external-LSA related functions. */
! 1503:
! 1504: /* Get 1st IP connection for Forward Addr */
! 1505:
! 1506: struct in_addr
! 1507: ospf_get_ip_from_ifp (struct ospf_interface *oi)
! 1508: {
! 1509: struct in_addr fwd;
! 1510:
! 1511: fwd.s_addr = 0;
! 1512:
! 1513: if (if_is_operative (oi->ifp))
! 1514: return oi->address->u.prefix4;
! 1515:
! 1516: return fwd;
! 1517: }
! 1518:
! 1519: /* Get 1st IP connection for Forward Addr */
! 1520: struct in_addr
! 1521: ospf_get_nssa_ip (struct ospf_area *area)
! 1522: {
! 1523: struct in_addr fwd;
! 1524: struct in_addr best_default;
! 1525: struct listnode *node;
! 1526: struct ospf_interface *oi;
! 1527:
! 1528: fwd.s_addr = 0;
! 1529: best_default.s_addr = 0;
! 1530:
! 1531: for (ALL_LIST_ELEMENTS_RO (area->ospf->oiflist, node, oi))
! 1532: {
! 1533: if (if_is_operative (oi->ifp))
! 1534: if (oi->area->external_routing == OSPF_AREA_NSSA)
! 1535: if (oi->address && oi->address->family == AF_INET)
! 1536: {
! 1537: if (best_default.s_addr == 0)
! 1538: best_default = oi->address->u.prefix4;
! 1539: if (oi->area == area)
! 1540: return oi->address->u.prefix4;
! 1541: }
! 1542: }
! 1543: if (best_default.s_addr != 0)
! 1544: return best_default;
! 1545:
! 1546: if (best_default.s_addr != 0)
! 1547: return best_default;
! 1548:
! 1549: return fwd;
! 1550: }
! 1551:
! 1552: #define DEFAULT_DEFAULT_METRIC 20
! 1553: #define DEFAULT_DEFAULT_ORIGINATE_METRIC 10
! 1554: #define DEFAULT_DEFAULT_ALWAYS_METRIC 1
! 1555:
! 1556: #define DEFAULT_METRIC_TYPE EXTERNAL_METRIC_TYPE_2
! 1557:
! 1558: int
! 1559: metric_type (struct ospf *ospf, u_char src)
! 1560: {
! 1561: return (ospf->dmetric[src].type < 0 ?
! 1562: DEFAULT_METRIC_TYPE : ospf->dmetric[src].type);
! 1563: }
! 1564:
! 1565: int
! 1566: metric_value (struct ospf *ospf, u_char src)
! 1567: {
! 1568: if (ospf->dmetric[src].value < 0)
! 1569: {
! 1570: if (src == DEFAULT_ROUTE)
! 1571: {
! 1572: if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA)
! 1573: return DEFAULT_DEFAULT_ORIGINATE_METRIC;
! 1574: else
! 1575: return DEFAULT_DEFAULT_ALWAYS_METRIC;
! 1576: }
! 1577: else if (ospf->default_metric < 0)
! 1578: return DEFAULT_DEFAULT_METRIC;
! 1579: else
! 1580: return ospf->default_metric;
! 1581: }
! 1582:
! 1583: return ospf->dmetric[src].value;
! 1584: }
! 1585:
! 1586: /* Set AS-external-LSA body. */
! 1587: static void
! 1588: ospf_external_lsa_body_set (struct stream *s, struct external_info *ei,
! 1589: struct ospf *ospf)
! 1590: {
! 1591: struct prefix_ipv4 *p = &ei->p;
! 1592: struct in_addr mask, fwd_addr;
! 1593: u_int32_t mvalue;
! 1594: int mtype;
! 1595: int type;
! 1596:
! 1597: /* Put Network Mask. */
! 1598: masklen2ip (p->prefixlen, &mask);
! 1599: stream_put_ipv4 (s, mask.s_addr);
! 1600:
! 1601: /* If prefix is default, specify DEFAULT_ROUTE. */
! 1602: type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
! 1603:
! 1604: mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ?
! 1605: ROUTEMAP_METRIC_TYPE (ei) : metric_type (ospf, type);
! 1606:
! 1607: mvalue = (ROUTEMAP_METRIC (ei) != -1) ?
! 1608: ROUTEMAP_METRIC (ei) : metric_value (ospf, type);
! 1609:
! 1610: /* Put type of external metric. */
! 1611: stream_putc (s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0));
! 1612:
! 1613: /* Put 0 metric. TOS metric is not supported. */
! 1614: stream_put_ospf_metric (s, mvalue);
! 1615:
! 1616: /* Get forwarding address to nexthop if on the Connection List, else 0. */
! 1617: fwd_addr = ospf_external_lsa_nexthop_get (ospf, ei->nexthop);
! 1618:
! 1619: /* Put forwarding address. */
! 1620: stream_put_ipv4 (s, fwd_addr.s_addr);
! 1621:
! 1622: /* Put route tag -- This value should be introduced from configuration. */
! 1623: stream_putl (s, 0);
! 1624: }
! 1625:
! 1626: /* Create new external-LSA. */
! 1627: static struct ospf_lsa *
! 1628: ospf_external_lsa_new (struct ospf *ospf,
! 1629: struct external_info *ei, struct in_addr *old_id)
! 1630: {
! 1631: struct stream *s;
! 1632: struct lsa_header *lsah;
! 1633: struct ospf_lsa *new;
! 1634: struct in_addr id;
! 1635: int length;
! 1636:
! 1637: if (ei == NULL)
! 1638: {
! 1639: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1640: zlog_debug ("LSA[Type5]: External info is NULL, could not originated");
! 1641: return NULL;
! 1642: }
! 1643:
! 1644: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1645: zlog_debug ("LSA[Type5]: Originate AS-external-LSA instance");
! 1646:
! 1647: /* If old Link State ID is specified, refresh LSA with same ID. */
! 1648: if (old_id)
! 1649: id = *old_id;
! 1650: /* Get Link State with unique ID. */
! 1651: else
! 1652: {
! 1653: id = ospf_lsa_unique_id (ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, &ei->p);
! 1654: if (id.s_addr == 0xffffffff)
! 1655: {
! 1656: /* Maybe Link State ID not available. */
! 1657: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 1658: zlog_debug ("LSA[Type5]: Link ID not available, can't originate");
! 1659: return NULL;
! 1660: }
! 1661: }
! 1662:
! 1663: /* Create new stream for LSA. */
! 1664: s = stream_new (OSPF_MAX_LSA_SIZE);
! 1665: lsah = (struct lsa_header *) STREAM_DATA (s);
! 1666:
! 1667: /* Set LSA common header fields. */
! 1668: lsa_header_set (s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA,
! 1669: id, ospf->router_id);
! 1670:
! 1671: /* Set AS-external-LSA body fields. */
! 1672: ospf_external_lsa_body_set (s, ei, ospf);
! 1673:
! 1674: /* Set length. */
! 1675: length = stream_get_endp (s);
! 1676: lsah->length = htons (length);
! 1677:
! 1678: /* Now, create OSPF LSA instance. */
! 1679: new = ospf_lsa_new ();
! 1680: new->area = NULL;
! 1681: SET_FLAG (new->flags, OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED);
! 1682:
! 1683: /* Copy LSA data to store, discard stream. */
! 1684: new->data = ospf_lsa_data_new (length);
! 1685: memcpy (new->data, lsah, length);
! 1686: stream_free (s);
! 1687:
! 1688: return new;
! 1689: }
! 1690:
! 1691: /* As Type-7 */
! 1692: static void
! 1693: ospf_install_flood_nssa (struct ospf *ospf,
! 1694: struct ospf_lsa *lsa, struct external_info *ei)
! 1695: {
! 1696: struct ospf_lsa *new;
! 1697: struct as_external_lsa *extlsa;
! 1698: struct ospf_area *area;
! 1699: struct listnode *node, *nnode;
! 1700:
! 1701: /* LSA may be a Type-5 originated via translation of a Type-7 LSA
! 1702: * which originated from an NSSA area. In which case it should not be
! 1703: * flooded back to NSSA areas.
! 1704: */
! 1705: if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
! 1706: return;
! 1707:
! 1708: /* NSSA Originate or Refresh (If anyNSSA)
! 1709:
! 1710: LSA is self-originated. And just installed as Type-5.
! 1711: Additionally, install as Type-7 LSDB for every attached NSSA.
! 1712:
! 1713: P-Bit controls which ABR performs translation to outside world; If
! 1714: we are an ABR....do not set the P-bit, because we send the Type-5,
! 1715: not as the ABR Translator, but as the ASBR owner within the AS!
! 1716:
! 1717: If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set. The
! 1718: elected ABR Translator will see the P-bit, Translate, and re-flood.
! 1719:
! 1720: Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to
! 1721: Type-5's to non-NSSA Areas. (it will also attempt a re-install) */
! 1722:
! 1723: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 1724: {
! 1725: /* Don't install Type-7 LSA's into nonNSSA area */
! 1726: if (area->external_routing != OSPF_AREA_NSSA)
! 1727: continue;
! 1728:
! 1729: /* make lsa duplicate, lock=1 */
! 1730: new = ospf_lsa_dup (lsa);
! 1731: new->area = area;
! 1732: new->data->type = OSPF_AS_NSSA_LSA;
! 1733:
! 1734: /* set P-bit if not ABR */
! 1735: if (! IS_OSPF_ABR (ospf))
! 1736: {
! 1737: SET_FLAG(new->data->options, OSPF_OPTION_NP);
! 1738:
! 1739: /* set non-zero FWD ADDR
! 1740:
! 1741: draft-ietf-ospf-nssa-update-09.txt
! 1742:
! 1743: if the network between the NSSA AS boundary router and the
! 1744: adjacent AS is advertised into OSPF as an internal OSPF route,
! 1745: the forwarding address should be the next op address as is cu
! 1746: currently done with type-5 LSAs. If the intervening network is
! 1747: not adversited into OSPF as an internal OSPF route and the
! 1748: type-7 LSA's P-bit is set a forwarding address should be
! 1749: selected from one of the router's active OSPF inteface addresses
! 1750: which belong to the NSSA. If no such addresses exist, then
! 1751: no type-7 LSA's with the P-bit set should originate from this
! 1752: router. */
! 1753:
! 1754: /* kevinm: not updating lsa anymore, just new */
! 1755: extlsa = (struct as_external_lsa *)(new->data);
! 1756:
! 1757: if (extlsa->e[0].fwd_addr.s_addr == 0)
! 1758: extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */
! 1759:
! 1760: if (extlsa->e[0].fwd_addr.s_addr == 0)
! 1761: {
! 1762: if (IS_DEBUG_OSPF_NSSA)
! 1763: zlog_debug ("LSA[Type-7]: Could not build FWD-ADDR");
! 1764: ospf_lsa_discard (new);
! 1765: return;
! 1766: }
! 1767: }
! 1768:
! 1769: /* install also as Type-7 */
! 1770: ospf_lsa_install (ospf, NULL, new); /* Remove Old, Lock New = 2 */
! 1771:
! 1772: /* will send each copy, lock=2+n */
! 1773: ospf_flood_through_as (ospf, NULL, new); /* all attached NSSA's, no AS/STUBs */
! 1774: }
! 1775: }
! 1776:
! 1777: static struct ospf_lsa *
! 1778: ospf_lsa_translated_nssa_new (struct ospf *ospf,
! 1779: struct ospf_lsa *type7)
! 1780: {
! 1781:
! 1782: struct ospf_lsa *new;
! 1783: struct as_external_lsa *ext, *extnew;
! 1784: struct external_info ei;
! 1785:
! 1786: ext = (struct as_external_lsa *)(type7->data);
! 1787:
! 1788: /* need external_info struct, fill in bare minimum */
! 1789: ei.p.family = AF_INET;
! 1790: ei.p.prefix = type7->data->id;
! 1791: ei.p.prefixlen = ip_masklen (ext->mask);
! 1792: ei.type = ZEBRA_ROUTE_OSPF;
! 1793: ei.nexthop = ext->header.adv_router;
! 1794: ei.route_map_set.metric = -1;
! 1795: ei.route_map_set.metric_type = -1;
! 1796: ei.tag = 0;
! 1797:
! 1798: if ( (new = ospf_external_lsa_new (ospf, &ei, &type7->data->id)) == NULL)
! 1799: {
! 1800: if (IS_DEBUG_OSPF_NSSA)
! 1801: zlog_debug ("ospf_nssa_translate_originate(): Could not originate "
! 1802: "Translated Type-5 for %s",
! 1803: inet_ntoa (ei.p.prefix));
! 1804: return NULL;
! 1805: }
! 1806:
! 1807: extnew = (struct as_external_lsa *)(new->data);
! 1808:
! 1809: /* copy over Type-7 data to new */
! 1810: extnew->e[0].tos = ext->e[0].tos;
! 1811: extnew->e[0].route_tag = ext->e[0].route_tag;
! 1812: extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr;
! 1813: new->data->ls_seqnum = type7->data->ls_seqnum;
! 1814:
! 1815: /* add translated flag, checksum and lock new lsa */
! 1816: SET_FLAG (new->flags, OSPF_LSA_LOCAL_XLT); /* Translated from 7 */
! 1817: new = ospf_lsa_lock (new);
! 1818:
! 1819: return new;
! 1820: }
! 1821:
! 1822: /* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
! 1823: struct ospf_lsa *
! 1824: ospf_translated_nssa_originate (struct ospf *ospf, struct ospf_lsa *type7)
! 1825: {
! 1826: struct ospf_lsa *new;
! 1827: struct as_external_lsa *extnew;
! 1828:
! 1829: /* we cant use ospf_external_lsa_originate() as we need to set
! 1830: * the OSPF_LSA_LOCAL_XLT flag, must originate by hand
! 1831: */
! 1832:
! 1833: if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL)
! 1834: {
! 1835: if (IS_DEBUG_OSPF_NSSA)
! 1836: zlog_debug ("ospf_translated_nssa_originate(): Could not translate "
! 1837: "Type-7, Id %s, to Type-5",
! 1838: inet_ntoa (type7->data->id));
! 1839: return NULL;
! 1840: }
! 1841:
! 1842: extnew = (struct as_external_lsa *)new;
! 1843:
! 1844: if (IS_DEBUG_OSPF_NSSA)
! 1845: {
! 1846: zlog_debug ("ospf_translated_nssa_originate(): "
! 1847: "translated Type 7, installed:");
! 1848: ospf_lsa_header_dump (new->data);
! 1849: zlog_debug (" Network mask: %d",ip_masklen (extnew->mask));
! 1850: zlog_debug (" Forward addr: %s", inet_ntoa (extnew->e[0].fwd_addr));
! 1851: }
! 1852:
! 1853: if ( (new = ospf_lsa_install (ospf, NULL, new)) == NULL)
! 1854: {
! 1855: if (IS_DEBUG_OSPF_NSSA);
! 1856: zlog_debug ("ospf_lsa_translated_nssa_originate(): "
! 1857: "Could not install LSA "
! 1858: "id %s", inet_ntoa (type7->data->id));
! 1859: return NULL;
! 1860: }
! 1861:
! 1862: ospf->lsa_originate_count++;
! 1863: ospf_flood_through_as (ospf, NULL, new);
! 1864:
! 1865: return new;
! 1866: }
! 1867:
! 1868: /* Refresh Translated from NSSA AS-external-LSA. */
! 1869: struct ospf_lsa *
! 1870: ospf_translated_nssa_refresh (struct ospf *ospf, struct ospf_lsa *type7,
! 1871: struct ospf_lsa *type5)
! 1872: {
! 1873: struct ospf_lsa *new = NULL;
! 1874:
! 1875: /* Sanity checks. */
! 1876: assert (type7 || type5);
! 1877: if (!(type7 || type5))
! 1878: return NULL;
! 1879: if (type7)
! 1880: assert (type7->data);
! 1881: if (type5)
! 1882: assert (type5->data);
! 1883: assert (ospf->anyNSSA);
! 1884:
! 1885: /* get required data according to what has been given */
! 1886: if (type7 && type5 == NULL)
! 1887: {
! 1888: /* find the translated Type-5 for this Type-7 */
! 1889: struct as_external_lsa *ext = (struct as_external_lsa *)(type7->data);
! 1890: struct prefix_ipv4 p =
! 1891: {
! 1892: .prefix = type7->data->id,
! 1893: .prefixlen = ip_masklen (ext->mask),
! 1894: .family = AF_INET,
! 1895: };
! 1896:
! 1897: type5 = ospf_external_info_find_lsa (ospf, &p);
! 1898: }
! 1899: else if (type5 && type7 == NULL)
! 1900: {
! 1901: /* find the type-7 from which supplied type-5 was translated,
! 1902: * ie find first type-7 with same LSA Id.
! 1903: */
! 1904: struct listnode *ln, *lnn;
! 1905: struct route_node *rn;
! 1906: struct ospf_lsa *lsa;
! 1907: struct ospf_area *area;
! 1908:
! 1909: for (ALL_LIST_ELEMENTS (ospf->areas, ln, lnn, area))
! 1910: {
! 1911: if (area->external_routing != OSPF_AREA_NSSA
! 1912: && !type7)
! 1913: continue;
! 1914:
! 1915: LSDB_LOOP (NSSA_LSDB(area), rn, lsa)
! 1916: {
! 1917: if (lsa->data->id.s_addr == type5->data->id.s_addr)
! 1918: {
! 1919: type7 = lsa;
! 1920: break;
! 1921: }
! 1922: }
! 1923: }
! 1924: }
! 1925:
! 1926: /* do we have type7? */
! 1927: if (!type7)
! 1928: {
! 1929: if (IS_DEBUG_OSPF_NSSA)
! 1930: zlog_debug ("ospf_translated_nssa_refresh(): no Type-7 found for "
! 1931: "Type-5 LSA Id %s",
! 1932: inet_ntoa (type5->data->id));
! 1933: return NULL;
! 1934: }
! 1935:
! 1936: /* do we have valid translated type5? */
! 1937: if (type5 == NULL || !CHECK_FLAG (type5->flags, OSPF_LSA_LOCAL_XLT) )
! 1938: {
! 1939: if (IS_DEBUG_OSPF_NSSA)
! 1940: zlog_debug ("ospf_translated_nssa_refresh(): No translated Type-5 "
! 1941: "found for Type-7 with Id %s",
! 1942: inet_ntoa (type7->data->id));
! 1943: return NULL;
! 1944: }
! 1945:
! 1946: /* Delete LSA from neighbor retransmit-list. */
! 1947: ospf_ls_retransmit_delete_nbr_as (ospf, type5);
! 1948:
! 1949: /* create new translated LSA */
! 1950: if ( (new = ospf_lsa_translated_nssa_new (ospf, type7)) == NULL)
! 1951: {
! 1952: if (IS_DEBUG_OSPF_NSSA)
! 1953: zlog_debug ("ospf_translated_nssa_refresh(): Could not translate "
! 1954: "Type-7 for %s to Type-5",
! 1955: inet_ntoa (type7->data->id));
! 1956: return NULL;
! 1957: }
! 1958:
! 1959: if ( !(new = ospf_lsa_install (ospf, NULL, new)) )
! 1960: {
! 1961: if (IS_DEBUG_OSPF_NSSA)
! 1962: zlog_debug ("ospf_translated_nssa_refresh(): Could not install "
! 1963: "translated LSA, Id %s",
! 1964: inet_ntoa (type7->data->id));
! 1965: return NULL;
! 1966: }
! 1967:
! 1968: /* Flood LSA through area. */
! 1969: ospf_flood_through_as (ospf, NULL, new);
! 1970:
! 1971: return new;
! 1972: }
! 1973:
! 1974: int
! 1975: is_prefix_default (struct prefix_ipv4 *p)
! 1976: {
! 1977: struct prefix_ipv4 q;
! 1978:
! 1979: q.family = AF_INET;
! 1980: q.prefix.s_addr = 0;
! 1981: q.prefixlen = 0;
! 1982:
! 1983: return prefix_same ((struct prefix *) p, (struct prefix *) &q);
! 1984: }
! 1985:
! 1986: /* Originate an AS-external-LSA, install and flood. */
! 1987: struct ospf_lsa *
! 1988: ospf_external_lsa_originate (struct ospf *ospf, struct external_info *ei)
! 1989: {
! 1990: struct ospf_lsa *new;
! 1991:
! 1992: /* Added for NSSA project....
! 1993:
! 1994: External LSAs are originated in ASBRs as usual, but for NSSA systems.
! 1995: there is the global Type-5 LSDB and a Type-7 LSDB installed for
! 1996: every area. The Type-7's are flooded to every IR and every ABR; We
! 1997: install the Type-5 LSDB so that the normal "refresh" code operates
! 1998: as usual, and flag them as not used during ASE calculations. The
! 1999: Type-7 LSDB is used for calculations. Each Type-7 has a Forwarding
! 2000: Address of non-zero.
! 2001:
! 2002: If an ABR is the elected NSSA translator, following SPF and during
! 2003: the ABR task it will translate all the scanned Type-7's, with P-bit
! 2004: ON and not-self generated, and translate to Type-5's throughout the
! 2005: non-NSSA/STUB AS.
! 2006:
! 2007: A difference in operation depends whether this ASBR is an ABR
! 2008: or not. If not an ABR, the P-bit is ON, to indicate that any
! 2009: elected NSSA-ABR can perform its translation.
! 2010:
! 2011: If an ABR, the P-bit is OFF; No ABR will perform translation and
! 2012: this ASBR will flood the Type-5 LSA as usual.
! 2013:
! 2014: For the case where this ASBR is not an ABR, the ASE calculations
! 2015: are based on the Type-5 LSDB; The Type-7 LSDB exists just to
! 2016: demonstrate to the user that there are LSA's that belong to any
! 2017: attached NSSA.
! 2018:
! 2019: Finally, it just so happens that when the ABR is translating every
! 2020: Type-7 into Type-5, it installs it into the Type-5 LSDB as an
! 2021: approved Type-5 (translated from Type-7); at the end of translation
! 2022: if any Translated Type-5's remain unapproved, then they must be
! 2023: flushed from the AS.
! 2024:
! 2025: */
! 2026:
! 2027: /* Check the AS-external-LSA should be originated. */
! 2028: if (!ospf_redistribute_check (ospf, ei, NULL))
! 2029: return NULL;
! 2030:
! 2031: /* Create new AS-external-LSA instance. */
! 2032: if ((new = ospf_external_lsa_new (ospf, ei, NULL)) == NULL)
! 2033: {
! 2034: if (IS_DEBUG_OSPF_EVENT)
! 2035: zlog_debug ("LSA[Type5:%s]: Could not originate AS-external-LSA",
! 2036: inet_ntoa (ei->p.prefix));
! 2037: return NULL;
! 2038: }
! 2039:
! 2040: /* Install newly created LSA into Type-5 LSDB, lock = 1. */
! 2041: ospf_lsa_install (ospf, NULL, new);
! 2042:
! 2043: /* Update LSA origination count. */
! 2044: ospf->lsa_originate_count++;
! 2045:
! 2046: /* Flooding new LSA. only to AS (non-NSSA/STUB) */
! 2047: ospf_flood_through_as (ospf, NULL, new);
! 2048:
! 2049: /* If there is any attached NSSA, do special handling */
! 2050: if (ospf->anyNSSA &&
! 2051: /* stay away from translated LSAs! */
! 2052: !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT)))
! 2053: ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */
! 2054:
! 2055: /* Debug logging. */
! 2056: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 2057: {
! 2058: zlog_debug ("LSA[Type%d:%s]: Originate AS-external-LSA %p",
! 2059: new->data->type, inet_ntoa (new->data->id), new);
! 2060: ospf_lsa_header_dump (new->data);
! 2061: }
! 2062:
! 2063: return new;
! 2064: }
! 2065:
! 2066: /* Originate AS-external-LSA from external info with initial flag. */
! 2067: int
! 2068: ospf_external_lsa_originate_timer (struct thread *thread)
! 2069: {
! 2070: struct ospf *ospf = THREAD_ARG (thread);
! 2071: struct route_node *rn;
! 2072: struct external_info *ei;
! 2073: struct route_table *rt;
! 2074: int type = THREAD_VAL (thread);
! 2075:
! 2076: ospf->t_external_lsa = NULL;
! 2077:
! 2078: /* Originate As-external-LSA from all type of distribute source. */
! 2079: if ((rt = EXTERNAL_INFO (type)))
! 2080: for (rn = route_top (rt); rn; rn = route_next (rn))
! 2081: if ((ei = rn->info) != NULL)
! 2082: if (!is_prefix_default ((struct prefix_ipv4 *)&ei->p))
! 2083: if (!ospf_external_lsa_originate (ospf, ei))
! 2084: zlog_warn ("LSA: AS-external-LSA was not originated.");
! 2085:
! 2086: return 0;
! 2087: }
! 2088:
! 2089: static struct external_info *
! 2090: ospf_default_external_info (struct ospf *ospf)
! 2091: {
! 2092: int type;
! 2093: struct route_node *rn;
! 2094: struct prefix_ipv4 p;
! 2095:
! 2096: p.family = AF_INET;
! 2097: p.prefix.s_addr = 0;
! 2098: p.prefixlen = 0;
! 2099:
! 2100: /* First, lookup redistributed default route. */
! 2101: for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
! 2102: if (EXTERNAL_INFO (type) && type != ZEBRA_ROUTE_OSPF)
! 2103: {
! 2104: rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p);
! 2105: if (rn != NULL)
! 2106: {
! 2107: route_unlock_node (rn);
! 2108: assert (rn->info);
! 2109: if (ospf_redistribute_check (ospf, rn->info, NULL))
! 2110: return rn->info;
! 2111: }
! 2112: }
! 2113:
! 2114: return NULL;
! 2115: }
! 2116:
! 2117: int
! 2118: ospf_default_originate_timer (struct thread *thread)
! 2119: {
! 2120: struct prefix_ipv4 p;
! 2121: struct in_addr nexthop;
! 2122: struct external_info *ei;
! 2123: struct ospf *ospf;
! 2124:
! 2125: ospf = THREAD_ARG (thread);
! 2126:
! 2127: p.family = AF_INET;
! 2128: p.prefix.s_addr = 0;
! 2129: p.prefixlen = 0;
! 2130:
! 2131: if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS)
! 2132: {
! 2133: /* If there is no default route via redistribute,
! 2134: then originate AS-external-LSA with nexthop 0 (self). */
! 2135: nexthop.s_addr = 0;
! 2136: ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop);
! 2137: }
! 2138:
! 2139: if ((ei = ospf_default_external_info (ospf)))
! 2140: ospf_external_lsa_originate (ospf, ei);
! 2141:
! 2142: return 0;
! 2143: }
! 2144:
! 2145: /* Flush any NSSA LSAs for given prefix */
! 2146: void
! 2147: ospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p)
! 2148: {
! 2149: struct listnode *node, *nnode;
! 2150: struct ospf_lsa *lsa;
! 2151: struct ospf_area *area;
! 2152:
! 2153: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 2154: {
! 2155: if (area->external_routing == OSPF_AREA_NSSA)
! 2156: {
! 2157: if (!(lsa = ospf_lsa_lookup (area, OSPF_AS_NSSA_LSA, p->prefix,
! 2158: ospf->router_id)))
! 2159: {
! 2160: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2161: zlog_debug ("LSA: There is no such AS-NSSA-LSA %s/%d in LSDB",
! 2162: inet_ntoa (p->prefix), p->prefixlen);
! 2163: continue;
! 2164: }
! 2165: ospf_ls_retransmit_delete_nbr_area (area, lsa);
! 2166: if (!IS_LSA_MAXAGE (lsa))
! 2167: {
! 2168: ospf_refresher_unregister_lsa (ospf, lsa);
! 2169: ospf_lsa_flush_area (lsa, area);
! 2170: }
! 2171: }
! 2172: }
! 2173: }
! 2174:
! 2175: /* Flush an AS-external-LSA from LSDB and routing domain. */
! 2176: void
! 2177: ospf_external_lsa_flush (struct ospf *ospf,
! 2178: u_char type, struct prefix_ipv4 *p,
! 2179: unsigned int ifindex /*, struct in_addr nexthop */)
! 2180: {
! 2181: struct ospf_lsa *lsa;
! 2182:
! 2183: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2184: zlog_debug ("LSA: Flushing AS-external-LSA %s/%d",
! 2185: inet_ntoa (p->prefix), p->prefixlen);
! 2186:
! 2187: /* First lookup LSA from LSDB. */
! 2188: if (!(lsa = ospf_external_info_find_lsa (ospf, p)))
! 2189: {
! 2190: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2191: zlog_debug ("LSA: There is no such AS-external-LSA %s/%d in LSDB",
! 2192: inet_ntoa (p->prefix), p->prefixlen);
! 2193: return;
! 2194: }
! 2195:
! 2196: /* If LSA is selforiginated, not a translated LSA, and there is
! 2197: * NSSA area, flush Type-7 LSA's at first.
! 2198: */
! 2199: if (IS_LSA_SELF(lsa) && (ospf->anyNSSA)
! 2200: && !(CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT)))
! 2201: ospf_nssa_lsa_flush (ospf, p);
! 2202:
! 2203: /* Sweep LSA from Link State Retransmit List. */
! 2204: ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
! 2205:
! 2206: /* There must be no self-originated LSA in rtrs_external. */
! 2207: #if 0
! 2208: /* Remove External route from Zebra. */
! 2209: ospf_zebra_delete ((struct prefix_ipv4 *) p, &nexthop);
! 2210: #endif
! 2211:
! 2212: if (!IS_LSA_MAXAGE (lsa))
! 2213: {
! 2214: /* Unregister LSA from Refresh queue. */
! 2215: ospf_refresher_unregister_lsa (ospf, lsa);
! 2216:
! 2217: /* Flush AS-external-LSA through AS. */
! 2218: ospf_lsa_flush_as (ospf, lsa);
! 2219: }
! 2220:
! 2221: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2222: zlog_debug ("ospf_external_lsa_flush(): stop");
! 2223: }
! 2224:
! 2225: void
! 2226: ospf_external_lsa_refresh_default (struct ospf *ospf)
! 2227: {
! 2228: struct prefix_ipv4 p;
! 2229: struct external_info *ei;
! 2230: struct ospf_lsa *lsa;
! 2231:
! 2232: p.family = AF_INET;
! 2233: p.prefixlen = 0;
! 2234: p.prefix.s_addr = 0;
! 2235:
! 2236: ei = ospf_default_external_info (ospf);
! 2237: lsa = ospf_external_info_find_lsa (ospf, &p);
! 2238:
! 2239: if (ei)
! 2240: {
! 2241: if (lsa)
! 2242: {
! 2243: if (IS_DEBUG_OSPF_EVENT)
! 2244: zlog_debug ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", lsa);
! 2245: ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
! 2246: }
! 2247: else
! 2248: {
! 2249: if (IS_DEBUG_OSPF_EVENT)
! 2250: zlog_debug ("LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
! 2251: ospf_external_lsa_originate (ospf, ei);
! 2252: }
! 2253: }
! 2254: else
! 2255: {
! 2256: if (lsa)
! 2257: {
! 2258: if (IS_DEBUG_OSPF_EVENT)
! 2259: zlog_debug ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA");
! 2260: ospf_refresher_unregister_lsa (ospf, lsa);
! 2261: ospf_lsa_flush_as (ospf, lsa);
! 2262: }
! 2263: }
! 2264: }
! 2265:
! 2266: void
! 2267: ospf_external_lsa_refresh_type (struct ospf *ospf, u_char type, int force)
! 2268: {
! 2269: struct route_node *rn;
! 2270: struct external_info *ei;
! 2271:
! 2272: if (type != DEFAULT_ROUTE)
! 2273: if (EXTERNAL_INFO(type))
! 2274: /* Refresh each redistributed AS-external-LSAs. */
! 2275: for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn))
! 2276: if ((ei = rn->info))
! 2277: if (!is_prefix_default (&ei->p))
! 2278: {
! 2279: struct ospf_lsa *lsa;
! 2280:
! 2281: if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
! 2282: ospf_external_lsa_refresh (ospf, lsa, ei, force);
! 2283: else
! 2284: ospf_external_lsa_originate (ospf, ei);
! 2285: }
! 2286: }
! 2287:
! 2288: /* Refresh AS-external-LSA. */
! 2289: struct ospf_lsa *
! 2290: ospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa,
! 2291: struct external_info *ei, int force)
! 2292: {
! 2293: struct ospf_lsa *new;
! 2294: int changed;
! 2295:
! 2296: /* Check the AS-external-LSA should be originated. */
! 2297: if (!ospf_redistribute_check (ospf, ei, &changed))
! 2298: {
! 2299: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 2300: zlog_debug ("LSA[Type%d:%s]: Could not be refreshed, "
! 2301: "redist check fail",
! 2302: lsa->data->type, inet_ntoa (lsa->data->id));
! 2303: ospf_external_lsa_flush (ospf, ei->type, &ei->p,
! 2304: ei->ifindex /*, ei->nexthop */);
! 2305: return NULL;
! 2306: }
! 2307:
! 2308: if (!changed && !force)
! 2309: {
! 2310: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 2311: zlog_debug ("LSA[Type%d:%s]: Not refreshed, not changed/forced",
! 2312: lsa->data->type, inet_ntoa (lsa->data->id));
! 2313: return NULL;
! 2314: }
! 2315:
! 2316: /* Delete LSA from neighbor retransmit-list. */
! 2317: ospf_ls_retransmit_delete_nbr_as (ospf, lsa);
! 2318:
! 2319: /* Unregister AS-external-LSA from refresh-list. */
! 2320: ospf_refresher_unregister_lsa (ospf, lsa);
! 2321:
! 2322: new = ospf_external_lsa_new (ospf, ei, &lsa->data->id);
! 2323:
! 2324: if (new == NULL)
! 2325: {
! 2326: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 2327: zlog_debug ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type,
! 2328: inet_ntoa (lsa->data->id));
! 2329: return NULL;
! 2330: }
! 2331:
! 2332: new->data->ls_seqnum = lsa_seqnum_increment (lsa);
! 2333:
! 2334: ospf_lsa_install (ospf, NULL, new); /* As type-5. */
! 2335:
! 2336: /* Flood LSA through AS. */
! 2337: ospf_flood_through_as (ospf, NULL, new);
! 2338:
! 2339: /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */
! 2340: if (ospf->anyNSSA && !(CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT)))
! 2341: ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood per new rules */
! 2342:
! 2343: /* Register self-originated LSA to refresh queue.
! 2344: * Translated LSAs should not be registered, but refreshed upon
! 2345: * refresh of the Type-7
! 2346: */
! 2347: if ( !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT) )
! 2348: ospf_refresher_register_lsa (ospf, new);
! 2349:
! 2350: /* Debug logging. */
! 2351: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 2352: {
! 2353: zlog_debug ("LSA[Type%d:%s]: AS-external-LSA refresh",
! 2354: new->data->type, inet_ntoa (new->data->id));
! 2355: ospf_lsa_header_dump (new->data);
! 2356: }
! 2357:
! 2358: return new;
! 2359: }
! 2360:
! 2361:
! 2362: /* LSA installation functions. */
! 2363:
! 2364: /* Install router-LSA to an area. */
! 2365: static struct ospf_lsa *
! 2366: ospf_router_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
! 2367: int rt_recalc)
! 2368: {
! 2369: struct ospf_area *area = new->area;
! 2370:
! 2371: /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
! 2372: The entire routing table must be recalculated, starting with
! 2373: the shortest path calculations for each area (not just the
! 2374: area whose link-state database has changed).
! 2375: */
! 2376:
! 2377: if (IS_LSA_SELF (new))
! 2378: {
! 2379:
! 2380: /* Only install LSA if it is originated/refreshed by us.
! 2381: * If LSA was received by flooding, the RECEIVED flag is set so do
! 2382: * not link the LSA */
! 2383: if (CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED))
! 2384: return new; /* ignore stale LSA */
! 2385:
! 2386: /* Set self-originated router-LSA. */
! 2387: ospf_lsa_unlock (&area->router_lsa_self);
! 2388: area->router_lsa_self = ospf_lsa_lock (new);
! 2389:
! 2390: ospf_refresher_register_lsa (ospf, new);
! 2391: }
! 2392: if (rt_recalc)
! 2393: ospf_spf_calculate_schedule (ospf);
! 2394:
! 2395: return new;
! 2396: }
! 2397:
! 2398: #define OSPF_INTERFACE_TIMER_ON(T,F,V) \
! 2399: if (!(T)) \
! 2400: (T) = thread_add_timer (master, (F), oi, (V))
! 2401:
! 2402: /* Install network-LSA to an area. */
! 2403: static struct ospf_lsa *
! 2404: ospf_network_lsa_install (struct ospf *ospf,
! 2405: struct ospf_interface *oi,
! 2406: struct ospf_lsa *new,
! 2407: int rt_recalc)
! 2408: {
! 2409:
! 2410: /* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
! 2411: The entire routing table must be recalculated, starting with
! 2412: the shortest path calculations for each area (not just the
! 2413: area whose link-state database has changed).
! 2414: */
! 2415: if (IS_LSA_SELF (new))
! 2416: {
! 2417: /* We supposed that when LSA is originated by us, we pass the int
! 2418: for which it was originated. If LSA was received by flooding,
! 2419: the RECEIVED flag is set, so we do not link the LSA to the int. */
! 2420: if (CHECK_FLAG (new->flags, OSPF_LSA_RECEIVED))
! 2421: return new; /* ignore stale LSA */
! 2422:
! 2423: ospf_lsa_unlock (&oi->network_lsa_self);
! 2424: oi->network_lsa_self = ospf_lsa_lock (new);
! 2425: ospf_refresher_register_lsa (ospf, new);
! 2426: }
! 2427: if (rt_recalc)
! 2428: ospf_spf_calculate_schedule (ospf);
! 2429:
! 2430: return new;
! 2431: }
! 2432:
! 2433: /* Install summary-LSA to an area. */
! 2434: static struct ospf_lsa *
! 2435: ospf_summary_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
! 2436: int rt_recalc)
! 2437: {
! 2438: if (rt_recalc && !IS_LSA_SELF (new))
! 2439: {
! 2440: /* RFC 2328 Section 13.2 Summary-LSAs
! 2441: The best route to the destination described by the summary-
! 2442: LSA must be recalculated (see Section 16.5). If this
! 2443: destination is an AS boundary router, it may also be
! 2444: necessary to re-examine all the AS-external-LSAs.
! 2445: */
! 2446:
! 2447: #if 0
! 2448: /* This doesn't exist yet... */
! 2449: ospf_summary_incremental_update(new); */
! 2450: #else /* #if 0 */
! 2451: ospf_spf_calculate_schedule (ospf);
! 2452: #endif /* #if 0 */
! 2453:
! 2454: if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
! 2455: zlog_debug ("ospf_summary_lsa_install(): SPF scheduled");
! 2456: }
! 2457:
! 2458: if (IS_LSA_SELF (new))
! 2459: ospf_refresher_register_lsa (ospf, new);
! 2460:
! 2461: return new;
! 2462: }
! 2463:
! 2464: /* Install ASBR-summary-LSA to an area. */
! 2465: static struct ospf_lsa *
! 2466: ospf_summary_asbr_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
! 2467: int rt_recalc)
! 2468: {
! 2469: if (rt_recalc && !IS_LSA_SELF (new))
! 2470: {
! 2471: /* RFC 2328 Section 13.2 Summary-LSAs
! 2472: The best route to the destination described by the summary-
! 2473: LSA must be recalculated (see Section 16.5). If this
! 2474: destination is an AS boundary router, it may also be
! 2475: necessary to re-examine all the AS-external-LSAs.
! 2476: */
! 2477: #if 0
! 2478: /* These don't exist yet... */
! 2479: ospf_summary_incremental_update(new);
! 2480: /* Isn't this done by the above call?
! 2481: - RFC 2328 Section 16.5 implies it should be */
! 2482: /* ospf_ase_calculate_schedule(); */
! 2483: #else /* #if 0 */
! 2484: ospf_spf_calculate_schedule (ospf);
! 2485: #endif /* #if 0 */
! 2486: }
! 2487:
! 2488: /* register LSA to refresh-list. */
! 2489: if (IS_LSA_SELF (new))
! 2490: ospf_refresher_register_lsa (ospf, new);
! 2491:
! 2492: return new;
! 2493: }
! 2494:
! 2495: /* Install AS-external-LSA. */
! 2496: static struct ospf_lsa *
! 2497: ospf_external_lsa_install (struct ospf *ospf, struct ospf_lsa *new,
! 2498: int rt_recalc)
! 2499: {
! 2500: ospf_ase_register_external_lsa (new, ospf);
! 2501: /* If LSA is not self-originated, calculate an external route. */
! 2502: if (rt_recalc)
! 2503: {
! 2504: /* RFC 2328 Section 13.2 AS-external-LSAs
! 2505: The best route to the destination described by the AS-
! 2506: external-LSA must be recalculated (see Section 16.6).
! 2507: */
! 2508:
! 2509: if (!IS_LSA_SELF (new))
! 2510: ospf_ase_incremental_update (ospf, new);
! 2511: }
! 2512:
! 2513: if (new->data->type == OSPF_AS_NSSA_LSA)
! 2514: {
! 2515: /* There is no point to register selforiginate Type-7 LSA for
! 2516: * refreshing. We rely on refreshing Type-5 LSA's
! 2517: */
! 2518: if (IS_LSA_SELF (new))
! 2519: return new;
! 2520: else
! 2521: {
! 2522: /* Try refresh type-5 translated LSA for this LSA, if one exists.
! 2523: * New translations will be taken care of by the abr_task.
! 2524: */
! 2525: ospf_translated_nssa_refresh (ospf, new, NULL);
! 2526: }
! 2527: }
! 2528:
! 2529: /* Register self-originated LSA to refresh queue.
! 2530: * Leave Translated LSAs alone if NSSA is enabled
! 2531: */
! 2532: if (IS_LSA_SELF (new) && !CHECK_FLAG (new->flags, OSPF_LSA_LOCAL_XLT ) )
! 2533: ospf_refresher_register_lsa (ospf, new);
! 2534:
! 2535: return new;
! 2536: }
! 2537:
! 2538: void
! 2539: ospf_discard_from_db (struct ospf *ospf,
! 2540: struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
! 2541: {
! 2542: struct ospf_lsa *old;
! 2543:
! 2544: if (!lsdb)
! 2545: {
! 2546: zlog_warn ("%s: Called with NULL lsdb!", __func__);
! 2547: if (!lsa)
! 2548: zlog_warn ("%s: and NULL LSA!", __func__);
! 2549: else
! 2550: zlog_warn ("LSA[Type%d:%s]: not associated with LSDB!",
! 2551: lsa->data->type, inet_ntoa (lsa->data->id));
! 2552: return;
! 2553: }
! 2554:
! 2555: old = ospf_lsdb_lookup (lsdb, lsa);
! 2556:
! 2557: if (!old)
! 2558: return;
! 2559:
! 2560: if (old->refresh_list >= 0)
! 2561: ospf_refresher_unregister_lsa (ospf, old);
! 2562:
! 2563: switch (old->data->type)
! 2564: {
! 2565: case OSPF_AS_EXTERNAL_LSA:
! 2566: ospf_ase_unregister_external_lsa (old, ospf);
! 2567: ospf_ls_retransmit_delete_nbr_as (ospf, old);
! 2568: break;
! 2569: #ifdef HAVE_OPAQUE_LSA
! 2570: case OSPF_OPAQUE_AS_LSA:
! 2571: ospf_ls_retransmit_delete_nbr_as (ospf, old);
! 2572: break;
! 2573: #endif /* HAVE_OPAQUE_LSA */
! 2574: case OSPF_AS_NSSA_LSA:
! 2575: ospf_ls_retransmit_delete_nbr_area (old->area, old);
! 2576: ospf_ase_unregister_external_lsa (old, ospf);
! 2577: break;
! 2578: default:
! 2579: ospf_ls_retransmit_delete_nbr_area (old->area, old);
! 2580: break;
! 2581: }
! 2582:
! 2583: ospf_lsa_maxage_delete (ospf, old);
! 2584: ospf_lsa_discard (old);
! 2585: }
! 2586:
! 2587: struct ospf_lsa *
! 2588: ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi,
! 2589: struct ospf_lsa *lsa)
! 2590: {
! 2591: struct ospf_lsa *new = NULL;
! 2592: struct ospf_lsa *old = NULL;
! 2593: struct ospf_lsdb *lsdb = NULL;
! 2594: int rt_recalc;
! 2595:
! 2596: /* Set LSDB. */
! 2597: switch (lsa->data->type)
! 2598: {
! 2599: /* kevinm */
! 2600: case OSPF_AS_NSSA_LSA:
! 2601: if (lsa->area)
! 2602: lsdb = lsa->area->lsdb;
! 2603: else
! 2604: lsdb = ospf->lsdb;
! 2605: break;
! 2606: case OSPF_AS_EXTERNAL_LSA:
! 2607: #ifdef HAVE_OPAQUE_LSA
! 2608: case OSPF_OPAQUE_AS_LSA:
! 2609: #endif /* HAVE_OPAQUE_LSA */
! 2610: lsdb = ospf->lsdb;
! 2611: break;
! 2612: default:
! 2613: lsdb = lsa->area->lsdb;
! 2614: break;
! 2615: }
! 2616:
! 2617: assert (lsdb);
! 2618:
! 2619: /* RFC 2328 13.2. Installing LSAs in the database
! 2620:
! 2621: Installing a new LSA in the database, either as the result of
! 2622: flooding or a newly self-originated LSA, may cause the OSPF
! 2623: routing table structure to be recalculated. The contents of the
! 2624: new LSA should be compared to the old instance, if present. If
! 2625: there is no difference, there is no need to recalculate the
! 2626: routing table. When comparing an LSA to its previous instance,
! 2627: the following are all considered to be differences in contents:
! 2628:
! 2629: o The LSA's Options field has changed.
! 2630:
! 2631: o One of the LSA instances has LS age set to MaxAge, and
! 2632: the other does not.
! 2633:
! 2634: o The length field in the LSA header has changed.
! 2635:
! 2636: o The body of the LSA (i.e., anything outside the 20-byte
! 2637: LSA header) has changed. Note that this excludes changes
! 2638: in LS Sequence Number and LS Checksum.
! 2639:
! 2640: */
! 2641: /* Look up old LSA and determine if any SPF calculation or incremental
! 2642: update is needed */
! 2643: old = ospf_lsdb_lookup (lsdb, lsa);
! 2644:
! 2645: /* Do comparision and record if recalc needed. */
! 2646: rt_recalc = 0;
! 2647: if ( old == NULL || ospf_lsa_different(old, lsa))
! 2648: rt_recalc = 1;
! 2649:
! 2650: /*
! 2651: Sequence number check (Section 14.1 of rfc 2328)
! 2652: "Premature aging is used when it is time for a self-originated
! 2653: LSA's sequence number field to wrap. At this point, the current
! 2654: LSA instance (having LS sequence number MaxSequenceNumber) must
! 2655: be prematurely aged and flushed from the routing domain before a
! 2656: new instance with sequence number equal to InitialSequenceNumber
! 2657: can be originated. "
! 2658: */
! 2659:
! 2660: if (ntohl(lsa->data->ls_seqnum) - 1 == OSPF_MAX_SEQUENCE_NUMBER)
! 2661: {
! 2662: if (ospf_lsa_is_self_originated(ospf, lsa))
! 2663: {
! 2664: lsa->data->ls_seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER);
! 2665:
! 2666: if (!IS_LSA_MAXAGE(lsa))
! 2667: lsa->flags |= OSPF_LSA_PREMATURE_AGE;
! 2668: lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
! 2669:
! 2670: if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
! 2671: {
! 2672: zlog_debug ("ospf_lsa_install() Premature Aging "
! 2673: "lsa 0x%p, seqnum 0x%x",
! 2674: lsa, ntohl(lsa->data->ls_seqnum));
! 2675: ospf_lsa_header_dump (lsa->data);
! 2676: }
! 2677: }
! 2678: else
! 2679: {
! 2680: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 2681: {
! 2682: zlog_debug ("ospf_lsa_install() got an lsa with seq 0x80000000 "
! 2683: "that was not self originated. Ignoring\n");
! 2684: ospf_lsa_header_dump (lsa->data);
! 2685: }
! 2686: return old;
! 2687: }
! 2688: }
! 2689:
! 2690: /* discard old LSA from LSDB */
! 2691: if (old != NULL)
! 2692: ospf_discard_from_db (ospf, lsdb, lsa);
! 2693:
! 2694: /* Calculate Checksum if self-originated?. */
! 2695: if (IS_LSA_SELF (lsa))
! 2696: ospf_lsa_checksum (lsa->data);
! 2697:
! 2698: /* Insert LSA to LSDB. */
! 2699: ospf_lsdb_add (lsdb, lsa);
! 2700: lsa->lsdb = lsdb;
! 2701:
! 2702: /* Do LSA specific installation process. */
! 2703: switch (lsa->data->type)
! 2704: {
! 2705: case OSPF_ROUTER_LSA:
! 2706: new = ospf_router_lsa_install (ospf, lsa, rt_recalc);
! 2707: break;
! 2708: case OSPF_NETWORK_LSA:
! 2709: assert (oi);
! 2710: new = ospf_network_lsa_install (ospf, oi, lsa, rt_recalc);
! 2711: break;
! 2712: case OSPF_SUMMARY_LSA:
! 2713: new = ospf_summary_lsa_install (ospf, lsa, rt_recalc);
! 2714: break;
! 2715: case OSPF_ASBR_SUMMARY_LSA:
! 2716: new = ospf_summary_asbr_lsa_install (ospf, lsa, rt_recalc);
! 2717: break;
! 2718: case OSPF_AS_EXTERNAL_LSA:
! 2719: new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
! 2720: break;
! 2721: #ifdef HAVE_OPAQUE_LSA
! 2722: case OSPF_OPAQUE_LINK_LSA:
! 2723: if (IS_LSA_SELF (lsa))
! 2724: lsa->oi = oi; /* Specify outgoing ospf-interface for this LSA. */
! 2725: else
! 2726: ; /* Incoming "oi" for this LSA has set at LSUpd reception. */
! 2727: /* Fallthrough */
! 2728: case OSPF_OPAQUE_AREA_LSA:
! 2729: case OSPF_OPAQUE_AS_LSA:
! 2730: new = ospf_opaque_lsa_install (lsa, rt_recalc);
! 2731: break;
! 2732: #endif /* HAVE_OPAQUE_LSA */
! 2733: case OSPF_AS_NSSA_LSA:
! 2734: new = ospf_external_lsa_install (ospf, lsa, rt_recalc);
! 2735: default: /* type-6,8,9....nothing special */
! 2736: break;
! 2737: }
! 2738:
! 2739: if (new == NULL)
! 2740: return new; /* Installation failed, cannot proceed further -- endo. */
! 2741:
! 2742: /* Debug logs. */
! 2743: if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
! 2744: {
! 2745: char area_str[INET_ADDRSTRLEN];
! 2746:
! 2747: switch (lsa->data->type)
! 2748: {
! 2749: case OSPF_AS_EXTERNAL_LSA:
! 2750: #ifdef HAVE_OPAQUE_LSA
! 2751: case OSPF_OPAQUE_AS_LSA:
! 2752: #endif /* HAVE_OPAQUE_LSA */
! 2753: case OSPF_AS_NSSA_LSA:
! 2754: zlog_debug ("LSA[%s]: Install %s",
! 2755: dump_lsa_key (new),
! 2756: LOOKUP (ospf_lsa_type_msg, new->data->type));
! 2757: break;
! 2758: default:
! 2759: strcpy (area_str, inet_ntoa (new->area->area_id));
! 2760: zlog_debug ("LSA[%s]: Install %s to Area %s",
! 2761: dump_lsa_key (new),
! 2762: LOOKUP (ospf_lsa_type_msg, new->data->type), area_str);
! 2763: break;
! 2764: }
! 2765: }
! 2766:
! 2767: /*
! 2768: If received LSA' ls_age is MaxAge, or lsa is being prematurely aged
! 2769: (it's getting flushed out of the area), set LSA on MaxAge LSA list.
! 2770: */
! 2771: if ((lsa->flags & OSPF_LSA_PREMATURE_AGE) ||
! 2772: (IS_LSA_MAXAGE (new) && !IS_LSA_SELF (new)))
! 2773: {
! 2774: if (IS_DEBUG_OSPF (lsa, LSA_INSTALL))
! 2775: zlog_debug ("LSA[Type%d:%s]: Install LSA 0x%p, MaxAge",
! 2776: new->data->type,
! 2777: inet_ntoa (new->data->id),
! 2778: lsa);
! 2779: ospf_lsa_flush (ospf, lsa);
! 2780: }
! 2781:
! 2782: return new;
! 2783: }
! 2784:
! 2785:
! 2786: static int
! 2787: ospf_check_nbr_status (struct ospf *ospf)
! 2788: {
! 2789: struct listnode *node, *nnode;
! 2790: struct ospf_interface *oi;
! 2791:
! 2792: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
! 2793: {
! 2794: struct route_node *rn;
! 2795: struct ospf_neighbor *nbr;
! 2796:
! 2797: if (ospf_if_is_enable (oi))
! 2798: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
! 2799: if ((nbr = rn->info) != NULL)
! 2800: if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading)
! 2801: {
! 2802: route_unlock_node (rn);
! 2803: return 0;
! 2804: }
! 2805: }
! 2806:
! 2807: return 1;
! 2808: }
! 2809:
! 2810:
! 2811:
! 2812: static int
! 2813: ospf_maxage_lsa_remover (struct thread *thread)
! 2814: {
! 2815: struct ospf *ospf = THREAD_ARG (thread);
! 2816: struct ospf_lsa *lsa;
! 2817: struct listnode *node, *nnode;
! 2818: int reschedule = 0;
! 2819:
! 2820: ospf->t_maxage = NULL;
! 2821:
! 2822: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2823: zlog_debug ("LSA[MaxAge]: remover Start");
! 2824:
! 2825: reschedule = !ospf_check_nbr_status (ospf);
! 2826:
! 2827: if (!reschedule)
! 2828: for (ALL_LIST_ELEMENTS (ospf->maxage_lsa, node, nnode, lsa))
! 2829: {
! 2830: if (lsa->retransmit_counter > 0)
! 2831: {
! 2832: reschedule = 1;
! 2833: continue;
! 2834: }
! 2835:
! 2836: /* TODO: maybe convert this function to a work-queue */
! 2837: if (thread_should_yield (thread))
! 2838: OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover, 0);
! 2839:
! 2840: /* Remove LSA from the LSDB */
! 2841: if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF))
! 2842: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2843: zlog_debug ("LSA[Type%d:%s]: LSA 0x%lx is self-oririnated: ",
! 2844: lsa->data->type, inet_ntoa (lsa->data->id), (u_long)lsa);
! 2845:
! 2846: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2847: zlog_debug ("LSA[Type%d:%s]: MaxAge LSA removed from list",
! 2848: lsa->data->type, inet_ntoa (lsa->data->id));
! 2849:
! 2850: if (CHECK_FLAG (lsa->flags, OSPF_LSA_PREMATURE_AGE))
! 2851: {
! 2852: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2853: zlog_debug ("originating new lsa for lsa 0x%p\n", lsa);
! 2854: ospf_lsa_refresh (ospf, lsa);
! 2855: }
! 2856:
! 2857: /* Remove from lsdb. */
! 2858: if (lsa->lsdb)
! 2859: {
! 2860: ospf_discard_from_db (ospf, lsa->lsdb, lsa);
! 2861: ospf_lsdb_delete (lsa->lsdb, lsa);
! 2862: }
! 2863: else
! 2864: zlog_warn ("%s: LSA[Type%d:%s]: No associated LSDB!", __func__,
! 2865: lsa->data->type, inet_ntoa (lsa->data->id));
! 2866: }
! 2867:
! 2868: /* A MaxAge LSA must be removed immediately from the router's link
! 2869: state database as soon as both a) it is no longer contained on any
! 2870: neighbor Link state retransmission lists and b) none of the router's
! 2871: neighbors are in states Exchange or Loading. */
! 2872: if (reschedule)
! 2873: OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover,
! 2874: ospf->maxage_delay);
! 2875:
! 2876: return 0;
! 2877: }
! 2878:
! 2879: void
! 2880: ospf_lsa_maxage_delete (struct ospf *ospf, struct ospf_lsa *lsa)
! 2881: {
! 2882: struct listnode *n;
! 2883:
! 2884: if ((n = listnode_lookup (ospf->maxage_lsa, lsa)))
! 2885: {
! 2886: list_delete_node (ospf->maxage_lsa, n);
! 2887: UNSET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE);
! 2888: ospf_lsa_unlock (&lsa); /* maxage_lsa */
! 2889: }
! 2890: }
! 2891:
! 2892: /* Add LSA onto the MaxAge list, and schedule for removal.
! 2893: * This does *not* lead to the LSA being flooded, that must be taken
! 2894: * care of elsewhere, see, e.g., ospf_lsa_flush* (which are callers of this
! 2895: * function).
! 2896: */
! 2897: void
! 2898: ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa)
! 2899: {
! 2900: /* When we saw a MaxAge LSA flooded to us, we put it on the list
! 2901: and schedule the MaxAge LSA remover. */
! 2902: if (CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE))
! 2903: {
! 2904: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2905: zlog_debug ("LSA[Type%d:%s]: %p already exists on MaxAge LSA list",
! 2906: lsa->data->type, inet_ntoa (lsa->data->id), lsa);
! 2907: return;
! 2908: }
! 2909:
! 2910: listnode_add (ospf->maxage_lsa, ospf_lsa_lock (lsa));
! 2911: SET_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE);
! 2912:
! 2913: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2914: zlog_debug ("LSA[%s]: MaxAge LSA remover scheduled.", dump_lsa_key (lsa));
! 2915:
! 2916: OSPF_TIMER_ON (ospf->t_maxage, ospf_maxage_lsa_remover,
! 2917: ospf->maxage_delay);
! 2918: }
! 2919:
! 2920: static int
! 2921: ospf_lsa_maxage_walker_remover (struct ospf *ospf, struct ospf_lsa *lsa)
! 2922: {
! 2923: /* Stay away from any Local Translated Type-7 LSAs */
! 2924: if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
! 2925: return 0;
! 2926:
! 2927: if (IS_LSA_MAXAGE (lsa))
! 2928: /* Self-originated LSAs should NOT time-out instead,
! 2929: they're flushed and submitted to the max_age list explicitly. */
! 2930: if (!ospf_lsa_is_self_originated (ospf, lsa))
! 2931: {
! 2932: if (IS_DEBUG_OSPF (lsa, LSA_FLOODING))
! 2933: zlog_debug("LSA[%s]: is MaxAge", dump_lsa_key (lsa));
! 2934:
! 2935: switch (lsa->data->type)
! 2936: {
! 2937: #ifdef HAVE_OPAQUE_LSA
! 2938: case OSPF_OPAQUE_LINK_LSA:
! 2939: case OSPF_OPAQUE_AREA_LSA:
! 2940: case OSPF_OPAQUE_AS_LSA:
! 2941: /*
! 2942: * As a general rule, whenever network topology has changed
! 2943: * (due to an LSA removal in this case), routing recalculation
! 2944: * should be triggered. However, this is not true for opaque
! 2945: * LSAs. Even if an opaque LSA instance is going to be removed
! 2946: * from the routing domain, it does not mean a change in network
! 2947: * topology, and thus, routing recalculation is not needed here.
! 2948: */
! 2949: break;
! 2950: #endif /* HAVE_OPAQUE_LSA */
! 2951: case OSPF_AS_EXTERNAL_LSA:
! 2952: case OSPF_AS_NSSA_LSA:
! 2953: ospf_ase_incremental_update (ospf, lsa);
! 2954: break;
! 2955: default:
! 2956: ospf_spf_calculate_schedule (ospf);
! 2957: break;
! 2958: }
! 2959: ospf_lsa_maxage (ospf, lsa);
! 2960: }
! 2961:
! 2962: if (IS_LSA_MAXAGE (lsa) && !ospf_lsa_is_self_originated (ospf, lsa))
! 2963: if (LS_AGE (lsa) > OSPF_LSA_MAXAGE + 30)
! 2964: printf ("Eek! Shouldn't happen!\n");
! 2965:
! 2966: return 0;
! 2967: }
! 2968:
! 2969: /* Periodical check of MaxAge LSA. */
! 2970: int
! 2971: ospf_lsa_maxage_walker (struct thread *thread)
! 2972: {
! 2973: struct ospf *ospf = THREAD_ARG (thread);
! 2974: struct route_node *rn;
! 2975: struct ospf_lsa *lsa;
! 2976: struct ospf_area *area;
! 2977: struct listnode *node, *nnode;
! 2978:
! 2979: ospf->t_maxage_walker = NULL;
! 2980:
! 2981: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 2982: {
! 2983: LSDB_LOOP (ROUTER_LSDB (area), rn, lsa)
! 2984: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 2985: LSDB_LOOP (NETWORK_LSDB (area), rn, lsa)
! 2986: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 2987: LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
! 2988: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 2989: LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
! 2990: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 2991: #ifdef HAVE_OPAQUE_LSA
! 2992: LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
! 2993: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 2994: LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
! 2995: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 2996: #endif /* HAVE_OPAQUE_LSA */
! 2997: LSDB_LOOP (NSSA_LSDB (area), rn, lsa)
! 2998: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 2999: }
! 3000:
! 3001: /* for AS-external-LSAs. */
! 3002: if (ospf->lsdb)
! 3003: {
! 3004: LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
! 3005: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 3006: #ifdef HAVE_OPAQUE_LSA
! 3007: LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
! 3008: ospf_lsa_maxage_walker_remover (ospf, lsa);
! 3009: #endif /* HAVE_OPAQUE_LSA */
! 3010: }
! 3011:
! 3012: OSPF_TIMER_ON (ospf->t_maxage_walker, ospf_lsa_maxage_walker,
! 3013: OSPF_LSA_MAXAGE_CHECK_INTERVAL);
! 3014: return 0;
! 3015: }
! 3016:
! 3017: struct ospf_lsa *
! 3018: ospf_lsa_lookup_by_prefix (struct ospf_lsdb *lsdb, u_char type,
! 3019: struct prefix_ipv4 *p, struct in_addr router_id)
! 3020: {
! 3021: struct ospf_lsa *lsa;
! 3022: struct in_addr mask, id;
! 3023: struct lsa_header_mask
! 3024: {
! 3025: struct lsa_header header;
! 3026: struct in_addr mask;
! 3027: } *hmask;
! 3028:
! 3029: lsa = ospf_lsdb_lookup_by_id (lsdb, type, p->prefix, router_id);
! 3030: if (lsa == NULL)
! 3031: return NULL;
! 3032:
! 3033: masklen2ip (p->prefixlen, &mask);
! 3034:
! 3035: hmask = (struct lsa_header_mask *) lsa->data;
! 3036:
! 3037: if (mask.s_addr != hmask->mask.s_addr)
! 3038: {
! 3039: id.s_addr = p->prefix.s_addr | (~mask.s_addr);
! 3040: lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, router_id);
! 3041: if (!lsa)
! 3042: return NULL;
! 3043: }
! 3044:
! 3045: return lsa;
! 3046: }
! 3047:
! 3048: struct ospf_lsa *
! 3049: ospf_lsa_lookup (struct ospf_area *area, u_int32_t type,
! 3050: struct in_addr id, struct in_addr adv_router)
! 3051: {
! 3052: struct ospf *ospf = ospf_lookup();
! 3053: assert(ospf);
! 3054:
! 3055: switch (type)
! 3056: {
! 3057: case OSPF_ROUTER_LSA:
! 3058: case OSPF_NETWORK_LSA:
! 3059: case OSPF_SUMMARY_LSA:
! 3060: case OSPF_ASBR_SUMMARY_LSA:
! 3061: case OSPF_AS_NSSA_LSA:
! 3062: #ifdef HAVE_OPAQUE_LSA
! 3063: case OSPF_OPAQUE_LINK_LSA:
! 3064: case OSPF_OPAQUE_AREA_LSA:
! 3065: #endif /* HAVE_OPAQUE_LSA */
! 3066: return ospf_lsdb_lookup_by_id (area->lsdb, type, id, adv_router);
! 3067: case OSPF_AS_EXTERNAL_LSA:
! 3068: #ifdef HAVE_OPAQUE_LSA
! 3069: case OSPF_OPAQUE_AS_LSA:
! 3070: #endif /* HAVE_OPAQUE_LSA */
! 3071: return ospf_lsdb_lookup_by_id (ospf->lsdb, type, id, adv_router);
! 3072: default:
! 3073: break;
! 3074: }
! 3075:
! 3076: return NULL;
! 3077: }
! 3078:
! 3079: struct ospf_lsa *
! 3080: ospf_lsa_lookup_by_id (struct ospf_area *area, u_int32_t type,
! 3081: struct in_addr id)
! 3082: {
! 3083: struct ospf_lsa *lsa;
! 3084: struct route_node *rn;
! 3085:
! 3086: switch (type)
! 3087: {
! 3088: case OSPF_ROUTER_LSA:
! 3089: return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
! 3090: case OSPF_NETWORK_LSA:
! 3091: for (rn = route_top (NETWORK_LSDB (area)); rn; rn = route_next (rn))
! 3092: if ((lsa = rn->info))
! 3093: if (IPV4_ADDR_SAME (&lsa->data->id, &id))
! 3094: {
! 3095: route_unlock_node (rn);
! 3096: return lsa;
! 3097: }
! 3098: break;
! 3099: case OSPF_SUMMARY_LSA:
! 3100: case OSPF_ASBR_SUMMARY_LSA:
! 3101: /* Currently not used. */
! 3102: assert (1);
! 3103: return ospf_lsdb_lookup_by_id (area->lsdb, type, id, id);
! 3104: case OSPF_AS_EXTERNAL_LSA:
! 3105: case OSPF_AS_NSSA_LSA:
! 3106: #ifdef HAVE_OPAQUE_LSA
! 3107: case OSPF_OPAQUE_LINK_LSA:
! 3108: case OSPF_OPAQUE_AREA_LSA:
! 3109: case OSPF_OPAQUE_AS_LSA:
! 3110: /* Currently not used. */
! 3111: break;
! 3112: #endif /* HAVE_OPAQUE_LSA */
! 3113: default:
! 3114: break;
! 3115: }
! 3116:
! 3117: return NULL;
! 3118: }
! 3119:
! 3120: struct ospf_lsa *
! 3121: ospf_lsa_lookup_by_header (struct ospf_area *area, struct lsa_header *lsah)
! 3122: {
! 3123: struct ospf_lsa *match;
! 3124:
! 3125: #ifdef HAVE_OPAQUE_LSA
! 3126: /*
! 3127: * Strictly speaking, the LSA-ID field for Opaque-LSAs (type-9/10/11)
! 3128: * is redefined to have two subfields; opaque-type and opaque-id.
! 3129: * However, it is harmless to treat the two sub fields together, as if
! 3130: * they two were forming a unique LSA-ID.
! 3131: */
! 3132: #endif /* HAVE_OPAQUE_LSA */
! 3133:
! 3134: match = ospf_lsa_lookup (area, lsah->type, lsah->id, lsah->adv_router);
! 3135:
! 3136: if (match == NULL)
! 3137: if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
! 3138: zlog_debug ("LSA[Type%d:%s]: Lookup by header, NO MATCH",
! 3139: lsah->type, inet_ntoa (lsah->id));
! 3140:
! 3141: return match;
! 3142: }
! 3143:
! 3144: /* return +n, l1 is more recent.
! 3145: return -n, l2 is more recent.
! 3146: return 0, l1 and l2 is identical. */
! 3147: int
! 3148: ospf_lsa_more_recent (struct ospf_lsa *l1, struct ospf_lsa *l2)
! 3149: {
! 3150: int r;
! 3151: int x, y;
! 3152:
! 3153: if (l1 == NULL && l2 == NULL)
! 3154: return 0;
! 3155: if (l1 == NULL)
! 3156: return -1;
! 3157: if (l2 == NULL)
! 3158: return 1;
! 3159:
! 3160: /* compare LS sequence number. */
! 3161: x = (int) ntohl (l1->data->ls_seqnum);
! 3162: y = (int) ntohl (l2->data->ls_seqnum);
! 3163: if (x > y)
! 3164: return 1;
! 3165: if (x < y)
! 3166: return -1;
! 3167:
! 3168: /* compare LS checksum. */
! 3169: r = ntohs (l1->data->checksum) - ntohs (l2->data->checksum);
! 3170: if (r)
! 3171: return r;
! 3172:
! 3173: /* compare LS age. */
! 3174: if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
! 3175: return 1;
! 3176: else if (!IS_LSA_MAXAGE (l1) && IS_LSA_MAXAGE (l2))
! 3177: return -1;
! 3178:
! 3179: /* compare LS age with MaxAgeDiff. */
! 3180: if (LS_AGE (l1) - LS_AGE (l2) > OSPF_LSA_MAXAGE_DIFF)
! 3181: return -1;
! 3182: else if (LS_AGE (l2) - LS_AGE (l1) > OSPF_LSA_MAXAGE_DIFF)
! 3183: return 1;
! 3184:
! 3185: /* LSAs are identical. */
! 3186: return 0;
! 3187: }
! 3188:
! 3189: /* If two LSAs are different, return 1, otherwise return 0. */
! 3190: int
! 3191: ospf_lsa_different (struct ospf_lsa *l1, struct ospf_lsa *l2)
! 3192: {
! 3193: char *p1, *p2;
! 3194: assert (l1);
! 3195: assert (l2);
! 3196: assert (l1->data);
! 3197: assert (l2->data);
! 3198:
! 3199: if (l1->data->options != l2->data->options)
! 3200: return 1;
! 3201:
! 3202: if (IS_LSA_MAXAGE (l1) && !IS_LSA_MAXAGE (l2))
! 3203: return 1;
! 3204:
! 3205: if (IS_LSA_MAXAGE (l2) && !IS_LSA_MAXAGE (l1))
! 3206: return 1;
! 3207:
! 3208: if (l1->data->length != l2->data->length)
! 3209: return 1;
! 3210:
! 3211: if (l1->data->length == 0)
! 3212: return 1;
! 3213:
! 3214: if (CHECK_FLAG ((l1->flags ^ l2->flags), OSPF_LSA_RECEIVED))
! 3215: return 1; /* May be a stale LSA in the LSBD */
! 3216:
! 3217: assert ( ntohs(l1->data->length) > OSPF_LSA_HEADER_SIZE);
! 3218:
! 3219: p1 = (char *) l1->data;
! 3220: p2 = (char *) l2->data;
! 3221:
! 3222: if (memcmp (p1 + OSPF_LSA_HEADER_SIZE, p2 + OSPF_LSA_HEADER_SIZE,
! 3223: ntohs( l1->data->length ) - OSPF_LSA_HEADER_SIZE) != 0)
! 3224: return 1;
! 3225:
! 3226: return 0;
! 3227: }
! 3228:
! 3229: #ifdef ORIGINAL_CODING
! 3230: void
! 3231: ospf_lsa_flush_self_originated (struct ospf_neighbor *nbr,
! 3232: struct ospf_lsa *self,
! 3233: struct ospf_lsa *new)
! 3234: {
! 3235: u_int32_t seqnum;
! 3236:
! 3237: /* Adjust LS Sequence Number. */
! 3238: seqnum = ntohl (new->data->ls_seqnum) + 1;
! 3239: self->data->ls_seqnum = htonl (seqnum);
! 3240:
! 3241: /* Recalculate LSA checksum. */
! 3242: ospf_lsa_checksum (self->data);
! 3243:
! 3244: /* Reflooding LSA. */
! 3245: /* RFC2328 Section 13.3
! 3246: On non-broadcast networks, separate Link State Update
! 3247: packets must be sent, as unicasts, to each adjacent neighbor
! 3248: (i.e., those in state Exchange or greater). The destination
! 3249: IP addresses for these packets are the neighbors' IP
! 3250: addresses. */
! 3251: if (nbr->oi->type == OSPF_IFTYPE_NBMA)
! 3252: {
! 3253: struct route_node *rn;
! 3254: struct ospf_neighbor *onbr;
! 3255:
! 3256: for (rn = route_top (nbr->oi->nbrs); rn; rn = route_next (rn))
! 3257: if ((onbr = rn->info) != NULL)
! 3258: if (onbr != nbr->oi->nbr_self && onbr->status >= NSM_Exchange)
! 3259: ospf_ls_upd_send_lsa (onbr, self, OSPF_SEND_PACKET_DIRECT);
! 3260: }
! 3261: else
! 3262: ospf_ls_upd_send_lsa (nbr, self, OSPF_SEND_PACKET_INDIRECT);
! 3263:
! 3264: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 3265: zlog_debug ("LSA[Type%d:%s]: Flush self-originated LSA",
! 3266: self->data->type, inet_ntoa (self->data->id));
! 3267: }
! 3268: #else /* ORIGINAL_CODING */
! 3269: static int
! 3270: ospf_lsa_flush_schedule (struct ospf *ospf, struct ospf_lsa *lsa)
! 3271: {
! 3272: if (lsa == NULL || !IS_LSA_SELF (lsa))
! 3273: return 0;
! 3274:
! 3275: if (IS_DEBUG_OSPF_EVENT)
! 3276: zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH", lsa->data->type, inet_ntoa (lsa->data->id));
! 3277:
! 3278: /* Force given lsa's age to MaxAge. */
! 3279: lsa->data->ls_age = htons (OSPF_LSA_MAXAGE);
! 3280:
! 3281: switch (lsa->data->type)
! 3282: {
! 3283: #ifdef HAVE_OPAQUE_LSA
! 3284: /* Opaque wants to be notified of flushes */
! 3285: case OSPF_OPAQUE_LINK_LSA:
! 3286: case OSPF_OPAQUE_AREA_LSA:
! 3287: case OSPF_OPAQUE_AS_LSA:
! 3288: ospf_opaque_lsa_refresh (lsa);
! 3289: break;
! 3290: #endif /* HAVE_OPAQUE_LSA */
! 3291: default:
! 3292: ospf_refresher_unregister_lsa (ospf, lsa);
! 3293: ospf_lsa_flush (ospf, lsa);
! 3294: break;
! 3295: }
! 3296:
! 3297: return 0;
! 3298: }
! 3299:
! 3300: void
! 3301: ospf_flush_self_originated_lsas_now (struct ospf *ospf)
! 3302: {
! 3303: struct listnode *node, *nnode;
! 3304: struct listnode *node2, *nnode2;
! 3305: struct ospf_area *area;
! 3306: struct ospf_interface *oi;
! 3307: struct ospf_lsa *lsa;
! 3308: struct route_node *rn;
! 3309: int need_to_flush_ase = 0;
! 3310:
! 3311: for (ALL_LIST_ELEMENTS (ospf->areas, node, nnode, area))
! 3312: {
! 3313: if ((lsa = area->router_lsa_self) != NULL)
! 3314: {
! 3315: if (IS_DEBUG_OSPF_EVENT)
! 3316: zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH",
! 3317: lsa->data->type, inet_ntoa (lsa->data->id));
! 3318:
! 3319: ospf_refresher_unregister_lsa (ospf, lsa);
! 3320: ospf_lsa_flush_area (lsa, area);
! 3321: ospf_lsa_unlock (&area->router_lsa_self);
! 3322: area->router_lsa_self = NULL;
! 3323: }
! 3324:
! 3325: for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi))
! 3326: {
! 3327: if ((lsa = oi->network_lsa_self) != NULL
! 3328: && oi->state == ISM_DR
! 3329: && oi->full_nbrs > 0)
! 3330: {
! 3331: if (IS_DEBUG_OSPF_EVENT)
! 3332: zlog_debug ("LSA[Type%d:%s]: Schedule self-originated LSA to FLUSH",
! 3333: lsa->data->type, inet_ntoa (lsa->data->id));
! 3334:
! 3335: ospf_refresher_unregister_lsa (ospf, oi->network_lsa_self);
! 3336: ospf_lsa_flush_area (oi->network_lsa_self, area);
! 3337: ospf_lsa_unlock (&oi->network_lsa_self);
! 3338: oi->network_lsa_self = NULL;
! 3339: }
! 3340:
! 3341: if (oi->type != OSPF_IFTYPE_VIRTUALLINK
! 3342: && area->external_routing == OSPF_AREA_DEFAULT)
! 3343: need_to_flush_ase = 1;
! 3344: }
! 3345:
! 3346: LSDB_LOOP (SUMMARY_LSDB (area), rn, lsa)
! 3347: ospf_lsa_flush_schedule (ospf, lsa);
! 3348: LSDB_LOOP (ASBR_SUMMARY_LSDB (area), rn, lsa)
! 3349: ospf_lsa_flush_schedule (ospf, lsa);
! 3350: #ifdef HAVE_OPAQUE_LSA
! 3351: LSDB_LOOP (OPAQUE_LINK_LSDB (area), rn, lsa)
! 3352: ospf_lsa_flush_schedule (ospf, lsa);
! 3353: LSDB_LOOP (OPAQUE_AREA_LSDB (area), rn, lsa)
! 3354: ospf_lsa_flush_schedule (ospf, lsa);
! 3355: #endif /* HAVE_OPAQUE_LSA */
! 3356: }
! 3357:
! 3358: if (need_to_flush_ase)
! 3359: {
! 3360: LSDB_LOOP (EXTERNAL_LSDB (ospf), rn, lsa)
! 3361: ospf_lsa_flush_schedule (ospf, lsa);
! 3362: #ifdef HAVE_OPAQUE_LSA
! 3363: LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)
! 3364: ospf_lsa_flush_schedule (ospf, lsa);
! 3365: #endif /* HAVE_OPAQUE_LSA */
! 3366: }
! 3367:
! 3368: /*
! 3369: * Make sure that the MaxAge LSA remover is executed immediately,
! 3370: * without conflicting to other threads.
! 3371: */
! 3372: if (ospf->t_maxage != NULL)
! 3373: {
! 3374: OSPF_TIMER_OFF (ospf->t_maxage);
! 3375: thread_execute (master, ospf_maxage_lsa_remover, ospf, 0);
! 3376: }
! 3377:
! 3378: return;
! 3379: }
! 3380: #endif /* ORIGINAL_CODING */
! 3381:
! 3382: /* If there is self-originated LSA, then return 1, otherwise return 0. */
! 3383: /* An interface-independent version of ospf_lsa_is_self_originated */
! 3384: int
! 3385: ospf_lsa_is_self_originated (struct ospf *ospf, struct ospf_lsa *lsa)
! 3386: {
! 3387: struct listnode *node;
! 3388: struct ospf_interface *oi;
! 3389:
! 3390: /* This LSA is already checked. */
! 3391: if (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED))
! 3392: return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
! 3393:
! 3394: /* Make sure LSA is self-checked. */
! 3395: SET_FLAG (lsa->flags, OSPF_LSA_SELF_CHECKED);
! 3396:
! 3397: /* AdvRouter and Router ID is the same. */
! 3398: if (IPV4_ADDR_SAME (&lsa->data->adv_router, &ospf->router_id))
! 3399: SET_FLAG (lsa->flags, OSPF_LSA_SELF);
! 3400:
! 3401: /* LSA is router-LSA. */
! 3402: else if (lsa->data->type == OSPF_ROUTER_LSA &&
! 3403: IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id))
! 3404: SET_FLAG (lsa->flags, OSPF_LSA_SELF);
! 3405:
! 3406: /* LSA is network-LSA. Compare Link ID with all interfaces. */
! 3407: else if (lsa->data->type == OSPF_NETWORK_LSA)
! 3408: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
! 3409: {
! 3410: /* Ignore virtual link. */
! 3411: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
! 3412: if (oi->address->family == AF_INET)
! 3413: if (IPV4_ADDR_SAME (&lsa->data->id, &oi->address->u.prefix4))
! 3414: {
! 3415: /* to make it easier later */
! 3416: SET_FLAG (lsa->flags, OSPF_LSA_SELF);
! 3417: return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
! 3418: }
! 3419: }
! 3420:
! 3421: return CHECK_FLAG (lsa->flags, OSPF_LSA_SELF);
! 3422: }
! 3423:
! 3424: /* Get unique Link State ID. */
! 3425: struct in_addr
! 3426: ospf_lsa_unique_id (struct ospf *ospf,
! 3427: struct ospf_lsdb *lsdb, u_char type, struct prefix_ipv4 *p)
! 3428: {
! 3429: struct ospf_lsa *lsa;
! 3430: struct in_addr mask, id;
! 3431:
! 3432: id = p->prefix;
! 3433:
! 3434: /* Check existence of LSA instance. */
! 3435: lsa = ospf_lsdb_lookup_by_id (lsdb, type, id, ospf->router_id);
! 3436: if (lsa)
! 3437: {
! 3438: struct as_external_lsa *al = (struct as_external_lsa *) lsa->data;
! 3439: if (ip_masklen (al->mask) == p->prefixlen)
! 3440: {
! 3441: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 3442: zlog_debug ("ospf_lsa_unique_id(): "
! 3443: "Can't get Link State ID for %s/%d",
! 3444: inet_ntoa (p->prefix), p->prefixlen);
! 3445: /* id.s_addr = 0; */
! 3446: id.s_addr = 0xffffffff;
! 3447: return id;
! 3448: }
! 3449: /* Masklen differs, then apply wildcard mask to Link State ID. */
! 3450: else
! 3451: {
! 3452: masklen2ip (p->prefixlen, &mask);
! 3453:
! 3454: id.s_addr = p->prefix.s_addr | (~mask.s_addr);
! 3455: lsa = ospf_lsdb_lookup_by_id (ospf->lsdb, type,
! 3456: id, ospf->router_id);
! 3457: if (lsa)
! 3458: {
! 3459: if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
! 3460: zlog_debug ("ospf_lsa_unique_id(): "
! 3461: "Can't get Link State ID for %s/%d",
! 3462: inet_ntoa (p->prefix), p->prefixlen);
! 3463: /* id.s_addr = 0; */
! 3464: id.s_addr = 0xffffffff;
! 3465: return id;
! 3466: }
! 3467: }
! 3468: }
! 3469:
! 3470: return id;
! 3471: }
! 3472:
! 3473:
! 3474: #define LSA_ACTION_FLOOD_AREA 1
! 3475: #define LSA_ACTION_FLUSH_AREA 2
! 3476:
! 3477: struct lsa_action
! 3478: {
! 3479: u_char action;
! 3480: struct ospf_area *area;
! 3481: struct ospf_lsa *lsa;
! 3482: };
! 3483:
! 3484: static int
! 3485: ospf_lsa_action (struct thread *t)
! 3486: {
! 3487: struct lsa_action *data;
! 3488:
! 3489: data = THREAD_ARG (t);
! 3490:
! 3491: if (IS_DEBUG_OSPF (lsa, LSA) == OSPF_DEBUG_LSA)
! 3492: zlog_debug ("LSA[Action]: Performing scheduled LSA action: %d",
! 3493: data->action);
! 3494:
! 3495: switch (data->action)
! 3496: {
! 3497: case LSA_ACTION_FLOOD_AREA:
! 3498: ospf_flood_through_area (data->area, NULL, data->lsa);
! 3499: break;
! 3500: case LSA_ACTION_FLUSH_AREA:
! 3501: ospf_lsa_flush_area (data->lsa, data->area);
! 3502: break;
! 3503: }
! 3504:
! 3505: ospf_lsa_unlock (&data->lsa); /* Message */
! 3506: XFREE (MTYPE_OSPF_MESSAGE, data);
! 3507: return 0;
! 3508: }
! 3509:
! 3510: void
! 3511: ospf_schedule_lsa_flood_area (struct ospf_area *area, struct ospf_lsa *lsa)
! 3512: {
! 3513: struct lsa_action *data;
! 3514:
! 3515: data = XCALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
! 3516: data->action = LSA_ACTION_FLOOD_AREA;
! 3517: data->area = area;
! 3518: data->lsa = ospf_lsa_lock (lsa); /* Message / Flood area */
! 3519:
! 3520: thread_add_event (master, ospf_lsa_action, data, 0);
! 3521: }
! 3522:
! 3523: void
! 3524: ospf_schedule_lsa_flush_area (struct ospf_area *area, struct ospf_lsa *lsa)
! 3525: {
! 3526: struct lsa_action *data;
! 3527:
! 3528: data = XCALLOC (MTYPE_OSPF_MESSAGE, sizeof (struct lsa_action));
! 3529: data->action = LSA_ACTION_FLUSH_AREA;
! 3530: data->area = area;
! 3531: data->lsa = ospf_lsa_lock (lsa); /* Message / Flush area */
! 3532:
! 3533: thread_add_event (master, ospf_lsa_action, data, 0);
! 3534: }
! 3535:
! 3536:
! 3537: /* LSA Refreshment functions. */
! 3538: struct ospf_lsa *
! 3539: ospf_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa)
! 3540: {
! 3541: struct external_info *ei;
! 3542: struct ospf_lsa *new = NULL;
! 3543: assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
! 3544: assert (lsa->lock > 0);
! 3545:
! 3546: switch (lsa->data->type)
! 3547: {
! 3548: /* Router and Network LSAs are processed differently. */
! 3549: case OSPF_ROUTER_LSA:
! 3550: new = ospf_router_lsa_refresh (lsa);
! 3551: break;
! 3552: case OSPF_NETWORK_LSA:
! 3553: new = ospf_network_lsa_refresh (lsa);
! 3554: break;
! 3555: case OSPF_SUMMARY_LSA:
! 3556: new = ospf_summary_lsa_refresh (ospf, lsa);
! 3557: break;
! 3558: case OSPF_ASBR_SUMMARY_LSA:
! 3559: new = ospf_summary_asbr_lsa_refresh (ospf, lsa);
! 3560: break;
! 3561: case OSPF_AS_EXTERNAL_LSA:
! 3562: /* Translated from NSSA Type-5s are refreshed when
! 3563: * from refresh of Type-7 - do not refresh these directly.
! 3564: */
! 3565: if (CHECK_FLAG (lsa->flags, OSPF_LSA_LOCAL_XLT))
! 3566: break;
! 3567: ei = ospf_external_info_check (lsa);
! 3568: if (ei)
! 3569: new = ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE);
! 3570: else
! 3571: ospf_lsa_flush_as (ospf, lsa);
! 3572: break;
! 3573: #ifdef HAVE_OPAQUE_LSA
! 3574: case OSPF_OPAQUE_LINK_LSA:
! 3575: case OSPF_OPAQUE_AREA_LSA:
! 3576: case OSPF_OPAQUE_AS_LSA:
! 3577: new = ospf_opaque_lsa_refresh (lsa);
! 3578: break;
! 3579: #endif /* HAVE_OPAQUE_LSA */
! 3580: default:
! 3581: break;
! 3582: }
! 3583: return new;
! 3584: }
! 3585:
! 3586: void
! 3587: ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
! 3588: {
! 3589: u_int16_t index, current_index;
! 3590:
! 3591: assert (lsa->lock > 0);
! 3592: assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
! 3593:
! 3594: if (lsa->refresh_list < 0)
! 3595: {
! 3596: int delay;
! 3597:
! 3598: if (LS_AGE (lsa) == 0 &&
! 3599: ntohl (lsa->data->ls_seqnum) == OSPF_INITIAL_SEQUENCE_NUMBER)
! 3600: /* Randomize first update by OSPF_LS_REFRESH_SHIFT factor */
! 3601: delay = OSPF_LS_REFRESH_SHIFT + (random () % OSPF_LS_REFRESH_TIME);
! 3602: else
! 3603: /* Randomize another updates by +-OSPF_LS_REFRESH_JITTER factor */
! 3604: delay = OSPF_LS_REFRESH_TIME - LS_AGE (lsa) - OSPF_LS_REFRESH_JITTER
! 3605: + (random () % (2*OSPF_LS_REFRESH_JITTER));
! 3606:
! 3607: if (delay < 0)
! 3608: delay = 0;
! 3609:
! 3610: current_index = ospf->lsa_refresh_queue.index + (quagga_time (NULL)
! 3611: - ospf->lsa_refresher_started)/OSPF_LSA_REFRESHER_GRANULARITY;
! 3612:
! 3613: index = (current_index + delay/OSPF_LSA_REFRESHER_GRANULARITY)
! 3614: % (OSPF_LSA_REFRESHER_SLOTS);
! 3615:
! 3616: if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
! 3617: zlog_debug ("LSA[Refresh]: lsa %s with age %d added to index %d",
! 3618: inet_ntoa (lsa->data->id), LS_AGE (lsa), index);
! 3619: if (!ospf->lsa_refresh_queue.qs[index])
! 3620: ospf->lsa_refresh_queue.qs[index] = list_new ();
! 3621: listnode_add (ospf->lsa_refresh_queue.qs[index],
! 3622: ospf_lsa_lock (lsa)); /* lsa_refresh_queue */
! 3623: lsa->refresh_list = index;
! 3624: if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
! 3625: zlog_debug ("LSA[Refresh:%s]: ospf_refresher_register_lsa(): "
! 3626: "setting refresh_list on lsa %p (slod %d)",
! 3627: inet_ntoa (lsa->data->id), lsa, index);
! 3628: }
! 3629: }
! 3630:
! 3631: void
! 3632: ospf_refresher_unregister_lsa (struct ospf *ospf, struct ospf_lsa *lsa)
! 3633: {
! 3634: assert (lsa->lock > 0);
! 3635: assert (CHECK_FLAG (lsa->flags, OSPF_LSA_SELF));
! 3636: if (lsa->refresh_list >= 0)
! 3637: {
! 3638: struct list *refresh_list = ospf->lsa_refresh_queue.qs[lsa->refresh_list];
! 3639: listnode_delete (refresh_list, lsa);
! 3640: if (!listcount (refresh_list))
! 3641: {
! 3642: list_free (refresh_list);
! 3643: ospf->lsa_refresh_queue.qs[lsa->refresh_list] = NULL;
! 3644: }
! 3645: ospf_lsa_unlock (&lsa); /* lsa_refresh_queue */
! 3646: lsa->refresh_list = -1;
! 3647: }
! 3648: }
! 3649:
! 3650: int
! 3651: ospf_lsa_refresh_walker (struct thread *t)
! 3652: {
! 3653: struct list *refresh_list;
! 3654: struct listnode *node, *nnode;
! 3655: struct ospf *ospf = THREAD_ARG (t);
! 3656: struct ospf_lsa *lsa;
! 3657: int i;
! 3658: struct list *lsa_to_refresh = list_new ();
! 3659:
! 3660: if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
! 3661: zlog_debug ("LSA[Refresh]:ospf_lsa_refresh_walker(): start");
! 3662:
! 3663:
! 3664: i = ospf->lsa_refresh_queue.index;
! 3665:
! 3666: /* Note: if clock has jumped backwards, then time change could be negative,
! 3667: so we are careful to cast the expression to unsigned before taking
! 3668: modulus. */
! 3669: ospf->lsa_refresh_queue.index =
! 3670: ((unsigned long)(ospf->lsa_refresh_queue.index +
! 3671: (quagga_time (NULL) - ospf->lsa_refresher_started)
! 3672: / OSPF_LSA_REFRESHER_GRANULARITY))
! 3673: % OSPF_LSA_REFRESHER_SLOTS;
! 3674:
! 3675: if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
! 3676: zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d",
! 3677: ospf->lsa_refresh_queue.index);
! 3678:
! 3679: for (;i != ospf->lsa_refresh_queue.index;
! 3680: i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS)
! 3681: {
! 3682: if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
! 3683: zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): "
! 3684: "refresh index %d", i);
! 3685:
! 3686: refresh_list = ospf->lsa_refresh_queue.qs [i];
! 3687:
! 3688: assert (i >= 0);
! 3689:
! 3690: ospf->lsa_refresh_queue.qs [i] = NULL;
! 3691:
! 3692: if (refresh_list)
! 3693: {
! 3694: for (ALL_LIST_ELEMENTS (refresh_list, node, nnode, lsa))
! 3695: {
! 3696: if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
! 3697: zlog_debug ("LSA[Refresh:%s]: ospf_lsa_refresh_walker(): "
! 3698: "refresh lsa %p (slot %d)",
! 3699: inet_ntoa (lsa->data->id), lsa, i);
! 3700:
! 3701: assert (lsa->lock > 0);
! 3702: list_delete_node (refresh_list, node);
! 3703: lsa->refresh_list = -1;
! 3704: listnode_add (lsa_to_refresh, lsa);
! 3705: }
! 3706: list_free (refresh_list);
! 3707: }
! 3708: }
! 3709:
! 3710: ospf->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
! 3711: ospf, ospf->lsa_refresh_interval);
! 3712: ospf->lsa_refresher_started = quagga_time (NULL);
! 3713:
! 3714: for (ALL_LIST_ELEMENTS (lsa_to_refresh, node, nnode, lsa))
! 3715: {
! 3716: ospf_lsa_refresh (ospf, lsa);
! 3717: assert (lsa->lock > 0);
! 3718: ospf_lsa_unlock (&lsa); /* lsa_refresh_queue & temp for lsa_to_refresh*/
! 3719: }
! 3720:
! 3721: list_delete (lsa_to_refresh);
! 3722:
! 3723: if (IS_DEBUG_OSPF (lsa, LSA_REFRESH))
! 3724: zlog_debug ("LSA[Refresh]: ospf_lsa_refresh_walker(): end");
! 3725:
! 3726: return 0;
! 3727: }
! 3728:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>