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

📄 if_scs.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	        }	    } else {		if (scsnetdebug)	            printf( "scsnet - SCS  accept failed from %c%c%c%c%c%c%c%c\n",		        s->node_name[ 0 ], s->node_name[ 1 ],		        s->node_name[ 2 ], s->node_name[ 3 ],		        s->node_name[ 4 ], s->node_name[ 5 ],		        s->node_name[ 6 ], s->node_name[ 7 ] );	        scsnet_rem_sys(sys, cmsb);	    }	    smp_unlock(&sys->lk_netsys);	    break;        case CRE_REJECT_DONE:	    break;        case CRE_CONN_REC:	    /* 	     * connection request received.  If a connection has already 	     * been established to the remote sysap then reject this request.	     * If we have already initiated a connection request then reject the	     * new request iff the remote sysid is greater than the local sysid.	     * (Any deterministic method for deciding who wins will do).	     * If we have not sent a connection request then accept this one.	     */	    {	    struct _netsystem *netsystem;	    ISB isb;	    int rmthost = in_lnaof(scd->rmt_inaddr) & 0xff;	    bzero((caddr_t)&isb, sizeof(ISB));	    if (rmthost < 0 || rmthost > SCSNET_MAXHOSTS - 1 ) {		cmsb->Reason = ADR_CONNECTION;		printf("scsnet: received connection request from invalid host, host#=%d \n", rmthost);		if ( (status = scs_reject( cmsb )) != RET_SUCCESS )		    mprintf("scsnet reject failed, status=%d\n", status);		return;	    }	    scsnet_status(cmsb->sysid, &status);	    if (scsnetdebug)	        printf("scsnet conn req recv from %x %x %x, status=%d\n",                     Scaaddr_hi( cmsb->sysid ), Scaaddr_mid( cmsb->sysid ),                    Scaaddr_low( cmsb->sysid ), status );	    switch (status) {	    case SCSNET_CONN_OPEN:	        cmsb->Reason = ADR_CONNECTION;				if (scsnetdebug)		    printf("scsnet: conn already open to %x %x %x\n",                       Scaaddr_hi( cmsb->sysid ),                       Scaaddr_mid( cmsb->sysid ), Scaaddr_low( cmsb->sysid ));		if ( (status = scs_reject( cmsb )) != RET_SUCCESS )		    mprintf("scsnet: failed to reject connection attempt from host %d, status=%d\n", rmthost, status);		return;		break;	    case SCSNET_CONN_SENT:		if (scsnetdebug) {		    Print_sysid(scsnet_local.system.sysid)		    printf("scsnet: conn req already sent to %x %x %x\n",                        Scaaddr_hi( cmsb->sysid ), Scaaddr_mid( cmsb->sysid ),                        Scaaddr_low( cmsb->sysid ));		}	        if( Sysid_greater(cmsb->sysid, scsnet_local.system.sysid) ) {		    if (scsnetdebug)		        printf("rejected\n");		    cmsb->Reason = ADR_CONNECTION;		    if ( (status = scs_reject( cmsb )) != RET_SUCCESS )		        mprintf("scsnet: failed to reject concurrent connection attempt from host %d, status=%d\n", rmthost, status);		    return;	        }		break;	    case SCSNET_CONN_REC:		mprintf("scsnet: duplicate connection request from: %x %x %x\n",                Scaaddr_hi( cmsb->sysid ), Scaaddr_mid( cmsb->sysid ),                Scaaddr_low( cmsb->sysid ));		cmsb->Reason = ADR_CONNECTION;		if ((status =  scs_reject( cmsb )) != RET_SUCCESS )		    mprintf("scsnet: failed to reject connection attempt from host %d, status=%d\n", rmthost, status);		return;		break;	    }	    /*	     * There is no connection to this system yet.  Check version	     * and if ok accept the connection.	     */#ifdef notdef	    if (scd->version < SCSNET_VERSION_ID) {		if (scsnetdebug)		    printf("version mismatch: local: %d, remote: %d\n", 			SCSNET_VERSION_ID, scd->version);		cmsb->Reason = ADR_VERSION;		if ((status =  scs_reject( cmsb )) != RET_SUCCESS )		    mprintf("scsnet: failed to reject connection attempt from host %d, status=%d\n", rmthost, status);		return;	    }#endif	    if ((netsystem=alloc_netsys())==SCSNET_NO_SYS) {	   	printf( "SCS_NET - could not accept connection from host %d, too many systems\n", in_lnaof(scd->rmt_inaddr) & 0xff);		return;	    }	    smp_lock(&netsystem->lk_netsys, LK_RETRY);	    /*	     * accept the connection	     */	    cmsb->control = scsnet_control;	    cmsb->dg_event = scsnet_dgevent;	    cmsb->msg_event = scsnet_msgevent;	    cmsb->init_rec_credit = 5;	    cmsb->init_dg_credit = 5;	    cmsb->min_snd_credit = 5;	    Move_scaaddr( cmsb->sysid, isb.next_sysid )	    if( scs_info_system(&isb, (s = &netsystem->sys_info)) 			!= RET_SUCCESS ) {	     	printf( "scsnet - Can't Find Recv System in Database\n" );		panic("scsnet - control");	    }	    netsystem->status = SCSNET_CONN_REC;	    netsystem->rmt_index = in_lnaof(scd->rmt_inaddr) & 0xff;	    if (scsnetdebug) {	        printf("scsnet:  conn recv, netsys=%x, rmtindex=%d, ourhost=%d\n",			netsystem, netsystem->rmt_index, scsnet_lhost);	        printf( "scsnet: accept sent to %c%c%c%c%c%c%c%c \n",			s->node_name[ 0 ], s->node_name[ 1 ],			s->node_name[ 2 ], s->node_name[ 3 ],			s->node_name[ 4 ], s->node_name[ 5 ],			s->node_name[ 6 ], s->node_name[ 7 ] );	    }	    /*	     * send our internet address to the remote site	     * so it can use it later on to figure out which connection	     * to use	     */	    scd->rmt_inaddr = scs_inet_addr;	    scd->version = SCSNET_VERSION_ID;	    cmsb->aux = (u_char *)netsystem;	    if (( status = scs_accept( cmsb )) != RET_SUCCESS )	    /* Acceptance of the connection request failed.  Reject the	     * connection request if the acceptance failed due to an	     * allocation error.  Otherwise, panic as some serious problem	     * has been encountered.  	     */		if ( status == RET_ALLOCFAIL ) {		    netsystem->status = SCSNET_CONN_CLOSED;		    cmsb->Reason = ADR_NORESOURCE;		    if ( (status = scs_reject( cmsb )) != RET_SUCCESS )		        mprintf("scsnet reject failed, status=%d\n", status);		    }		else		    panic( "scsnet - ACCEPT Failed\n" );	    smp_unlock(&netsystem->lk_netsys);	    }	    break;	        default:	    panic( "scsnet - Unknown or Unexpected Event Reported\n" );	}}scsnet_output(ifp, m0, dst)	struct ifnet *ifp;	struct mbuf *m0;	struct sockaddr *dst;{	register struct scsnet_cntl *scscp;	register struct mbuf *m = m0;	register int i;	struct scsnet_msg *msg;	CSB csb;	u_char *off;	struct _netsystem *nextsys;	int notblock = 0;	int len;	struct in_addr inet_dst;	struct _netsystem *scs_dst;	long type;	int status;	int ipl;	int broadcast = 0;	struct mbuf *mchain = 0;	extern u_short scs_msg_size;	int rspid;	        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {                return(ENETDOWN);        }	if (dst->sa_family == AF_INET) {		inet_dst = ((struct sockaddr_in *)dst)->sin_addr;		if ((broadcast = in_broadcast(inet_dst))) 			nextsys = netsystems;		else { 			Scsnet_resolve(inet_dst, scs_dst)		}		type = AF_INET;	} 	else	if (dst->sa_family != AF_UNSPEC) {		printf("scsnet output:  unknown family %x\n", dst->sa_family);		m_freem(m0);		return (EAFNOSUPPORT);	}broadcastloop:	if (broadcast) {		while (nextsys <= scsnet_topsysaddr)			if (nextsys->status == SCSNET_CONN_OPEN) {				scs_dst = nextsys;				nextsys++;				m = m0;				goto send;			} else				nextsys++;		m_freem(m0);		return (0);	}		send:	len = ntohs((u_short)mtod(m, struct ip *)->ip_len);#ifdef notdef	if (scsnetstaton)		if (len < 100)			scsnetstat[0]++; 		else if (len < 200) 			scsnetstat[1]++; 		else if (len < 500)			scsnetstat[2]++; 		else if (len < 1000)			scsnetstat[3]++; 		else if (len < 2000)			scsnetstat[4]++; 		else if (len < 3000)			scsnetstat[5]++; 		else if (len < 4000)			scsnetstat[6]++; 		else if (len < 5000)			scsnetstat[7]++; 		else		    scsnetstat[8]++;#endif        ipl = Splscs();	smp_lock(&scs_dst->lk_netsys, LK_RETRY);	/* recheck status just in case the connection went away before we	 * grabbed the lock.   We grab the lock here because we dont want	 * to keep the output routine at high ipl very long.	 */	if (scs_dst->status != SCSNET_CONN_OPEN) {		smp_unlock(&scs_dst->lk_netsys);		if (broadcast) {			(void)splx(ipl);			goto broadcastloop;		}		else {			if (scsnetdebug)		    	    printf("scsnet: connection not resolved to %d\n", 				in_lnaof(inet_dst) & 0xff);				m_freem(m0);								(void)splx(ipl);			return(0);						}	}	/* if we can stuff everything into a datagram then do it.	 * Otherwise try a block transfer	 */	if (len > scs_dg_size - SCSNET_HDR_SIZ) {	    /* block transfer	     * Move mbuf data to a virtually contiguous buffer.	     * Place protocol header in sequenced msg.	     * Send the sequenced msg to the remote host requesting	     * it to block transfer the data from us to it.	     * The block transfer will take place asynchronously.	     * We release mbuf resourses when we receive a sequenced	     * msg acknowledgment that the transfer completed.	     * There can be SCSNET_XFERS outstanding transmissions.	     * If we cannot transmit the current packet because	     * the quota of outstanding transmissions has been reached then	     * the packet is queued. 	     * If we can not allocate resources for the block transfer 	     * or the ack indicates that the remote	     * host could not perform the block transfer	     * then we release the resouces and return with ENOBUFS.	     */		 	    /*	     * Find a free buffer 	     */			    scscp = scsnet_xfers + scs_dst->rmt_index*SCSNET_XFERS;	    {	        register struct scsnet_cntl *lim = scscp + SCSNET_XFERS;	        for (; scscp < lim;  scscp++) 		    if (scscp->state & SCSNET_BDONE)			goto got_one;		if (scsnetdebug)	        	printf("scsnet out: no free buffers for host= %d\n", 				scs_dst->rmt_index);		/* Currently smp locked by knownsystems but should use 		 * its own lock if we get rid of knownsystems lock above		 */		Scsnet_If_Enqueue_Return got_one:		scscp->timer = 0;	        rspid = scs_dst->rmt_index*SCSNET_XFERS + scscp->xindex;	    }			   /*	    * we have all the resources we need.  Theoretically	    * the remote side does also.	    */		    if (broadcast) {		 if ((mchain = m_copy(m0, 0, M_COPYALL))==0) {			if (scsnetdebug)			    printf("scsnet_out: could not copy broadcast msg\n");					smp_unlock(&scs_dst->lk_netsys);			Scsnet_Return_ENOBUFS 		 }	    }	    else 		mchain = m0;		 	   /*	    * save pointer to mbuf chain so that we can free it later 	    */	    scscp->mchain = mchain;#ifdef SCSNETDEBUG	    if (scsnetdebug > 1)		mprintf("scsnet_out: len=%d\n", len);#endif	   /*	    * set up command packet 	    */	    msg = (struct scsnet_msg *)scscp->csb.buf;	    msg->rspid = rspid;	    msg->cmd = SCSNET_BCMD_REQUEST;	   /*	    * copy protocol type and header to message buffer	    */	    bcopy(&type, msg->proto_hdr, SCSNET_HDR_SIZ);	    bcopy(mtod(m, caddr_t), msg->proto_hdr+SCSNET_HDR_SIZ, m->m_len);	    scscp->csb.size = Scsnet_msg_hdr_siz + SCSNET_HDR_SIZ + m->m_len;	    off = scscp->csb.buf + scscp->csb.size;	    if (scscp->csb.size > scs_msg_size)		panic("SCSNET: proto header to long");	    len -= m->m_len;	    /*	     * Put leading small mbufs in seq message. This	     * will ensure that leading data is page aligned.	     */	    m = m->m_next; /* point to data */			    while (m && scscp->csb.size + m->m_len <= scs_msg_size)  {		bcopy(mtod(m, caddr_t), off, m->m_len);		off += m->m_len;		len -= m->m_len;		scscp->csb.size += m->m_len;		m = m->m_next;	    }			    /*	     * A page may also be chopped.  If the data is larger than	     * NBPG then the upper levels try to use pages. Otherwise	     * little mbufs are used.  The protocol layers may cut 	     * a page in pieces by adjusting the offset to the page	     * buffer.  The offset to a page mbuf should always be	     * greater than MMAXOFF.  We have to be prepared to transmit	     * an offset page at the beginning of a chain and a cut	     * page at the end of a chain.	     * We should also be prepared for type II mbufs in which	     * the data may not start on a page boundary and can be	     * more than CLBYTES in length.  We can not assume that	     * the data area in a type II mbuf comes from the mbuf pool	     * i.e.  the use of mbuf specific macros could fail.	     */	    /* We should now be pointing to data.  If the data is page	     * aligned then we can use the pfn from the mbuf pages instead	     * of copying.  	     */	    {	        register caddr_t dp;		register struct pte *frompte;		register struct pte *topte = &scsmemptmap[scscp->xpte];	        register caddr_t tova = (caddr_t) scsxtob(scscp->xpte);		int rem = 0;		#define Mbufpage(m)	(m->m_off > MMAXOFF)  		msg->off = 0;	        while (m) { 		    int pgoff = 0;		    		    dp = mtod(m, char *);		    pgoff = (int)dp & PGOFSET;	            if ( Mbufpage(m) && claligned(tova) 				     && pgoff+m->m_len >= NBPG){			    

⌨️ 快捷键说明

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