lwip-users
[Top][All Lists]
Advanced

[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: Fri, 9 Dec 2011 01:18:28 +0000

So ... I did some more debugging with WireShark and a hub, and here is what I 
am finding ...


When I have the ETH_PAD_SIZE set to 2, I see the following sent out ..

20      4.468790        ff:ff:bc:9a:78:56       CamtecEl_ff:ff:ff       0x3412  
352     Ethernet II

The actual packet is ...

0000   00 00 ff ff ff ff ff ff bc 9a 78 56 34 12 08 00  ..........xV4...
0010   45 00 01 50 00 01 00 00 ff 11 f8 f1 c0 a8 01 02  E..P............
0020   ff ff ff ff 00 44 00 43 01 3c 21 f9 01 01 06 00  .....D.C.<!.....
0030   ab cd 00 01 00 00 00 00 00 00 00 00 00 00 00 00  ................
0040   00 00 00 00 00 00 00 00 bc 9a 78 56 34 12 00 00  ..........xV4...
0050   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0060   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0070   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0080   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0090   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00a0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00b0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00c0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00d0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00e0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00f0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0100   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0110   00 00 00 00 00 00 00 00 63 82 53 63 35 01 01 39  ........c.Sc5..9
0120   02 06 00 37 04 01 03 1c 06 ff 00 00 00 00 00 00  ...7............
0130   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0140   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0150   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00                          
                        ................

In etharp.h, the eth_hdr is defined as:
/** Ethernet header */
struct eth_hdr {
#if ETH_PAD_SIZE
  PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
#endif
  PACK_STRUCT_FIELD(struct eth_addr dest);
  PACK_STRUCT_FIELD(struct eth_addr src);
  PACK_STRUCT_FIELD(u16_t type);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END

Which apparently is packing 2 bytes worth of 0 into the ethernet header. 
So ... the ethernet header is padding the packet with ETH_PAD_SIZE bytes of 0.

In etharp.c,  there is:
static err_t
etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, 
struct eth_addr *dst)
{
  struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;

  LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for 
etharp!",
              (netif->hwaddr_len == ETHARP_HWADDR_LEN));
  ETHADDR32_COPY(&ethhdr->dest, dst);
  ETHADDR16_COPY(&ethhdr->src, src);
  ethhdr->type = PP_HTONS(ETHTYPE_IP);
  LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet 
%p\n", (void *)p));
  /* send the packet */
  return netif->linkoutput(netif, p);
}

Which seems to be sending the pointer to the padding rather than the pointer to 
the start of the data that the linkoutput function is supposed to send. I 
changed my linkoutput function and saw the correct ethernet header go out, and 
then I see DHCP Offers coming back, but apparently there are some other 
responses that need to go out that don't want me to change payload pointer. 
Have I stumbled onto a bug or am I missing something (not that these are 
mutually exclusive in any way :-)

Anyway - I changed my send and receive functions (added below), and this seems 
to get me past DHCP with the ETH_PAD_SIZE set to 2. In fact, it seems to solve 
all of my problems. I am now sending and receiving packets. Cool.

So - is this the advised way to handle this? (It works :-)

-Gary

//==============================================================================
static err_t ethernetif_send(ethernetif_t *ethernetif, struct pbuf *p)
{
  err_t retval = ERR_OK;
  void * payload;

  // 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) )
  {
    payload = p->payload + ETH_PAD_SIZE;
    //if (SUCCESS(emac_send(p->payload, p->len)))
    if (SUCCESS(emac_send(payload, p->len)))
    {
      retval = ERR_OK;
    }
    else
    {
      retval = ! ERR_OK;
    }
    p = p->next;
  }
  return retval;
}

//==============================================================================
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;
  void * payload;

  // 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);
        payload = chainp->payload + ETH_PAD_SIZE;
        //bytes_read = emac_receive(chainp->payload, bytes_to_read);
        bytes_read = emac_receive(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;
    }
  }
}


-Gary


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 mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/lwip-users





reply via email to

[Prev in Thread] Current Thread [Next in Thread]