1/* 2 * Copyright (C) 2001 Yasuhiro Ohara 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the 18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 * Boston, MA 02111-1307, USA. 20 */ 21 22#include "ospf6d.h" 23 24#include "ospf6_dump.h" 25#include "ospf6_abr.h" 26 27static int abr_index; 28#define IS_OSPF6_DUMP_ABR (ospf6_dump_is_on (abr_index)) 29 30#define ADD 0 31#define CHANGE 1 32#define REMOVE 2 33 34/* Inter-Area-Prefix-LSA Calculation */ 35 36static struct ospf6_route_req * 37ospf6_abr_entry_lookup (struct ospf6_route_req *abr_entry, 38 u_int32_t router_id, struct ospf6_area *area) 39{ 40 struct prefix_ls abr_id; 41 char router_string[32]; 42 43 inet_ntop (AF_INET, &router_id, router_string, sizeof (router_string)); 44 45 zlog_info ("ABR: Finding router %s in area %s", router_string, area->str); 46 47 memset (&abr_id, 0, sizeof (abr_id)); 48 abr_id.family = AF_UNSPEC; 49 abr_id.prefixlen = 64; /* xxx */ 50 abr_id.id.s_addr = htonl (0); 51 abr_id.adv_router.s_addr = router_id; 52 53 ospf6_route_lookup (abr_entry, (struct prefix *) &abr_id, 54 area->table_topology); 55 56 if (ospf6_route_end (abr_entry)) 57 { 58 if (IS_OSPF6_DUMP_ABR) 59 zlog_info ("ABR: Router %s not found in area %s", 60 router_string, area->str); 61 return NULL; 62 } 63 64 if (abr_entry->path.area_id != area->area_id) 65 { 66 if (IS_OSPF6_DUMP_ABR) 67 zlog_info ("ABR: ABR area id mismatch"); 68 return NULL; 69 } 70 71 if (! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B)) 72 { 73 if (IS_OSPF6_DUMP_ABR) 74 zlog_info ("ABR: ABR entry's B bit off"); 75 return NULL; 76 } 77 78 return abr_entry; 79} 80 81static int 82ospf6_abr_prefix_lsa_to_route (struct ospf6_lsa *lsa, 83 struct ospf6_route_req *request) 84{ 85 struct ospf6_inter_area_prefix_lsa *iep; 86 struct ospf6_route_req abr_entry; 87 88 if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTER_PREFIX)) 89 { 90 if (IS_OSPF6_DUMP_ABR) 91 zlog_info ("ABR: LSA type mismatch"); 92 return -1; 93 } 94 95 if (IS_LSA_MAXAGE (lsa)) 96 { 97 if (IS_OSPF6_DUMP_ABR) 98 zlog_info ("ABR: LSA MaxAge"); 99 return -1; 100 } 101 102 if (! ospf6_abr_entry_lookup (&abr_entry, lsa->header->adv_router, 103 (struct ospf6_area *) lsa->scope)) 104 { 105 if (IS_OSPF6_DUMP_ABR) 106 zlog_info ("ABR: ABR check failed"); 107 return -1; 108 } 109 110 iep = OSPF6_LSA_HEADER_END (lsa->header); 111 112 memset (request, 0, sizeof (struct ospf6_route_req)); 113 request->route.type = OSPF6_DEST_TYPE_NETWORK; 114 request->route.prefix.family = AF_INET6; 115 request->route.prefix.prefixlen = iep->prefix.prefix_length; 116 ospf6_prefix_in6_addr (&iep->prefix, &request->route.prefix.u.prefix6); 117 118 request->path.cost = abr_entry.path.cost + 119 (ntohl (iep->metric) & ntohl (0x000fffff)); 120 request->path.type = OSPF6_PATH_TYPE_INTER; 121 request->path.origin.type = lsa->header->type; 122 request->path.origin.id = lsa->header->id; 123 request->path.origin.adv_router = lsa->header->adv_router; 124 memcpy (&request->nexthop.address, &abr_entry.nexthop.address, 125 sizeof (request->nexthop.address)); 126 request->nexthop.ifindex = abr_entry.nexthop.ifindex; 127 128 return 0; 129} 130 131void 132ospf6_abr_prefix_lsa_add (struct ospf6_lsa *lsa) 133{ 134 struct ospf6_route_req request; 135 int ret; 136 137 if (IS_OSPF6_DUMP_ABR) 138 zlog_info ("ABR: Calculate %s", lsa->str); 139 140 ret = ospf6_abr_prefix_lsa_to_route (lsa, &request); 141 if (ret < 0) 142 return; 143 144 if (IS_OSPF6_DUMP_ABR) 145 zlog_info ("ABR: Inter Area Route add for %s", lsa->str); 146 147 ospf6_route_add (&request, ospf6->route_table); 148} 149 150void 151ospf6_abr_prefix_lsa_remove (struct ospf6_lsa *lsa) 152{ 153 struct ospf6_inter_area_prefix_lsa *iep; 154 struct prefix_ipv6 prefix6; 155 struct ospf6_route_req request; 156 157 iep = OSPF6_LSA_HEADER_END (lsa->header); 158 159 prefix6.family = AF_INET6; 160 prefix6.prefixlen = iep->prefix.prefix_length; 161 ospf6_prefix_in6_addr (&iep->prefix, &prefix6.prefix); 162 163 if (IS_OSPF6_DUMP_ABR) 164 zlog_info ("ABR: Inter Area Route remove for %s", lsa->str); 165 166 for (ospf6_route_lookup (&request, (struct prefix *) &prefix6, 167 ospf6->route_table); 168 ! ospf6_route_end (&request); 169 ospf6_route_next (&request)) 170 { 171 if (memcmp (&prefix6, &request.route.prefix, sizeof (prefix6))) 172 break; 173 if (request.path.origin.type != htons (OSPF6_LSA_TYPE_INTER_PREFIX) || 174 request.path.origin.adv_router != lsa->header->adv_router || 175 request.path.origin.id != lsa->header->id) 176 continue; 177 178 ospf6_route_remove (&request, ospf6->route_table); 179 } 180} 181 182static int 183ospf6_abr_router_lsa_to_route (struct ospf6_lsa *lsa, 184 struct ospf6_route_req *request) 185{ 186 struct ospf6_inter_area_router_lsa *ier; 187 struct ospf6_route_req abr_entry; 188 189 if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTER_ROUTER)) 190 { 191 if (IS_OSPF6_DUMP_ABR) 192 zlog_info ("ABR: LSA type mismatch"); 193 return -1; 194 } 195 196 if (IS_LSA_MAXAGE (lsa)) 197 { 198 if (IS_OSPF6_DUMP_ABR) 199 zlog_info ("ABR: LSA MaxAge"); 200 return -1; 201 } 202 203 if (! ospf6_abr_entry_lookup (&abr_entry, lsa->header->adv_router, 204 (struct ospf6_area *) lsa->scope)) 205 { 206 if (IS_OSPF6_DUMP_ABR) 207 zlog_info ("ABR: Advertising router check failed"); 208 return -1; 209 } 210 211 ier = OSPF6_LSA_HEADER_END (lsa->header); 212 213 memset (request, 0, sizeof (struct ospf6_route_req)); 214 request->route.type = OSPF6_DEST_TYPE_ROUTER; 215 request->route.prefix.family = AF_UNSPEC; 216 request->route.prefix.prefixlen = 64; /* XXX */ 217 ((struct prefix_ls *) &request->route.prefix)->adv_router.s_addr 218 = ier->router_id; 219 220 request->path.cost = abr_entry.path.cost + 221 (ntohl (ier->metric & htonl (0x000fffff))); 222 request->path.type = OSPF6_PATH_TYPE_INTER; 223 request->path.origin.type = lsa->header->type; 224 request->path.origin.id = lsa->header->id; 225 request->path.origin.adv_router = lsa->header->adv_router; 226 SET_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E); 227 request->path.capability[0] = ier->options[0]; 228 request->path.capability[1] = ier->options[1]; 229 request->path.capability[2] = ier->options[2]; 230 231 memcpy (&request->nexthop.address, &abr_entry.nexthop.address, 232 sizeof (request->nexthop.address)); 233 request->nexthop.ifindex = abr_entry.nexthop.ifindex; 234 235 return 0; 236} 237 238void 239ospf6_abr_router_lsa_add (struct ospf6_lsa *lsa) 240{ 241 struct ospf6_route_req request; 242 int ret; 243 244 if (IS_OSPF6_DUMP_ABR) 245 zlog_info ("ABR: Calculate %s", lsa->str); 246 247 ret = ospf6_abr_router_lsa_to_route (lsa, &request); 248 if (ret < 0) 249 return; 250 251 if (IS_OSPF6_DUMP_ABR) 252 zlog_info ("ABR: Inter Area Router add for %s", lsa->str); 253 254 ospf6_route_add (&request, ospf6->topology_table); 255} 256 257void 258ospf6_abr_router_lsa_remove (struct ospf6_lsa *lsa) 259{ 260 struct ospf6_inter_area_router_lsa *ier; 261 struct prefix_ls prefix_ls; 262 struct ospf6_route_req request; 263 264 ier = OSPF6_LSA_HEADER_END (lsa->header); 265 266 memset (&prefix_ls, 0, sizeof (prefix_ls)); 267 prefix_ls.family = AF_INET6; 268 prefix_ls.prefixlen = 64; /* XXX */ 269 prefix_ls.adv_router.s_addr = ier->router_id; 270 271 if (IS_OSPF6_DUMP_ABR) 272 zlog_info ("ABR: Inter Area Route remove for %s", lsa->str); 273 274 for (ospf6_route_lookup (&request, (struct prefix *) &prefix_ls, 275 ospf6->route_table); 276 ! ospf6_route_end (&request); 277 ospf6_route_next (&request)) 278 { 279 if (memcmp (&prefix_ls, &request.route.prefix, sizeof (prefix_ls))) 280 break; 281 if (request.path.origin.type != htons (OSPF6_LSA_TYPE_INTER_ROUTER) || 282 request.path.origin.adv_router != lsa->header->adv_router || 283 request.path.origin.id != lsa->header->id) 284 continue; 285 286 ospf6_route_remove (&request, ospf6->route_table); 287 } 288} 289 290 291void 292ospf6_abr_abr_entry_add (struct ospf6_route_req *abr_entry) 293{ 294 struct ospf6_lsdb_node node; 295 struct prefix_ls *abr_id; 296 struct ospf6_route_req request; 297 struct ospf6_area *area; 298 299 if (IS_OSPF6_DUMP_ABR) 300 zlog_info ("ABR: New Area Border Router found"); 301 302 area = ospf6_area_lookup (abr_entry->path.area_id, ospf6); 303 if (! area) 304 { 305 if (IS_OSPF6_DUMP_ABR) 306 zlog_info ("ABR: Can't find associated area"); 307 return; 308 } 309 310 abr_id = (struct prefix_ls *) &abr_entry->route.prefix; 311 if (! ospf6_abr_entry_lookup (&request, abr_id->adv_router.s_addr, area)) 312 { 313 if (IS_OSPF6_DUMP_ABR) 314 zlog_info ("ABR: back check failed"); 315 return; 316 } 317 318 /* for each inter-prefix LSA this ABR originated */ 319 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX), 320 abr_id->adv_router.s_addr, area->lsdb); 321 ! ospf6_lsdb_is_end (&node); 322 ospf6_lsdb_next (&node)) 323 ospf6_abr_prefix_lsa_add (node.lsa); 324 325 /* for each inter-router LSA this ABR originated */ 326 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_ROUTER), 327 abr_id->adv_router.s_addr, area->lsdb); 328 ! ospf6_lsdb_is_end (&node); 329 ospf6_lsdb_next (&node)) 330 ospf6_abr_router_lsa_add (node.lsa); 331} 332 333void 334ospf6_abr_abr_entry_remove (struct ospf6_route_req *abr_entry) 335{ 336 struct ospf6_lsdb_node node; 337 struct prefix_ls *abr_id; 338 struct ospf6_area *area; 339 340 if (IS_OSPF6_DUMP_ABR) 341 zlog_info ("ABR: Area Border Router removed"); 342 343 abr_id = (struct prefix_ls *) &abr_entry->route.prefix; 344 345 area = ospf6_area_lookup (abr_entry->path.area_id, ospf6); 346 if (! area) 347 { 348 if (IS_OSPF6_DUMP_ABR) 349 zlog_info ("ABR: Can't find associated area"); 350 return; 351 } 352 353 /* for each inter-prefix LSA this ABR originated */ 354 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX), 355 abr_id->adv_router.s_addr, area->lsdb); 356 ! ospf6_lsdb_is_end (&node); 357 ospf6_lsdb_next (&node)) 358 ospf6_abr_prefix_lsa_remove (node.lsa); 359 360 /* for each inter-router LSA this ABR originated */ 361 for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_ROUTER), 362 abr_id->adv_router.s_addr, area->lsdb); 363 ! ospf6_lsdb_is_end (&node); 364 ospf6_lsdb_next (&node)) 365 ospf6_abr_router_lsa_remove (node.lsa); 366} 367 368/* Inter-Area-Prefix-LSA Origination */ 369 370static void 371ospf6_abr_prefix_lsa_update_add (struct ospf6_route_req *request, 372 struct ospf6_area *area) 373{ 374 char buffer [MAXLSASIZE]; 375 u_int16_t size; 376 struct ospf6_inter_area_prefix_lsa *iep; 377 char *p; 378 379 if (IS_OSPF6_DUMP_ABR) 380 zlog_info ("Update Inter-Prefix for %s: ID: %lu", 381 area->str, (u_long) ntohl (request->route_id)); 382 383 /* prepare buffer */ 384 memset (buffer, 0, sizeof (buffer)); 385 size = sizeof (struct ospf6_inter_area_prefix_lsa); 386 iep = (struct ospf6_inter_area_prefix_lsa *) buffer; 387 p = (char *) (iep + 1); 388 389 /* prefixlen */ 390 iep->prefix.prefix_length = request->route.prefix.prefixlen; 391 392 /* PrefixOptions */ 393 iep->prefix.prefix_options = request->path.prefix_options; 394 395 /* set Prefix */ 396 memcpy (p, &request->route.prefix.u.prefix6, 397 OSPF6_PREFIX_SPACE (request->route.prefix.prefixlen)); 398 ospf6_prefix_apply_mask (&iep->prefix); 399 size += OSPF6_PREFIX_SPACE (request->route.prefix.prefixlen); 400 401 ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTER_PREFIX), 402 htonl (request->route_id), ospf6->router_id, 403 (char *) iep, size, area); 404} 405 406static void 407ospf6_abr_prefix_lsa_update_remove (struct ospf6_route_req *request, 408 struct ospf6_area *area) 409{ 410 struct ospf6_lsa *lsa; 411 lsa = ospf6_lsdb_lookup_lsdb (htons (OSPF6_LSA_TYPE_INTER_PREFIX), 412 htonl (request->route_id), 413 ospf6->router_id, area->lsdb); 414 if (lsa) 415 ospf6_lsa_premature_aging (lsa); 416} 417 418static void 419ospf6_abr_prefix_lsa_update (int type, struct ospf6_route_req *request) 420{ 421 struct ospf6_route_req route, target; 422 listnode node; 423 struct ospf6_area *area; 424 struct ospf6_interface *o6i; 425 426 if (request->route.type != OSPF6_DEST_TYPE_NETWORK) 427 return; 428 429 /* assert this is best path; if not, return */ 430 ospf6_route_lookup (&route, &request->route.prefix, request->table); 431 if (memcmp (&route.path, &request->path, sizeof (route.path))) 432 return; 433 434 if (target.path.cost >= LS_INFINITY || 435 target.path.cost_e2 >= LS_INFINITY) 436 { 437 if (IS_OSPF6_DUMP_ABR) 438 zlog_info ("ABR: Exceeds LS Infinity, ignore"); 439 return; 440 } 441 442 ospf6_route_lookup (&target, &request->route.prefix, request->table); 443 if (type == REMOVE) 444 { 445 ospf6_route_next (&route); 446 if (! memcmp (&route.route, &request->route, sizeof (route.route))) 447 { 448 type = ADD; 449 ospf6_route_next (&target); 450 } 451 } 452 453 for (node = listhead (ospf6->area_list); node; nextnode (node)) 454 { 455 area = getdata (node); 456 457 if (target.path.area_id == area->area_id) 458 continue; 459 460 o6i = ospf6_interface_lookup_by_index (target.nexthop.ifindex); 461 if (o6i && o6i->area && o6i->area->area_id == area->area_id) 462 { 463 zlog_info ("ABR: Logical equivalent of split horizon, skip for %s", 464 area->str); 465 continue; 466 } 467 468 if (area->area_id == ntohs (0) && /* Backbone */ 469 target.path.type != OSPF6_PATH_TYPE_INTRA) 470 continue; 471 472 /* XXX, stub area check */ 473 474 /* XXX, aggregate */ 475 /* if either the area of the route or the area trying to 476 advertise is backbone, do not aggregate */ 477 478 if (type == ADD) 479 ospf6_abr_prefix_lsa_update_add (&target, area); 480 else 481 ospf6_abr_prefix_lsa_update_remove (&target, area); 482 } 483} 484 485void 486ospf6_abr_route_add (struct ospf6_route_req *request) 487{ 488 ospf6_abr_prefix_lsa_update (ADD, request); 489} 490 491void 492ospf6_abr_route_remove (struct ospf6_route_req *request) 493{ 494 ospf6_abr_prefix_lsa_update (REMOVE, request); 495} 496 497int 498ospf6_abr_prefix_lsa_refresh (void *data) 499{ 500 struct ospf6_lsa *lsa = data; 501 struct ospf6_inter_area_prefix_lsa *ier; 502 struct prefix_ipv6 prefix6; 503 struct ospf6_route_req route; 504 505 ier = OSPF6_LSA_HEADER_END (lsa->header); 506 memset (&prefix6, 0, sizeof (prefix6)); 507 prefix6.family = AF_INET6; 508 prefix6.prefixlen = ier->prefix.prefix_length; 509 ospf6_prefix_in6_addr (&ier->prefix, &prefix6.prefix); 510 511 ospf6_route_lookup (&route, (struct prefix *) &prefix6, 512 ospf6->route_table); 513 assert (! ospf6_route_end (&route)); 514 515 ospf6_abr_prefix_lsa_update (ADD, &route); 516 return 0; 517} 518 519int 520ospf6_abr_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) 521{ 522 struct ospf6_inter_area_prefix_lsa *ier; 523 char prefix[128]; 524 525 assert (lsa->header); 526 ier = OSPF6_LSA_HEADER_END (lsa->header); 527 528 ospf6_prefix_string (&ier->prefix, prefix, sizeof (prefix)); 529 530 vty_out (vty, " Metric: %d%s", 531 ntohl (ier->metric & htonl (0x000fffff)), VTY_NEWLINE); 532 vty_out (vty, " Prefix: %s%s", prefix, VTY_NEWLINE); 533 534 return 0; 535} 536 537int 538ospf6_abr_prefix_lsa_hook_add (void *data) 539{ 540 struct ospf6_lsa *lsa = data; 541 ospf6_abr_prefix_lsa_add (lsa); 542 return 0; 543} 544 545int 546ospf6_abr_prefix_lsa_hook_remove (void *data) 547{ 548 struct ospf6_lsa *lsa = data; 549 ospf6_abr_prefix_lsa_remove (lsa); 550 return 0; 551} 552 553void 554ospf6_abr_database_hook_inter_prefix (struct ospf6_lsa *old, 555 struct ospf6_lsa *new) 556{ 557 if (old) 558 ospf6_abr_prefix_lsa_hook_remove (old); 559 if (new && ! IS_LSA_MAXAGE (new)) 560 ospf6_abr_prefix_lsa_hook_add (new); 561} 562 563void 564ospf6_abr_register_inter_prefix () 565{ 566 struct ospf6_lsa_slot slot; 567 568 memset (&slot, 0, sizeof (slot)); 569 slot.type = htons (OSPF6_LSA_TYPE_INTER_PREFIX); 570 slot.name = "Inter-Prefix"; 571 slot.func_show = ospf6_abr_prefix_lsa_show; 572 slot.func_refresh = ospf6_abr_prefix_lsa_refresh; 573 ospf6_lsa_slot_register (&slot); 574 575 ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTER_PREFIX & OSPF6_LSTYPE_CODE_MASK].hook = 576 ospf6_abr_database_hook_inter_prefix; 577} 578 579int 580ospf6_abr_router_lsa_hook_add (void *data) 581{ 582 struct ospf6_lsa *lsa = data; 583 ospf6_abr_router_lsa_add (lsa); 584 return 0; 585} 586 587int 588ospf6_abr_router_lsa_hook_remove (void *data) 589{ 590 struct ospf6_lsa *lsa = data; 591 ospf6_abr_router_lsa_remove (lsa); 592 return 0; 593} 594 595int 596ospf6_abr_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) 597{ 598 return 0; 599} 600 601int 602ospf6_abr_router_lsa_refresh (void *data) 603{ 604 return 0; 605} 606 607void 608ospf6_abr_database_hook_inter_router (struct ospf6_lsa *old, 609 struct ospf6_lsa *new) 610{ 611 if (old) 612 ospf6_abr_router_lsa_hook_remove (old); 613 if (new && ! IS_LSA_MAXAGE (new)) 614 ospf6_abr_router_lsa_hook_add (new); 615} 616 617void 618ospf6_abr_register_inter_router () 619{ 620 struct ospf6_lsa_slot slot; 621 622 memset (&slot, 0, sizeof (slot)); 623 slot.type = htons (OSPF6_LSA_TYPE_INTER_ROUTER); 624 slot.name = "Inter-Router"; 625 slot.func_show = ospf6_abr_router_lsa_show; 626 slot.func_refresh = ospf6_abr_router_lsa_refresh; 627 ospf6_lsa_slot_register (&slot); 628 629 ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTER_ROUTER & OSPF6_LSTYPE_CODE_MASK].hook = 630 ospf6_abr_database_hook_inter_router; 631} 632 633void 634ospf6_abr_inter_route_calculation (struct ospf6_area *area) 635{ 636 struct ospf6_lsdb_node node; 637 638 /* for each inter-prefix LSA */ 639 for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX), 640 area->lsdb); 641 ! ospf6_lsdb_is_end (&node); 642 ospf6_lsdb_next (&node)) 643 ospf6_abr_prefix_lsa_add (node.lsa); 644} 645 646void 647ospf6_abr_init () 648{ 649 abr_index = ospf6_dump_install ("abr", "Area Border Router Function\n"); 650 651 ospf6_abr_register_inter_prefix (); 652 ospf6_abr_register_inter_router (); 653} 654 655 656