LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

UDP Library, UDPRead packet loss

Hello together,

 

i send UDP Packets from a Xilinx Evaluation Board to the PC with a GBit NIC. In Wireshark (running on PC) i count 1008 packets with 1500 bytes each in 0.01234 seconds. So it is a throughput of about 980MBit. I want to detect and check these packets in CVI so i use the UDP Library. I have written a loop where UDPRead() is called and if a packet is recognized a counter increments. But the counter just shows a number between 330 and 430. So it "loses" about 60-70% of the packets. Is the UDP Library too slow? Is my code wrong? Is the PC too slow (even though i just increment a counter and don't yet compare the payload if it is correct)?

 

The code:


#include <userint.h>
#include "toolbox.h"
#include <udpsupp.h>
#include <ansi_c.h>
static int channel = 0;
 
void main(void)
{
 unsigned int port = 60101;
 int status = -1;
 char srcAddr[16];
 unsigned int srcPort,counter=0;
 int size = 0;
 unsigned char *msg = NULL;

 status = CreateUDPChannel (port, &channel);
 
 // wait for a UDP packet and count it

 while(1)
 {
  // Pass NULL as the input buffer to determine the size of the arrived data.
     size = UDPRead(channel, NULL, 0, UDP_DO_NOT_WAIT, NULL, NULL);

     msg = malloc(size);

     // Read the waiting message into the allocated buffer.
     size = UDPRead(channel, msg, size, UDP_DO_NOT_WAIT, &srcPort, srcAddr);
  
  // if a packet received, count it and send one packet
  if(msg)
  {
   counter++;
  }
  else{;}

 } 
 status = DisposeUDPChannel (channel);
}


 

regards Florian

0 Kudos
Message 1 of 11
(6,036 Views)

Update: I tried to send udp packets at a slower rate. 127 packets * 1500 bytes in 0.085578 s = 17.8 MBit/s (due to an error only 127 packets were sent). Now in the CVI programm all the 127 packets were counted. But after fixing the error and sending 1000 packets * 1500 bytes in  0.56344 seconds = 2.6 MBit/s only 982 packets were counted (wireshark detected all of them). 18 packets werent detected, even though the throughput was slower. Any suggestions?

0 Kudos
Message 2 of 11
(6,036 Views)

Just a guess: are you sure in your loop you are not reading more than one packet at a time? You effectively count the times the loop has read from UDP, but not the size of messages read. Try accumulating 'size' variable and see if it matches with the total packets effectively sent or with the counter.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 3 of 11
(6,031 Views)

from the CVI help:


Reads a single datagram from the UDP channel.

The function polls the channel port for data and retrieves the first available datagram. On success, the function returns the number of bytes read. The function never retrieves more than one datagram at a time; you must call the function exactly once for each datagram that arrives on the channel. When the function successfully reads a datagram, UDPRead also reports the sourcePort number and IP sourceAddress from which the datagram was sent.

If you pass 0 for inputBuffer or inputBufferSize, the function peeks at the port and returns the size of the first available datagram.

Note   Input buffering may or may not be provided and is handled by the system socket library. The UDP protocol provides no guarantee that datagrams will be delivered, but if you experience an excessive number of lost datagrams, try registering a UDP callback function to ensure that you read each datagram as soon as it is received.


i could assign a callback function with int CreateUDPChannelConfig (unsigned int localPort, const char *localAddr, unsigned int exclusive, UDPCallbackPtr callback, void *callbackData, unsigned int *channel);


callbackFunction UDP Callback Pointer Pointer to the callback function that processes messages associated with your UDP channel. Events are sent synchronously to the callback function.

The callback function must have the following form:

int CVICALLBACK UDPCallback (unsigned channel, int eventType, int errCode, void *callbackData);

channel specifies the channel that received the event.

eventType specifies the type of event that occurred:

  •  
    • UDP_DATAREADY indicates that a datagram has arrived on the channel's port and is waiting to be read. Your program must call UDPRead to obtain the data.
Note    This event is received once per datagram that arrives.
errCode indicates the error, if any, associated with the event.

callbackData contains the data that was registered with the callback


But in the loop over UDPRead() i dont do anything else, so how to improve performance. I will give a try with the callback.

0 Kudos
Message 4 of 11
(6,029 Views)

I don't get the version with callback function to run. I adapt the CVI UDPReader example. Is it correct to just have a while(1); in main to just wait until a callback is received?

 


int CVICALLBACK UDPCallback (unsigned channel, int eventType, int errCode, void *callbackData);

static int ReaderChannel = 0;
unsigned int counter = 0, countError = 0;
char srcAddr[16];
unsigned int srcPort;

 

void main(void)
{
 unsigned int port = 60101;
 int status = -1;
 status = CreateUDPChannelConfig (port, "192.168.1.1", 1, UDPCallback, NULL, &ReaderChannel);

  
 // wait for a UDP packet and count it.
 while(1)
 {;} 
 status = DisposeUDPChannel (ReaderChannel);
}

 

int CVICALLBACK UDPCallback (unsigned channel, int eventType, int errCode, void *callbackData)
{          
    int             error = 0,
                    size;
    unsigned char *msg = NULL;
   
    if (eventType == UDP_DATAREADY)
    {
        // Pass NULL as the input buffer to determine the size of the arrived data.
        size = UDPRead(channel, NULL, 0, UDP_DO_NOT_WAIT, NULL, NULL);
       
        msg = malloc(size);
       
        // Read the waiting reply message.
        size = UDPRead(channel, msg, size, UDP_DO_NOT_WAIT, &srcPort, srcAddr);;
     if(size == 1458)
  {
   counter++;
  }
  else
  {
   countError++;
  }
    }
 return 0;
}


 

The callback function never gets invoked (have set a breakpoint). What am i doing wrong?

0 Kudos
Message 5 of 11
(6,018 Views)

I suppose you are not processing events inside your loop so the callback is not called. Try with

 

while (1) {

  ProcessSystemEvents ();

}

 

This will permit you also to detect an event that makes you exit the loop.

Additionally, malloc-ing memory without freeing it is a potential problems as you are continuously consuming resources and never releasing them. It can work for small tests but is to be absolutely avoided in real program.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 6 of 11
(6,014 Views)

Thank you for your reply. I have found the solution at the same time.

Now it works. I saw that the function  RunUserInterface(); is invoked in the sample main. I used this command instead of while(1);. The callback function gets now invoked. But the problem is the same. I ran 3 tests with high speed at about 980MBit/s and the counter had values of 124, 145 and 132 (1000 packets were sent and monitored in wireshark).

At a rate of 21 MBit/s the counter had the value 969 (of 1000 packets).

As you can see in the code i check the received size, if it fits 1458 bytes (payload of my udp packet) the counter gets incremented, else an error counter gets incremented. in all tests the errorcounter was 0.

 

As mentioned in the CVI help "Note   Input buffering may or may not be provided and is handled by the system socket library. The UDP protocol provides no guarantee that datagrams will be delivered, but if you experience an excessive number of lost datagrams, try registering a UDP callback function to ensure that you read each datagram as soon as it is received." i tried to use the callback function but it doesn't improve the data loss.

 

So i guess its the library which lacks in performance.

 

edit: You are right with freeing buffers, but for this test purpose i dont mind.

0 Kudos
Message 7 of 11
(6,009 Views)

Yes, using RunUserInterface () is a better mechanism than an endless loop Smiley Happy

 

Well, I really never used UDP so I cannot be of much help in this case Smiley Sad . I simply tried to highlight some general hints to improve system performance. Let's see if anybody more experienced than me can help.

 

In the meanwhile I would look at CVI sleep policy (Options >> Environment menu item), setting it to Do not sleep in case it is at a lower level.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 8 of 11
(5,995 Views)

I appreciate your help.

 

I changed the setting as you mentioned but no improvement. I also tried to shut down wireshark in case it interferes the ethernet traffic, also no improvement. 156 of 1000 packets counted.

0 Kudos
Message 9 of 11
(5,991 Views)

I realise you are only using malloc() in this way because it is a test, but it may be the case that it is slowing down your loop somewhat. As an experiment, try just using a static array instead and see if that makes any difference.

 

Having said that, I think you will have to jump through a few hoops to get the performance level up closer to 1000MB/s - for example I guess you are running in debug mode? Release mode will be quicker. You could read the data in a separate thread, where you can raise the priority. I haven't used the native CVI UDP functions, as I always write my own using the SDK, but is there the option of just using a single call to read the data and return the size at the same time, rather than making two calls? This is supported by the underlying sockets.

 

If there is one, a call to ProcessUDPEvents() (well, there is a ProcessTCPEvents() function, so this is only a guess!) might be a more efficient way of triggering UDP callbacks, if you want to use this method.

 

JR

0 Kudos
Message 10 of 11
(5,971 Views)