I am implementing neighbor solicitation using asynchronous I/O with poll on Linux. My host has multiple interfaces (and no default route). Since neither the socket API nor libnetlink offer a way to perform neighbor discovery on request, I'm implementing it myself.
My set of next hop IPv6 addresses comes from the local routing table (about 100 next hops). The neighbor cache only has about 30 to 80 cached at a time and I can't rely on the hardware address of the next hop to be available there.
Problem: When sending out solicitations as fast as async I/O allows, I receive only one or no responses.
Details: For each interface, I create a socket (socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)
), perform a range of configuration (FD_CLOEXEC
, nonblocking, ICMP6_FILTER
, SO_DONTROUTE
, IPV6_MULTICAST_HOPS
, IPV6_UNICAST_HOPS
, IPV6_RECVHOPLIMIT
) and bind it to the address of the interface.
In a typical fashion, I'm running a poll loop and send out solicitations when I can write and receive packets when I can read. Here is the weird behavior:
- If I run the code with a single neighbor addresses everything works as expected.
- If I run the code with multiple neighbor addresses and wait for a matching advertisement before sending a new solicitation, the code works.
- But, if I send out multiple solicitations without waiting for the respective advertisements, I get one or (mostly) no advertisements matching my solicitations.
In all cases my program receives advertisements that are not responses to my requests. As a result I'm confident that receiving generally works in all three cases.
To ensure that this is not corrupted state and to verify that the packets are actually send out, I recorded the solicitations with Wireshark. The packets that solicit an advertisement are identical to packets that don't solicit an advertisement. (I extracted the bytes of both packets and ran them through diff
.) One capture has a reply while the other one does not.
(I checked the source code of ndisc6
, which does use poll
as well, but only sends out one solicitation at once.)
Edit: Added information on query set. See comment below.