How does IPSet handle IPv6 zones?
danderson opened this issue · comments
In #126, the question came up of what the set complement of an IPSet containing a v6+zone address would be.
In strict math terms, the complement of a set with no IPv6 is the infinite set of all possible IPv6s in all possible zones. Obviously, we can't do that :)
@josharian suggested, for Complement specifically, to scan s.Ranges(), find all zones in use, and generate the complementary IPv6s for those zones only. So, if you have ::1%eth0 in the set, taking the complement would add (all IPs except ::1)%eth0
. That feels a bit weird to me though, I'm unsure if that makes sense as an API user.
s.Ranges also doesn't deal with zones properly. Given s.AddPrefix("::/0%eth0")
, s.Remove("::10")
, s.Ranges currently will slice up ::/0%eth0
, and some of those ranges won't preserve the zone.
Going even wider, IPRange also doesn't handle zones properly - more accurately, it ignores zones entirely, so you can have a range from ::1%eth0
to ::10%eno4
, and that would compare unequal to ::1-::10
, but behave like ::1-::10
in practice.
Options:
- Status quo: declare that IPRange and IPSet are zones-agnostic, and if you expect zones to make sense within them you're going to have a bad time.
- Declare IPRange and IPSet to not support zones. Make IPRanges with zones invalid, make IPSets containing zone-ful ranges equally invalid.
- Add zone support. Make IPRange valid only if
To.Zone() == From.Zone()
, make IPSet behave sensibly given valid IPRanges (including probably the Complement behavior @josharian suggested, but also correcting Range to be zone-aware, etc.)
Thoughts @bradfitz @josharian @mdlayher ?
Zones, the gift that keeps on giving.
Another option for complement is to force the caller to provide the universe (as another IPSet). Which is, I suppose, to eliminate complement and tell people to use difference instead. We could have some convenience functions to generate common universe sets, like AllIPv4, AllIPv6, AllIP.
I think we should either actively reject zones or completely support them. That is, I do not like option 1. I don't feel strongly between 2 and 3.
Providing the universe is an interesting idea. We could still keep Complement, but specify that its universe is AllIP, so if you're not doing whacky things, you get a handy helper. If you are doing whacky things, well, set difference is your friend.
Note I was wrong, #84 made IPRanges somewhat zone-aware, in that mixed-zone ranges are invalid. They still don't handle zones correctly in other areas (e.g. Contains() doesn't return the correct answers).
I think I'm lean toward option 3 assuming it can be done without immense complexity or corner cases. If the caller has zones in their addresses then I assume they know what they are doing with them (link-local IPv6 addresses being the primary use case).