Annotation of embedaddon/pimdd/route.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 1998 by the University of Oregon.
! 3: * All rights reserved.
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software and
! 6: * its documentation in source and binary forms for lawful
! 7: * purposes and without fee is hereby granted, provided
! 8: * that the above copyright notice appear in all copies and that both
! 9: * the copyright notice and this permission notice appear in supporting
! 10: * documentation, and that any documentation, advertising materials,
! 11: * and other materials related to such distribution and use acknowledge
! 12: * that the software was developed by the University of Oregon.
! 13: * The name of the University of Oregon may not be used to endorse or
! 14: * promote products derived from this software without specific prior
! 15: * written permission.
! 16: *
! 17: * THE UNIVERSITY OF OREGON DOES NOT MAKE ANY REPRESENTATIONS
! 18: * ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
! 19: * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
! 20: * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
! 21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
! 22: * NON-INFRINGEMENT.
! 23: *
! 24: * IN NO EVENT SHALL UO, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
! 25: * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
! 26: * TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
! 27: * THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 28: *
! 29: * Other copyrights might apply to parts of this software and are so
! 30: * noted when applicable.
! 31: */
! 32: /*
! 33: * Questions concerning this software should be directed to
! 34: * Kurt Windisch (kurtw@antc.uoregon.edu)
! 35: *
! 36: * $Id: route.c,v 1.27 1998/12/30 20:26:21 kurtw Exp $
! 37: */
! 38: /*
! 39: * Part of this program has been derived from PIM sparse-mode pimd.
! 40: * The pimd program is covered by the license in the accompanying file
! 41: * named "LICENSE.pimd".
! 42: *
! 43: * The pimd program is COPYRIGHT 1998 by University of Southern California.
! 44: *
! 45: * Part of this program has been derived from mrouted.
! 46: * The mrouted program is covered by the license in the accompanying file
! 47: * named "LICENSE.mrouted".
! 48: *
! 49: * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
! 50: * Leland Stanford Junior University.
! 51: *
! 52: */
! 53:
! 54: #include "defs.h"
! 55:
! 56:
! 57: static void process_cache_miss __P((struct igmpmsg *igmpctl));
! 58: static void process_wrong_iif __P((struct igmpmsg *igmpctl));
! 59:
! 60: u_int32 default_source_preference = DEFAULT_LOCAL_PREF;
! 61: u_int32 default_source_metric = DEFAULT_LOCAL_METRIC;
! 62:
! 63: /* Return the iif for given address */
! 64: vifi_t
! 65: get_iif(address)
! 66: u_int32 address;
! 67: {
! 68: struct rpfctl rpfc;
! 69:
! 70: k_req_incoming(address, &rpfc);
! 71: if (rpfc.rpfneighbor.s_addr == INADDR_ANY_N)
! 72: return (NO_VIF);
! 73: return (rpfc.iif);
! 74: }
! 75:
! 76: /* Return the PIM neighbor toward a source */
! 77: /* If route not found or if a local source or if a directly connected source,
! 78: * but is not PIM router, or if the first hop router is not a PIM router,
! 79: * then return NULL.
! 80: */
! 81: pim_nbr_entry_t *
! 82: find_pim_nbr(source)
! 83: u_int32 source;
! 84: {
! 85: struct rpfctl rpfc;
! 86: pim_nbr_entry_t *pim_nbr;
! 87: u_int32 next_hop_router_addr;
! 88:
! 89: if (local_address(source) != NO_VIF)
! 90: return (pim_nbr_entry_t *)NULL;
! 91: k_req_incoming(source, &rpfc);
! 92: if ((rpfc.rpfneighbor.s_addr == INADDR_ANY_N)
! 93: || (rpfc.iif == NO_VIF))
! 94: return (pim_nbr_entry_t *)NULL;
! 95: next_hop_router_addr = rpfc.rpfneighbor.s_addr;
! 96: for (pim_nbr = uvifs[rpfc.iif].uv_pim_neighbors;
! 97: pim_nbr != (pim_nbr_entry_t *)NULL;
! 98: pim_nbr = pim_nbr->next)
! 99: if (pim_nbr->address == next_hop_router_addr)
! 100: return(pim_nbr);
! 101: return (pim_nbr_entry_t *)NULL;
! 102: }
! 103:
! 104:
! 105: /* TODO: check again the exact setup if the source is local or directly
! 106: * connected!!!
! 107: */
! 108: /* TODO: XXX: change the metric and preference for all (S,G) entries per
! 109: * source?
! 110: */
! 111: /* PIMDM TODO - If possible, this would be the place to correct set the
! 112: * source's preference and metric to that obtained from the kernel
! 113: * and/or unicast routing protocol. For now, set it to the configured
! 114: * default for local pref/metric.
! 115: */
! 116: /*
! 117: * Set the iif, upstream router, preference and metric for the route
! 118: * toward the source. Return TRUE is the route was found, othewise FALSE.
! 119: * If srctype==PIM_IIF_SOURCE and if the source is directly connected
! 120: * then the "upstream" is set to NULL.
! 121: * Note that srctype is a hold-over from the PIM-SM daemon and is unused.
! 122: */
! 123: int
! 124: set_incoming(srcentry_ptr, srctype)
! 125: srcentry_t *srcentry_ptr;
! 126: int srctype;
! 127: {
! 128: struct rpfctl rpfc;
! 129: u_int32 source = srcentry_ptr->address;
! 130: u_int32 neighbor_addr;
! 131: register struct uvif *v;
! 132: register pim_nbr_entry_t *n;
! 133:
! 134: /* Preference will be 0 if directly connected */
! 135: srcentry_ptr->preference = 0;
! 136: srcentry_ptr->metric = 0;
! 137:
! 138: if ((srcentry_ptr->incoming = local_address(source)) != NO_VIF) {
! 139: /* The source is a local address */
! 140: /* TODO: set the upstream to myself? */
! 141: srcentry_ptr->upstream = (pim_nbr_entry_t *)NULL;
! 142: return (TRUE);
! 143: }
! 144:
! 145: if ((srcentry_ptr->incoming = find_vif_direct(source)) == NO_VIF) {
! 146: /* TODO: probably need to check the case if the iif is disabled */
! 147: /* Use the lastest resource: the kernel unicast routing table */
! 148: k_req_incoming(source, &rpfc);
! 149: if ((rpfc.iif == NO_VIF) ||
! 150: rpfc.rpfneighbor.s_addr == INADDR_ANY_N) {
! 151: /* couldn't find a route */
! 152: IF_DEBUG(DEBUG_PIM_MRT | DEBUG_RPF)
! 153: log(LOG_DEBUG, 0, "NO ROUTE found for %s",
! 154: inet_fmt(source, s1));
! 155: return(FALSE);
! 156: }
! 157: srcentry_ptr->incoming = rpfc.iif;
! 158: neighbor_addr = rpfc.rpfneighbor.s_addr;
! 159: }
! 160: else {
! 161: /* The source is directly connected.
! 162: */
! 163: srcentry_ptr->upstream = (pim_nbr_entry_t *)NULL;
! 164: return (TRUE);
! 165: }
! 166:
! 167: /* set the preference for sources that aren't directly connected. */
! 168: v = &uvifs[srcentry_ptr->incoming];
! 169: srcentry_ptr->preference = v->uv_local_pref;
! 170: srcentry_ptr->metric = v->uv_local_metric;
! 171:
! 172: /*
! 173: * The upstream router must be a (PIM router) neighbor, otherwise we
! 174: * are in big trouble ;-)
! 175: */
! 176: for (n = v->uv_pim_neighbors; n != NULL; n = n->next) {
! 177: if (ntohl(neighbor_addr) < ntohl(n->address))
! 178: continue;
! 179: if (neighbor_addr == n->address) {
! 180: /*
! 181: *The upstream router is found in the list of neighbors.
! 182: * We are safe!
! 183: */
! 184: srcentry_ptr->upstream = n;
! 185: IF_DEBUG(DEBUG_RPF)
! 186: log(LOG_DEBUG, 0,
! 187: "For src %s, iif is %d, next hop router is %s",
! 188: inet_fmt(source, s1), srcentry_ptr->incoming,
! 189: inet_fmt(neighbor_addr, s2));
! 190: return(TRUE);
! 191: }
! 192: else break;
! 193: }
! 194:
! 195: /* TODO: control the number of messages! */
! 196: log(LOG_INFO, 0,
! 197: "For src %s, iif is %d, next hop router is %s: NOT A PIM ROUTER",
! 198: inet_fmt(source, s1), srcentry_ptr->incoming,
! 199: inet_fmt(neighbor_addr, s2));
! 200: srcentry_ptr->upstream = (pim_nbr_entry_t *)NULL;
! 201:
! 202: return(FALSE);
! 203: }
! 204:
! 205:
! 206: /* Set the leaves in a new mrtentry */
! 207: void set_leaves(mrtentry_ptr)
! 208: mrtentry_t *mrtentry_ptr;
! 209: {
! 210: vifi_t vifi;
! 211: struct uvif *v;
! 212:
! 213: /* Check for a group report on each vif */
! 214: for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v)
! 215: if(check_grp_membership(v, mrtentry_ptr->group->group))
! 216: VIFM_SET(vifi, mrtentry_ptr->leaves);
! 217: }
! 218:
! 219:
! 220: /* Handle new receiver
! 221: *
! 222: * TODO: XXX: currently `source` is not used. Will be used with IGMPv3 where
! 223: * we have source-specific Join/Prune.
! 224: */
! 225: void
! 226: add_leaf(vifi, source, group)
! 227: vifi_t vifi;
! 228: u_int32 source;
! 229: u_int32 group;
! 230: {
! 231: grpentry_t *grpentry_ptr;
! 232: mrtentry_t *mrtentry_srcs;
! 233: vifbitmap_t new_leaves;
! 234: int state_change;
! 235:
! 236: grpentry_ptr = find_group(group);
! 237: if (grpentry_ptr == (grpentry_t *)NULL)
! 238: return;
! 239:
! 240: /* walk the source list for the group and add vif to oiflist */
! 241: for (mrtentry_srcs = grpentry_ptr->mrtlink;
! 242: mrtentry_srcs != (mrtentry_t *)NULL;
! 243: mrtentry_srcs = mrtentry_srcs->grpnext) {
! 244:
! 245: /* if applicable, add the vif to the leaves */
! 246: if (mrtentry_srcs->incoming == vifi)
! 247: continue;
! 248:
! 249: if(!(VIFM_ISSET(vifi, mrtentry_srcs->leaves))) {
! 250:
! 251: IF_DEBUG(DEBUG_MRT)
! 252: log(LOG_DEBUG, 0, "Adding leaf vif %d for src %s group %s",
! 253: vifi,
! 254: inet_fmt(mrtentry_srcs->source->address, s1),
! 255: inet_fmt(group, s2));
! 256:
! 257: VIFM_COPY(mrtentry_srcs->leaves, new_leaves);
! 258: VIFM_SET(vifi, new_leaves); /* Add the leaf */
! 259:
! 260: state_change =
! 261: change_interfaces(mrtentry_srcs,
! 262: mrtentry_srcs->incoming,
! 263: mrtentry_srcs->pruned_oifs,
! 264: new_leaves);
! 265:
! 266: /* Handle transition from negative cache */
! 267: if(state_change == 1)
! 268: trigger_join_alert(mrtentry_srcs);
! 269: }
! 270: }
! 271: }
! 272:
! 273:
! 274: /*
! 275: * TODO: XXX: currently `source` is not used. To be used with IGMPv3 where
! 276: * we have source-specific joins/prunes.
! 277: */
! 278: void
! 279: delete_leaf(vifi, source, group)
! 280: vifi_t vifi;
! 281: u_int32 source;
! 282: u_int32 group;
! 283: {
! 284: grpentry_t *grpentry_ptr;
! 285: mrtentry_t *mrtentry_srcs;
! 286: vifbitmap_t new_leaves;
! 287: int state_change;
! 288:
! 289: /* mrtentry_t *mrtentry_ptr;
! 290: * mrtentry_t *mrtentry_srcs;
! 291: * vifbitmap_t new_oifs;
! 292: * vifbitmap_t old_oifs;
! 293: * vifbitmap_t new_leaves;
! 294: */
! 295:
! 296: grpentry_ptr = find_group(group);
! 297: if (grpentry_ptr == (grpentry_t *)NULL)
! 298: return;
! 299:
! 300: /* walk the source list for the group and delete vif to leaves */
! 301: for (mrtentry_srcs = grpentry_ptr->mrtlink;
! 302: mrtentry_srcs != (mrtentry_t *)NULL;
! 303: mrtentry_srcs = mrtentry_srcs->grpnext) {
! 304:
! 305: /* if applicable, delete the vif from the leaves */
! 306: if (mrtentry_srcs->incoming == vifi)
! 307: continue;
! 308:
! 309: if(VIFM_ISSET(vifi, mrtentry_srcs->leaves)) {
! 310:
! 311: IF_DEBUG(DEBUG_MRT)
! 312: log(LOG_DEBUG, 0, "Deleting leaf vif %d for src %s, group %s",
! 313: vifi,
! 314: inet_fmt(mrtentry_srcs->source->address, s1),
! 315: inet_fmt(group, s2));
! 316:
! 317: VIFM_COPY(mrtentry_srcs->leaves, new_leaves);
! 318: VIFM_CLR(vifi, new_leaves); /* Remove the leaf */
! 319:
! 320: state_change =
! 321: change_interfaces(mrtentry_srcs,
! 322: mrtentry_srcs->incoming,
! 323: mrtentry_srcs->pruned_oifs,
! 324: new_leaves);
! 325:
! 326: /* Handle transition to negative cache */
! 327: if(state_change == -1)
! 328: trigger_prune_alert(mrtentry_srcs);
! 329: }
! 330: }
! 331: }
! 332:
! 333: void
! 334: calc_oifs(mrtentry_ptr, oifs_ptr)
! 335: mrtentry_t *mrtentry_ptr;
! 336: vifbitmap_t *oifs_ptr;
! 337: {
! 338: vifbitmap_t oifs;
! 339:
! 340: /*
! 341: * oifs =
! 342: * ((nbr_ifs - my_prune) + my_leaves) - incoming_interface,
! 343: * i.e. `leaves` have higher priority than `prunes`.
! 344: * Asserted oifs (those that lost assert) are handled as pruned oifs.
! 345: * The incoming interface is always deleted from the oifs
! 346: */
! 347:
! 348: if (mrtentry_ptr == (mrtentry_t *)NULL) {
! 349: VIFM_CLRALL(*oifs_ptr);
! 350: return;
! 351: }
! 352:
! 353: VIFM_COPY(nbr_vifs, oifs);
! 354: VIFM_CLR_MASK(oifs, mrtentry_ptr->pruned_oifs);
! 355: VIFM_MERGE(oifs, mrtentry_ptr->leaves, oifs);
! 356: VIFM_CLR(mrtentry_ptr->incoming, oifs);
! 357: VIFM_COPY(oifs, *oifs_ptr);
! 358: }
! 359:
! 360:
! 361: /*
! 362: * Set the iif, join/prune/leaves/asserted interfaces. Calculate and
! 363: * set the oifs.
! 364: * Return 1 if oifs change from NULL to not-NULL.
! 365: * Return -1 if oifs change from non-NULL to NULL
! 366: * else return 0
! 367: * If the iif change or if the oifs change from NULL to non-NULL
! 368: * or vice-versa, then schedule that mrtentry join/prune timer to
! 369: * timeout immediately.
! 370: */
! 371: int
! 372: change_interfaces(mrtentry_ptr, new_iif, new_pruned_oifs,
! 373: new_leaves_)
! 374: mrtentry_t *mrtentry_ptr;
! 375: vifi_t new_iif;
! 376: vifbitmap_t new_pruned_oifs;
! 377: vifbitmap_t new_leaves_;
! 378: {
! 379: vifbitmap_t old_pruned_oifs;
! 380: vifbitmap_t old_leaves;
! 381: vifbitmap_t new_leaves;
! 382: vifbitmap_t new_real_oifs; /* The result oifs */
! 383: vifbitmap_t old_real_oifs;
! 384: vifi_t old_iif;
! 385: int return_value;
! 386:
! 387: if (mrtentry_ptr == (mrtentry_t *)NULL)
! 388: return (0);
! 389:
! 390: VIFM_COPY(new_leaves_, new_leaves);
! 391:
! 392: old_iif = mrtentry_ptr->incoming;
! 393: VIFM_COPY(mrtentry_ptr->leaves, old_leaves);
! 394: VIFM_COPY(mrtentry_ptr->pruned_oifs, old_pruned_oifs);
! 395:
! 396: VIFM_COPY(mrtentry_ptr->oifs, old_real_oifs);
! 397:
! 398: mrtentry_ptr->incoming = new_iif;
! 399: VIFM_COPY(new_pruned_oifs, mrtentry_ptr->pruned_oifs);
! 400: VIFM_COPY(new_leaves, mrtentry_ptr->leaves);
! 401: calc_oifs(mrtentry_ptr, &new_real_oifs);
! 402:
! 403: if (VIFM_ISEMPTY(old_real_oifs)) {
! 404: if (VIFM_ISEMPTY(new_real_oifs))
! 405: return_value = 0;
! 406: else
! 407: return_value = 1;
! 408: } else {
! 409: if (VIFM_ISEMPTY(new_real_oifs))
! 410: return_value = -1;
! 411: else
! 412: return_value = 0;
! 413: }
! 414:
! 415: if ((VIFM_SAME(new_real_oifs, old_real_oifs))
! 416: && (new_iif == old_iif))
! 417: return 0; /* Nothing to change */
! 418:
! 419: VIFM_COPY(new_real_oifs, mrtentry_ptr->oifs);
! 420:
! 421: k_chg_mfc(igmp_socket, mrtentry_ptr->source->address,
! 422: mrtentry_ptr->group->group, new_iif, new_real_oifs);
! 423:
! 424: #ifdef RSRR
! 425: rsrr_cache_send(mrtentry_ptr, RSRR_NOTIFICATION_OK);
! 426: #endif /* RSRR */
! 427:
! 428: return (return_value);
! 429: }
! 430:
! 431:
! 432: /* TODO: implement it. Required to allow changing of the physical interfaces
! 433: * configuration without need to restart pimd.
! 434: */
! 435: int
! 436: delete_vif_from_mrt(vifi)
! 437: vifi_t vifi;
! 438: {
! 439: return TRUE;
! 440: }
! 441:
! 442:
! 443: static u_int16
! 444: max_prune_timeout(mrtentry_ptr)
! 445: mrtentry_t *mrtentry_ptr;
! 446: {
! 447: vifi_t vifi;
! 448: u_int16 time_left, max_holdtime = 0;
! 449:
! 450: for(vifi=0; vifi < numvifs; ++vifi)
! 451: if(VIFM_ISSET(vifi, mrtentry_ptr->pruned_oifs))
! 452: IF_TIMER_SET(mrtentry_ptr->prune_timers[vifi])
! 453: /* XXX - too expensive ? */
! 454: /* XXX: TIMER implem. dependency! */
! 455: if(mrtentry_ptr->prune_timers[vifi] > max_holdtime)
! 456: max_holdtime = time_left;
! 457:
! 458: if(max_holdtime == 0)
! 459: max_holdtime = (u_int16)PIM_JOIN_PRUNE_HOLDTIME;
! 460:
! 461: return(max_holdtime);
! 462: }
! 463:
! 464:
! 465: void process_kernel_call()
! 466: {
! 467: register struct igmpmsg *igmpctl; /* igmpmsg control struct */
! 468:
! 469: igmpctl = (struct igmpmsg *) igmp_recv_buf;
! 470:
! 471: switch (igmpctl->im_msgtype) {
! 472: case IGMPMSG_NOCACHE:
! 473: process_cache_miss(igmpctl);
! 474: break;
! 475: case IGMPMSG_WRONGVIF:
! 476: process_wrong_iif(igmpctl);
! 477: break;
! 478: default:
! 479: IF_DEBUG(DEBUG_KERN)
! 480: log(LOG_DEBUG, 0, "Unknown kernel_call code");
! 481: break;
! 482: }
! 483: }
! 484:
! 485:
! 486: /*
! 487: * Protocol actions:
! 488: * 1. Create (S,G) entry (find_route(CREATE))
! 489: * a. set iif and oifs
! 490: */
! 491: static void
! 492: process_cache_miss(igmpctl)
! 493: struct igmpmsg *igmpctl;
! 494: {
! 495: u_int32 source;
! 496: u_int32 group;
! 497: mrtentry_t *mrtentry_ptr;
! 498:
! 499: /*
! 500: * When there is a cache miss, we check only the header of the packet
! 501: * (and only it should be sent up by the kernel.
! 502: */
! 503:
! 504: group = igmpctl->im_dst.s_addr;
! 505: source = igmpctl->im_src.s_addr;
! 506:
! 507: IF_DEBUG(DEBUG_MFC)
! 508: log(LOG_DEBUG, 0, "Cache miss, src %s, dst %s",
! 509: inet_fmt(source, s1), inet_fmt(group, s2));
! 510:
! 511: /* Don't create routing entries for the LAN scoped addresses */
! 512: if (ntohl(group) <= INADDR_MAX_LOCAL_GROUP)
! 513: return;
! 514:
! 515: /* Create the (S,G) entry */
! 516: mrtentry_ptr = find_route(source, group, MRTF_SG, CREATE);
! 517: if (mrtentry_ptr == (mrtentry_t *)NULL)
! 518: return;
! 519: mrtentry_ptr->flags &= ~MRTF_NEW;
! 520:
! 521: /* Initialize Entry Timer */
! 522: SET_TIMER(mrtentry_ptr->timer, PIM_DATA_TIMEOUT);
! 523:
! 524: /* Set oifs */
! 525: set_leaves(mrtentry_ptr);
! 526: calc_oifs(mrtentry_ptr, &(mrtentry_ptr->oifs));
! 527:
! 528: /* Add it to the kernel */
! 529: k_chg_mfc(igmp_socket, source, group, mrtentry_ptr->incoming,
! 530: mrtentry_ptr->oifs);
! 531:
! 532: #ifdef RSRR
! 533: rsrr_cache_send(mrtentry_ptr, RSRR_NOTIFICATION_OK);
! 534: #endif /* RSRR */
! 535:
! 536: /* No need to call change_interfaces, but check for NULL oiflist */
! 537: if(VIFM_ISEMPTY(mrtentry_ptr->oifs))
! 538: trigger_prune_alert(mrtentry_ptr);
! 539: }
! 540:
! 541:
! 542: /*
! 543: * A multicast packet has been received on wrong iif by the kernel.
! 544: * If the packet was received on a point-to-point interface, rate-limit
! 545: * prunes. if the packet was received on a LAN interface, rate-limit
! 546: * asserts.
! 547: */
! 548: static void
! 549: process_wrong_iif(igmpctl)
! 550: struct igmpmsg *igmpctl;
! 551: {
! 552: u_int32 source;
! 553: u_int32 group;
! 554: vifi_t vifi;
! 555: mrtentry_t *mrtentry_ptr;
! 556:
! 557: group = igmpctl->im_dst.s_addr;
! 558: source = igmpctl->im_src.s_addr;
! 559: vifi = igmpctl->im_vif;
! 560:
! 561: /* PIMDM TODO Don't create routing entries for the LAN scoped addresses */
! 562: if (ntohl(group) <= INADDR_MAX_LOCAL_GROUP)
! 563: return;
! 564:
! 565: /* Ratelimit prunes or asserts */
! 566: if(uvifs[vifi].uv_flags & VIFF_POINT_TO_POINT) {
! 567:
! 568: mrtentry_ptr = find_route(source, group, MRTF_SG, DONT_CREATE);
! 569: if(mrtentry_ptr == (mrtentry_t *)NULL)
! 570: return;
! 571:
! 572: /* Wrong vif on P2P interface - rate-limit prunes */
! 573:
! 574: if(mrtentry_ptr->last_prune[vifi] == virtual_time)
! 575: /* Skip due to rate-limiting */
! 576: return;
! 577: mrtentry_ptr->last_prune[vifi] = virtual_time;
! 578:
! 579: if(uvifs[vifi].uv_rmt_addr)
! 580: send_pim_jp(mrtentry_ptr, PIM_ACTION_PRUNE, vifi,
! 581: uvifs[vifi].uv_rmt_addr,
! 582: max_prune_timeout(mrtentry_ptr));
! 583: else
! 584: log(LOG_WARNING, 0,
! 585: "Can't send wrongvif prune on p2p %s: no remote address",
! 586: uvifs[vifi].uv_lcl_addr);
! 587: } else {
! 588: u_int32 pref, metric;
! 589:
! 590: /* Wrong vif on LAN interface - rate-limit asserts */
! 591:
! 592: mrtentry_ptr = find_route(source, group, MRTF_SG, DONT_CREATE);
! 593: if(mrtentry_ptr == (mrtentry_t *)NULL) {
! 594: pref = 0x7fffffff;
! 595: metric = 0x7fffffff;
! 596: }
! 597: else {
! 598: pref = mrtentry_ptr->source->preference;
! 599: metric = mrtentry_ptr->source->metric;
! 600: }
! 601:
! 602: if(mrtentry_ptr->last_assert[vifi] == virtual_time)
! 603: /* Skip due to rate-limiting */
! 604: return;
! 605: mrtentry_ptr->last_assert[vifi] = virtual_time;
! 606:
! 607: /* Send the assert */
! 608: send_pim_assert(source, group, vifi, pref, metric);
! 609: }
! 610: }
! 611:
! 612:
! 613: void trigger_prune_alert(mrtentry_ptr)
! 614: mrtentry_t *mrtentry_ptr;
! 615: {
! 616: IF_DEBUG(DEBUG_MRT)
! 617: log(LOG_DEBUG, 0, "Now negative cache for src %s, grp %s - pruning",
! 618: inet_fmt(mrtentry_ptr->source->address, s1),
! 619: inet_fmt(mrtentry_ptr->group->group, s2));
! 620:
! 621: /* Set the entry timer to the max of the prune timers */
! 622: SET_TIMER(mrtentry_ptr->timer, max_prune_timeout(mrtentry_ptr));
! 623:
! 624: /* Send a prune */
! 625: if(mrtentry_ptr->upstream)
! 626: send_pim_jp(mrtentry_ptr, PIM_ACTION_PRUNE, mrtentry_ptr->incoming,
! 627: mrtentry_ptr->upstream->address,
! 628: max_prune_timeout(mrtentry_ptr));
! 629: }
! 630:
! 631: void trigger_join_alert(mrtentry_ptr)
! 632: mrtentry_t *mrtentry_ptr;
! 633: {
! 634: IF_DEBUG(DEBUG_MRT)
! 635: log(LOG_DEBUG, 0, "Now forwarding state for src %s, grp %s - grafting",
! 636: inet_fmt(mrtentry_ptr->source->address, s1),
! 637: inet_fmt(mrtentry_ptr->group->group, s2));
! 638:
! 639: /* Refresh the entry timer */
! 640: SET_TIMER(mrtentry_ptr->timer, PIM_DATA_TIMEOUT);
! 641:
! 642: /* Send graft */
! 643: send_pim_graft(mrtentry_ptr);
! 644: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>