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

📄 sch_atm.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct atm_qdisc_data *p = PRIV(sch);	struct atm_flow_data *flow;	DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker);	if (walker->stop) return;	for (flow = p->flows; flow; flow = flow->next) {		if (walker->count >= walker->skip)			if (walker->fn(sch,(unsigned long) flow,walker) < 0) {				walker->stop = 1;				break;			}		walker->count++;	}}static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch,unsigned long cl){	struct atm_qdisc_data *p = PRIV(sch);	struct atm_flow_data *flow = (struct atm_flow_data *) cl;	DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n",sch,p,flow);        return flow ? &flow->filter_list : &p->link.filter_list;}/* --------------------------- Qdisc operations ---------------------------- */static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch){	struct atm_qdisc_data *p = PRIV(sch);	struct atm_flow_data *flow = NULL ; /* @@@ */	struct tcf_result res;	int result;	int ret = NET_XMIT_POLICED;	D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);	result = TC_POLICE_OK; /* be nice to gcc */	if (TC_H_MAJ(skb->priority) != sch->handle ||	    !(flow = (struct atm_flow_data *) atm_tc_get(sch,skb->priority)))		for (flow = p->flows; flow; flow = flow->next)			if (flow->filter_list) {				result = tc_classify(skb,flow->filter_list,				    &res);				if (result < 0) continue;				flow = (struct atm_flow_data *) res.class;				if (!flow) flow = lookup_flow(sch,res.classid);				break;			}	if (!flow) flow = &p->link;	else {		if (flow->vcc)			ATM_SKB(skb)->atm_options = flow->vcc->atm_options;			/*@@@ looks good ... but it's not supposed to work :-)*/#ifdef CONFIG_NET_CLS_POLICE		switch (result) {			case TC_POLICE_SHOT:				kfree_skb(skb);				break;			case TC_POLICE_RECLASSIFY:				if (flow->excess) flow = flow->excess;				else {					ATM_SKB(skb)->atm_options |=					    ATM_ATMOPT_CLP;					break;				}				/* fall through */			case TC_POLICE_OK:				/* fall through */			default:				break;		}#endif	}	if (#ifdef CONFIG_NET_CLS_POLICE	    result == TC_POLICE_SHOT ||#endif	    (ret = flow->q->enqueue(skb,flow->q)) != 0) {		sch->stats.drops++;		if (flow) flow->stats.drops++;		return ret;	}	sch->stats.bytes += skb->len;	sch->stats.packets++;	flow->stats.bytes += skb->len;	flow->stats.packets++;	/*	 * Okay, this may seem weird. We pretend we've dropped the packet if	 * it goes via ATM. The reason for this is that the outer qdisc	 * expects to be able to q->dequeue the packet later on if we return	 * success at this place. Also, sch->q.qdisc needs to reflect whether	 * there is a packet egligible for dequeuing or not. Note that the	 * statistics of the outer qdisc are necessarily wrong because of all	 * this. There's currently no correct solution for this.	 */	if (flow == &p->link) {		sch->q.qlen++;		return 0;	}	tasklet_schedule(&p->task);	return NET_XMIT_BYPASS;}/* * Dequeue packets and send them over ATM. Note that we quite deliberately * avoid checking net_device's flow control here, simply because sch_atm * uses its own channels, which have nothing to do with any CLIP/LANE/or * non-ATM interfaces. */static void sch_atm_dequeue(unsigned long data){	struct Qdisc *sch = (struct Qdisc *) data;	struct atm_qdisc_data *p = PRIV(sch);	struct atm_flow_data *flow;	struct sk_buff *skb;	D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n",sch,p);	for (flow = p->link.next; flow; flow = flow->next)		/*		 * If traffic is properly shaped, this won't generate nasty		 * little bursts. Otherwise, it may ... (but that's okay)		 */		while ((skb = flow->q->dequeue(flow->q))) {			if (!atm_may_send(flow->vcc,skb->truesize)) {				(void) flow->q->ops->requeue(skb,flow->q);				break;			}			D2PRINTK("atm_tc_deqeueue: sending on class %p\n",flow);			/* remove any LL header somebody else has attached */			skb_pull(skb,(char *) skb->nh.iph-(char *) skb->data);			if (skb_headroom(skb) < flow->hdr_len) {				struct sk_buff *new;				new = skb_realloc_headroom(skb,flow->hdr_len);				dev_kfree_skb(skb);				if (!new) continue;				skb = new;			}			D2PRINTK("sch_atm_dequeue: ip %p, data %p\n",			    skb->nh.iph,skb->data);			ATM_SKB(skb)->vcc = flow->vcc;			memcpy(skb_push(skb,flow->hdr_len),flow->hdr,			    flow->hdr_len);			atomic_add(skb->truesize,&flow->vcc->tx_inuse);			ATM_SKB(skb)->iovcnt = 0;			/* atm.atm_options are already set by atm_tc_enqueue */			(void) flow->vcc->send(flow->vcc,skb);		}}static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch){	struct atm_qdisc_data *p = PRIV(sch);	struct sk_buff *skb;	D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n",sch,p);	tasklet_schedule(&p->task);	skb = p->link.q->dequeue(p->link.q);	if (skb) sch->q.qlen--;	return skb;}static int atm_tc_requeue(struct sk_buff *skb,struct Qdisc *sch){	struct atm_qdisc_data *p = PRIV(sch);	int ret;	D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);	ret = p->link.q->ops->requeue(skb,p->link.q);	if (!ret) sch->q.qlen++;	else {		sch->stats.drops++;		p->link.stats.drops++;	}	return ret;}static int atm_tc_drop(struct Qdisc *sch){	struct atm_qdisc_data *p = PRIV(sch);	struct atm_flow_data *flow;	DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n",sch,p);	for (flow = p->flows; flow; flow = flow->next)		if (flow->q->ops->drop && flow->q->ops->drop(flow->q))			return 1;	return 0;}static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt){	struct atm_qdisc_data *p = PRIV(sch);	DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);	memset(p,0,sizeof(*p));	p->flows = &p->link;	if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops)))		p->link.q = &noop_qdisc;	DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q);	p->link.filter_list = NULL;	p->link.vcc = NULL;	p->link.sock = NULL;	p->link.classid = sch->handle;	p->link.ref = 1;	p->link.next = NULL;	tasklet_init(&p->task,sch_atm_dequeue,(unsigned long) sch);	MOD_INC_USE_COUNT;	return 0;}static void atm_tc_reset(struct Qdisc *sch){	struct atm_qdisc_data *p = PRIV(sch);	struct atm_flow_data *flow;	DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n",sch,p);	for (flow = p->flows; flow; flow = flow->next) qdisc_reset(flow->q);	sch->q.qlen = 0;}static void atm_tc_destroy(struct Qdisc *sch){	struct atm_qdisc_data *p = PRIV(sch);	struct atm_flow_data *flow;	DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p);	/* races ? */	while ((flow = p->flows)) {		destroy_filters(flow);		if (flow->ref > 1)			printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow,			    flow->ref);		atm_tc_put(sch,(unsigned long) flow);		if (p->flows == flow) {			printk(KERN_ERR "atm_destroy: putting flow %p didn't "			    "kill it\n",flow);			p->flows = flow->next; /* brute force */			break;		}	}	tasklet_kill(&p->task);	MOD_DEC_USE_COUNT;}#ifdef CONFIG_RTNETLINKstatic int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,    struct sk_buff *skb, struct tcmsg *tcm){	struct atm_qdisc_data *p = PRIV(sch);	struct atm_flow_data *flow = (struct atm_flow_data *) cl;	unsigned char *b = skb->tail;	struct rtattr *rta;	DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",	    sch,p,flow,skb,tcm);	if (!find_flow(p,flow)) return -EINVAL;	tcm->tcm_handle = flow->classid;	rta = (struct rtattr *) b;	RTA_PUT(skb,TCA_OPTIONS,0,NULL);	RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr);	if (flow->vcc) {		struct sockaddr_atmpvc pvc;		int state;		pvc.sap_family = AF_ATMPVC;		pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1;		pvc.sap_addr.vpi = flow->vcc->vpi;		pvc.sap_addr.vci = flow->vcc->vci;		RTA_PUT(skb,TCA_ATM_ADDR,sizeof(pvc),&pvc);		state = ATM_VF2VS(flow->vcc->flags);		RTA_PUT(skb,TCA_ATM_STATE,sizeof(state),&state);	}	if (flow->excess)		RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(u32),&flow->classid);	else {		static u32 zero = 0;		RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(zero),&zero);	}	rta->rta_len = skb->tail-b;	return skb->len;rtattr_failure:	skb_trim(skb,b-skb->data);	return -1;}static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb){	return 0;}#endifstatic struct Qdisc_class_ops atm_class_ops ={	atm_tc_graft,			/* graft */	atm_tc_leaf,			/* leaf */	atm_tc_get,			/* get */	atm_tc_put,			/* put */	atm_tc_change,			/* change */	atm_tc_delete,			/* delete */	atm_tc_walk,			/* walk */	atm_tc_find_tcf,		/* tcf_chain */	atm_tc_bind_filter,		/* bind_tcf */	atm_tc_put,			/* unbind_tcf */#ifdef CONFIG_RTNETLINK	atm_tc_dump_class,		/* dump */#endif};struct Qdisc_ops atm_qdisc_ops ={	NULL,				/* next */	&atm_class_ops,			/* cl_ops */	"atm",	sizeof(struct atm_qdisc_data),	atm_tc_enqueue,			/* enqueue */	atm_tc_dequeue,			/* dequeue */	atm_tc_requeue,			/* requeue */	atm_tc_drop,			/* drop */	atm_tc_init,			/* init */	atm_tc_reset,			/* reset */	atm_tc_destroy,			/* destroy */	NULL,				/* change */#ifdef CONFIG_RTNETLINK	atm_tc_dump			/* dump */#endif};#ifdef MODULEint init_module(void){	return register_qdisc(&atm_qdisc_ops);}void cleanup_module(void) {	unregister_qdisc(&atm_qdisc_ops);}#endif

⌨️ 快捷键说明

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