The IP_PKTINFO socket option does not work

I’ve been knocking on this head for several weeks, and finally I understand that I just can’t understand. I also worked with network engineers on my team to no avail. My problem is this:

I am working on an application that quite straightforwardly combines UDP groups across multiple vlans (each vlan appears as its own virtual interface, in this case the NIC is SolarFlare, if that matters). All of these connections occur on the same socket (where messages are deduplicated based on payload sequence numbers). Before doing IP_ADD_MEMBERSHIP, I set the socket options as follows:

setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &yes, sizeof yes)
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes))
setsockopt(sock, IPPROTO_IP, PACKET_AUXDATA, &yes, sizeof(yes))

I need to get either the interface index through IP_PKTINFO or the vlan identifier through PACKET_AUXDATA in order to collect statistics over the stream. Now everything is initialized without errors, and I can process UDP files without any problems. Where I run into difficulties, I try to access the helper / control messages requested above, as shown by using simple debug logging:

for (cmsgptr = CMSG_FIRSTHDR(&msg);
    cmsgptr != NULL;
    cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
    printf("Control Message: cmsg_level: %d, cmsg_type %d\n", cmsgptr->cmsg_level, cmsgptr->cmsg_type);
}

For each packet received, this only gives:

Control Message: cmsg_level: 1, cmsg_type 29

For reference, SOL_SOCKET = 1 and SO_TIMESTAMP = 29. So, although I request 3 different types of control messages, only the timestamp is filled. This behavior does not depend on whether I join one UDP group on one interface or several groups on several interfaces.

, , , . ip (7) IP_PKTINFO Linux 2.2. Ubuntu 14.04.4, ​​3.13.0-24-generic.

, !

+4
1

1) reset yes 1 setsockopt. , , , .

int yes = 1;
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &yes, sizeof(yes));

yes = 1;
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes));

yes = 1;
setsockopt(sock, IPPROTO_IP, PACKET_AUXDATA, &yes, sizeof(yes));

2) setsockopt, , . , , "0" "-1" . .

3) recvmsg, . , struct msghdr . , , ? :

struct iovec vec;
ssize_t ret;

const size_t CONTROL_DATA_SIZE = 1000;  // THIS NEEDS TO BE BIG ENOUGH.
char controldata[CONTROL_DATA_SIZE]; 
struct msghdr hdr = {};
sockaddr_storage addrRemote = {};

vec.iov_base = buf;
vec.iov_len = len;

hdr.msg_name = &addrRemote;
hdr.msg_namelen = sizeof(addrRemote);
hdr.msg_iov = &vec;
hdr.msg_iovlen = 1;
hdr.msg_control = controldata;
hdr.msg_controllen = CONTROL_DATA_SIZE;

ret = ::recvmsg(sockfd, &hdr, flags);
0

All Articles