FreeBSD IPv6 Router Advertisements, SLAAC, and Neighbor Discovery Operations
Diagnose FreeBSD IPv6 router advertisements, SLAAC, default routes, and neighbor state with host and router configurations grounded in official manuals.
An IPv6 interface can have a link-local address and still have no usable path beyond its local segment. A global address, a default route, successful neighbor resolution, and working DNS are separate pieces of state. FreeBSD’s Router Advertisement (RA), Stateless Address Autoconfiguration (SLAAC), and Neighbor Discovery (ND) tools are easiest to operate when those layers are checked independently.
This guide covers host-side SLAAC and a basic FreeBSD router using rtadvd(8). It does not assume that every network delegates a prefix, uses SLAAC for every setting, or advertises a router on every interface. Confirm the upstream prefix and router policy before applying the examples. Addresses under 2001:db8::/32 are documentation-only and must not be copied into a production network.
Separate Router Solicitation, Router Advertisement, and NDP
Neighbor Discovery is the IPv6 control-plane family used for tasks including router discovery, address resolution on a link, and reachability detection. An IPv6 host can generate a link-local address when an interface comes up. A router advertisement can provide a default-router indication and prefix information; the prefix’s flags and lifetimes affect whether and how a host can form addresses from it. This is distinct from DNS resolution and from an application’s ability to reach a remote service.
On FreeBSD, rtsold(8) sends Router Solicitation messages so a host can discover routers when it attaches to a link. The kernel processes received Router Advertisements when configured to accept them. rtadvd(8) is the userland daemon for a router that sends advertisements. These names are easy to confuse: starting rtadvd on a workstation does not make it a better RA client, and enabling rtsold does not turn the host into a router.
At the neighbor layer, ndp(8) reports the IPv6 neighbor cache. An entry that is incomplete or repeatedly expires can point to a local-link problem even when a default route exists. Conversely, a stable neighbor entry for the first-hop router does not prove the upstream router has a working route or prefix delegation.
Configure an ordinary SLAAC host
First record the interface names, current IPv6 addresses, route table, resolver configuration, and forwarding role. The following commands are observational:
freebsd-version -kru
ifconfig em0
netstat -rn -f inet6
ndp -an
sysctl net.inet6.ip6.forwarding net.inet6.ip6.accept_rtadv
Replace em0 with the actual interface. For a normal host expected to use router advertisements, the FreeBSD Handbook documents this persistent configuration pattern:
sysrc ifconfig_em0_ipv6="inet6 accept_rtadv"
sysrc rtsold_enable="YES"
Reboot or apply the change through a planned network reconfiguration, then verify the effective ifconfig flags, IPv6 addresses, and route table. A configured accept_rtadv value alone proves only the requested policy; it does not prove an RA arrived or that its advertised information is suitable. rtsold sends solicitations, but routers may also advertise periodically, and a link-layer filter or switch policy can prevent either direction from working.
Forwarding changes the role of the machine. The Handbook specifically notes that when IPv6 packet forwarding is enabled, FreeBSD does not configure a SLAAC address unless net.inet6.ip6.rfc6204w3 is set to 1. Do not flip that tunable simply to make an address appear: first determine whether this host is a router, a multihomed host, or a single-interface endpoint, and design the intended RA and forwarding policy. Hosts with multiple interfaces and routers need deliberate route selection and per-interface behavior rather than a copied laptop recipe.
Configure a router to advertise a delegated prefix
On a router, use a prefix that the provider or upstream network actually delegated to this link. The Handbook’s basic pattern enables rtadvd on the selected LAN interface and gives it a per-interface prefix configuration:
sysrc rtadvd_enable="YES"
sysrc rtadvd_interfaces="em0"
An /etc/rtadvd.conf entry has this form, with the documentation prefix below replaced by the authorized production prefix:
em0:\
:addrs#1:addr="2001:db8:1f11:246::":prefixlen#64:tc=ether:
Validate the file against the installed rtadvd.conf(5) manual and confirm the prefix length, lifetime policy, interface, and advertised router preference match the network design. Do not advertise a prefix that the router cannot route upstream, or a prefix already in use on another link. Restarting the daemon is an externally visible network change: stage the configuration, keep console access, and observe an actual client before saving it as a stable design.
RA is not a DHCP lease. It is a link-local control message that can supply router and prefix information. DNS is a separate host-configuration outcome and may come from DHCPv6, an RA-based RDNSS mechanism when supported and integrated, or local resolver policy; do not infer it from a configured SLAAC address. On a multi-router link, inspect all advertisements and route preferences; an unplanned router can cause clients to select an unusable default path even if the intended router is healthy.
Trace each state boundary when clients fail
Take a before-and-after snapshot rather than restarting networking immediately. Check whether the interface is up, whether a link-local address exists, whether ACCEPT_RTADV appears in ifconfig, whether a non-link-local address is present, and whether an IPv6 default route is installed. Compare the route with the intended interface and next hop. Then inspect ndp -an for the router’s link-local neighbor entry.
For a bounded packet observation, capture ICMPv6 on the client interface:
tcpdump -ni em0 'icmp6'
Router Solicitation and Router Advertisement messages use ICMPv6 types 133 and 134. Neighbor Solicitation and Neighbor Advertisement are 135 and 136. A capture can show whether the client transmits solicitations and whether advertisements return on the same link. It does not prove that the kernel accepted the contents, that a firewall permits the later data plane, or that the advertised upstream route works.
Use the failure pattern to narrow the layer:
- No link-local address usually means the interface is down or its IPv6 configuration is absent; investigate the interface and driver before RA policy.
- A link-local address but no solicitation suggests
rtsoldis disabled, not bound to the expected interface, or is not being triggered by the current configuration. - Solicitations with no advertisements point toward the Layer-2 segment, router policy, or filtering. Confirm the router’s selected interface and capture on both ends.
- An advertisement with no global address requires checking the advertised prefix information, its autonomous flag and lifetime, DAD results, and the host’s forwarding role.
- An address with no default route calls for inspection of the RA’s router lifetime and the installed route table, not merely DNS.
- A default route with an unresolved first-hop neighbor points to link-local reachability, VLAN, bridge, or neighbor-discovery filtering. A resolved neighbor with failed remote traffic shifts attention upstream.
Do not treat IPv4 ping or DNS success as evidence that the IPv6 path works. Test an IPv6 literal first, then IPv6 DNS and the application hostname. Check both directions where possible, because asymmetric routing and filtering can make a local interface look configured while return traffic fails.
Define operational acceptance criteria
For a host, record a successful link-local address, expected SLAAC address or other assigned address, intended default route, resolvers, and application-level IPv6 connectivity. Confirm that the address remains valid after a link bounce and reboot, and that the host does not accidentally begin forwarding. For a router, verify the advertised prefix and lifetime on a client capture, confirm clients install the intended address and default route, and test routed traffic beyond the first hop.
Keep a rollback path before changing rc.conf, sysctls, firewall rules, or rtadvd.conf. Record the old configuration, exact interface names, address plan, forwarding state, and packet timestamps. Avoid broad packet-filter changes just to make discovery work; IPv6 needs essential ICMPv6 control traffic, and the correct policy should be tested with the network’s actual role and interface boundaries.
The core operational lesson is to avoid collapsing discovery, address assignment, neighbor resolution, routing, DNS, and application reachability into a single “IPv6 is up” check. Each is a separate observable contract. Proving them in order turns an intermittent SLAAC incident into a specific failure that can be corrected without disturbing unrelated IPv4 service.
Related:
- FreeBSD DHCP Client Lease Lifecycle: Boot, Renewal, and Recovery
- Fixing FreeBSD Jail Networking When VNET Jails Can’t Reach the Network
Sources: