Update a few util functions in the common demo area.

This commit is contained in:
Richard Barry 2011-08-01 08:34:05 +00:00
parent a548ef34f8
commit 1aa52c2a7a
5 changed files with 616 additions and 422 deletions

View file

@ -69,7 +69,6 @@
#include <lwip/stats.h>
#include <lwip/snmp.h>
#include "netif/etharp.h"
#include "netif/ppp_oe.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'w'
@ -77,15 +76,32 @@
#define netifMAX_MTU 1500
struct ethernetif
struct xEthernetIf
{
struct eth_addr *ethaddr;
/* Add whatever per-interface state that is needed here. */
};
/* Forward declarations. */
static void ethernetif_input( const unsigned char * const pucInputData, long lLength );
static struct pbuf *low_level_input( const unsigned char * const pucInputData, long lDataLength );
/*
* Place received packet in a pbuf and send a message to the tcpip task to let
* it know new data has arrived.
*/
static void prvEthernetInput( const unsigned char * const pucInputData, long lInputLength );
/*
* Copy the received data into a pbuf.
*/
static struct pbuf *prvLowLevelInput( const unsigned char * const pucInputData, long lDataLength );
/*
* Send data from a pbuf to the hardware.
*/
static err_t prvLowLevelOutput( struct netif *pxNetIf, struct pbuf *p );
/*
* Perform any hardware and/or driver initialisation necessary.
*/
static void prvLowLevelInit( struct netif *pxNetIf );
/*
* Query the computer the simulation is being executed on to find the network
@ -104,12 +120,15 @@ static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
* just polls the interface.
*/
static void prvInterruptSimulator( void *pvParameters );
/*
* Configure the capture filter to allow blocking reads, and to filter out
* packets that are not of interest to this demo.
*/
static void prvConfigureCaptureBehaviour( void );
/*-----------------------------------------------------------*/
/* The WinPCap interface being used. */
static pcap_t *pxOpenedInterfaceHandle = NULL;
@ -117,33 +136,35 @@ static pcap_t *pxOpenedInterfaceHandle = NULL;
static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];
/* The network interface that was opened. */
static struct netif *xlwIPNetif = NULL;
static struct netif *pxlwIPNetIf = NULL;
/*-----------------------------------------------------------*/
/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
* @param pxNetIf the already initialized lwip network interface structure
* for this ethernetif.
*/
static void low_level_init(struct netif *netif)
static void prvLowLevelInit( struct netif *pxNetIf )
{
pcap_if_t *pxAllNetworkInterfaces;
/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
pxNetIf->hwaddr_len = ETHARP_HWADDR_LEN;
/* set MAC hardware address */
netif->hwaddr[ 0 ] = configMAC_ADDR0;
netif->hwaddr[ 1 ] = configMAC_ADDR1;
netif->hwaddr[ 2 ] = configMAC_ADDR2;
netif->hwaddr[ 3 ] = configMAC_ADDR3;
netif->hwaddr[ 4 ] = configMAC_ADDR4;
netif->hwaddr[ 5 ] = configMAC_ADDR5;
pxNetIf->hwaddr[ 0 ] = configMAC_ADDR0;
pxNetIf->hwaddr[ 1 ] = configMAC_ADDR1;
pxNetIf->hwaddr[ 2 ] = configMAC_ADDR2;
pxNetIf->hwaddr[ 3 ] = configMAC_ADDR3;
pxNetIf->hwaddr[ 4 ] = configMAC_ADDR4;
pxNetIf->hwaddr[ 5 ] = configMAC_ADDR5;
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
/* don't set pxNetIf_FLAG_ETHARP if this device is not an ethernet one */
pxNetIf->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
/* Query the computer the simulation is being executed on to find the
network interfaces it has installed. */
@ -161,7 +182,7 @@ pcap_if_t *pxAllNetworkInterfaces;
/* Remember which interface was opened as it is used in the interrupt
simulator task. */
xlwIPNetif = netif;
pxlwIPNetIf = pxNetIf;
}
/**
@ -169,109 +190,117 @@ pcap_if_t *pxAllNetworkInterfaces;
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param pxNetIf the lwip network interface structure for this ethernetif
* @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
* 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 availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
* strange results. You might consider waiting for space in the DMA queue
* to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p)
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 buffer[ 1520 ];
unsigned char *buf = buffer;
unsigned char *ptr;
struct eth_hdr *ethhdr;
u16_t tot_len = p->tot_len - ETH_PAD_SIZE;
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;
#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);
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)
/* Initiate transfer. */
if( p->len == p->tot_len )
{
/* no pbuf chain, don't have to copy -> faster */
buf = &((unsigned char*)p->payload)[ETH_PAD_SIZE];
/* No pbuf chain, don't have to copy -> faster. */
pucBuffer = &( ( unsigned char * ) p->payload )[ ETH_PAD_SIZE ];
}
else
{
/* pbuf chain, copy into contiguous buffer */
if (p->tot_len >= sizeof(buffer))
/* 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(netif);
return ERR_BUF;
LINK_STATS_INC( link.lenerr );
LINK_STATS_INC( link.drop );
snmp_inc_ifoutdiscards( pxNetIf );
xReturn = ERR_BUF;
}
ptr = buffer;
for( q = p; q != NULL; q = q->next )
else
{
/* 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)
pucChar = ucBuffer;
for( q = p; q != NULL; q = q->next )
{
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;
/* 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;
}
}
}
}
/* signal that packet should be sent */
if( pcap_sendpacket( pxOpenedInterfaceHandle, buf, tot_len ) < 0 )
if( xReturn == ERR_OK )
{
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
snmp_inc_ifoutdiscards(netif);
return ERR_BUF;
/* 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 );
}
}
}
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;
return xReturn;
}
/**
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @param pxNetIf the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
* NULL on memory error
*/
static struct pbuf *low_level_input( const unsigned char * const pucInputData, long lDataLength )
static struct pbuf *prvLowLevelInput( const unsigned char * const pucInputData, long lDataLength )
{
struct pbuf *p = NULL, *q;
@ -287,7 +316,7 @@ struct pbuf *p = NULL, *q;
if( p != NULL )
{
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
pbuf_header( p, -ETH_PAD_SIZE ); /* drop the padding word */
#endif
/* We iterate over the pbuf chain until we have read the entire
@ -300,7 +329,7 @@ struct pbuf *p = NULL, *q;
* variable.
* This does not necessarily have to be a memcpy, you can also preallocate
* pbufs for a DMA-enabled MAC and after receiving truncate it to the
* actually received size. In this case, ensure the tot_len member of the
* actually received size. In this case, ensure the usTotalLength member of the
* pbuf is the sum of the chained pbuf len members.
*/
memcpy( q->payload, &( pucInputData[ lDataLength ] ), q->len );
@ -311,7 +340,7 @@ struct pbuf *p = NULL, *q;
pbuf_header( p, ETH_PAD_SIZE ); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
LINK_STATS_INC( link.recv );
}
}
@ -320,119 +349,124 @@ struct pbuf *p = NULL, *q;
/**
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* from the interface. It uses the function prvLowLevelInput() 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
* @param pxNetIf the lwip network interface structure for this ethernetif
*/
static void ethernetif_input( const unsigned char * const pucInputData, long lInputLength )
static void prvEthernetInput( const unsigned char * const pucInputData, long lInputLength )
{
/* This is taken from lwIP example code and therefore does not conform
to the FreeRTOS coding standard. */
struct eth_hdr *ethhdr;
struct eth_hdr *pxHeader;
struct pbuf *p;
/* move received packet into a new pbuf */
p = low_level_input( pucInputData, lInputLength );
p = prvLowLevelInput( pucInputData, lInputLength );
/* no packet could be read, silently ignore this */
if( p == NULL )
if( p != NULL )
{
return;
}
/* points to packet payload, which starts with an Ethernet header */
pxHeader = p->payload;
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
switch( htons( pxHeader->type ) )
{
/* IP or ARP packet? */
case ETHTYPE_IP:
case ETHTYPE_ARP:
/* full packet send to tcpip_thread to process */
if( pxlwIPNetIf->input( p, pxlwIPNetIf ) != ERR_OK )
{
LWIP_DEBUGF(NETIF_DEBUG, ( "ethernetif_input: IP input error\n" ) );
pbuf_free(p);
p = NULL;
}
break;
switch( htons( ethhdr->type ) )
{
/* IP or ARP packet? */
case ETHTYPE_IP:
case ETHTYPE_ARP:
/* full packet send to tcpip_thread to process */
if(xlwIPNetif->input( p, xlwIPNetif )!=ERR_OK )
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
default:
pbuf_free( p );
p = NULL;
}
break;
default:
pbuf_free( p );
p = NULL;
break;
break;
}
}
}
/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* network interface. It calls the function prvLowLevelInit() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @param pxNetIf the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif_init( struct netif *netif )
err_t ethernetif_init( struct netif *pxNetIf )
{
err_t xReturn = ERR_OK;
/* This is taken from lwIP example code and therefore does not conform
to the FreeRTOS coding standard. */
struct ethernetif *ethernetif;
struct xEthernetIf *pxEthernetIf;
LWIP_ASSERT( "netif != NULL", ( netif != NULL ) );
ethernetif = mem_malloc( sizeof( struct ethernetif ) );
if (ethernetif == NULL)
LWIP_ASSERT( "pxNetIf != NULL", ( pxNetIf != NULL ) );
pxEthernetIf = mem_malloc( sizeof( struct xEthernetIf ) );
if( pxEthernetIf == NULL )
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
return ERR_MEM;
LWIP_DEBUGF(NETIF_DEBUG, ( "ethernetif_init: out of memory\n" ) );
xReturn = ERR_MEM;
}
else
{
#if LWIP_NETIF_HOSTNAME
{
/* Initialize interface hostname */
pxNetIf->hostname = "lwip";
}
#endif /* LWIP_NETIF_HOSTNAME */
pxNetIf->state = pxEthernetIf;
pxNetIf->name[ 0 ] = IFNAME0;
pxNetIf->name[ 1 ] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
pxNetIf->output = etharp_output;
pxNetIf->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
pxNetIf->hwaddr_len = ETHARP_HWADDR_LEN;
pxNetIf->mtu = netifMAX_MTU;
pxNetIf->linkoutput = prvLowLevelOutput;
pxEthernetIf->ethaddr = ( struct eth_addr * ) &( pxNetIf->hwaddr[ 0 ] );
/* initialize the hardware */
prvLowLevelInit( pxNetIf );
}
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
netif->state = ethernetif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
netif->output = etharp_output;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
netif->hwaddr_len = ETHARP_HWADDR_LEN;
netif->mtu = netifMAX_MTU;
netif->linkoutput = low_level_output;
ethernetif->ethaddr = ( struct eth_addr * ) &( netif->hwaddr[ 0 ] );
/* initialize the hardware */
low_level_init( netif );
return ERR_OK;
return xReturn;
}
/*-----------------------------------------------------------*/
static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )
{
{
pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;
long lInterfaceNumber = 1;
if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
{
printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );
pxAllNetworkInterfaces = NULL;
}
if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )
{
printf( "\r\nCould not obtain a list of network interfaces\r\n%s\r\n", cErrorBuffer );
pxAllNetworkInterfaces = NULL;
}
if( pxAllNetworkInterfaces != NULL )
{
@ -455,20 +489,20 @@ long lInterfaceNumber = 1;
}
}
if( lInterfaceNumber == 1 )
{
if( lInterfaceNumber == 1 )
{
/* The interface number was never incremented, so the above for() loop
did not execute meaning no interfaces were found. */
printf( " \r\nNo network interfaces were found.\r\n" );
pxAllNetworkInterfaces = NULL;
}
printf( " \r\nNo network interfaces were found.\r\n" );
pxAllNetworkInterfaces = NULL;
}
printf( "\r\nThe interface that will be opened is set by configNETWORK_INTERFACE_TO_USE which should be defined in FreeRTOSConfig.h\r\n" );
printf( "Attempting to open interface number %d.\r\n", configNETWORK_INTERFACE_TO_USE );
if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )
{
printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );
if( ( configNETWORK_INTERFACE_TO_USE < 1L ) || ( configNETWORK_INTERFACE_TO_USE > lInterfaceNumber ) )
{
printf("\r\nconfigNETWORK_INTERFACE_TO_USE is not in the valid range.\r\n" );
if( pxAllNetworkInterfaces != NULL )
{
@ -476,7 +510,7 @@ long lInterfaceNumber = 1;
pcap_freealldevs( pxAllNetworkInterfaces );
pxAllNetworkInterfaces = NULL;
}
}
}
return pxAllNetworkInterfaces;
}
@ -487,15 +521,15 @@ static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
pcap_if_t *xInterface;
long x;
/* Walk the list of devices until the selected device is located. */
/* Walk the list of devices until the selected device is located. */
xInterface = pxAllNetworkInterfaces;
for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )
for( x = 0L; x < ( configNETWORK_INTERFACE_TO_USE - 1L ); x++ )
{
xInterface = xInterface->next;
}
/* Open the selected interface. */
pxOpenedInterfaceHandle = pcap_open( xInterface->name, /* The name of the selected interface. */
/* Open the selected interface. */
pxOpenedInterfaceHandle = pcap_open( xInterface->name, /* The name of the selected interface. */
netifMAX_MTU, /* The size of the packet to capture. */
PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscious mode as the MAC and
IP address is going to be "simulated", and
@ -503,17 +537,17 @@ long x;
trafic to the simulated IP address to be routed
to uIP, and trafic to the real IP address to be
routed to the Windows TCP/IP stack. */
0L, /* The read time out. This is going to block
0L, /* The read time out. This is going to block
until data is available. */
NULL, /* No authentication is required as this is
NULL, /* No authentication is required as this is
not a remote capture session. */
cErrorBuffer
cErrorBuffer
);
if ( pxOpenedInterfaceHandle == NULL )
{
printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );
}
if ( pxOpenedInterfaceHandle == NULL )
{
printf( "\r\n%s is not supported by WinPcap and cannot be opened\r\n", xInterface->name );
}
else
{
/* Configure the capture filter to allow blocking reads, and to filter
@ -542,9 +576,9 @@ long lResult;
lResult = pcap_next_ex( pxOpenedInterfaceHandle, &pxHeader, &pucPacketData );
if( lResult == 1 )
{
if( xlwIPNetif != NULL )
if( pxlwIPNetIf != NULL )
{
ethernetif_input( pucPacketData, pxHeader->len );
prvEthernetInput( pucPacketData, pxHeader->len );
}
}
else
@ -577,11 +611,11 @@ unsigned long ulNetMask;
ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
if( pcap_compile(pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )
{
printf("\r\nThe packet filter string is invalid\r\n" );
}
{
printf( "\r\nThe packet filter string is invalid\r\n" );
}
else
{
{
if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )
{
printf( "\r\nAn error occurred setting the packet filter.\r\n" );