Skip to content

Working with RRsets #606

@bal-e

Description

@bal-e

new::base currently has some gaps regarding RRset handling.

Ideally, new::base::Record would implement [Partial]Ord to match the DNSSEC canonical order. However, DNSSEC canonical order does not account for records which are identical in every way except TTL; such records cannot coexist. But new::base::Record does implement [Partial]Eq, within which it does check TTLs. This is the most intuitive behavior we can provide. If we provided a [Partial]Ord impl, it would have to be consistent with [Partial]Eq, and so could not match DNSSEC canonical order perfectly. This needs to be documented in the API so that users understand why Record does not implement [Partial]Ord. Hash is not implemented for the same reason.

Because of this, new::base::Record cannot be stored in the standard {BTree,Hash}{Map,Set} types. A common use case here would be to deduplicate records or organize them into RRsets. This came up in the context of Cascade's zone storage, but it is not a particularly strong motivator, since we expect to implement some bespoke data structures and do everything manually. We expect there are many more use cases around deduplicating records and handling RRsets, which could benefit from ordering and hashing semantics, but we need to understand them better before we can provide convenient functionality for them.

This issue exists to remind us to add documentation on new::base or new::base::Record to explain this situation, and in the future, to point users towards good solutions for them. It also exists to collect use cases we want to design for.

Use Cases

  • Writing a simple DNSSEC signer: organizing records (from an unsorted stream, e.g. zonefile or XFR) into RRsets to sign them. (Cascade does things manually for more efficiency.)
  • Writing a DNS zone validator (possibly including DNSSEC verification): ensuring that the zone does not contain duplicate records.
  • ...

Potential Solutions

One option is to provide wrapper types around Record that implement Ord (and perhaps Hash) in specific ways. For example, a CanonicalRecord wrapper would implement Ord as per DNSSEC canonical ordering, and ignore TTLs in Ord, Eq, and Hash.

type RRsets = BTreeSet<CanonicalRecord>;

struct CanonicalRecord(Record<Box<Name>, BoxedRecordData>);

While conceptually simple, this isn't so easy to work with; many useful BTreeSet methods have not been stabilized. It also duplicates a lot of information per RRset.

Another option would be to provide an "RRset key" type, which only stores the name and type (and perhaps class). We could also provide an "RRset data" type, which only stores the TTL and the data for each record. This is a little bit more complicated for the user, but quite flexible and powerful.

type RRsets = BTreeMap<RRsetKey, RRsetData>;
type RRsets = HashMap<RRsetKey, RRsetData>;

struct RRsetKey(Box<Name>, RType);
struct RRsetData(TTL, Vec<BoxedRecordData>);

Metadata

Metadata

Assignees

No one assigned

    Labels

    new-apiRelating to the new API, i.e. `domain::new::*`.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions