组播接收包的问题

时间:2015-03-10 11:41:31

标签: linux-device-driver

我创建了一个网络设备,可以组播dev-> flags = IFF_MULTICAST。

我发送UDP消息,但是当我收到数据包时,我没有收到系统跟踪的udp消息

   ipv6_rcv()
    |--> ip6_route_input()
          |-->ip6_mc_input() 

ipv6_chk_mcast_addr()在函数ip6_mc_input()中返回的值为0。 我想我需要在mc_list中添加多播地址ff02 :: 2.

这是真的吗?

我该如何制作?

感谢。

2 个答案:

答案 0 :(得分:0)

您需要加入多播组以接收其上的流量。 IFF_MULTICAST标志表示您的设备(驱动程序)支持多播。当系统想要加入或离开多播组时,驱动程序应配置硬件(通常只是一个过滤器)。

由于您正在将数据包传递到堆栈中,因此默认情况下您的硬件非常混杂,或者您已经以某种方式配置了硬件过滤器而系统没有加入多播组。

无论情况如何,为了使ipv6_chk_mcast_addr()成功,您必须加入目标多播组。在用户空间中,您可以使用IP_ADD_MEMBERSHIP setsockopt()来执行此操作。由于您对全路由器组播组(ff02 :: 2)感兴趣,我相信(但不能确定)在配置转发时内核会自动加入它。

答案 1 :(得分:0)

我终于解决了我的问题。我需要制作这样的插座。

if ((sockEnvio = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP))){

        printf("socket() failed");

    }

 // Bind the socket to the interface we're interested in
    int err=0;
    memset(&server, 0, sizeof(server));
    server.sin6_family = AF_INET6;
    server.sin6_scope_id = if_nametoindex("eth2");
    server.sin6_port = htons(15118);
    err = bind(sockEnvio, (struct sockaddr *)&server, sizeof(server));
    if (err < 0) {
        perror("packet socket bind return failed:");
        close(sockEnvio);     
    }
    printf("ICMPv6 socket bind to interface %d OK", if_nametoindex("eth2")); //if_nametoindex(lan));

   int optval = 1;
    if (setsockopt(sockEnvio, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval, sizeof(optval)) < 0) {
        perror("Error! setsockopt(IPV6_RECVPKTINFO)"); 
        close(sockEnvio);

    }

   optval = 0;
    if (setsockopt(sockEnvio, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) <0 ) {
        perror("Error! setsockopt(IPV6_MULTICAST_LOOP)");
        close(sockEnvio);

    }

    struct ipv6_mreq mreq;
    memset(&mreq, 0, sizeof(mreq));
    mreq.ipv6mr_interface = if_nametoindex("eth2");
    mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xff;
    mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
    mreq.ipv6mr_multiaddr.s6_addr[15] = 0x02;
    if (setsockopt(sockEnvio, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("Error! setsockopt(IPV6_ADD_MEMBERSHIP, ff02::02)");
        close(sockEnvio);       
    }