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

📄 ethernet.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
  }  for(i=0;i<state->copy.numSndEntries;i++) {    if( regs->sndEntries[i].flag != OS_OWNED || 	!state->sndAcks[i] )       return;  }  /* clear the interrupt bit */  if (state->intrPosted) {    /* clear the interrupt line */    SIM_DEBUG(('e', "ETHER-trace: %d ClearSlot\n", state->ethernum));     if (state->int_f) state->int_f(state->ethernum, 0);      state->intrPosted = 0; /* just like EWOULDBLOCK case */  }}static void SimetherRaiseSlot(SimetherState *state, char* cause){  if (!state->intrPosted) {    SIM_DEBUG(('e', "ETHER-trace: %d RaiseSlot (%s)\n", state->ethernum, cause));    if (state->int_f) state->int_f(state->ethernum, 1);    state->intrPosted = 1;  } else {    SIM_DEBUG(('e', "ETHER-trace: %d RaiseSlot (%s) already posted\n",	     state->ethernum, cause));  }}static void SimetherSendOver(SimetherState *state, int index) {   int i,lastChunk;   /* release send chunks */   i = state->copy.sndEntries[index].firstChunk;   lastChunk = state->copy.sndEntries[index].lastChunk;   while( 1 ) {       state->chunkOwner[i] = OS_OWNED;      if( i==lastChunk ) break;      i++;      if( i >= state->copy.numSndChunks )          i -= state->copy.numSndChunks ;   }   /* Packet fully sent */   state->copy.sndEntries[index].flag = OS_OWNED;    /* Set done flag immediately. should be base mode only */   SimetherRaiseSlot( state, "send" );}#ifdef VCS_FAKE/* Types of packets */#define VCS_FAKE_REQUEST 0#define VCS_FAKE_REPLY 1#define VCS_FAKE_ERROR 2/* Markers, in case we get lost in the packet */#define VCS_FAKE_MARKER "01xy"#define VCS_FAKE_SMARKER "01xy"#define VCS_FAKE_RMARKER "02xy"#define VCS_FAKE_EMARKER "03xy"#define VCS_FAKE_MSIZE 4#define VCS_FAKE_OFF 0 #define VCS_FAKE_SAVE 1#define VCS_FAKE_MATCH 2/* These two defines are reaching into the structure   below. So if that changes (Fat chance!) we must change   the defines too. They take a ethernet packet and return   the IP ID field or the IP Checksum field*//* #define VCS_FAKE_IPID(x) (*((u_short *)(((u_char *)(x)) + 18))) */#define VCS_FAKE_IPID(x) (((struct ip *)(((u_char *)(x)) + sizeof(struct ether_header)))->ip_id)/* #define VCS_FAKE_IPCKSUM(x) (*((u_short *)(((u_char *)(x)) + 24))) */#define VCS_FAKE_IPCKSUM(x) (((struct ip *)(((u_char *)(x)) + sizeof(struct ether_header)))->ip_sum)/* structure for storing the previously traced packets for comparison */#define VCS_FAKE_MAX_BUF 40	/* maximum number of captured packets */struct ipbuf_t {  int len;  int replyLen;  int used;  char *request;  char *reply;} ipbuf[VCS_FAKE_MAX_BUF];static int ipbufid = 0;static int vfd;		/* file descriptor for storing or matching */static int efd;static char dumpbuf[1600];	/* need this for copying data at various points */int VcsFakeType = 0;	 /* Type of operation to be done, nothing, save or match */char *VcsFakeFilename = NULL; /* filename for writing or reading packets *//*    If we are using VCSFAKESAVE, just open the file to save the packets.   If VCSFAKEMATCH, then read in the packets from the file and store them away.*/voidVcsFakeInit(void){  u_long marker, prevmarker = -1, dbuflen;  struct ipbuf_t *ptr, *replyPtr;  if(VcsFakeType == VCS_FAKE_OFF) {    /* default behavior, just return */    return;  }  /* if in Save mode, just open the file and return */  if(VcsFakeType == VCS_FAKE_SAVE) {    if((vfd = open(VcsFakeFilename, O_CREAT|O_RDWR|O_TRUNC, 0777)) == NULL) {      CPUError("Error: Could not open dump file %s\n", VcsFakeFilename);      vfd = -1;    }    return;  }  if(VcsFakeType == VCS_FAKE_MATCH) {    if((vfd = open(VcsFakeFilename, O_RDONLY, 0777)) == NULL) {      CPUError("Error: Could not open dump file %s\n", VcsFakeFilename);      vfd = -1;      return;    }        CPUWarning("Opened VcsFake dumpfile\n");    while(read(vfd, &marker, VCS_FAKE_MSIZE) == VCS_FAKE_MSIZE) {      if(!bcmp(&marker, VCS_FAKE_SMARKER, VCS_FAKE_MSIZE)) {	marker = VCS_FAKE_REQUEST;      } else if(!bcmp(&marker, VCS_FAKE_RMARKER, VCS_FAKE_MSIZE)) {	marker = VCS_FAKE_REPLY;      } else {	CPUError("VcsFakeEther: Unknown marker");	marker = -1;	return;      }      if(marker == VCS_FAKE_REQUEST) {	ptr = &(ipbuf[ipbufid++]);	ptr->used = 0;	read(vfd, &(ptr->len), sizeof(ptr->len));	ptr->request = (char *)ZMALLOC(ptr->len,"etherReq");	read(vfd, ptr->request, ptr->len);	VCS_FAKE_IPID(ptr->request) = 0;	VCS_FAKE_IPCKSUM(ptr->request) = 0;	CPUWarning("REQ (%d): SRC = 0x%x DST = 0x%x\n", ptr->len, 		    *((int *)&(ptr->request[26])), *((int *)&(ptr->request[30])));	ptr->reply = 0;	ptr->replyLen = 0;      } else if(marker == VCS_FAKE_REPLY) {	if(prevmarker == VCS_FAKE_REQUEST) {	  read(vfd, &(ptr->replyLen), sizeof(ptr->replyLen));	  ptr->reply = (char *)ZMALLOC(ptr->replyLen,"VCS");	  read(vfd, ptr->reply, ptr->replyLen);	  CPUWarning("REP (%d): SRC = 0x%x DST = 0x%x\n", ptr->replyLen, 		    *((int *)&(ptr->reply[26])), *((int *)&(ptr->reply[30])));	} else {	  /* Reply without a matching request */	  read(vfd, &(dbuflen), sizeof(u_long));	  read(vfd, dumpbuf, dbuflen);	  CPUWarning("REP (Unsolicited)(%d): SRC = 0x%x DST = 0x%x\n", ptr->replyLen, 		    *((int *)&(dumpbuf[26])), *((int *)&(dumpbuf[30])));	}      }      prevmarker = marker;    }    CPUWarning("VcsFake init done\n");  }}#endif/******************************************************************** * SimetherSendPacket * Returns 0 if the interrupt was posted, 1 if the transmission is * still in flight ********************************************************************/static int SimetherSendPacket(SimetherState *state, int index ) {#ifndef i386   int err, i, j, lastChunk;   struct msghdr  msg;   int length = 0;   int cpuNum = FIRST_CPU(state->machine);    /* The following two cannot be on the stack since in base    * mode we get to this point while running on the kernel stack.    * They take waayyy to much memory and cause a TLB miss    * while in the back door.    *    * Making them static appears to be safe because each cpu process    * gets its own copy.  In non-base-mode runs we are safe because    * this code is non-reentrant.    */   static struct iovec iovec[ETHER_MAX_SND_CHUNKS+1];   static char extraBuf[ETHERMIN + sizeof(struct ether_header)];   j = state->copy.sndEntries[index].firstChunk;   lastChunk = state->copy.sndEntries[index].lastChunk;   for(i=0;i<ETHER_MAX_SND_CHUNKS+1; i ++) {       ASSERT(IS_VALID_PA(M_FROM_CPU(cpuNum), state->copy.sndChunks[j].pAddr));      iovec[i].iov_base = PHYS_TO_MEMADDR(M_FROM_CPU(cpuNum),                                          state->copy.sndChunks[j].pAddr);      iovec[i].iov_len  = state->copy.sndChunks[j].len;      length += state->copy.sndChunks[j].len;      if( j == lastChunk ) {          i++;         break;      }      j++;      if( j >= state->copy.numSndChunks  )          j -= state->copy.numSndChunks ;   }    ASSERT( i <=state->copy.numSndChunks );   if (length < ETHERMIN + sizeof(struct ether_header)) {      bzero(extraBuf,sizeof(extraBuf));      iovec[i].iov_base = extraBuf;      iovec[i].iov_len = ETHERMIN + sizeof(struct ether_header) - length;      length =  ETHERMIN + sizeof(struct ether_header);      i++;   }   {      int j;      SIM_DEBUG_DETAIL(('i', "ETHER-trans", cpuNum, "controller=%d ",                        state->ethernum));      for(j=0; j<i; j++) {         CPUPrint(" %x/%i",  iovec[j].iov_base, iovec[j].iov_len);      }      CPUPrint("\n");   }      msg.msg_name = (caddr_t) &state->toaddr;   msg.msg_namelen = state->toaddrlen;   msg.msg_iov = iovec;   msg.msg_iovlen = i;   msg.msg_accrights = (caddr_t) 0;   msg.msg_accrightslen = 0;   if( ClusterSendPacket(cpuNum,iovec, msg.msg_iovlen) ||       LocalClusterSendPacket(cpuNum, state->ethernum,                              iovec, msg.msg_iovlen) ) {      /* packet sent through the cluster */      /* no timing model for now */      SimetherSendOver(state,index);      return 0; /* override the copy */   } else { #ifdef VCS_FAKE     if(VcsFakeType == VCS_FAKE_MATCH) {       int i, j = 0;       struct ipbuf_t *ptr;       struct sockaddr_in myaddr;        int myaddrlen, matchNoReply = -1;       /* Since we have to zero out the checksum and id, 	  make a copy in a single buffer */       for(i=0;i<msg.msg_iovlen;i++) { 	 bcopy(iovec[i].iov_base, &(dumpbuf[j]), iovec[i].iov_len);	 j += iovec[i].iov_len;       }       /* zero the IP id and check sum fields of the packet */       VCS_FAKE_IPID(dumpbuf) = 0;       VCS_FAKE_IPCKSUM(dumpbuf) = 0;       for(i=0;i<ipbufid;i++) {	 ptr = &(ipbuf[i]);	 if(!(ptr->used) && (ptr->len == length) &&	    (bcmp(ptr->request, dumpbuf, length) == 0)) {	   /* found a match */	   iovec[0].iov_base = ptr->reply;	   iovec[0].iov_len = ptr->replyLen;	   myaddrlen = sizeof(struct sockaddr_in);	   getsockname(state->fd, &myaddr, &myaddrlen);	   msg.msg_name = (caddr_t) &myaddr;	   msg.msg_namelen = myaddrlen;	   msg.msg_iov = iovec;	   msg.msg_iovlen = 1;	   ptr->used = 1;	   break;	 }       }       err = 0;       if(i == ipbufid) {	 /* did not find a match */	 CPUError("VcsFakeEther: No match (%d) SRC = 0x%x DST = 0x%x\n", length, 		    *((int *)&(dumpbuf[26])), *((int *)&(dumpbuf[30])));	 /*	   write(vfd, VCS_EMARKER, VCS_MSIZE);	   write(vfd, &length, sizeof(length));	   write(vfd, devPtr->req.buffer, length);	   */	 err = -1;       } else if(iovec[0].iov_len) {	   /* found a match with a reply, send the message. It is	      has been switched previously to be the reply, addressed to	      me. 	      */	   CPUWarning("VCS_FAKE: Match(%d) SRC = 0x%x DST = 0x%x\n", ptr->len, 		       *((int *)&(ptr->request[26])), *((int *)&(ptr->request[30])));	   /*	   if (sendmsg(state->fd, &msg, 0) < 0) {	     CPUError("simetherOutput: sendmsg");	     err = -1;	   }	   */	   SimetherSendOver(state,index);	   if(SimetherReceivePacket(state->ethernum, dumpbuf, length) < 0) {	     CPUError("simetherOutput: sendmsg");	     err = -1;	   }	   return(0);       } else {	 /* Found a match, but there was no associated reply. Do nothing */	 CPUWarning("VCS_FAKE: Match No reply (%d) SRC = 0x%x DST = 0x%x\n", 		    ptr->len, *((int *)&(ptr->request[26])), *((int *)&(ptr->request[30])));       }       SimetherSendOver(state,index);       return 0;      }#endif      if (sendmsg(state->fd, &msg, 0) < 0) {         perror("simetherOutput: sendmsg");         err = -1;      } else {#ifdef VCS_FAKE	if(VcsFakeType == VCS_FAKE_SAVE) {	  /* Send was successful, save the packet */	  int i;	  	  write(vfd, VCS_FAKE_SMARKER, VCS_FAKE_MSIZE);	  write(vfd, &length, sizeof(length));	  for(i=0;i<msg.msg_iovlen;i++) { 	    write(vfd, iovec[i].iov_base, iovec[i].iov_len);	  }	}#endif         err = 0;      }      SimetherSendOver(state,index);      return err; /* override the copy */   }   /* return 1;- make compiler happy */  /* allow the copy */#else   Sim_Warning("Uh oh... SimetherSendPacked called\n");  return 1;#endif}/*********************************************************************** * SimetherReceivePacket. * * Called either in interrupt dispatcher (simcp0 poll) when using UDP * to carry or in the normal context of the CPU simulator if we bypass * UPD. * * !!! Never install a callback from when using UDP * ************************************************************************/intSimetherReceivePacket(int iface_num, char *packet, int packetSize){ #ifndef i386   SimetherState *state = simetherState +iface_num;   int size = 0;   struct sockaddr_in fromaddr;   int  fromaddrlen;   char buffer[SIMETHER_MAX_TRANSFER_SIZE];   int cpuNum = FIRST_CPU(state->machine);   ASSERT( iface_num < ETHER_MAX_CONTROLLERS);   /*     * Choose a free receiving buffer or drop the packet     * in this model, we do not drop packets on the floor, but    * delay the processing of the UDP packets.    */       if( !packet ) {      ASSERT( !disableEthernet );      /* the packet comes from the UDP port */              if( state->copy.rcvEntries[state->rcvPtr].flag == OS_OWNED ) {         /*           * wait for the kernel to process          */         SIM_DEBUG(('e', "ETHER-receive: %d Recieve buffers full \n", state->ethernum));         LogEntry("ETHER",cpuNum,"controller=%d receive buffers full\n",                  state->ethernum);#ifdef sgi         sginap( 1 ); /* free up CPU */#endif#ifdef sun	sleep(1);#endif         return -1;      }              fromaddrlen = sizeof(fromaddr);      size = recvfrom(state->fd, buffer,SIMETHER_MAX_TRANSFER_SIZE,                      0, (struct sockaddr *) &fromaddr, &fromaddrlen);      if (size < 0) {         if (errno != EWOULDBLOCK)            perror("simetherRecvProcess:recvfrom");      } else if (size < sizeof(struct ether_header)) {         Sim_Warning("simetherRecvProcess: Ethernet packet too small (%d)\n",                     size);      }      ASSERT( state->copy.rcvEntries[state->rcvPtr].flag == CONTROLLER_OWNED);      packet = buffer;      packetSize = size;#ifdef VCS_FAKE      if(VcsFakeType == VCS_FAKE_SAVE) {	/* save the received packet to the file */	write(vfd, VCS_FAKE_RMARKER, VCS_FAKE_MSIZE);	write(vfd, &size, sizeof(size));	write(vfd, buffer, size);      }#endif      /*DMA the contents of the packet */   } else {       if( state->copy.rcvEntries[state->rcvPtr].flag == OS_OWNED ) {         CPUWarning("CLUSTER-packet: drop packet \n");         return -1;      }      ASSERT( packetSize );   } 

⌨️ 快捷键说明

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