Ok... i will try to explain my test and the problem.
After i will post a network sniffer report.
I have a simple pc application (client) which read packet from server and
show in a window.
My application in board whit lwip works using two task:
- the first task get paccket from serial port, at 115200 baud; packet has
the delimiter, so, at the end of packet, this task send it on queue.
- the second task has a loop with a select on data received on socket, with
a timeout of 50 ms: when timeout expired, loop on queue, get the packet from
queue and call socket function send, and loop again
i did the test using very small packet (max 30 bytes), sending them on uart
every 100 ms
After few packets, i saw lwip blocked: in particolar, the task which manage
socket is blocked, i suppose in send function.
I saw that in this case, tcpip thread (i suppose) is looping in tcp_enqueue
function, and in particolar i have: queuelen = TCP_SND_QUEUELEN, so,
TCP_STATS_INC(tcp.memerr) is done.
i have options below this post.
i'm doing other test, i will post some report.
Piero
/*
-----------------------------------------------
---------- Platform specific locking ----------
-----------------------------------------------
*/
/**
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
* critical regions during buffer allocation, deallocation and memory
* allocation and deallocation.
*/
#define SYS_LIGHTWEIGHT_PROT 1
/**
* NO_SYS==1: Provides VERY minimal functionality. Otherwise,
* use lwIP facilities.
*/
#define NO_SYS 0
/*
------------------------------------
---------- Memory options ----------
------------------------------------
*/
/**
* MEM_ALIGNMENT: should be set to the alignment of the CPU
* 4 byte alignment -> #define MEM_ALIGNMENT 4
* 2 byte alignment -> #define MEM_ALIGNMENT 2
*/
#define MEM_ALIGNMENT 4
/**
* MEM_SIZE: the size of the heap memory. If the application will send
* a lot of data that needs to be copied, this should be set high.
*/
#define MEM_SIZE 2000
/**
* MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable
* amount of bytes before and after each memp element in every pool and
fills
* it with a prominent default value.
* MEMP_OVERFLOW_CHECK == 0 no checking
* MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed
* MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time
* memp_malloc() or memp_free() is called (useful but slow!)
*/
#define MEMP_OVERFLOW_CHECK 0
/**
* MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make
* sure that there are no cycles in the linked lists.
*/
#define MEMP_SANITY_CHECK 0
/**
* MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set
* of memory pools of various sizes. When mem_malloc is called, an element
of
* the smallest pool that can provide the lenght needed is returned.
*/
#define MEM_USE_POOLS 0
/**
* MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h
* that defines additional pools beyond the "standard" ones required
* by lwIP. If you set this to 1, you must have lwippools.h in your
* inlude path somewhere.
*/
#define MEMP_USE_CUSTOM_POOLS 0
/*
------------------------------------------------
---------- Internal Memory Pool Sizes ----------
------------------------------------------------
*/
/**
* MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and
PBUF_REF).
* If the application sends a lot of data out of ROM (or other static
memory),
* this should be set high.
*/
#define MEMP_NUM_PBUF 10
// piero??
/**
* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
* per active UDP "connection".
* (requires the LWIP_UDP option)
*/
#define MEMP_NUM_UDP_PCB 2
/**
* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections.
* (requires the LWIP_TCP option)
*/
#define MEMP_NUM_TCP_PCB 3
/**
* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections.
* (requires the LWIP_TCP option)
*/
#define MEMP_NUM_TCP_PCB_LISTEN 3
/**
* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments.
* (requires the LWIP_TCP option)
*/
#define MEMP_NUM_TCP_SEG 20
/**
* MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing
* packets (pbufs) that are waiting for an ARP request (to resolve
* their destination address) to finish.
* (requires the ARP_QUEUEING option)
*/
#define MEMP_NUM_ARP_QUEUE 6
/**
* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts.
* (requires NO_SYS==0)
*/
#define MEMP_NUM_SYS_TIMEOUT 10
/**
* MEMP_NUM_NETBUF: the number of struct netbufs.
* (only needed if you use the sequential API, like api_lib.c)
*/
#define MEMP_NUM_NETBUF 10
// piero: tcp+udp ? no dal forum
/**
* MEMP_NUM_NETCONN: the number of struct netconns.
* (only needed if you use the sequential API, like api_lib.c)
*/
#define MEMP_NUM_NETCONN 10
// piero: listen+tcp+udp? sì, dare un margine per connessioni che non si
chiudono subito
/**
* MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
* for callback/timeout API communication.
* (only needed if you use tcpip.c)
*/
#define MEMP_NUM_TCPIP_MSG_API 8
// piero? legato al numero di task lwip, ed uso interno
/**
* MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
* for incoming packets.
* (only needed if you use tcpip.c)
*/
#define MEMP_NUM_TCPIP_MSG_INPKT 10
// piero?
/**
* PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
*/
#define PBUF_POOL_SIZE 20
// piero
/*
---------------------------------
---------- ARP options ----------
---------------------------------
*/
/**
* LWIP_ARP==1: Enable ARP functionality.
*/
#define LWIP_ARP 1
/**
* ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached.
*/
#define ARP_TABLE_SIZE 5
/**
* ARP_QUEUEING==1: Outgoing packets are queued during hardware address
* resolution.
*/
#define ARP_QUEUEING 1
/**
* ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be
* updated with the source MAC and IP addresses supplied in the packet.
* You may want to disable this if you do not trust LAN peers to have the
* correct addresses, or as a limited approach to attempt to handle
* spoofing. If disabled, lwIP will need to make a new ARP request if
* the peer is not already in the ARP table, adding a little latency.
*/
#define ETHARP_TRUST_IP_MAC 1
/*
--------------------------------
---------- IP options ----------
--------------------------------
*/
/**
* IP_FORWARD==1: Enables the ability to forward IP packets across network
* interfaces. If you are going to run lwIP on a device with only one
network
* interface, define this to 0.
*/
#define IP_FORWARD 0
/**
* IP_OPTIONS_ALLOWED: Defines the behavior for IP options.
* IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
* IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed).
*/
#define IP_OPTIONS_ALLOWED 1
/**
* IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that
* this option does not affect outgoing packet sizes, which can be
controlled
* via IP_FRAG.
*/
#define IP_REASSEMBLY 1
/**
* IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note
* that this option does not affect incoming packet sizes, which can be
* controlled via IP_REASSEMBLY.
*/
#define IP_FRAG 0
/**
* IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be
reassembled.
* Since the received pbufs are enqueued, be sure to configure
* PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to
receive
* packets even if the maximum amount of fragments is enqueued for
reassembly!
*/
#define IP_REASS_MAX_PBUFS 10
/**
* IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP
* fragmentation. Otherwise pbufs are allocated and reference the original
* packet data to be fragmented.
*/
#define IP_FRAG_USES_STATIC_BUF 0
/*
----------------------------------
---------- ICMP options ----------
----------------------------------
*/
/*
---------------------------------
---------- RAW options ----------
---------------------------------
*/
/**
* LWIP_RAW==1: Enable application layer to hook into the IP layer itself.
*/
#define LWIP_RAW 0
/*
----------------------------------
---------- DHCP options ----------
----------------------------------
*/
/**
* LWIP_DHCP==1: Enable DHCP module.
*/
#define LWIP_DHCP 1
/*
------------------------------------
---------- AUTOIP options ----------
------------------------------------
*/
/**
* LWIP_AUTOIP==1: Enable AUTOIP module.
*/
#define LWIP_AUTOIP 0
/**
* LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on
* the same interface at the same time.
*/
#define LWIP_DHCP_AUTOIP_COOP 0
/*
----------------------------------
---------- SNMP options ----------
----------------------------------
*/
/*
----------------------------------
---------- IGMP options ----------
----------------------------------
*/
/*
----------------------------------
---------- DNS options -----------
----------------------------------
*/
/**
* LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS
* transport.
*/
#define LWIP_DNS 0
/** DNS maximum number of entries to maintain locally. */
#define DNS_TABLE_SIZE 4
/** DNS maximum host name length supported in the name table. */
#define DNS_MAX_NAME_LENGTH 256
/** The maximum of DNS servers */
#define DNS_MAX_SERVERS 2
/** DNS do a name checking between the query and the response. */
#define DNS_DOES_NAME_CHECK 1
/** DNS use a local buffer if DNS_USES_STATIC_BUF=0, a static one if
DNS_USES_STATIC_BUF=1, or a dynamic one if DNS_USES_STATIC_BUF=2.
The buffer will be of size DNS_MSG_SIZE */
#define DNS_USES_STATIC_BUF 1
/** DNS message max. size. Default value is RFC compliant. */
#define DNS_MSG_SIZE 512
/*
---------------------------------
---------- UDP options ----------
---------------------------------
*/
/**
* LWIP_UDP==1: Turn on UDP.
*/
#define LWIP_UDP 1
/**
* LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP)
*/
#define LWIP_UDPLITE 0
/*
---------------------------------
---------- TCP options ----------
---------------------------------
*/
/**
* LWIP_TCP==1: Turn on TCP.
*/
#define LWIP_TCP 1
/**
* TCP_MSS: TCP Maximum segment size. (default is 128, a *very*
* conservative default.)
* For the receive side, this MSS is advertised to the remote side
* when opening a connection. For the transmit size, this MSS sets
* an upper limit on the MSS advertised by the remote host.
*/
#define TCP_MSS 1460
/**
* TCP_SND_BUF: TCP sender buffer space (bytes).
*/
#define TCP_SND_BUF (TCP_MSS<<1)
/**
* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
*/
#define TCP_SND_QUEUELEN (8 * (TCP_SND_BUF/TCP_MSS))
/**
* TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb.
*/
#define TCP_LISTEN_BACKLOG 1
/**
* The maximum allowed backlog for TCP listen netconns.
* This backlog is used unless another is explicitly specified.
* 0xff is the maximum (u8_t).
*/
#define TCP_DEFAULT_LISTEN_BACKLOG 0xff
/*
----------------------------------
---------- Pbuf options ----------
----------------------------------
*/
/**
* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is
* designed to accomodate single full size TCP frame in one pbuf, including
* TCP_MSS, IP header, and link header.
*/
#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(128)
/*
------------------------------------------------
---------- Network Interfaces options ----------
------------------------------------------------
*/
/**
* LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname
* field.
*/
#define LWIP_NETIF_HOSTNAME 0
// piero
/**
* LWIP_NETIF_API==1: Support netif api (in netifapi.c)
*/
#define LWIP_NETIF_API 0
/**
* LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an
interface
* changes its up/down status (i.e., due to DHCP IP acquistion)
*/
#define LWIP_NETIF_STATUS_CALLBACK 1
/**
* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an
interface
* whenever the link changes (i.e., link down)
*/
#define LWIP_NETIF_LINK_CALLBACK 0
/**
* LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table
* indices) in struct netif. TCP and UDP can make use of this to prevent
* scanning the ARP table for every sent packet. While this is faster for
big
* ARP tables or many concurrent connections, it might be counterproductive
* if you have a tiny ARP table or if there never are concurrent
connections.
*/
#define LWIP_NETIF_HWADDRHINT 0
/*
------------------------------------
---------- LOOPIF options ----------
------------------------------------
*/
/**
* LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c
*/
#define LWIP_HAVE_LOOPIF 0
/**
* LWIP_LOOPIF_MULTITHREADING: Indicates whether threading is enabled in
* the system, as LOOPIF must change how it behaves depending on this
setting.
* Setting this is needed to avoid reentering non-reentrant functions like
* tcp_input().
* LWIP_LOOPIF_MULTITHREADING==1: Indicates that the user is using a
* multithreaded environment like tcpip.c. In this case,
netif->input()
* is called directly.
* LWIP_LOOPIF_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
* The packets are put on a list and loopif_poll() must be called in
* the main application loop.
*/
#define LWIP_LOOPIF_MULTITHREADING 1
/*
------------------------------------
---------- Thread options ----------
------------------------------------
*/
/**
* TCPIP_THREAD_NAME: The name assigned to the main tcpip thread.
*/
#define TCPIP_THREAD_NAME "tcpip_thread"
/**
* TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread.
* The stack size value itself is platform-dependent, but is passed to
* sys_thread_new() when the thread is created.
*/
#define TCPIP_THREAD_STACKSIZE 300
// piero ?
/**
* TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread.
* The priority value itself is platform-dependent, but is passed to
* sys_thread_new() when the thread is created.
*/
#define TCPIP_THREAD_PRIO 1
// piero ?
/**
* TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages
* The queue size value itself is platform-dependent, but is passed to
* sys_mbox_new() when tcpip_init is called.
*/
#define TCPIP_MBOX_SIZE 30
// piero?
/**
* DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
* NETCONN_UDP. The queue size value itself is platform-dependent, but is
passed
* to sys_mbox_new() when the recvmbox is created.
*/
#define DEFAULT_UDP_RECVMBOX_SIZE 30
// piero?
/**
* DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
* NETCONN_TCP. The queue size value itself is platform-dependent, but is
passed
* to sys_mbox_new() when the recvmbox is created.
*/
#define DEFAULT_TCP_RECVMBOX_SIZE 30
// piero?
/**
* DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections.
* The queue size value itself is platform-dependent, but is passed to
* sys_mbox_new() when the acceptmbox is created.
*/
#define DEFAULT_ACCEPTMBOX_SIZE 10
// piero
/*
----------------------------------------------
---------- Sequential layer options ----------
----------------------------------------------
*/
/**
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
*/
#define LWIP_NETCONN 1
/*
------------------------------------
---------- Socket options ----------
------------------------------------
*/
/**
* LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
*/
#define LWIP_SOCKET 1
/**
* LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names.
* (only used if you use sockets.c)
*/
#define LWIP_COMPAT_SOCKETS 1
/**
* LWIP_COMPAT_SOCKETS==1: Enable POSIX-style sockets functions names.
Disable
* this option if you use a POSIX operating system that uses the same names
* (read, write & close). (only used if you use sockets.c)
*/
#define LWIP_POSIX_SOCKETS_IO_NAMES 1
/**
* LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT
* options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be
set
* in seconds. (does not require sockets.c, and will affect tcp.c)
*/
#define LWIP_TCP_KEEPALIVE 0
/**
* LWIP_SO_RCVTIMEO==1: Enable SO_RCVTIMEO processing.
*/
#define LWIP_SO_RCVTIMEO 0
/**
* LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing.
*/
#define LWIP_SO_RCVBUF 0
2008/3/19, [EMAIL PROTECTED] <[EMAIL PROTECTED]>:
>
> Jonathan Larmour wrote:
> > The comment could be better positioned. The bit:
> > /* if ERR_MEM, we wait for sent_tcp or poll_tcp to be called
> >
> > applies to the previous block.
> >
> > The bit:
> > on other errors we don't try writing any more */
> > applies to the block the comment is presently in.
> >
>
> That would be my fault. The comment is indeed a little confusing!
>
> > If tcp_enqueue returns ERR_MEM, the present code is correct - it is not
> a
> > fatal error, it just means that it should be retried and the . The
> netconn
> > layer will do this as a result of its sent_tcp() and poll_tcp()
> callbacks.
> > The calling thread will only be woken up when the data really is sent,
> or
> > there _is_ a fatal error.
> >
>
> Everything I read in this subject seems perfectly fine to me:
> - data gets queued up, the remote host doesn't ACK fast enough
> - at one point, the application thread using the socket API gets blocked
> while the tcpip thread _isn't_ blocked but processes the tcp pcb (s)
>
> As already noticed, there are 2 settings that limit the date enqueued on
> one PCB: the sendbuf (in bytes) and the queuelen (the number of pbufs
> being queued - unsent and unacked - for one tcp pcb).
>
> In my opinion, what Piero sees is intended behaviour of lwIP: the
> queuelen reaches the predefined limit. Note that this was an u8_t but is
> now (1.3.0) an u16_t so by setting it to 0xffff, you can effectively
> disable this check if you want.
>
> The fact that one limit is tested in api_msg.c (check sendbuf before
> calling tcp_write) and the other is checked in tcp_out.c is due to the
> nature of the limits: if the sendbuf can't accept all the data, we can
> send less data, but if the queuelen has reached the limit there is
> nothing that can be done in api_msg.c so no need to add extra code for it!
>
> About the blocking of lwIP: as Jonathan already said, socket
> implementations DO block by default (in situations as described, for
> example). Most of them can be told to not block (using O_NONBLOCK or
> something). However, lwIP does not fully support this at the moment.
>
> The fact that the problem disappears when disabeling the nagle algorithm
> could mean the nagle algorithm has a bug, indeed. But to get to the
> source of this, a detailed analysis of the packet flow (using
> ethereal/wireshark) as well as a log output of the target runing lwIP
> would be useful!
>
>
> Simon
>
>
>
> _______________________________________________
> lwip-users mailing list
> [email protected]
> http://lists.nongnu.org/mailman/listinfo/lwip-users
>
_______________________________________________
lwip-users mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/lwip-users