NI Linux Real-Time Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Raw packets support in LabView RT

Hello,

I am trying to develop a .so library in C to send raw packets with a cRIO 9035 under LabView RT. In principle, it should be possible by using the socket.h Linux library. So far, I manage to create the IPv4 socket with the following code:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#include <linux/if_packet.h>

#include <linux/if_ether.h>

#include <linux/if_arp.h>

int create_ipv4_socket(void){

     int connection_id;

     connection_id = socket(AF_INET, SOCK_STREAM,0);

     return connectio_id;

}

Having downloaded it to the cRIO and using a simple VI with Call Library Function Node, I get a result bigger than 0 (result ok). The problem is that I would like to send/receive raw packets (no IP protocol) but it is not working for me. Reading the Linux Socket library documentation, this should be possible by using the previous code but modyfing the socket creation sentence:

connection_id = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

With this sentence I get a result of -1 which means that there is some problem. I tried different combinations but again same result. I am wondering if this part of the library might not be compatible with the LabView RT. If so, I would like to know if it might be some workaround.

I hope that someone can provide some feedback on that.

Thank you in advance,

Carlos

0 Kudos
Message 1 of 9
(5,365 Views)

You are getting: -EPERM

#define EPERM            1      /* Operation not permitted */

You need to give the binary that is loading your library permission.

setcap "CAP_NET_RAW+ep" /path/to/bin

Message 2 of 9
(4,814 Views)

The binary in this case would be the LabVIEW RT binary at '/usr/local/natinst/labview/lvrt'.

Be careful not to wipe the existing capabilities in the process otherwise various things in LabVIEW RT will stop working. You can use the 'getcap' utility to get the current set of capabilities and add them to the 'setcap' command.

e.g.

Using the 2015 software stack:

# getcap  /usr/local/natinst/labview/lvrt

lvrt = cap_net_bind_service,cap_ipc_lock,cap_sys_rawio,cap_sys_boot,cap_sys_nice,cap_sys_time+ep

and then

# setcap "cap_net_bind_service,cap_ipc_lock,cap_sys_rawio,cap_sys_boot,cap_sys_nice,cap_sys_time,cap_net_raw+ep" /usr/local/natinst/labview/lvrt

Message 3 of 9
(4,814 Views)

Thanks for you support. This solved my problem and now I can send/receive raw packets from the corresponding interface but I am facing problems to get the timestamps.

It fails at the configuration stage so it makes me think that there is something else I would need to enable in the sofware stack but I do not know what.

The configuration I am trying to set up is:

connection_id = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

if(connection_id < 0){

     perror("ERROR opening socket");

     return connection_id;

}


flags = 1;

result = setsockopt(connection_id, SOL_PACKET, SO_TIMESTAMP, &flags, (socklen_t)sizeof(flags));  

Socket is correctly created but the result of the setsockopt is always -1.

In fact, my objective is to get tx and rx timestamp from hardware and I was trying the following:

flags = SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE;

result = setsockopt(connection_id, SOL_PACKET, SO_TIMESTAMP, &flags, (socklen_t)sizeof(flags));   

But it is also failing. From what I read the hardware and tx timestamp might not be supported by the driver. Thats is why I am trying a much simple configuration but without any success.

I would appreciate if you can provide your feedback on that!

0 Kudos
Message 4 of 9
(4,814 Views)

One thing that you could use to help determine the cause of the failure is to use the errno functionality that socket operations (as well as pretty much anything in the standard C library or part of the POSIX standard). See the manual page on errno

0 Kudos
Message 5 of 9
(4,814 Views)

Doing some quick digging, it seems that even software timestamping requires the kernel module for your network interface to support it. See: http://comments.gmane.org/gmane.linux.network/171376 . What controller are you using? I see that you're using a 9035 (thanks gratian.crisan), which I think uses the igb intel driver. Can you verify by posting the results of running "lsmod" from the console?

0 Kudos
Message 6 of 9
(4,814 Views)

Finally I solved by changing SOL_PACKET by SOL_SOCKET:

flags = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;

    result = setsockopt(connection_id, SOL_SOCKET, SO_TIMESTAMPING, (char *)&flags, (socklen_t)sizeof(flags));

But I still have the problem wiht the HW timestamp.The results of running "lsmod" is the following:

cRIO 9035 lsmod.PNG

0 Kudos
Message 7 of 9
(4,814 Views)

So, the driver is the igb driver. From a quick check of the code, it seems that the igb driver supports hardware timestamping, so long as the underlying hardware supports it. From the 9030 that I have on my desk, it seems that the controller's using an Intel i210 gbe controller, which is supported by the driver.

I'd take a look at https://www.kernel.org/doc/Documentation/networking/timestamping/timestamping.c from the kernel source itself (in the documentation folder, showing how to work with the network timestamping system), and use the errno functionality to see why things fail.

0 Kudos
Message 8 of 9
(4,814 Views)

If you want to get the HW timestamp, you must call the ioctl(sock, SIOCSHWTSTAMP, &hwtstam) to open the timestamp mode.

I have do some test about the https://www.kernel.org/doc/Documentation/networking/timestamping/timestamping.c, it can work well, you can reference it to write your code.

My test steps:

1. Modify the source code to compile it as a dynamic library.

2. Add HW timestamp log in igb driver

3. Call library node to get TX HW timestamp in LabView vi,

Message 9 of 9
(4,814 Views)