AFI and SAFI were closed enums, so a family without a variant could not be
represented at all, and the set of negotiated families was a struct with
one bool per family. Supporting another family meant touching both.
- `Afi`, `Safi` and `AfiSafi` in bgp-primitives are newtypes over the wire
numbers, with constants and names for the common families. Capabilities
and MP_REACH/MP_UNREACH use them, so any family a peer names is read as
what it is. The special case that turned a capability for an unlisted
family into an unknown capability is gone.
- `FamilySet` is a set of `AfiSafi`. What we can exchange routes for is the
explicit `family::SUPPORTED` list; only those are offered in our OPEN.
- `AddressFamilyId` stays as the IP version of a prefix.
- NLRI is still a list of IP prefixes. MP_REACH/MP_UNREACH for a family
whose NLRI is something else (labelled, VPN, EVPN, ...) is refused
rather than misread as prefixes, which is what happened before for the
SAFIs the old enum listed.
Bug found on the way: the reserved octet in MP_REACH_NLRI was skipped only
for IPv6, so an IPv4 MP_REACH_NLRI was parsed with an extra 0.0.0.0/0
route that the peer never sent.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>