IPv6 address selection for ICMP6 neighbor solicitation (12-RELEASE)

I've got a VM with a /48 block that routes over link-local addresses. So that's fe80::2%vtnet0, the gateway is fe80::1%vtnet0, and vtnet0 also has an autoconfigured link-local address and a global address in that /48 block.

Code:
$ ifconfig vtnet0
vtnet0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=6c07bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,VLAN_HWTSO,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
        ether x:x:x:x:x:x
        inet x.y.z.w netmask 0xfffffffc broadcast x.y.z.v
        inet6 fe80::x:x:x:x%vtnet0 prefixlen 64 scopeid 0x1
        inet6 26xx:xxxx:xxxx::x prefixlen 64
        inet6 fe80::2%vtnet0 prefixlen 64 scopeid 0x1
        media: Ethernet 10Gbase-T <full-duplex>
        status: active
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>

When I ping6 an external system, the kernel sends a neighbor solicitation message for fe80::1 as expected, but sends it from the global address. Moving the global address to a loopback fixes the problem, but then programs want to use the link-local addresses as source addresses for non-local connections. It's possible ip6addrctl could make that option work, but I can't figure it out. I ended up moving the global back to vtnet0 and added a NAT rule:

Code:
nat on $ext_if inet6 proto icmp6 from ($ext_if) to ff02::1:ff00:1  -> fe80::2%vtnet0

It seems overkill, but works. (pf wasn't turned on before, and the new rules pass all icmp6, so that shouldn't be the problem.) I'd have thought that a link-local source would be preferred for the NS message given that the destination is link-local; is the actual behavior expected? Is there a better way to do this?
 
Back
Top