Annotation of embedaddon/quagga/ospf6d/ospf6_abr.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Area Border Router function.
! 3: * Copyright (C) 2004 Yasuhiro Ohara
! 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
! 19: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
! 20: * Boston, MA 02111-1307, USA.
! 21: */
! 22:
! 23: #include <zebra.h>
! 24:
! 25: #include "log.h"
! 26: #include "prefix.h"
! 27: #include "table.h"
! 28: #include "vty.h"
! 29: #include "linklist.h"
! 30: #include "command.h"
! 31: #include "thread.h"
! 32: #include "plist.h"
! 33: #include "filter.h"
! 34:
! 35: #include "ospf6_proto.h"
! 36: #include "ospf6_route.h"
! 37: #include "ospf6_lsa.h"
! 38: #include "ospf6_route.h"
! 39: #include "ospf6_lsdb.h"
! 40: #include "ospf6_message.h"
! 41:
! 42: #include "ospf6_top.h"
! 43: #include "ospf6_area.h"
! 44: #include "ospf6_interface.h"
! 45: #include "ospf6_neighbor.h"
! 46:
! 47: #include "ospf6_flood.h"
! 48: #include "ospf6_intra.h"
! 49: #include "ospf6_abr.h"
! 50: #include "ospf6d.h"
! 51:
! 52: unsigned char conf_debug_ospf6_abr;
! 53:
! 54: int
! 55: ospf6_is_router_abr (struct ospf6 *o)
! 56: {
! 57: struct listnode *node;
! 58: struct ospf6_area *oa;
! 59: int area_count = 0;
! 60:
! 61: for (ALL_LIST_ELEMENTS_RO (o->area_list, node, oa))
! 62: if (IS_AREA_ENABLED (oa))
! 63: area_count++;
! 64:
! 65: if (area_count > 1)
! 66: return 1;
! 67: return 0;
! 68: }
! 69:
! 70: void
! 71: ospf6_abr_enable_area (struct ospf6_area *area)
! 72: {
! 73: struct ospf6_area *oa;
! 74: struct ospf6_route *ro;
! 75: struct listnode *node, *nnode;
! 76:
! 77: for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
! 78: {
! 79: /* update B bit for each area */
! 80: OSPF6_ROUTER_LSA_SCHEDULE (oa);
! 81:
! 82: /* install other area's configured address range */
! 83: if (oa != area)
! 84: {
! 85: for (ro = ospf6_route_head (oa->range_table); ro;
! 86: ro = ospf6_route_next (ro))
! 87: {
! 88: if (CHECK_FLAG (ro->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
! 89: ospf6_abr_originate_summary_to_area (ro, area);
! 90: }
! 91: }
! 92: }
! 93:
! 94: /* install calculated routes to border routers */
! 95: for (ro = ospf6_route_head (area->ospf6->brouter_table); ro;
! 96: ro = ospf6_route_next (ro))
! 97: ospf6_abr_originate_summary_to_area (ro, area);
! 98:
! 99: /* install calculated routes to network (may be rejected by ranges) */
! 100: for (ro = ospf6_route_head (area->ospf6->route_table); ro;
! 101: ro = ospf6_route_next (ro))
! 102: ospf6_abr_originate_summary_to_area (ro, area);
! 103: }
! 104:
! 105: void
! 106: ospf6_abr_disable_area (struct ospf6_area *area)
! 107: {
! 108: struct ospf6_area *oa;
! 109: struct ospf6_route *ro;
! 110: struct ospf6_lsa *old;
! 111: struct listnode *node, *nnode;
! 112:
! 113: /* Withdraw all summary prefixes previously originated */
! 114: for (ro = ospf6_route_head (area->summary_prefix); ro;
! 115: ro = ospf6_route_next (ro))
! 116: {
! 117: old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
! 118: area->ospf6->router_id, area->lsdb);
! 119: if (old)
! 120: ospf6_lsa_purge (old);
! 121: ospf6_route_remove (ro, area->summary_prefix);
! 122: }
! 123:
! 124: /* Withdraw all summary router-routes previously originated */
! 125: for (ro = ospf6_route_head (area->summary_router); ro;
! 126: ro = ospf6_route_next (ro))
! 127: {
! 128: old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
! 129: area->ospf6->router_id, area->lsdb);
! 130: if (old)
! 131: ospf6_lsa_purge (old);
! 132: ospf6_route_remove (ro, area->summary_router);
! 133: }
! 134:
! 135: /* Schedule Router-LSA for each area (ABR status may change) */
! 136: for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
! 137: /* update B bit for each area */
! 138: OSPF6_ROUTER_LSA_SCHEDULE (oa);
! 139: }
! 140:
! 141: /* RFC 2328 12.4.3. Summary-LSAs */
! 142: void
! 143: ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
! 144: struct ospf6_area *area)
! 145: {
! 146: struct ospf6_lsa *lsa, *old = NULL;
! 147: struct ospf6_interface *oi;
! 148: struct ospf6_route *summary, *range = NULL;
! 149: struct ospf6_area *route_area;
! 150: char buffer[OSPF6_MAX_LSASIZE];
! 151: struct ospf6_lsa_header *lsa_header;
! 152: caddr_t p;
! 153: struct ospf6_inter_prefix_lsa *prefix_lsa;
! 154: struct ospf6_inter_router_lsa *router_lsa;
! 155: struct ospf6_route_table *summary_table = NULL;
! 156: u_int16_t type;
! 157: char buf[64];
! 158: int is_debug = 0;
! 159:
! 160: if (route->type == OSPF6_DEST_TYPE_ROUTER)
! 161: {
! 162: if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER))
! 163: {
! 164: is_debug++;
! 165: inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
! 166: buf, sizeof (buf));
! 167: zlog_debug ("Originating summary in area %s for ASBR %s",
! 168: area->name, buf);
! 169: }
! 170: summary_table = area->summary_router;
! 171: }
! 172: else
! 173: {
! 174: if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX))
! 175: {
! 176: is_debug++;
! 177: prefix2str (&route->prefix, buf, sizeof (buf));
! 178: zlog_debug ("Originating summary in area %s for %s",
! 179: area->name, buf);
! 180: }
! 181: summary_table = area->summary_prefix;
! 182: }
! 183:
! 184: summary = ospf6_route_lookup (&route->prefix, summary_table);
! 185: if (summary)
! 186: old = ospf6_lsdb_lookup (summary->path.origin.type,
! 187: summary->path.origin.id,
! 188: area->ospf6->router_id, area->lsdb);
! 189:
! 190: /* if this route has just removed, remove corresponding LSA */
! 191: if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
! 192: {
! 193: if (is_debug)
! 194: zlog_debug ("The route has just removed, purge previous LSA");
! 195: if (summary)
! 196: ospf6_route_remove (summary, summary_table);
! 197: if (old)
! 198: ospf6_lsa_purge (old);
! 199: return;
! 200: }
! 201:
! 202: /* Only destination type network, range or ASBR are considered */
! 203: if (route->type != OSPF6_DEST_TYPE_NETWORK &&
! 204: route->type != OSPF6_DEST_TYPE_RANGE &&
! 205: (route->type != OSPF6_DEST_TYPE_ROUTER ||
! 206: ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E)))
! 207: {
! 208: if (is_debug)
! 209: zlog_debug ("Route type is none of network, range nor ASBR, withdraw");
! 210: if (summary)
! 211: ospf6_route_remove (summary, summary_table);
! 212: if (old)
! 213: ospf6_lsa_purge (old);
! 214: return;
! 215: }
! 216:
! 217: /* AS External routes are never considered */
! 218: if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
! 219: route->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
! 220: {
! 221: if (is_debug)
! 222: zlog_debug ("Path type is external, withdraw");
! 223: if (summary)
! 224: ospf6_route_remove (summary, summary_table);
! 225: if (old)
! 226: ospf6_lsa_purge (old);
! 227: return;
! 228: }
! 229:
! 230: /* do not generate if the path's area is the same as target area */
! 231: if (route->path.area_id == area->area_id)
! 232: {
! 233: if (is_debug)
! 234: zlog_debug ("The route is in the area itself, ignore");
! 235: if (summary)
! 236: ospf6_route_remove (summary, summary_table);
! 237: if (old)
! 238: ospf6_lsa_purge (old);
! 239: return;
! 240: }
! 241:
! 242: /* do not generate if the nexthops belongs to the target area */
! 243: oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex);
! 244: if (oi && oi->area && oi->area == area)
! 245: {
! 246: if (is_debug)
! 247: zlog_debug ("The route's nexthop is in the same area, ignore");
! 248: if (summary)
! 249: ospf6_route_remove (summary, summary_table);
! 250: if (old)
! 251: ospf6_lsa_purge (old);
! 252: return;
! 253: }
! 254:
! 255: /* do not generate if the route cost is greater or equal to LSInfinity */
! 256: if (route->path.cost >= LS_INFINITY)
! 257: {
! 258: if (is_debug)
! 259: zlog_debug ("The cost exceeds LSInfinity, withdraw");
! 260: if (summary)
! 261: ospf6_route_remove (summary, summary_table);
! 262: if (old)
! 263: ospf6_lsa_purge (old);
! 264: return;
! 265: }
! 266:
! 267: /* if this is a route to ASBR */
! 268: if (route->type == OSPF6_DEST_TYPE_ROUTER)
! 269: {
! 270: /* Only the prefered best path is considered */
! 271: if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST))
! 272: {
! 273: if (is_debug)
! 274: zlog_debug ("This is the secondary path to the ASBR, ignore");
! 275: if (summary)
! 276: ospf6_route_remove (summary, summary_table);
! 277: if (old)
! 278: ospf6_lsa_purge (old);
! 279: return;
! 280: }
! 281:
! 282: /* Do not generate if the area is stub */
! 283: /* XXX */
! 284: }
! 285:
! 286: /* if this is an intra-area route, this may be suppressed by aggregation */
! 287: if (route->type == OSPF6_DEST_TYPE_NETWORK &&
! 288: route->path.type == OSPF6_PATH_TYPE_INTRA)
! 289: {
! 290: /* search for configured address range for the route's area */
! 291: route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
! 292: assert (route_area);
! 293: range = ospf6_route_lookup_bestmatch (&route->prefix,
! 294: route_area->range_table);
! 295:
! 296: /* ranges are ignored when originate backbone routes to transit area.
! 297: Otherwise, if ranges are configured, the route is suppressed. */
! 298: if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
! 299: (route->path.area_id != BACKBONE_AREA_ID ||
! 300: ! IS_AREA_TRANSIT (area)))
! 301: {
! 302: if (is_debug)
! 303: {
! 304: prefix2str (&range->prefix, buf, sizeof (buf));
! 305: zlog_debug ("Suppressed by range %s of area %s",
! 306: buf, route_area->name);
! 307: }
! 308:
! 309: if (summary)
! 310: ospf6_route_remove (summary, summary_table);
! 311: if (old)
! 312: ospf6_lsa_purge (old);
! 313: return;
! 314: }
! 315: }
! 316:
! 317: /* If this is a configured address range */
! 318: if (route->type == OSPF6_DEST_TYPE_RANGE)
! 319: {
! 320: /* If DoNotAdvertise is set */
! 321: if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
! 322: {
! 323: if (is_debug)
! 324: zlog_debug ("This is the range with DoNotAdvertise set. ignore");
! 325: if (summary)
! 326: ospf6_route_remove (summary, summary_table);
! 327: if (old)
! 328: ospf6_lsa_purge (old);
! 329: return;
! 330: }
! 331:
! 332: /* Whether the route have active longer prefix */
! 333: if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
! 334: {
! 335: if (is_debug)
! 336: zlog_debug ("The range is not active. withdraw");
! 337: if (summary)
! 338: ospf6_route_remove (summary, summary_table);
! 339: if (old)
! 340: ospf6_lsa_purge (old);
! 341: return;
! 342: }
! 343: }
! 344:
! 345: /* Check export list */
! 346: if (EXPORT_NAME (area))
! 347: {
! 348: if (EXPORT_LIST (area) == NULL)
! 349: EXPORT_LIST (area) =
! 350: access_list_lookup (AFI_IP6, EXPORT_NAME (area));
! 351:
! 352: if (EXPORT_LIST (area))
! 353: if (access_list_apply (EXPORT_LIST (area),
! 354: &route->prefix) == FILTER_DENY)
! 355: {
! 356: if (is_debug)
! 357: {
! 358: inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
! 359: buf, sizeof(buf));
! 360: zlog_debug ("prefix %s was denied by export list", buf);
! 361: }
! 362: return;
! 363: }
! 364: }
! 365:
! 366: /* Check filter-list */
! 367: if (PREFIX_NAME_OUT (area))
! 368: {
! 369: if (PREFIX_LIST_OUT (area) == NULL)
! 370: PREFIX_LIST_OUT (area) =
! 371: prefix_list_lookup(AFI_IP6, PREFIX_NAME_OUT (area));
! 372:
! 373: if (PREFIX_LIST_OUT (area))
! 374: if (prefix_list_apply (PREFIX_LIST_OUT (area),
! 375: &route->prefix) != PREFIX_PERMIT)
! 376: {
! 377: if (is_debug)
! 378: {
! 379: inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
! 380: buf, sizeof (buf));
! 381: zlog_debug ("prefix %s was denied by filter-list out", buf);
! 382: }
! 383: return;
! 384: }
! 385: }
! 386:
! 387: /* the route is going to be originated. store it in area's summary_table */
! 388: if (summary == NULL)
! 389: {
! 390: summary = ospf6_route_copy (route);
! 391: if (route->type == OSPF6_DEST_TYPE_NETWORK ||
! 392: route->type == OSPF6_DEST_TYPE_RANGE)
! 393: summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
! 394: else
! 395: summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER);
! 396: summary->path.origin.adv_router = area->ospf6->router_id;
! 397: summary->path.origin.id =
! 398: ospf6_new_ls_id (summary->path.origin.type,
! 399: summary->path.origin.adv_router, area->lsdb);
! 400: summary = ospf6_route_add (summary, summary_table);
! 401: }
! 402: else
! 403: {
! 404: summary->type = route->type;
! 405: quagga_gettime (QUAGGA_CLK_MONOTONIC, &summary->changed);
! 406: }
! 407:
! 408: summary->path.router_bits = route->path.router_bits;
! 409: summary->path.options[0] = route->path.options[0];
! 410: summary->path.options[1] = route->path.options[1];
! 411: summary->path.options[2] = route->path.options[2];
! 412: summary->path.prefix_options = route->path.prefix_options;
! 413: summary->path.area_id = area->area_id;
! 414: summary->path.type = OSPF6_PATH_TYPE_INTER;
! 415: summary->path.cost = route->path.cost;
! 416: summary->nexthop[0] = route->nexthop[0];
! 417:
! 418: /* prepare buffer */
! 419: memset (buffer, 0, sizeof (buffer));
! 420: lsa_header = (struct ospf6_lsa_header *) buffer;
! 421:
! 422: if (route->type == OSPF6_DEST_TYPE_ROUTER)
! 423: {
! 424: router_lsa = (struct ospf6_inter_router_lsa *)
! 425: ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
! 426: p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa);
! 427:
! 428: /* Fill Inter-Area-Router-LSA */
! 429: router_lsa->options[0] = route->path.options[0];
! 430: router_lsa->options[1] = route->path.options[1];
! 431: router_lsa->options[2] = route->path.options[2];
! 432: OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
! 433: router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix);
! 434: type = htons (OSPF6_LSTYPE_INTER_ROUTER);
! 435: }
! 436: else
! 437: {
! 438: prefix_lsa = (struct ospf6_inter_prefix_lsa *)
! 439: ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
! 440: p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
! 441:
! 442: /* Fill Inter-Area-Prefix-LSA */
! 443: OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
! 444: prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
! 445: prefix_lsa->prefix.prefix_options = route->path.prefix_options;
! 446:
! 447: /* set Prefix */
! 448: memcpy (p, &route->prefix.u.prefix6,
! 449: OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
! 450: ospf6_prefix_apply_mask (&prefix_lsa->prefix);
! 451: p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
! 452: type = htons (OSPF6_LSTYPE_INTER_PREFIX);
! 453: }
! 454:
! 455: /* Fill LSA Header */
! 456: lsa_header->age = 0;
! 457: lsa_header->type = type;
! 458: lsa_header->id = summary->path.origin.id;
! 459: lsa_header->adv_router = area->ospf6->router_id;
! 460: lsa_header->seqnum =
! 461: ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
! 462: lsa_header->adv_router, area->lsdb);
! 463: lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
! 464:
! 465: /* LSA checksum */
! 466: ospf6_lsa_checksum (lsa_header);
! 467:
! 468: /* create LSA */
! 469: lsa = ospf6_lsa_create (lsa_header);
! 470:
! 471: /* Originate */
! 472: ospf6_lsa_originate_area (lsa, area);
! 473: }
! 474:
! 475: static void
! 476: ospf6_abr_range_update (struct ospf6_route *range)
! 477: {
! 478: u_int32_t cost = 0;
! 479: struct ospf6_route *ro;
! 480:
! 481: assert (range->type == OSPF6_DEST_TYPE_RANGE);
! 482:
! 483: /* update range's cost and active flag */
! 484: for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table);
! 485: ro; ro = ospf6_route_match_next (&range->prefix, ro))
! 486: {
! 487: if (ro->path.area_id == range->path.area_id &&
! 488: ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
! 489: cost = MAX (cost, ro->path.cost);
! 490: }
! 491:
! 492: if (range->path.cost != cost)
! 493: {
! 494: range->path.cost = cost;
! 495:
! 496: if (range->path.cost)
! 497: SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
! 498: else
! 499: UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
! 500:
! 501: ospf6_abr_originate_summary (range);
! 502: }
! 503: }
! 504:
! 505: void
! 506: ospf6_abr_originate_summary (struct ospf6_route *route)
! 507: {
! 508: struct listnode *node, *nnode;
! 509: struct ospf6_area *oa;
! 510: struct ospf6_route *range = NULL;
! 511:
! 512: if (route->type == OSPF6_DEST_TYPE_NETWORK)
! 513: {
! 514: oa = ospf6_area_lookup (route->path.area_id, ospf6);
! 515: range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table);
! 516: if (range)
! 517: ospf6_abr_range_update (range);
! 518: }
! 519:
! 520: for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
! 521: ospf6_abr_originate_summary_to_area (route, oa);
! 522: }
! 523:
! 524: /* RFC 2328 16.2. Calculating the inter-area routes */
! 525: void
! 526: ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
! 527: {
! 528: struct prefix prefix, abr_prefix;
! 529: struct ospf6_route_table *table = NULL;
! 530: struct ospf6_route *range, *route, *old = NULL;
! 531: struct ospf6_route *abr_entry;
! 532: u_char type = 0;
! 533: char options[3] = {0, 0, 0};
! 534: u_int8_t prefix_options = 0;
! 535: u_int32_t cost = 0;
! 536: u_char router_bits = 0;
! 537: int i;
! 538: char buf[64];
! 539: int is_debug = 0;
! 540:
! 541: memset (&prefix, 0, sizeof (prefix));
! 542:
! 543: if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
! 544: {
! 545: struct ospf6_inter_prefix_lsa *prefix_lsa;
! 546:
! 547: if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
! 548: {
! 549: is_debug++;
! 550: zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
! 551: }
! 552:
! 553: prefix_lsa = (struct ospf6_inter_prefix_lsa *)
! 554: OSPF6_LSA_HEADER_END (lsa->header);
! 555: prefix.family = AF_INET6;
! 556: prefix.prefixlen = prefix_lsa->prefix.prefix_length;
! 557: ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix);
! 558: if (is_debug)
! 559: prefix2str (&prefix, buf, sizeof (buf));
! 560: table = oa->ospf6->route_table;
! 561: type = OSPF6_DEST_TYPE_NETWORK;
! 562: prefix_options = prefix_lsa->prefix.prefix_options;
! 563: cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa);
! 564: }
! 565: else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
! 566: {
! 567: struct ospf6_inter_router_lsa *router_lsa;
! 568:
! 569: if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
! 570: {
! 571: is_debug++;
! 572: zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
! 573: }
! 574:
! 575: router_lsa = (struct ospf6_inter_router_lsa *)
! 576: OSPF6_LSA_HEADER_END (lsa->header);
! 577: ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix);
! 578: if (is_debug)
! 579: inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
! 580: table = oa->ospf6->brouter_table;
! 581: type = OSPF6_DEST_TYPE_ROUTER;
! 582: options[0] = router_lsa->options[0];
! 583: options[1] = router_lsa->options[1];
! 584: options[2] = router_lsa->options[2];
! 585: cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa);
! 586: SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E);
! 587: }
! 588: else
! 589: assert (0);
! 590:
! 591: /* Find existing route */
! 592: route = ospf6_route_lookup (&prefix, table);
! 593: if (route)
! 594: ospf6_route_lock (route);
! 595: while (route && ospf6_route_is_prefix (&prefix, route))
! 596: {
! 597: if (route->path.area_id == oa->area_id &&
! 598: route->path.origin.type == lsa->header->type &&
! 599: route->path.origin.id == lsa->header->id &&
! 600: route->path.origin.adv_router == lsa->header->adv_router &&
! 601: ! CHECK_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED))
! 602: old = route;
! 603: route = ospf6_route_next (route);
! 604: }
! 605:
! 606: /* (1) if cost == LSInfinity or if the LSA is MaxAge */
! 607: if (cost == LS_INFINITY)
! 608: {
! 609: if (is_debug)
! 610: zlog_debug ("cost is LS_INFINITY, ignore");
! 611: if (old)
! 612: ospf6_route_remove (old, table);
! 613: return;
! 614: }
! 615: if (OSPF6_LSA_IS_MAXAGE (lsa))
! 616: {
! 617: if (is_debug)
! 618: zlog_debug ("LSA is MaxAge, ignore");
! 619: if (old)
! 620: ospf6_route_remove (old, table);
! 621: return;
! 622: }
! 623:
! 624: /* (2) if the LSA is self-originated, ignore */
! 625: if (lsa->header->adv_router == oa->ospf6->router_id)
! 626: {
! 627: if (is_debug)
! 628: zlog_debug ("LSA is self-originated, ignore");
! 629: if (old)
! 630: ospf6_route_remove (old, table);
! 631: return;
! 632: }
! 633:
! 634: /* (3) if the prefix is equal to an active configured address range */
! 635: if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
! 636: {
! 637: range = ospf6_route_lookup (&prefix, oa->range_table);
! 638: if (range)
! 639: {
! 640: if (is_debug)
! 641: zlog_debug ("Prefix is equal to address range, ignore");
! 642: if (old)
! 643: ospf6_route_remove (old, table);
! 644: return;
! 645: }
! 646: }
! 647:
! 648: /* (4) if the routing table entry for the ABR does not exist */
! 649: ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
! 650: abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
! 651: if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
! 652: CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) ||
! 653: ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
! 654: {
! 655: if (is_debug)
! 656: zlog_debug ("ABR router entry does not exist, ignore");
! 657: if (old)
! 658: ospf6_route_remove (old, table);
! 659: return;
! 660: }
! 661:
! 662: /* Check import list */
! 663: if (IMPORT_NAME (oa))
! 664: {
! 665: if (IMPORT_LIST (oa) == NULL)
! 666: IMPORT_LIST (oa) = access_list_lookup (AFI_IP6, IMPORT_NAME (oa));
! 667:
! 668: if (IMPORT_LIST (oa))
! 669: if (access_list_apply (IMPORT_LIST (oa), &prefix) == FILTER_DENY)
! 670: {
! 671: if (is_debug)
! 672: zlog_debug ("Prefix was denied by import-list");
! 673: if (old)
! 674: ospf6_route_remove (old, table);
! 675: return;
! 676: }
! 677: }
! 678:
! 679: /* Check input prefix-list */
! 680: if (PREFIX_NAME_IN (oa))
! 681: {
! 682: if (PREFIX_LIST_IN (oa) == NULL)
! 683: PREFIX_LIST_IN (oa) = prefix_list_lookup (AFI_IP6, PREFIX_NAME_IN (oa));
! 684:
! 685: if (PREFIX_LIST_IN (oa))
! 686: if (prefix_list_apply (PREFIX_LIST_IN (oa), &prefix) != PREFIX_PERMIT)
! 687: {
! 688: if (is_debug)
! 689: zlog_debug ("Prefix was denied by prefix-list");
! 690: if (old)
! 691: ospf6_route_remove (old, table);
! 692: return;
! 693: }
! 694: }
! 695:
! 696: /* (5),(6),(7) the path preference is handled by the sorting
! 697: in the routing table. Always install the path by substituting
! 698: old route (if any). */
! 699: if (old)
! 700: route = ospf6_route_copy (old);
! 701: else
! 702: route = ospf6_route_create ();
! 703:
! 704: route->type = type;
! 705: route->prefix = prefix;
! 706: route->path.origin.type = lsa->header->type;
! 707: route->path.origin.id = lsa->header->id;
! 708: route->path.origin.adv_router = lsa->header->adv_router;
! 709: route->path.router_bits = router_bits;
! 710: route->path.options[0] = options[0];
! 711: route->path.options[1] = options[1];
! 712: route->path.options[2] = options[2];
! 713: route->path.prefix_options = prefix_options;
! 714: route->path.area_id = oa->area_id;
! 715: route->path.type = OSPF6_PATH_TYPE_INTER;
! 716: route->path.cost = abr_entry->path.cost + cost;
! 717: for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
! 718: route->nexthop[i] = abr_entry->nexthop[i];
! 719:
! 720: if (is_debug)
! 721: zlog_debug ("Install route: %s", buf);
! 722: ospf6_route_add (route, table);
! 723: }
! 724:
! 725: void
! 726: ospf6_abr_examin_brouter (u_int32_t router_id)
! 727: {
! 728: struct ospf6_lsa *lsa;
! 729: struct ospf6_area *oa;
! 730: struct listnode *node, *nnode;
! 731: u_int16_t type;
! 732:
! 733: for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
! 734: {
! 735: type = htons (OSPF6_LSTYPE_INTER_ROUTER);
! 736: for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa;
! 737: lsa = ospf6_lsdb_type_router_next (type, router_id, lsa))
! 738: ospf6_abr_examin_summary (lsa, oa);
! 739:
! 740: type = htons (OSPF6_LSTYPE_INTER_PREFIX);
! 741: for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa;
! 742: lsa = ospf6_lsdb_type_router_next (type, router_id, lsa))
! 743: ospf6_abr_examin_summary (lsa, oa);
! 744: }
! 745: }
! 746:
! 747: void
! 748: ospf6_abr_reimport (struct ospf6_area *oa)
! 749: {
! 750: struct ospf6_lsa *lsa;
! 751: u_int16_t type;
! 752:
! 753: type = htons (OSPF6_LSTYPE_INTER_ROUTER);
! 754: for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
! 755: lsa = ospf6_lsdb_type_next (type, lsa))
! 756: ospf6_abr_examin_summary (lsa, oa);
! 757:
! 758: type = htons (OSPF6_LSTYPE_INTER_PREFIX);
! 759: for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
! 760: lsa = ospf6_lsdb_type_next (type, lsa))
! 761: ospf6_abr_examin_summary (lsa, oa);
! 762: }
! 763:
! 764:
! 765:
! 766: /* Display functions */
! 767: static int
! 768: ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
! 769: {
! 770: struct ospf6_inter_prefix_lsa *prefix_lsa;
! 771: struct in6_addr in6;
! 772: char buf[64];
! 773:
! 774: prefix_lsa = (struct ospf6_inter_prefix_lsa *)
! 775: OSPF6_LSA_HEADER_END (lsa->header);
! 776:
! 777: vty_out (vty, " Metric: %lu%s",
! 778: (u_long) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa), VNL);
! 779:
! 780: ospf6_prefix_options_printbuf (prefix_lsa->prefix.prefix_options,
! 781: buf, sizeof (buf));
! 782: vty_out (vty, " Prefix Options: %s%s", buf, VNL);
! 783:
! 784: ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
! 785: inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
! 786: vty_out (vty, " Prefix: %s/%d%s", buf,
! 787: prefix_lsa->prefix.prefix_length, VNL);
! 788:
! 789: return 0;
! 790: }
! 791:
! 792: static int
! 793: ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
! 794: {
! 795: struct ospf6_inter_router_lsa *router_lsa;
! 796: char buf[64];
! 797:
! 798: router_lsa = (struct ospf6_inter_router_lsa *)
! 799: OSPF6_LSA_HEADER_END (lsa->header);
! 800:
! 801: ospf6_options_printbuf (router_lsa->options, buf, sizeof (buf));
! 802: vty_out (vty, " Options: %s%s", buf, VNL);
! 803: vty_out (vty, " Metric: %lu%s",
! 804: (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL);
! 805: inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
! 806: vty_out (vty, " Destination Router ID: %s%s", buf, VNL);
! 807:
! 808: return 0;
! 809: }
! 810:
! 811: /* Debug commands */
! 812: DEFUN (debug_ospf6_abr,
! 813: debug_ospf6_abr_cmd,
! 814: "debug ospf6 abr",
! 815: DEBUG_STR
! 816: OSPF6_STR
! 817: "Debug OSPFv3 ABR function\n"
! 818: )
! 819: {
! 820: OSPF6_DEBUG_ABR_ON ();
! 821: return CMD_SUCCESS;
! 822: }
! 823:
! 824: DEFUN (no_debug_ospf6_abr,
! 825: no_debug_ospf6_abr_cmd,
! 826: "no debug ospf6 abr",
! 827: NO_STR
! 828: DEBUG_STR
! 829: OSPF6_STR
! 830: "Debug OSPFv3 ABR function\n"
! 831: )
! 832: {
! 833: OSPF6_DEBUG_ABR_OFF ();
! 834: return CMD_SUCCESS;
! 835: }
! 836:
! 837: int
! 838: config_write_ospf6_debug_abr (struct vty *vty)
! 839: {
! 840: if (IS_OSPF6_DEBUG_ABR)
! 841: vty_out (vty, "debug ospf6 abr%s", VNL);
! 842: return 0;
! 843: }
! 844:
! 845: void
! 846: install_element_ospf6_debug_abr (void)
! 847: {
! 848: install_element (ENABLE_NODE, &debug_ospf6_abr_cmd);
! 849: install_element (ENABLE_NODE, &no_debug_ospf6_abr_cmd);
! 850: install_element (CONFIG_NODE, &debug_ospf6_abr_cmd);
! 851: install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd);
! 852: }
! 853:
! 854: struct ospf6_lsa_handler inter_prefix_handler =
! 855: {
! 856: OSPF6_LSTYPE_INTER_PREFIX,
! 857: "Inter-Prefix",
! 858: ospf6_inter_area_prefix_lsa_show
! 859: };
! 860:
! 861: struct ospf6_lsa_handler inter_router_handler =
! 862: {
! 863: OSPF6_LSTYPE_INTER_ROUTER,
! 864: "Inter-Router",
! 865: ospf6_inter_area_router_lsa_show
! 866: };
! 867:
! 868: void
! 869: ospf6_abr_init (void)
! 870: {
! 871: ospf6_install_lsa_handler (&inter_prefix_handler);
! 872: ospf6_install_lsa_handler (&inter_router_handler);
! 873: }
! 874:
! 875:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>