moq L. Curley Internet-Draft 3 August 2026 Intended status: Informational Expires: 4 February 2027 MoQ Cluster Extension draft-lcurley-moq-cluster-00 Abstract This document defines a clustering extension for MoQ Transport [moqt], used to build a mesh of relays. Each namespace advertisement carries the ordered list of Hop IDs it has traversed, starting with the original publisher, plus the accumulated cost of that path. A receiver uses the list to detect routing loops and to identify which advertisements come from the same publisher, and the cost to choose between paths. Each endpoint declares its own Hop ID during setup, and the peer uses it to avoid advertising or serving a path that already passed through that endpoint. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on 4 February 2027. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components Curley Expires 4 February 2027 [Page 1] Internet-Draft moq-cluster August 2026 extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Table of Contents 1. Conventions and Definitions . . . . . . . . . . . . . . . . . 2 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 3. Setup Negotiation . . . . . . . . . . . . . . . . . . . . . . 3 3.1. Relay Hops . . . . . . . . . . . . . . . . . . . . . . . 3 3.2. Relay Cost . . . . . . . . . . . . . . . . . . . . . . . 3 4. Hop IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4.1. The Reserved Hop ID 0 . . . . . . . . . . . . . . . . . . 4 5. Namespace Advertisements . . . . . . . . . . . . . . . . . . 5 5.1. HOP_PATH Parameter . . . . . . . . . . . . . . . . . . . 5 5.2. ROUTE_COST Parameter . . . . . . . . . . . . . . . . . . 6 6. Relay Behavior . . . . . . . . . . . . . . . . . . . . . . . 6 6.1. Accumulating Cost . . . . . . . . . . . . . . . . . . . . 6 6.2. Updating an Advertisement . . . . . . . . . . . . . . . . 7 7. Path Selection . . . . . . . . . . . . . . . . . . . . . . . 7 8. Security Considerations . . . . . . . . . . . . . . . . . . . 8 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 9 9.1. MOQT Setup Options . . . . . . . . . . . . . . . . . . . 9 9.2. MOQT Message Parameters . . . . . . . . . . . . . . . . . 9 10. Normative References . . . . . . . . . . . . . . . . . . . . 9 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 10 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 10 1. Conventions and Definitions The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. *Upstream* and *downstream* are relative to the flow of an advertisement, not to the endpoints: the peer that sends an advertisement is upstream, the one that receives it is downstream. The same pair of relays can be upstream of each other for different namespaces. 2. Introduction [moqt] is designed to deliver content through a mesh of relays, but is deliberately vague about how that mesh is built, and the base transport does not carry enough information to build one. Curley Expires 4 February 2027 [Page 2] Internet-Draft moq-cluster August 2026 Relays that gossip namespaces with PUBLISH_NAMESPACE quickly break down: advertisements loop between relays forever, and when two connections advertise the same namespace, a relay has no basis for deciding which one to route a SUBSCRIBE toward. This extension adds the HOP_PATH parameter to PUBLISH_NAMESPACE and NAMESPACE. It lists every node an advertisement has passed through, starting with the original publisher, which is enough to break loops and to compare paths. Each connection also declares its own Hop ID at SETUP, so loops are avoided even across multiple connections between the same pair of relays. Not every route is equal: one crossing a metered backbone costs more than one inside a datacenter. The RELAY_COST Setup Option prices a link, defaulting to 1 so an unpriced mesh simply ranks by hop count. The ROUTE_COST parameter carries the accumulated price per namespace, and a relay may lower it to advertise that it already has the content cached, steering subscribers toward a warm copy. 3. Setup Negotiation 3.1. Relay Hops The extension is negotiated during the SETUP exchange ([moqt] Section 10.3). An endpoint indicates support with the following Setup Option, whose value is its own Hop ID: RELAY_HOPS Setup Option { Option Key (vi64) = 0x40B55 Option Value Length (vi64) Hop ID (vi64) } Negotiation is per session; a relay MUST NOT assume that because one of its sessions negotiated Relay Hops, another did. It also enables the extended NAMESPACE message (Section 5), which is what lets a NAMESPACE carry these parameters at all. On a session that negotiated the extension, an endpoint MUST include HOP_PATH on every PUBLISH_NAMESPACE and NAMESPACE it sends, and a receiver MUST close the session with a PROTOCOL_VIOLATION if one arrives without it. 3.2. Relay Cost The client MAY declare what this link costs to cross; a server MUST NOT send this option, so one side owns the price: Curley Expires 4 February 2027 [Page 3] Internet-Draft moq-cluster August 2026 RELAY_COST Setup Option { Option Key (vi64) = 0x40B56 Option Value (vi64) } Both endpoints add the client's value to the ROUTE_COST of every advertisement they receive over the connection, so the link is priced the same in both directions. An absent option means 1, under which the accumulated cost equals the hop count. 0 is meaningful and distinct from absent: it makes the link free, which is how a deployment describes two relays in the same datacenter. 4. Hop IDs A *Hop ID* is a variable-length integer identifying one endpoint within an advertisement's path. Hop IDs SHOULD be unique among the endpoints an advertisement can traverse. An endpoint MAY generate one randomly, since collisions across a 64-bit space are unlikely, or use a stable configured identifier that survives restarts. Loop detection and origin identification compare Hop IDs for equality, so two endpoints sharing a Hop ID are indistinguishable. Redundant publishers producing interchangeable content MAY share one deliberately, so a receiver treats their paths as failover options for the same content (Section 7). 4.1. The Reserved Hop ID 0 *0 means "no identity"* and is reserved. It is used for an endpoint that did not negotiate this extension, and an endpoint MAY also declare 0 to withhold its identity. Because any number of endpoints can be 0, it identifies nothing, which constrains all three uses: * *Loop detection*: 0 in a HOP_PATH is never a loop. A receiver whose own Hop ID is 0 cannot detect loops through itself, and MUST NOT discard an advertisement merely because the path contains 0. * *Origin identity*: an advertisement whose first entry is 0 has an unknown origin. A receiver MUST NOT treat two such advertisements as interchangeable (Section 7). * *Filtering*: a peer that declared 0 excludes nothing, so the sender applies no filter to that session. Curley Expires 4 February 2027 [Page 4] Internet-Draft moq-cluster August 2026 Duplicate _non-zero_ Hop IDs in one HOP_PATH are a loop; duplicate zeros are not. Declaring 0 therefore trades loop detection, failover, and update continuity (Section 6.2) for anonymity. 5. Namespace Advertisements This extension carries HOP_PATH and ROUTE_COST as Key-Value-Pair parameters ([moqt] Section 2.5). PUBLISH_NAMESPACE ([moqt] Section 10.15) already has a Parameters field. NAMESPACE ([moqt] Section 10.16) does not, and a subscriber-driven mesh propagates advertisements as NAMESPACE messages, so this extension defines an extended form used only on a session that negotiated Relay Hops: NAMESPACE Message (Relay Hops) { Type (vi64) = 0x8, Length (16), Track Namespace Suffix (..), Number of Parameters (vi64), Parameters (..) ... } The appended fields are encoded exactly as in PUBLISH_NAMESPACE. An endpoint MUST NOT append them on a session that did not negotiate the extension. NAMESPACE_DONE ([moqt] Section 10.17) carries no state from this extension and is not extended. 5.1. HOP_PATH Parameter HOP_PATH is the ordered list of Hop IDs an advertisement has traversed, from the original publisher to the relay immediately upstream of the receiver: HOP_PATH Parameter { Type (vi64) = 0x40B57 Length (vi64) Hop ID (vi64) ... } The list always has at least one entry, the original publisher, which is 0 if that publisher is unknown (Section 4.1). A receiver MUST close the session with a PROTOCOL_VIOLATION if the entries do not exactly fill Length, if the list is empty, or if a non-zero Hop ID appears twice. Curley Expires 4 February 2027 [Page 5] Internet-Draft moq-cluster August 2026 5.2. ROUTE_COST Parameter ROUTE_COST is the marginal cost of subscribing via this advertisement: the price of the transfers a new subscription would actually cause. ROUTE_COST Parameter { Type (vi64) = 0x40B58 Value (vi64) } It is OPTIONAL and absent means 0, so an endpoint that prices nothing sends nothing. Costs still accumulate across such a mesh, because each receiver adds its own link's price (Section 3.2) regardless. The original publisher seeds the value with its production cost: 0 for content it is already producing, higher for content it would have to spin up on demand, such as a standby transcoder advertising everything it _could_ serve. 6. Relay Behavior When forwarding an advertisement downstream, a relay MUST append its own Hop ID to the HOP_PATH it received, so its own ID is always the last entry. An advertisement arriving from an upstream that did not negotiate the extension has no HOP_PATH; the relay creates one containing a single 0 for that upstream (Section 4.1), then appends its own. On receipt, a relay MUST discard an advertisement whose HOP_PATH already contains its own non-zero Hop ID: forwarding it would extend a loop, and subscribing through it would route the relay back to itself. This receiver-side check catches loops of any length and is the only loop defense required. 6.1. Accumulating Cost A relay MUST add the session's link cost (Section 3.2) to the ROUTE_COST it received before forwarding or acting on an advertisement. The addition MUST saturate rather than wrap, so an absurd upstream value ranks last instead of overflowing to best. A relay actively carrying the namespace (a live subscription exists for at least one of its tracks) SHOULD advertise 0 instead of the accumulated value: its ingress is already paid for, so one more subscriber costs only the links below it. This is what lets a cluster deduplicate onto a warm copy. The discount applies only to the advertisement for the path it actually serves from; a standby Curley Expires 4 February 2027 [Page 6] Internet-Draft moq-cluster August 2026 path keeps its accumulated value, since serving from it means opening a fresh ingest. When it stops carrying the namespace it SHOULD restore the accumulated value, optionally after a grace period so brief churn does not flap routing. Two relays that independently begin carrying the same namespace would each see the other's 0 as cheaper than its own source, and both switching at once would leave the namespace with no source. Before re-parenting onto a 0-cost advertisement from another actively- carrying relay (one whose HOP_PATH has two or more entries), a relay SHOULD apply a deterministic tie-break, such as comparing a hash of the namespace and each Hop ID, so exactly one side moves. Equal Hop IDs (including two relays that both declared 0) cannot be ordered, and neither side SHOULD move. Cheaper advertisements from anything else carry no such hazard and SHOULD be adopted immediately. 6.2. Updating an Advertisement An endpoint updates an advertisement by re-sending it with new parameters *on the stream that already carries it*: the original PUBLISH_NAMESPACE request stream, or the SUBSCRIBE_NAMESPACE response stream the NAMESPACE arrived on. A receiver MUST NOT treat the repeat as a duplicate or a protocol violation. In [moqt] an advertisement lives for the lifetime of its stream, so an update on a _new_ stream would leave two streams claiming one namespace and let the superseded one retract its replacement. An endpoint MUST NOT open a second stream for a namespace it already advertises on this session. Replacement is atomic, so a receiver MUST NOT tear down subscriptions or drop cached state merely because an update arrived. What it means for existing subscriptions follows the first HOP_PATH entry (Section 7): unchanged and non-zero, the content is continuous and subscriptions MAY resume on the new route at a group boundary; changed or 0 (Section 4.1), a different publisher may have taken over and they do not carry over. The expected case is a ROUTE_COST-only change, which is how a relay signals that it started or stopped carrying the namespace. 7. Path Selection A receiver holding advertisements for the same namespace over several sessions SHOULD prefer the lowest ROUTE_COST, breaking ties toward the shorter HOP_PATH and then toward the most recently received. This is advisory: a receiver MAY apply local policy such as measured RTT instead. Curley Expires 4 February 2027 [Page 7] Internet-Draft moq-cluster August 2026 Two advertisements whose HOP_PATH begins with the same non-zero Hop ID share a publisher and carry interchangeable content, so a receiver MAY hold them as redundant paths and fail an active subscription over to the survivor. If the first entries differ, or either is 0, they are distinct publishers reusing a namespace: a receiver MUST NOT treat them as interchangeable and SHOULD treat the later as replacing the earlier. A publisher SHOULD advertise, per session, the best path whose HOP_PATH does not contain the Hop ID that peer declared, and SHOULD advertise nothing when every known path contains it. Because selection is per session, a peer that the serving path flows through still receives the best standby, which is what lets it fail over if its own copy dies. When serving a subscription, a publisher MUST select the source by that same rule. If only excluded sources remain the subscription is unroutable, since serving it would hand the subscriber data that already flowed through itself. Applying one rule to both advertisement and dispatch keeps advertised paths truthful and prevents subscription cycles of any length. 8. Security Considerations A Hop ID reveals nothing beyond what its operator encodes in it, and a deployment that considers its identifiers sensitive can use random values or declare 0 (Section 4.1). A HOP_PATH does expose how many hops an advertisement crossed, which hints at the size of a deployment; a relay MAY coalesce its internal hops into one entry, or strip HOP_PATH, before forwarding across a trust boundary. Because a relay only appends to HOP_PATH, it cannot make a competing path look shorter than it is; the worst it can do is under-report its own upstream portion to win an advisory tie-break. ROUTE_COST has no such structural protection: it is a single value the sender chooses, so a relay can advertise 0 for content it is not carrying and attract subscriptions it then has to fetch. Both cost only a suboptimal path choice, and the latter is self-limiting, since the traffic won this way must then be served. A receiver MUST NOT make security decisions based on Hop IDs, and a deployment spanning a trust boundary SHOULD treat a peer's ROUTE_COST as a hint to clamp or ignore rather than an accounting figure. Curley Expires 4 February 2027 [Page 8] Internet-Draft moq-cluster August 2026 9. IANA Considerations This document requests the following registrations. High, distinctive values are requested to avoid the low ranges reserved by [moqt] and to minimize collisions with provisional registrations by other extensions. 9.1. MOQT Setup Options This document requests two registrations in the "MOQT Setup Options" registry ([moqt] Section 15.4), whose policy is Specification Required. +=========+============+===============+ | Value | Name | Reference | +=========+============+===============+ | 0x40B55 | RELAY_HOPS | This Document | +---------+------------+---------------+ | 0x40B56 | RELAY_COST | This Document | +---------+------------+---------------+ Table 1 9.2. MOQT Message Parameters This document requests two registrations in the "MOQT Message Parameters" registry ([moqt] Section 15.7). Both are carried in PUBLISH_NAMESPACE and in the extended NAMESPACE message (Section 5). +=========+============+==============================+===========+ | Value | Name | Carried In | Reference | +=========+============+==============================+===========+ | 0x40B57 | HOP_PATH | PUBLISH_NAMESPACE, NAMESPACE | This | | | | | Document | +---------+------------+------------------------------+-----------+ | 0x40B58 | ROUTE_COST | PUBLISH_NAMESPACE, NAMESPACE | This | | | | | Document | +---------+------------+------------------------------+-----------+ Table 2 The Key-Value-Pair parity is load-bearing: HOP_PATH and RELAY_HOPS are odd, so their values are length-prefixed byte strings, while ROUTE_COST and RELAY_COST are even, so their values are bare varints. 10. Normative References Curley Expires 4 February 2027 [Page 9] Internet-Draft moq-cluster August 2026 [moqt] Nandakumar, S., Vasiliev, V., Swett, I., and A. Frindell, "Media over QUIC Transport", Work in Progress, Internet- Draft, draft-ietf-moq-transport-19, 6 July 2026, . [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . Acknowledgments This document was drafted with the assistance of Claude, an AI assistant by Anthropic. Author's Address Luke Curley Email: kixelated@gmail.com Curley Expires 4 February 2027 [Page 10]