Example #1
0
/*
 * 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));
}
Example #2
0
File: route.c Project: F0rth/pimd
/*
 * Set the iif, join/prune/leaves/asserted interfaces. Calculate and
 * set the oifs.
 * Return 1 if oifs change from NULL to not-NULL.
 * Return -1 if oifs change from non-NULL to NULL
 *  else return 0
 * If the iif change or if the oifs change from NULL to non-NULL
 * or vice-versa, then schedule that mrtentry join/prune timer to
 * timeout immediately.
 */
int change_interfaces(mrtentry_t *mrtentry_ptr,
                      vifi_t new_iif,
                      vifbitmap_t new_joined_oifs_,
                      vifbitmap_t new_pruned_oifs,
                      vifbitmap_t new_leaves_,
                      vifbitmap_t new_asserted_oifs,
                      u_int16 flags)
{
    vifbitmap_t new_joined_oifs;  /* The oifs for that particular mrtentry */
    vifbitmap_t old_joined_oifs;
    vifbitmap_t old_pruned_oifs;
    vifbitmap_t old_leaves;
    vifbitmap_t new_leaves;
    vifbitmap_t old_asserted_oifs;
    vifbitmap_t new_real_oifs;    /* The result oifs */
    vifbitmap_t old_real_oifs;
    vifi_t      old_iif;
    rpentry_t   *rpentry_ptr;
    cand_rp_t   *cand_rp_ptr;
    kernel_cache_t *kernel_cache_ptr;
    rp_grp_entry_t *rp_grp_entry_ptr;
    grpentry_t     *grpentry_ptr;
    mrtentry_t     *mrtentry_srcs;
    mrtentry_t     *mrtentry_wc;
    mrtentry_t     *mrtentry_rp;
    int delete_mrtentry_flag;
    int return_value;
    int fire_timer_flag;

    if (mrtentry_ptr == (mrtentry_t *)NULL)
        return 0;

    VIFM_COPY(new_joined_oifs_, new_joined_oifs);
    VIFM_COPY(new_leaves_, new_leaves);

    old_iif = mrtentry_ptr->incoming;
    VIFM_COPY(mrtentry_ptr->joined_oifs, old_joined_oifs);
    VIFM_COPY(mrtentry_ptr->leaves, old_leaves);
    VIFM_COPY(mrtentry_ptr->pruned_oifs, old_pruned_oifs);
    VIFM_COPY(mrtentry_ptr->asserted_oifs, old_asserted_oifs);

    VIFM_COPY(mrtentry_ptr->oifs, old_real_oifs);

    mrtentry_ptr->incoming = new_iif;
    VIFM_COPY(new_joined_oifs, mrtentry_ptr->joined_oifs);
    VIFM_COPY(new_pruned_oifs, mrtentry_ptr->pruned_oifs);
    VIFM_COPY(new_leaves, mrtentry_ptr->leaves);
    VIFM_COPY(new_asserted_oifs, mrtentry_ptr->asserted_oifs);
    calc_oifs(mrtentry_ptr, &new_real_oifs);

    if (VIFM_ISEMPTY(old_real_oifs)) {
        if (VIFM_ISEMPTY(new_real_oifs))
            return_value = 0;
        else
            return_value = 1;
    } else {
        if (VIFM_ISEMPTY(new_real_oifs))
            return_value = -1;
        else
            return_value = 0;
    }

    if ((VIFM_SAME(new_real_oifs, old_real_oifs))
        && (new_iif == old_iif)
        && !(flags & MFC_UPDATE_FORCE))
        return 0;                  /* Nothing to change */

    if ((return_value != 0) || (new_iif != old_iif)
        || (flags & MFC_UPDATE_FORCE))
        FIRE_TIMER(mrtentry_ptr->jp_timer);

    VIFM_COPY(new_real_oifs, mrtentry_ptr->oifs);

    if (mrtentry_ptr->flags & MRTF_PMBR) {
        /* (*,*,RP) entry */
        rpentry_ptr = mrtentry_ptr->source;
        if (rpentry_ptr == (rpentry_t *)NULL)
            return (0);    /* Shoudn't happen */
        rpentry_ptr->incoming = new_iif;
        cand_rp_ptr = rpentry_ptr->cand_rp;

        if (VIFM_ISEMPTY(new_real_oifs)) {
            delete_mrtentry_flag = TRUE;
        }
        else {
            delete_mrtentry_flag = FALSE;
#ifdef RSRR
            rsrr_cache_send(mrtentry_ptr, RSRR_NOTIFICATION_OK);
#endif /* RSRR */
        }

        if (mrtentry_ptr->flags & MRTF_KERNEL_CACHE) {
            /* Update the kernel MFC entries */
            if (delete_mrtentry_flag == TRUE)
                /* XXX: no need to send RSRR message. Will do it when
                 * delete the mrtentry.
                 */
                for (kernel_cache_ptr = mrtentry_ptr->kernel_cache;
                     kernel_cache_ptr != (kernel_cache_t *)NULL;
                     kernel_cache_ptr = kernel_cache_ptr->next)
                    delete_mrtentry_all_kernel_cache(mrtentry_ptr);
            else {
                for (kernel_cache_ptr = mrtentry_ptr->kernel_cache;
                     kernel_cache_ptr != (kernel_cache_t *)NULL;
                     kernel_cache_ptr = kernel_cache_ptr->next)
                    /* here mrtentry_ptr->source->address is the RP address */
                    k_chg_mfc(igmp_socket, kernel_cache_ptr->source,
                              kernel_cache_ptr->group, new_iif,
                              new_real_oifs, mrtentry_ptr->source->address);
            }
        }

        /*
         * Update all (*,G) entries associated with this RP.
         * The particular (*,G) outgoing are not changed, but the change
         * in the (*,*,RP) oifs may have affect the real oifs.
         */
        fire_timer_flag = FALSE;
        for (rp_grp_entry_ptr = cand_rp_ptr->rp_grp_next;
             rp_grp_entry_ptr != (rp_grp_entry_t *)NULL;
             rp_grp_entry_ptr = rp_grp_entry_ptr->rp_grp_next) {
            for (grpentry_ptr = rp_grp_entry_ptr->grplink;
                 grpentry_ptr != (grpentry_t *)NULL;
                 grpentry_ptr = grpentry_ptr->rpnext) {
                if (grpentry_ptr->grp_route != (mrtentry_t *)NULL) {
                    if (change_interfaces(grpentry_ptr->grp_route, new_iif,
                                          grpentry_ptr->grp_route->joined_oifs,
                                          grpentry_ptr->grp_route->pruned_oifs,
                                          grpentry_ptr->grp_route->leaves,
                                          grpentry_ptr->grp_route->asserted_oifs,
                                          flags))
                        fire_timer_flag = TRUE;
                } else {
                    /* Change all (S,G) entries if no (*,G) */
                    for (mrtentry_srcs = grpentry_ptr->mrtlink;
                         mrtentry_srcs != (mrtentry_t *)NULL;
                         mrtentry_srcs = mrtentry_srcs->grpnext) {
                        if (mrtentry_srcs->flags & MRTF_RP) {
                            if (change_interfaces(mrtentry_srcs, new_iif,
                                                  mrtentry_srcs->joined_oifs,
                                                  mrtentry_srcs->pruned_oifs,
                                                  mrtentry_srcs->leaves,
                                                  mrtentry_srcs->asserted_oifs,
                                                  flags))
                                fire_timer_flag = TRUE;
                        } else {
                            if (change_interfaces(mrtentry_srcs,
                                                  mrtentry_srcs->incoming,
                                                  mrtentry_srcs->joined_oifs,
                                                  mrtentry_srcs->pruned_oifs,
                                                  mrtentry_srcs->leaves,
                                                  mrtentry_srcs->asserted_oifs,
                                                  flags))
                                fire_timer_flag = TRUE;
                        }
                    }
                }
            }
        }
        if (fire_timer_flag == TRUE)
            FIRE_TIMER(mrtentry_ptr->jp_timer);
        if (delete_mrtentry_flag == TRUE) {
            /* TODO: XXX: trigger a Prune message? Don't delete now, it will
             * be automatically timed out. If want to delete now, don't
             * reference to it anymore!
             delete_mrtentry(mrtentry_ptr);
            */
        }

        return return_value;   /* (*,*,RP) */
    }

    if (mrtentry_ptr->flags & MRTF_WC) {
        /* (*,G) entry */
        if (VIFM_ISEMPTY(new_real_oifs))
            delete_mrtentry_flag = TRUE;
        else {
            delete_mrtentry_flag = FALSE;
#ifdef RSRR
            rsrr_cache_send(mrtentry_ptr, RSRR_NOTIFICATION_OK);
#endif /* RSRR */
        }
        if (mrtentry_ptr->flags & MRTF_KERNEL_CACHE) {
            if (delete_mrtentry_flag == TRUE)
                delete_mrtentry_all_kernel_cache(mrtentry_ptr);
            else {
                for (kernel_cache_ptr = mrtentry_ptr->kernel_cache;
                     kernel_cache_ptr != (kernel_cache_t *)NULL;
                     kernel_cache_ptr = kernel_cache_ptr->next)
                    k_chg_mfc(igmp_socket, kernel_cache_ptr->source,
                              kernel_cache_ptr->group, new_iif,
                              new_real_oifs, mrtentry_ptr->group->rpaddr);
            }
        }
        /* Update all (S,G) entries for this group.
         * For the (S,G)RPbit entries the iif is the iif toward the RP;
         * The particular (S,G) oifs are not changed, but the change in the
         * (*,G) oifs may affect the real oifs.
         */
        fire_timer_flag = FALSE;
        for (mrtentry_srcs = mrtentry_ptr->group->mrtlink;
             mrtentry_srcs != (mrtentry_t *)NULL;
             mrtentry_srcs = mrtentry_srcs->grpnext) {
            if (mrtentry_srcs->flags & MRTF_RP) {
                if (change_interfaces(mrtentry_srcs, new_iif,
                                      mrtentry_srcs->joined_oifs,
                                      mrtentry_srcs->pruned_oifs,
                                      mrtentry_srcs->leaves,
                                      mrtentry_srcs->asserted_oifs, flags))
                    fire_timer_flag = TRUE;
            } else {
                if (change_interfaces(mrtentry_srcs, mrtentry_srcs->incoming,
                                      mrtentry_srcs->joined_oifs,
                                      mrtentry_srcs->pruned_oifs,
                                      mrtentry_srcs->leaves,
                                      mrtentry_srcs->asserted_oifs, flags))
                    fire_timer_flag = TRUE;
            }
        }

        if (fire_timer_flag == TRUE)
            FIRE_TIMER(mrtentry_ptr->jp_timer);
        if (delete_mrtentry_flag == TRUE) {
            /* TODO: XXX: the oifs are NULL. Send a Prune message? */
        }
        return return_value;   /* (*,G) */
    }

    if (mrtentry_ptr->flags & MRTF_SG) {
        /* (S,G) entry */
#ifdef KERNEL_MFC_WC_G
        vifbitmap_t tmp_oifs;
        mrtentry_t *mrtentry_tmp;
#endif /* KERNEL_MFC_WC_G */

        mrtentry_rp = mrtentry_ptr->group->active_rp_grp->rp->rpentry->mrtlink;
        mrtentry_wc = mrtentry_ptr->group->grp_route;
#ifdef KERNEL_MFC_WC_G
        /* Check whether (*,*,RP) or (*,G) have different (iif,oifs) from
         * the (S,G). If "yes", then forbid creating (*,G) MFC.
         */
        for (mrtentry_tmp = mrtentry_rp; 1; mrtentry_tmp = mrtentry_wc) {
            for ( ; 1; ) {
                if (mrtentry_tmp == (mrtentry_t *)NULL)
                    break;
                if (mrtentry_tmp->flags & MRTF_MFC_CLONE_SG)
                    break;
                if (mrtentry_tmp->incoming != mrtentry_ptr->incoming) {
                    delete_single_kernel_cache_addr(mrtentry_tmp, INADDR_ANY_N,
                                                    mrtentry_ptr->group->group);
                    mrtentry_tmp->flags |= MRTF_MFC_CLONE_SG;
                    break;
                }
                calc_oifs(mrtentry_tmp, &tmp_oifs);
                if (!(VIFM_SAME(new_real_oifs, tmp_oifs)))
                    mrtentry_tmp->flags |= MRTF_MFC_CLONE_SG;
                break;
            }
            if (mrtentry_tmp == mrtentry_wc)
                break;
        }
#endif /* KERNEL_MFC_WC_G */

        if (VIFM_ISEMPTY(new_real_oifs))
            delete_mrtentry_flag = TRUE;
        else {
            delete_mrtentry_flag = FALSE;
#ifdef RSRR
            rsrr_cache_send(mrtentry_ptr, RSRR_NOTIFICATION_OK);
#endif /* RSRR */
        }
        if (mrtentry_ptr->flags & MRTF_KERNEL_CACHE) {
            if (delete_mrtentry_flag == TRUE)
                delete_mrtentry_all_kernel_cache(mrtentry_ptr);
            else {
                k_chg_mfc(igmp_socket, mrtentry_ptr->source->address,
                          mrtentry_ptr->group->group, new_iif, new_real_oifs,
                          mrtentry_ptr->group->rpaddr);
            }
        }
        if (old_iif != new_iif) {
            if (new_iif == mrtentry_ptr->source->incoming) {
                /* For example, if this was (S,G)RPbit with iif toward the RP,
                 * and now switch to the Shortest Path.
                 * The setup of MRTF_SPT flag must be
                 * done by the external calling function (triggered only
                 * by receiving of a data from the source.)
                 */
                mrtentry_ptr->flags &= ~MRTF_RP;
                /* TODO: XXX: delete? Check again where will be the best
                 * place to set it.
                 mrtentry_ptr->flags |= MRTF_SPT;
                */
            }
            if (((mrtentry_wc != (mrtentry_t *)NULL)
                 && (mrtentry_wc->incoming == new_iif))
                || ((mrtentry_rp != (mrtentry_t *)NULL)
                    && (mrtentry_rp->incoming == new_iif))) {
                /* If the new iif points toward the RP, reset the SPT flag.
                 * (PIM-SM-spec-10.ps pp. 11, 2.10, last sentence of first
                 * paragraph.
                 */
                /* TODO: XXX: check again! */
                mrtentry_ptr->flags &= ~MRTF_SPT;
                mrtentry_ptr->flags |= MRTF_RP;
            }
        }
        /* TODO: XXX: if this is (S,G)RPbit entry and the oifs==(*,G)oifs,
         * then delete the (S,G) entry?? The same if we have (*,*,RP) ?
         */
        if (delete_mrtentry_flag == TRUE) {
            /* TODO: XXX: the oifs are NULL. Send a Prune message ? */
        }

        /* TODO: XXX: have the feeling something is missing.... */
        return return_value;  /* (S,G) */
    }

    return return_value;
}