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

📄 llc_subr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
 * AWAIT_REJECT --- A data link connection exists between the local LLC service *                  access point and the remote LLC service access point. The *                  local connection component has requested that the remote *                  connection component re-transmit a specific I PDU that the *                  local connection component has detected as being out of *                  sequence. Before the local LLC entered this state it was *                  performing a timer recovery operation and had sent a *                  command PDU with the P bit set to ``1'', and is still *                  awaiting an acknowledgment from the remote LLC. I PDUs may *                  be received but not transmitted. Supervisory PDUs may be *                  both transmitted and received. */intllc_state_AWAIT_REJECT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,		       int cmdrsp, int pollfinal){	int action = LLC_PASSITON;	switch(frame_kind + cmdrsp) {	case LLC_LOCAL_BUSY_DETECTED:		llc_send(linkp, LLCFT_RNR, LLC_CMD, 0);		LLC_SETFLAG(linkp, DATA, 2);		LLC_NEWSTATE(linkp, AWAIT_BUSY);		action = 0;		break;	case LLC_INVALID_NS + LLC_CMD:	case LLC_INVALID_NS + LLC_RSP: {		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);				if (cmdrsp == LLC_CMD && pollfinal == 1) {			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);			LLC_UPDATE_NR_RECEIVED(linkp, nr);			action = 0;		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {			LLC_UPDATE_NR_RECEIVED(linkp, nr);			linkp->llcl_vs = nr;			llc_resend(linkp, LLC_CMD, 1);			LLC_START_P_TIMER(linkp);			LLC_CLEAR_REMOTE_BUSY(linkp, action);			LLC_NEWSTATE(linkp, REJECT);		} else if (pollfinal == 0) {			LLC_UPDATE_NR_RECEIVED(linkp, nr);			action = 0;			}		break;	}	case LLCFT_INFO + LLC_CMD:	case LLCFT_INFO + LLC_RSP: {		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);		if (cmdrsp == LLC_CMD && pollfinal == 1) {			LLC_INC(linkp->llcl_vr);			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);			LLC_STOP_REJ_TIMER(linkp);			LLC_UPDATE_NR_RECEIVED(linkp, nr);			LLC_NEWSTATE(linkp, AWAIT);			action = LLC_DATA_INDICATION;		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {			LLC_INC(linkp->llcl_vr);			LLC_STOP_P_TIMER(linkp);			LLC_STOP_REJ_TIMER(linkp);			LLC_UPDATE_NR_RECEIVED(linkp, nr);			linkp->llcl_vs = nr;			llc_resend(linkp, LLC_CMD, 0);			LLC_CLEAR_REMOTE_BUSY(linkp, action);			LLC_NEWSTATE(linkp, NORMAL);			action = LLC_DATA_INDICATION;		} else if (pollfinal == 0) {			LLC_INC(linkp->llcl_vr);			llc_send(linkp, LLCFT_RR, LLC_CMD, 0);			LLC_STOP_REJ_TIMER(linkp);			LLC_UPDATE_NR_RECEIVED(linkp, nr);			LLC_NEWSTATE(linkp, AWAIT);			action = LLC_DATA_INDICATION;		}		break;	}	case LLCFT_RR + LLC_CMD:	case LLCFT_REJ + LLC_CMD:	case LLCFT_RR + LLC_RSP:	case LLCFT_REJ + LLC_RSP: {		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);				if (cmdrsp == LLC_CMD && pollfinal ==  1) {			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);			LLC_UPDATE_NR_RECEIVED(linkp, nr);			LLC_CLEAR_REMOTE_BUSY(linkp, action);		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {			LLC_UPDATE_NR_RECEIVED(linkp, nr);			linkp->llcl_vs = nr;			llc_resend(linkp, LLC_CMD, 1);			LLC_START_P_TIMER(linkp);			LLC_CLEAR_REMOTE_BUSY(linkp, action);			LLC_NEWSTATE(linkp, REJECT);		} else if (pollfinal == 0) {			LLC_UPDATE_NR_RECEIVED(linkp, nr);			LLC_CLEAR_REMOTE_BUSY(linkp, action);		}		break;	}	case LLCFT_RNR + LLC_CMD:	case LLCFT_RNR + LLC_RSP: {		register int nr = LLCGBITS(frame->llc_control_ext, s_nr);		if (cmdrsp == LLC_CMD && pollfinal == 1) {			llc_send(linkp, LLCFT_RR, LLC_RSP, 1);			LLC_UPDATE_NR_RECEIVED(linkp, nr);			LLC_SET_REMOTE_BUSY(linkp, action);		} else if (cmdrsp == LLC_RSP && pollfinal == 1) {			LLC_UPDATE_NR_RECEIVED(linkp, nr);			linkp->llcl_vs = nr;			LLC_STOP_P_TIMER(linkp);			LLC_SET_REMOTE_BUSY(linkp, action);			LLC_NEWSTATE(linkp, REJECT);		} else if (pollfinal == 0) {			LLC_UPDATE_NR_RECEIVED(linkp, nr);			LLC_SET_REMOTE_BUSY(linkp, action);		}		break;	}	case LLC_P_TIMER_EXPIRED:		if (linkp->llcl_retry < llc_n2) {			llc_send(linkp, LLCFT_REJ, LLC_CMD, 1);			LLC_START_P_TIMER(linkp);			linkp->llcl_retry++;			action = 0;		}		break;	}	if (action == LLC_PASSITON)		action = llc_state_NBRAcore(linkp, frame, frame_kind, 					    cmdrsp, pollfinal);	return action;}/* * llc_statehandler() --- Wrapper for llc_state_*() functions. *                         Deals with action codes and checks for *                         ``stuck'' links. */intllc_statehandler(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,		 int cmdrsp, int pollfinal){	register int action = 0;	/*	 * To check for ``zombie'' links each time llc_statehandler() gets called	 * the AGE timer of linkp is reset. If it expires llc_timer() will	 * take care of the link --- i.e. kill it 8=)	 */	LLC_STARTTIMER(linkp, AGE);	/*	 * Now call the current statehandler function.	 */	action = (*linkp->llcl_statehandler)(linkp, frame, frame_kind, 					     cmdrsp, pollfinal);once_more_and_again:	switch (action) {	case LLC_CONNECT_INDICATION: {		int naction;		LLC_TRACE(linkp, LLCTR_INTERESTING, "CONNECT INDICATION");		linkp->llcl_nlnext = 		     (*linkp->llcl_sapinfo->si_ctlinput)		      (PRC_CONNECT_INDICATION,		       (struct sockaddr *) &linkp->llcl_addr, (caddr_t) linkp);		if (linkp->llcl_nlnext == 0)			naction = NL_DISCONNECT_REQUEST;		else naction = NL_CONNECT_RESPONSE;		action = (*linkp->llcl_statehandler)(linkp, frame, naction, 0, 0);		goto once_more_and_again;	}	case LLC_CONNECT_CONFIRM:		/* llc_resend(linkp, LLC_CMD, 0); */		llc_start(linkp);		break;	case LLC_DISCONNECT_INDICATION:		LLC_TRACE(linkp, LLCTR_INTERESTING, "DISCONNECT INDICATION");		(*linkp->llcl_sapinfo->si_ctlinput)		  (PRC_DISCONNECT_INDICATION, 		   (struct sockaddr *) &linkp->llcl_addr, linkp->llcl_nlnext);		break;        /* internally visible only */	case LLC_RESET_CONFIRM:	case LLC_RESET_INDICATION_LOCAL:		/*		 * not much we can do here, the state machine either makes it or		 * brakes it ...		 */		break;	case LLC_RESET_INDICATION_REMOTE:		LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "RESET INDICATION (REMOTE)");		action = (*linkp->llcl_statehandler)(linkp, frame, 						     NL_RESET_RESPONSE, 0, 0);		goto once_more_and_again;	case LLC_FRMR_SENT:		LLC_TRACE(linkp, LLCTR_URGENT, "FRMR SENT");		break;	case LLC_FRMR_RECEIVED:		LLC_TRACE(linkp, LLCTR_URGEN, "FRMR RECEIVED");		action = (*linkp->llcl_statehandler)(linkp, frame,						     NL_RESET_REQUEST, 0, 0);				goto once_more_and_again;	case LLC_REMOTE_BUSY:		LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "REMOTE BUSY");		break;	case LLC_REMOTE_NOT_BUSY:		LLC_TRACE(linkp, LLCTR_SHOULDKNOW, "REMOTE BUSY CLEARED");		/*		 * try to get queued frames out		 */		llc_start(linkp);		break;	}			/*         * Only LLC_DATA_INDICATION is for the time being	 * passed up to the network layer entity.	 * The remaining action codes are for the time 	 * being visible internally only.         * However, this can/may be changed if necessary.	 */	return action;}/* * Core LLC2 routines */ /* * The INIT call. This routine is called once after the system is booted. */llc_init(){	llcintrq.ifq_maxlen = IFQ_MAXLEN;}/* * In case of a link reset we need to shuffle the frames queued inside the * LLC2 window. */voidllc_resetwindow(struct llc_linkcb *linkp){	register struct mbuf *mptr = (struct mbuf *) 0;	register struct mbuf *anchor = (struct mbuf *)0;	register short i;	/* Pick up all queued frames and collect them in a linked mbuf list */	if (linkp->llcl_slotsfree != linkp->llcl_window) {		i = llc_seq2slot(linkp, linkp->llcl_nr_received);		anchor = mptr = linkp->llcl_output_buffers[i]; 		for (; i != linkp->llcl_freeslot; 		     i = llc_seq2slot(linkp, i+1)) {			if (linkp->llcl_output_buffers[i]) {				mptr->m_nextpkt = linkp->llcl_output_buffers[i];				mptr = mptr->m_nextpkt;			} else panic("LLC2 window broken");		}	}	/* clean closure */	if (mptr)		mptr->m_nextpkt = (struct mbuf *) 0;	/* Now --- plug 'em in again */	if (anchor != (struct mbuf *)0) {		for (i = 0, mptr = anchor; mptr != (struct mbuf *) 0; i++) {			linkp->llcl_output_buffers[i] = mptr;			mptr = mptr->m_nextpkt;			linkp->llcl_output_buffers[i]->m_nextpkt = (struct mbuf *)0;		}		linkp->llcl_freeslot = i;	} else linkp->llcl_freeslot = 0;		/* We're resetting the link, the next frame to be acknowledged is 0 */	linkp->llcl_nr_received = 0;	/* set distance between LLC2 sequence number and the top of window to 0 */	linkp->llcl_projvs = linkp->llcl_freeslot;	return;}			/* * llc_newlink() --- We allocate enough memory to contain a link control block *                   and initialize it properly. We don't intiate the actual setup *                   of the LLC2 link here. */struct llc_linkcb *llc_newlink(struct sockaddr_dl *dst, struct ifnet *ifp, struct rtentry *nlrt, 	    caddr_t nlnext, struct rtentry *llrt){	struct llc_linkcb *nlinkp;	u_char sap = LLSAPADDR(dst);	short llcwindow;	/* allocate memory for link control block */	MALLOC(nlinkp, struct llc_linkcb *, sizeof(struct llc_linkcb),	       M_PCB, M_DONTWAIT);	if (nlinkp == 0)		return (NULL);	bzero((caddr_t)nlinkp, sizeof(struct llc_linkcb));		/* copy link address */	sdl_copy(dst, &nlinkp->llcl_addr);	/* hold on to the network layer route entry */	nlinkp->llcl_nlrt = nlrt;	/* likewise the network layer control block */	nlinkp->llcl_nlnext = nlnext;	/* jot down the link layer route entry */	nlinkp->llcl_llrt = llrt;	/* reset writeq */	nlinkp->llcl_writeqh = nlinkp->llcl_writeqt = NULL;	/* setup initial state handler function */	nlinkp->llcl_statehandler = llc_state_ADM;		/* hold on to interface pointer */	nlinkp->llcl_if = ifp;	/* get service access point information */	nlinkp->llcl_sapinfo = llc_getsapinfo(sap, ifp);	/* get window size from SAP info block */	if ((llcwindow = nlinkp->llcl_sapinfo->si_window) == 0)		llcwindow = LLC_MAX_WINDOW;	/* allocate memory for window buffer */	MALLOC(nlinkp->llcl_output_buffers, struct mbuf **, 	       llcwindow*sizeof(struct mbuf *), M_PCB, M_DONTWAIT);	if (nlinkp->llcl_output_buffers == 0) {		FREE(nlinkp, M_PCB);		return(NULL);	}	bzero((caddr_t)nlinkp->llcl_output_buffers, 	      llcwindow*sizeof(struct mbuf *));	/* set window size & slotsfree */	nlinkp->llcl_slotsfree = nlinkp->llcl_window = llcwindow;	/* enter into linked listed of link control blocks */	insque(nlinkp, &llccb_q);	return(nlinkp);}/* * llc_dellink() --- farewell to link control block */llc_dellink(struct llc_linkcb *linkp){	register struct mbuf *m;	register struct mbuf *n;	register struct npaidbentry *sapinfo = linkp->llcl_sapinfo;	register i;	/* notify upper layer of imminent death */	if (linkp->llcl_nlnext && sapinfo->si_ctlinput)		(*sapinfo->si_ctlinput)		   (PRC_DISCONNECT_INDICATION, 		    (struct sockaddr *)&linkp->llcl_addr, linkp->llcl_nlnext);	/* pull the plug */	if (linkp->llcl_llrt)		((struct npaidbentry *)(linkp->llcl_llrt->rt_llinfo))->np_link 			= (struct llc_linkcb *) 0;	/* leave link control block queue */	remque(linkp);	/* drop queued packets */	for (m = linkp->llcl_writeqh; m;) {		n = m->m_act;		m_freem(m);		m = n;	}	/* drop packets in the window */	for(i = 0; i < linkp->llcl_window; i++)		if (linkp->llcl_output_buffers[i])			m_freem(linkp->llcl_output_buffers[i]);	/* return the window space */	FREE((caddr_t)linkp->llcl_output_buffers, M_PCB);	/* return the control block space --- now it's gone ... */	FREE((caddr_t)linkp, M_PCB);}llc_decode(struct llc* frame, struct llc_linkcb * linkp){	register int ft = LLC_BAD_PDU;	if ((frame->llc_control & 01) == 0) {		ft = LLCFT_INFO;	/* S or U frame ? */	} else switch (frame->llc_control) {	/* U frames */	case LLC_UI:	case LLC_UI_P:     ft = LLC_UI; break;	case LLC_DM:	case LLC_DM_P:     ft =LLCFT_DM; break;	case LLC_DISC:	case LLC_DISC_P:   ft = LLCFT_DISC; break;	case LLC_UA:	case LLC_UA_P:     ft = LLCFT_UA; break;	case LLC_SABME:	case LLC_SABME_P:  ft = LLCFT_SABME; break;	case LLC_FRMR:	case LLC_FRMR_P:   ft = LLCFT_FRMR; break;	case LLC_XID:	case LLC_XID_P:    ft = LLCFT_XID; break;	case LLC_TEST:	case LLC_TEST_P:   ft = LLCFT_TEST; break;	/* S frames */	case LLC_RR:       ft = LLCFT_RR; break;	case LLC_RNR:      ft = LLCFT_RNR; break;	case LLC_REJ:      ft = LLCFT_REJ; break;	} /* switch */	if (linkp) {		switch (ft) {		case LLCFT_INFO:			if (LLCGBITS(frame->llc_control, i_ns) != linkp->llcl_vr) {				ft = LLC_INVALID_NS;				break;			}			/* fall thru --- yeeeeeee */		case LLCF

⌨️ 快捷键说明

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