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

📄 dcp.c

📁 DCCP协议在linux下的C编程实现 linux C
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Parameters:	skb - the sk_buff containing the received packet */static int dccp_rcv (struct sk_buff *skb){	struct sock *sk;	u32 locala, remotea, svc;	u16 lport, rport;	unsigned char ptype;	/* extract the info we need to get the list lookup */	if ((ptype = parse_dccp_pkt (skb,&locala,&remotea,&svc,&lport,&rport)) == TYPE_INVALID)	{		printk ("dccp: Packet is not a valid DCCP packet\n");		goto drop;	}	/* lookup the sk for it.. */	sk = lookup_dccp_sk(0,remotea,svc,lport,rport,ptype);	if (!sk)	{		printk ("dccp: rcvd dccp packet for non existant session %08X:%d to %08X:%d (svc=%X)\n",				remotea,ntohs(rport),locala,ntohs(lport),svc);		goto rst;	}	/* if found we want to signal newdata via wake_up() after	   placing skb in a circular q.. */	if (dccp_enq_rcv (sk,skb))	{#if DCP_DEBUG > 0		printk ("dccp: rcvd dccp packet but there doesn't seem to be any room for it\n");#endif		goto drop;	}	/* don't touch skb after this point - it's either been xferred to another handler,	   or freed completely if it was just an ack */	//TODO: [TOM] MAYBE here is better for CCID3?	//no here is in the upper half and its baaad here@!	return 0;			/* OK! */rst:	if ( (skb->data[4] != TYPE_RESET))	{		itask.data = skb;	/* some risk of lost resets here - thats ok by me */		if (schedule_task(&itask))			return 0;	}drop:	/* we'll drop the packet if we can't find the sk, or if there	   is no room in the q */	/* if we don't queue this thing up we want to drop it */#if DCP_DEBUG > 0	printk ("dccp: dropping packet\n");#endif	kfree_skb(skb);	return 0;}static struct inet_protocol dccp_protocol = {handler:	dccp_rcv,err_handler:	NULL,protocol:	DCCP_PROTO, /* 33 as per eddie kohler 4/25/2002 */name:		"DCCP"};/* Sets a different outstanding packet to be the round trip time estimator,  * in the event of the previous round trip time measurement timing out without a response * * Parameters:	vd - the socket on which the connection is taking place * */static void *dccp_charged_timeout (unsigned long vd){	/* ok - we've had an RTO timer go off */	struct sock *sk;	struct dcp_opt *tp;	u32 ld,lsn;	sk = (struct sock *)vd;	tp = &(sk->tp_pinfo.tp_dcp);	spin_lock (&tp->rsem);   		// if the timer is actually set and the outstanding timer packet is in the congestion window	if ((tp->rto_num != 0x1000000) &&   (ld = value_in_cwndvector (sk,tp->rto_num)))	{		// nope, we haven't actually timed out - ideally, we wouldn't reach this point		if ((jiffies - ld) < tp->rto)		{			/* just reschedule it */			tp->retransmit_timer.expires = ld + tp->rto;      			mod_timer (&tp->retransmit_timer,tp->retransmit_timer.expires);		}		else		{	#if DCP_DEBUG > 1					printk ("PACKET TIMEOUT %d\n",tp->rto_num);#endif			// The outstanding timer packet has not been acked before the timeout			tp->checkingrtt = tp->checkingsn = 0;	/* karn says we don't want to count any outstanding window measures */			lsn = tp->rto_num;			tp->rto_num = 0x1000000;			// we've given up on this packet so remove it from the congestion window			credit_pkt(sk,lsn); 			// Our timing info has to come from another outstanding packet asap			while ((tp->cv_ts != tp->cv_hs) && tp->outstanding)			{				tp->retransmit_timer.function = (void *) dccp_charged_timeout;				tp->retransmit_timer.data = (unsigned long) sk;				// we use cv_tp because it should be the next packet ACKed				tp->retransmit_timer.expires = *((u32 *)tp->cv_tp) + tp->rto;      				// making sure our timer isn't due to expire sometime in the past 				if (tp->retransmit_timer.expires <= jiffies)				{#if DCP_DEBUG > 2					printk ("CONCURRENT PACKET TO %d\n",tp->cv_ts);#endif					credit_pkt(sk,tp->cv_ts); 				}				else				{					/*printk ("would set new rto timer to %d (delta %d)\n",					  tp->retransmit_timer.expires,					  tp->retransmit_timer.expires - jiffies); */					tp->rto_num = tp->cv_ts; 					add_timer (&tp->retransmit_timer);     					break;				}			}						// all data packets have been lost so adjust cwnd, ssthresh et al.			if (jiffies > tp->timeout_barrier) /* can't adj more than once a window*/			{				tp->timeout_barrier = jiffies + tp->rtt;				tp->ssthresh = tp->cwnd/2;				tp->cwnd = 1;				if (!tp->ssthresh)					tp->ssthresh = 1;				rcvr_ratio_inbounds(tp);			}		}	}	else		tp->rto_num = 0x1000000;	spin_unlock (&tp->rsem);   	wake_up (&tp->newdata);	return NULL;}/* Updates timer related variables to signify that the packet needs to be re-sent - used with regards to connection * handshakes and closing. Not applicable to data or acks * * Parameters:	s - the socket on which the connection is taking place * */static void *dcp_resend (unsigned long s){	struct sock *sk;	struct dcp_opt *tp;	sk = (struct sock *)s;	tp = &(sk->tp_pinfo.tp_dcp);	// I presume something checks the value of timer_expired later on to see if a resend is required - SHANE	tp->timer_expired = 1;	tp->retries++;#if DCP_DEBUG > 2	printk ("dccp: Timer Expired at %d:%X\n",tp->whoami,(unsigned)jiffies);#endif	wake_up (&tp->newdata);	return NULL;}/* Updates rtt information based on the new sample received * * Parameters:	tp - the dcp_opt structure containing the current rtt information	 * 		M - the rtt estimate * */static inline void new_rtt_sample (struct dcp_opt *tp, u16 M){				/* lock held */	u16 err;	// deviation calculations	if (M >= tp->rtt)	{		err = M - tp->rtt;		tp->rtt = tp->rtt + (err >> 3);	}	else	{		err = tp->rtt - M;		tp->rtt = tp->rtt - (err >> 3);	}		tp->rtt_d = tp->rtt_d + ((err - tp->rtt_d) >> 2);	// updating the timeout value	tp->rto = tp->rtt + (tp->rtt_d << 2);	// Updating minimum rtt if necessary	if (tp->rtt < DCP_MIN_RTT)		tp->rtt = DCP_MIN_RTT;#if DCP_DEBUG > 1	printk ("new rtt sample: %d, rtt is now %d\n",M,tp->rtt);#endif	return;}/* Initializes the ack and congestion window vectors for a socket * * Parameters:	sk - the socket for which the vectors need to be initialized * */static int finalize_init(struct sock *sk){				/* setup vector trackers */	struct dcp_opt *tp = &(sk->tp_pinfo.tp_dcp);	tp->av_sz = tp->cv_sz = INIT_VECTOR_SIZE;	/* initially track this number of packets - keep as multiple of 8 */	tp->av_hs =tp->av_ts = tp->cv_hs = tp->cv_ts = 0;	//tp->ackvector  =  kmalloc(tp->av_sz/4, GFP_KERNEL); /* 2 bits entry */   tp->ackvector  =  vmalloc(tp->av_sz/4); /* 2 bits entry */	//tp->cwndvector =  kmalloc(tp->cv_sz*4,GFP_KERNEL); /* 32 bits per entry */   tp->cwndvector =  vmalloc(tp->cv_sz*4L); /* 32 bits per entry */ 	memset (tp->ackvector,0xff,tp->av_sz/4);	memset (tp->cwndvector,0,tp->cv_sz*4);	tp->av_tp = tp->ackvector;	tp->cv_hp = tp->cv_tp = tp->cwndvector;	tp->av_clist = NULL;	return 0;}/* Updates the congestion window to reflect the receipt of an ack for a particular outstanding packet. * Also used to remove packets that are regarded as lost from the congestion window * * Parameters:	sk - the socket where the connection is taking place * 		sn - the sequence number of the packet that has been acked * */static int credit_pkt (struct sock *sk, u32 sn){	struct dcp_opt *tp = &(sk->tp_pinfo.tp_dcp);	u32 bo,gap,*rt;	unsigned char *t;	int rv = 0;#if DCP_DEBUG > 2  	printk ("credit request %d\n",sn); #endif	/* rsem lock held */	/* opposite of charge pkt, in	   reaction to rcvd ack on cwndvector */	if (tp->cv_ts == tp->cv_hs)	/* empty */		goto ackofack_q;	if (sn >= tp->cv_ts)		gap = (sn - tp->cv_ts);	else				/* sn has wrapped but ts hasn't */		gap = (sn + (0x1000000 - tp->cv_ts));	if (gap > tp->cv_sz)  /* probably from past */	{		/*     printk ("excessive gap %d (sn=%d, ts=%d)\n",gap,sn,tp->cv_ts); */		goto ackofack_q;	}	// four bytes for each entry	bo = gap*4;	t = tp->cv_tp+bo;	if (t >= (tp->cwndvector + (tp->cv_sz*4))) /* wrapped */		t -= tp->cv_sz*4;	rt = (u32 *) t;	if (*rt)			/* packets were set */	{		tp->outstanding--;	#if DCP_DEBUG > 2		printk ("%d Giving Credit for %d - %d\n",tp->whoami,sn,*rt);  #endif		rv++;		dcp_writeable(sk);	/* for polling sleepers */		*rt = 0;			/* clear the packet in vector */		rt = (u32 *) tp->cv_tp;		// moving the tail pointer ahead to the first un-credited packet in the cwnd, or the head pointer		// whichever comes first		while ((tp->cv_hs != tp->cv_ts) && (! *rt))		{			tp->cv_tp += 4;			if (tp->cv_tp >= (tp->cwndvector + (tp->cv_sz*4)))				tp->cv_tp = tp->cwndvector; /* wrap */			tp->cv_ts += 1;			if (tp->cv_ts == 0x1000000)				tp->cv_ts = 0;			rt = (u32 *) tp->cv_tp;		}		if (tp->rto_num == sn)	/* timer was set for this packet */		{			/* see if we've got another outstanding pkt */			if (tp->outstanding && (tp->cv_hs != tp->cv_ts))			{				tp->rto_num = tp->cv_ts;				tp->retransmit_timer.expires = *rt + tp->rto;      				mod_timer (&tp->retransmit_timer,tp->retransmit_timer.expires);			}			else			{				tp->rto_num = 0x1000000; /* not used */				del_timer_sync (&tp->retransmit_timer); /* cancel it */			}		}		return rv;	}ackofack_q:	check_clist (tp,sn);	/* maybe an ack of ack? */	return rv;}/* Adds a packet to the congestion window  * * Parameters:	sk - the socket on which the connection is taking place * 		sn - the sequence number of the packet being sent * */static inline void charge_pkt (struct sock *sk, u32 sn){				/* assume a lock */	/* charge a sending packet against cwnd - store it's sn so we can	   credit cwnd when it gets acked */	struct dcp_opt *tp = &(sk->tp_pinfo.tp_dcp);	u32  tc, gap;	unsigned char *n,*t;	u32 *rt;	// only needed for CCID 2	if (tp->ccid !=2)		return;	// congestion window is empty so we're the first entry	if (tp->cv_ts == tp->cv_hs)		tp->cv_ts = tp->cv_hs = sn;	if (sn >= tp->cv_ts)		gap = (sn - tp->cv_ts);	else				/* sn has wrapped but ts hasn't */		gap = (sn + (0x1000000 - tp->cv_ts));	if (gap > tp->cv_sz) return ; /* probably from past */	tp->outstanding++;	// setting the timer if necessary	if (tp->rto_num == 0x1000000)	/* no timer set */	{		tp->rto_num = sn;		tp->retransmit_timer.function = (void *) dccp_charged_timeout;		tp->retransmit_timer.data = (unsigned long) sk;		tp->retransmit_timer.expires = jiffies + tp->rto;      		add_timer (&tp->retransmit_timer);      	}	t = tp->cv_tp+(gap*4);	if (t >= (tp->cwndvector + (tp->cv_sz*4))) /* wrapped */		t -= tp->cv_sz*4;	rt = (u32 *) t;	*rt = jiffies;		/* set bits */#if DCP_DEBUG > 2	printk ("%d Charging for %d - %p\n",tp->whoami,sn,t);#endif	// we haven't increment sn yet	tp->cv_hs = sn +1;	if (tp->cv_hs == 0x1000000)		tp->cv_hs = 0;	tp->cv_hp = t;	if (gap > (tp->cv_sz - 128))	/* running out of room, should expand cwnd vector */	{		//n = kmalloc (tp->cv_sz*8,GFP_ATOMIC);	/* a doubling */      n = vmalloc (tp->cv_sz*8);	/* a doubling */		memset (n+tp->cv_sz*4,0x00,tp->cv_sz*4); /* new half all missing */		tc = (tp->cwndvector + (tp->cv_sz*4)) - tp->cv_tp;			memcpy (n,tp->cv_tp, tc); /* tail to end */		memcpy (n+tc,tp->cwndvector,tp->cv_tp - tp->cwndvector); /* start to tail */		tp->cv_tp = n;		tp->cv_sz = tp->cv_sz * 2; /* counted in items, so it's a doubling */		      //kfree (tp->cwndvector);      vfree(tp->cwndvector);      		tp->cwndvector = n;		tp->cv_hp = tp->cv_tp +(gap*4);	}#if DCP_DEBUG > 2	printk ("dccp %d: charge pkt [%d] - outstanding now %d\n",tp->whoami,sn,tp->outstanding);#endif	return;}/* Updates the ack vector when a packet has been received. *  * Parameters:	sk - the socket the packet was received on * 		sn - the sequence number of the received packet * */static inline int increment_ackvector (struct sock *sk, u32 sn){				/* assume a lock */	/* we've recvd a packet, and want to put it in the local	   ackvector so that when we send it off the av, it will	   be included */	struct dcp_opt *tp = &(sk->tp_pinfo.tp_dcp);	u32 offset, tc,gap;	unsigned char *n,*t;	tp->av_ts = tp->av_hs = sn;		if (sn >= tp->av_ts)	{		gap = (sn - tp->av_ts);	}	else				/* sn has wrapped but ts hasn't */	{		gap = (sn + (0x1000000 - tp->av_ts));	}	offset = gap %4;	/*

⌨️ 快捷键说明

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