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

📄 hd_input.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* 	 *  This section tests the IFRAME for proper sequence. That is, it's	 *  sequence number N(S) MUST be equal to V(S).	 */	if (ns != hdp->hd_vr) {		hdp->hd_invalid_ns++;		if (pf || (hdp->hd_condition & REJ_CONDITION) == 0) {			hdp->hd_condition |= REJ_CONDITION;			/*			 * Flush the transmit queue. This is ugly but we			 * have no choice.  A reject response must be			 * immediately sent to the DCE.  Failure to do so			 * may result in another out of sequence iframe			 * arriving (and thus sending another reject)			 * before the first reject is transmitted. This			 * will cause the DCE to receive two or more			 * rejects back to back, which must never happen.			 */			hd_flush (hdp->hd_ifp);			hd_writeinternal (hdp, REJ, pf);		}		return (queued);	}	hdp->hd_condition &= ~REJ_CONDITION;	/* 	 *  This section finally tests the IFRAME's sequence number against	 *  the window size (K)  and the sequence number of the  last frame	 *  we have acknowledged.  If the IFRAME is completely correct then 	 *  it is queued for the packet level.	 */	if (ns != (hdp -> hd_lasttxnr + hdp -> hd_xcp -> xc_lwsize) % MODULUS) {		hdp -> hd_vr = (hdp -> hd_vr + 1) % MODULUS;		if (pf == 1) {			/* Must generate a RR or RNR with final bit on. */			hd_writeinternal (hdp, RR, POLLON);		} else			/*    			 *  Hopefully we can piggyback the RR, if not we will generate			 *  a RR when T3 timer expires.			 */			if (hdp -> hd_rrtimer == 0)				hdp->hd_rrtimer = hd_t3;		/* Forward iframe to packet level of X.25. */		fbuf -> m_data += HDHEADERLN;		fbuf -> m_len -= HDHEADERLN;		fbuf -> m_pkthdr.len -= HDHEADERLN;		fbuf -> m_pkthdr.rcvif = (struct ifnet *)hdp -> hd_pkp;#ifdef BSD4_3		fbuf->m_act = 0;	/* probably not necessary */#else		{			register struct mbuf *m;						for (m = fbuf; m -> m_next; m = m -> m_next)				m -> m_act = (struct mbuf *) 0;			m -> m_act = (struct mbuf *) 1;		}#endif		pk_input (fbuf);		queued = TRUE;		hd_start (hdp);	} else {		/* 		 *  Here if the remote station has transmitted more iframes then		 *  the number which have been acknowledged plus K. 		 */		hdp->hd_invalid_ns++;		frame_reject (hdp, W, frame);	}	return (queued);}/*  *  This routine is used to determine if a value (the middle parameter) *  is between two other values. The low value is  the first  parameter *  the high value is the last parameter. The routine checks the middle *  value to see if it is within the range of the first and last values. *  The reason we need this routine is the values are modulo some  base *  hence a simple test for greater or less than is not sufficient. */boolrange_check (rear, value, front)int     rear,        value,        front;{	register bool result = FALSE;	if (front > rear)		result = (rear <= value) && (value <= front);	else		result = (rear <= value) || (value <= front);	return (result);}/*  *  This routine handles all the frame reject conditions which can *  arise as a result  of secondary  processing.  The frame reject *  condition Y (frame length error) are handled elsewhere. */staticframe_reject (hdp, rejectcode, frame)struct hdcb *hdp;struct Hdlc_iframe *frame;{	register struct Frmr_frame *frmr = &hd_frmr;	frmr -> frmr_control = ((struct Hdlc_frame *) frame) -> control;	frmr -> frmr_ns = frame -> ns;	frmr -> frmr_f1_0 = 0;	frmr -> frmr_nr = frame -> nr;	frmr -> frmr_f2_0 = 0;	frmr -> frmr_0000 = 0;	frmr -> frmr_w = frmr -> frmr_x = frmr -> frmr_y =		frmr -> frmr_z = 0;	switch (rejectcode) {	case Z: 		frmr -> frmr_z = 1;/* invalid N(R). */		break;	case Y: 		frmr -> frmr_y = 1;/* iframe length error. */		break;	case X: 		frmr -> frmr_x = 1;/* invalid information field. */		frmr -> frmr_w = 1;		break;	case W: 		frmr -> frmr_w = 1;/* invalid N(S). */	}	hd_writeinternal (hdp, FRMR, POLLOFF);	hdp->hd_state = WAIT_SABM;	SET_TIMER (hdp);}/*  *  This procedure is invoked when ever we receive a supervisor *  frame such as RR, RNR and REJ. All processing for these *  frames is done here. */process_sframe (hdp, frame, frametype)register struct hdcb *hdp;register struct Hdlc_sframe *frame;int frametype;{	register int nr = frame -> nr, pf = frame -> pf, pollbit = 0;	if (valid_nr (hdp, nr, pf) == TRUE) {		switch (frametype) {		case RR: 			hdp->hd_condition &= ~REMOTE_RNR_CONDITION;			break;		case RNR: 			hdp->hd_condition |= REMOTE_RNR_CONDITION;			hdp->hd_retxcnt = 0;			break;		case REJ: 			hdp->hd_condition &= ~REMOTE_RNR_CONDITION;			rej_routine (hdp, nr);		}		if (pf == 1) {			hdp->hd_retxcnt = 0;			hdp->hd_condition &= ~TIMER_RECOVERY_CONDITION;			if (frametype == RR && hdp->hd_lastrxnr == hdp->hd_vs				&& hdp->hd_timer == 0 && hdp->hd_txq.head == 0)				hd_writeinternal(hdp, RR, pf);			else			/* If any iframes have been queued because of the			   timer condition, transmit then now. */			if (hdp->hd_condition & REMOTE_RNR_CONDITION) {				/* Remote is busy or timer condition, so only				   send one. */				if (hdp->hd_vs != hdp->hd_retxqi)					hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], pollbit);			}			else	/* Flush the retransmit list first. */				while (hdp->hd_vs != hdp->hd_retxqi)					hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF);		}		hd_start (hdp);	} else		frame_reject (hdp, Z, (struct Hdlc_iframe *)frame);	/* Invalid N(R). */}/*  *  This routine tests the validity of the N(R) which we have received. *  If it is ok,  then all the  iframes which it acknowledges  (if any) *  will be freed. */boolvalid_nr (hdp, nr, finalbit)register struct hdcb *hdp;register int finalbit;{	/* Make sure it really does acknowledge something. */	if (hdp->hd_lastrxnr == nr)		return (TRUE);	/* 	 *  This section validates the frame's  N(R) value.  It's N(R) value	 *  must be  in syncronization  with  our V(S)  value and  our "last	 *  received nr" variable. If it is correct then we are able to send	 *  more IFRAME's, else frame reject condition is entered.	 */	if (range_check (hdp->hd_lastrxnr, nr, hdp->hd_vs) == FALSE) {		if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) &&				range_check (hdp->hd_vs, nr, hdp->hd_xx) == TRUE)			hdp->hd_vs = nr;		else {			hdp->hd_invalid_nr++;			return (FALSE);		}	}	/* 	 *  If we get to here, we do have a valid frame  but it might be out	 *  of sequence.  However, we should  still accept the receive state	 *  number N(R) since it has already passed our previous test and it	 *  does acknowledge frames which we are sending.	 */	KILL_TIMER (hdp);	free_iframes (hdp, &nr, finalbit);/* Free all acknowledged iframes */	if (nr != hdp->hd_vs)		SET_TIMER (hdp);	return (TRUE);}/*  *  This routine determines how many iframes need to be retransmitted. *  It then resets the Send State Variable V(S) to accomplish this. */staticrej_routine (hdp, rejnr)register struct hdcb *hdp;register int rejnr;{	register int anchor;	/*	 * Flush the output queue.  Any iframes queued for	 * transmission will be out of sequence.	 */	hd_flush (hdp->hd_ifp);	/* 	 *  Determine how many frames should be re-transmitted. In the case 	 *  of a normal REJ this  should be 1 to K.  In the case of a timer	 *  recovery REJ (ie. a REJ with the Final Bit on) this could be 0. 	 */	anchor = hdp->hd_vs;	if (hdp->hd_condition & TIMER_RECOVERY_CONDITION)		anchor = hdp->hd_xx;	anchor = (anchor - rejnr + 8) % MODULUS;	if (anchor > 0) {		/* There is at least one iframe to retransmit. */		KILL_TIMER (hdp);		hdp->hd_vs = rejnr;		while (hdp->hd_vs != hdp->hd_retxqi)			hd_send_iframe (hdp, hdp->hd_retxq[hdp->hd_vs], POLLOFF);	}	hd_start (hdp);}/*  *  This routine frees iframes from the retransmit queue. It is called *  when a previously written iframe is acknowledged. */staticfree_iframes (hdp, nr, finalbit)register struct hdcb *hdp;int *nr;register int finalbit;{	register int    i, k;	/* 	 *  We  need to do the  following  because  of a  funny quirk  in  the 	 *  protocol.  This case  occures  when  in Timer  recovery  condition 	 *  we get  a  N(R)  which  acknowledges all  the outstanding  iframes	 *  but with  the Final Bit off. In this case we need to save the last	 *  iframe for possible retransmission even though it has already been 	 *  acknowledged!	 */	if ((hdp->hd_condition & TIMER_RECOVERY_CONDITION) && *nr == hdp->hd_xx && finalbit == 0) {		*nr = (*nr - 1 + 8) % MODULUS;/*		printf ("QUIRK\n"); */	}	k = (*nr - hdp->hd_lastrxnr + 8) % MODULUS;	/* Loop here freeing all acknowledged iframes. */	for (i = 0; i < k; ++i) {		m_freem (hdp->hd_retxq[hdp->hd_lastrxnr]);		hdp->hd_retxq[hdp->hd_lastrxnr] = 0;		hdp->hd_lastrxnr = (hdp->hd_lastrxnr + 1) % MODULUS;	}}

⌨️ 快捷键说明

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