예제 #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
low_level_output(struct netif *netif, struct pbuf *p)
{
  struct mintapif *mintapif;
  struct pbuf *q;
  char buf[1514];
  char *bufptr;
  int written;

  mintapif = netif->state;
  
  /* initiate transfer(); */
  
  bufptr = &buf[0];
  
  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); */
    memcpy(bufptr, q->payload, q->len);
    bufptr += q->len;
  }

  /* signal that packet should be sent(); */
  written = write(mintapif->fd, buf, p->tot_len);
  if (written == -1) {
    snmp_inc_ifoutdiscards(netif);
    perror("tapif: write");
  }
  else {
    snmp_add_ifoutoctets(netif, written);
  }
  return ERR_OK;
}
예제 #3
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;
}
예제 #4
0
파일: netif.c 프로젝트: projectarkc/psiphon
/**
 * 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;
}
예제 #5
0
파일: pcapif.c 프로젝트: lipro/lwip-contrib
/** 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;
}
예제 #6
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;
}
예제 #7
0
파일: cs8900if.c 프로젝트: 10code/lwip
/**
 *
 *
 * @return error code
 * - ERR_OK: packet transferred to hardware
 * - ERR_CONN: no link or link failure
 * - ERR_IF: could not transfer to link (hardware buffer full?)
 */
static err_t cs8900_output(struct netif *netif, struct pbuf *p)
{
  s16_t tries = 0;
  err_t result;

  // exit if link has failed
  PACKETPP = CS_PP_LINESTATUS;
  if ((PPDATA & 0x0080U/*LinkOK*/) == 0) return ERR_CONN; // no Ethernet link

  result = ERR_OK;
  /* TODO: should this occur AFTER setting TXLENGTH??? */
  /* drop the padding word */
#if ETH_PAD_SIZE
  pbuf_header(p, -ETH_PAD_SIZE);
#endif

  /* issue 'transmit' command to CS8900 */
  TXCMD = 0x00C9U;
  /* send length (in bytes) of packet to send, but at least minimum frame length */
  TXLENGTH = (p->tot_len < ETH_MIN_FRAME_LEN? ETH_MIN_FRAME_LEN: p->tot_len);

  PACKETPP = CS_PP_BUSSTATUS;
  // not ready for transmission and still within 100 retries?
  while (((PPDATA & 0x0100U/*Rdy4TxNOW*/) == 0) && (tries++ < 100))
  {
    // throw away the last committed received frame
    PACKETPP = CS_PP_RXCFG;
    PPDATA = (0x0003U | 0x0040U/*Skip_1*/ | 0x0100U/*RxOKiE*/);
    PACKETPP = CS_PP_BUSSTATUS;
    /* cs8900if->dropped++; // CHECK: we do not know if we actually will drop a frame here */
  }
  // ready to transmit?
  if ((PPDATA & 0x0100U/*Rdy4TxNOW*/) != 0)
  {
    u16_t sent_bytes = 0;
    /* q traverses through linked list of pbuf's
     * This list MUST consist of a single packet ONLY */
    struct pbuf *q;
    u16_t pbuf_index = 0;
    u8_t word_index = 0;
    u8_t word[2];
    q = p;
    /* Write data into CS8900, two bytes at a time
     * Handling pbuf's with odd number of bytes correctly 
     * No attempt to optimize for speed has been made */
    while (q)
    {
      if (pbuf_index < q->len)
      {
        word[word_index++] = ((u8_t*)q->payload)[pbuf_index++];
        if (word_index == 2)
        {
          RXTXREG = (word[1] << 8) | word[0];
          word_index = 0;
          sent_bytes += 2;
        }
      }
      else
      {
        q = q->next;
        pbuf_index = 0;
      }
    }
    /* One byte could still be unsent */
    if (word_index == 1)
    {
      RXTXREG = word[0];
      sent_bytes += 2;
    }
    /* provide any additional padding to comply with minimum Ethernet
     * frame length (RFC10242) */
    while (sent_bytes < ETH_MIN_FRAME_LEN)
    {
      RXTXREG = 0x0000;
      sent_bytes += 2;
    }
    /* { the packet has been sent } */
#if (CS8900_STATS > 0)
    ((struct cs8900if *)netif->state)->sentpackets++;
    ((struct cs8900if *)netif->state)->sentbytes += sent_bytes;
#endif
    snmp_add_ifoutoctets(netif,sent_bytes);
  }
  else
  {
    // { not ready to transmit!? }
    snmp_inc_ifoutdiscards(netif);
    /* return not connected */
    result = ERR_IF;
  }
#if ETH_PAD_SIZE
  /* reclaim the padding word */
  pbuf_header(p, ETH_PAD_SIZE);
#endif
  return result;
}