📄 cls_rsvp.h
字号:
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 + -