Receive real-time UDP packets with QNX RTOS

I have a source that sends UDP packets at 819.2 Hz (~ 1.2 ms) to my QNX Neutrino machine. I want to receive and process these messages with minimal delay and jitter.

My first code was basically:

SetupUDPSocket(); while (true) { recv(socket, buffer, BufferSize, MSG_WAITALL); // blocks until whole packet is received processPacket(buffer); } 

The problem is that recv () only checks for every tick of the system timer if there is a new package. The timer is usually 1 ms. So, if I use this, I get a huge jitter because I process the packet every 1 ms or every 2 ms. I could reset the size of the timer ticks, but that would affect the whole system (and other timers of other processes, etc.). And I will still tremble, because I will definitely never exactly correspond to 819.2 Hz.

So, I tried to use the network card interrupt line (5). But it looks like there are other things that make interruption grow. I used the following code:

 ThreadCtl(_NTO_TCTL_IO, 0); SIGEV_INTR_INIT(&event); iID = InterruptAttachEvent(IRQ5, &event, _NTO_INTR_FLAGS_TRK_MSK); while(true) { if (InterruptWait(0, NULL) == -1) { std::cerr << "errno: " << errno << std::endl; } length = recv(socket, buffer, bufferSize, 0); // non-blocking this time LogTimeAndLength(); InterruptUnmask(IRQ5, iID; } 

This results in the only successful read at the beginning, followed by a read with a length of 0 bytes after passing 0 time. It seems that after InterruptUnmask (), InterruptWait () does not wait at all, so there should already be a new interrupt (or the same ?!).

Is it possible to do something similar with a network card interrupt line? Are there any other options for receiving packets at 819.2 Hz?

Some network card information: pci -vvv outputs:

 Class = Network (Ethernet) Vendor ID = 8086h, Intel Corporation Device ID = 107ch, 82541PI Gigabit Ethernet Controller PCI index = 0h Class Codes = 020000h Revision ID = 5h Bus number = 4 Device number = 15 Function num = 0 Status Reg = 230h Command Reg = 17h I/O space access enabled Memory space access enabled Bus Master enabled Special Cycle operations ignored Memory Write and Invalidate enabled Palette Snooping disabled Parity Error Response disabled Data/Address stepping disabled SERR# driver disabled Fast back-to-back transactions to different agents disabled Header type = 0h Single-function BIST = 0h Build-in-self-test not supported Latency Timer = 40h Cache Line Size= 8h un-cacheable PCI Mem Address = febc0000h 32bit length 131072 enabled PCI Mem Address = feba0000h 32bit length 131072 enabled PCI IO Address = ec00h length 64 enabled Subsystem Vendor ID = 8086h Subsystem ID = 1376h PCI Expansion ROM = feb80000h length 131072 disabled Max Lat = 0ns Min Gnt = 255ns PCI Int Pin = INT A Interrupt line = 5 CPU Interrupt = 5h Capabilities Pointer = dch Capability ID = 1h - Power Management Capabilities = c822h - 28002000h Capability ID = 7h - PCI-X Capabilities = 2h - 400000h Device Dependent Registers: 0x040: 0000 0000 0000 0000 0000 0000 0000 0000 ... 0x0d0: 0000 0000 0000 0000 0000 0000 01e4 22c8 0x0e0: 0020 0028 0700 0200 0000 4000 0000 0000 0x0f0: 0500 8000 0000 0000 0000 0000 0000 0000 

and 'nicinfo':

 wm1: INTEL 82544 Gigabit (Copper) Ethernet Controller Physical Node ID ........................... 000E0C C5F6DD Current Physical Node ID ................... 000E0C C5F6DD Current Operation Rate ..................... 100.00 Mb/s full-duplex Active Interface Type ...................... MII Active PHY address ....................... 0 Maximum Transmittable data Unit ............ 1500 Maximum Receivable data Unit ............... 0 Hardware Interrupt ......................... 0x5 Memory Aperture ............................ 0xfebc0000 - 0xfebdffff Promiscuous Mode ........................... Off Multicast Support .......................... Enabled 

Thanks for reading!

+8
c ++ interrupt udp real-time qnx
source share
4 answers

I don’t quite understand why the statement β€œThe problem is that recv () only checks for every tick timer of the system if there is a new package available. The tick timer is usually 1 ms.” will be true for proactive OS. There should be something in the system configuration or there are some problems in the implementation of the network protocol stack.

A few years ago, when I was working on some IPTV STB project for Yahoo BB Japan, I had a problem getting RTP. The problems are not latency or jitter, but the overall system performance in STB after adding some NDS algorithm. We use vxWorks, and vxWorks supports an Ethernet interface interface that will be called every time the Ethernet driver receives an ethernet packet.

I connect the API to it and simply parse UDP with the specified port from ethernet packets directly. Of course, we have the assumption that there is no fragmentation, which is guaranteed by the network setup for performance problems. Perhaps you can also check if you can get the same hook in the Ethernet QNX driver. On rent, you found out if the driver was shaking or not.

+1
source share

How big are your UDP packets? If the packet size is small, you will get more efficiency by packing more data in one packet and reducing the transmission speed.

0
source share

I suspect that the interrupt service routing (ISR) does not mask the interrupt. It may be designed for edge sensitivity, and interruption is level sensitive.

0
source share

Sorry, I'm a little late to the party, but I stumbled upon your question and saw that this looked like the situation I was facing. Instead of hardware interrupts, you can try interrupting software using signals. QNX has documentation: http://www.qnx.com/developers/docs/qnx_4.25_docs/qnx4/sysarch/microkernel.html#IPCSIGNALS . I used CentOS at the time, but the theory is the same. According to http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/lib_ref/s/socket.html you can use ioctl () to configure the receive group for the SIGIO signal for this file descriptor ... in your case for UDP sockets. When the socket has data ready to be read, a SIGIO signal is sent to the process specified by ioctl (). Use sigaction () to tell the OS which signal processing function to use. In your case, the signal handler can read data from the socket and store it in the buffer for processing. Use pause () to pause the process until it processes the SIGIO signal. When the signal handler returns, the process wakes up and you can process the data in the buffer. This should allow you to process your data as it arrives, without the need for timers or hardware interrupts. One thing to keep in mind is that your system can process these signals as fast as UDP traffic arrives.

0
source share

All Articles