This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Need help with lwIP - UDP vs TCP

I am using the TM4C129X eval kit with TivaWare and lwIP. Ethernet port is connected to Windows 7 PC on a private (secondary) port.

I start things by exchanging 4 sets of TCP packets - the PC sends a request and the Eval kit responds. All is good.

After the fourth exchange, the Eval kit starts to send UDP data packets back to the PC at a regular interval. If it sends one packet, all is good. But if it sends more than one packet, the UDP packets get sent before the response to the 4th TCP packet is sent.(witnessed by Wireshark) which causes problems.  I have tried using tcp_output( ) to no avail. I have also tried to use the tcp_sent( ) callback but it never gets called.

Any suggestions?

Thanks,

Jeff

  • I'm confused. Is this a UDP session or a TCP session?

    How do you intend to transfer the data? UDP or TCP?

    Maybe some code or a program design or flow chart could help here.

  • Sorry for the confusion. I am trying to send video using RTSP/RTP (I know it will be slow, but that's OK). Based on a sample program that runs on Windows I am porting it to the TM4C129X Eval kit.

    It goes like this:

    Host (Win PC)                       Eval Kit                       Type

    -----------------------------------------------------------------------

    Request Options ->                                                 TCP

                                                  <- Send Options         TCP

    Describe  ->                                                               TCP

                                                   <- reply to describe   TCP

    Setup ->                                                                     TCP

                                                   <- reply to setup          TCP

    Play ->                                                                         TCP

                                                   <- reply to play            TCP   (<===== problem is here)

                                                   <- Send 1 frame         UDP

                                                   <- Send 1 frame         UDP

                                                   <- Send 1 frame         UDP

                                                   <- Send 1 frame         UDP

                                                   <- Send 1 frame         UDP

                                                    and so on.

    The problem is that if I send more than one frame via UDP, the reply to the Play command is delayed (but eventually sent).

    How do I force the TCP reply to be sent before sending UDP packets?

    Thanks,

    Jeff

  • You left out some critical things -- I can see why due to the complexity...

    I presume that you are using a port for the TCP and a port for the UDP. say 55560(TCP) and 55570 (UDP) or whatever is convenient to you for whatever reason.

    I am betting that as soon as you see the start command you start to send UDP packets. This would mean that if you are not "multi threaded" the reply to the TCP command will get dropped.

    You could acknowledge by simply sending packets rather than pinging and ponging everything -- or so it seems to me.

    The UDP connection and subsequent send of packets could be a sufficient ACK.

    In any case... You should be storing the fact that a command was received and putting it in a queue...

    At the point of receipt of the last command, the queue should hold:

    (1) Reply to "Play command"

    (2) Start UDP send (or just this and skip (1)

    I am presuming that you have a thread (interrupt) available to listen for further control info during the send from the eval kit. SO that you can stop sending or slow down or whatever...

    This is clearly a case for an RTOS -- is that what you are using?

    Hoping this makes sense to you.

  • Dave,

    You are correct about the ports. But, I do not start sending UDP packets until AFTER I respond to the Start command. The inner workings of lwIP are re-ordering things such that the UDP packets are sent before the Start reply. I have tried inserting time delays after the Start reply but that just delays everything.

    The lwIP tcp_write( ) function contains this in the comments:

    * Write data for sending (but does not send it immediately).
    *
    * It waits in the expectation of more data being sent soon (as
    * it can send them more efficiently by combining them together).
    * To prompt the system to send data now, call tcp_output() after
    * calling tcp_write().

    I tried calling tcp_output( ) as indicated but it had no effect, so either it doesn't work or I am not using it correctly.

    I am unable to debug at this time (working on it) so I can't step through the code.

    I am not currently using a RTOS as I planned to use a hardware timer interrupt to send the UDP packets.

    Thanks,

    Jeff

  • It sounds to me like you have isolated the issue cleanly. I have built similar systems successfully -- but with other processors.

    * To prompt the system to send data now, call tcp_output() after
    * calling tcp_write().

    It seems to me that there could be a bug within the lwip(?) package and maybe TI should get involved.

    Curious about what version of the TCP/IP lib you are using and if you have looked to see if there is a later version with a referenced problem.

    Using Arduino and others I definitely found some issues in the TCP/Ip and UDP -- it was based on an early version of the library.

    I dropped my TI implementation because they NRND'd all my TI w/Ethernet processors. I have not yet considered buying the new TI M4 w/Ethernet kit for my sensor suite.


    Bottom line -- ask TI for some assistance here!

  • David - thanks again for the help. Just to update where I am at:

    I got tcp_sent_callback( )  to work by moving my call to tcp_sent( ) from my init code to the accept callback. Waiting for the callback for the reply to the Play command before sending the UDP packets simply hung the program.

    My call to tcp_output( ) after calling tcp_write( ) to send the response to the Play command is exiting prematurely because of this code within tcp_output( ):

    /* First, check if we are invoked by the TCP input processing
    code. If so, we do not output anything. Instead, we rely on the
    input processing code to call us when input processing is done
    with. */
    if (tcp_input_pcb == pcb) {
    return ERR_OK;

    This seems to imply that I should use a separate PCB for returning data but I have not been able to get that to work.

    If anyone from TI can chime in here it would be greatly appreciated.

    Thanks,

    Jeff

  • Jeff:

    When I first started (serious) Object Oriented programming in 1995 it quickly became apparent that the most important decision was where to put the code. Then, and only then, could you decide what the code should be, as positioning determined exactly what the code should be in many cases.

    I will have to have another look at lwIP -- the latest appears to be V 1.41

    Available here: http://savannah.nongnu.org/projects/lwip/

    Look here first for documentation:

    http://lwip.wikia.com/wiki/LwIP_Wiki

    A previous post with doc sources...

    http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/471/t/152092.aspx

    A ggogle search on lwIP documentation turns up a lot -- but mostly not useful.

    Might be worth looking through what's available.

    Cheers.

  • Dave,

    I have been scouring the 'Net looking for help and have yet to find any that directly helps me. I am hoping TI will chime in soon.

    TI is in fact using LwIP V1.4.1.

    Thanks,

    Jeff

  • Jeff,

    Thank you for your patience, hopefully we can work through your issue.

    In what location or interrupt context are you making the lwip API calls.  It is important to note that lwip is not re-entrant, thus all calls must be done inside of the Ethernet interrupt handler to ensure that all calls come from the same context.  Calls to lwip APIs from main (or anywhere else) can cause mutexes or hangs similar to what you have described above. 

    For this reason, the lwip library includes a timer based interrupt event to support calls like you have mentioned.  It is serviced during every lwipEthernetIntHandler event.

    If you review the “enet_io” example application within the DK-TM4C129x directory of TivaWare2.0, you will find a function called lwIPHostTimerHandler() within "enet_io.c".

    In the case of your application, you would need to implement a handler like this, which would include all of your lwip API calls to ensure they are bounded within Ethernet handler context correctly.

    If you feel comfortable, please share as much of your source or code snippets as possible for us to review.

    Regards,
    Chris

                      

  • Chris,

    Thanks for the reply. Let me bring you up to date on what I have found since my initial post.

    I originally thought that there was an issue with the tcp_output( ) function not working. I looked through the code for that function and found it was checking to see if the passed-in pcb was the input pcb, and if it was the function just returned a good status. I commented out that check and it solved the problem of the UDP packets getting sent before the reply to the last TCP packet was sent. (This was described in my third post)

    I then had the issue of only being able to send a few UDP packets before I got errors. As it turns out, I was sending the UDP packets from within the context of the TCP receive callback. Yesterday I changed my code to simply set a flag in the TCP receive callback and send the UDP packets from the mainline "while forever" loop. After that, everything worked. I even removed my hack to the tcp_out( ) function and that worked as well.

    Getting back to your comments about the enet_io.c example, you said that "all calls must be done inside of the Ethernet interrupt handler". In looking at the lwIP interrupt handler, I see several calls that relate to finding an IP address. My interrupt handler has always been that way as well. The example then calls httpd_init( ) from the mainline which eventually calls several tcp functions.The tcp accept and receive functions are then handled by other functions within the httpd.c file. Are all of these functions within the context of the lwIP interrupt handler?

    So, in summary, things appear to be working now but I am not exactly following your rule about keeping all calls within the interrupt handler. Am I walking on thin ice or is my method acceptable? 

    Thanks,

    Jeff

  • Jeff,

     Its great to hear you got this functioning.

    Some exceptions to the recommendation are allowed for “init” type functions. However in cases where you have unpredictable TCP and UDP data traffic, staying confined to Ethernet interrupt context is a must.  From your last, it sounds like you are doing this with the exception of the UDP packets in the while-1.

    We actually have some example apps in TivaWare2.0 that don’t do this quite right, many of which are being fixed within the upcoming 2.1 release.

    In your case, it sounds like you are continuously streaming UDP packets.  You many never have an issue, however the recommendation is still valid.  It you run into issue in the future, you’ll know where to look first.

    Regards,
    Chris