Comment 13 for bug 1624722

Revision history for this message
VF (fviktor) wrote :

Same happens in Ubuntu 14.04 with kernel 4.4.0-36-generic. Also reproduced on the above 16.04 distribution.

DHCPv6 server: isc-dhcp-server in IPv6 mode (isc-dhcp-server6)

Wireshark captures indicate that the solicit is sent from the client, arrives to the server's network interface, then lost in the kernel before arriving to dhcpd.

Cleared ip6tables and tc completely, so no firewall nor QoS could block/redirect the packet.

Running dhcpd under strace in the foreground confirms that no broadcast packet is received in user space.

Traced kernel function calls:

#!/bin/bash
mkdir -p /debug
mount -t debugfs nodev /debug
mount -t debugfs nodev /sys/kernel/debug
echo '*' >/debug/tracing/set_ftrace_filter
echo function_graph >/debug/tracing/current_tracer
echo 1 >/debug/tracing/tracing_on
sleep 10
echo 0 >/debug/tracing/tracing_on
cat /debug/tracing/trace > tracing.$$.out

Found the following fragment, where the packet is dropped:

ipv6_rcv() {
  ...
  ip6_rcv_finish() {
    ...
    ip6_mc_input() {
      ipv6_chk_mcast_addr() {
        _raw_read_lock_bh();
        _raw_read_unlock_bh() {
          __local_bh_enable_ip();
        }
      }
      kfree_skb() {
        ...
      }
    }
  }
}

(Timing information removed and irrelevant fragments replaced by ellipsis.)

Relevant kernel source code:

Function discards the packet: ip6_mc_input
http://lxr.free-electrons.com/source/net/ipv6/ip6_input.c?v=4.4#L285

Decision is based on false value returned here:
deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);

I verified that deliver is false by instrumenting the kernel with printk here.

(The long conditional block after the above code line does nothing, since it is not an MLD packet.)

Packet is discarded at the end of function by calling the kfree_skb function.

So the ultimate decision is made by this function: ipv6_chk_mcast_addr
http://lxr.free-electrons.com/source/net/ipv6/mcast.c?v=4.4#L955

Please note that src_addr = NULL. (See the function call above.)

I verified by kernel logging that idev is not NULL, so the device is found here.

Since src_addr is NULL rv can only be true if the for loop finds the destination address of the packet (variable: group) in the list of registered broadcast addresses.

Listing registered broadcast groups: netstat -g

I verified that dhcpd is indeed registered to ff02::1:2

Registration is also visible in the strace output.

I can get an address with the server (from itself) by adding a new virtual network adapter and connecting it to the same network. So it works if the packet remains inside the VM and does not go through the virtual switch.

I have spent days on this problem so far. Any ideas?