[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE
From: |
Gary Spivey |
Subject: |
Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE |
Date: |
Thu, 8 Dec 2011 23:45:40 +0000 |
I set the following in my lwipopts.h
#define TCP_MSS 1536
#define TCP_SND_BUF 1536
#define PBUF_LINK_HLEN 16
//#define ETH_PAD_SIZE 2
This runs through DHCP.
When I change it to this:
#define TCP_MSS 1536
#define TCP_SND_BUF 1536
//#define PBUF_LINK_HLEN 16
#define ETH_PAD_SIZE 2
The netif_is_up call in my ethernetif_init never returns positive.
I think the files of interest on my end are the ethernetif.h and .c, and the
arch/cc.h file. I am using the CrossWorks compiler, so my arch/cc.h file looks
like this:
#ifndef __CC_H__
#define __CC_H__
#include <types.h>
#include <string.h>
#define BYTE_ORDER LITTLE_ENDIAN
/* Compiler hints for packing structures */
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT __attribute__ ((packed))
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
/* prototypes for printf() and abort() */
#include <stdio.h>
#include <stdlib.h>
/* Plaform specific diagnostic output */
#ifndef LWIP_PLATFORM_ASSERT
#define LWIP_PLATFORM_ASSERT(x) while(1);
#endif
#endif /* __CC_H__ */
My ethernetif.h file basically contains prototypes and the following:
typedef struct netif ethernetif_t;
My ethernetif.c file is attached below ...
I will work more with a hub and wireshark to see if I can pin down the DHCP
problem further. But any info you can shed on my setup or what should be
happening is most appreciated.
#include <data_types.h>
#include <board.h>
#include <emac.h>
#include <sys_time.h>
#include <ethernetif.h>
#include <lwipopts.h>
#include "lwip/mem.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/dhcp.h"
#include "lwip/pbuf.h"
#include "lwip/tcp.h"
#include "lwip/tcp_impl.h"
#include "lwip/dns.h"
#include "lwip/stats.h"
#include "lwip/ip_frag.h"
#include "lwip/ip_addr.h"
#include "netif/etharp.h"
//-----------------------------------------------------------------------------
// __ __ __ ___ ___ __
// / ` / \ |\ | /__` | /\ |\ | | /__`
// \__, \__/ | \| .__/ | /~~\ | \| | .__/
//
//-----------------------------------------------------------------------------
//Define the interface name
#define IFNAME0 'e'
#define IFNAME1 'n'
//-----------------------------------------------------------------------------
// ___ __ ___ __ ___ ___ __
// | \ / |__) |__ | \ |__ |__ /__`
// | | | |___ |__/ |___ | .__/
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// __ __ ___ __
// \ / /\ |__) | /\ |__) | |__ /__`
// \/ /~~\ | \ | /~~\ |__) |___ |___ .__/
//
//-----------------------------------------------------------------------------
static ethernetif_t ethernetif_allocator;
static ip_addr_t ipaddr;
static ip_addr_t netmask;
static ip_addr_t gw;
static uint32_t lwip250mStimer;
//-----------------------------------------------------------------------------
// __ __ __ ___ __ ___ __ ___ __
// |__) |__) / \ | / \ | \ / |__) |__ /__`
// | | \ \__/ | \__/ | | | |___ .__/
//
//-----------------------------------------------------------------------------
static err_t ethernetif_hardware_init(ethernetif_t * ethernetif);
static err_t ethernetif_send(ethernetif_t *ethernetif, struct pbuf *p);
static void ethernetif_receive(ethernetif_t * ethernetif);
static void ethernetif_process_timers(void);
//-----------------------------------------------------------------------------
// __ __ __
// |__) | | |__) | | / `
// | \__/ |__) |___ | \__,
//
//-----------------------------------------------------------------------------
//==============================================================================
// I don't know where to put this - lwip doesn't define this function.
// But it is the same as my sys_time.
//==============================================================================
u32_t sys_now(void)
{
return(sys_time());
}
//==============================================================================
ethernetif_t * ethernetif_get_handle()
{
return(ðernetif_allocator);
}
//==============================================================================
// This should be called by the board.c file when it is setting up the
// hardware.
//==============================================================================
void ethernetif_init(ethernetif_t * ethernetif)
{
uint32_t last_time;
// Set up the LWIP functions
// startup defaults (may be overridden by one or more opts)
IP4_ADDR(&ipaddr, 192,168,1,2);
IP4_ADDR(&gw, 192,168,1,1);
IP4_ADDR(&netmask, 255,255,255,0);
// Initialize the lwip functions
lwip_init();
// Add the network interface
netif_add(ethernetif, &ipaddr, &netmask, &gw, NULL, ethernetif_hardware_init,
ethernet_input);
// Set it as the default
netif_set_default(ethernetif);
// Set up the interface
//netif_set_up(ethernetif);
// Start dhcp
dhcp_start(ethernetif);
last_time = sys_time();
while (!netif_is_up(ethernetif))
{
if (sys_time() > last_time + 250)
{
ethernetif_process_timers();
last_time = sys_time();
}
ethernetif_receive(ethernetif);
}
}
//==============================================================================
void ethernetif_process(ethernetif_t * ethernetif)
{
uint32_t timestamp;
uint8_t first_time = 1;
// See if we rolled over - if so, adjust the timestamp to match
// Also check if this is our first time. If so, set up the timestamp.
if ((first_time) || (sys_time() < timestamp))
{
timestamp = sys_time();
first_time = 0;
}
// We will do the ethernetif processing here. Initially, we can just poll.
// Later, I can use a flag via interrupt - although, polling will likely
// be the same as checking the flag. Maybe not.
ethernetif_receive(ethernetif);
// Check on the ethernet timers every 250 ms
if (sys_time() > timestamp + 250)
{
// If we have gone 250ms, process the timers
ethernetif_process_timers();
timestamp = sys_time();
}
}
//-----------------------------------------------------------------------------
// __ __ __ __
// / ` /\ | | |__) /\ / ` |__/ /__`
// \__, /~~\ |___ |___ |__) /~~\ \__, | \ .__/
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// __ __ ___ ___
// |__) |__) | \ / /\ | |__
// | | \ | \/ /~~\ | |___
//
//-----------------------------------------------------------------------------
//=============================================================================
// Run this every 250mS to update lwIP timers
//=============================================================================
static void ethernetif_process_timers(void)
{
lwip250mStimer += 250;
if( (lwip250mStimer % TCP_TMR_INTERVAL) == 0 ) { tcp_tmr(); }
if( (lwip250mStimer % ARP_TMR_INTERVAL) == 0 ) { etharp_tmr(); }
#if IP_REASSEMBLY
if( (lwip250mStimer % IP_TMR_INTERVAL) == 0 ) { ip_reass_tmr(); }
#endif
#if LWIP_AUTOIP
if( (lwip250mStimer % AUTOIP_TMR_INTERVAL ) == 0 ) { autoip_tmr(); }
#endif
#if LWIP_IGMP
if( (lwip250mStimer % IGMP_TMR_INTERVAL ) == 0 ) { igmp_tmr(); }
#endif
#if LWIP_DHCP
if( (lwip250mStimer % DHCP_FINE_TIMER_MSECS ) == 0 ) { dhcp_fine_tmr(); }
if( (lwip250mStimer % (DHCP_COARSE_TIMER_SECS*1000) ) == 0 ) {
dhcp_coarse_tmr(); }
#endif
#if LWIP_DNS
if( (lwip250mStimer % DNS_TMR_INTERVAL) == 0 ) { dns_tmr(); }
#endif
}
//==============================================================================
static err_t ethernetif_send(ethernetif_t *ethernetif, struct pbuf *p)
{
err_t retval = ERR_OK;
// Send the packet - we don't need the ethernetif info as we just have the one
// interface. Also, we don't need to check the total bytes as this is just
// double-checking the lwip structs.
while ( (NULL != p) && (ERR_OK == retval) )
{
if (SUCCESS(emac_send(p->payload, p->len)))
{
retval = ERR_OK;
}
else
{
retval = ! ERR_OK;
}
p = p->next;
}
return retval;
}
//==============================================================================
// This function should be called when a packet is ready to be read
// from the interface (either because we are polling, or because an interrupt
// has told us it is time to read).
// Should allocate a pbuf and transfer the bytes of the incoming
// packet from the interface into the pbuf if something exists.
//
// @param ethernetif the lwip network interface structure for this ethernetif
//==============================================================================
static void ethernetif_receive(ethernetif_t * ethernetif)
{
struct eth_hdr *ethhdr;
struct pbuf *p, *chainp;
uint32_t bufsize;
uint32_t bytes_read;
uint32_t bytes_to_read;
// See if there is a packet to get
if (FALSE(emac_checkReceiveIndex()))
{
p = NULL;
}
else
{
// See how much data we need to allocate
bufsize = emac_getReceiveDataSize();
// If there is data (and there should be ...)
if (bufsize)
{
// Allocate a chain of pbufs big enough to hold it
p = pbuf_alloc(PBUF_RAW, bufsize, PBUF_POOL);
// Set up our linked-list index
chainp = p;
// Now let's copy the data into our chain
while (bufsize)
{
// Don't read more than one buffer at a time
bytes_to_read = MINIMUM(bufsize, PBUF_POOL_BUFSIZE);
bytes_read = emac_receive(chainp->payload, bytes_to_read);
// If something goes wrong, we will bail
// I don't know what this will mean to the rest of the system
if ( bytes_read == 0)
{
pbuf_free(p);
p = NULL;
bufsize = 0;
}
// If we successfully read, advance the chain and decrement the amount
// of data left to read.
else
{
chainp = chainp->next;
bufsize -= bytes_read;
}
}
}
}
// If we have a packet,
if (p != NULL) {
// points to packet payload, which starts with an Ethernet header
ethhdr = (struct eth_hdr *) p->payload;
switch (htons(ethhdr->type)) {
// IP or ARP packet?
case ETHTYPE_IP:
case ETHTYPE_ARP:
#if PPPOE_SUPPORT
// PPPoE packet?
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE:
#endif // PPPOE_SUPPORT
// send complete packet to tcpip_thread to process
if (ethernetif->input(p, ethernetif)!=ERR_OK)
{
// If there was a problem with the packet, free it up
pbuf_free(p);
}
break;
default:
pbuf_free(p);
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
// actual setup of the hardware.
//
// This function should be passed as a parameter to netif_add().
//
// @param ethernetif 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
//==============================================================================
static err_t ethernetif_hardware_init(ethernetif_t * ethernetif)
{
struct pbuf *p;
err_t retval;
emac_t * emac;
uint8_t i;
// Initialize the low-level hardware
emac = emac_get_handle();
emac->Mode = EMAC_MODE_AUTO;
if (SUCCESS(emac_init(emac)))
{
retval = ERR_OK;
}
else
{
retval = !ERR_OK;
}
//
// Set up the lwip network interface
//
#if LWIP_NETIF_HOSTNAME
// Initialize interface hostname
ethernetif->hostname = "C3PO";
#endif
// Initialize the snmp variables and counters inside the ethernetif_t
// The last argument should be replaced with your link speed, in units
// of bits per second.
//NETIF_INIT_SNMP(ethernetif, snmp_ifType_ethernet_csmacd,
LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
// I am totally guessing about the link speed here.
//NETIF_INIT_SNMP(ethernetif, snmp_ifType_ethernet_csmacd, 10000000);
ethernetif->name[0] = IFNAME0;
ethernetif->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...)
ethernetif->output = etharp_output;
//ethernetif->linkoutput = (ethernetif_linkoutput_fn) ethernetif_send;
ethernetif->linkoutput = ethernetif_send;
// set MAC hardware address length
ethernetif->hwaddr_len = ETHARP_HWADDR_LEN;
// Set MAC address. It is required that the emac_address be set in the emac
// handle for the lower-level driver. We will just copy that address up
// into our ethernetif.
for (i = 0; i < 6; i++)
{
ethernetif->hwaddr[i] = emac->emac_address[i];
}
// maximum transfer unit - I don't see why this shouldn't be as big as the
// ethernet can handle. Our lwip interface should be able to handle this.
ethernetif->mtu = EMAC_MAX_FRAME_LENGTH;
//ethernetif->mtu = MINIMUM(EMAC_MAX_FRAME_LENGTH, PBUF_POOL_BUFSIZE-4);
// device capabilities
// don't set NETIF_FLAG_ETHARP if this device is not an ethernet one
ethernetif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
NETIF_FLAG_LINK_UP;
return retval;
}
-----Original Message-----
From: address@hidden [mailto:address@hidden On Behalf Of Kieran Mansley
Sent: Thursday, December 08, 2011 12:25 PM
To: Mailing list for lwIP users
Subject: Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE
On 8 Dec 2011, at 18:51, Gary Spivey wrote:
> What is the preferred way to configure lwip so that I can either accept
> packets larger than PBUF_POOL_BUFSIZE or ensure that I don't receive them?
To accept packets larger than PBUF_POOL_BUFSIZE you should, when you receive
them, copy them into the chain of pbufs that you get when you alloc, being
careful to split the received data across the pbufs as necessary.
To ensure that you don't receive packets larger than PBUF_POOL_BUFSIZE, set
that value larger than the biggest packet you can receive. This is a property
of the LAN you are connected to (i.e. it is a value that should be known by all
the hosts and configured the same) and can vary, so I can't tell you a good
value.
In the default, we assume that the largest value on the network is
MSS+40+PBUF_LINK_HLEN, where the 40 is for IP and TCP headers. It is possible
for TCP headers to be bigger than that (if there are options included for
example) or for another host on the network to have a larger MSS and MTU than
lwIP's default, and so you may need to adjust PBUF_POOL_BUFSIZE to match if you
want to fit a frame into a single buffer.
I'm not sure whey DHCP didn't work when you started splitting packets across
buffers. It should. It's either a bug in lwIP or a bug in the way you were
filling the buffers. If you can get more information on the reason for the
failure that would be useful.
Note that you should also handle chains of pbufs on the send path in your
driver. With a relatively small PBUF_POOL_BUFSIZE lwIP can pass packets for
transmission to the driver as a chain as well.
Hope that helps,
Kieran
_______________________________________________
lwip-users mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/lwip-users
- [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, Gary Spivey, 2011/12/07
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, web, 2011/12/07
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, Gary Spivey, 2011/12/07
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, Bill Auerbach, 2011/12/08
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, Gary Spivey, 2011/12/08
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, Kieran Mansley, 2011/12/08
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE,
Gary Spivey <=
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, Gary Spivey, 2011/12/08
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, address@hidden, 2011/12/09
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, Simon Goldschmidt, 2011/12/09
- Re: [lwip-users] Incoming packet bigger than PBUF_POOL_BUFSIZE, Simon Goldschmidt, 2011/12/09