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

📄 sctp_msg.c

📁 No7信令,我需要交换类似的代码, 请店长审核,谢谢了,急着交换,谢谢
💻 C
📖 第 1 页 / 共 5 页
字号:
	mblk_t *mp = bufq_head(&sp->urgq);	size_t swnd = sctp_avail(sp, sd, dmps, *mrem);	for ( ; mp && *mrem && swnd; mp = mp->b_next )	{		mblk_t *db;		sctp_tcb_t *cb = SCTP_TCB(mp);		size_t dlen = cb->dlen;		size_t plen = PADC(sizeof(struct sctp_data) + dlen);		ensure( cb->st, continue );#if defined(_DEBUG)||defined(_SAFE)		/* this should only occur if the pmtu is falling */		if ( amps <= *mrem && plen > amps ) { rare();			sctp_frag_chunk(&sp->urgq, mp, amps);			dlen = cb->dlen;			plen = PADC(sizeof(struct sctp_data) + dlen);		}#endif		if ( dlen > swnd ) {			rare(); return;	/* congested */		}		if ( plen > *mrem && plen <= dmps ) {			rare(); return; /* wait for next packet */		}		if ( (mp == cb->st->x.head) ) {			rare(); cb->st->x.head = NULL; /* steal partial */		}		if ( (db = dupmsg(mp)) )		{			uint32_t tsn = sp->t_tsn++;			struct sctp_data *m = (struct sctp_data *)db->b_rptr;			cb->tsn	    = tsn;			cb->flags  |= SCTPCB_FLAG_SENT;			cb->trans   = 0;			cb->sacks   = 0;			cb->when    = jiffies;			cb->daddr   = sd;			m->tsn = htonl( tsn );			sd->in_flight += dlen;			sp->in_flight += dlen;			*mrem = *mrem > plen ? *mrem - plen : 0;			*mlen += plen;			**dpp = db;			*dpp = &(db->b_next);			db->b_next = NULL;			bufq_queue(&sp->rtxq, bufq_dequeue(&sp->urgq));			swnd = sctp_avail(sp, sd, dmps, *mrem);			continue;		}		rare(); return;	}	return;}/* *  BUNDLE NEW NORMAL (ORDERED) DATA */static void sctp_bundle_data_normal(sp, sd, dmps, amps, dpp, mrem, mlen)	sctp_t *sp;	    /* association */	sctp_daddr_t *sd;   /* destination */	size_t dmps;	    /* destination maximum payload size */	size_t amps;	    /* association maximum payload size */	mblk_t ***dpp;	    /* place to link buffer */	size_t *mrem;	    /* remaining payload */	size_t *mlen;	    /* current message length */{	mblk_t *mp = bufq_head(&sp->sndq);	size_t swnd = sctp_avail(sp, sd, dmps, *mrem);	/* don't bundle normal data without more to send (like a SACK) */	if ( sp->options & SCTP_OPTION_CORK || (			sp->options & SCTP_OPTION_NAGLE			&& *mlen == sizeof(struct sctphdr)			&& bufq_size(&sp->sndq) < *mrem>>1 ) )		return;	for ( ; mp && *mrem && swnd; mp = mp->b_next )	{		mblk_t *db;		sctp_tcb_t *cb = SCTP_TCB(mp);		size_t dlen = cb->dlen;		size_t plen = PADC(sizeof(struct sctp_data) + dlen);		ensure( cb->st, continue );#if defined(_DEBUG)||defined(_SAFE)		/* this should only occur if the pmtu is falling */		if ( amps <= *mrem && plen > amps ) { rare();			sctp_frag_chunk(&sp->sndq, mp, amps);			dlen = cb->dlen;			plen = PADC(sizeof(struct sctp_data) + dlen);		}#endif		if ( dlen > swnd ) {			rare(); return;	/* congested */		}		if ( plen > *mrem && plen <= dmps ) {			rare(); return; /* wait for next packet */		}		if ( (mp == cb->st->n.head) ) {			rare(); cb->st->n.head = NULL; /* steal partial */		}		if ( (db = dupmsg(mp)) )		{			uint32_t tsn = sp->t_tsn++;			cb->tsn	    = tsn;			cb->flags  |= SCTPCB_FLAG_SENT;//			cb->trans   = 1;    done by sctp_send_msg */			cb->sacks   = 0;			cb->when    = jiffies;			cb->daddr   = sd;			((struct sctp_data *)db->b_rptr)->tsn = htonl( tsn );			sd->in_flight += dlen;			sp->in_flight += dlen;			*mrem = *mrem > plen ? *mrem - plen : 0;			*mlen += plen;			**dpp = db;			*dpp = &(db->b_next);			db->b_next = NULL;			bufq_queue(&sp->rtxq, bufq_dequeue(&sp->sndq));			swnd = sctp_avail(sp, sd, dmps, *mrem);			continue;		}		rare(); return;	}	return;}/* *  BUNDLE CHUNKS *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *  Tack on SACK, ERROR, and DATA chunks up to the destination MTU considering *  congestion windows and fragmentation sizes. */static void sctp_retrans_timeout(caddr_t data);static void sctp_bundle_more(sp, sd, mp)	sctp_t *sp;	sctp_daddr_t *sd;	mblk_t *mp;{	mblk_t **dpp;	size_t mrem, dmps, amps, mlen;	size_t htax = sizeof(struct iphdr) + sizeof(struct sctphdr);	size_t in_flight;	ensure( mp, return );	assert( sp );	assert( sd );	in_flight = sd->in_flight;	ensure( sd->mtu  > htax, return );  /* FIXME: this is worse... */	ensure( sp->pmtu > htax, return );  /* FIXME: this is worse... */	dmps = sd->mtu  - htax;	/* destintaion max payload size */	amps = sp->pmtu - htax;	/* association max payload size */	mlen = msgdsize(mp);	mrem = sd->mtu - sizeof(struct iphdr);	mrem = ( mlen < mrem ) ? mrem - mlen : 0;	dpp = &(mp->b_next);	mp->b_next = NULL;	if ( mrem && sp->sackf )		sctp_bundle_sack        (sp, sd, dmps, amps, &dpp, &mrem, &mlen);	if ( mrem && bufq_head(&sp->errq) )		sctp_bundle_error       (sp, sd, dmps, amps, &dpp, &mrem, &mlen);	if ( mrem && bufq_head(&sp->urgq) )		sctp_bundle_data_urgent (sp, sd, dmps, amps, &dpp, &mrem, &mlen);	if ( mrem && sp->nrtxs )		sctp_bundle_data_retrans(sp, sd, dmps, amps, &dpp, &mrem, &mlen);	if ( mrem && bufq_head(&sp->sndq) )		sctp_bundle_data_normal (sp, sd, dmps, amps, &dpp, &mrem, &mlen);	SCTP_TCB(mp)->dlen = mlen;	if ( sd->in_flight && !sd->timer_retrans ) {		set_timeout(&sd->timer_retrans, &sctp_retrans_timeout, sd, sd->rto);	}	return;}/* *  ALLOC MSG *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *  Allocates a new message block with a hidden transmission control block, an *  SCTP message header, and the first chunk of a message. */static mblk_t *sctp_alloc_msg(sp, clen)	sctp_t *sp;	size_t clen;{	mblk_t *mp;	struct sctphdr *sh;	sctp_tcb_t *cb;	size_t plen = PADC(clen);		assert(sp);	if ( (mp = allocb(sizeof(*cb)+sizeof(*sh)+plen, BPRI_MED)) )	{		mp->b_datap->db_type = M_DATA;		cb = (sctp_tcb_t *)mp->b_wptr;		bzero(cb, sizeof(*cb));		cb->mp	    = mp;		cb->dlen    = sizeof(*sh)+plen;		mp->b_rptr += sizeof(*cb);  /* hide control block */		mp->b_wptr += sizeof(*cb);				sh = (struct sctphdr *)mp->b_wptr;		sh->srce    = sp->sport;		sh->dest    = sp->dport;		sh->v_tag   = sp->p_tag;		sh->check   = 0;		mp->b_wptr += sizeof(*sh);				bzero(mp->b_wptr+clen,plen-clen);		mp->b_next = NULL;	}	return(mp);}/* *  ALLOC REPLY *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *  This is for allocating a message block with a hidden transmission control *  block for a message sith an STCP header.  This is for out of the blue *  replies and all that is required is the SCTP header of the message to *  which this is a reply. */static mblk_t *sctp_alloc_reply(rh, clen)	struct sctphdr *rh;	size_t clen;{	mblk_t *mp;	struct sctphdr *sh;	sctp_tcb_t *cb;	size_t plen = PADC(clen);	assert(rh);	if ( (mp = allocb(sizeof(*cb)+sizeof(*sh)+plen, BPRI_MED)) )	{		mp->b_datap->db_type = M_DATA;		cb = (sctp_tcb_t *)mp->b_wptr;		bzero(cb, sizeof(*cb));		cb->mp	    = mp;		cb->dlen    = sizeof(*sh)+plen;		mp->b_rptr += sizeof(*cb);  /* hide control block */		mp->b_wptr += sizeof(*cb);				sh = (struct sctphdr *)mp->b_wptr;		sh->srce    = rh->dest;		sh->dest    = rh->srce;		sh->v_tag   = rh->v_tag;		sh->check   = 0;		mp->b_wptr += sizeof(*sh);				bzero(mp->b_wptr+clen,plen-clen);		mp->b_next = NULL;	}	return(mp);}/* *  ROUTE SELECTION *  ------------------------------------------------------------------------- *   *  ROUTE NORMAL *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *  Send to the normal transmit (primary) address.  If that has timedout, we *  use the retransmit (secondary) address.  We always use the secondary *  address if we have retransmit chunks to bundle or if we have be receiving *  duplicates (our SACKs are not getting through on the primary address). * */static sctp_daddr_t *sctp_route_normal(sp)	sctp_t *sp;{	sctp_daddr_t *sd;	assert(sp);	if ( sctp_update_routes(sp,1) )	{		rare();		/* we have no viable route */		if ( (1<<sp->s_state) & (SCTPF_HAVEUSER) ) {			sp->ops->sctp_discon_ind(sp, SCTP_ORIG_PROVIDER, -EHOSTUNREACH, NULL);		} else rare();		__sctp_disconnect(sp);		return(NULL);	}	sd = sp->taddr;	normal(sd);#if 0	if ( ( !sd || ((sd->retransmits || sp->nrtxs) && sd->max_retrans) ) && sp->raddr )		sd = sp->raddr;//	if ( !sd || ((sd->retransmits || sp->nrtxs) && sd->max_retrans) || (sp->sackf & SCTP_SACKF_DUP) )	if ( !sd || (sp->nrtxs && sd->max_retrans) || (sp->sackf & SCTP_SACKF_DUP) )		sd = sp->raddr;	/* might be same address */#endif	return(sd);}/* *  ROUTE RESPONSE *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *  In response to control chunks we normally send back to the address that *  the control chunk came from.  If that address is unusable or wasn't *  provided we send as normal. */static sctp_daddr_t *sctp_route_response(sp)	sctp_t *sp;{	sctp_daddr_t *sd;	assert(sp);	sd = sp->caddr;	if ( !sd || !sd->dst_cache || sd->retransmits )		sd = sctp_route_normal(sp);	normal(sd);	return(sd);}/* *  WAKEUP (Send SACK, ERROR, DATA) *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */void sctp_transmit_wakeup(sp)	sctp_t *sp;{	int i;	mblk_t *mp;	sctp_daddr_t *sd;	int loop_max = 3000;		assert(sp);	sctp_lock(sp);	if ( (1<<sp->s_state) & SCTPF_SENDING ) {	for ( i=0; i<loop_max; i++ )	{		/* placed in order of probability */		if ( bufq_head(&sp->sndq)				|| (sp->sackf & SCTP_SACKF_NOW)				|| sp->nrtxs				|| bufq_head(&sp->urgq)				|| bufq_head(&sp->errq)				)		{			if ( !(sd = sctp_route_normal(sp)) ) {				rare(); break;			}			if ( !(mp = sctp_alloc_msg(sp, 0)) ) {				rare(); break;			}			sctp_bundle_more(sp, sd, mp);			if ( mp->b_next )			{				sctp_send_msg(sp, sd, mp);				freechunks(mp);				continue;			}			unusual( bufq_head(&sp->sndq) );			unusual( bufq_head(&sp->urgq) );			unusual( bufq_head(&sp->errq) );			unusual( sp->sackf & SCTP_SACKF_NOD );			unusual( sp->nrtxs ); if ( sp->nrtxs ) ptrace(("sp->nrtxs = %u\n",sp->nrtxs));			rare();			freechunks(mp);#if _DEBUG			for ( mp = bufq_head(&sp->sndq); mp; mp = mp->b_next )			{				sctp_tcb_t *cb = SCTP_TCB(mp);				printk("sndq: mp = %08x, dlen = %u\n", (uint)mp, cb->dlen);			}			for ( mp = bufq_head(&sp->urgq); mp; mp = mp->b_next )			{				sctp_tcb_t *cb = SCTP_TCB(mp);				printk("urgq: mp = %08x, dlen = %u\n", (uint)mp, cb->dlen);			}			for ( mp = bufq_head(&sp->rtxq); mp; mp = mp->b_next )			{				sctp_tcb_t *cb = SCTP_TCB(mp);				printk("rtxq: mp = %08x, dlen = %u, tsn = %u\n", (uint)mp, cb->dlen, cb->tsn);			}#endif		}		break;	}	assure( i < loop_max );	}	sctp_unlock(sp);	return;}/* *  ========================================================================= * *  SCTP State Machine TIMEOUTS * *  ========================================================================= */static void sctp_send_heartbeat(sctp_t *sp, sctp_daddr_t *sd);static void sctp_reset_idle(sctp_daddr_t *sd);/* *  ASSOCIATION TIMEOUT FUNCTION *  ------------------------------------------------------------------------- */static int sctp_assoc_timedout(sp, sd, rmax)	sctp_t *sp;	sctp_daddr_t *sd;	size_t rmax;{	assert( sp );	assert( sd );	/* RFC 2960 6.3.3 E1 and 7.2.3, E2, E3 and 8.3 */	sd->ssthresh	= sd->cwnd>>1 > sd->mtu<<1 ? sd->cwnd>>1 : sd->mtu<<1;	sd->cwnd	= sd->mtu;	sd->rto		= sd->rto ? sd->rto<<1 : 1;	sd->rto		= sd->rto_min > sd->rto ? sd->rto_min : sd->rto;	sd->rto		= sd->rto_max < sd->rto ? sd->rto_max : sd->rto;	/*See RFC 2960 Section 8.3 */	if ( sd->retransmits++ >= sd->max_retrans )	{		if ( sd->dst_cache )			dst_negative_advice(&sd->dst_cache);		if ( sd->retransmits == sd->max_retrans+1 )		{			/*			 *  IMPLEMENTATION NOTE:-  When max_retrans and			 *  rto_max are set to zero, we are cruel on			 *  destinations that drop a single packet due to			 *  noise.  This forces an immediate heartbeat on the			 *  destination so that it can be made available again			 *  quickly it if passes the heartbeat.			 */			if ( (1<<sp->s_state) & (SCTPF_CONNECTED|SCTPF_CLOSING) ) {				if ( sd->timer_idle )					untimeout(xchg(&sd->timer_idle,0));				sctp_send_heartbeat(sp, sd);			}		} else {			if ( (1<<sp->s_state) & (SCTPF_CONNECTED) )				return(0);		}	}	/*See RFC 2960 Section 8.2 */	if ( rmax && sp->retransmits++ >= rmax )	{		seldom();		if ( (1<<sp->s_state) & (SCTPF_HAVEUSER) ) {			sp->ops->sctp_discon_ind(sp, SCTP_ORIG_PROVIDER, -ETIMEDOUT, NULL);		} else rare();		__sctp_disconnect(sp);		return(-ETIMEDOUT);	}	return(0);}/* *  INIT TIMEOUT (T1-init) *  ------------------------------------------------------------------------- *  The init timer has expired indicating that we have not received an INIT *  ACK within timer T1-init.  This means that we should attempt to retransmit *  the INIT until we have attempted Max.Init.Retrans times. */static void sctp_init_timeout(data)	caddr_t data;{	sctp_t *sp;	sctp_daddr_t *sd;	sd = (sctp_daddr_t *)data;  assert( sd );	sp = sd->sp;		    assert( sp );	if ( sctp_locked(sp) ) { seldom();		sp->timer_init = timeout(sctp_init_timeout, (caddr_t)sd, 1);		return;	}	sp->timer_init = 0;	if ( sp->s_state != SCTP_COOKIE_WAIT ) {		rare(); return;	}	if ( sctp_assoc_timedout(sp, sd, sp->max_inits) ) {		seldom(); return;	}	sd = sp->taddr;	/* might have new primary */	ensure( sd, return );	set_timeout(&sp->timer_init, sctp_init_timeout, (caddr_t)sd, sd->rto);	usual( sp->retry );	sctp_send_msg(sp, sd, sp->retry);

⌨️ 快捷键说明

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