コード例 #1
0
ファイル: ethernetif.c プロジェクト: samkrew/nxp-lpc
err_t eth_input(struct pbuf *p, struct netif *inp)
{
	struct eth_hdr *ethhdr;

	if(p != RT_NULL)
	{
#ifdef LINK_STATS
		LINK_STATS_INC(link.recv);
#endif /* LINK_STATS */

		ethhdr = p->payload;

		switch(htons(ethhdr->type))
		{
		case ETHTYPE_IP:
			etharp_ip_input(inp, p);
			pbuf_header(p, -(s16_t) sizeof(struct eth_hdr));
			tcpip_input(p, inp);
			break;

		case ETHTYPE_ARP:
			etharp_arp_input(inp, (struct eth_addr *)inp->hwaddr, p);
			break;

		default:
			pbuf_free(p);
			p = RT_NULL;
			break;
		}
	}

	return ERR_OK;
}
コード例 #2
0
static void ethernetif_input( void *pParams )
{
    struct netif *netif;
    struct ethernetif *ethernetif;
    struct eth_hdr *ethhdr;
    struct pbuf *p;

	netif = (struct netif*) pParams;
	ethernetif = netif->state;
	
	for( ;; )
	{
		do
		{
			// move received packet into a new pbuf
			p = low_level_input( netif );
			
			if ( p == NULL )
			{
				// No packet could be read.  Wait for an interrupt to tell us
				// there is more data available.
				xSemaphoreTake( s_xSemaphore, enc28j60BLOCK_TIME_WAITING_FOR_INPUT );
			}
		
		} while( p == NULL );

		// points to packet payload, which starts with an Ethernet header 
		ethhdr = p->payload;

		switch ( htons( ethhdr->type ) ) {
			
	        //  IP or ARP packet?
		    case ETHTYPE_IP:
	
			    // full packet send to tcpip_thread to process 

			    if ( netif->input( p, netif ) != ERR_OK)
			    {
				    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
				    pbuf_free( p );
				    p = NULL;
			    }
			    break;
				
		    case ETHTYPE_ARP:
				
#if ETHARP_TRUST_IP_MAC
			    etharp_ip_input( netif, p );
#endif
				
			    etharp_arp_input( netif, ethernetif->ethaddr, p );
			    break;
		
		    default:
			    pbuf_free( p );
			    p = NULL;
		    	break;
		}
	}
}
コード例 #3
0
ファイル: nifce_driver.c プロジェクト: webom2008/BF512.VDK
/*##########################################################################
*
* Sends an incoming Ethernet frame up the stack to a function that will
* understand it (or just drops the frame).
*
*#########################################################################*/
static void
eth_input(struct pbuf* p, struct netif* netif)
{
  // Ethernet protocol layer
  struct eth_hdr* ethhdr;
  struct pbuf* q = NULL;

  ethhdr = p->payload;

  switch (htons(ethhdr->type))
  {
      case ETHTYPE_IP:
      etharp_ip_input(netif, p);
      pbuf_header(p, -(s16_t)sizeof(struct eth_hdr));
      netif->input(p, netif);
      break;
      case ETHTYPE_ARP:
      etharp_arp_input(netif, (struct eth_addr*)&(netif->hwaddr[0]), p);
      break;
      default:
      pbuf_free(p);
      break;
  }

  if (q != NULL)
  {
    low_level_output(netif, q);
    pbuf_free(q);
  }
}
コード例 #4
0
ファイル: fec.c プロジェクト: alexrayne/freemodbus
void
eth_input( struct netif *netif, struct pbuf *p )
{
    struct eth_hdr *eth_hdr = p->payload;

    LWIP_ASSERT( "eth_input: p != NULL ", p != NULL );

    switch ( htons( eth_hdr->type ) )
    {
    case ETHTYPE_IP:
        /* Pass to ARP layer. */
        etharp_ip_input( netif, p );

        /* Skip Ethernet header. */
        pbuf_header( p, ( s16_t ) - sizeof( struct eth_hdr ) );

        /* Pass to network layer. */
        netif->input( p, netif );
        break;

    case ETHTYPE_ARP:
        /* Pass to ARP layer. */
        etharp_arp_input( netif, ( struct eth_addr * )netif->hwaddr, p );
        break;

    default:
        pbuf_free( p );
        break;
    }
}
コード例 #5
0
ファイル: ethernetif.c プロジェクト: Dzenik/FreeRTOS_TEST
static void ethernetif_input( void * pvParameters )
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;

	for( ;; )
	{
		do
		{
			ethernetif = s_pxNetIf->state;
			
			/* move received packet into a new pbuf */
			p = low_level_input( s_pxNetIf );
			
			if( p == NULL )
			{
				/* No packet could be read.  Wait a for an interrupt to tell us
				there is more data available. */
				vEMACWaitForInput();
			}
		
		} while( p == NULL );

		/* points to packet payload, which starts with an Ethernet header */
		ethhdr = p->payload;

		#if LINK_STATS
			lwip_stats.link.recv++;
		#endif /* LINK_STATS */

		ethhdr = p->payload;

		switch (htons(ethhdr->type))
		{
			/* IP packet? */
			case ETHTYPE_IP:
				/* update ARP table */
				etharp_ip_input(s_pxNetIf, p);
				/* skip Ethernet header */
				pbuf_header(p, (s16_t)-sizeof(struct eth_hdr));
				/* pass to network layer */
				s_pxNetIf->input(p, s_pxNetIf);
				break;
		
			case ETHTYPE_ARP:
				  /* pass p to ARP module  */
				  etharp_arp_input(s_pxNetIf, ethernetif->ethaddr, p);
				  break;
				
			default:
				  pbuf_free(p);
				  p = NULL;
				  break;
		}
	}
}
コード例 #6
0
ファイル: ps2ip.c プロジェクト: AzagraMac/PS2_SDK
static void
InputCB(void* pvArg)
{

	//TCPIP input callback. This function has been registered by ps2ip_input and will be invoked in the context of the
	//tcpip-thread. Hence, only synchronization for the message-queue is required.

	InputMSG*	pMSG=(InputMSG*)pvArg;
	PBuf*			pInput=pMSG->pInput;
	NetIF*		pNetIF=pMSG->pNetIF;
	int			iFlags;

	//Remove the first message in the message-queue. BTW: pMSG == &aMSGs[u8FirstMSG].

	CpuSuspendIntr(&iFlags);
	u8FirstMSG=GetNextMSGQueueIndex(u8FirstMSG);
	CpuResumeIntr(iFlags);

	//What kind of package is it?

	switch	(htons(((struct eth_hdr*)(pInput->payload))->type))
	{
	case	ETHTYPE_IP:

		//IP-packet. Update ARP table, obtain first queued packet.

		etharp_ip_input(pNetIF,pInput);

		//Skip Ethernet header.

		pbuf_header(pInput,-14);

		//Pass to network layer.

		ip_input(pInput,pNetIF);

		//Send out the ARP reply or ARP queued packet.

		SendARPReply(pNetIF,NULL);
		break;
	case	ETHTYPE_ARP:

		//ARP-packet. Pass pInput to ARP module, get ARP reply or ARP queued packet.

		etharp_arp_input(pNetIF,(struct eth_addr*)&pNetIF->hwaddr,pInput);

		//Send out the ARP reply or ARP queued packet.

		SendARPReply(pNetIF,NULL);
		break;
	default:

		//Unsupported ethernet packet-type. Free pInput.

		pbuf_free(pInput);
	}
}
コード例 #7
0
static void
ethernetif_input(void *pReserved)
{
    struct ethernetif		*__pstEthernetif;
    struct pbuf				*__pstPbuf;
    struct eth_hdr			*__pstEthhdr;
    struct netif			*__pstNetif;

    /*	传进来的网卡资料	*/
    __pstNetif = (struct netif*)pReserved;

    while(1)
    {
        __pstEthernetif = (struct ethernetif*)__pstNetif->state;
        //Uart_Printf("  into ethernetif_inputTask  ");
        //* 从EMAC循环读取数据
        do {
            __pstPbuf = low_level_input(__pstNetif);
            if(__pstPbuf == NULL)
                ///*采用查询的方式工作,一直在查看底层的网卡是否有新的数据过来了
                OSAPISemWait(EthernetInput, 300);
        } while(__pstPbuf == NULL);
        //*如果底层有数据过来了,那么进入相应的处理阶段
        __pstEthhdr = __pstPbuf->payload;
        //*查看是那种数据包,然后再将其向上传送
        switch(htons(__pstEthhdr->type))
        {
        case ETHTYPE_IP:
            //* 更新ARP表
            etharp_ip_input(__pstNetif, __pstPbuf);
            //* 跳过以太网头部字段
            pbuf_header(__pstPbuf, -sizeof(struct eth_hdr) );

            //* 传递到网络层
            __pstNetif->input(__pstPbuf, __pstNetif);

            break;

        case ETHTYPE_ARP:
            //* 将__pstPbuf传递到ARP模块
            etharp_arp_input(__pstNetif, __pstEthernetif->ethaddr, __pstPbuf);
            break;

        default:
            pbuf_free(__pstPbuf);
            __pstPbuf = NULL;
            break;
        }
    }
}
コード例 #8
0
ファイル: ethernetif.c プロジェクト: MetaEngine/lwip-win32
static void ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;
  
  ethernetif = netif->state;
  
  /* move received packet into a new pbuf */
  while (TRUE)
  {
    p = low_level_input(netif);
    if (p == NULL) 
      continue;
    
    ethhdr = p->payload;
    switch (htons(ethhdr->type)) {
    case ETHTYPE_IP:
      /* update ARP table */
      etharp_ip_input(netif, p);
      /* skip Ethernet header */
      //pbuf_header(p, -(14+ETH_PAD_SIZE));
      /* pass to network layer */
      netif->input(p, netif);
      break;
    case ETHTYPE_ARP:
      etharp_arp_input(netif, ethernetif->ethaddr, p);
      break;
#if PPPOE_SUPPORT
      /* PPPoE packet? */
    case ETHTYPE_PPPOEDISC:
    case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
      /* full packet send to tcpip_thread to process */
      if (netif->input(p, netif)!=ERR_OK)
      { 
        LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
        pbuf_free(p);
        p = NULL;
      }
      break;
    default:
      pbuf_free(p);
      p = NULL;
      break;
    }
  }
}
コード例 #9
0
ファイル: net.c プロジェクト: 0xBADCA7/lk
static void
ethernetif_input(struct netif *netif)
{
    struct ethernetif *ethernetif;
    struct eth_hdr *ethhdr;
    struct pbuf *p;

    ethernetif = netif->state;

    /* move received packet into a new pbuf */
    p = low_level_input(netif);
    /* no packet could be read, silently ignore this */
    if (p == NULL) return;
    /* points to packet payload, which starts with an Ethernet header */
    ethhdr = p->payload;

#if LINK_STATS
    lwip_stats.link.recv++;
#endif /* LINK_STATS */

    ethhdr = p->payload;

//  dprintf("ethernetif_input: type 0x%x\n", htons(ethhdr->type));

    switch (htons(ethhdr->type)) {
            /* IP packet? */
        case ETHTYPE_IP:
            /* update ARP table */
            etharp_ip_input(netif, p);
            /* skip Ethernet header */
            pbuf_header(p, -sizeof(struct eth_hdr));
            /* pass to network layer */
            netif->input(p, netif);
            break;

        case ETHTYPE_ARP:
            /* pass p to ARP module  */
            etharp_arp_input(netif, ethernetif->ethaddr, p);
            break;
        default:
            pbuf_free(p);
            p = NULL;
            break;
    }
}
コード例 #10
0
ファイル: enc28j60if.c プロジェクト: KrystianD/kdhome
/**
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 *
 * @param netif the lwip network interface structure for this ethernetif
 */
void enc28j60_if_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;

  ethernetif = netif->state;

  /* move received packet into a new pbuf */
  p = low_level_input(netif);
  /* no packet could be read, silently ignore this */
  if (p == NULL) return;
  /* points to packet payload, which starts with an Ethernet header */
  ethhdr = p->payload;

  switch(htons(ethhdr->type)) {
  /* IP packet? */
  case ETHTYPE_IP:
#if 0
/* CSi disabled ARP table update on ingress IP packets.
   This seems to work but needs thorough testing. */
    /* update ARP table */
    etharp_ip_input(netif, p);
#endif
    /* skip Ethernet header */
    pbuf_header(p, -(s16_t)sizeof(struct eth_hdr));
    LWIP_DEBUGF(NETIF_DEBUG,("enc28j60_if_input: passing packet up to IP\n"));
    // pbuf_free(p);
    /* pass to network layer */
    netif->input(p, netif);
    break;
  /* ARP packet? */
  case ETHTYPE_ARP:
    /* pass p to ARP module */
    ethernet_input(p, netif);
    break;
  /* unsupported Ethernet packet type */
  default:
    /* free pbuf */
    pbuf_free(p);
    p = NULL;
    break;
  }
}
コード例 #11
0
ファイル: mintapif.c プロジェクト: iwanbk/ethserbridge
/*-----------------------------------------------------------------------------------*/
static void
mintapif_input(struct netif *netif)
{
  struct mintapif *mintapif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;


  mintapif = netif->state;
  
  p = low_level_input(netif);

  if (p != NULL) {

#if LINK_STATS
    lwip_stats.link.recv++;
#endif /* LINK_STATS */

    ethhdr = p->payload;

    switch (htons(ethhdr->type)) {
    case ETHTYPE_IP:
#if 0
/* CSi disabled ARP table update on ingress IP packets.
   This seems to work but needs thorough testing. */
      etharp_ip_input(netif, p);
#endif
      pbuf_header(p, -14);
      netif->input(p, netif);
      break;
    case ETHTYPE_ARP:
      etharp_arp_input(netif, mintapif->ethaddr, p);
      break;
    default:
      LWIP_ASSERT("p != NULL", p != NULL);
      pbuf_free(p);
      break;
    }
  }
}
コード例 #12
0
ファイル: etherif.cpp プロジェクト: ShotaroTsuji/mona
/*-----------------------------------------------------------------------------------*/
static bool etherif_input(struct netif *netif)
{
    struct etherif* etherif = (struct etherif*)netif->state;
    struct eth_hdr *ethhdr;
    struct pbuf *p;
    p = low_level_input(netif);
    if (p != NULL) {
#if LINK_STATS
        lwip_stats.link.recv++;
#endif /* LINK_STATS */

        ethhdr = (struct eth_hdr*)p->payload;

        switch (htons(ethhdr->type)) {
        case ETHTYPE_IP:
#if 0
/* CSi disabled ARP table update on ingress IP packets.
   This seems to work but needs thorough testing. */
            etharp_ip_input(netif, p);
#endif
            pbuf_header(p, -14);
            netif->input(p, netif);
            break;
        case ETHTYPE_ARP:
            struct eth_addr ethaddr;
            memcpy(ethaddr.addr, etherif->virtioNet->macAddress(), ETHARP_HWADDR_LEN);
            etharp_arp_input(netif, &ethaddr, p);
            break;
        default:
            LWIP_ASSERT("p != NULL", p != NULL);
            pbuf_free(p);
            break;
        }
        return true;
    } else {
        return false;
    }
}
コード例 #13
0
ファイル: 5272fec.c プロジェクト: NKSG/INTER_MANET_NS3
/*-----------------------------------------------------------------------------------*/
static void
eth_input(struct pbuf *p, struct netif *netif)
{
    /* Ethernet protocol layer */
    struct eth_hdr *ethhdr;
    mcf5272if_t *mcf5272 = netif->state;

    ethhdr = p->payload;
    
    switch (htons(ethhdr->type)) {
      case ETHTYPE_IP:
        etharp_ip_input(netif, p);
        pbuf_header(p, -14);
        netif->input(p, netif);
        break;
      case ETHTYPE_ARP:
        etharp_arp_input(netif, mcf5272->ethaddr, p);
        break;
      default:
        pbuf_free(p);
        break;
    }
}
コード例 #14
0
err_t eth_input(struct pbuf *p,struct netif *inp)
{

	struct eth_hdr *ethhdr;

	if(p != NULL)
	{
#ifdef LINK_STATS
		//LINK_STATS_INC(link.recv);
#endif  LINK_STATS

		ethhdr = p->payload;

		switch(uip_htons(ethhdr->type))
		{
		case ETHTYPE_IP: //ETHTYPE_IP
			etharp_ip_input(inp, p);
			pbuf_header(p, -((rt_int16_t)sizeof(struct eth_hdr)));
			if (tcpip_input(p, inp) != ERR_OK)
			{
				// discard packet
				pbuf_free(p);
			}
			break;

		case ETHTYPE_ARP:
			etharp_arp_input(inp, (struct eth_addr *)inp->hwaddr, p);
			break;

		default:
			pbuf_free(p);
			p = NULL;
			break;
		}
	}
    return ERR_OK;
}
コード例 #15
0
//
// ecosif_input():
// This function is called when the eCos hw independent driver
// has some data to pass up to lwIP.It does it through ecosif_input.
//
static void
ecosif_input(struct netif *netif, struct pbuf *p)
{
  struct eth_hdr *ethhdr;
  
  ethhdr = p->payload;

  switch (htons(ethhdr->type)) {
  case ETHTYPE_IP:
    LWIP_DEBUGF(0, ("ecosif_input: IP packet\n"));
    etharp_ip_input(netif, p);
    pbuf_header(p, -14);
    netif->input(p, netif);
    break;
  case ETHTYPE_ARP:
    LWIP_DEBUGF(0, ("ecosif_input: ARP packet\n"));
    etharp_arp_input(netif, (struct eth_addr *) &netif->hwaddr, p);
    break;
  default:
    pbuf_free(p);
    break;
  }

}
コード例 #16
0
ファイル: jif.c プロジェクト: rbowden91/fp261
void
jif_input(struct netif *netif, void *va)
{
    struct jif *jif;
    struct eth_hdr *ethhdr;
    struct pbuf *p;

    jif = (struct jif *) netif->state;
  
    /* move received packet into a new pbuf */
    p = low_level_input(va);

    /* no packet could be read, silently ignore this */
    if (p == NULL) return;
    /* points to packet payload, which starts with an Ethernet header */
    ethhdr = (struct eth_hdr *) p->payload;

    switch (htons(ethhdr->type)) {
    case ETHTYPE_IP:
	/* update ARP table */
	etharp_ip_input(netif, p);
	/* skip Ethernet header */
	pbuf_header(p, -(int)sizeof(struct eth_hdr));
	/* pass to network layer */
	netif->input(p, netif);
	break;
      
    case ETHTYPE_ARP:
	/* pass p to ARP module  */
	etharp_arp_input(netif, jif->ethaddr, p);
	break;

    default:
	pbuf_free(p);
    }
}
コード例 #17
0
ファイル: ethernetif.c プロジェクト: 003900107/netIAP
/**
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 *
 * @param netif the lwip network interface structure for this ethernetif
 */
static void ethernetif_input( void * pvParameters )
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;

	for( ;; )
	{
		do
		{
			ethernetif = s_pxNetIf->state;
			
			/* move received packet into a new pbuf */
			p = low_level_input( s_pxNetIf );
			
			if( p == NULL )
			{
				/* No packet could be read.  Wait a for an interrupt to tell us
				there is more data available. */
				vEMACWaitForInput();
			}
		
		} while( p == NULL );

		/* points to packet payload, which starts with an Ethernet header */
		ethhdr = p->payload;

		#if LINK_STATS
			lwip_stats.link.recv++;
		#endif /* LINK_STATS */

		ethhdr = p->payload;

		switch (htons(ethhdr->type))
		{
			/* IP packet? */
			case ETHTYPE_IP:
				
                          /* full packet send to tcpip_thread to process */
			if (s_pxNetIf->input(p, s_pxNetIf) != ERR_OK)
			{
				LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
				pbuf_free(p);
				p = NULL;
			}
			break;
      
      case ETHTYPE_ARP:                    
#if ETHARP_TRUST_IP_MAC
			etharp_ip_input(s_pxNetIf, p);
#endif
				  /* pass p to ARP module  */
				  etharp_arp_input(s_pxNetIf, ethernetif->ethaddr, p);
				  break;
				
			default:
				  pbuf_free(p);
				  p = NULL;
				  break;
		}
	}
}
コード例 #18
0
ファイル: paulosif.c プロジェクト: kingcope/LikeOS
static void paulosif_input (struct netif *netif)
{
    struct genericif *genericif;
    struct eth_hdr *ethhdr;
    struct pbuf *p, *q = NULL, *r = NULL;
    int len;
    u16_t ether_type;

    genericif = netif->state;
    ioctl (genericif->fd, FIONREAD, &len);

    if (len <= 0)
	return;

    p = low_level_input (genericif);

    if (!p) {
	DEBUGF (TAPIF_DEBUG, ("paulosif_input: low_level_input returned NULL\n"));
	return;
    }
    ethhdr = p->payload;
    ether_type = ntohs (ethhdr->type);

    if (pppoe_input_callback && (ether_type == 0x8863 || ether_type == 0x8864)) {
//printf ("paulosif_input: got PPPoE packet, %d bytes\n", (int) p->len);
	(*pppoe_input_callback) (pppoe_user_data, p, ether_type);
	pbuf_free (p);
	return;
    }

    if (packet_validate (p, netif, genericif)) {
	pbuf_free (p);
	return;
    }

    if (packet_filter_callback) {
	if ((*packet_filter_callback) (packet_filter_data, (unsigned char *) p->payload, (int) p->len)) {
	    pbuf_free (p);
	    return;
	}
    }

    switch (ether_type) {
    case ETHTYPE_IP:
	DEBUGF (TAPIF_DEBUG, ("paulosif_input: IP packet\n"));
	q = etharp_ip_input (netif, p);
	pbuf_header (p, -14);
	netif->input (p, netif);	/* segfault */
	break;
    case ETHTYPE_ARP:
	DEBUGF (TAPIF_DEBUG, ("paulosif_input: ARP packet\n"));
	q = etharp_arp_input (netif, genericif->ethaddr, p, &r);
	pbuf_free (p);
	break;
    default:
	pbuf_free (p);
	break;
    }
    if (q != NULL) {
	magic (q, PBUF_MAGIC);
	low_level_output (genericif, q);
	pbuf_free (q);		/* free'd */
    }
    if (r != NULL) {
	magic (r, PBUF_MAGIC);
	low_level_output (genericif, r);
	pbuf_free (r);		/* free'd */
    }
}
コード例 #19
0
static void
netfront_input(struct netif *netif, unsigned char* data, int len)
{
  struct eth_hdr *ethhdr;
  struct pbuf *p, *q;

#if ETH_PAD_SIZE
  len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
  
  /* move received packet into a new pbuf */
  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
  if (p == NULL) {
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    return;
  }

#if ETH_PAD_SIZE
  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
  
  /* We iterate over the pbuf chain until we have read the entire
   * packet into the pbuf. */
  for(q = p; q != NULL && len > 0; q = q->next) {
    /* Read enough bytes to fill this pbuf in the chain. The
     * available data in the pbuf is given by the q->len
     * variable. */
    memcpy(q->payload, data, len < q->len ? len : q->len);
    data += q->len;
    len -= q->len;
  }

#if ETH_PAD_SIZE
  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif

  LINK_STATS_INC(link.recv);

  /* points to packet payload, which starts with an Ethernet header */
  ethhdr = p->payload;

  ethhdr = p->payload;
    
  switch (htons(ethhdr->type)) {
  /* IP packet? */
  case ETHTYPE_IP:
#if 0
/* CSi disabled ARP table update on ingress IP packets.
   This seems to work but needs thorough testing. */
    /* update ARP table */
    etharp_ip_input(netif, p);
#endif
    /* skip Ethernet header */
    pbuf_header(p, -(int16_t)sizeof(struct eth_hdr));
    /* pass to network layer */
    if (tcpip_input(p, netif) == ERR_MEM)
      /* Could not store it, drop */
      pbuf_free(p);
    break;
      
  case ETHTYPE_ARP:
    /* pass p to ARP module  */
    etharp_arp_input(netif, (struct eth_addr *) netif->hwaddr, p);
    break;

  default:
    pbuf_free(p);
    p = NULL;
    break;
  }
}