iMX8QM, UDP, and TorizonCore IDE

Let me begin by saying I’m likely missing something small, but I’m at the point of pulling my hair out so here we are.

Technical specs, and such:
Toradex Apalis iMX8QM V1.1 on Apalis Ixora V1.2 Carrier Board
Toardex version: 0037 V1.1E
Architecture: aarch64
Kernel 5.15.148-6.6.1
Distro Name and Version: TorizonCore 6.6.1-build.14

Ubuntu 22.04 LTS
VSCode with TorizonOS IDE

For simplicity of attempting to debug, I’ve created a fresh Qt QML CMake application, and have added 2 new files, a header and source to handle UDP communications. Simply, it binds to a socket, connects, and processes any incoming datagrams. This works perfectly fine in practice on my Windows machine, and on my Ubuntu machine. However, when I move towards testing on the hardware, I am running into trouble.

I believe when I attempt to bind to my socket, I am throwing an error that borks up the program.

Binding code below:

bool result;

    result = udpSocket6.bind(QHostAddress::AnyIPv4, 45454);

This returns a failed boolean value. This is immediately followed by two exceptions with unknown sources, but my general thought process is they will be resolved if I can bind this socket. (Yes, is the thrown twice).

"QLibProxyWrappe" hit Catchpoint 3 (exception thrown), 0x0000ffff97b926bc in __cxa_throw () from /lib/aarch64-linux-gnu/libstdc++.so.6
"QLibProxyWrappe" hit Catchpoint 3 (exception thrown), 0x0000ffff97b926bc in __cxa_throw () from /lib/aarch64-linux-gnu/libstdc++.so.6

My inclination is that the port may not be available, because I can’t see any reason IPv4 wouldn’t be. Any initial clues or places for me to start looking at this point?

Thanks in advance.

Hi, I’m the Toradex AI Assistant. I’m in early beta, and I would appreciate your feedback.
The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hello,

Given the details you’ve provided, it seems like the issue might be related to the network configuration or permissions on the Toradex Apalis iMX8QM module running TorizonCore. Here are a few steps and considerations to help troubleshoot and potentially resolve the UDP binding issue:

  1. Check Network Configuration: Ensure that the network configuration on the Toradex module allows for UDP communication. This includes verifying that the network interfaces are correctly configured and up.

  2. Verify Permissions: Running applications that bind to network ports typically require certain permissions. Ensure your application has the necessary permissions to bind to the UDP port. Running the application with elevated privileges (e.g., using sudo) for testing purposes can help determine if it’s a permission issue.

  3. Port Availability: Verify that the port 45454 is not already in use on the device. You can use the command netstat -an | grep 45454 or ss -an | grep 45454 on the device to check if the port is already bound by another process.

  4. Firewall/Security Policies: Although less common in embedded environments, ensure that there are no firewall rules or security policies in place that might be blocking UDP traffic on the specified port.

  5. SELinux/AppArmor: If SELinux or AppArmor is enabled and enforcing, it might be restricting the application’s ability to bind to the network port. Check the relevant logs (/var/log/audit/audit.log for SELinux, /var/log/syslog or /var/log/kern.log for AppArmor) for any denied operations that match your application’s attempts to bind to the port.

  6. Test with a Minimal Example: If not already done, try to test the UDP binding with a minimal C++ example outside of the Qt environment. This can help isolate whether the issue is related to Qt or the system/network configuration.

  7. Qt Network Configuration: Ensure that the Qt environment is correctly configured for cross-compilation and execution in the TorizonCore environment. This includes any Qt-specific network configuration that might be necessary.

  8. Debugging Output: Increase the verbosity of debugging output for both your application and the system’s network stack (if possible). This might provide more insights into what’s failing during the bind operation.

If after these steps the issue persists, it might be helpful to look into any known issues with the specific version of Qt you are using, especially regarding UDP socket communication on Linux-based platforms.

Please, also check if these links can help you solve your problem:

High performance, low power Embedded Computing Systems | Toradex Developer Center.

Greetings @tharper,

I’ll need further information regarding your setup to understand your situation more fully.

Could you share your entire code? Or at the least share a minimal standalone code that reproduces the same issue. I’ll need this to investigate further.

Also in your VSCode project did you make any other changes? For example did you add any additional packages, or modify any configurations in the project?

Best Regards,
Jeremias

Hi jeremias,

I can share some code, sure.

In response to the VSCode project, this is a completely fresh single container project from the C++ CMake Console App template.

Thanks for your time,
Tim

UDP_Question.zip (1.7 KB)

Alright using your code as a reference I created a more minimal program that isolates just the socket binding portion that we are concerned about:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <iostream>
#include <QObject>
#include <QQmlEngine>
#include <QHostAddress>
#include <QUdpSocket>
#include <QNetworkDatagram>

int main(int argc, char *argv[])
{
    QUdpSocket udpSocket6;
    bool result;
    result = udpSocket6.bind(QHostAddress::AnyIPv4, 45454);

    std::cout << std::boolalpha << "Socket binding: " << result <<  std::endl;

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    const QUrl url("qrc:/socket/QML/main.qml");
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);

    engine.load(url);

    std::cout << "Hello Torizon!" << std::endl;

    return app.exec();
}

Here you can see we just perform the socket binding operation similar to your code and read out the result. When I run this I get:

Socket binding: true

Which according to the QtAbstractSocket documentation means a success: QAbstractSocket Class | Qt Network 6.7.2

I also did not get any exceptions like you did. This suggests to me that the socket binding portion of your code is not problematic, as it seems to work in isolation as my example just showed.

It could be the surrounding parts of your code is causing your socket bind operation to fail for some reason. Though you probably understand how the rest of your code works in conjunction here better than I do.

I hope this at least helps narrow the possible root cause a bit.

Best Regards,
Jeremias

Jeremias,

Thanks a bunch for your input. I went back and found you’re right - I am binding correctly. I guess the logical ‘next question’ is identifying the IP address of the SoM. I gave it a static IP Address on ethernet0, and was attempting to send packets to that address, but upon further research, it looks like the exposed IP address of the SoM is actually the torizon_default bridge IP. If I’m totally off-base at this point, feel free to let me know.

Just going to toss an edit on this, I believe my initial thoughts for this were spurred by this post (albeit a while ago). I’m not really sure if this is still possible, as I don’t see the “Configurations” tab in my Torizon extension?

TH

That other post you’re referencing is using an old version of our IDE extension that worked quite differently.

In the current version of the extension you can make changes to your container configuration by directly modifying the docker-compose.yml file in your project. The syntax of the file is well-documented on the Docker website here: Overview | Docker Docs

Now on the topic of network. I’m not sure how familiar you are with how containers work in this regard but I’ll give a brief intro on the topic.

By default containers operate in their own isolated bridge network.This means networking inside the container can make outgoing connections to websites for example. But, it has no knowledge about the host networking stack. So it doesn’t know the module’s IP address for instance.

Now this is just the default configuration. You can poke holes in this bridge network to allow access to certain parts of the host network stack outside of the container. This ranges from mapping a port from inside the container to a port outside. For example you can map port 1000 in the container to port 1000 outside. In the extreme case you can just have the container adopt the host network’s entire network stack. This means all ports inside the container are the same as the ports outside. Even the IP address of the container is the exact same as the IP address of the module in this case.

Now what configuration is best depends on your specific use-case and needs. If you want to learn more about how networking with Docker containers work there is more detailed article from Docker here: Networking overview | Docker Docs

Best Regards,
Jeremias