6
votes

I am writing a Qt (5.6) application that communicates with an FPGA over UDP socket. Packets are being streamed to the PC at 2 KHz (all packets identical size, 1272 bytes). Wireshark shows that packets are being sent, and the UDP header is as expected. The problem is, the Qt UDP Socket that I am using is never receiving these packets. The readyRead signal is never called.

Here is a code snippet:

UdpConnection::UdpConnection(QObject* parent)
{
    fpgaConnection = QSharedPointer<QUdpSocket>(new QUdpSocket);

    qDebug() << connect(fpgaConnection.data(), &QUdpSocket::readyRead, this, &UdpConnection::readyRead);

    if (fpgaConnection->bind(QHostAddress("192.168.10.10"), 1920))
    {
        qDebug() << "Successfully Bound!";
    }
    else
    {
        qDebug() << "BINDING FAILURE";
    }

    fpgaConnection->connectToHost(QHostAddress("192.168.10.200"), 1919);

    sendArpRequest();
}

void UdpConnection::readyRead()
{
    while (fpgaConnection->hasPendingDatagrams())
    {
        QByteArray buffer;
        buffer.resize(fpgaConnection->pendingDatagramSize());

        QHostAddress sender;
        quint16 senderPort;

        fpgaConnection->readDatagram(buffer.data(), buffer.size(), &sender, &senderPort);
        qDebug() << "Message from:" << sender;
        qDebug() << "Message port:" << senderPort;
        qDebug() << buffer;
    }
}
  • UdpConnection is not running on a separate thread from main. Should it be?
  • I am binding successfully, and I would assume that "connectToHost" is working because I'm able to send a message to the remote host.
  • The application has been added to the Firewall exception list (again, the ARP handshake proves that they are capable of communicating).
  • The interface is a direct ethernet connection between the FPGA and a PC.

Why is Wireshark able to see these messages, but my program is not?

UPDATE #1 Wireshark has the 2KHz packets as LLC packets. The Ethernet Header shows a correct Destination (my MAC address), Source Address (hard coded in the FPGA), and Length. The IP header has the Source IP as 192.168.10.200 and the Destination IP as 192.168.10.10, UDP Header has Source Port as 1920 and Destination Port as 1919.

UPDATE #2 Wireshark logs: paste.ee/p/98c1H As you can see, the packet is repeated and sent from the FPGA at 2KHz. The ARP transmission and reply can be found as the 5th, 10th, and 11th packet.

UPDATE #3 The IP packets of the incoming packets have a correct checksum that is NOT being set to 0x0000.

3
Are the desired UDP packets actually being sent from 192.168.10.200:1920 to 192.168.10.10:1919? Can you show the actual UDP packet info from Wireshark? Do you receive the packets if you remove the call to connectToHost()?Remy Lebeau
@RemyLebeau Added in Update #1benny.bennett
If you replace the first argument to bind() with QHostAddress::AnyIPv4, and/or comment out the connectToHost() call, does that make any difference?Jeremy Friesner
Also, shouldn't the last argument to your connect() call be &UDPConnection::readyRead instead of &FPGA_HardwareInterface::readyRead ?Jeremy Friesner
The package you receive is just not a datagram as far as I know. Your size in the ethernet header should be the IPv4-Type followed by the IP-Frame followed by the UDP Header and your payload. Since the UDP Socket tries to interprete complete Datagrams its not giving you any signal to now read a new datagram.Sebastian Lange

3 Answers

1
votes

The packet seems not to be a valid UDP Datagram.

Edit:

After fiddling with the packet it seem to be enough to change the type in the ethernet header to to IPv4 (0x0800).

It does show a strange TTL with a value of 0, but that may be sender related.

Original Post:

Instead of your current data you should send like this for having a valid datagram:

Ethernet Headers w/ IPv4 (14Byte): (as in your implementation, but type IPv4 0x0800), Source, Dest, Type

64006a493488 020826283900 0800

IPv4-Headers (20Byte): Version, Other, Size=1298(0512) UDP + 20, Ident, Flags(0x00), FlagOffset(0), TTL(128), Protocol(17 UDP), Checksum, Source = .10.200, Dest = .10.10

45 00 0512 31f0 00 00 80 11 0000 c0a80ac8 c0a80a0a

UDP-Header (8Byte): Source=1919, Dest=1920, Length=1278(04fe) = Data + 8, Checksum 2Byte NOT CALCULATED in example!!!

077f 0780 003e 9672

DataPayload: 1270 Byte of raw data

0a9f....

Using this as datagram you actually should not use connectToHost() but use the writeDatagram() and now probably working by signal invoked readyRead() slot with hasPendingDatagrams() and readDatagram().

2
votes

I'm not too familiar with Qt but for BSD socket API, I usually use bind to set my receive port but don't use connect for UDP connection especially when using different ports like your 1919 vs 1920 For socket API, use sendto() for sending packets with the target IP/port.

So, try commenting out connectToHost and directly use writeDatagram when sending.

0
votes

Try with nc and verify packets receiving from FPGA

nc -lu 192.168.10.10 1920

If you got packets with nc, the problem is in your Qt code. You could try Qt::DirectConnection in the last (optional) argument of connect. maybe youre blocking current thread and program counter never reaches event loop anymore and thus no slots will be called actually.