示例#1
0
文件: pktif.c 项目: 10code/lwip
/*-----------------------------------------------------------------------------------*/
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
  struct pbuf *q;
  unsigned char buffer[1600];
  unsigned char *ptr;
  struct eth_hdr *ethhdr;
  u16_t tot_len = p->tot_len - ETH_PAD_SIZE;

#if defined(LWIP_DEBUG) && LWIP_NETIF_TX_SINGLE_PBUF
  LWIP_ASSERT("p->next == NULL && p->len == p->tot_len", p->next == NULL && p->len == p->tot_len);
#endif

  /* initiate transfer(); */
  if (p->tot_len >= sizeof(buffer)) {
    LINK_STATS_INC(link.lenerr);
    LINK_STATS_INC(link.drop);
    snmp_inc_ifoutdiscards(netif);
    return ERR_BUF;
  }
  ptr = buffer;
  for(q = p; q != NULL; q = q->next) {
    /* Send the data from the pbuf to the interface, one pbuf at a
       time. The size of the data in each pbuf is kept in the ->len
       variable. */
    /* send data from(q->payload, q->len); */
    LWIP_DEBUGF(NETIF_DEBUG, ("netif: send ptr %p q->payload %p q->len %i q->next %p\n", ptr, q->payload, (int)q->len, q->next));
    if (q == p) {
      memcpy(ptr, &((char*)q->payload)[ETH_PAD_SIZE], q->len - ETH_PAD_SIZE);
      ptr += q->len - ETH_PAD_SIZE;
    } else {
      memcpy(ptr, q->payload, q->len);
      ptr += q->len;
    }
  }

  /* signal that packet should be sent(); */
  if (packet_send(netif->state, buffer, tot_len) < 0) {
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    snmp_inc_ifoutdiscards(netif);
    return ERR_BUF;
  }

  LINK_STATS_INC(link.xmit);
  snmp_add_ifoutoctets(netif, tot_len);
  ethhdr = (struct eth_hdr *)p->payload;
  if ((ethhdr->dest.addr[0] & 1) != 0) {
    /* broadcast or multicast packet*/
    snmp_inc_ifoutnucastpkts(netif);
  } else {
    /* unicast packet */
    snmp_inc_ifoutucastpkts(netif);
  }
  return ERR_OK;
}
示例#2
0
static err_t prvLowLevelOutput( struct netif *pxNetIf, struct pbuf *p )
{

    /* This is taken from lwIP example code and therefore does not conform
    to the FreeRTOS coding standard. */

    struct pbuf *q;
    static unsigned char ucBuffer[ 1520 ];
    unsigned char *pucBuffer = ucBuffer;
    unsigned char *pucChar;
    struct eth_hdr *pxHeader;
    u16_t usTotalLength = p->tot_len - ETH_PAD_SIZE;
    err_t xReturn = ERR_OK;

    ( void ) pxNetIf;

#if defined(LWIP_DEBUG) && LWIP_NETIF_TX_SINGLE_PBUF
    LWIP_ASSERT("p->next == NULL && p->len == p->tot_len", p->next == NULL && p->len == p->tot_len);
#endif

    /* Initiate transfer. */
    if( p->len == p->tot_len ) {
        /* No pbuf chain, don't have to copy -> faster. */
        pucBuffer = &( ( unsigned char * ) p->payload )[ ETH_PAD_SIZE ];
    } else {
        /* pbuf chain, copy into contiguous ucBuffer. */
        if( p->tot_len >= sizeof( ucBuffer ) ) {
            LINK_STATS_INC( link.lenerr );
            LINK_STATS_INC( link.drop );
            snmp_inc_ifoutdiscards( pxNetIf );
            xReturn = ERR_BUF;
        } else {
            pucChar = ucBuffer;

            for( q = p; q != NULL; q = q->next ) {
                /* Send the data from the pbuf to the interface, one pbuf at a
                time. The size of the data in each pbuf is kept in the ->len
                variable. */
                /* send data from(q->payload, q->len); */
                LWIP_DEBUGF( NETIF_DEBUG, ("NETIF: send pucChar %p q->payload %p q->len %i q->next %p\n", pucChar, q->payload, ( int ) q->len, ( void* ) q->next ) );
                if( q == p ) {
                    memcpy( pucChar, &( ( char * ) q->payload )[ ETH_PAD_SIZE ], q->len - ETH_PAD_SIZE );
                    pucChar += q->len - ETH_PAD_SIZE;
                } else {
                    memcpy( pucChar, q->payload, q->len );
                    pucChar += q->len;
                }
            }
        }
    }

    if( xReturn == ERR_OK ) {
        /* signal that packet should be sent */
        if( pcap_sendpacket( pxOpenedInterfaceHandle, pucBuffer, usTotalLength ) < 0 ) {
            LINK_STATS_INC( link.memerr );
            LINK_STATS_INC( link.drop );
            snmp_inc_ifoutdiscards( pxNetIf );
            xReturn = ERR_BUF;
        } else {
            LINK_STATS_INC( link.xmit );
            snmp_add_ifoutoctets( pxNetIf, usTotalLength );
            pxHeader = ( struct eth_hdr * )p->payload;

            if( ( pxHeader->dest.addr[ 0 ] & 1 ) != 0 ) {
                /* broadcast or multicast packet*/
                snmp_inc_ifoutnucastpkts( pxNetIf );
            } else {
                /* unicast packet */
                snmp_inc_ifoutucastpkts( pxNetIf );
            }
        }
    }

    return xReturn;
}
示例#3
0
/**
 * Send an IP packet to be received on the same netif (loopif-like).
 * The pbuf is simply copied and handed back to netif->input.
 * In multithreaded mode, this is done directly since netif->input must put
 * the packet on a queue.
 * In callback mode, the packet is put on an internal queue and is fed to
 * netif->input by netif_poll().
 *
 * @param netif the lwip network interface structure
 * @param p the (IP) packet to 'send'
 * @param ipaddr the ip address to send the packet to (not used)
 * @return ERR_OK if the packet has been sent
 *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
 */
err_t
netif_loop_output(struct netif *netif, struct pbuf *p,
       ip_addr_t *ipaddr)
{
  struct pbuf *r;
  err_t err;
  struct pbuf *last;
#if LWIP_LOOPBACK_MAX_PBUFS
  u8_t clen = 0;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
  /* If we have a loopif, SNMP counters are adjusted for it,
   * if not they are adjusted for 'netif'. */
#if LWIP_SNMP
#if LWIP_HAVE_LOOPIF
  struct netif *stats_if = &loop_netif;
#else /* LWIP_HAVE_LOOPIF */
  struct netif *stats_if = netif;
#endif /* LWIP_HAVE_LOOPIF */
#endif /* LWIP_SNMP */
  SYS_ARCH_DECL_PROTECT(lev);
  LWIP_UNUSED_ARG(ipaddr);

  /* Allocate a new pbuf */
  r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
  if (r == NULL) {
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    snmp_inc_ifoutdiscards(stats_if);
    return ERR_MEM;
  }
#if LWIP_LOOPBACK_MAX_PBUFS
  clen = pbuf_clen(r);
  /* check for overflow or too many pbuf on queue */
  if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
     ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
    pbuf_free(r);
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    snmp_inc_ifoutdiscards(stats_if);
    return ERR_MEM;
  }
  netif->loop_cnt_current += clen;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */

  /* Copy the whole pbuf queue p into the single pbuf r */
  if ((err = pbuf_copy(r, p)) != ERR_OK) {
    pbuf_free(r);
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    snmp_inc_ifoutdiscards(stats_if);
    return err;
  }

  /* Put the packet on a linked list which gets emptied through calling
     netif_poll(). */

  /* let last point to the last pbuf in chain r */
  for (last = r; last->next != NULL; last = last->next);

  SYS_ARCH_PROTECT(lev);
  if(netif->loop_first != NULL) {
    LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
    netif->loop_last->next = r;
    netif->loop_last = last;
  } else {
    netif->loop_first = r;
    netif->loop_last = last;
  }
  SYS_ARCH_UNPROTECT(lev);

  LINK_STATS_INC(link.xmit);
  snmp_add_ifoutoctets(stats_if, p->tot_len);
  snmp_inc_ifoutucastpkts(stats_if);

#if LWIP_NETIF_LOOPBACK_MULTITHREADING
  /* For multithreading environment, schedule a call to netif_poll */
  tcpip_callback((tcpip_callback_fn)netif_poll, netif);
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */

  return ERR_OK;
}
示例#4
0
/** low_level_output():
 * Transmit a packet. The packet is contained in the pbuf that is passed to
 * the function. This pbuf might be chained.
 */
static err_t
pcapif_low_level_output(struct netif *netif, struct pbuf *p)
{
  struct pbuf *q;
  unsigned char buffer[ETH_MAX_FRAME_LEN + ETH_PAD_SIZE];
  unsigned char *buf = buffer;
  unsigned char *ptr;
  struct eth_hdr *ethhdr;
  u16_t tot_len = p->tot_len - ETH_PAD_SIZE;
  struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);

#if defined(LWIP_DEBUG) && LWIP_NETIF_TX_SINGLE_PBUF && !(LWIP_IPV4 && IP_FRAG) && (LWIP_IPV6 && LWIP_IPV6_FRAG)
  LWIP_ASSERT("p->next == NULL && p->len == p->tot_len", p->next == NULL && p->len == p->tot_len);
#endif

  /* initiate transfer */
  if ((p->len == p->tot_len) && (p->len >= ETH_MIN_FRAME_LEN + ETH_PAD_SIZE)) {
    /* no pbuf chain, don't have to copy -> faster */
    buf = &((unsigned char*)p->payload)[ETH_PAD_SIZE];
  } else {
    /* pbuf chain, copy into contiguous buffer */
    if (p->tot_len >= sizeof(buffer)) {
      LINK_STATS_INC(link.lenerr);
      LINK_STATS_INC(link.drop);
      snmp_inc_ifoutdiscards(netif);
      return ERR_BUF;
    }
    ptr = buffer;
    for(q = p; q != NULL; q = q->next) {
      /* Send the data from the pbuf to the interface, one pbuf at a
         time. The size of the data in each pbuf is kept in the ->len
         variable. */
      /* send data from(q->payload, q->len); */
      LWIP_DEBUGF(NETIF_DEBUG, ("netif: send ptr %p q->payload %p q->len %i q->next %p\n", ptr, q->payload, (int)q->len, (void*)q->next));
      if (q == p) {
        memcpy(ptr, &((char*)q->payload)[ETH_PAD_SIZE], q->len - ETH_PAD_SIZE);
        ptr += q->len - ETH_PAD_SIZE;
      } else {
        memcpy(ptr, q->payload, q->len);
        ptr += q->len;
      }
    }
  }

  if (tot_len < ETH_MIN_FRAME_LEN) {
    /* ensure minimal frame length */
    memset(&buf[tot_len], 0, ETH_MIN_FRAME_LEN - tot_len);
    tot_len = ETH_MIN_FRAME_LEN;
  }

  /* signal that packet should be sent */
  if (pcap_sendpacket(pa->adapter, buf, tot_len) < 0) {
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    snmp_inc_ifoutdiscards(netif);
    return ERR_BUF;
  }

  LINK_STATS_INC(link.xmit);
  snmp_add_ifoutoctets(netif, tot_len);
  ethhdr = (struct eth_hdr *)p->payload;
  if ((ethhdr->dest.addr[0] & 1) != 0) {
    /* broadcast or multicast packet*/
    snmp_inc_ifoutnucastpkts(netif);
  } else {
    /* unicast packet */
    snmp_inc_ifoutucastpkts(netif);
  }
  return ERR_OK;
}
示例#5
0
/**
 * This function should do the actual transmission of the packet. The packet is
 * contained in the pbuf that is passed to the function. This pbuf
 * might be chained.
 *
 * @param pxNetIf the lwip network interface structure for this etherpxNetIf
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *		 an err_t value if the packet couldn't be sent
 *
 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
 *	   strange results. You might consider waiting for space in the DMA queue
 *	   to become available since the stack doesn't retry to send a packet
 *	   dropped because of memory failure (except for the TCP timers).
 */
static err_t prvLowLevelOutput( struct netif *pxNetIf, struct pbuf *p )
{

	/* This is taken from lwIP example code and therefore does not conform
	to the FreeRTOS coding standard. */

struct pbuf *q;
uint8_t *pucChar;
struct eth_hdr *pxHeader;
err_t xReturn = ERR_BUF;
int32_t x;
extern uint8_t *EMAC_NextPacketToSend( void );
void EMAC_StartTransmitNextBuffer( uint32_t ulLength );

	( void ) pxNetIf;

	/* Attempt to obtain access to a Tx buffer. */
	for( x = 0; x < netifMAX_TX_ATTEMPTS; x++ )
	{
		if( EMAC_CheckTransmitIndex() == TRUE )
		{
			/* Will the data fit in the Tx buffer? */
			if( p->tot_len < EMAC_ETH_MAX_FLEN )
			{
				/* Get a pointer to the Tx buffer that is now known to be free. */
				pucChar = EMAC_NextPacketToSend();

				/* Copy the data into the Tx buffer. */
				for( q = p; q != NULL; q = q->next )
				{
					/* Send the data from the pbuf to the interface, one pbuf at a
					time. The size of the data in each pbuf is kept in the ->len
					variable. */
					/* send data from(q->payload, q->len); */
					LWIP_DEBUGF( NETIF_DEBUG, ( "NETIF: send pucChar %p q->payload %p q->len %i q->next %p\n", pucChar, q->payload, ( int ) q->len, ( void* ) q->next ) );
					if( q == p )
					{
						memcpy( pucChar, &( ( char * ) q->payload )[ ETH_PAD_SIZE ], q->len - ETH_PAD_SIZE );
						pucChar += q->len - ETH_PAD_SIZE;
					}
					else
					{
						memcpy( pucChar, q->payload, q->len );
						pucChar += q->len;
					}
				}

				/* Initiate the Tx. */
				EMAC_StartTransmitNextBuffer( p->tot_len - ETH_PAD_SIZE );

				LINK_STATS_INC( link.xmit );
				snmp_add_ifoutoctets( pxNetIf, usTotalLength );
				pxHeader = ( struct eth_hdr * )p->payload;

				if( ( pxHeader->dest.addr[ 0 ] & 1 ) != 0 )
				{
					/* broadcast or multicast packet*/
					snmp_inc_ifoutnucastpkts( pxNetIf );
				}
				else
				{
					/* unicast packet */
					snmp_inc_ifoutucastpkts( pxNetIf );
				}

				/* The Tx has been initiated. */
				xReturn = ERR_OK;
			}
			else
			{
				configASSERT( ( volatile void * ) 0 );
			}

			break;
		}
		else
		{
			vTaskDelay( netifTX_BUFFER_FREE_WAIT );
		}
	}

	configASSERT( xReturn == ERR_OK );
	if( xReturn != ERR_OK )
	{
		LINK_STATS_INC( link.memerr );
		LINK_STATS_INC( link.drop );
		snmp_inc_ifoutdiscards( pxNetIf );
	}

	return xReturn;
}