📄 if_scs.c
字号:
#ifdef INET /* this will have to change when we make things more general */ smp_lock(&lk_ifnet, LK_RETRY); for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if (ifa->ifa_addr.sa_family == AF_INET) break; scs_inet_addr = IA_SIN(ifa)->sin_addr; smp_unlock(&lk_ifnet); scsnet_lhost = in_lnaof(scs_inet_addr) & 0xff; if (scsnet_lhost < 0 || scsnet_lhost > SCSNET_MAXHOSTS - 1 ) { printf("scsnet: can not initialize because host number is invalid, host=%d\n", scsnet_lhost); return(1); }#endif /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return (1); if (ifp->if_flags & IFF_RUNNING) return (0); scsnet_topsysaddr = netsystems; ifp->if_snd.ifq_maxlen = ifqmaxlen; /* scs_info_scs get lock at scs level so raise priority here */ ipl = Splscs(); /* obtain local system information */ scs_info_scs(&scsnet_local); Move_scaaddr( scsnet_local.system.sysid, sid ) if (scsnetdebug) printf("scs init - local sysid: %x,%x,%x, local inet host=%d\n", Scaaddr_hi( sid ), Scaaddr_mid( sid ), Scaaddr_low( sid ), scsnet_lhost ); for (i=0; i<SCSNET_RECVS; i++) scsnet_recvs[i].state = SCSNET_BDONE; for (i=0; i<SCSNET_MAXHOSTS; i++) knownsystems[i] = SCSNET_NO_SYS; Init_queue(netsys_head) /* start listening */ netcmsb.control = scsnet_control; bcopy (SYSAP_NET, netcmsb.lproc_name, NAME_SIZE); ipl = Splscs(); if ((ret=scs_listen(&netcmsb))!= RET_SUCCESS) { (void)splx( ipl ); if (scsnetdebug) printf("scs_listen failed, ret=%x\n", ret); return(1); } (void)splx( ipl ); /* * Connect to all of the systems we know about */ Zero_scaaddr(isb->next_sysid); /* start at the beginning */ do { if ((netsystem=alloc_netsys())==SCSNET_NO_SYS) panic("scsnet: too many systems"); smp_lock(&netsystem->lk_netsys, LK_RETRY); netsystem->rmt_index = SCSNET_NO_INDEX; if (scsnet_connect(netsystem, isb) != RET_SUCCESS) scsnet_rem_sys(netsystem, &netcmsb); smp_unlock(&netsystem->lk_netsys); } while (!Test_scaaddr( isb->next_sysid)); (void)splx( ipl ); scsnet_timeo = SCSNET_TIMEO; ifp->if_flags |= IFF_RUNNING | IFF_UP; return (0);}/* * scsnet_control: event notification routine. * * * * event Action * * CRE_CONN_REC If enough resources are available send an accept. * Otherwise send a reject. * * CRE_ACCEPT_DONE Add remote system to known systems list and reserve * resources for I/O. * * CRE_REJECT_DONE none * CRE_DISCONN_REC Issue disconnect to remote sysap and deallocate * resources dedicated to connection. * CRE_PATH_FAILURE Issue disconnect to remote sysap and deallocate * resources dedicated to connection. Try to reconnect * in the event another path exists. * CRE_DISCONN_DONE none * CRE_BLOCK_DONE Deallocate buffer space and send ack. * CRE_CREDIT_AVAIL none * CRE_NEW_PATH Issue connect to new system. * CRE_CONN_DONE If successful then add to list of known systems and * reserve resources for I/O. * If remote sysap was busy then issue another connect. * If connect failed deallocate any resources devoted * to the connection request. * * Inputs: * * cmsb - Connection Management Services Block * event - Event type * * Outputs: * * cmsb - Connection Management Service Block pointer * INITIALIZED ( depending upon actions taken ) * * Return * Values: NONE */ voidscsnet_control( event, cmsb ) u_short event; register CMSB *cmsb;{ register struct _netsystem *sys = (struct _netsystem *)cmsb->aux; register SIB *s = &sys->sys_info; struct scsnet_conn_data *scd = (struct scsnet_conn_data *)cmsb->conn_data; int status, ret;#ifdef SCSNETDEBUG if (scsnetdebug > 1) { printf("scsnet_control: sys=%x, event=%d, cmsb->status=%d, cmsb->sysid=%x,%x,%x\n", sys, event, cmsb->status, Scaaddr_hi( cmsb->sysid ) Scaaddr_mid( cmsb->sysid ), Scaaddr_low( cmsb->sysid )); printf(" lproc_name=%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n", cmsb->lproc_name[0], cmsb->lproc_name[1], cmsb->lproc_name[2], cmsb->lproc_name[3], cmsb->lproc_name[4], cmsb->lproc_name[5], cmsb->lproc_name[6], cmsb->lproc_name[7], cmsb->lproc_name[8], cmsb->lproc_name[9], cmsb->lproc_name[10], cmsb->lproc_name[11], cmsb->lproc_name[12], cmsb->lproc_name[13],cmsb->lproc_name[14], cmsb->lproc_name[15]); printf(" rproc_name=%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n", cmsb->rproc_name[0], cmsb->rproc_name[1], cmsb->rproc_name[2], cmsb->rproc_name[3], cmsb->rproc_name[4], cmsb->rproc_name[5], cmsb->rproc_name[6], cmsb->rproc_name[7], cmsb->rproc_name[8], cmsb->rproc_name[9], cmsb->rproc_name[10], cmsb->rproc_name[11], cmsb->rproc_name[12], cmsb->rproc_name[13],cmsb->rproc_name[14], cmsb->rproc_name[15]); }#endif if (event == CRE_BLOCK_DONE) { /* block transfer completed. * Send and ack to the other side and free up local resource. */ register struct scsnet_cntl *scscp = &scsnet_recvs[cmsb->blockid]; register struct scsnet_msg *msg = (struct scsnet_msg *)scscp->csb.buf; register struct mbuf *m = scscp->mchain; register struct ifnet *ifp = &scsnetif;#ifdef SCSNETDEBUG if (scsnetdebug > 2) printf("scsnet_control: rspid=%d\n", msg->rspid);#endif /* * queue data to the appropriate protocol. */ Scsnet_enqueue(m) ifp->if_ipackets++; /* * send and acknowledment back to the remote host */ msg->cmd = SCSNET_BCMD_ACK; scscp->csb.connid = cmsb->connid; scscp->csb.size = Scsnet_msg_hdr_siz; scscp->csb.Disposal = RECEIVE_BUF; scscp->csb.Aux = 0; if ((status=scs_send_msg(&scscp->csb)) != RET_SUCCESS) printf("scsnet: send ack0 failed, status = %d\n", status); /* * free up local resources */ if ((status=scs_unmap_buf(&scscp->csb)) != RET_SUCCESS) printf("scsnet: unmap0 failed, status = %d\n", status); scscp->mchain = 0; scscp->state = SCSNET_BDONE; } else switch( event ) { case CRE_CONN_DONE: { /* An attempt to establish a SCS connection has completed. Process it * according to its completion status. * Add this system to a list of known systems. */ smp_lock(&sys->lk_netsys, LK_RETRY); if( cmsb->status == ADR_SUCCESS ) { /* mark connection open and add to list of known systems */ if (scsnetdebug) printf( "scsnet - Established SCS Connection 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 ] ); if (scsnet_add_sys(in_lnaof(scd->rmt_inaddr)&0xff, sys, cmsb)!=RET_SUCCESS) { printf("scsnet: conn recv, could not allocate resources for connection to host %d\n", in_lnaof(scd->rmt_inaddr)&0xff); /* * send a disconnect */#ifdef notdef /* should not get here but if we do then we need to schedule the * scs_disconnect with ksched or timeout. TODO */ if( scs_disconnect( cmsb ) != RET_SUCCESS ) panic( "SCS_NET - SCS Disconnect Failed\n" ); else if (scsnetdebug) printf( "scsnet - SCS DISCONNECT to %c%c%c%c%c%c%c%c sent\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 ] );#endif scsnet_rem_sys(sys, cmsb); } } else /* * connection attempt failed */ { ISB isb; bzero((caddr_t)&isb, sizeof(ISB)); /* * if remote sysap is busy keep trying */ if (cmsb->status == ADR_BUSY && sys->retries++ < scsnet_maxretries) { Move_scaaddr( cmsb->sysid, isb.next_sysid ); sys->rmt_index = SCSNET_NO_INDEX; if (scsnet_connect(sys, &isb) != RET_SUCCESS) scsnet_rem_sys(sys, cmsb); smp_unlock(&sys->lk_netsys); return; } /* * mark connection closed */ if (scsnetdebug) { printf( "scsnet - Unable to Establish SCS Connection to " ); printf( "%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_CREDIT_AVAIL: break; case CRE_DISCONN_REC: /* A SCS connection has terminated due to virtual path failure. Clean * up and then disconnect the connection. */ case CRE_PATH_FAILURE: { ISB isb; struct _netsystem *netsystem; bzero((caddr_t)&isb, sizeof(ISB)); smp_lock(&sys->lk_netsys, LK_RETRY); if (scsnetdebug) { if (event == CRE_PATH_FAILURE) printf( "Scsnet - Virtual Path Failed to: "); else printf( "Scsnet - Received disconnect from: "); printf( "%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 ] ); } /* * Issue the SCS Disconnect to complete connection termination. */ scsnet_rem_sys(sys, cmsb); /* * this disconnect is ok because I am not changing the state * of an scs connection */ if( scs_disconnect( cmsb ) != RET_SUCCESS ) panic( "SCS_NET - SCS Disconnect Failed\n" ); else if (scsnetdebug) printf( "scsnet - SCS DISCONNECT 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 ] ); /* * try to reconnect just in case there exists an alternate path */ smp_unlock(&sys->lk_netsys); if ((netsystem=alloc_netsys())==SCSNET_NO_SYS) return; /* Check to see if the system is still in the system-wide * configuration database. */ Move_scaaddr( cmsb->sysid, isb.next_sysid ) smp_lock(&netsystem->lk_netsys, LK_RETRY); if (scsnet_connect(netsystem, &isb) != RET_SUCCESS) scsnet_rem_sys(netsystem, cmsb); smp_unlock(&netsystem->lk_netsys); break; } /* * A previously unknown new system exists. * Try to establish a connection to the net sysap on the new system. */ case CRE_NEW_PATH: { ISB isb; register SIB *sib; struct _netsystem *netsystem; bzero((caddr_t)&isb, sizeof(ISB));#ifdef notdef if (Comp_scaaddr(cmsb->sysid, scsnet_local.system.sysid) == 0 ) return; /* only connect to local system for now */#endif if (scsnetdebug) printf("scsnet control: new path\n"); /* * find a free netsystem structure for this connection * and then try to connect. */ if ((netsystem=alloc_netsys())==SCSNET_NO_SYS) { printf( "SCS_NET - can not allocate resources for new system\n"); return; } smp_lock(&netsystem->lk_netsys, LK_RETRY); Move_scaaddr( cmsb->sysid, isb.next_sysid ) if (scsnet_connect(netsystem, &isb) != RET_SUCCESS) { scsnet_rem_sys(netsystem, cmsb); smp_unlock(&netsystem->lk_netsys); return; } sib = &netsystem->sys_info; /* * This entire process is interrupt driven once establishment of the * SCS connection is initiated. */ if (scsnetdebug) printf( "SCS_NET - SCS Discovered %c%c%c%c%c%c%c%c\n", sib->node_name[ 0 ], sib->node_name[ 1 ], sib->node_name[ 2 ], sib->node_name[ 3 ], sib->node_name[ 4 ], sib->node_name[ 5 ], sib->node_name[ 6 ], sib->node_name[ 7 ] ); smp_unlock(&netsystem->lk_netsys); break; } /* Termination of a SCS conn has completed. */ case CRE_DISCONN_DONE: smp_lock(&sys->lk_netsys, LK_RETRY); if (scsnetdebug) printf( "scsnet - Completed Disconnect 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 ] ); smp_unlock(&sys->lk_netsys); break; case CRE_ACCEPT_DONE: /* An attempt to accept a SCS connection has completed. Process it * according to its completion status. * We add this system to a list of known systems if successful. */ smp_lock(&sys->lk_netsys, LK_RETRY); if( cmsb->status == ADR_SUCCESS ) { /* * mark connection open and add to list of known systems */ if (scsnetdebug) printf( "scsnet - accept done 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 ] ); if (scsnet_add_sys(sys->rmt_index, sys, cmsb) == RET_SUCCESS) { if (scsnetdebug) printf("scsnet - accept succeeded\n"); } else { if (scsnetdebug) printf( "scsnet - can not add to list of systems\n"); cmsb->Reason = ADR_NOLISTENER; if((status = scs_disconnect( cmsb ) != RET_SUCCESS) ) mprintf("scsnet control: disconnect failed, status=%x\n", status); scsnet_rem_sys(sys, cmsb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -