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

📄 tc_cbq.c

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * tc_cbq.c * *		This program is free software; you can redistribute it and/or *		modify it under the terms of the GNU General Public License *		as published by the Free Software Foundation; either version *		2 of the License, or (at your option) any later version. * * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * */#include <stddef.h>#include <sys/types.h>#include <linux/types.h>#include "rsvp_daemon.h"#include "rapi_lib.h"		/* Define flowspec formats */#include "rsvp_specs.h"		/* Flowspec descriptor format */#include "rsvp_TCif.h"		/* Adaptation interface */extern double pow(double x, double y);extern double exp(double x);#include "libnetlink.h"#include "tc_linux.h"struct cbq_class{	struct cbq_class 	*next;	Chandle			classid;	Chandle			parent;	struct tc_cbq_lssopt	lss;	struct tc_cbq_wrropt	wrr;	struct tc_ratespec	rate;};struct cbq_qdisc{	rsvp_qdisc_t		*qi;	struct cbq_class	lll;	struct cbq_class	is_g;	struct cbq_class	*is_cl;};unsigned tc_cbq_calc_maxidle(unsigned bndw, unsigned rate, unsigned avpkt,			     int ewma_log, unsigned maxburst){	double maxidle;	double g = 1.0 - 1.0/(1<<ewma_log);	double xmt = (double)avpkt/bndw;	maxidle = xmt*(1-g);	if (bndw != rate && maxburst) {		double vxmt = (double)avpkt/rate - xmt;		vxmt *= (pow(g, -(double)maxburst) - 1);		if (vxmt > maxidle)			maxidle = vxmt;	}	return tc_core_usec2tick(maxidle*(1<<ewma_log)*1000000);}unsigned tc_cbq_calc_offtime(unsigned bndw, unsigned rate, unsigned avpkt,			     int ewma_log, unsigned minburst){	double g = 1.0 - 1.0/(1<<ewma_log);	double offtime = (double)avpkt/rate - (double)avpkt/bndw;	if (minburst == 0)		return 0;	if (minburst == 1)		offtime *= pow(g, -(double)minburst) - 1;	else		offtime *= 1 + (pow(g, -(double)(minburst-1)) - 1)/(1-g);	return tc_core_usec2tick(offtime*1000000);}static intstore_classinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg){	struct tcmsg *t = NLMSG_DATA(n);	struct rtattr *tb[TCA_MAX+1];	struct rtattr *rta[TCA_CBQ_MAX+1];	rsvp_qdisc_t	*qi = arg;	struct cbq_qdisc *cbq = qi->data;	struct cbq_class *cl = NULL;	if (n->nlmsg_type != RTM_NEWTCLASS)		return 0;	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(t)))		return -1;	if (qi->link->ifl_index != t->tcm_ifindex)		return 0;	if (TC_H_MAJ(t->tcm_parent^qi->handle) && t->tcm_parent != TC_H_ROOT)		return 0;	if (t->tcm_handle == TC_H_MAKE(qi->handle, 0)) {		cl = &cbq->lll;	} else if (t->tcm_handle == TC_H_MAKE(qi->handle, 0x7FFE)) {		cl = &cbq->is_g;	}	parse_rtattr(tb, TCA_MAX, TCA_RTA(t), TCA_PAYLOAD(n));	if (tb[TCA_OPTIONS])		parse_rtattr(rta, TCA_CBQ_MAX, RTA_DATA(tb[TCA_OPTIONS]), RTA_PAYLOAD(tb[TCA_OPTIONS]));	if (rta[TCA_CBQ_LSSOPT] == NULL || rta[TCA_CBQ_WRROPT] == NULL ||	    rta[TCA_CBQ_RATE] == NULL)		return 0;	if (cl == NULL) {		if ((cl = malloc(sizeof(*cl))) == NULL)			return -1;		memset(cl, 0, sizeof(*cl));	}	cl->classid = t->tcm_handle;	cl->parent = t->tcm_parent;	memcpy(&cl->lss, RTA_DATA(rta[TCA_CBQ_LSSOPT]), sizeof(cl->lss));	memcpy(&cl->wrr, RTA_DATA(rta[TCA_CBQ_WRROPT]), sizeof(cl->wrr));	memcpy(&cl->rate, RTA_DATA(rta[TCA_CBQ_RATE]), sizeof(cl->rate));	if (cl != &cbq->lll && cl != &cbq->is_g) {		if (cl->wrr.priority != 1) {			free(cl);			return 0;		}		cl->next = cbq->lll.next;		cbq->lll.next = cl;	}	return 0;}static int cbq_alloc(rsvp_qdisc_t *qi, struct tcmsg *tcm, struct rtattr **rta){	struct rtattr *tb[TCA_CBQ_MAX+1];	struct cbq_qdisc *cbq;	if (rta[TCA_OPTIONS] == NULL)		return -1;	cbq = malloc(sizeof(*cbq));	if (cbq == NULL)		return -1;	memset(cbq, 0, sizeof(struct cbq_qdisc));	cbq->qi = qi;	qi->data = cbq;	parse_rtattr(tb, TCA_CBQ_MAX, RTA_DATA(rta[TCA_OPTIONS]),		     RTA_PAYLOAD(rta[TCA_OPTIONS]));	cbq->lll.classid = tcm->tcm_handle;	if (tb[TCA_CBQ_LSSOPT])		memcpy(&cbq->lll.lss, RTA_DATA(tb[TCA_CBQ_LSSOPT]), sizeof(cbq->lll.lss));	if (tb[TCA_CBQ_WRROPT])		memcpy(&cbq->lll.wrr, RTA_DATA(tb[TCA_CBQ_WRROPT]), sizeof(cbq->lll.wrr));	if (tb[TCA_CBQ_RATE])		memcpy(&cbq->lll.rate, RTA_DATA(tb[TCA_CBQ_RATE]), sizeof(cbq->lll.rate));	return 0;}static void cbq_free(rsvp_qdisc_t *qi){	struct cbq_qdisc *cbq = qi->data;	struct cbq_class *cl;	qi->data = NULL;	while ((cl = cbq->lll.next) != NULL) {		cbq->lll.next = cl->next;		free(cl);	}	free(cbq);}static void cbq_free_class(rsvp_qdisc_t *qi, struct cbq_class *cl){	struct cbq_qdisc *cbq = qi->data;	struct cbq_class **clp;	for (clp = &cbq->lll.next; *clp; clp = &(*clp)->next) {		if (cl == *clp) {			*clp = cl->next;			free(cl);			return;		}	}}static void cbq_kill_classes(rsvp_qdisc_t *qi){	int level;	struct cbq_qdisc *cbq = qi->data;	struct cbq_class *cl, **clp;	for (level = 0; level <= TC_CBQ_MAXLEVEL; level++) {		clp = &cbq->lll.next;		while ((cl = *clp) != NULL) {			if (cl->lss.level <= level &&			    tc_kill_class(qi->link->ifl_index, cl->classid) == 0) {				*clp = cl->next;				free(cl);				continue;			}			clp = &cl->next;		}	}}static void cbq_clear(rsvp_qdisc_t *qi){	struct cbq_qdisc *cbq = qi->data;	if (cbq->lll.classid)		tc_kill_filters(qi, cbq->lll.classid);	cbq_kill_classes(qi);}static int cbq_start(rsvp_qdisc_t *qi){	struct cbq_qdisc *cbq = qi->data;	struct cbq_class *cl;	if (cbq->lll.rate.rate == 0) {		log(LOG_ERR, 0, "CBQ@%s: no all-link class\n", qi->link->ifl_name);		return -1;	}	if (cbq->is_g.rate.rate == 0) {		log(LOG_ERR, 0, "CBQ@%s: no reserved class\n", qi->link->ifl_name);		return -1;	}	qi->link->ifl_path_bw = cbq->lll.rate.rate;	tc_init_filters(qi, cbq->lll.classid);	/* These parameters must be settable via config file! */	qi->ai.epsilon = 1e-6;	qi->ai.g_max = 15;	qi->ai.cl_max = 256;	qi->ai.mem_max = 1024*1024;	qi->ai.interval = 1;	qi->ai.time_const = 8;	qi->laddend = 0;	qi->lmtu = cbq->lll.wrr.allot;	qi->wfactor = (float)cbq->is_g.rate.rate/cbq->is_g.wrr.weight;	qi->llhead = qi->lmtu - qi->link->ifl_path_mtu;	/* Account for ping-pong buffers.	   Dmaing cards need TX queue len-1 instead of 1 (f.e. 15 for tulip)	 */	qi->lmaxlatency = (double)qi->lmtu/cbq->lll.rate.rate;	if (qi->link->ifl_min_latency == 0)		qi->link->ifl_min_latency = 1000000*(double)cbq->lll.rate.mpu/cbq->lll.rate.rate;	/* Calculate some values */	qi->ai.ewma_const = exp(-(float)qi->ai.interval/qi->ai.time_const);	qi->ai.bw_max = cbq->is_g.rate.rate;	qi->D = qi->lmaxlatency + 2*(double)qi->lmtu*qi->ai.g_max/cbq->lll.rate.rate;	qi->C = (double)qi->lmtu*cbq->is_g.rate.rate/cbq->lll.rate.rate;	for (cl = cbq->lll.next; cl; cl = cl->next) {		qi->ai.g_max--;		qi->ai.bw_max -= cl->rate.rate;		log(LOG_ERR, 0, "CBQ@%s: stale class %08x eated %dbps\n",		    qi->link->ifl_name, cl->classid, cl->rate.rate);	}	if (qi->ai.g_max <= 0 || qi->ai.bw_max <= 0) {		log(LOG_ERR, 0, "CBQ@%s: no capacities for reservations.\n",		    qi->link->ifl_name);		return -1;	}	/* OK. Machine is ready to fly! */	return 0;}static int cbq_init(rsvp_qdisc_t *qi){	struct tcmsg t;	memset(&t, 0, sizeof(t));	t.tcm_parent = qi->handle;	t.tcm_ifindex = qi->link->ifl_index;	if (rtnl_dump_request(&tc_nl, RTM_GETTCLASS, &t, sizeof(t)) < 0) {		log(LOG_ERR, errno, "cannot send dump request");		return -1;	}	if (rtnl_dump_filter(&tc_nl, store_classinfo, qi) < 0) {		log(LOG_ERR, errno, "dump terminated\n");		cbq_clear(qi);		return -1;	}	/* Clear old CBQ state */	cbq_clear(qi);	/* Start CBQ */	if (cbq_start(qi)) {		cbq_clear(qi);		return -1;	}	return 0;}int cbq_sync_cl(rsvp_qdisc_t *qi){	struct cbq_qdisc *cbq = qi->data;	struct cbq_class *cl = cbq->is_cl;	struct tc_estimator est;	struct tc_cbq_police pol;	__u32 rtab[256];	char buf[4096];	struct rtattr *rta = (void*)buf;	if (qi->ai.cl_num == 0) {		qi->ai.cl_cur_rate = qi->ai.cl_rate;		if (cl == NULL)			return 0;		log(LOG_DEBUG, 0, "kill class %08x\n", cl->classid);		if (tc_kill_class(qi->link->ifl_index, cl->classid) == 0) {			cbq->is_cl = NULL;			cbq_free_class(qi, cl);			return 0;		}		log(LOG_ERR, 0, "kill class %08x: not deleted\n", cl->classid);

⌨️ 快捷键说明

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