Skip to content

net/netip: add Prefix.Compare and AddrPort.Compare #61642

Open
@danderson

Description

@danderson

In our code, we've ended up writing ad-hoc ordering functions for netip.Prefix a whole bunch of times, for use with sort.Slice and the new slices.SortFunc. Writing those ordering functions is repetitive, and just tricky enough that it's easy to write comparators that don't conform to the contracts that sort and slices specify.

I propose adding Prefix.Less and Prefix.Compare to net/netip, so that people don't have to write their own ordering functions for prefixes. Less is a trivial wrapper around Compare. Compare orders two prefixes as follows:

  • By address family (e.g. IPv4 before IPv6)
  • Then by ascending pfx.Bits(),
  • Then by pfx.Addr().

An example ordering:

0.0.0.0/0
10.0.0.0/8
11.0.0.0/8
10.0.0.0/24
::/0

Back when we first wrote net/netip, we hesitated to add Less and Compare to prefix, because there didn't seem to be an obvious order we could impose: Prefixes organize themselves naturally into a binary tree rather than a flat list. So, Contains has an obvious definition, as does Overlaps, but Less and Compare would require us to come up with some arbitrary flattening of the tree to make sense.

Now that we have a bit more experience with using net/netip in the wild, I have two arguments for implementing Less and Compare as defined above:

  • Empirically, there does exist a generally accepted ordering for prefixes: it's the ordering from ip route show, and virtually all other network-oriented software. That order is the one specified above, where smaller prefixes appear first, and so the list reads from most general to most specific. This is also the order you get when implementing a binary tree as an array, or when you place prefixes into a tree and traverse it breadth-first.
  • A lot of prefix sorting happens in test code, where the caller just wants any reproducible ordering, and mainly doesn't want to have to implement the mildly fiddly Compare themselves.

While we're in there, AddrPort also lacks comparators, so we could add those as well. The above discussion doesn't apply to AddrPort, in that there is an obvious ordering available (order by Addr first, then Port). Looking back, I believe we simply forgot to make AddrPort's API consistent with Addr.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    No status

    Status

    Accepted

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions