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

📄 net_3c509.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 4 页
字号:
  if (len)    MsgLog::printf("cksum: out of data\n");  if (byte_swapped) {    UNSWAP;  }  REDUCE;  ADDCARRY;  return (sum ^ 0xffff);}#elif !defined(INCREDIBLY_SLOW)/* * Checksum routine for Internet Protocol family headers (Portable Version). * * This routine is very heavily used in the network * code and should be modified for each CPU to be as fast as possible. */#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}typedef uint32_t u_int32_t;typedef uint16_t u_int16_t;typedef uint8_t u_int8_t;typedef char int8_t;intin_cksum(register uint16_t *buf, register int len){  register u_int16_t *w;  register int sum = 0;  register int mlen = len;  int byte_swapped = 0;  union {    u_int8_t  c[2];    u_int16_t s;  } s_util;  union {    u_int16_t s[2];    u_int32_t l;  } l_util;  w = buf;	  if (len < mlen)    mlen = len;  len -= mlen;  /*   * Force to even boundary.   */  if ((1 & (long) w) && (mlen > 0)) {    REDUCE;    sum <<= 8;    s_util.c[0] = *(u_int8_t *)w;    w = (u_int16_t *)((int8_t *)w + 1);    mlen--;    byte_swapped = 1;  }  /*   * Unroll the loop to make overhead from   * branches &c small.   */  while ((mlen -= 32) >= 0) {    sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];    sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];    sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];    sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];    w += 16;  }  mlen += 32;  while ((mlen -= 8) >= 0) {    sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];    w += 4;  }  mlen += 8;  if (mlen == 0 && byte_swapped == 0)    goto done;    REDUCE;  while ((mlen -= 2) >= 0) {    sum += *w++;  }  if (byte_swapped) {    REDUCE;    sum <<= 8;    byte_swapped = 0;    if (mlen == -1) {      s_util.c[1] = *(u_int8_t *)w;      sum += s_util.s;      mlen = 0;    } else      mlen = -1;  } else if (mlen == -1)    s_util.c[0] = *(u_int8_t *)w;done:  if (len)    MsgLog::printf("cksum: out of data\n");  if (mlen == -1) {    /* The last mbuf has odd # of bytes. Follow the       standard (the odd byte may be shifted left by 8 bits       or not as determined by endian-ness of the machine) */    s_util.c[1] = 0;    sum += s_util.s;  }  REDUCE;  return (~sum & 0xffff);}#elseuint16_tin_cksum(uint16_t *buf, int len){  uint32_t cksum=0;  if ((u_long)buf & 0x01) {    cksum=(*(u_char *)buf)<<8;    buf=(uint16_t *)((char *)buf+1);    len--;  }  while (len>1) {    cksum+=*buf++;    if (cksum & 0x10000)      cksum=(cksum & 0xFFFF)+1;    len-=2;  }  if (len) {    cksum+=*(u_char *)buf;    if (cksum & 0x10000)      cksum=(cksum & 0xFFFF)+1;  }  return ~cksum;}#endif#define	ETHERTYPE_IP		0x0800	/* IP protocol */#define	ICMP_ECHOREPLY		0		/* echo reply */#define	ICMP_ECHO		8		/* echo service */#define	IPPROTO_ICMP		1		/* control message protocol */#define LEN_ICMP_HDR		16#define LEN_ICMP_DATA		48#define LEN_ICMP		(LEN_ICMP_HDR+LEN_ICMP_DATA)#define LEN_IP			(sizeof(struct ip)+LEN_ICMP)#define	ETHER_ADDR_LEN	6struct ether_addr {	uint8_t ether_addr_octet[6];};struct	ether_header {	uint8_t  ether_dhost[ETHER_ADDR_LEN];	uint8_t  ether_shost[ETHER_ADDR_LEN];	uint16_t ether_type;};struct in_addr {	Word s_addr;};struct ip {#if BYTE_ORDER == LITTLE_ENDIAN	uint8_t  ip_hl:4,		/* header length */		  ip_v:4;		/* version */#endif#if BYTE_ORDER == BIG_ENDIAN	uint8_t  ip_v:4,		/* version */		  ip_hl:4;		/* header length */#endif	uint8_t  ip_tos;		/* type of service */	short	  ip_len;		/* total length */	uint16_t ip_id;		/* identification */	short	  ip_off;		/* fragment offset field */#define	IP_DF 0x4000			/* dont fragment flag */#define	IP_MF 0x2000			/* more fragments flag */#define	IP_OFFMASK 0x1fff		/* mask for fragmenting bits */	uint8_t  ip_ttl;		/* time to live */	uint8_t  ip_p;			/* protocol */	uint16_t ip_sum;		/* checksum */	struct	  in_addr ip_src, ip_dst; /* source and dest address */};/* * Structure of an icmp header. */typedef short n_short;typedef unsigned int n_time;struct icmp {	uint8_t  icmp_type;		/* type of message, see below */	uint8_t  icmp_code;		/* type sub code */	uint16_t icmp_cksum;		/* ones complement cksum of struct */	union {		uint8_t  ih_pptr;		/* ICMP_PARAMPROB */		struct in_addr ih_gwaddr;	/* ICMP_REDIRECT */		struct ih_idseq {			  n_short icd_id;			  n_short icd_seq;		} ih_idseq;		int   ih_void;		/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */		struct ih_pmtu {			  n_short ipm_void;    			  n_short ipm_nextmtu;		} ih_pmtu;	} icmp_hun;#define	icmp_pptr	  icmp_hun.ih_pptr#define	icmp_gwaddr	  icmp_hun.ih_gwaddr#define	icmp_id		  icmp_hun.ih_idseq.icd_id#define	icmp_seq	  icmp_hun.ih_idseq.icd_seq#define	icmp_void	  icmp_hun.ih_void#define	icmp_pmvoid	  icmp_hun.ih_pmtu.ipm_void#define	icmp_nextmtu	  icmp_hun.ih_pmtu.ipm_nextmtu	union {		struct id_ts {			  n_time its_otime;			  n_time its_rtime;			  n_time its_ttime;		} id_ts;		struct id_ip  {			  struct ip idi_ip;			  /* options and then 64 bits of data */		} id_ip;		unsigned int id_mask;		char	  id_data[1];	} icmp_dun;#define	icmp_otime	  icmp_dun.id_ts.its_otime#define	icmp_rtime	  icmp_dun.id_ts.its_rtime#define	icmp_ttime	  icmp_dun.id_ts.its_ttime#define	icmp_ip		  icmp_dun.id_ip.idi_ip#define	icmp_mask	  icmp_dun.id_mask#define	icmp_data	  icmp_dun.id_data};static uint32_t IpIdNext = 0;boolPingPacket(NetInterface *ni, uint8_t *pPkt, uint32_t len){  struct ether_header *h_ether=(struct ether_header *)pPkt;  struct ip *h_ip=(struct ip *)(pPkt+sizeof(struct ether_header));  struct icmp *h_icmp=(struct icmp *)(((char *)h_ip)+(h_ip->ip_hl<<2));  struct in_addr tmp;  uint16_t the_ether_type = ETHERTYPE_IP;  HTONS(the_ether_type);  if (!(h_ether->ether_type == the_ether_type &&	len>=LEN_IP &&	h_ip->ip_p == IPPROTO_ICMP &&	h_icmp->icmp_type == ICMP_ECHO))    return false;  if (h_ip->ip_ttl == 0)    return false;#if 0  MsgLog::printf("It's icmp echo!\n");#endif    bcopy(h_ether->ether_shost, h_ether->ether_dhost, sizeof(struct ether_addr));  bcopy(ni->info.niAddr, h_ether->ether_shost, sizeof(struct ether_addr));  if (in_cksum((uint16_t *)h_ip, (h_ip->ip_hl<<2)))    return false;#if 0  MsgLog::printf("Cksum OK\n");#endif  tmp=h_ip->ip_dst;  h_ip->ip_dst=h_ip->ip_src;  h_ip->ip_sum=0;  h_ip->ip_src=tmp;  h_ip->ip_ttl = 64;		/* it's a new packet! */  h_ip->ip_id=IpIdNext++;  h_ip->ip_sum=in_cksum((uint16_t *)h_ip, h_ip->ip_hl<<2);  h_icmp->icmp_cksum=0;  h_icmp->icmp_type=ICMP_ECHOREPLY;  h_icmp->icmp_cksum=in_cksum((uint16_t *)h_icmp,			      h_ip->ip_len-(h_ip->ip_hl<<2));  return true;}#endif/* SLEAZY HACK ALERT -- it proves that the x86 caches are not * write-allocate.  The consequence is that the packet comes in from * the I/O port, goes through the store buffer TO MAIN MEMORY, and * promptly gets read back in by the in_cksum routine.  For things the * size of ethernet packets, it is therefore worth forcing them into * the cache. */inline voidIoRdPkt(NetInterface *ni, uint8_t *buf, uint32_t len){  /* Patch up the buffer alignment so we can move the data quickly: */  while ((uint32_t) buf & 3) {    *buf++ = in8(ni->ioAddr + Wn1Rxuint8_tFifo);    len --;  }    ins32(ni->ioAddr + Wn1RxFifo, buf, len >> 2);  buf += (len & ~3u);  len &= 3;  while (len--)    *buf++ = in8(ni->ioAddr + Wn1Rxuint8_tFifo);  /* A complete, good packet has been read.  We do not need to read dribble   * bytes.   */}inline voidIoWrPkt(NetInterface *ni, uint8_t *buf, uint32_t len){  uint32_t totlen = len & 3;    /* Begin sending the packet, but be careful about send buffer   * alignment:   */  while ((uint32_t) buf & 3) {    out8(*buf++, ni->ioAddr + Wn1Txuint8_tFifo);	/* write to low-order byte */    len--;  }  /* sndBufPtr is now word aligned.  Send as many words as we can: */  outs32(ni->ioAddr + Wn1TxFifo, buf, len >> 2);  buf += (len & ~3u);  len &= 3;  while (len--)    out8(*buf++, ni->ioAddr + Wn1Txuint8_tFifo); /* write to low-order byte */  while (totlen & 3) {    out8(0, ni->ioAddr + Wn1Txuint8_tFifo); /* write to low-order byte */    totlen++;  }}static voidSkipBadRxPackets(NetInterface *ni){  /* Check the status to see if the packet is any good -- if not,   * there is really no point waking up the caller.   */    for ( ;; ) {    uint16_t rx_status = in16(ni->ioAddr + Wn1RxStatus);    if (rx_status & RxsIncomplete)      return;    if (rx_status & RxsError) {      bool goodPacket = false;            /* Packet reception error -- update the error statistics: */      uint16_t whichErr = rx_status & RxsErrType;#ifdef VERBOSE      MsgLog::printf("Rx: dropped packet (");#endif      switch (whichErr) {      case RxsOverrun:	ni->stats.rxOverrun++;#ifdef VERBOSE	MsgLog::printf("overrun");#endif	break;      case RxsOversize:	ni->stats.rxLengthErrors++;#ifdef VERBOSE	MsgLog::printf("oversize");#endif	break;      case RxsDribble:	ni->stats.rxFrameErrors++;	goodPacket = true;	/* packet should be processed! */#ifdef VERBOSE	MsgLog::printf("dribble");#endif	break;      case RxsRunt:	ni->stats.rxLengthErrors++;#ifdef VERBOSE	MsgLog::printf("runt");#endif	break;      case RxsAlignment:	ni->stats.rxFrameErrors++;#ifdef VERBOSE	MsgLog::printf("align");#endif	break;      case RxsCRC:	ni->stats.rxCrcErrors++;#ifdef VERBOSE	MsgLog::printf("crc");#endif	break;      }      if (goodPacket)	break;      ni->stats.rxDropped++;      #ifdef VERBOSE      MsgLog::printf(") dropped pkt 0x%04x err=%d\n", rx_status);#endif      OutCmd(ni, RxDiscard, true);    }    else      break;  }}/* RxPacket logic: *  *   Skip past any bad packets in the FIFO. *   If packets remain *      mask out packet receive interrupts *      wake up readers, if any *   ack the interrupt */static voidRxPacket(NetInterface *ni){#ifdef VERBOSE  MsgLog::printf("Got rd pkt intr on %s\n", ni->info.name);#endif  SkipBadRxPackets(ni);  uint16_t rx_status = in16(ni->ioAddr + Wn1RxStatus);  /* We have skipped past all the bad packets.  See if any good   * packets remain:   */    if ( (rx_status & RxsIncomplete) == 0 ) {    /* Disable receive completion interrupts */    ni->curInts &= ~RxComplete;    /* MsgLog::printf("Disable RxComplete interrupt\n"); */    OutCmd(ni, SetIntrMask | ni->curInts);    ni->rdQ.WakeAll(0, true);  }  /* Finally, ack this interrupt: */  OutCmd(ni, AckIntr | RxComplete | RxEarly);}static inline voidClearTxStatusStack(NetInterface *ni){  uint16_t tx_status = 0;  int i = 4;  while (--i > 0  && (tx_status = in8(ni->ioAddr + Wn1TxStatus)) > 0) {    /* This generates printfs on collisions, which happens with acks.     * MsgLog::printf("3c509: tx_status = 0x%08x\n", tx_status);     */    if (tx_status & (TxsJabber | TxsUnderrun | TxsCollisions))      ni->stats.txAbort++;    if (tx_status & (TxsJabber|TxsUnderrun))      OutCmd(ni, TxReset, true);    if (tx_status & (TxsJabber|TxsUnderrun|TxsCollisions|TxsStatusOverflow))      OutCmd(ni, TxEnable);    /* Pop the status stack. */    out8(0x00, ni->ioAddr + Wn1TxStatus);   }}static voidWritePacket(NetInterface * ni, Invocation& inv){  uint64_t dw = rdtsc();    ClearTxStatusStack(ni);  /* See if the TX Fifo has room for the outbound packet: */  uint16_t txFree = in16(ni->ioAddr + Wn1TxFree);#if 0  MsgLog::printf("inv.entry.len=%d\n", inv.entry.len);#endif  if (inv.entry.len < MIN_ENET_PACKET_SZ ||      inv.entry.len > MAX_ENET_PACKET_SZ) {    /* input buffer not aligned properly. */    inv.exit.code = RC_RequestError;    return;

⌨️ 快捷键说明

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