Annotation of embedaddon/quagga/zebra/zebra_rib.c, revision 1.1
1.1 ! misho 1: /* Routing Information Base.
! 2: * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
! 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 Free
! 18: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 19: * 02111-1307, USA.
! 20: */
! 21:
! 22: #include <zebra.h>
! 23:
! 24: #include "prefix.h"
! 25: #include "table.h"
! 26: #include "memory.h"
! 27: #include "str.h"
! 28: #include "command.h"
! 29: #include "if.h"
! 30: #include "log.h"
! 31: #include "sockunion.h"
! 32: #include "linklist.h"
! 33: #include "thread.h"
! 34: #include "workqueue.h"
! 35: #include "prefix.h"
! 36: #include "routemap.h"
! 37:
! 38: #include "zebra/rib.h"
! 39: #include "zebra/rt.h"
! 40: #include "zebra/zserv.h"
! 41: #include "zebra/redistribute.h"
! 42: #include "zebra/debug.h"
! 43:
! 44: /* Default rtm_table for all clients */
! 45: extern struct zebra_t zebrad;
! 46:
! 47: /* Hold time for RIB process, should be very minimal.
! 48: * it is useful to able to set it otherwise for testing, hence exported
! 49: * as global here for test-rig code.
! 50: */
! 51: int rib_process_hold_time = 10;
! 52:
! 53: /* Each route type's string and default distance value. */
! 54: static const struct
! 55: {
! 56: int key;
! 57: int distance;
! 58: } route_info[] =
! 59: {
! 60: {ZEBRA_ROUTE_SYSTEM, 0},
! 61: {ZEBRA_ROUTE_KERNEL, 0},
! 62: {ZEBRA_ROUTE_CONNECT, 0},
! 63: {ZEBRA_ROUTE_STATIC, 1},
! 64: {ZEBRA_ROUTE_RIP, 120},
! 65: {ZEBRA_ROUTE_RIPNG, 120},
! 66: {ZEBRA_ROUTE_OSPF, 110},
! 67: {ZEBRA_ROUTE_OSPF6, 110},
! 68: {ZEBRA_ROUTE_ISIS, 115},
! 69: {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}
! 70: };
! 71:
! 72: /* Vector for routing table. */
! 73: static vector vrf_vector;
! 74:
! 75: /* Allocate new VRF. */
! 76: static struct vrf *
! 77: vrf_alloc (const char *name)
! 78: {
! 79: struct vrf *vrf;
! 80:
! 81: vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
! 82:
! 83: /* Put name. */
! 84: if (name)
! 85: vrf->name = XSTRDUP (MTYPE_VRF_NAME, name);
! 86:
! 87: /* Allocate routing table and static table. */
! 88: vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init ();
! 89: vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();
! 90: vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();
! 91: vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init ();
! 92:
! 93: return vrf;
! 94: }
! 95:
! 96: /* Lookup VRF by identifier. */
! 97: struct vrf *
! 98: vrf_lookup (u_int32_t id)
! 99: {
! 100: return vector_lookup (vrf_vector, id);
! 101: }
! 102:
! 103: /* Initialize VRF. */
! 104: static void
! 105: vrf_init (void)
! 106: {
! 107: struct vrf *default_table;
! 108:
! 109: /* Allocate VRF vector. */
! 110: vrf_vector = vector_init (1);
! 111:
! 112: /* Allocate default main table. */
! 113: default_table = vrf_alloc ("Default-IP-Routing-Table");
! 114:
! 115: /* Default table index must be 0. */
! 116: vector_set_index (vrf_vector, 0, default_table);
! 117: }
! 118:
! 119: /* Lookup route table. */
! 120: struct route_table *
! 121: vrf_table (afi_t afi, safi_t safi, u_int32_t id)
! 122: {
! 123: struct vrf *vrf;
! 124:
! 125: vrf = vrf_lookup (id);
! 126: if (! vrf)
! 127: return NULL;
! 128:
! 129: return vrf->table[afi][safi];
! 130: }
! 131:
! 132: /* Lookup static route table. */
! 133: struct route_table *
! 134: vrf_static_table (afi_t afi, safi_t safi, u_int32_t id)
! 135: {
! 136: struct vrf *vrf;
! 137:
! 138: vrf = vrf_lookup (id);
! 139: if (! vrf)
! 140: return NULL;
! 141:
! 142: return vrf->stable[afi][safi];
! 143: }
! 144:
! 145: /* Add nexthop to the end of the list. */
! 146: static void
! 147: nexthop_add (struct rib *rib, struct nexthop *nexthop)
! 148: {
! 149: struct nexthop *last;
! 150:
! 151: for (last = rib->nexthop; last && last->next; last = last->next)
! 152: ;
! 153: if (last)
! 154: last->next = nexthop;
! 155: else
! 156: rib->nexthop = nexthop;
! 157: nexthop->prev = last;
! 158:
! 159: rib->nexthop_num++;
! 160: }
! 161:
! 162: /* Delete specified nexthop from the list. */
! 163: static void
! 164: nexthop_delete (struct rib *rib, struct nexthop *nexthop)
! 165: {
! 166: if (nexthop->next)
! 167: nexthop->next->prev = nexthop->prev;
! 168: if (nexthop->prev)
! 169: nexthop->prev->next = nexthop->next;
! 170: else
! 171: rib->nexthop = nexthop->next;
! 172: rib->nexthop_num--;
! 173: }
! 174:
! 175: /* Free nexthop. */
! 176: static void
! 177: nexthop_free (struct nexthop *nexthop)
! 178: {
! 179: if (nexthop->ifname)
! 180: XFREE (0, nexthop->ifname);
! 181: XFREE (MTYPE_NEXTHOP, nexthop);
! 182: }
! 183:
! 184: struct nexthop *
! 185: nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
! 186: {
! 187: struct nexthop *nexthop;
! 188:
! 189: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
! 190: nexthop->type = NEXTHOP_TYPE_IFINDEX;
! 191: nexthop->ifindex = ifindex;
! 192:
! 193: nexthop_add (rib, nexthop);
! 194:
! 195: return nexthop;
! 196: }
! 197:
! 198: struct nexthop *
! 199: nexthop_ifname_add (struct rib *rib, char *ifname)
! 200: {
! 201: struct nexthop *nexthop;
! 202:
! 203: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
! 204: nexthop->type = NEXTHOP_TYPE_IFNAME;
! 205: nexthop->ifname = XSTRDUP (0, ifname);
! 206:
! 207: nexthop_add (rib, nexthop);
! 208:
! 209: return nexthop;
! 210: }
! 211:
! 212: struct nexthop *
! 213: nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
! 214: {
! 215: struct nexthop *nexthop;
! 216:
! 217: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
! 218: nexthop->type = NEXTHOP_TYPE_IPV4;
! 219: nexthop->gate.ipv4 = *ipv4;
! 220: if (src)
! 221: nexthop->src.ipv4 = *src;
! 222:
! 223: nexthop_add (rib, nexthop);
! 224:
! 225: return nexthop;
! 226: }
! 227:
! 228: static struct nexthop *
! 229: nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
! 230: struct in_addr *src, unsigned int ifindex)
! 231: {
! 232: struct nexthop *nexthop;
! 233:
! 234: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
! 235: nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
! 236: nexthop->gate.ipv4 = *ipv4;
! 237: if (src)
! 238: nexthop->src.ipv4 = *src;
! 239: nexthop->ifindex = ifindex;
! 240:
! 241: nexthop_add (rib, nexthop);
! 242:
! 243: return nexthop;
! 244: }
! 245:
! 246: #ifdef HAVE_IPV6
! 247: struct nexthop *
! 248: nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
! 249: {
! 250: struct nexthop *nexthop;
! 251:
! 252: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
! 253: nexthop->type = NEXTHOP_TYPE_IPV6;
! 254: nexthop->gate.ipv6 = *ipv6;
! 255:
! 256: nexthop_add (rib, nexthop);
! 257:
! 258: return nexthop;
! 259: }
! 260:
! 261: static struct nexthop *
! 262: nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
! 263: char *ifname)
! 264: {
! 265: struct nexthop *nexthop;
! 266:
! 267: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
! 268: nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
! 269: nexthop->gate.ipv6 = *ipv6;
! 270: nexthop->ifname = XSTRDUP (0, ifname);
! 271:
! 272: nexthop_add (rib, nexthop);
! 273:
! 274: return nexthop;
! 275: }
! 276:
! 277: static struct nexthop *
! 278: nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
! 279: unsigned int ifindex)
! 280: {
! 281: struct nexthop *nexthop;
! 282:
! 283: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
! 284: nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
! 285: nexthop->gate.ipv6 = *ipv6;
! 286: nexthop->ifindex = ifindex;
! 287:
! 288: nexthop_add (rib, nexthop);
! 289:
! 290: return nexthop;
! 291: }
! 292: #endif /* HAVE_IPV6 */
! 293:
! 294: struct nexthop *
! 295: nexthop_blackhole_add (struct rib *rib)
! 296: {
! 297: struct nexthop *nexthop;
! 298:
! 299: nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
! 300: nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
! 301: SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
! 302:
! 303: nexthop_add (rib, nexthop);
! 304:
! 305: return nexthop;
! 306: }
! 307:
! 308: /* If force flag is not set, do not modify falgs at all for uninstall
! 309: the route from FIB. */
! 310: static int
! 311: nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set,
! 312: struct route_node *top)
! 313: {
! 314: struct prefix_ipv4 p;
! 315: struct route_table *table;
! 316: struct route_node *rn;
! 317: struct rib *match;
! 318: struct nexthop *newhop;
! 319:
! 320: if (nexthop->type == NEXTHOP_TYPE_IPV4)
! 321: nexthop->ifindex = 0;
! 322:
! 323: if (set)
! 324: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
! 325:
! 326: /* Make lookup prefix. */
! 327: memset (&p, 0, sizeof (struct prefix_ipv4));
! 328: p.family = AF_INET;
! 329: p.prefixlen = IPV4_MAX_PREFIXLEN;
! 330: p.prefix = nexthop->gate.ipv4;
! 331:
! 332: /* Lookup table. */
! 333: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 334: if (! table)
! 335: return 0;
! 336:
! 337: rn = route_node_match (table, (struct prefix *) &p);
! 338: while (rn)
! 339: {
! 340: route_unlock_node (rn);
! 341:
! 342: /* If lookup self prefix return immediately. */
! 343: if (rn == top)
! 344: return 0;
! 345:
! 346: /* Pick up selected route. */
! 347: for (match = rn->info; match; match = match->next)
! 348: {
! 349: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
! 350: continue;
! 351: if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
! 352: break;
! 353: }
! 354:
! 355: /* If there is no selected route or matched route is EGP, go up
! 356: tree. */
! 357: if (! match
! 358: || match->type == ZEBRA_ROUTE_BGP)
! 359: {
! 360: do {
! 361: rn = rn->parent;
! 362: } while (rn && rn->info == NULL);
! 363: if (rn)
! 364: route_lock_node (rn);
! 365: }
! 366: else
! 367: {
! 368: if (match->type == ZEBRA_ROUTE_CONNECT)
! 369: {
! 370: /* Directly point connected route. */
! 371: newhop = match->nexthop;
! 372: if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4)
! 373: nexthop->ifindex = newhop->ifindex;
! 374:
! 375: return 1;
! 376: }
! 377: else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
! 378: {
! 379: for (newhop = match->nexthop; newhop; newhop = newhop->next)
! 380: if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
! 381: && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
! 382: {
! 383: if (set)
! 384: {
! 385: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
! 386: nexthop->rtype = newhop->type;
! 387: if (newhop->type == NEXTHOP_TYPE_IPV4 ||
! 388: newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
! 389: nexthop->rgate.ipv4 = newhop->gate.ipv4;
! 390: if (newhop->type == NEXTHOP_TYPE_IFINDEX
! 391: || newhop->type == NEXTHOP_TYPE_IFNAME
! 392: || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
! 393: nexthop->rifindex = newhop->ifindex;
! 394: }
! 395: return 1;
! 396: }
! 397: return 0;
! 398: }
! 399: else
! 400: {
! 401: return 0;
! 402: }
! 403: }
! 404: }
! 405: return 0;
! 406: }
! 407:
! 408: #ifdef HAVE_IPV6
! 409: /* If force flag is not set, do not modify falgs at all for uninstall
! 410: the route from FIB. */
! 411: static int
! 412: nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set,
! 413: struct route_node *top)
! 414: {
! 415: struct prefix_ipv6 p;
! 416: struct route_table *table;
! 417: struct route_node *rn;
! 418: struct rib *match;
! 419: struct nexthop *newhop;
! 420:
! 421: if (nexthop->type == NEXTHOP_TYPE_IPV6)
! 422: nexthop->ifindex = 0;
! 423:
! 424: if (set)
! 425: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
! 426:
! 427: /* Make lookup prefix. */
! 428: memset (&p, 0, sizeof (struct prefix_ipv6));
! 429: p.family = AF_INET6;
! 430: p.prefixlen = IPV6_MAX_PREFIXLEN;
! 431: p.prefix = nexthop->gate.ipv6;
! 432:
! 433: /* Lookup table. */
! 434: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 435: if (! table)
! 436: return 0;
! 437:
! 438: rn = route_node_match (table, (struct prefix *) &p);
! 439: while (rn)
! 440: {
! 441: route_unlock_node (rn);
! 442:
! 443: /* If lookup self prefix return immediately. */
! 444: if (rn == top)
! 445: return 0;
! 446:
! 447: /* Pick up selected route. */
! 448: for (match = rn->info; match; match = match->next)
! 449: {
! 450: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
! 451: continue;
! 452: if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
! 453: break;
! 454: }
! 455:
! 456: /* If there is no selected route or matched route is EGP, go up
! 457: tree. */
! 458: if (! match
! 459: || match->type == ZEBRA_ROUTE_BGP)
! 460: {
! 461: do {
! 462: rn = rn->parent;
! 463: } while (rn && rn->info == NULL);
! 464: if (rn)
! 465: route_lock_node (rn);
! 466: }
! 467: else
! 468: {
! 469: if (match->type == ZEBRA_ROUTE_CONNECT)
! 470: {
! 471: /* Directly point connected route. */
! 472: newhop = match->nexthop;
! 473:
! 474: if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6)
! 475: nexthop->ifindex = newhop->ifindex;
! 476:
! 477: return 1;
! 478: }
! 479: else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
! 480: {
! 481: for (newhop = match->nexthop; newhop; newhop = newhop->next)
! 482: if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
! 483: && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
! 484: {
! 485: if (set)
! 486: {
! 487: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
! 488: nexthop->rtype = newhop->type;
! 489: if (newhop->type == NEXTHOP_TYPE_IPV6
! 490: || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
! 491: || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
! 492: nexthop->rgate.ipv6 = newhop->gate.ipv6;
! 493: if (newhop->type == NEXTHOP_TYPE_IFINDEX
! 494: || newhop->type == NEXTHOP_TYPE_IFNAME
! 495: || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX
! 496: || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME)
! 497: nexthop->rifindex = newhop->ifindex;
! 498: }
! 499: return 1;
! 500: }
! 501: return 0;
! 502: }
! 503: else
! 504: {
! 505: return 0;
! 506: }
! 507: }
! 508: }
! 509: return 0;
! 510: }
! 511: #endif /* HAVE_IPV6 */
! 512:
! 513: struct rib *
! 514: rib_match_ipv4 (struct in_addr addr)
! 515: {
! 516: struct prefix_ipv4 p;
! 517: struct route_table *table;
! 518: struct route_node *rn;
! 519: struct rib *match;
! 520: struct nexthop *newhop;
! 521:
! 522: /* Lookup table. */
! 523: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 524: if (! table)
! 525: return 0;
! 526:
! 527: memset (&p, 0, sizeof (struct prefix_ipv4));
! 528: p.family = AF_INET;
! 529: p.prefixlen = IPV4_MAX_PREFIXLEN;
! 530: p.prefix = addr;
! 531:
! 532: rn = route_node_match (table, (struct prefix *) &p);
! 533:
! 534: while (rn)
! 535: {
! 536: route_unlock_node (rn);
! 537:
! 538: /* Pick up selected route. */
! 539: for (match = rn->info; match; match = match->next)
! 540: {
! 541: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
! 542: continue;
! 543: if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
! 544: break;
! 545: }
! 546:
! 547: /* If there is no selected route or matched route is EGP, go up
! 548: tree. */
! 549: if (! match
! 550: || match->type == ZEBRA_ROUTE_BGP)
! 551: {
! 552: do {
! 553: rn = rn->parent;
! 554: } while (rn && rn->info == NULL);
! 555: if (rn)
! 556: route_lock_node (rn);
! 557: }
! 558: else
! 559: {
! 560: if (match->type == ZEBRA_ROUTE_CONNECT)
! 561: /* Directly point connected route. */
! 562: return match;
! 563: else
! 564: {
! 565: for (newhop = match->nexthop; newhop; newhop = newhop->next)
! 566: if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
! 567: return match;
! 568: return NULL;
! 569: }
! 570: }
! 571: }
! 572: return NULL;
! 573: }
! 574:
! 575: struct rib *
! 576: rib_lookup_ipv4 (struct prefix_ipv4 *p)
! 577: {
! 578: struct route_table *table;
! 579: struct route_node *rn;
! 580: struct rib *match;
! 581: struct nexthop *nexthop;
! 582:
! 583: /* Lookup table. */
! 584: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 585: if (! table)
! 586: return 0;
! 587:
! 588: rn = route_node_lookup (table, (struct prefix *) p);
! 589:
! 590: /* No route for this prefix. */
! 591: if (! rn)
! 592: return NULL;
! 593:
! 594: /* Unlock node. */
! 595: route_unlock_node (rn);
! 596:
! 597: for (match = rn->info; match; match = match->next)
! 598: {
! 599: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
! 600: continue;
! 601: if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
! 602: break;
! 603: }
! 604:
! 605: if (! match || match->type == ZEBRA_ROUTE_BGP)
! 606: return NULL;
! 607:
! 608: if (match->type == ZEBRA_ROUTE_CONNECT)
! 609: return match;
! 610:
! 611: for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
! 612: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
! 613: return match;
! 614:
! 615: return NULL;
! 616: }
! 617:
! 618: /*
! 619: * This clone function, unlike its original rib_lookup_ipv4(), checks
! 620: * if specified IPv4 route record (prefix/mask -> gate) exists in
! 621: * the whole RIB and has ZEBRA_FLAG_SELECTED set.
! 622: *
! 623: * Return values:
! 624: * -1: error
! 625: * 0: exact match found
! 626: * 1: a match was found with a different gate
! 627: * 2: connected route found
! 628: * 3: no matches found
! 629: */
! 630: int
! 631: rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate)
! 632: {
! 633: struct route_table *table;
! 634: struct route_node *rn;
! 635: struct rib *match;
! 636: struct nexthop *nexthop;
! 637:
! 638: /* Lookup table. */
! 639: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 640: if (! table)
! 641: return ZEBRA_RIB_LOOKUP_ERROR;
! 642:
! 643: /* Scan the RIB table for exactly matching RIB entry. */
! 644: rn = route_node_lookup (table, (struct prefix *) p);
! 645:
! 646: /* No route for this prefix. */
! 647: if (! rn)
! 648: return ZEBRA_RIB_NOTFOUND;
! 649:
! 650: /* Unlock node. */
! 651: route_unlock_node (rn);
! 652:
! 653: /* Find out if a "selected" RR for the discovered RIB entry exists ever. */
! 654: for (match = rn->info; match; match = match->next)
! 655: {
! 656: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
! 657: continue;
! 658: if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
! 659: break;
! 660: }
! 661:
! 662: /* None such found :( */
! 663: if (!match)
! 664: return ZEBRA_RIB_NOTFOUND;
! 665:
! 666: if (match->type == ZEBRA_ROUTE_CONNECT)
! 667: return ZEBRA_RIB_FOUND_CONNECTED;
! 668:
! 669: /* Ok, we have a cood candidate, let's check it's nexthop list... */
! 670: for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next)
! 671: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
! 672: {
! 673: /* We are happy with either direct or recursive hexthop */
! 674: if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr ||
! 675: nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr)
! 676: return ZEBRA_RIB_FOUND_EXACT;
! 677: else
! 678: {
! 679: if (IS_ZEBRA_DEBUG_RIB)
! 680: {
! 681: char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN];
! 682: inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
! 683: inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN);
! 684: inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN);
! 685: zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf);
! 686: }
! 687: return ZEBRA_RIB_FOUND_NOGATE;
! 688: }
! 689: }
! 690:
! 691: return ZEBRA_RIB_NOTFOUND;
! 692: }
! 693:
! 694: #ifdef HAVE_IPV6
! 695: struct rib *
! 696: rib_match_ipv6 (struct in6_addr *addr)
! 697: {
! 698: struct prefix_ipv6 p;
! 699: struct route_table *table;
! 700: struct route_node *rn;
! 701: struct rib *match;
! 702: struct nexthop *newhop;
! 703:
! 704: /* Lookup table. */
! 705: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 706: if (! table)
! 707: return 0;
! 708:
! 709: memset (&p, 0, sizeof (struct prefix_ipv6));
! 710: p.family = AF_INET6;
! 711: p.prefixlen = IPV6_MAX_PREFIXLEN;
! 712: IPV6_ADDR_COPY (&p.prefix, addr);
! 713:
! 714: rn = route_node_match (table, (struct prefix *) &p);
! 715:
! 716: while (rn)
! 717: {
! 718: route_unlock_node (rn);
! 719:
! 720: /* Pick up selected route. */
! 721: for (match = rn->info; match; match = match->next)
! 722: {
! 723: if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED))
! 724: continue;
! 725: if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED))
! 726: break;
! 727: }
! 728:
! 729: /* If there is no selected route or matched route is EGP, go up
! 730: tree. */
! 731: if (! match
! 732: || match->type == ZEBRA_ROUTE_BGP)
! 733: {
! 734: do {
! 735: rn = rn->parent;
! 736: } while (rn && rn->info == NULL);
! 737: if (rn)
! 738: route_lock_node (rn);
! 739: }
! 740: else
! 741: {
! 742: if (match->type == ZEBRA_ROUTE_CONNECT)
! 743: /* Directly point connected route. */
! 744: return match;
! 745: else
! 746: {
! 747: for (newhop = match->nexthop; newhop; newhop = newhop->next)
! 748: if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
! 749: return match;
! 750: return NULL;
! 751: }
! 752: }
! 753: }
! 754: return NULL;
! 755: }
! 756: #endif /* HAVE_IPV6 */
! 757:
! 758: #define RIB_SYSTEM_ROUTE(R) \
! 759: ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
! 760:
! 761: /* This function verifies reachability of one given nexthop, which can be
! 762: * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
! 763: * in nexthop->flags field. If the 4th parameter, 'set', is non-zero,
! 764: * nexthop->ifindex will be updated appropriately as well.
! 765: * An existing route map can turn (otherwise active) nexthop into inactive, but
! 766: * not vice versa.
! 767: *
! 768: * The return value is the final value of 'ACTIVE' flag.
! 769: */
! 770:
! 771: static unsigned
! 772: nexthop_active_check (struct route_node *rn, struct rib *rib,
! 773: struct nexthop *nexthop, int set)
! 774: {
! 775: struct interface *ifp;
! 776: route_map_result_t ret = RMAP_MATCH;
! 777: extern char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX+1];
! 778: struct route_map *rmap;
! 779: int family;
! 780:
! 781: family = 0;
! 782: switch (nexthop->type)
! 783: {
! 784: case NEXTHOP_TYPE_IFINDEX:
! 785: ifp = if_lookup_by_index (nexthop->ifindex);
! 786: if (ifp && if_is_operative(ifp))
! 787: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 788: else
! 789: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 790: break;
! 791: case NEXTHOP_TYPE_IPV6_IFNAME:
! 792: family = AFI_IP6;
! 793: case NEXTHOP_TYPE_IFNAME:
! 794: ifp = if_lookup_by_name (nexthop->ifname);
! 795: if (ifp && if_is_operative(ifp))
! 796: {
! 797: if (set)
! 798: nexthop->ifindex = ifp->ifindex;
! 799: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 800: }
! 801: else
! 802: {
! 803: if (set)
! 804: nexthop->ifindex = 0;
! 805: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 806: }
! 807: break;
! 808: case NEXTHOP_TYPE_IPV4:
! 809: case NEXTHOP_TYPE_IPV4_IFINDEX:
! 810: family = AFI_IP;
! 811: if (nexthop_active_ipv4 (rib, nexthop, set, rn))
! 812: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 813: else
! 814: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 815: break;
! 816: #ifdef HAVE_IPV6
! 817: case NEXTHOP_TYPE_IPV6:
! 818: family = AFI_IP6;
! 819: if (nexthop_active_ipv6 (rib, nexthop, set, rn))
! 820: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 821: else
! 822: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 823: break;
! 824: case NEXTHOP_TYPE_IPV6_IFINDEX:
! 825: family = AFI_IP6;
! 826: if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6))
! 827: {
! 828: ifp = if_lookup_by_index (nexthop->ifindex);
! 829: if (ifp && if_is_operative(ifp))
! 830: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 831: else
! 832: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 833: }
! 834: else
! 835: {
! 836: if (nexthop_active_ipv6 (rib, nexthop, set, rn))
! 837: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 838: else
! 839: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 840: }
! 841: break;
! 842: #endif /* HAVE_IPV6 */
! 843: case NEXTHOP_TYPE_BLACKHOLE:
! 844: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 845: break;
! 846: default:
! 847: break;
! 848: }
! 849: if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
! 850: return 0;
! 851:
! 852: if (RIB_SYSTEM_ROUTE(rib) ||
! 853: (family == AFI_IP && rn->p.family != AF_INET) ||
! 854: (family == AFI_IP6 && rn->p.family != AF_INET6))
! 855: return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 856:
! 857: rmap = 0;
! 858: if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX &&
! 859: proto_rm[family][rib->type])
! 860: rmap = route_map_lookup_by_name (proto_rm[family][rib->type]);
! 861: if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX])
! 862: rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]);
! 863: if (rmap) {
! 864: ret = route_map_apply(rmap, &rn->p, RMAP_ZEBRA, nexthop);
! 865: }
! 866:
! 867: if (ret == RMAP_DENYMATCH)
! 868: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 869: return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 870: }
! 871:
! 872: /* Iterate over all nexthops of the given RIB entry and refresh their
! 873: * ACTIVE flag. rib->nexthop_active_num is updated accordingly. If any
! 874: * nexthop is found to toggle the ACTIVE flag, the whole rib structure
! 875: * is flagged with ZEBRA_FLAG_CHANGED. The 4th 'set' argument is
! 876: * transparently passed to nexthop_active_check().
! 877: *
! 878: * Return value is the new number of active nexthops.
! 879: */
! 880:
! 881: static int
! 882: nexthop_active_update (struct route_node *rn, struct rib *rib, int set)
! 883: {
! 884: struct nexthop *nexthop;
! 885: unsigned int prev_active, prev_index, new_active;
! 886:
! 887: rib->nexthop_active_num = 0;
! 888: UNSET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
! 889:
! 890: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 891: {
! 892: prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
! 893: prev_index = nexthop->ifindex;
! 894: if ((new_active = nexthop_active_check (rn, rib, nexthop, set)))
! 895: rib->nexthop_active_num++;
! 896: if (prev_active != new_active ||
! 897: prev_index != nexthop->ifindex)
! 898: SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED);
! 899: }
! 900: return rib->nexthop_active_num;
! 901: }
! 902:
! 903:
! 904:
! 905: static void
! 906: rib_install_kernel (struct route_node *rn, struct rib *rib)
! 907: {
! 908: int ret = 0;
! 909: struct nexthop *nexthop;
! 910:
! 911: switch (PREFIX_FAMILY (&rn->p))
! 912: {
! 913: case AF_INET:
! 914: ret = kernel_add_ipv4 (&rn->p, rib);
! 915: break;
! 916: #ifdef HAVE_IPV6
! 917: case AF_INET6:
! 918: ret = kernel_add_ipv6 (&rn->p, rib);
! 919: break;
! 920: #endif /* HAVE_IPV6 */
! 921: }
! 922:
! 923: /* This condition is never met, if we are using rt_socket.c */
! 924: if (ret < 0)
! 925: {
! 926: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 927: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 928: }
! 929: }
! 930:
! 931: /* Uninstall the route from kernel. */
! 932: static int
! 933: rib_uninstall_kernel (struct route_node *rn, struct rib *rib)
! 934: {
! 935: int ret = 0;
! 936: struct nexthop *nexthop;
! 937:
! 938: switch (PREFIX_FAMILY (&rn->p))
! 939: {
! 940: case AF_INET:
! 941: ret = kernel_delete_ipv4 (&rn->p, rib);
! 942: break;
! 943: #ifdef HAVE_IPV6
! 944: case AF_INET6:
! 945: ret = kernel_delete_ipv6 (&rn->p, rib);
! 946: break;
! 947: #endif /* HAVE_IPV6 */
! 948: }
! 949:
! 950: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 951: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 952:
! 953: return ret;
! 954: }
! 955:
! 956: /* Uninstall the route from kernel. */
! 957: static void
! 958: rib_uninstall (struct route_node *rn, struct rib *rib)
! 959: {
! 960: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
! 961: {
! 962: redistribute_delete (&rn->p, rib);
! 963: if (! RIB_SYSTEM_ROUTE (rib))
! 964: rib_uninstall_kernel (rn, rib);
! 965: UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED);
! 966: }
! 967: }
! 968:
! 969: static void rib_unlink (struct route_node *, struct rib *);
! 970:
! 971: /* Core function for processing routing information base. */
! 972: static void
! 973: rib_process (struct route_node *rn)
! 974: {
! 975: struct rib *rib;
! 976: struct rib *next;
! 977: struct rib *fib = NULL;
! 978: struct rib *select = NULL;
! 979: struct rib *del = NULL;
! 980: int installed = 0;
! 981: struct nexthop *nexthop = NULL;
! 982: char buf[INET6_ADDRSTRLEN];
! 983:
! 984: assert (rn);
! 985:
! 986: if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
! 987: inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
! 988:
! 989: for (rib = rn->info; rib; rib = next)
! 990: {
! 991: /* The next pointer is saved, because current pointer
! 992: * may be passed to rib_unlink() in the middle of iteration.
! 993: */
! 994: next = rib->next;
! 995:
! 996: /* Currently installed rib. */
! 997: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
! 998: {
! 999: assert (fib == NULL);
! 1000: fib = rib;
! 1001: }
! 1002:
! 1003: /* Unlock removed routes, so they'll be freed, bar the FIB entry,
! 1004: * which we need to do do further work with below.
! 1005: */
! 1006: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 1007: {
! 1008: if (rib != fib)
! 1009: {
! 1010: if (IS_ZEBRA_DEBUG_RIB)
! 1011: zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
! 1012: buf, rn->p.prefixlen, rn, rib);
! 1013: rib_unlink (rn, rib);
! 1014: }
! 1015: else
! 1016: del = rib;
! 1017:
! 1018: continue;
! 1019: }
! 1020:
! 1021: /* Skip unreachable nexthop. */
! 1022: if (! nexthop_active_update (rn, rib, 0))
! 1023: continue;
! 1024:
! 1025: /* Infinit distance. */
! 1026: if (rib->distance == DISTANCE_INFINITY)
! 1027: continue;
! 1028:
! 1029: /* Newly selected rib, the common case. */
! 1030: if (!select)
! 1031: {
! 1032: select = rib;
! 1033: continue;
! 1034: }
! 1035:
! 1036: /* filter route selection in following order:
! 1037: * - connected beats other types
! 1038: * - lower distance beats higher
! 1039: * - lower metric beats higher for equal distance
! 1040: * - last, hence oldest, route wins tie break.
! 1041: */
! 1042:
! 1043: /* Connected routes. Pick the last connected
! 1044: * route of the set of lowest metric connected routes.
! 1045: */
! 1046: if (rib->type == ZEBRA_ROUTE_CONNECT)
! 1047: {
! 1048: if (select->type != ZEBRA_ROUTE_CONNECT
! 1049: || rib->metric <= select->metric)
! 1050: select = rib;
! 1051: continue;
! 1052: }
! 1053: else if (select->type == ZEBRA_ROUTE_CONNECT)
! 1054: continue;
! 1055:
! 1056: /* higher distance loses */
! 1057: if (rib->distance > select->distance)
! 1058: continue;
! 1059:
! 1060: /* lower wins */
! 1061: if (rib->distance < select->distance)
! 1062: {
! 1063: select = rib;
! 1064: continue;
! 1065: }
! 1066:
! 1067: /* metric tie-breaks equal distance */
! 1068: if (rib->metric <= select->metric)
! 1069: select = rib;
! 1070: } /* for (rib = rn->info; rib; rib = next) */
! 1071:
! 1072: /* After the cycle is finished, the following pointers will be set:
! 1073: * select --- the winner RIB entry, if any was found, otherwise NULL
! 1074: * fib --- the SELECTED RIB entry, if any, otherwise NULL
! 1075: * del --- equal to fib, if fib is queued for deletion, NULL otherwise
! 1076: * rib --- NULL
! 1077: */
! 1078:
! 1079: /* Same RIB entry is selected. Update FIB and finish. */
! 1080: if (select && select == fib)
! 1081: {
! 1082: if (IS_ZEBRA_DEBUG_RIB)
! 1083: zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
! 1084: __func__, buf, rn->p.prefixlen, select, fib);
! 1085: if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
! 1086: {
! 1087: redistribute_delete (&rn->p, select);
! 1088: if (! RIB_SYSTEM_ROUTE (select))
! 1089: rib_uninstall_kernel (rn, select);
! 1090:
! 1091: /* Set real nexthop. */
! 1092: nexthop_active_update (rn, select, 1);
! 1093:
! 1094: if (! RIB_SYSTEM_ROUTE (select))
! 1095: rib_install_kernel (rn, select);
! 1096: redistribute_add (&rn->p, select);
! 1097: }
! 1098: else if (! RIB_SYSTEM_ROUTE (select))
! 1099: {
! 1100: /* Housekeeping code to deal with
! 1101: race conditions in kernel with linux
! 1102: netlink reporting interface up before IPv4 or IPv6 protocol
! 1103: is ready to add routes.
! 1104: This makes sure the routes are IN the kernel.
! 1105: */
! 1106:
! 1107: for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
! 1108: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
! 1109: {
! 1110: installed = 1;
! 1111: break;
! 1112: }
! 1113: if (! installed)
! 1114: rib_install_kernel (rn, select);
! 1115: }
! 1116: goto end;
! 1117: }
! 1118:
! 1119: /* At this point we either haven't found the best RIB entry or it is
! 1120: * different from what we currently intend to flag with SELECTED. In both
! 1121: * cases, if a RIB block is present in FIB, it should be withdrawn.
! 1122: */
! 1123: if (fib)
! 1124: {
! 1125: if (IS_ZEBRA_DEBUG_RIB)
! 1126: zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
! 1127: buf, rn->p.prefixlen, fib);
! 1128: redistribute_delete (&rn->p, fib);
! 1129: if (! RIB_SYSTEM_ROUTE (fib))
! 1130: rib_uninstall_kernel (rn, fib);
! 1131: UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
! 1132:
! 1133: /* Set real nexthop. */
! 1134: nexthop_active_update (rn, fib, 1);
! 1135: }
! 1136:
! 1137: /* Regardless of some RIB entry being SELECTED or not before, now we can
! 1138: * tell, that if a new winner exists, FIB is still not updated with this
! 1139: * data, but ready to be.
! 1140: */
! 1141: if (select)
! 1142: {
! 1143: if (IS_ZEBRA_DEBUG_RIB)
! 1144: zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
! 1145: rn->p.prefixlen, select);
! 1146: /* Set real nexthop. */
! 1147: nexthop_active_update (rn, select, 1);
! 1148:
! 1149: if (! RIB_SYSTEM_ROUTE (select))
! 1150: rib_install_kernel (rn, select);
! 1151: SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
! 1152: redistribute_add (&rn->p, select);
! 1153: }
! 1154:
! 1155: /* FIB route was removed, should be deleted */
! 1156: if (del)
! 1157: {
! 1158: if (IS_ZEBRA_DEBUG_RIB)
! 1159: zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
! 1160: rn->p.prefixlen, del, rn);
! 1161: rib_unlink (rn, del);
! 1162: }
! 1163:
! 1164: end:
! 1165: if (IS_ZEBRA_DEBUG_RIB_Q)
! 1166: zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
! 1167: }
! 1168:
! 1169: /* Take a list of route_node structs and return 1, if there was a record
! 1170: * picked from it and processed by rib_process(). Don't process more,
! 1171: * than one RN record; operate only in the specified sub-queue.
! 1172: */
! 1173: static unsigned int
! 1174: process_subq (struct list * subq, u_char qindex)
! 1175: {
! 1176: struct listnode *lnode = listhead (subq);
! 1177: struct route_node *rnode;
! 1178:
! 1179: if (!lnode)
! 1180: return 0;
! 1181:
! 1182: rnode = listgetdata (lnode);
! 1183: rib_process (rnode);
! 1184:
! 1185: if (rnode->info) /* The first RIB record is holding the flags bitmask. */
! 1186: UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex));
! 1187: #if 0
! 1188: else
! 1189: {
! 1190: zlog_debug ("%s: called for route_node (%p, %d) with no ribs",
! 1191: __func__, rnode, rnode->lock);
! 1192: zlog_backtrace(LOG_DEBUG);
! 1193: }
! 1194: #endif
! 1195: route_unlock_node (rnode);
! 1196: list_delete_node (subq, lnode);
! 1197: return 1;
! 1198: }
! 1199:
! 1200: /* Dispatch the meta queue by picking, processing and unlocking the next RN from
! 1201: * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data
! 1202: * is pointed to the meta queue structure.
! 1203: */
! 1204: static wq_item_status
! 1205: meta_queue_process (struct work_queue *dummy, void *data)
! 1206: {
! 1207: struct meta_queue * mq = data;
! 1208: unsigned i;
! 1209:
! 1210: for (i = 0; i < MQ_SIZE; i++)
! 1211: if (process_subq (mq->subq[i], i))
! 1212: {
! 1213: mq->size--;
! 1214: break;
! 1215: }
! 1216: return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
! 1217: }
! 1218:
! 1219: /* Map from rib types to queue type (priority) in meta queue */
! 1220: static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {
! 1221: [ZEBRA_ROUTE_SYSTEM] = 4,
! 1222: [ZEBRA_ROUTE_KERNEL] = 0,
! 1223: [ZEBRA_ROUTE_CONNECT] = 0,
! 1224: [ZEBRA_ROUTE_STATIC] = 1,
! 1225: [ZEBRA_ROUTE_RIP] = 2,
! 1226: [ZEBRA_ROUTE_RIPNG] = 2,
! 1227: [ZEBRA_ROUTE_OSPF] = 2,
! 1228: [ZEBRA_ROUTE_OSPF6] = 2,
! 1229: [ZEBRA_ROUTE_ISIS] = 2,
! 1230: [ZEBRA_ROUTE_BGP] = 3,
! 1231: [ZEBRA_ROUTE_HSLS] = 4,
! 1232: };
! 1233:
! 1234: /* Look into the RN and queue it into one or more priority queues,
! 1235: * increasing the size for each data push done.
! 1236: */
! 1237: static void
! 1238: rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn)
! 1239: {
! 1240: struct rib *rib;
! 1241: char buf[INET6_ADDRSTRLEN];
! 1242:
! 1243: if (IS_ZEBRA_DEBUG_RIB_Q)
! 1244: inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
! 1245:
! 1246: for (rib = rn->info; rib; rib = rib->next)
! 1247: {
! 1248: u_char qindex = meta_queue_map[rib->type];
! 1249:
! 1250: /* Invariant: at this point we always have rn->info set. */
! 1251: if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)))
! 1252: {
! 1253: if (IS_ZEBRA_DEBUG_RIB_Q)
! 1254: zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u",
! 1255: __func__, buf, rn->p.prefixlen, rn, qindex);
! 1256: continue;
! 1257: }
! 1258:
! 1259: SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex));
! 1260: listnode_add (mq->subq[qindex], rn);
! 1261: route_lock_node (rn);
! 1262: mq->size++;
! 1263:
! 1264: if (IS_ZEBRA_DEBUG_RIB_Q)
! 1265: zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u",
! 1266: __func__, buf, rn->p.prefixlen, rn, qindex);
! 1267: }
! 1268: }
! 1269:
! 1270: /* Add route_node to work queue and schedule processing */
! 1271: static void
! 1272: rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
! 1273: {
! 1274:
! 1275: if (IS_ZEBRA_DEBUG_RIB_Q)
! 1276: {
! 1277: char buf[INET6_ADDRSTRLEN];
! 1278:
! 1279: zlog_info ("%s: %s/%d: work queue added", __func__,
! 1280: inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN),
! 1281: rn->p.prefixlen);
! 1282: }
! 1283:
! 1284: /*
! 1285: * The RIB queue should normally be either empty or holding the only
! 1286: * work_queue_item element. In the latter case this element would
! 1287: * hold a pointer to the meta queue structure, which must be used to
! 1288: * actually queue the route nodes to process. So create the MQ
! 1289: * holder, if necessary, then push the work into it in any case.
! 1290: * This semantics was introduced after 0.99.9 release.
! 1291: */
! 1292: if (!zebra->ribq->items->count)
! 1293: work_queue_add (zebra->ribq, zebra->mq);
! 1294:
! 1295: rib_meta_queue_add (zebra->mq, rn);
! 1296: }
! 1297:
! 1298: /* Create new meta queue.
! 1299: A destructor function doesn't seem to be necessary here.
! 1300: */
! 1301: static struct meta_queue *
! 1302: meta_queue_new (void)
! 1303: {
! 1304: struct meta_queue *new;
! 1305: unsigned i;
! 1306:
! 1307: new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue));
! 1308: assert(new);
! 1309:
! 1310: for (i = 0; i < MQ_SIZE; i++)
! 1311: {
! 1312: new->subq[i] = list_new ();
! 1313: assert(new->subq[i]);
! 1314: }
! 1315:
! 1316: return new;
! 1317: }
! 1318:
! 1319: /* initialise zebra rib work queue */
! 1320: static void
! 1321: rib_queue_init (struct zebra_t *zebra)
! 1322: {
! 1323: if (! (zebra->ribq = work_queue_new (zebra->master,
! 1324: "route_node processing")))
! 1325: {
! 1326: zlog_err ("%s: could not initialise work queue!", __func__);
! 1327: return;
! 1328: }
! 1329:
! 1330: /* fill in the work queue spec */
! 1331: zebra->ribq->spec.workfunc = &meta_queue_process;
! 1332: zebra->ribq->spec.errorfunc = NULL;
! 1333: /* XXX: TODO: These should be runtime configurable via vty */
! 1334: zebra->ribq->spec.max_retries = 3;
! 1335: zebra->ribq->spec.hold = rib_process_hold_time;
! 1336:
! 1337: if (!(zebra->mq = meta_queue_new ()))
! 1338: zlog_err ("%s: could not initialise meta queue!", __func__);
! 1339: }
! 1340:
! 1341: /* RIB updates are processed via a queue of pointers to route_nodes.
! 1342: *
! 1343: * The queue length is bounded by the maximal size of the routing table,
! 1344: * as a route_node will not be requeued, if already queued.
! 1345: *
! 1346: * RIBs are submitted via rib_addnode or rib_delnode which set minimal
! 1347: * state, or static_install_ipv{4,6} (when an existing RIB is updated)
! 1348: * and then submit route_node to queue for best-path selection later.
! 1349: * Order of add/delete state changes are preserved for any given RIB.
! 1350: *
! 1351: * Deleted RIBs are reaped during best-path selection.
! 1352: *
! 1353: * rib_addnode
! 1354: * |-> rib_link or unset RIB_ENTRY_REMOVE |->Update kernel with
! 1355: * |-------->| | best RIB, if required
! 1356: * | |
! 1357: * static_install->|->rib_addqueue...... -> rib_process
! 1358: * | |
! 1359: * |-------->| |-> rib_unlink
! 1360: * |-> set RIB_ENTRY_REMOVE |
! 1361: * rib_delnode (RIB freed)
! 1362: *
! 1363: *
! 1364: * Queueing state for a route_node is kept in the head RIB entry, this
! 1365: * state must be preserved as and when the head RIB entry of a
! 1366: * route_node is changed by rib_unlink / rib_link. A small complication,
! 1367: * but saves having to allocate a dedicated object for this.
! 1368: *
! 1369: * Refcounting (aka "locking" throughout the GNU Zebra and Quagga code):
! 1370: *
! 1371: * - route_nodes: refcounted by:
! 1372: * - RIBs attached to route_node:
! 1373: * - managed by: rib_link/unlink
! 1374: * - route_node processing queue
! 1375: * - managed by: rib_addqueue, rib_process.
! 1376: *
! 1377: */
! 1378:
! 1379: /* Add RIB to head of the route node. */
! 1380: static void
! 1381: rib_link (struct route_node *rn, struct rib *rib)
! 1382: {
! 1383: struct rib *head;
! 1384: char buf[INET6_ADDRSTRLEN];
! 1385:
! 1386: assert (rib && rn);
! 1387:
! 1388: route_lock_node (rn); /* rn route table reference */
! 1389:
! 1390: if (IS_ZEBRA_DEBUG_RIB)
! 1391: {
! 1392: inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
! 1393: zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
! 1394: buf, rn->p.prefixlen, rn, rib);
! 1395: }
! 1396:
! 1397: head = rn->info;
! 1398: if (head)
! 1399: {
! 1400: if (IS_ZEBRA_DEBUG_RIB)
! 1401: zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__,
! 1402: buf, rn->p.prefixlen);
! 1403: head->prev = rib;
! 1404: /* Transfer the rn status flags to the new head RIB */
! 1405: rib->rn_status = head->rn_status;
! 1406: }
! 1407: rib->next = head;
! 1408: rn->info = rib;
! 1409: rib_queue_add (&zebrad, rn);
! 1410: }
! 1411:
! 1412: static void
! 1413: rib_addnode (struct route_node *rn, struct rib *rib)
! 1414: {
! 1415: /* RIB node has been un-removed before route-node is processed.
! 1416: * route_node must hence already be on the queue for processing..
! 1417: */
! 1418: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 1419: {
! 1420: if (IS_ZEBRA_DEBUG_RIB)
! 1421: {
! 1422: char buf[INET6_ADDRSTRLEN];
! 1423: inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
! 1424: zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
! 1425: __func__, buf, rn->p.prefixlen, rn, rib);
! 1426: }
! 1427: UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
! 1428: return;
! 1429: }
! 1430: rib_link (rn, rib);
! 1431: }
! 1432:
! 1433: static void
! 1434: rib_unlink (struct route_node *rn, struct rib *rib)
! 1435: {
! 1436: struct nexthop *nexthop, *next;
! 1437: char buf[INET6_ADDRSTRLEN];
! 1438:
! 1439: assert (rn && rib);
! 1440:
! 1441: if (IS_ZEBRA_DEBUG_RIB)
! 1442: {
! 1443: inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
! 1444: zlog_debug ("%s: %s/%d: rn %p, rib %p",
! 1445: __func__, buf, rn->p.prefixlen, rn, rib);
! 1446: }
! 1447:
! 1448: if (rib->next)
! 1449: rib->next->prev = rib->prev;
! 1450:
! 1451: if (rib->prev)
! 1452: rib->prev->next = rib->next;
! 1453: else
! 1454: {
! 1455: rn->info = rib->next;
! 1456:
! 1457: if (rn->info)
! 1458: {
! 1459: if (IS_ZEBRA_DEBUG_RIB)
! 1460: zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy",
! 1461: __func__, buf, rn->p.prefixlen, rn, rib);
! 1462: rib->next->rn_status = rib->rn_status;
! 1463: }
! 1464: }
! 1465:
! 1466: /* free RIB and nexthops */
! 1467: for (nexthop = rib->nexthop; nexthop; nexthop = next)
! 1468: {
! 1469: next = nexthop->next;
! 1470: nexthop_free (nexthop);
! 1471: }
! 1472: XFREE (MTYPE_RIB, rib);
! 1473:
! 1474: route_unlock_node (rn); /* rn route table reference */
! 1475: }
! 1476:
! 1477: static void
! 1478: rib_delnode (struct route_node *rn, struct rib *rib)
! 1479: {
! 1480: if (IS_ZEBRA_DEBUG_RIB)
! 1481: {
! 1482: char buf[INET6_ADDRSTRLEN];
! 1483: inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
! 1484: zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
! 1485: buf, rn->p.prefixlen, rn, rib);
! 1486: }
! 1487: SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
! 1488: rib_queue_add (&zebrad, rn);
! 1489: }
! 1490:
! 1491: int
! 1492: rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
! 1493: struct in_addr *gate, struct in_addr *src,
! 1494: unsigned int ifindex, u_int32_t vrf_id,
! 1495: u_int32_t metric, u_char distance)
! 1496: {
! 1497: struct rib *rib;
! 1498: struct rib *same = NULL;
! 1499: struct route_table *table;
! 1500: struct route_node *rn;
! 1501: struct nexthop *nexthop;
! 1502:
! 1503: /* Lookup table. */
! 1504: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 1505: if (! table)
! 1506: return 0;
! 1507:
! 1508: /* Make it sure prefixlen is applied to the prefix. */
! 1509: apply_mask_ipv4 (p);
! 1510:
! 1511: /* Set default distance by route type. */
! 1512: if (distance == 0)
! 1513: {
! 1514: distance = route_info[type].distance;
! 1515:
! 1516: /* iBGP distance is 200. */
! 1517: if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
! 1518: distance = 200;
! 1519: }
! 1520:
! 1521: /* Lookup route node.*/
! 1522: rn = route_node_get (table, (struct prefix *) p);
! 1523:
! 1524: /* If same type of route are installed, treat it as a implicit
! 1525: withdraw. */
! 1526: for (rib = rn->info; rib; rib = rib->next)
! 1527: {
! 1528: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 1529: continue;
! 1530:
! 1531: if (rib->type != type)
! 1532: continue;
! 1533: if (rib->type != ZEBRA_ROUTE_CONNECT)
! 1534: {
! 1535: same = rib;
! 1536: break;
! 1537: }
! 1538: /* Duplicate connected route comes in. */
! 1539: else if ((nexthop = rib->nexthop) &&
! 1540: nexthop->type == NEXTHOP_TYPE_IFINDEX &&
! 1541: nexthop->ifindex == ifindex &&
! 1542: !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 1543: {
! 1544: rib->refcnt++;
! 1545: return 0 ;
! 1546: }
! 1547: }
! 1548:
! 1549: /* Allocate new rib structure. */
! 1550: rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
! 1551: rib->type = type;
! 1552: rib->distance = distance;
! 1553: rib->flags = flags;
! 1554: rib->metric = metric;
! 1555: rib->table = vrf_id;
! 1556: rib->nexthop_num = 0;
! 1557: rib->uptime = time (NULL);
! 1558:
! 1559: /* Nexthop settings. */
! 1560: if (gate)
! 1561: {
! 1562: if (ifindex)
! 1563: nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
! 1564: else
! 1565: nexthop_ipv4_add (rib, gate, src);
! 1566: }
! 1567: else
! 1568: nexthop_ifindex_add (rib, ifindex);
! 1569:
! 1570: /* If this route is kernel route, set FIB flag to the route. */
! 1571: if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
! 1572: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 1573: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 1574:
! 1575: /* Link new rib to node.*/
! 1576: if (IS_ZEBRA_DEBUG_RIB)
! 1577: zlog_debug ("%s: calling rib_addnode (%p, %p)", __func__, rn, rib);
! 1578: rib_addnode (rn, rib);
! 1579:
! 1580: /* Free implicit route.*/
! 1581: if (same)
! 1582: {
! 1583: if (IS_ZEBRA_DEBUG_RIB)
! 1584: zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
! 1585: rib_delnode (rn, same);
! 1586: }
! 1587:
! 1588: route_unlock_node (rn);
! 1589: return 0;
! 1590: }
! 1591:
! 1592: /* This function dumps the contents of a given RIB entry into
! 1593: * standard debug log. Calling function name and IP prefix in
! 1594: * question are passed as 1st and 2nd arguments.
! 1595: */
! 1596:
! 1597: void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib * rib)
! 1598: {
! 1599: char straddr1[INET_ADDRSTRLEN], straddr2[INET_ADDRSTRLEN];
! 1600: struct nexthop *nexthop;
! 1601:
! 1602: inet_ntop (AF_INET, &p->prefix, straddr1, INET_ADDRSTRLEN);
! 1603: zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen);
! 1604: zlog_debug
! 1605: (
! 1606: "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d",
! 1607: func,
! 1608: rib->refcnt,
! 1609: (unsigned long) rib->uptime,
! 1610: rib->type,
! 1611: rib->table
! 1612: );
! 1613: zlog_debug
! 1614: (
! 1615: "%s: metric == %u, distance == %u, flags == %u, status == %u",
! 1616: func,
! 1617: rib->metric,
! 1618: rib->distance,
! 1619: rib->flags,
! 1620: rib->status
! 1621: );
! 1622: zlog_debug
! 1623: (
! 1624: "%s: nexthop_num == %u, nexthop_active_num == %u, nexthop_fib_num == %u",
! 1625: func,
! 1626: rib->nexthop_num,
! 1627: rib->nexthop_active_num,
! 1628: rib->nexthop_fib_num
! 1629: );
! 1630: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 1631: {
! 1632: inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, straddr1, INET_ADDRSTRLEN);
! 1633: inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, straddr2, INET_ADDRSTRLEN);
! 1634: zlog_debug
! 1635: (
! 1636: "%s: NH %s (%s) with flags %s%s%s",
! 1637: func,
! 1638: straddr1,
! 1639: straddr2,
! 1640: (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
! 1641: (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
! 1642: (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE) ? "RECURSIVE" : "")
! 1643: );
! 1644: }
! 1645: zlog_debug ("%s: dump complete", func);
! 1646: }
! 1647:
! 1648: /* This is an exported helper to rtm_read() to dump the strange
! 1649: * RIB entry found by rib_lookup_ipv4_route()
! 1650: */
! 1651:
! 1652: void rib_lookup_and_dump (struct prefix_ipv4 * p)
! 1653: {
! 1654: struct route_table *table;
! 1655: struct route_node *rn;
! 1656: struct rib *rib;
! 1657: char prefix_buf[INET_ADDRSTRLEN];
! 1658:
! 1659: /* Lookup table. */
! 1660: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 1661: if (! table)
! 1662: {
! 1663: zlog_err ("%s: vrf_table() returned NULL", __func__);
! 1664: return;
! 1665: }
! 1666:
! 1667: inet_ntop (AF_INET, &p->prefix.s_addr, prefix_buf, INET_ADDRSTRLEN);
! 1668: /* Scan the RIB table for exactly matching RIB entry. */
! 1669: rn = route_node_lookup (table, (struct prefix *) p);
! 1670:
! 1671: /* No route for this prefix. */
! 1672: if (! rn)
! 1673: {
! 1674: zlog_debug ("%s: lookup failed for %s/%d", __func__, prefix_buf, p->prefixlen);
! 1675: return;
! 1676: }
! 1677:
! 1678: /* Unlock node. */
! 1679: route_unlock_node (rn);
! 1680:
! 1681: /* let's go */
! 1682: for (rib = rn->info; rib; rib = rib->next)
! 1683: {
! 1684: zlog_debug
! 1685: (
! 1686: "%s: rn %p, rib %p: %s, %s",
! 1687: __func__,
! 1688: rn,
! 1689: rib,
! 1690: (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"),
! 1691: (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected")
! 1692: );
! 1693: rib_dump (__func__, p, rib);
! 1694: }
! 1695: }
! 1696:
! 1697: /* Check if requested address assignment will fail due to another
! 1698: * route being installed by zebra in FIB already. Take necessary
! 1699: * actions, if needed: remove such a route from FIB and deSELECT
! 1700: * corresponding RIB entry. Then put affected RN into RIBQ head.
! 1701: */
! 1702: void rib_lookup_and_pushup (struct prefix_ipv4 * p)
! 1703: {
! 1704: struct route_table *table;
! 1705: struct route_node *rn;
! 1706: struct rib *rib;
! 1707: unsigned changed = 0;
! 1708:
! 1709: if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0)))
! 1710: {
! 1711: zlog_err ("%s: vrf_table() returned NULL", __func__);
! 1712: return;
! 1713: }
! 1714:
! 1715: /* No matches would be the simplest case. */
! 1716: if (NULL == (rn = route_node_lookup (table, (struct prefix *) p)))
! 1717: return;
! 1718:
! 1719: /* Unlock node. */
! 1720: route_unlock_node (rn);
! 1721:
! 1722: /* Check all RIB entries. In case any changes have to be done, requeue
! 1723: * the RN into RIBQ head. If the routing message about the new connected
! 1724: * route (generated by the IP address we are going to assign very soon)
! 1725: * comes before the RIBQ is processed, the new RIB entry will join
! 1726: * RIBQ record already on head. This is necessary for proper revalidation
! 1727: * of the rest of the RIB.
! 1728: */
! 1729: for (rib = rn->info; rib; rib = rib->next)
! 1730: {
! 1731: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) &&
! 1732: ! RIB_SYSTEM_ROUTE (rib))
! 1733: {
! 1734: changed = 1;
! 1735: if (IS_ZEBRA_DEBUG_RIB)
! 1736: {
! 1737: char buf[INET_ADDRSTRLEN];
! 1738: inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
! 1739: zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
! 1740: rib_dump (__func__, (struct prefix_ipv4 *)&rn->p, rib);
! 1741: }
! 1742: rib_uninstall (rn, rib);
! 1743: }
! 1744: }
! 1745: if (changed)
! 1746: rib_queue_add (&zebrad, rn);
! 1747: }
! 1748:
! 1749: int
! 1750: rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)
! 1751: {
! 1752: struct route_table *table;
! 1753: struct route_node *rn;
! 1754: struct rib *same;
! 1755: struct nexthop *nexthop;
! 1756:
! 1757: /* Lookup table. */
! 1758: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 1759: if (! table)
! 1760: return 0;
! 1761: /* Make it sure prefixlen is applied to the prefix. */
! 1762: apply_mask_ipv4 (p);
! 1763:
! 1764: /* Set default distance by route type. */
! 1765: if (rib->distance == 0)
! 1766: {
! 1767: rib->distance = route_info[rib->type].distance;
! 1768:
! 1769: /* iBGP distance is 200. */
! 1770: if (rib->type == ZEBRA_ROUTE_BGP
! 1771: && CHECK_FLAG (rib->flags, ZEBRA_FLAG_IBGP))
! 1772: rib->distance = 200;
! 1773: }
! 1774:
! 1775: /* Lookup route node.*/
! 1776: rn = route_node_get (table, (struct prefix *) p);
! 1777:
! 1778: /* If same type of route are installed, treat it as a implicit
! 1779: withdraw. */
! 1780: for (same = rn->info; same; same = same->next)
! 1781: {
! 1782: if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED))
! 1783: continue;
! 1784:
! 1785: if (same->type == rib->type && same->table == rib->table
! 1786: && same->type != ZEBRA_ROUTE_CONNECT)
! 1787: break;
! 1788: }
! 1789:
! 1790: /* If this route is kernel route, set FIB flag to the route. */
! 1791: if (rib->type == ZEBRA_ROUTE_KERNEL || rib->type == ZEBRA_ROUTE_CONNECT)
! 1792: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 1793: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 1794:
! 1795: /* Link new rib to node.*/
! 1796: rib_addnode (rn, rib);
! 1797: if (IS_ZEBRA_DEBUG_RIB)
! 1798: {
! 1799: zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
! 1800: __func__, rn, rib);
! 1801: rib_dump (__func__, p, rib);
! 1802: }
! 1803:
! 1804: /* Free implicit route.*/
! 1805: if (same)
! 1806: {
! 1807: if (IS_ZEBRA_DEBUG_RIB)
! 1808: {
! 1809: zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
! 1810: __func__, rn, same);
! 1811: rib_dump (__func__, p, same);
! 1812: }
! 1813: rib_delnode (rn, same);
! 1814: }
! 1815:
! 1816: route_unlock_node (rn);
! 1817: return 0;
! 1818: }
! 1819:
! 1820: /* XXX factor with rib_delete_ipv6 */
! 1821: int
! 1822: rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,
! 1823: struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
! 1824: {
! 1825: struct route_table *table;
! 1826: struct route_node *rn;
! 1827: struct rib *rib;
! 1828: struct rib *fib = NULL;
! 1829: struct rib *same = NULL;
! 1830: struct nexthop *nexthop;
! 1831: char buf1[INET_ADDRSTRLEN];
! 1832: char buf2[INET_ADDRSTRLEN];
! 1833:
! 1834: /* Lookup table. */
! 1835: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 1836: if (! table)
! 1837: return 0;
! 1838:
! 1839: /* Apply mask. */
! 1840: apply_mask_ipv4 (p);
! 1841:
! 1842: if (IS_ZEBRA_DEBUG_KERNEL && gate)
! 1843: zlog_debug ("rib_delete_ipv4(): route delete %s/%d via %s ifindex %d",
! 1844: inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
! 1845: p->prefixlen,
! 1846: inet_ntoa (*gate),
! 1847: ifindex);
! 1848:
! 1849: /* Lookup route node. */
! 1850: rn = route_node_lookup (table, (struct prefix *) p);
! 1851: if (! rn)
! 1852: {
! 1853: if (IS_ZEBRA_DEBUG_KERNEL)
! 1854: {
! 1855: if (gate)
! 1856: zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
! 1857: inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
! 1858: p->prefixlen,
! 1859: inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
! 1860: ifindex);
! 1861: else
! 1862: zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
! 1863: inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
! 1864: p->prefixlen,
! 1865: ifindex);
! 1866: }
! 1867: return ZEBRA_ERR_RTNOEXIST;
! 1868: }
! 1869:
! 1870: /* Lookup same type route. */
! 1871: for (rib = rn->info; rib; rib = rib->next)
! 1872: {
! 1873: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 1874: continue;
! 1875:
! 1876: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
! 1877: fib = rib;
! 1878:
! 1879: if (rib->type != type)
! 1880: continue;
! 1881: if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
! 1882: nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
! 1883: {
! 1884: if (rib->refcnt)
! 1885: {
! 1886: rib->refcnt--;
! 1887: route_unlock_node (rn);
! 1888: route_unlock_node (rn);
! 1889: return 0;
! 1890: }
! 1891: same = rib;
! 1892: break;
! 1893: }
! 1894: /* Make sure that the route found has the same gateway. */
! 1895: else if (gate == NULL ||
! 1896: ((nexthop = rib->nexthop) &&
! 1897: (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
! 1898: IPV4_ADDR_SAME (&nexthop->rgate.ipv4, gate))))
! 1899: {
! 1900: same = rib;
! 1901: break;
! 1902: }
! 1903: }
! 1904:
! 1905: /* If same type of route can't be found and this message is from
! 1906: kernel. */
! 1907: if (! same)
! 1908: {
! 1909: if (fib && type == ZEBRA_ROUTE_KERNEL)
! 1910: {
! 1911: /* Unset flags. */
! 1912: for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
! 1913: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 1914:
! 1915: UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
! 1916: }
! 1917: else
! 1918: {
! 1919: if (IS_ZEBRA_DEBUG_KERNEL)
! 1920: {
! 1921: if (gate)
! 1922: zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
! 1923: inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
! 1924: p->prefixlen,
! 1925: inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
! 1926: ifindex,
! 1927: type);
! 1928: else
! 1929: zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
! 1930: inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
! 1931: p->prefixlen,
! 1932: ifindex,
! 1933: type);
! 1934: }
! 1935: route_unlock_node (rn);
! 1936: return ZEBRA_ERR_RTNOEXIST;
! 1937: }
! 1938: }
! 1939:
! 1940: if (same)
! 1941: rib_delnode (rn, same);
! 1942:
! 1943: route_unlock_node (rn);
! 1944: return 0;
! 1945: }
! 1946:
! 1947: /* Install static route into rib. */
! 1948: static void
! 1949: static_install_ipv4 (struct prefix *p, struct static_ipv4 *si)
! 1950: {
! 1951: struct rib *rib;
! 1952: struct route_node *rn;
! 1953: struct route_table *table;
! 1954:
! 1955: /* Lookup table. */
! 1956: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 1957: if (! table)
! 1958: return;
! 1959:
! 1960: /* Lookup existing route */
! 1961: rn = route_node_get (table, p);
! 1962: for (rib = rn->info; rib; rib = rib->next)
! 1963: {
! 1964: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 1965: continue;
! 1966:
! 1967: if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
! 1968: break;
! 1969: }
! 1970:
! 1971: if (rib)
! 1972: {
! 1973: /* Same distance static route is there. Update it with new
! 1974: nexthop. */
! 1975: route_unlock_node (rn);
! 1976: switch (si->type)
! 1977: {
! 1978: case STATIC_IPV4_GATEWAY:
! 1979: nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
! 1980: break;
! 1981: case STATIC_IPV4_IFNAME:
! 1982: nexthop_ifname_add (rib, si->gate.ifname);
! 1983: break;
! 1984: case STATIC_IPV4_BLACKHOLE:
! 1985: nexthop_blackhole_add (rib);
! 1986: break;
! 1987: }
! 1988: rib_queue_add (&zebrad, rn);
! 1989: }
! 1990: else
! 1991: {
! 1992: /* This is new static route. */
! 1993: rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
! 1994:
! 1995: rib->type = ZEBRA_ROUTE_STATIC;
! 1996: rib->distance = si->distance;
! 1997: rib->metric = 0;
! 1998: rib->nexthop_num = 0;
! 1999:
! 2000: switch (si->type)
! 2001: {
! 2002: case STATIC_IPV4_GATEWAY:
! 2003: nexthop_ipv4_add (rib, &si->gate.ipv4, NULL);
! 2004: break;
! 2005: case STATIC_IPV4_IFNAME:
! 2006: nexthop_ifname_add (rib, si->gate.ifname);
! 2007: break;
! 2008: case STATIC_IPV4_BLACKHOLE:
! 2009: nexthop_blackhole_add (rib);
! 2010: break;
! 2011: }
! 2012:
! 2013: /* Save the flags of this static routes (reject, blackhole) */
! 2014: rib->flags = si->flags;
! 2015:
! 2016: /* Link this rib to the tree. */
! 2017: rib_addnode (rn, rib);
! 2018: }
! 2019: }
! 2020:
! 2021: static int
! 2022: static_ipv4_nexthop_same (struct nexthop *nexthop, struct static_ipv4 *si)
! 2023: {
! 2024: if (nexthop->type == NEXTHOP_TYPE_IPV4
! 2025: && si->type == STATIC_IPV4_GATEWAY
! 2026: && IPV4_ADDR_SAME (&nexthop->gate.ipv4, &si->gate.ipv4))
! 2027: return 1;
! 2028: if (nexthop->type == NEXTHOP_TYPE_IFNAME
! 2029: && si->type == STATIC_IPV4_IFNAME
! 2030: && strcmp (nexthop->ifname, si->gate.ifname) == 0)
! 2031: return 1;
! 2032: if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE
! 2033: && si->type == STATIC_IPV4_BLACKHOLE)
! 2034: return 1;
! 2035: return 0;
! 2036: }
! 2037:
! 2038: /* Uninstall static route from RIB. */
! 2039: static void
! 2040: static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si)
! 2041: {
! 2042: struct route_node *rn;
! 2043: struct rib *rib;
! 2044: struct nexthop *nexthop;
! 2045: struct route_table *table;
! 2046:
! 2047: /* Lookup table. */
! 2048: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 2049: if (! table)
! 2050: return;
! 2051:
! 2052: /* Lookup existing route with type and distance. */
! 2053: rn = route_node_lookup (table, p);
! 2054: if (! rn)
! 2055: return;
! 2056:
! 2057: for (rib = rn->info; rib; rib = rib->next)
! 2058: {
! 2059: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 2060: continue;
! 2061:
! 2062: if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
! 2063: break;
! 2064: }
! 2065:
! 2066: if (! rib)
! 2067: {
! 2068: route_unlock_node (rn);
! 2069: return;
! 2070: }
! 2071:
! 2072: /* Lookup nexthop. */
! 2073: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 2074: if (static_ipv4_nexthop_same (nexthop, si))
! 2075: break;
! 2076:
! 2077: /* Can't find nexthop. */
! 2078: if (! nexthop)
! 2079: {
! 2080: route_unlock_node (rn);
! 2081: return;
! 2082: }
! 2083:
! 2084: /* Check nexthop. */
! 2085: if (rib->nexthop_num == 1)
! 2086: rib_delnode (rn, rib);
! 2087: else
! 2088: {
! 2089: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
! 2090: rib_uninstall (rn, rib);
! 2091: nexthop_delete (rib, nexthop);
! 2092: nexthop_free (nexthop);
! 2093: rib_queue_add (&zebrad, rn);
! 2094: }
! 2095: /* Unlock node. */
! 2096: route_unlock_node (rn);
! 2097: }
! 2098:
! 2099: /* Add static route into static route configuration. */
! 2100: int
! 2101: static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
! 2102: u_char flags, u_char distance, u_int32_t vrf_id)
! 2103: {
! 2104: u_char type = 0;
! 2105: struct route_node *rn;
! 2106: struct static_ipv4 *si;
! 2107: struct static_ipv4 *pp;
! 2108: struct static_ipv4 *cp;
! 2109: struct static_ipv4 *update = NULL;
! 2110: struct route_table *stable;
! 2111:
! 2112: /* Lookup table. */
! 2113: stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
! 2114: if (! stable)
! 2115: return -1;
! 2116:
! 2117: /* Lookup static route prefix. */
! 2118: rn = route_node_get (stable, p);
! 2119:
! 2120: /* Make flags. */
! 2121: if (gate)
! 2122: type = STATIC_IPV4_GATEWAY;
! 2123: else if (ifname)
! 2124: type = STATIC_IPV4_IFNAME;
! 2125: else
! 2126: type = STATIC_IPV4_BLACKHOLE;
! 2127:
! 2128: /* Do nothing if there is a same static route. */
! 2129: for (si = rn->info; si; si = si->next)
! 2130: {
! 2131: if (type == si->type
! 2132: && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
! 2133: && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
! 2134: {
! 2135: if (distance == si->distance)
! 2136: {
! 2137: route_unlock_node (rn);
! 2138: return 0;
! 2139: }
! 2140: else
! 2141: update = si;
! 2142: }
! 2143: }
! 2144:
! 2145: /* Distance changed. */
! 2146: if (update)
! 2147: static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id);
! 2148:
! 2149: /* Make new static route structure. */
! 2150: si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4));
! 2151:
! 2152: si->type = type;
! 2153: si->distance = distance;
! 2154: si->flags = flags;
! 2155:
! 2156: if (gate)
! 2157: si->gate.ipv4 = *gate;
! 2158: if (ifname)
! 2159: si->gate.ifname = XSTRDUP (0, ifname);
! 2160:
! 2161: /* Add new static route information to the tree with sort by
! 2162: distance value and gateway address. */
! 2163: for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
! 2164: {
! 2165: if (si->distance < cp->distance)
! 2166: break;
! 2167: if (si->distance > cp->distance)
! 2168: continue;
! 2169: if (si->type == STATIC_IPV4_GATEWAY && cp->type == STATIC_IPV4_GATEWAY)
! 2170: {
! 2171: if (ntohl (si->gate.ipv4.s_addr) < ntohl (cp->gate.ipv4.s_addr))
! 2172: break;
! 2173: if (ntohl (si->gate.ipv4.s_addr) > ntohl (cp->gate.ipv4.s_addr))
! 2174: continue;
! 2175: }
! 2176: }
! 2177:
! 2178: /* Make linked list. */
! 2179: if (pp)
! 2180: pp->next = si;
! 2181: else
! 2182: rn->info = si;
! 2183: if (cp)
! 2184: cp->prev = si;
! 2185: si->prev = pp;
! 2186: si->next = cp;
! 2187:
! 2188: /* Install into rib. */
! 2189: static_install_ipv4 (p, si);
! 2190:
! 2191: return 1;
! 2192: }
! 2193:
! 2194: /* Delete static route from static route configuration. */
! 2195: int
! 2196: static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
! 2197: u_char distance, u_int32_t vrf_id)
! 2198: {
! 2199: u_char type = 0;
! 2200: struct route_node *rn;
! 2201: struct static_ipv4 *si;
! 2202: struct route_table *stable;
! 2203:
! 2204: /* Lookup table. */
! 2205: stable = vrf_static_table (AFI_IP, SAFI_UNICAST, vrf_id);
! 2206: if (! stable)
! 2207: return -1;
! 2208:
! 2209: /* Lookup static route prefix. */
! 2210: rn = route_node_lookup (stable, p);
! 2211: if (! rn)
! 2212: return 0;
! 2213:
! 2214: /* Make flags. */
! 2215: if (gate)
! 2216: type = STATIC_IPV4_GATEWAY;
! 2217: else if (ifname)
! 2218: type = STATIC_IPV4_IFNAME;
! 2219: else
! 2220: type = STATIC_IPV4_BLACKHOLE;
! 2221:
! 2222: /* Find same static route is the tree */
! 2223: for (si = rn->info; si; si = si->next)
! 2224: if (type == si->type
! 2225: && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4))
! 2226: && (! ifname || strcmp (ifname, si->gate.ifname) == 0))
! 2227: break;
! 2228:
! 2229: /* Can't find static route. */
! 2230: if (! si)
! 2231: {
! 2232: route_unlock_node (rn);
! 2233: return 0;
! 2234: }
! 2235:
! 2236: /* Install into rib. */
! 2237: static_uninstall_ipv4 (p, si);
! 2238:
! 2239: /* Unlink static route from linked list. */
! 2240: if (si->prev)
! 2241: si->prev->next = si->next;
! 2242: else
! 2243: rn->info = si->next;
! 2244: if (si->next)
! 2245: si->next->prev = si->prev;
! 2246: route_unlock_node (rn);
! 2247:
! 2248: /* Free static route configuration. */
! 2249: if (ifname)
! 2250: XFREE (0, si->gate.ifname);
! 2251: XFREE (MTYPE_STATIC_IPV4, si);
! 2252:
! 2253: route_unlock_node (rn);
! 2254:
! 2255: return 1;
! 2256: }
! 2257:
! 2258:
! 2259: #ifdef HAVE_IPV6
! 2260: static int
! 2261: rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
! 2262: struct in6_addr *gate, unsigned int ifindex, int table)
! 2263: {
! 2264: if (type == ZEBRA_ROUTE_CONNECT && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)) {
! 2265: #if defined (MUSICA) || defined (LINUX)
! 2266: /* IN6_IS_ADDR_V4COMPAT(&p->prefix) */
! 2267: if (p->prefixlen == 96)
! 2268: return 0;
! 2269: #endif /* MUSICA */
! 2270: return 1;
! 2271: }
! 2272: if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix)
! 2273: && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate))
! 2274: {
! 2275: kernel_delete_ipv6_old (p, gate, ifindex, 0, table);
! 2276: return 1;
! 2277: }
! 2278: return 0;
! 2279: }
! 2280:
! 2281: int
! 2282: rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
! 2283: struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
! 2284: u_int32_t metric, u_char distance)
! 2285: {
! 2286: struct rib *rib;
! 2287: struct rib *same = NULL;
! 2288: struct route_table *table;
! 2289: struct route_node *rn;
! 2290: struct nexthop *nexthop;
! 2291:
! 2292: /* Lookup table. */
! 2293: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 2294: if (! table)
! 2295: return 0;
! 2296:
! 2297: /* Make sure mask is applied. */
! 2298: apply_mask_ipv6 (p);
! 2299:
! 2300: /* Set default distance by route type. */
! 2301: if (!distance)
! 2302: distance = route_info[type].distance;
! 2303:
! 2304: if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
! 2305: distance = 200;
! 2306:
! 2307: /* Filter bogus route. */
! 2308: if (rib_bogus_ipv6 (type, p, gate, ifindex, 0))
! 2309: return 0;
! 2310:
! 2311: /* Lookup route node.*/
! 2312: rn = route_node_get (table, (struct prefix *) p);
! 2313:
! 2314: /* If same type of route are installed, treat it as a implicit
! 2315: withdraw. */
! 2316: for (rib = rn->info; rib; rib = rib->next)
! 2317: {
! 2318: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 2319: continue;
! 2320:
! 2321: if (rib->type != type)
! 2322: continue;
! 2323: if (rib->type != ZEBRA_ROUTE_CONNECT)
! 2324: {
! 2325: same = rib;
! 2326: break;
! 2327: }
! 2328: else if ((nexthop = rib->nexthop) &&
! 2329: nexthop->type == NEXTHOP_TYPE_IFINDEX &&
! 2330: nexthop->ifindex == ifindex)
! 2331: {
! 2332: rib->refcnt++;
! 2333: return 0;
! 2334: }
! 2335: }
! 2336:
! 2337: /* Allocate new rib structure. */
! 2338: rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
! 2339:
! 2340: rib->type = type;
! 2341: rib->distance = distance;
! 2342: rib->flags = flags;
! 2343: rib->metric = metric;
! 2344: rib->table = vrf_id;
! 2345: rib->nexthop_num = 0;
! 2346: rib->uptime = time (NULL);
! 2347:
! 2348: /* Nexthop settings. */
! 2349: if (gate)
! 2350: {
! 2351: if (ifindex)
! 2352: nexthop_ipv6_ifindex_add (rib, gate, ifindex);
! 2353: else
! 2354: nexthop_ipv6_add (rib, gate);
! 2355: }
! 2356: else
! 2357: nexthop_ifindex_add (rib, ifindex);
! 2358:
! 2359: /* If this route is kernel route, set FIB flag to the route. */
! 2360: if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
! 2361: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 2362: SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 2363:
! 2364: /* Link new rib to node.*/
! 2365: rib_addnode (rn, rib);
! 2366:
! 2367: /* Free implicit route.*/
! 2368: if (same)
! 2369: rib_delnode (rn, same);
! 2370:
! 2371: route_unlock_node (rn);
! 2372: return 0;
! 2373: }
! 2374:
! 2375: /* XXX factor with rib_delete_ipv6 */
! 2376: int
! 2377: rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
! 2378: struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id)
! 2379: {
! 2380: struct route_table *table;
! 2381: struct route_node *rn;
! 2382: struct rib *rib;
! 2383: struct rib *fib = NULL;
! 2384: struct rib *same = NULL;
! 2385: struct nexthop *nexthop;
! 2386: char buf1[INET6_ADDRSTRLEN];
! 2387: char buf2[INET6_ADDRSTRLEN];
! 2388:
! 2389: /* Apply mask. */
! 2390: apply_mask_ipv6 (p);
! 2391:
! 2392: /* Lookup table. */
! 2393: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 2394: if (! table)
! 2395: return 0;
! 2396:
! 2397: /* Lookup route node. */
! 2398: rn = route_node_lookup (table, (struct prefix *) p);
! 2399: if (! rn)
! 2400: {
! 2401: if (IS_ZEBRA_DEBUG_KERNEL)
! 2402: {
! 2403: if (gate)
! 2404: zlog_debug ("route %s/%d via %s ifindex %d doesn't exist in rib",
! 2405: inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
! 2406: p->prefixlen,
! 2407: inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
! 2408: ifindex);
! 2409: else
! 2410: zlog_debug ("route %s/%d ifindex %d doesn't exist in rib",
! 2411: inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
! 2412: p->prefixlen,
! 2413: ifindex);
! 2414: }
! 2415: return ZEBRA_ERR_RTNOEXIST;
! 2416: }
! 2417:
! 2418: /* Lookup same type route. */
! 2419: for (rib = rn->info; rib; rib = rib->next)
! 2420: {
! 2421: if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
! 2422: continue;
! 2423:
! 2424: if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
! 2425: fib = rib;
! 2426:
! 2427: if (rib->type != type)
! 2428: continue;
! 2429: if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) &&
! 2430: nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex)
! 2431: {
! 2432: if (rib->refcnt)
! 2433: {
! 2434: rib->refcnt--;
! 2435: route_unlock_node (rn);
! 2436: route_unlock_node (rn);
! 2437: return 0;
! 2438: }
! 2439: same = rib;
! 2440: break;
! 2441: }
! 2442: /* Make sure that the route found has the same gateway. */
! 2443: else if (gate == NULL ||
! 2444: ((nexthop = rib->nexthop) &&
! 2445: (IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate) ||
! 2446: IPV6_ADDR_SAME (&nexthop->rgate.ipv6, gate))))
! 2447: {
! 2448: same = rib;
! 2449: break;
! 2450: }
! 2451: }
! 2452:
! 2453: /* If same type of route can't be found and this message is from
! 2454: kernel. */
! 2455: if (! same)
! 2456: {
! 2457: if (fib && type == ZEBRA_ROUTE_KERNEL)
! 2458: {
! 2459: /* Unset flags. */
! 2460: for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
! 2461: UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
! 2462:
! 2463: UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
! 2464: }
! 2465: else
! 2466: {
! 2467: if (IS_ZEBRA_DEBUG_KERNEL)
! 2468: {
! 2469: if (gate)
! 2470: zlog_debug ("route %s/%d via %s ifindex %d type %d doesn't exist in rib",
! 2471: inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
! 2472: p->prefixlen,
! 2473: inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
! 2474: ifindex,
! 2475: type);
! 2476: else
! 2477: zlog_debug ("route %s/%d ifindex %d type %d doesn't exist in rib",
! 2478: inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
! 2479: p->prefixlen,
! 2480: ifindex,
! 2481: type);
! 2482: }
! 2483: route_unlock_node (rn);
! 2484: return ZEBRA_ERR_RTNOEXIST;
! 2485: }
! 2486: }
! 2487:
! 2488: if (same)
! 2489: rib_delnode (rn, same);
! 2490:
! 2491: route_unlock_node (rn);
! 2492: return 0;
! 2493: }
! 2494:
! 2495: /* Install static route into rib. */
! 2496: static void
! 2497: static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
! 2498: {
! 2499: struct rib *rib;
! 2500: struct route_table *table;
! 2501: struct route_node *rn;
! 2502:
! 2503: /* Lookup table. */
! 2504: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 2505: if (! table)
! 2506: return;
! 2507:
! 2508: /* Lookup existing route */
! 2509: rn = route_node_get (table, p);
! 2510: for (rib = rn->info; rib; rib = rib->next)
! 2511: {
! 2512: if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED))
! 2513: continue;
! 2514:
! 2515: if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
! 2516: break;
! 2517: }
! 2518:
! 2519: if (rib)
! 2520: {
! 2521: /* Same distance static route is there. Update it with new
! 2522: nexthop. */
! 2523: route_unlock_node (rn);
! 2524:
! 2525: switch (si->type)
! 2526: {
! 2527: case STATIC_IPV6_GATEWAY:
! 2528: nexthop_ipv6_add (rib, &si->ipv6);
! 2529: break;
! 2530: case STATIC_IPV6_IFNAME:
! 2531: nexthop_ifname_add (rib, si->ifname);
! 2532: break;
! 2533: case STATIC_IPV6_GATEWAY_IFNAME:
! 2534: nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
! 2535: break;
! 2536: }
! 2537: rib_queue_add (&zebrad, rn);
! 2538: }
! 2539: else
! 2540: {
! 2541: /* This is new static route. */
! 2542: rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
! 2543:
! 2544: rib->type = ZEBRA_ROUTE_STATIC;
! 2545: rib->distance = si->distance;
! 2546: rib->metric = 0;
! 2547: rib->nexthop_num = 0;
! 2548:
! 2549: switch (si->type)
! 2550: {
! 2551: case STATIC_IPV6_GATEWAY:
! 2552: nexthop_ipv6_add (rib, &si->ipv6);
! 2553: break;
! 2554: case STATIC_IPV6_IFNAME:
! 2555: nexthop_ifname_add (rib, si->ifname);
! 2556: break;
! 2557: case STATIC_IPV6_GATEWAY_IFNAME:
! 2558: nexthop_ipv6_ifname_add (rib, &si->ipv6, si->ifname);
! 2559: break;
! 2560: }
! 2561:
! 2562: /* Save the flags of this static routes (reject, blackhole) */
! 2563: rib->flags = si->flags;
! 2564:
! 2565: /* Link this rib to the tree. */
! 2566: rib_addnode (rn, rib);
! 2567: }
! 2568: }
! 2569:
! 2570: static int
! 2571: static_ipv6_nexthop_same (struct nexthop *nexthop, struct static_ipv6 *si)
! 2572: {
! 2573: if (nexthop->type == NEXTHOP_TYPE_IPV6
! 2574: && si->type == STATIC_IPV6_GATEWAY
! 2575: && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6))
! 2576: return 1;
! 2577: if (nexthop->type == NEXTHOP_TYPE_IFNAME
! 2578: && si->type == STATIC_IPV6_IFNAME
! 2579: && strcmp (nexthop->ifname, si->ifname) == 0)
! 2580: return 1;
! 2581: if (nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
! 2582: && si->type == STATIC_IPV6_GATEWAY_IFNAME
! 2583: && IPV6_ADDR_SAME (&nexthop->gate.ipv6, &si->ipv6)
! 2584: && strcmp (nexthop->ifname, si->ifname) == 0)
! 2585: return 1;
! 2586: return 0;
! 2587: }
! 2588:
! 2589: static void
! 2590: static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
! 2591: {
! 2592: struct route_table *table;
! 2593: struct route_node *rn;
! 2594: struct rib *rib;
! 2595: struct nexthop *nexthop;
! 2596:
! 2597: /* Lookup table. */
! 2598: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 2599: if (! table)
! 2600: return;
! 2601:
! 2602: /* Lookup existing route with type and distance. */
! 2603: rn = route_node_lookup (table, (struct prefix *) p);
! 2604: if (! rn)
! 2605: return;
! 2606:
! 2607: for (rib = rn->info; rib; rib = rib->next)
! 2608: {
! 2609: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 2610: continue;
! 2611:
! 2612: if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance)
! 2613: break;
! 2614: }
! 2615:
! 2616: if (! rib)
! 2617: {
! 2618: route_unlock_node (rn);
! 2619: return;
! 2620: }
! 2621:
! 2622: /* Lookup nexthop. */
! 2623: for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
! 2624: if (static_ipv6_nexthop_same (nexthop, si))
! 2625: break;
! 2626:
! 2627: /* Can't find nexthop. */
! 2628: if (! nexthop)
! 2629: {
! 2630: route_unlock_node (rn);
! 2631: return;
! 2632: }
! 2633:
! 2634: /* Check nexthop. */
! 2635: if (rib->nexthop_num == 1)
! 2636: {
! 2637: rib_delnode (rn, rib);
! 2638: }
! 2639: else
! 2640: {
! 2641: if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
! 2642: rib_uninstall (rn, rib);
! 2643: nexthop_delete (rib, nexthop);
! 2644: nexthop_free (nexthop);
! 2645: rib_queue_add (&zebrad, rn);
! 2646: }
! 2647: /* Unlock node. */
! 2648: route_unlock_node (rn);
! 2649: }
! 2650:
! 2651: /* Add static route into static route configuration. */
! 2652: int
! 2653: static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
! 2654: const char *ifname, u_char flags, u_char distance,
! 2655: u_int32_t vrf_id)
! 2656: {
! 2657: struct route_node *rn;
! 2658: struct static_ipv6 *si;
! 2659: struct static_ipv6 *pp;
! 2660: struct static_ipv6 *cp;
! 2661: struct route_table *stable;
! 2662:
! 2663: /* Lookup table. */
! 2664: stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
! 2665: if (! stable)
! 2666: return -1;
! 2667:
! 2668: if (!gate &&
! 2669: (type == STATIC_IPV6_GATEWAY || type == STATIC_IPV6_GATEWAY_IFNAME))
! 2670: return -1;
! 2671:
! 2672: if (!ifname &&
! 2673: (type == STATIC_IPV6_GATEWAY_IFNAME || type == STATIC_IPV6_IFNAME))
! 2674: return -1;
! 2675:
! 2676: /* Lookup static route prefix. */
! 2677: rn = route_node_get (stable, p);
! 2678:
! 2679: /* Do nothing if there is a same static route. */
! 2680: for (si = rn->info; si; si = si->next)
! 2681: {
! 2682: if (distance == si->distance
! 2683: && type == si->type
! 2684: && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
! 2685: && (! ifname || strcmp (ifname, si->ifname) == 0))
! 2686: {
! 2687: route_unlock_node (rn);
! 2688: return 0;
! 2689: }
! 2690: }
! 2691:
! 2692: /* Make new static route structure. */
! 2693: si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6));
! 2694:
! 2695: si->type = type;
! 2696: si->distance = distance;
! 2697: si->flags = flags;
! 2698:
! 2699: switch (type)
! 2700: {
! 2701: case STATIC_IPV6_GATEWAY:
! 2702: si->ipv6 = *gate;
! 2703: break;
! 2704: case STATIC_IPV6_IFNAME:
! 2705: si->ifname = XSTRDUP (0, ifname);
! 2706: break;
! 2707: case STATIC_IPV6_GATEWAY_IFNAME:
! 2708: si->ipv6 = *gate;
! 2709: si->ifname = XSTRDUP (0, ifname);
! 2710: break;
! 2711: }
! 2712:
! 2713: /* Add new static route information to the tree with sort by
! 2714: distance value and gateway address. */
! 2715: for (pp = NULL, cp = rn->info; cp; pp = cp, cp = cp->next)
! 2716: {
! 2717: if (si->distance < cp->distance)
! 2718: break;
! 2719: if (si->distance > cp->distance)
! 2720: continue;
! 2721: }
! 2722:
! 2723: /* Make linked list. */
! 2724: if (pp)
! 2725: pp->next = si;
! 2726: else
! 2727: rn->info = si;
! 2728: if (cp)
! 2729: cp->prev = si;
! 2730: si->prev = pp;
! 2731: si->next = cp;
! 2732:
! 2733: /* Install into rib. */
! 2734: static_install_ipv6 (p, si);
! 2735:
! 2736: return 1;
! 2737: }
! 2738:
! 2739: /* Delete static route from static route configuration. */
! 2740: int
! 2741: static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
! 2742: const char *ifname, u_char distance, u_int32_t vrf_id)
! 2743: {
! 2744: struct route_node *rn;
! 2745: struct static_ipv6 *si;
! 2746: struct route_table *stable;
! 2747:
! 2748: /* Lookup table. */
! 2749: stable = vrf_static_table (AFI_IP6, SAFI_UNICAST, vrf_id);
! 2750: if (! stable)
! 2751: return -1;
! 2752:
! 2753: /* Lookup static route prefix. */
! 2754: rn = route_node_lookup (stable, p);
! 2755: if (! rn)
! 2756: return 0;
! 2757:
! 2758: /* Find same static route is the tree */
! 2759: for (si = rn->info; si; si = si->next)
! 2760: if (distance == si->distance
! 2761: && type == si->type
! 2762: && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6))
! 2763: && (! ifname || strcmp (ifname, si->ifname) == 0))
! 2764: break;
! 2765:
! 2766: /* Can't find static route. */
! 2767: if (! si)
! 2768: {
! 2769: route_unlock_node (rn);
! 2770: return 0;
! 2771: }
! 2772:
! 2773: /* Install into rib. */
! 2774: static_uninstall_ipv6 (p, si);
! 2775:
! 2776: /* Unlink static route from linked list. */
! 2777: if (si->prev)
! 2778: si->prev->next = si->next;
! 2779: else
! 2780: rn->info = si->next;
! 2781: if (si->next)
! 2782: si->next->prev = si->prev;
! 2783:
! 2784: /* Free static route configuration. */
! 2785: if (ifname)
! 2786: XFREE (0, si->ifname);
! 2787: XFREE (MTYPE_STATIC_IPV6, si);
! 2788:
! 2789: return 1;
! 2790: }
! 2791: #endif /* HAVE_IPV6 */
! 2792:
! 2793: /* RIB update function. */
! 2794: void
! 2795: rib_update (void)
! 2796: {
! 2797: struct route_node *rn;
! 2798: struct route_table *table;
! 2799:
! 2800: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
! 2801: if (table)
! 2802: for (rn = route_top (table); rn; rn = route_next (rn))
! 2803: if (rn->info)
! 2804: rib_queue_add (&zebrad, rn);
! 2805:
! 2806: table = vrf_table (AFI_IP6, SAFI_UNICAST, 0);
! 2807: if (table)
! 2808: for (rn = route_top (table); rn; rn = route_next (rn))
! 2809: if (rn->info)
! 2810: rib_queue_add (&zebrad, rn);
! 2811: }
! 2812:
! 2813:
! 2814: /* Remove all routes which comes from non main table. */
! 2815: static void
! 2816: rib_weed_table (struct route_table *table)
! 2817: {
! 2818: struct route_node *rn;
! 2819: struct rib *rib;
! 2820: struct rib *next;
! 2821:
! 2822: if (table)
! 2823: for (rn = route_top (table); rn; rn = route_next (rn))
! 2824: for (rib = rn->info; rib; rib = next)
! 2825: {
! 2826: next = rib->next;
! 2827:
! 2828: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 2829: continue;
! 2830:
! 2831: if (rib->table != zebrad.rtm_table_default &&
! 2832: rib->table != RT_TABLE_MAIN)
! 2833: rib_delnode (rn, rib);
! 2834: }
! 2835: }
! 2836:
! 2837: /* Delete all routes from non main table. */
! 2838: void
! 2839: rib_weed_tables (void)
! 2840: {
! 2841: rib_weed_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
! 2842: rib_weed_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
! 2843: }
! 2844:
! 2845: /* Delete self installed routes after zebra is relaunched. */
! 2846: static void
! 2847: rib_sweep_table (struct route_table *table)
! 2848: {
! 2849: struct route_node *rn;
! 2850: struct rib *rib;
! 2851: struct rib *next;
! 2852: int ret = 0;
! 2853:
! 2854: if (table)
! 2855: for (rn = route_top (table); rn; rn = route_next (rn))
! 2856: for (rib = rn->info; rib; rib = next)
! 2857: {
! 2858: next = rib->next;
! 2859:
! 2860: if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
! 2861: continue;
! 2862:
! 2863: if (rib->type == ZEBRA_ROUTE_KERNEL &&
! 2864: CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELFROUTE))
! 2865: {
! 2866: ret = rib_uninstall_kernel (rn, rib);
! 2867: if (! ret)
! 2868: rib_delnode (rn, rib);
! 2869: }
! 2870: }
! 2871: }
! 2872:
! 2873: /* Sweep all RIB tables. */
! 2874: void
! 2875: rib_sweep_route (void)
! 2876: {
! 2877: rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
! 2878: rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
! 2879: }
! 2880:
! 2881: /* Close RIB and clean up kernel routes. */
! 2882: static void
! 2883: rib_close_table (struct route_table *table)
! 2884: {
! 2885: struct route_node *rn;
! 2886: struct rib *rib;
! 2887:
! 2888: if (table)
! 2889: for (rn = route_top (table); rn; rn = route_next (rn))
! 2890: for (rib = rn->info; rib; rib = rib->next)
! 2891: {
! 2892: if (! RIB_SYSTEM_ROUTE (rib)
! 2893: && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
! 2894: rib_uninstall_kernel (rn, rib);
! 2895: }
! 2896: }
! 2897:
! 2898: /* Close all RIB tables. */
! 2899: void
! 2900: rib_close (void)
! 2901: {
! 2902: rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
! 2903: rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
! 2904: }
! 2905:
! 2906: /* Routing information base initialize. */
! 2907: void
! 2908: rib_init (void)
! 2909: {
! 2910: rib_queue_init (&zebrad);
! 2911: /* VRF initialization. */
! 2912: vrf_init ();
! 2913: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>