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

📄 tc_linux.c

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 C
📖 第 1 页 / 共 2 页
字号:
		a.g_sum += fa->rate;		a.cl_rate = a.bw_max - a.g_sum;		goto finish;	}	return -1;finish:	*ai = a;	fa->commited = 1;	return 0;}int tc_admit(rsvp_qdisc_t *qi, struct admission_info *ai, flow_acinfo_t *a){	switch (a->admtype) {	case ADM_CL_STAT:		return is_cl_stat_admit(qi, ai, a);	case ADM_CL_DET:	case ADM_G_DET:		return is_g_det_admit(qi, ai, a);	default:		return -1;	}}void tc_unadmit(rsvp_qdisc_t *qi, struct admission_info *ai, flow_acinfo_t *a){	switch (a->admtype) {	case ADM_CL_STAT:		is_cl_stat_unadmit(qi, ai, a);		break;	case ADM_CL_DET:	case ADM_G_DET:		is_g_det_unadmit(qi, ai, a);		break;	}}/* * TC_AddFlowspec(): Call the kernel to make reservation for a flow. * 	It checks admission control, and returns a handle for the *	reservation, or -1 if an error.  It may also set *fwd_specpp * 	to point to a modified flowspec to be forwarded. */unsigned longTC_AddFlowspec(int OIf, FLOWSPEC *spec, SENDER_TSPEC *stspec, ADSPEC *adspp,					int flags, FLOWSPEC **fwd_specpp){	rsvp_qdisc_t *qi;	rsvp_flow_t *f = NULL;	struct admission_info ai;	rsvp_errno = 0;	*fwd_specpp = NULL;	if (OIf == if_num)		return 0;	if (!if_vec[OIf].if_up || (qi = ifl_vec[OIf].ifl_qdisc) == NULL) {		log(LOG_ERR, 0, "TC_AddFlowspec: err1 %d\n", OIf);		goto some_error;	}	f = malloc(sizeof(*f));	if (f == NULL)		goto some_error;	memset(f, 0, sizeof(*f));	f->qi = qi;	switch (Obj_CType(spec)) {	case ctype_FLOWSPEC_Intserv0:		is_admission_strategy(f, spec, stspec, adspp, flags);		break;	default:			log(LOG_ERR, 0, "TC_AddFlowspec: nosvc1\n");		goto nosvc_error;	}	if (f->ai.admtype == 0) {		log(LOG_ERR, 0, "TC_AddFlowspec: nosvc2\n");		goto nosvc_error;	}	ai = qi->ai;	if (tc_admit(qi, &qi->ai, &f->ai)) {		log(LOG_ERR, 0, "TC_AddFlowspec: nobw1\n");		goto nobw_error;	}	if (qi->qops->new_flow(f) == 0) {		f->next = qi->flow_list;		qi->flow_list = f;		f->magic = RSVP_FLOW_MAG;		return (unsigned long)f;	}	log(LOG_ERR, 0, "TC_AddFlowspec: new_flow\n");	qi->ai = ai;some_error:	rsvp_errno = Set_Errno(RSVP_Err_TC_ERROR, 0);err_out:	if (f)		free(f);    	return TC_ERROR;nosvc_error:	rsvp_errno = Set_Errno(RSVP_Err_TC_ERROR, RSVP_Erv_No_Serv);	goto err_out;nobw_error:	rsvp_errno = Set_Errno(RSVP_Err_ADMISSION, RSVP_Erv_Bandwidth);	goto err_out;}/* * TC_ModFlowspec(): Modifies a flowspec of a given flow. * *	It may also set *fwd_specpp to point to a modified flowspec to *	be forwarded. */intTC_ModFlowspec(int OIf, u_long rhandle,	       FLOWSPEC *specp, SENDER_TSPEC *stspecp, ADSPEC *adspecp,	       int flags, FLOWSPEC **fwd_specpp){	rsvp_flow_t	*f = (rsvp_flow_t*)rhandle;	rsvp_qdisc_t	*qi;	rsvp_flow_t	**fp;	rsvp_flow_t	new_f;	rsvp_filter_t	*fh;	struct admission_info ai;	if (OIf == if_num)		return 0;	if (!if_vec[OIf].if_up || (qi = ifl_vec[OIf].ifl_qdisc) == NULL)		goto some_error;	if (f == NULL || f->magic != RSVP_FLOW_MAG) {		log(LOG_ERR, 0, "bad flow %p/%d\n", f, f ? f->magic : 345);		goto some_error;	}	qi = f->qi;	for (fp = &qi->flow_list; *fp; fp = &(*fp)->next) {		if (*fp == f)			break;	}	if (*fp == NULL) {		log(LOG_ERR, 0, "TC_ModFlowspec: flow is lost!\n");		goto some_error;	}	*fwd_specpp = NULL;	memset(&new_f, 0, sizeof(new_f));	new_f.qi = qi;	switch (Obj_CType(specp)) {	case ctype_FLOWSPEC_Intserv0:		is_admission_strategy(&new_f, specp, stspecp, adspecp, flags);		break;	default:			goto nosvc_error;	}	if (new_f.ai.admtype == 0)		goto nosvc_error;	ai = qi->ai;	tc_unadmit(qi, &qi->ai, &f->ai);	if (tc_admit(qi, &qi->ai, &new_f.ai)) {		qi->ai = ai;		goto nobw_error;	}	if (qi->qops->mod_flow(f, &new_f)) {		qi->ai = ai;		goto some_error;	}	f->ai = new_f.ai;	f->class = new_f.class;	f->classid = new_f.classid;	f->policer = new_f.policer;	for (fh = f->filters; fh; fh = fh->next)		tc_mod_filter(fh);	return TC_OK;some_error:	rsvp_errno = Set_Errno(RSVP_Err_TC_ERROR, 0);err_out:    	return TC_ERROR;nosvc_error:	rsvp_errno = Set_Errno(RSVP_Err_TC_ERROR, RSVP_Erv_No_Serv);	goto err_out;nobw_error:	rsvp_errno = Set_Errno(RSVP_Err_ADMISSION, RSVP_Erv_Bandwidth);	goto err_out;}/* * TC_DelFlowspec(): This routine deletes flow for specified handle */intTC_DelFlowspec(int OIf, unsigned long rhandle){	rsvp_flow_t	*f = (rsvp_flow_t*)rhandle;	rsvp_qdisc_t	*qi;	rsvp_flow_t	**fp;	rsvp_filter_t	*fh;	if (f == NULL || f->magic != RSVP_FLOW_MAG) {		log(LOG_ERR, 0, "bad flow %p/%d\n", f, f ? f->magic : 345);		return 0;	}	qi = f->qi;	/* Kill filters owned by this flow */	while ((fh = f->filters) != NULL) {		f->filters = fh->next;		tc_del_filter(fh);		fh->magic = -fh->magic;		free(fh);	}	for (fp = &qi->flow_list; *fp; fp = &(*fp)->next) {		if (*fp == f) {			*fp = f->next;			tc_unadmit(qi, &qi->ai, &f->ai);			qi->qops->del_flow(f);			f->magic = -f->magic;			free(f);			return 0;		}	}	log(LOG_ERR, 0, "TC_DelFlowspec: flow is lost!\n");	f->magic = -f->magic;	return 0;}/* * TC_AddFilter(): Adds a filter for an existing flow. * *	Returns fhandle or TC_ERROR. */unsigned longTC_AddFilter(int OIf, unsigned long rhandle, Session *dest, FILTER_SPEC *filtp){	rsvp_filter_t *fh;	rsvp_flow_t *f = (rsvp_flow_t*)rhandle;	if (f == NULL || OIf == if_num || !if_vec[OIf].if_up)		return TC_OK;	assert(f->qi->link == &ifl_vec[OIf]);	rsvp_errno = 0;		fh = malloc(sizeof(*fh));	if (fh) {		memset(fh, 0, sizeof(*fh));		fh->flow = f;		if (tc_add_filter(fh, filtp, dest) == 0) {			fh->next = f->filters;			f->filters = fh;			fh->magic = RSVP_FILTER_MAG;			return (unsigned long)fh;		}		free(fh);	}	if (!rsvp_errno) 		rsvp_errno = RSVP_Err_TC_ERROR;	return TC_ERROR;}/* * TC_DelFilter(): Deletes existing filter. */intTC_DelFilter(int OIf, unsigned long fhandle){	rsvp_filter_t **fhp;	rsvp_filter_t *fh = (rsvp_filter_t*)fhandle;	rsvp_flow_t *f;	rsvp_errno = 0;	if (fh == NULL || fh->magic != RSVP_FILTER_MAG) {		log(LOG_ERR, 0, "bad filter %p/%d\n", fh, fh ? fh->magic : 345);		rsvp_errno = RSVP_Err_TC_ERROR;		return TC_ERROR;	}	f = fh->flow;	for (fhp = &f->filters; *fhp; fhp = &(*fhp)->next) {		if (fh == *fhp) {			*fhp = fh->next;			if (f->policer.action == TC_POLICE_RECLASSIFY &&			    f->filters == NULL)				f->policer.index = 0;			tc_del_filter(fh);			fh->magic = -fh->magic;			free(fh);			return TC_OK;		}	}	fh->magic = -fh->magic;	log(LOG_ERR, 0, "TC_DelFilter: filter is lost!\n");	if (!rsvp_errno) 		rsvp_errno = RSVP_Err_TC_ERROR;	return TC_ERROR;}#define CLAMPED_ADD(a, b) \({ __u32 _a = (a); __u32 _b = (b); \   if (_b == 0xFFFFFFFFU || _b >= 0xFFFFFFFFU - _a) \	   (a) = 0xFFFFFFFFU; \   else \	   (a) = _a + _b; \})static int adspec_adv_gen_parms(int OIf, IS_serv_hdr_t *shp){	IS_parm_hdr_t *php;	IS_parm_hdr_t *lastphp;	rsvp_qdisc_t	*qi = ifl_vec[OIf].ifl_qdisc;	float32_t	hop_bw;	u_int32_t	hop_latency, hop_mtu;	if (qi)		hop_bw = qi->ai.bw_max - qi->ai.g_sum;	else		hop_bw = qi->link->ifl_path_bw ? : TC_DFLT_PATH_BW;	hop_latency = qi->link->ifl_min_latency ? : TC_DFLT_MIN_LATENCY;	hop_mtu = qi->link->ifl_path_mtu ? : TC_DFLT_MTU;	php = (IS_parm_hdr_t *)(shp+1);	lastphp = (IS_parm_hdr_t *)Next_Serv_Hdr(shp);	while (php < lastphp) {		switch (php->isph_parm_num) {		case IS_WKP_HOP_CNT:			(*(u_int32_t *)(php+1))++;			break;		case IS_WKP_MIN_LATENCY:			CLAMPED_ADD(*(u_int32_t *)(php+1), hop_latency);			break;		case IS_WKP_COMPOSED_MTU:			(*(u_int32_t *)(php+1)) = MIN(hop_mtu, (*(u_int32_t *)(php+1)));			break;		case IS_WKP_PATH_BW:			(*(float32_t *)(php+1)) = MIN(hop_bw, (*(float32_t *)(php+1)));			break;		default:			break;		}		php = Next_Parm_Hdr(php);	}	return 0;}static int adspec_adv_gs_parms(int OIf, IS_serv_hdr_t *shp){	IS_parm_hdr_t *php;	IS_parm_hdr_t *lastphp;	rsvp_qdisc_t	*qi = ifl_vec[OIf].ifl_qdisc;	php = (IS_parm_hdr_t *)(shp+1);	lastphp = (IS_parm_hdr_t *)Next_Serv_Hdr(shp);	while (php < lastphp) {		switch (php->isph_parm_num) {		case GUAR_ADSPARM_Csum:			/* Hey, guys! How can I know here, that			   I am reshaper and, hence, should			   reset Csum/Dsum ?			   I need at least path information			   to make it. Is it bug in functional spec??			 */			if (0)				(*(u_int32_t *)(php+1)) = 0;		case GUAR_ADSPARM_Ctot:			CLAMPED_ADD(*(u_int32_t *)(php+1), qi->C);			break;		case GUAR_ADSPARM_Dsum:			if (0)				(*(u_int32_t *)(php+1)) = 0;		case GUAR_ADSPARM_Dtot:			CLAMPED_ADD(*(u_int32_t *)(php+1), qi->D*1000000);			break;		default:			break;		}		php = Next_Parm_Hdr(php);	}	return 0;}static int adspec_new_gs_parms(int OIf, IS_serv_hdr_t *shp){	Gads_parms_t *g = (Gads_parms_t*)shp;	memset(shp+1, 0, sizeof(Gads_parms_t)-sizeof(*shp));	Issh_len32b(shp) = wordsof(sizeof(Gads_parms_t))-1;	g->Gads_Ctot_hdr.isph_parm_num = GUAR_ADSPARM_Ctot;	g->Gads_Ctot_hdr.isph_len32b = 1;	g->Gads_Dtot_hdr.isph_parm_num = GUAR_ADSPARM_Dtot;	g->Gads_Dtot_hdr.isph_len32b = 1;	g->Gads_Csum_hdr.isph_parm_num = GUAR_ADSPARM_Csum;	g->Gads_Csum_hdr.isph_len32b = 1;	g->Gads_Dsum_hdr.isph_parm_num = GUAR_ADSPARM_Dsum;	g->Gads_Dsum_hdr.isph_len32b = 1;	return 0;}/* * TC_Advertise(): Given existing OPWA ADSPEC, return a new updated object. */ADSPEC *TC_Advertise(int OIf, ADSPEC * old_asp, int flags){	/* Room for expanded Guaranteed svc header is reserved */	ADSPEC *new_asp = (void*)malloc(Object_Size(old_asp) + sizeof(Gads_parms_t));	const IS_main_hdr_t   *old_mhp = (IS_main_hdr_t *) Obj_data(old_asp);	IS_serv_hdr_t	*shp, *lastshp;	IS_main_hdr_t   *mhp;	rsvp_qdisc_t	*qi = ifl_vec[OIf].ifl_qdisc;	Obj_Class(new_asp) = Obj_Class(old_asp);	Obj_CType(new_asp) = Obj_CType(old_asp);	Obj_Length(new_asp) = sizeof(Object_header);	/* Copy main header */	mhp = (IS_main_hdr_t *) Obj_data(new_asp);	Obj_Length(new_asp) += sizeof(*old_mhp);	*mhp = *old_mhp;	mhp->ismh_len32b = 0;	/* Scan service headers and copy them */	shp = (IS_serv_hdr_t *)(old_mhp+1);	lastshp  = (IS_serv_hdr_t *) Next_Main_Hdr(old_mhp);	while (shp < lastshp) {		IS_serv_hdr_t *nshp = (void*)Next_Main_Hdr(mhp);		/* Copy all the service header */		memcpy(nshp, shp, Issh_len32b(shp)*4 + sizeof(*shp));		if (!if_vec[OIf].if_up || qi == NULL) {			/* No RSVP support here */			if (shp->issh_service != GENERAL_INFO)				Set_Break_Bit(nshp);		} else {			switch (shp->issh_service) {			default:				Set_Break_Bit(nshp);				/* Update gen parms in any case... */			case GENERAL_INFO:			case CONTROLLED_LOAD_SERV:				adspec_adv_gen_parms(OIf, nshp);				break;			case GUARANTEED_SERV:				if (Issh_len32b(nshp) == 0) {					adspec_new_gs_parms(OIf, nshp);				} else if (Issh_len32b(nshp) < wordsof(sizeof(Gads_parms_t))-1) {					log(LOG_ERR, 0, "illegal Gads parms\n");					Set_Break_Bit(nshp);					break;				}				adspec_adv_gs_parms(OIf, nshp);				adspec_adv_gen_parms(OIf, nshp);				break;			}			/* ADVERTF_NonRSVP flag means, that PREVIOUS			   hop is non-RSVP. However, we update			   adspec, it could be still useful.			 */			if (flags & ADVERTF_NonRSVP)				Set_Break_Bit(nshp);		}		mhp->ismh_len32b += Issh_len32b(nshp) + 1;		Obj_Length(new_asp) += (Issh_len32b(nshp) + 1) * 4;		shp = Next_Serv_Hdr(shp);	}	return new_asp;}

⌨️ 快捷键说明

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