µTasker Forum

µTasker Forum => NXPTM M522XX, KINETIS and i.MX RT => Topic started by: neil on January 06, 2009, 05:29:34 PM

Title: TCP Buffer
Post by: neil on January 06, 2009, 05:29:34 PM
Hi Mark,
  I have a tcp connection in which text is sent to my server application. I do the following:

void SendMessage(unsigned char *Ptr,int Length)
{
TCP_MESSAGE test_message;
uMemcpy((CHAR*)&test_message.ucTCP_Message,&Ptr[0], Length);
fnSendTCP(TCPsocket, (unsigned char *)&test_message.TCP_Header, Length, TCP_FLAG_PUSH);
}

which works fine when doing 1 SendMessage(..). But If there is another SendMessage() soon after, characters are lost. Is there a facility within utasker to have a buffer for sending data (so a few SendMessage() can simply fill the buffer)?

Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 06, 2009, 05:46:56 PM
Hi Neil

When using a simple TCP socket it is necessary to wait for an ACK to the previous frame before sending a second. If a second is sent before the ACK to the first has been received it can cause strange things (since sequence counters are not correct). i don't know exactly why characters are lost in your case but it may be a consequence of sending a second message too early and causing strange things to happen at the TCP level (?).

It would be possible to add a queue of multiple buffers and send the next only when the previous has been acked, but there is a also the buffered TCP method (as used by TELNET for debug output messages). See the following:
http://www.utasker.com/forum/index.php?topic=25.msg101#msg101
and also http://www.utasker.com/forum/index.php?topic=91.0

If you use a buffered TCP socket rather than a simple TCP socket it should help handling buffering for you (up to the buffer size). A "TELNET-like socket "
see http://www.utasker.com/forum/index.php?topic=25.msg106#msg106 is the most luxurious method since it should handle really everything for you.

Regards

Mark
Title: Re: TCP Buffer
Post by: neil on January 06, 2009, 06:00:32 PM
Hi Mark,
  Thanks, the buffering looks the best way.

I will be having a few TCP connections, and only one needs buffering . I assume there shouldnt be any problems doing this?

Neil
Title: Re: TCP Buffer
Post by: mark on January 06, 2009, 06:31:29 PM
Neil

Buffered TCP can be performed on a socket basis so can be mixed as required.

Regards

Mark
Title: Re: TCP Buffer
Post by: neil on January 07, 2009, 11:47:19 AM
Hi Mark,
   I cant seem to get anything sent using the buffer method.

My previous routine, had :
      uMemcpy((CHAR*)&test_message.ucTCP_Message,&Ptr[0], Length);
      fnSendTCP(TCPsocket, (unsigned char *)&test_message.TCP_Header, Length, TCP_FLAG_PUSH);

which works fine with 1 send. So I simply done the following with buffers , in its place:
in config.h:
            #define SUPPORT_PEER_WINDOW                                 
            #define WINDOWING_BUFFERS      4                             
            #define CONTROL_WINDOW_SIZE                                 

placed:
          #define USE_BUFFERED_TCP  outside USE_TELNET define, as not using TELNET.

commented out WAKE_BLOCKED_TCP_BUF, as will never reach 2800 bytes.
left TCP_BUFFER, and TCP_BUFFER_FRAME as default.

within callback placed:
case TCP_EVENT_PARTIAL_ACK: fnSendBufTCP(Socket, 0, usPortLen, TCP_BUF_NEXT);break;
case TCP_EVENT_ACK: fnSendBufTCP(Socket, 0, 0, TCP_BUF_NEXT);break;

and in place of previous fnSendTCP() and uMemcpy(), I placed:
      fnSendBufTCP(TCPsocket, (unsigned char *)&test_message, Length, (TCP_BUF_SEND | TCP_BUF_SEND_REPORT_COPY));      

but nothing gets sent to server.

Regards
Neil


Title: Re: TCP Buffer
Post by: mark on January 07, 2009, 02:56:54 PM
Hi Neil

I assume that the TCP connection is working correctly before you send the data.

Check that you have enough HEAP for the defined buffer. The following discusses this and indicates where to check in the code:
http://www.utasker.com/forum/index.php?topic=480.msg1905#msg1905

Regards

Mark

Title: Re: TCP Buffer
Post by: neil on January 07, 2009, 06:25:59 PM
Hi mark,
  If I replace the  fnSendBufTCP() with  uMemcpy() and   fnSendTCP(), then it works fine. I will have a look at the link to see the heap, but my application has approx set aside 5k of RAM for my code.

Neil
Title: Re: TCP Buffer
Post by: neil on January 08, 2009, 06:31:29 PM
Hi Mark,
  It looks like its a heap problem, the first uMalloc returns 0 in the fnSendBufTCP().

How is the RAM set aside in utasker ?
As the processors I am using has 32K, after the static is used for own global variables, and arrays, Is the rest not set aside for functions  that usethe memory, uMalloc for example?

just checked the fnHeapFree() functions etc . I got back
Free heap = 0x0810 from 0x4c00
Unused stack = 0x09db

Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 08, 2009, 06:57:58 PM
Hi Neil

See the following:

http://www.utasker.com/forum/index.php?topic=96.msg384#msg384
http://www.utasker.com/forum/index.php?topic=468.0

You can control the HEAP size with OUR_HEAP_SIZE (in config.h). Assuming you have enough free memory (to ensure that the CPU has adequate stack for its routines) you can increase this value to allow the TCP buffer to be set up.

Good luck

Regards

Mark

Title: Re: TCP Buffer
Post by: neil on January 08, 2009, 07:42:44 PM
Hi mark,
  My application uses approx 6k(after doing some reductions) ram , including in TxQueueSize/RxQueueSize for serial/II2 etc, and for global variables.

fnHeapFree()=2308
fnHeapAvailable()= 19456 bytes. leaves a lot from the available 32k for other use.

so this means 17148bytes of ram has been used, taking away my 6k approx, is 11148bytes used by utasker. Isnt this a lot for ustasker?

Regards
Neil

Title: Re: TCP Buffer
Post by: mark on January 08, 2009, 07:51:09 PM
Hi Neil

Don't forget to include Ethernet buffers, which uTasker also puts on HEAP:

Default:
#define NUMBER_OF_TX_BUFFERS_IN_ETHERNET_DEVICE         2                // allocate 2 buffers for transmission
#define NUMBER_OF_RX_BUFFERS_IN_ETHERNET_DEVICE         6                // allocate 6 (full) buffers for reception


which gives about 12k.

Otherwise uTasker probably uses only a couple of hundred bytes for task queues, timers etc.

Regards

Mark

Title: Re: TCP Buffer
Post by: neil on January 08, 2009, 08:02:44 PM
Hi Mark,
  12k is a lot for my application.  I assume this is buffers for all ethernet connections, I dont have ftp,TELNET  etc, only a few TCP and a UDP connection.

How can I work out how the 12k is split, so I can reduce this.

Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 08, 2009, 08:55:01 PM
Neil

These are physical buffers for Ethernet (shared by all sockets).

2 for transmission is necessary due to a slight problem in the chip. When 1 is used it tends to send the buffer twice since the controller sometimes recognizes the same buffer as waiting, even when it has just been send.

6 for reception is advisable so that the amount of reception overruns in kept to a minimum in busy networks (with lots of broadcast traffic). This has always given good results. This can be reduced (each buffer reduction saving 1.5k of SRAM) to 5, 4, or maybe 3 (NUMBER_OF_RX_BUFFERS_IN_ETHERNET_DEVICE in app_hw_m5223x.h). If the RAM is otherwise not needed (would otherwise not be used for important things) it is however best invested in Ethernet reception performance.

Regards

Mark
Title: Re: TCP Buffer
Post by: neil on January 08, 2009, 09:01:52 PM
Hi Mark,
 Thanks for that.

When you say physical buffers, do these buffers capture all traffic for the chip only in an interupt, then pass them to the relevant callback function?

There will be never that heavy traffic within the processor, so I think I can reduce it.

When traffic flows around the network, does the chip ethernet module filter out the traffic only for it, then pass it onto the buffers?


Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 08, 2009, 10:05:26 PM
Neil

The Ethernet controller works only with the MAC address.

It receives frames which are addressed to its MAC address and broadcast addresses (eg. ARP resolves and various other broadcast based things). In a busy network there tends to be a lot of broadcasts which have to be received, although they may not be relevant.

When programmed for promiscuous operation the Ethernet controller receive ALL frames, irrespective of the MAC address (usually only needed for monitoring functions but may also be needed for IPv6 - watered down in the form of multi-cast addressing).

Since the SW needs to look at all received Ethernet frames (to see whether relevant or to be discarded) this is a load for the CPU. If a busy network is passing say 5 fast broadcast frames, the CPU needs to look at them all. It probably can't do it as fast as the burst is arriving but the buffers ensure that all 5 are queued. If 6 uninteresting broadcast frames are queued and a valid frame for the address is received as 7th frame then the first received one must have been dealt with before the 7th is received (otherwise it is an overrun and gets lost). The more buffers you have, the more fast frame bursts can be queued without an overrun.

Note that the M5223x project has also an option called USE_MULTIPLE_BUFFERS.
This works slightly differently because it doesn't reserve say 6 full size frame (9k) buffers but instead a larger number of 256 byte buffers (36 x 256 = 9k in this example).
The difference is that 6 full size buffers can hold only 6 frames. The frames can be from 60bytes - often the case for fast broadcast frames - up to 1500 bytes in size, but one frame requires one buffer. After 6 fast small frames all buffers may get full.
36 x 256 byte buffers can hold up to 36 small (up to 256 byte) frames and so can better withstand a bombardment of small frames without an overrun. But, to receive long frames multiple buffers are required and the management of frames spread over multiple buffers (not necessarily contiguous in memory) is more difficult. To overcome the difficulty there is one 'extra' full size buffer (here some memory saving is lost again) which is used to piece the received frame fragment together into a linear buffer before being passed to the stack. This requires an extra copy which is also time consuming.

Although the multiple buffer technique can be useful in environments where lots of fast small frames are to be expected, the fact that it requires an extra 1k5 overhead (although the overall size can still be reduced) and the extra memory copy required means that the standard technique with 6 rx buffers tends to be preferred unless the SRAM restrictions call for a "maximum memory size reduction with highest tolerance to fast frame overrun" compromise.

Regards

Mark


Title: Re: TCP Buffer
Post by: neil on January 08, 2009, 10:24:00 PM
Hi Mark,
  Thanks for the reply.

So really, as we wont use much memory, the large buffers will help in dealing with promiscuous access to the chip. What happens if there is an overrun? Is the data simply not placed into the buffer, therefore lost, or does it wrap around to the start again? If it doesnt ovewrite any other parts in memory, then our code can handle it, and will resume reading the correct data when it settles down.

We have one application where no incoming connections are made, it only connects to our server, so there will be no promiscuous access to the chip. In this case it would be safe on lowering the buffer size(theres not much traffic sent/received here too)?
Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 09, 2009, 01:56:40 AM
Neil

A frame that can't be put to a buffer will be discarded by the Ethernet controller and lost. This is generally not serious since it will be repeated (higher layer protocol) but is is of course to keep loses as low as possible.

Regards

Mark
Title: Re: TCP Buffer
Post by: neil on January 09, 2009, 11:21:35 AM
Mark,
  I reduced NUMBER_OF_RX_BUFFERS_IN_ETHERNET_DEVICE to 4, to set aside more memory.  What margin is there for changing OUR_HEAP_SIZE?

umalloc doesnt have a memory problem when sending with buffers now. But I still cant get it to work. I am now at the stage at the above message on7th Jan 11.49.  If I simply change the fnSendBufTCP() with uMemcpy(..), and    fnSendTCP(..) then it works fine.

Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 09, 2009, 12:32:50 PM
Hi Neil

When OUT_HEAP_SIZE is increased its reserved area grows into the space which is open for use by the CPU stack. Therefore the value of fnStackFree() will tell you how much can be added to OUT_HEAP_SIZE.

I don't known why you can send with buffered TCP. I just checked the way that Telnet uses it and the options set in the demo project. In addition to your settings it uses SUPPORT_PEER_MSS and the define USE_TELNET (there is also a part of fnSendBufTCP() which optionally filters TELNET escape sequences). The various configurations should however be able to live without other bits but you may like to quickly set these two defines just to be sure. [I just checked removing SUPPORT_PEER_MSS and USE_TELNET from the function and TELNET still worked normally in the demo project]

fnSendBufTCP() essentially does this.
- memcpy() of user data to a local ring buffer
- fnSendTCP()

so at the end of the day just uses fnSendTCP() to actually send. You could set a break at the line
        if ((ssReturn = fnSendTCP(TCP_socket, ucTCP_data_buf, TxFrameSize, TCP_FLAG_PUSH)) > TxFrameSize) {
where the frame is finally sent to ensure that it is arriving there and doesn't have any unexpected values.

If you don't identify the problem I think it will be best to send me your config.h file and the code which is controlling the socket and sending the data.

Regards

Mark


Title: Re: TCP Buffer
Post by: neil on January 09, 2009, 01:26:00 PM
Mark,
  the value returned from fnStackFree(), is this never used? Does the system know how much stack is needed through all the functions, along with their variable space?

The fnStackFree() function returns 2519bytes, so would it be safe for me to add 2k of this to OUR_HEAP_SIZE? If I have one function that uses 2k of stack, and add a new function that uses 1k of stack, will fnStackFree() still return the same as no more extra memory is needed?

But if I create a new function that uses 2.5k of stack, then fnStackFree() will return 500bytes less?

Neil
Title: Re: TCP Buffer
Post by: mark on January 09, 2009, 02:31:57 PM
Neil

The space between the top of heap and the stack pointer is filled with a pattern (pattern defined by UNUSED_STACK_PATTERN in config.h - default 0x55) when the system starts.

The function fnStackFree() counts the number of bytes which still have the initialization pattern by starting at the top of HEAP and counting upwards until a value of != UNUSED_STACK_PATTERN is found. Since CPU stack grows down, the lower the stack is used, the less the unused space becomes. As long as this value remains positive it means that the CPU stack has never 'collided' with the HEAP and so represents a safety margin. Of course there may be some special cases where the value measured is not perfect but if the value is reviewed after the system has been running for some time and exercising as much code as possible the value should be stable and representative.

In your case it looks safe to add 2k of heap to the present configuration.

Also your other remarks are generally correct. Of course if you have 2 functions using 2k and 1k and use them both at the same time (one calling the other) it will result in 3k stack used, but otherwise only the largest stack user will really be the limiting case. Note that interrupts will use stack too so an interrupt of the 2k stack case will result in 2k + interrupt use, but this is generally only a small addition.

Regards

Mark
Title: Re: TCP Buffer
Post by: neil on January 09, 2009, 05:32:15 PM
Hi Mark,
  I have attached the config.h and a txt document showing the callback function along with how I call the send functions.

When I use fnSendTCP(..) I comment out the send in TCP_EVENT_ACK and TCP_EVENT_PARTIAL_ACK, and the fnSendBufTCP(..) command. And works fine.
When I use the fnSendBufTCP(..) and comment out fnSendTCP(..) doesnt work.

Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 09, 2009, 07:09:56 PM
Hi Neil

I am sorry but I am having difficulties to identify why you are having problems. With my tests I can't reproduce a problem with the same settings and the listener shouldn't actually have any influence on the transmission of the first packet.

Have you verified using Wireshark that nothing is physically being sent (maybe you see that something unexpected is being sent which may help to explain something?)

In Telnet.c you can also find a good example for the handling of listner events (not a problem at this stage). See fnTELNETListener().

For example, the best way to handle acks is:


        if (fnSendBufTCP(Socket, 0, 0, TCP_BUF_NEXT) != 0) {               // send next buffered (if waiting)
            return(APP_SENT_DATA);                                     // mark that data has been transmitted
        }


This will avoid TCP from unnecessarily sending additional ACKs.

The regenerate can also be used to kick of waiting messages like this, improving efficiency in repetition case:

    case TCP_EVENT_REGENERATE:
        if (fnSendBufTCP(Socket, 0, 0, TCP_BUF_REP) != 0) {              // repeat send buffered
  #ifdef SUPPORT_PEER_WINDOW
            fnSendBufTCP(Socket, 0, 0, (TCP_BUF_NEXT | TCP_BUF_KICK_NEXT)); // kick off any following data as long as windowing allows it
  #endif
            return APP_SENT_DATA;
        }
        break;



Since I can't work out what is happening in your case I think that we will need to debug the routine fnSendBufTCP() to find out what it is doing wrong. At the moment I have run out of ideas why it should not transmit something when called.
Could you step into the code and see whether you identify something unusual? It should simply copy the passed data to its own buffer and call fnSendTCP(). If it gets this far it is not actually doing anything differently to your other working case.

If you don't identify what is happening, can you give me a time when we can skype and debug in parallel?

Thanks

regards

Mark
Title: Re: TCP Buffer
Post by: neil on January 09, 2009, 07:18:23 PM
Hi Mark,
  Thanks for the reply. I will do what you suggest, and will let you know of the results.

Regards
Neil
Title: Re: TCP Buffer
Post by: neil on January 10, 2009, 04:33:09 PM
Hi Mark,
  I couldnt get it to work, the debugger kept freezing. So I re-installed a new utasker, and now seems to work.

After the memory gets allocated for the send buffer on the first buffer send, does it get freed again?
Does this feature use any more memory apart from the umalloc() of the send buffer?

I want to make sure I am correct, I added the following in the callback:

    case TCP_EVENT_ACK:       
     if (fnSendBufTCP(Socket, 0, 0, TCP_BUF_NEXT)) {               
            return APP_SENT_DATA;                                   
        }
      break;
   
    case TCP_EVENT_ARP_RESOLUTION_FAILED:
        break;
    case TCP_EVENT_PARTIAL_ACK:
        if (fnSendBufTCP(Socket, 0, 0, TCP_BUF_REP)) {                   // repeat send buffered
  #ifdef SUPPORT_PEER_WINDOW
            fnSendBufTCP(Socket, 0, 0, (TCP_BUF_NEXT | TCP_BUF_KICK_NEXT)); // kick off any following data as long as windowing allows it
  #endif
            return APP_SENT_DATA;
        }
       break;
    case TCP_EVENT_REGENERATE:
       break;

I dont have telit defined, and have #define SUPPORT_PEER_WINDOW , and #define USE_BUFFERED_TCP outside the #ifdef USE_TELNET.


Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 10, 2009, 08:28:10 PM
Hi Neil

I am glad that it worked after the re-install.
The TCP buffer is allocated once, the first time it is used. It is never freed and the size doesn't grown. It uses only a few extra bytes bytes in the socket structure to manage the buffer but this is negligible in comparison to the buffer size.
The listener also looks good.

Regards

Mark
Title: Re: TCP Buffer
Post by: neil on January 10, 2009, 08:33:23 PM
Hi Mark,
  If using fnSendBufTCP() with multiple sockets, I assume the buffer size doesnt increase?

Regards
Neil

Title: Re: TCP Buffer
Post by: mark on January 10, 2009, 08:54:12 PM
Hi Neil

When using on multiple sockets, each socket using fnSendBufTCP() requires its own buffer!!

Therefore increasing socket number in this case does increase memory use (and quite dramatically if the buffer is large).
This is unavoidable since each connection will need its own personal buffer to work with.

Since debug type output doesn't really need multiple sockets this shouldn't be an issue.

Other sockets which doesn't use fnSendBufTCP() do not need a buffer and so doesn't use additional memory.

Regards

Mark
Title: Re: TCP Buffer
Post by: neil on January 21, 2009, 12:11:10 PM
Hi mark,
    As my application wont be sending massive TCP data (when using fnSendBufTCP), probably amout 500 bytes a time, so if I change TCP_BUFFER to 700, then this will allow 4 TCP sockets to use fnSendBufTCP() with a max buffer of 700. Is this correct? And if so , is there much other memory overhead?

Also, TCP_BUFFER_FRAME does this make sense in having this larger than TCP_BUFFER value? If I can do the above, then reducing this to the same, will it save RAM?

Is TCP_BUFFER_FRAME used per socket, or for all sockets?

Regards
Neil
Title: Re: TCP Buffer
Post by: mark on January 21, 2009, 02:42:54 PM
Hi Neil

Each socket configured for buffer operation will have a structure of type TCP_TX_BUFFER. This contains a local buffer unsigned char  ucTCP_tx[TCP_BUFFER]; This is its own ring buffer used for buffered streaming. The structure TCP_TX_BUFFER is created on heap when the socket is actually used the first time (until used it will not have the memory).
This means that when 4 sockets are used there will be 4 TCP_TX_BUFFER structures (each with TCP_BUFFER buffer space) - [4 x TCP_BUFFER buffer memory will be used]. In your configuration there will be 4 x 700 bytes allocated for buffer use by the 4 sockets (when all are actually used).

TCP_BUFFER_FRAME is the largest TCP frame that will be send. This is temporary memory (on stack when the TCP frame is constructed). It is used to copy the buffered data from the ring buffer (if in TELNET mode it may also do some filtering or control character stuffing if in ASCII mode) to the TCP frame buffer which is then sent. You are right that it doesn't need to be larger than the buffer size since it will never need to build a frame of larger than a buffer length of data. It can also be smaller than a buffer (logical since its maximum size if about 1500 and a buffer can be several kbytes). The restriction is however more useful in systems where the maximum LAN buffer is reduced (in small systems where thsi saves memory space) so that the TCP layer doesn't try to build a frame which is too large to fit in the LAN buffer space.

Since TCP_BUFFER_FRAME doesn't belong to a socket it is shared by all. However this is stack memory (normal subroutine operation) and so as long as you have enough free stack it is not that critical.

Regards

Mark


Title: Re: TCP Buffer
Post by: neil on February 02, 2009, 11:01:52 AM
Hi Mark,
 I use fnSendBufTCP() to send info, how to I flush the buffer it uses?

Neil
Title: Re: TCP Buffer
Post by: mark on February 02, 2009, 11:45:53 AM
Hi Neil

The buffer is flushed when a connection is closed (see fnResetWindowing() in tcp.c).

It shouldn't be necessary to flush it at any other time - and also quite complicated since it may be used for TCP activity. Closing a connection should therefore be the best method.

Regards

Mark

Title: Re: TCP Buffer
Post by: neil on February 02, 2009, 07:46:57 PM
Hi Mark,
 I am having problems when using fnSendBufTCP(), the processor locks up. I am having problems debugging it as you described, but looked at my code and looks fine. As I am not to sure on how the callback function works with partial acks etc, can you let me know if okay?.

 Here is a copy of my callback function. There is only about 100 characters at a time being sent (will be more when I get it working) and have the following defines:
    #define TCP_BUFFER                2800                               // size of TCP buffer (with USE_BUFFERED_TCP) - generous with M5223X
    #define TCP_BUFFER_FRAME          1400                               // allow this max. TCP frame size
  #define SUPPORT_PEER_WINDOW                                  // respect peer's Open Window when sending TCP frames
        #define WINDOWING_BUFFERS      4                             // we can send 4 frames before requiring ACKs
         #define CONTROL_WINDOW_SIZE     

And the callback function..
  its the TCP_EVENT_ACK and TCP_EVENT_PARTIAL_ACK im not sure about..

int fnTCP(USOCKET Socket, unsigned char ucEvent, unsigned char *ucIp_Data, unsigned short usPortLen)
{
   TCP_MESSAGE test_message;
   unsigned char Value;
   int Loop;
    
    switch (ucEvent) {
    case TCP_EVENT_CONNECTED:
                Diagnostic_TCPSocket.Diagnostics=1;
                ConnectionInfo.DiagHeartbeat=3; //gets decreased in seconds, then send heartbeat to app.
                   break;
    case TCP_EVENT_CLOSE:
      
    case TCP_EVENT_CONREQ:  break;                                           
   
    case TCP_EVENT_ACK:       
     if (fnSendBufTCP(Socket, 0, 0, TCP_BUF_NEXT)) {                  // send next buffered (if waiting)
            return APP_SENT_DATA;                                     // mark that data has been transmitted
        }
      break;
   
    case TCP_EVENT_ARP_RESOLUTION_FAILED:
        break;
    case TCP_EVENT_PARTIAL_ACK:
        if (fnSendBufTCP(Socket, 0, 0, TCP_BUF_REP)) {                   // repeat send buffered
  #ifdef SUPPORT_PEER_WINDOW
            fnSendBufTCP(Socket, 0, 0, (TCP_BUF_NEXT | TCP_BUF_KICK_NEXT)); // kick off any following data as long as windowing allows it
  #endif
            return APP_SENT_DATA;
       }
       break;
    case TCP_EVENT_REGENERATE:
       break;
    case TCP_EVENT_DATA:
                   for(Loop=0;Loop<usPortLen;Loop++)
                   {
                      Value=ucIp_Data[Loop];
                     .. save in buffer here...
                   }
                    break;
    case TCP_EVENT_ABORT:
    case TCP_EVENT_CLOSED:
      Diagnostic_TCPSocket.Diagnostics=0;
      fnTCP_close(Socket);
        break;
        }

    return APP_ACCEPT;
}

Regards
Neil
Title: Re: TCP Buffer
Post by: mark on February 02, 2009, 09:24:38 PM
Hi Neil

You can also use fnTELNETListener() in telnet.c as a reference. This also using buffered TCP.

This is the partial ACK handling that it performs:

#ifdef SUPPORT_PEER_WINDOW
    case TCP_EVENT_PARTIAL_ACK:                                          // possible ack to a part of a transmission received
        if (TELNET_session->wakeOnAck) {
            uTaskerStateChange(TELNET_session->wakeOnAck, UTASKER_ACTIVATE); // wake application so that it can continue with queued receive data
        }

        if (fnSendBufTCP(Socket, 0, usPortLen, TCP_BUF_NEXT)) {          // send next buffered (if waiting)
            return APP_SENT_DATA;
        }
        break;
#endif



I think that your use in this case is incorrect (it is the code from the regenerate case). This means that it tries to resent the last frame rather continuing with next chunks from the buffer.

Regards

Mark
Title: Re: TCP Buffer
Post by: neil on February 02, 2009, 10:20:33 PM
Hi Mark,
 
I see the 'TCP_EVENT_PARTIAL_ACK' , 'TCP_EVENT_ACK' and 'TCP_EVENT_REGENERATE' is used , but these use the Telit structure, and also a task is state is changed uTaskerStateChange(..).

What do I add in their place as Im not using Telit, and only buffers?  Also if I have to add the uTaskerStateChange(..) what task is it effecting?

Neil
Title: Re: TCP Buffer
Post by: mark on February 02, 2009, 11:10:28 PM
Hi Neil

You can ignore the Telnet session specific things. Just look at the way that it interacts with fnSendBufTCP(). The rest is 'application' (in this case Telnet) specific.

Eg. in the partial ack case simple do

        if (fnSendBufTCP(Socket, 0, usPortLen, TCP_BUF_NEXT)) {          // send next buffered (if waiting)
            return APP_SENT_DATA;
        }


In the ACK case, just

        if (fnSendBufTCP(Socket, 0, 0, TCP_BUF_NEXT)) {                  // send next buffered (if waiting)
            iReturn = APP_SENT_DATA;                                     // mark that data has been transmitted
        }


In the regenerate case you can copy all of it.

Of course you can also add your own application specific things as well if it makes sense but probably not for your case.

Regards

Mark

Title: Re: TCP Buffer
Post by: neil on February 02, 2009, 11:30:20 PM
Hi Mark,
  Thanks for that, Im just not familiar with these low level tcp sequences.

Regards

Neil
Title: Re: TCP Buffer
Post by: neil on February 02, 2009, 11:53:10 PM
Hi Mark,
  I noticed that the
case TCP_EVENT_PARTIAL_ACK: 

 in telnet has the following around it:

#ifdef SUPPORT_PEER_WINDOW

is it best to have this in my call back too?

Regards
Neil
Title: Re: TCP Buffer
Post by: mark on February 03, 2009, 12:23:55 AM
Hi Neil

When working with windowing the peer's TCP Windows should generally be respected - if the peer is slow and you are sending a lot of data quickly it would otherwise be possible to close its receive window and then over run it. With the small amounts of data you are sending it will never actually happen (unless the receiver is a very weak device with small memory buffer  - eg. an 8-bit micro with only 1k of receiver space). But I would enable it since it hardly has any extra overhead and then it fully respects TCP operation.

Regards

Mark