コード例 #1
0
ファイル: mrt.c プロジェクト: CameronNemo/pimd
void delete_grpentry(grpentry_t *grp)
{
    mrtentry_t *node;
    mrtentry_t *next;

    if (!grp)
	return;

    /* TODO: XXX: the first entry is unused and always there */
    grp->prev->next = grp->next;
    if (grp->next)
	grp->next->prev = grp->prev;

    if (grp->grp_route) {
	if (grp->grp_route->flags & MRTF_KERNEL_CACHE)
	    delete_mrtentry_all_kernel_cache(grp->grp_route);
	FREE_MRTENTRY(grp->grp_route);
    }

    /* Delete from the rp_grp_entry chain */
    if (grp->active_rp_grp) {
	if (grp->rpnext)
	    grp->rpnext->rpprev = grp->rpprev;

	if (grp->rpprev)
	    grp->rpprev->rpnext = grp->rpnext;
	else
	    grp->active_rp_grp->grplink = grp->rpnext;
    }

    for (node = grp->mrtlink; node; node = next) {
	next = node->grpnext;
	if (node->flags & MRTF_KERNEL_CACHE)
	    /* Delete the kernel cache first */
	    delete_mrtentry_all_kernel_cache(node);

	if (node->srcprev) {
	    node->srcprev->srcnext = node->srcnext;
	} else {
	    node->source->mrtlink = node->srcnext;
	    if (!node->srcnext) {
		/* Delete the srcentry if this was the last routing entry */
		delete_srcentry(node->source);
	    }
	}

	if (node->srcnext)
	    node->srcnext->srcprev = node->srcprev;

	FREE_MRTENTRY(node);
    }

    free(grp);
}
コード例 #2
0
ファイル: route.c プロジェクト: F0rth/pimd
mrtentry_t *switch_shortest_path(u_int32 source, u_int32 group)
{
    mrtentry_t *mrtentry_ptr;

    /* TODO: XXX: prepare and send immediately the (S,G) join? */
    if ((mrtentry_ptr = find_route(source, group, MRTF_SG, CREATE)) !=
        (mrtentry_t *)NULL) {
        if (mrtentry_ptr->flags & MRTF_NEW) {
            mrtentry_ptr->flags &= ~MRTF_NEW;
        }
        else if (mrtentry_ptr->flags & MRTF_RP) {
            /* (S,G)RPbit with iif toward RP. Reset to (S,G) with iif
             * toward S. Delete the kernel cache (if any), because
             * change_interfaces() will reset it with iif toward S
             * and no data will arrive from RP before the switch
             * really occurs.
             */
            mrtentry_ptr->flags &= ~MRTF_RP;
            mrtentry_ptr->incoming = mrtentry_ptr->source->incoming;
            mrtentry_ptr->upstream = mrtentry_ptr->source->upstream;
            delete_mrtentry_all_kernel_cache(mrtentry_ptr);
            change_interfaces(mrtentry_ptr,
                              mrtentry_ptr->incoming,
                              mrtentry_ptr->joined_oifs,
                              mrtentry_ptr->pruned_oifs,
                              mrtentry_ptr->leaves,
                              mrtentry_ptr->asserted_oifs, 0);
        }

        SET_TIMER(mrtentry_ptr->timer, PIM_DATA_TIMEOUT);
        FIRE_TIMER(mrtentry_ptr->jp_timer);
    }

    return mrtentry_ptr;
}
コード例 #3
0
ファイル: mrt.c プロジェクト: CameronNemo/pimd
void delete_srcentry(srcentry_t *src)
{
    mrtentry_t *node;
    mrtentry_t *next;

    if (!src)
	return;

    /* TODO: XXX: the first entry is unused and always there */
    src->prev->next =  src->next;
    if (src->next)
	src->next->prev = src->prev;

    for (node = src->mrtlink; node; node = next) {
	next = node->srcnext;
	if (node->flags & MRTF_KERNEL_CACHE)
	    /* Delete the kernel cache first */
	    delete_mrtentry_all_kernel_cache(node);

	if (node->grpprev) {
	    node->grpprev->grpnext = node->grpnext;
	} else {
	    node->group->mrtlink = node->grpnext;
	    if (!node->grpnext && !node->group->grp_route)
		/* Delete the group entry if it has no (*,G) routing entry */
		delete_grpentry(node->group);
	}

	if (node->grpnext)
	    node->grpnext->grpprev = node->grpprev;

	FREE_MRTENTRY(node);
    }

    free(src);
}
コード例 #4
0
ファイル: mrt.c プロジェクト: CameronNemo/pimd
void delete_mrtentry(mrtentry_t *mrt)
{
    grpentry_t *grp;
    mrtentry_t *mrt_wc;
    mrtentry_t *mrt_rp;

    if (!mrt)
	return;

    /* Delete the kernel cache first */
    if (mrt->flags & MRTF_KERNEL_CACHE)
	delete_mrtentry_all_kernel_cache(mrt);

#ifdef RSRR
    /* Tell the reservation daemon */
    rsrr_cache_clean(mrt);
#endif /* RSRR */

    if (mrt->flags & MRTF_PMBR) {
	/* (*,*,RP) mrtentry */
	mrt->source->mrtlink = NULL;
    } else if (mrt->flags & MRTF_SG) {
	/* (S,G) mrtentry */

	/* Delete from the grpentry MRT chain */
	if (mrt->grpprev) {
	    mrt->grpprev->grpnext = mrt->grpnext;
	} else {
	    mrt->group->mrtlink = mrt->grpnext;
	    if (!mrt->grpnext) {
		/* All (S,G) MRT entries are gone. Allow creating (*,G) MFC entries. */
		mrt_rp = mrt->group->active_rp_grp->rp->rpentry->mrtlink;
		mrt_wc = mrt->group->grp_route;
		if (mrt_rp)
		    mrt_rp->flags &= ~MRTF_MFC_CLONE_SG;

		if (mrt_wc)
		    mrt_wc->flags &= ~MRTF_MFC_CLONE_SG;
		else
		    /* Delete the group entry if it has no (*,G) routing entry */
		    delete_grpentry(mrt->group);
	    }
	}

	if (mrt->grpnext)
	    mrt->grpnext->grpprev = mrt->grpprev;

	/* Delete from the srcentry MRT chain */
	if (mrt->srcprev) {
	    mrt->srcprev->srcnext = mrt->srcnext;
	} else {
	    mrt->source->mrtlink = mrt->srcnext;
	    if (!mrt->srcnext)
		/* Delete the srcentry if this was the last routing entry */
		delete_srcentry(mrt->source);
	}

	if (mrt->srcnext)
	    mrt->srcnext->srcprev = mrt->srcprev;
    } else {
	/* This mrtentry should be (*,G) */
	grp	       = mrt->group;
	grp->grp_route = NULL;

	/* Delete the group entry if it has no (S,G) entries */
	if (!grp->mrtlink)
	    delete_grpentry(grp);
    }

    FREE_MRTENTRY(mrt);
}
コード例 #5
0
ファイル: route.c プロジェクト: 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;
}