/*-----------------------------------------------------------------------------------*/ 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; }
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; }
/** 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; }
/** * 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; }