📄 if_scs.c
字号:
} } 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 + -