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