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

📄 cls_rsvp.h

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 H
📖 第 1 页 / 共 2 页
字号:
	while (i-- > 0) {		u32 h;		if ((data->hgenerator += 0x10000) == 0)			data->hgenerator = 0x10000;		h = data->hgenerator|salt;		if (rsvp_get(tp, h) == 0)			return h;	}	return 0;}static int tunnel_bts(struct rsvp_head *data){	int n = data->tgenerator>>5;	u32 b = 1<<(data->tgenerator&0x1F);		if (data->tmap[n]&b)		return 0;	data->tmap[n] |= b;	return 1;}static void tunnel_recycle(struct rsvp_head *data){	struct rsvp_session **sht = data->ht;	u32 tmap[256/32];	int h1, h2;	memset(tmap, 0, sizeof(tmap));	for (h1=0; h1<256; h1++) {		struct rsvp_session *s;		for (s = sht[h1]; s; s = s->next) {			for (h2=0; h2<=16; h2++) {				struct rsvp_filter *f;				for (f = s->ht[h2]; f; f = f->next) {					if (f->tunnelhdr == 0)						continue;					data->tgenerator = f->res.classid;					tunnel_bts(data);				}			}		}	}	memcpy(data->tmap, tmap, sizeof(tmap));}static u32 gen_tunnel(struct rsvp_head *data){	int i, k;	for (k=0; k<2; k++) {		for (i=255; i>0; i--) {			if (++data->tgenerator == 0)				data->tgenerator = 1;			if (tunnel_bts(data))				return data->tgenerator;		}		tunnel_recycle(data);	}	return 0;}static int rsvp_change(struct tcf_proto *tp, unsigned long base,		       u32 handle,		       struct rtattr **tca,		       unsigned long *arg){	struct rsvp_head *data = tp->root;	struct rsvp_filter *f, **fp;	struct rsvp_session *s, **sp;	struct tc_rsvp_pinfo *pinfo = NULL;	struct rtattr *opt = tca[TCA_OPTIONS-1];	struct rtattr *tb[TCA_RSVP_MAX];	unsigned h1, h2;	u32 *dst;	int err;	if (opt == NULL)		return handle ? -EINVAL : 0;	if (rtattr_parse(tb, TCA_RSVP_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt)) < 0)		return -EINVAL;	if ((f = (struct rsvp_filter*)*arg) != NULL) {		/* Node exists: adjust only classid */		if (f->handle != handle && handle)			return -EINVAL;		if (tb[TCA_RSVP_CLASSID-1]) {			unsigned long cl;			f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);			cl = cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));			if (cl)				tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);		}#ifdef CONFIG_NET_CLS_POLICE		if (tb[TCA_RSVP_POLICE-1]) {			struct tcf_police *police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);			tcf_tree_lock(tp);			police = xchg(&f->police, police);			tcf_tree_unlock(tp);			tcf_police_release(police);		}#endif		return 0;	}	/* Now more serious part... */	if (handle)		return -EINVAL;	if (tb[TCA_RSVP_DST-1] == NULL)		return -EINVAL;	f = kmalloc(sizeof(struct rsvp_filter), GFP_KERNEL);	if (f == NULL)		return -ENOBUFS;	memset(f, 0, sizeof(*f));	h2 = 16;	if (tb[TCA_RSVP_SRC-1]) {		err = -EINVAL;		if (RTA_PAYLOAD(tb[TCA_RSVP_SRC-1]) != sizeof(f->src))			goto errout;		memcpy(f->src, RTA_DATA(tb[TCA_RSVP_SRC-1]), sizeof(f->src));		h2 = hash_src(f->src);	}	if (tb[TCA_RSVP_PINFO-1]) {		err = -EINVAL;		if (RTA_PAYLOAD(tb[TCA_RSVP_PINFO-1]) < sizeof(struct tc_rsvp_pinfo))			goto errout;		pinfo = RTA_DATA(tb[TCA_RSVP_PINFO-1]);		f->spi = pinfo->spi;		f->tunnelhdr = pinfo->tunnelhdr;	}	if (tb[TCA_RSVP_CLASSID-1]) {		err = -EINVAL;		if (RTA_PAYLOAD(tb[TCA_RSVP_CLASSID-1]) != 4)			goto errout;		f->res.classid = *(u32*)RTA_DATA(tb[TCA_RSVP_CLASSID-1]);	}	err = -EINVAL;	if (RTA_PAYLOAD(tb[TCA_RSVP_DST-1]) != sizeof(f->src))		goto errout;	dst = RTA_DATA(tb[TCA_RSVP_DST-1]);	h1 = hash_dst(dst, pinfo ? pinfo->protocol : 0, pinfo ? pinfo->tunnelid : 0);	err = -ENOMEM;	if ((f->handle = gen_handle(tp, h1 | (h2<<8))) == 0)		goto errout;	if (f->tunnelhdr) {		err = -EINVAL;		if (f->res.classid > 255)			goto errout;		err = -ENOMEM;		if (f->res.classid == 0 &&		    (f->res.classid = gen_tunnel(data)) == 0)			goto errout;	}	for (sp = &data->ht[h1]; (s=*sp) != NULL; sp = &s->next) {		if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] &&		    pinfo->protocol == s->protocol &&		    memcmp(&pinfo->dpi, &s->dpi, sizeof(s->dpi)) == 0#if RSVP_DST_LEN == 4		    && dst[0] == s->dst[0]		    && dst[1] == s->dst[1]		    && dst[2] == s->dst[2]#endif		    && pinfo->tunnelid == s->tunnelid) {insert:			/* OK, we found appropriate session */			fp = &s->ht[h2];			f->sess = s;			if (f->tunnelhdr == 0)				cls_set_class(tp, &f->res.class, tp->q->ops->cl_ops->bind_tcf(tp->q, base, f->res.classid));#ifdef CONFIG_NET_CLS_POLICE			if (tb[TCA_RSVP_POLICE-1])				f->police = tcf_police_locate(tb[TCA_RSVP_POLICE-1], tca[TCA_RATE-1]);#endif			for (fp = &s->ht[h2]; *fp; fp = &(*fp)->next)				if (((*fp)->spi.mask&f->spi.mask) != f->spi.mask)					break;			f->next = *fp;			wmb();			*fp = f;			*arg = (unsigned long)f;			return 0;		}	}	/* No session found. Create new one. */	err = -ENOBUFS;	s = kmalloc(sizeof(struct rsvp_session), GFP_KERNEL);	if (s == NULL)		goto errout;	memset(s, 0, sizeof(*s));	memcpy(s->dst, dst, sizeof(s->dst));	s->dpi = pinfo->dpi;	s->protocol = pinfo->protocol;	s->tunnelid = pinfo->tunnelid;	for (sp = &data->ht[h1]; *sp; sp = &(*sp)->next) {		if (((*sp)->dpi.mask&s->dpi.mask) != s->dpi.mask)			break;	}	s->next = *sp;	wmb();	*sp = s;		goto insert;errout:	if (f)		kfree(f);	return err;}static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg){	struct rsvp_head *head = tp->root;	unsigned h, h1;	if (arg->stop)		return;	for (h = 0; h < 256; h++) {		struct rsvp_session *s;		for (s = head->ht[h]; s; s = s->next) {			for (h1 = 0; h1 <= 16; h1++) {				struct rsvp_filter *f;				for (f = s->ht[h1]; f; f = f->next) {					if (arg->count < arg->skip) {						arg->count++;						continue;					}					if (arg->fn(tp, (unsigned long)f, arg) < 0) {						arg->stop = 1;						break;					}					arg->count++;				}			}		}	}}#ifdef CONFIG_RTNETLINKstatic int rsvp_dump(struct tcf_proto *tp, unsigned long fh,		     struct sk_buff *skb, struct tcmsg *t){	struct rsvp_filter *f = (struct rsvp_filter*)fh;	struct rsvp_session *s;	unsigned char	 *b = skb->tail;	struct rtattr *rta;	struct tc_rsvp_pinfo pinfo;	if (f == NULL)		return skb->len;	s = f->sess;	t->tcm_handle = f->handle;	rta = (struct rtattr*)b;	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);	RTA_PUT(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst);	pinfo.dpi = s->dpi;	pinfo.spi = f->spi;	pinfo.protocol = s->protocol;	pinfo.tunnelid = s->tunnelid;	pinfo.tunnelhdr = f->tunnelhdr;	RTA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo);	if (f->res.classid)		RTA_PUT(skb, TCA_RSVP_CLASSID, 4, &f->res.classid);	if (((f->handle>>8)&0xFF) != 16)		RTA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src);#ifdef CONFIG_NET_CLS_POLICE	if (f->police) {		struct rtattr * p_rta = (struct rtattr*)skb->tail;		RTA_PUT(skb, TCA_RSVP_POLICE, 0, NULL);		if (tcf_police_dump(skb, f->police) < 0)			goto rtattr_failure;		p_rta->rta_len = skb->tail - (u8*)p_rta;	}#endif	rta->rta_len = skb->tail - b;#ifdef CONFIG_NET_CLS_POLICE	if (f->police) {		if (qdisc_copy_stats(skb, &f->police->stats))			goto rtattr_failure;	}#endif	return skb->len;rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;}#endifstruct tcf_proto_ops RSVP_OPS = {	NULL,	RSVP_ID,	rsvp_classify,	rsvp_init,	rsvp_destroy,	rsvp_get,	rsvp_put,	rsvp_change,	rsvp_delete,	rsvp_walk,#ifdef CONFIG_RTNETLINK	rsvp_dump#else	NULL#endif};#ifdef MODULEint init_module(void){	return register_tcf_proto_ops(&RSVP_OPS);}void cleanup_module(void) {	unregister_tcf_proto_ops(&RSVP_OPS);}#endif

⌨️ 快捷键说明

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