Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C IP_PKTINFO套接字选项不工作_C_Linux_Sockets_Vlan - Fatal编程技术网

C IP_PKTINFO套接字选项不工作

C IP_PKTINFO套接字选项不工作,c,linux,sockets,vlan,C,Linux,Sockets,Vlan,我已经在这个问题上苦思冥想了好几个星期了,现在终于接受了一个事实:我就是想不出来。我也一直在与我的团队中的网络工程师合作,但毫无结果。我的问题如下: 我正在开发一个在多个vlan上进行相当直接的UDP组联接的应用程序(每个vlan都作为自己的虚拟接口公开,如果相关的话,在本例中的NIC是SolarFlare)。所有这些连接都发生在单个套接字上(其中消息根据有效负载序列号消除重复)。在执行IP_添加_成员资格之前,我将设置如下套接字选项: setsockopt(sock, SOL_SOCKET,

我已经在这个问题上苦思冥想了好几个星期了,现在终于接受了一个事实:我就是想不出来。我也一直在与我的团队中的网络工程师合作,但毫无结果。我的问题如下:

我正在开发一个在多个vlan上进行相当直接的UDP组联接的应用程序(每个vlan都作为自己的虚拟接口公开,如果相关的话,在本例中的NIC是SolarFlare)。所有这些连接都发生在单个套接字上(其中消息根据有效负载序列号消除重复)。在执行IP_添加_成员资格之前,我将设置如下套接字选项:

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))
我需要通过IP_PKTINFO获取接口索引,或者通过PACKET_AUXDATA获取vlan id,以便在下游收集统计信息。现在,所有的初始化都没有错误,我能够毫无问题地处理UDP有效负载。我遇到的问题是当我试图访问上面请求的辅助/控制消息时,如简单调试日志所示:

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);
}
对于接收到的每个数据包,这仅输出:

Control Message: cmsg_level: 1, cmsg_type 29
作为参考,SOL_SOCKET=1,SO_TIMESTAMP=29。因此,尽管我请求3种不同的控制消息类型,但只填充时间戳。此行为与我是在单个接口上加入单个UDP组还是在多个接口上加入多个组无关

一种解决方案是重写应用程序,将每个接口放在自己的套接字上,然后将所有内容都放入队列中,但根据我的经验,上下文切换会降低应用程序的性能。根据手册页面ip(7),自Linux内核2.2以来,ip_PKTINFO一直可用。我正在运行Ubuntu 14.04.4,它使用内核3.13.0-24-generic


任何帮助、见解或指导都将不胜感激

暗中猜测

1) 每次成功调用
setsockopt
后,您需要将
yes
重置回1。文件暗示这是不必要的,但我会这么做

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
代码,这可能是您用来获取额外信息的代码。但可能是结构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);