1

I'm trying to use netlink sockets in a pthread. I googled some examples and most of them use the following pattern to identify a "local" end of the socket:

struct sockaddr_nl  local = {};
local.nl_family = AF_NETLINK;
local.nl_pid = pthread_self() << 16 | getpid();
...
ret = bind(fd, (struct sockaddr*)&local, sizeof(local));
...

As I understand, normally when a netlink socket is opened per process, nl_pid is set to 0 and the kernel would pick the right portid. However it is not true for netlink-per-thread case, where PID value will be shared among all threads.

Besides I think pthread_self() << 16 | getpid() is not portable. What is the right way to set nl_pid in this case?

Mark
  • 6,052
  • 8
  • 61
  • 129
  • After some research and further considerations, I'm coming to conclusion that it is better to leave nl_pid to be automatically assigned by the kernel. In Linux a file descriptor table exists per process, so even if the netlink socket is opened in thread, the kernel will establish communication with the process. I think the only way for threads to distinguish data is via `struct nlmsghdr`'s `nlmsg_seq` field. – Mark Aug 18 '20 at 15:30
  • How about using gettid()? – user253751 Aug 19 '20 at 15:29

1 Answers1

1

As I understand, normally when a netlink socket is opened per process, nl_pid is set to 0 and the kernel would pick the right portid. However it is not true for netlink-per-thread case, where PID value will be shared among all threads.

There is no "the right" portid. Identification of portids with process ids is a convention, consistent with the kernel's default behavior when it assigns the portid, not a rule. Applications, whether single- or multi-threaded, are free to request arbitrary port ids within the allowed range of port ids.

Moreover, when a process, whether single- or multi-threaded, binds multiple netlink sockets and delegates portid selection to the kernel, the kernel can be relied upon to assign a unique portid to each.

Besides I think pthread_self() << 16 | getpid() is not portable.

You are correct. For that to have well-defined behavior in the general case, pthread_t, the return type of pthread_self(), would need to be an unsigned integer type, but POSIX does not require it to be even an integer, signedness notwithstanding.

Netlink is Linux-specific, and that does limit the scope you need to care about. Still, there have been more than one pthreads implementation for Linux, there may be new ones in the future, and because this detail is unspecified it is conceivable that implementations will change the type between versions.

What is the right way to set nl_pid in this case?

I would say that the best option for choosing netlink portids is almost always to let the kernel assign them, as you concluded in comments. Including in single-threaded applications. This is not a question of the process's file descriptor table, however, because portids are not file descriptors. In particular, unlike file descriptors, portids are system-wide. This is all the more reason to let the kernel choose.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157