⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rsvp_resv.c

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (IsHopAPI(&sp->ps_phop)) {			if (rp->rs_confirm) {				send_confirm(destp, rp);				rp->rs_confirm = NULL;			}			continue;		}					/*		 * 2. (If the B_Merge flag is off then) ignore a blockaded		 *	RSB, as follows.		 *		 *      Select BSBs that match this RSB.  If any of		 *	these BSBs has a Qb that is not strictly larger		 *	than TC_Flowspec, then this RSB is blockaded;		 *	continue processing with the next RSB.		 */		fwd_specp = (rp->rs_fwd_spec)? rp->rs_fwd_spec: rp->rs_spec;		if (BSBp->ps_BSB_Qb && LT(BSBp->ps_BSB_Tb, time_now)) {			/* Blockade state has timed out; delete it.			 */			free(BSBp->ps_BSB_Qb);			BSBp->ps_BSB_Qb = NULL;			BSBp->ps_BSB_Tb = 0;		}		if ((BSBp->ps_BSB_Qb) &&		     Compare_Flowspecs(BSBp->ps_BSB_Qb, fwd_specp)!=SPEC1_GTR) {			Incr_ifstats(BSBp->ps_in_if, rsvpstat_blockade_ev);			continue;		}		n_match++;		/*		 *	3. Merge the flowspecs from this set of RSBs.		 *	   Maintain RSB seen so far that has largest flowspec		 *	   in confRSBp, for sending a confirm message.		 */		cmp = Compare_Flowspecs(fwd_specp, max_specp);		assert(cmp != SPECS_INCOMPAT);		if (cmp == SPEC1_GTR) {			max_specp = fwd_specp;			if (confRSBp && !IsHopAPI(&rp->rs_nhop))			    send_confirm(destp, confRSBp);			confRSBp = NULL;			if (rp->rs_confirm)				confRSBp = rp;		}		else {			if (cmp == SPECS_USELUB)				max_specp =				      LUB_of_Flowspecs(rp->rs_spec, max_specp);			if (rp->rs_confirm)				send_confirm(destp, rp);		}		/*		 *	Also merge the lists of unknown objects, if any.		 */#define MAKE_COPY 1		merge_UnkObjL2(&rp->rs_UnkObjList, &UnkObjectL, MAKE_COPY);	}	if (IsHopAPI(&sp->ps_phop))		return(0);	/*	However, if steps 1 and 2 result in finding that all	 *	RSBs matching this PSB are blockaded, then:	 *	-  If this Resv REFRESH sequence was invoked from	 *	   accept_resv_err(), then return to the latter.	 *	-  Otherwise, turn on the B_Merge flag and restart at	 *	   step 1 (actually, second copy of code):	 */	if (n_match == 0) {		if (IsResvErr)			return(0);		B_Merge = 1;		/* (isn't really used) */		max_specp = NULL;		for (rp = destp->d_RSB_list; rp != NULL; rp = rp->rs_next) {			if (!PSBmaps2RSB(destp, sp, rp))				continue;			/*			 *	3. Merge the flowspecs from this set of			 *	   RSBs, as follows.			 *			 *	   Compute the GLB over the Flowspec objects			 *	   of this set of RSBs.			 *	   While computing the GLB, delete any			 *	   RESV_CONFIRM objects.			 */			n_match++;			max_specp = GLB_of_Flowspecs(rp->rs_spec, max_specp);			assert(max_specp); /* These flowspecs must be OK */			if (rp->rs_confirm) {				free(rp->rs_confirm);				rp->rs_confirm = NULL;			}			confRSBp = NULL;			merge_UnkObjL2(&rp->rs_UnkObjList, &UnkObjectL, 								MAKE_COPY);		}	}	/*	 *	All matching RSB's have been processed.  If there	 *	were some, do style-dependent processing:	 *	    o Distinct style (FF): Pack flow descriptor into pkt.	 *	    o Shared style (SE,WF): continue to merge.	 */	if (n_match) {		flwdp = FlowDesc_of(pkt, pkt->rsvp_nflwd);		assert(max_specp);		switch (style) {		case STYLE_WF:			flwdp->rsvp_specp = max_specp;			flwdp->rsvp_filtp = NULL;			pkt->rsvp_nflwd = 1;			/*			 *    If this sender has scope bit on, add this			 *    sender host to the outgoing SCOPE list.			 */			if (sp->ps_flags & PSBF_InScope)				scope_catf(&mapp->rsvp_scope_list, sp->ps_templ);			break;		case STYLE_FF:			if (!confRSBp &&			    sameas_last_spec(&sp->ps_resv_spec, max_specp)) {				max_specp = NULL;				FQkill(&UnkObjectL);				break;			}			flwdp->rsvp_specp = max_specp;			max_specp = NULL;			/*  To merge filter specs, simply use sender template,			 */			flwdp->rsvp_filtp = sp->ps_templ;			pkt->rsvp_nflwd++; /* Test nflwd for overflow XXX */			break;		case STYLE_SE:			(FlowDesc_of(pkt, 0))->rsvp_specp = max_specp;			flwdp->rsvp_filtp = sp->ps_templ;			pkt->rsvp_nflwd++;  /* Test nflwd for overflow XXX */			break;		}	}	merge_UnkObjL2(&UnkObjectL, &UnkObjL_perPHOP, !MAKE_COPY);	/*	 *  Senders are ordered by phop address.  Return if next PSB has	 *  the same PHOP, else finish up message and send it.	 */	if (sp->ps_next && hop_addr_eq(&sp->ps_next->ps_phop,&sp->ps_phop)) {		return(0);	}	/*	If there are no flow descriptors, or if new flowspec is same	 *	as last sent for this PSB, the filter spec list did not change,	 *	and there is no confirmation request, return without sending.	 */	if (pkt->rsvp_nflwd == 0 	    || ( Style_is_Shared(style)		&& !confRSBp		&& sameas_last_spec(&BSBp->ps_resv_spec, max_specp)	       )){		FQkill(&UnkObjL_perPHOP);		pkt->rsvp_nflwd = 0;		return(0);	}	pkt->pkt_map->rsvp_UnkObjList = UnkObjL_perPHOP;	UnkObjL_perPHOP = NULL;	/*	 *	If a RESV_CONFIRM object was saved earlier, put a ptr	 *	to it in the new Resv message.	 */	if (confRSBp)		mapp->rsvp_confirm = confRSBp->rs_confirm;	/*	If the style is wildcard, decide whether a SCOPE object	 *	must be sent.	 */	if (Style_is_Wildcard(style))		Need_Scope = is_scope_needed(destp, sp);	/*	 *	Send Resv message (unless there is an empty scope list) 	 *	Must first make copy of filter spec objects and set their	 *	class (because they were SENDER_TEMPLATEs); then free copies.	 */	if (!Need_Scope || mapp->rsvp_scope_list) {		for (i= 0; i < pkt->rsvp_nflwd; i++) {			flwdp = FlowDesc_of(pkt, i);			if (flwdp->rsvp_filtp) {				flwdp->rsvp_filtp= 						copy_filter(flwdp->rsvp_filtp);				Obj_Class(flwdp->rsvp_filtp)= class_FILTER_SPEC;			}		}		send_resv_out(sp, pkt);		for (i= 0; i < pkt->rsvp_nflwd; i++) {			flwdp = FlowDesc_of(pkt, i);			if (flwdp->rsvp_filtp)				free(flwdp->rsvp_filtp);		}	} else		/* Was not sent because scope list was empty */		Incr_ifstats(sp->ps_in_if, rsvpstat_no_outscope);	/*	 *	Free storage and re-initialize pkt for next PHOP	 */	for (i= 0; i < pkt->rsvp_nflwd; i++) {		flwdp = FlowDesc_of(pkt, i);		flwdp->rsvp_specp = NULL;	}	pkt->rsvp_nflwd = 0;	if (mapp->rsvp_scope_list) {		free(mapp->rsvp_scope_list);		mapp->rsvp_scope_list = NULL;	}	max_specp = NULL;	FQkill(&pkt->pkt_map->rsvp_UnkObjList);	return(0);}/*	Compare new resv refresh flowspec for particular sender/phop *	with the last one sent.  If they are equal, return 1, else *	save new one and return 0. */intsameas_last_spec(FLOWSPEC **last_specpp, FLOWSPEC *newspecp)	{	if (*last_specpp	      && Compare_Flowspecs(*last_specpp, newspecp) == SPECS_EQL)		return(1);	if (*last_specpp)		free(*last_specpp);	*last_specpp = copy_spec(newspecp);	return(0);}#ifdef ISI_TEST#define MAX_RTEAR_PACK 2 /* XXX  (For testing!) ***/#else#define MAX_RTEAR_PACK MAX_FLWDS#endif/* * cleanup_resv_state():  For given session, kill all expired reservations. *		For consistency, we kill a reservation by constructing and *		processing a dummy RESV_TEAR message. */intcleanup_resv_state(Session *destp)	{	packet_area	 data;	struct packet	*pkt = NULL;	RSB		*rp, *rpn;	FlowDesc	*flwdp;	int		 i;	rpn = destp->d_RSB_list;	/* Next RSB */	while (rpn) {		rp = rpn;		rpn = rpn->rs_next;		if (!LT(rp->rs_ttd, time_now))			continue;		Incr_ifstats(rp->rs_OIf, rsvpstat_resv_timeout);		/*	Found timed-out RSB.  Fake teardown message for it.		 */		if (pkt == NULL) {			pkt = new_packet_area(&data);			common_resv_tear_header(pkt, destp);		}		Style_of(pkt)->style_word = rp->rs_style;		*pkt->rsvp_nhop = rp->rs_rsvp_nhop;		if (Style_is_Wildcard(rp->rs_style)) {			flwdp = FlowDesc_of(pkt, 0);		    	flwdp->rsvp_filtp = NULL;			flwdp->rsvp_specp = NULL;			pkt->rsvp_nflwd = 1;		} else {				    for (i= 0; i < rp->rs_fcount; i++) {			if (LT(rp->rs_Filt_TTD(i), time_now)) {			    /*			     *  Individual filter has timed out.			     *	If packet is full, process dummy pkt and			     *	start again.  Add filter to dummy pkt.			     */			    if (pkt->rsvp_nflwd >= MAX_RTEAR_PACK) {				process_dummy_rtear(pkt);				pkt->rsvp_nflwd = 0;			    }			    flwdp = FlowDesc_of(pkt, pkt->rsvp_nflwd);		    	    flwdp->rsvp_filtp = copy_filter(rp->rs_Filtp(i));			    flwdp->rsvp_specp = NULL;			    pkt->rsvp_nflwd++;			}		    }		}		if (Style_is_Shared(rp->rs_style) || rpn == NULL ||		    !hop_addr_eq(&rpn->rs_nhop, &rp->rs_nhop)) {			/* A little optimization: if a set of FF-style			 * reservations time out at the same time, try			 * (but not hard) to packet teardowns into same			 * RTear. Works if order of RSB list is right.			 */						if (pkt->rsvp_nflwd) { 				process_dummy_rtear(pkt);				pkt->rsvp_nflwd = 0;				}				}						}	return(0);}voidprocess_dummy_rtear(struct packet *pkt)	{	int i;	if (!pkt)		return;	accept_resv_tear(-1, pkt);	for (i= 0; i < pkt->rsvp_nflwd; i++) {		if (spec_of(FlowDesc_of(pkt, i)))			free(spec_of(FlowDesc_of(pkt, i)));		if (filter_of(FlowDesc_of(pkt, i)))			free(filter_of(FlowDesc_of(pkt, i)));	}}/* *  delete_resv4PSB():  Delete reservations corresponding to given PSB, *		which is already deleted from session list. Called from  *		kill_PSB(). */voiddelete_resv4PSB(Session *destp, PSB *psbp)	{	RSB		*rp, *rpn;	int		j, rc;	/*	 *	Find each RSB that matches this PSB	 */	for (rp = destp->d_RSB_list; rp != NULL; rp = rpn) {		rpn = rp->rs_next;		if (!PSBmaps2RSB(destp, psbp, rp))			continue;					if (!Style_is_Shared(rp->rs_style)) {			kill_RSB(destp, rp);			/* Style FF: delete RSB and update link layer.			 */		}		else if (Style_is_Wildcard(rp->rs_style)) {			PSB	*sp;			/*			 *  Wildcard (WF) style => If there is another			 *	matching PSB, update link layer and continue			 *	with next RSB; else, delete RSB & update LL.			 */ 			for (sp = destp->d_PSB_list; sp; sp = sp->ps_next) {				if (sp != psbp &&				   IsRoutePSB2nhop(destp,sp,&rp->rs_rsvp_nhop))					break;			}			if (sp) {				rc = LL_ModFlowspec(rp->rs_OIf, destp, rp);				if (rc != LLDAL_RC_LATER) /* synchronous */					Complete_ModFlowspec(destp, rp, rc);				continue;			}			else				kill_RSB(destp, rp);					}		else {	/* Else SE style.  Delete matching filter specs.			 * 	If filters all gone, delete RSB & update LL.			 */			for (j= 0; j < rp->rs_fcount; j++) {				if (match_filter(psbp->ps_templ,						rp->rs_Filtp(j))){					free(rp->rs_Filtp(j));					rp->rs_Filt_TTD(j) = 0;				}	  		}			coalesce_filtstar(rp->rs_filtstar);			if (rp->rs_fcount == 0)				kill_RSB(destp, rp);			else {				rc = LL_ModFilter(rp->rs_OIf, destp, rp);				if (rc != LLDAL_RC_LATER)					Complete_ModFilter(destp, rp, rc);			}		}	}}/*	Update link-layer reservation with respect to given PSB, which *	is new or changed. */voidPSB_update_LL(Session *destp, PSB *psbp)	{	RSB		*rp;	bitmap		out_vifs;	int		rc;	bmp_rst(&out_vifs);	/* None seen yet */	for (rp = destp->d_RSB_list; rp != NULL; rp = rp->rs_next) {		/*		 *	Search for first RSB for given OI that PSB		 *	routes to and whose Filter_spec_list includes		 *	a FILTER_SPEC matching the SENDER_TEMPLATE.		 *	Using this as the 'active RB', update traffic		 *	control on that OI.  Use bit mask out_vifs to		 *	process only one RSB per distinct OI.		 */		if (!PSBmaps2RSB(destp, psbp, rp))			continue;		if (bmp_tst(&out_vifs, rp->rs_OIf))			continue;		bmp_set(&out_vifs, rp->rs_OIf);  /* ignore later RSBs */		/*		 *	Update traffic control.  In unlikely event		 *	that admission Control fails, send ResvErr msg		 */                rc = LL_ModFlowspec(rp->rs_OIf, destp, rp);		if (rc != LLDAL_RC_LATER)	/* synchronous */			Complete_ModFlowspec(destp, rp, rc);	}}/* * 	IsRoutePSB2nhop():	Return 1 if sender defined by PSB can *				route to specified next hop. */intIsRoutePSB2nhop(Session *destp, PSB *psbp, RSVP_HOP *hopp)	{	/*	 *	If Resv came from network, it cannot match LocalOnly PSB.	 */ 		if (!IsHopAPI(hopp)) {		if  (psbp->ps_flags & PSBF_LocalOnly)			return(0);		else if (bmp_tst(&(psbp->ps_outif_list), hop_lih(hopp)))			return(1);	}	else  {		/*	Resv came from API.  OK if:		 *	* dest is unicast, or		 *	* incoming interface matches recv interface, or		 *	* PSB not LocalOnly and not from API and routes to OI.		 */		if (IF_UNICAST(psbp->ps_in_if) == hop_lih(hopp))			return(1);		else if (!session_multicast(destp->d_session))			return(1);		else if (!(psbp->ps_flags & PSBF_LocalOnly) &&			  !IsHopAPI(&psbp->ps_phop) &&			  bmp_tst(&(psbp->ps_outif_list), hop_lih(hopp)))			return(1);	}	return(0);}/*	Search for (any) RSB that matches the given PSB */RSB *RSB_match_path(Session *destp, PSB *psbp)	{	RSB		*rp;	for (rp = destp->d_RSB_list; rp; rp = rp->rs_next) {		if (PSBmaps2RSB(destp, psbp, rp))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -