void calc_oifs(mrtentry_t *mrtentry_ptr, vifbitmap_t *oifs_ptr) { vifbitmap_t oifs; mrtentry_t *grp_route; mrtentry_t *rp_route; /* * oifs = * (((copied_outgoing + my_join) - my_prune) + my_leaves) * - my_asserted_oifs - incoming_interface, * i.e. `leaves` have higher priority than `prunes`, but lower priority * than `asserted`. The incoming interface is always deleted from the oifs */ if (mrtentry_ptr == (mrtentry_t *)NULL) { VIFM_CLRALL(*oifs_ptr); return; } VIFM_CLRALL(oifs); if (!(mrtentry_ptr->flags & MRTF_PMBR)) { /* Either (*,G) or (S,G). Merge with the oifs from the (*,*,RP) */ if ((rp_route = mrtentry_ptr->group->active_rp_grp->rp->rpentry->mrtlink) != (mrtentry_t *)NULL) { VIFM_MERGE(oifs, rp_route->joined_oifs, oifs); VIFM_CLR_MASK(oifs, rp_route->pruned_oifs); VIFM_MERGE(oifs, rp_route->leaves, oifs); VIFM_CLR_MASK(oifs, rp_route->asserted_oifs); } } if (mrtentry_ptr->flags & MRTF_SG) { /* (S,G) entry. Merge with the oifs from (*,G) */ if ((grp_route = mrtentry_ptr->group->grp_route) != (mrtentry_t *)NULL) { VIFM_MERGE(oifs, grp_route->joined_oifs, oifs); VIFM_CLR_MASK(oifs, grp_route->pruned_oifs); VIFM_MERGE(oifs, grp_route->leaves, oifs); VIFM_CLR_MASK(oifs, grp_route->asserted_oifs); } } /* Calculate my own stuff */ VIFM_MERGE(oifs, mrtentry_ptr->joined_oifs, oifs); VIFM_CLR_MASK(oifs, mrtentry_ptr->pruned_oifs); VIFM_MERGE(oifs, mrtentry_ptr->leaves, oifs); VIFM_CLR_MASK(oifs, mrtentry_ptr->asserted_oifs); VIFM_COPY(oifs, *oifs_ptr); }
/* * Initialize the children and leaf bits for route 'r', along with the * associated dominant, subordinate, and leaf timing data structures. * Return TRUE if this changes the value of either the children or * leaf bitmaps for 'r'. */ static int init_children_and_leaves(struct rtentry *r, vifi_t parent) { register vifi_t vifi; register struct uvif *v; vifbitmap_t old_children, old_leaves; VIFM_COPY(r->rt_children, old_children); VIFM_COPY(r->rt_leaves, old_leaves ); VIFM_CLRALL(r->rt_children); VIFM_CLRALL(r->rt_leaves); r->rt_flags &= ~RTF_LEAF_TIMING; for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { r->rt_dominants [vifi] = 0; r->rt_subordinates[vifi] = 0; if (vifi != parent && !(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) { VIFM_SET(vifi, r->rt_children); if (v->uv_neighbors == NULL) { VIFM_SET(vifi, r->rt_leaves); r->rt_leaf_timers[vifi] = 0; } else { r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; r->rt_flags |= RTF_LEAF_TIMING; } } else { r->rt_leaf_timers[vifi] = 0; } } return (!VIFM_SAME(r->rt_children, old_children) || !VIFM_SAME(r->rt_leaves, old_leaves)); }
static mrtentry_t *alloc_mrtentry(srcentry_t *src, grpentry_t *grp) { mrtentry_t *mrt; u_int16 i, *timer; u_int8 vif_numbers; mrt = calloc(1, sizeof(mrtentry_t)); if (!mrt) { logit(LOG_WARNING, 0, "alloc_mrtentry(): out of memory"); return NULL; } /* * grpnext, grpprev, srcnext, srcprev will be setup when we link the * mrtentry to the source and group chains */ mrt->source = src; mrt->group = grp; mrt->incoming = NO_VIF; VIFM_CLRALL(mrt->joined_oifs); VIFM_CLRALL(mrt->leaves); VIFM_CLRALL(mrt->pruned_oifs); VIFM_CLRALL(mrt->asserted_oifs); VIFM_CLRALL(mrt->oifs); mrt->upstream = NULL; mrt->metric = 0; mrt->preference = 0; mrt->pmbr_addr = INADDR_ANY_N; #ifdef RSRR mrt->rsrr_cache = NULL; #endif /* RSRR */ /* XXX: TODO: if we are short in memory, we can reserve as few as possible * space for vif timers (per group and/or routing entry), but then everytime * when a new interfaces is configured, the router will be restarted and * will delete the whole routing table. The "memory is cheap" solution is * to reserve timer space for all potential vifs in advance and then no * need to delete the routing table and disturb the forwarding. */ #ifdef SAVE_MEMORY mrt->vif_timers = (u_int16 *)calloc(1, sizeof(u_int16) * numvifs); mrt->vif_deletion_delay = (u_int16 *)calloc(1, sizeof(u_int16) * numvifs); vif_numbers = numvifs; #else mrt->vif_timers = (u_int16 *)calloc(1, sizeof(u_int16) * total_interfaces); mrt->vif_deletion_delay = (u_int16 *)calloc(1, sizeof(u_int16) * total_interfaces); vif_numbers = total_interfaces; #endif /* SAVE_MEMORY */ if (!mrt->vif_timers || !mrt->vif_deletion_delay) { logit(LOG_WARNING, 0, "alloc_mrtentry(): out of memory"); FREE_MRTENTRY(mrt); return NULL; } /* Reset the timers */ for (i = 0, timer = mrt->vif_timers; i < vif_numbers; i++, timer++) RESET_TIMER(*timer); for (i = 0, timer = mrt->vif_deletion_delay; i < vif_numbers; i++, timer++) RESET_TIMER(*timer); mrt->flags = MRTF_NEW; RESET_TIMER(mrt->timer); RESET_TIMER(mrt->jp_timer); RESET_TIMER(mrt->rs_timer); RESET_TIMER(mrt->assert_timer); RESET_TIMER(mrt->assert_rate_timer); mrt->kernel_cache = NULL; return mrt; }