Skip to content

Commit

Permalink
Clarify Gateway Listener Distinct definitions (#3477)
Browse files Browse the repository at this point in the history
* Clarify Gateway Listener Distinct definitions

Signed-off-by: Nick Young <nick@isovalent.com>

* Update with PR comments

Signed-off-by: Nick Young <nick@isovalent.com>

---------

Signed-off-by: Nick Young <nick@isovalent.com>
  • Loading branch information
youngnick authored Dec 12, 2024
1 parent 1dc9d2e commit 27b4aa8
Show file tree
Hide file tree
Showing 4 changed files with 396 additions and 186 deletions.
116 changes: 79 additions & 37 deletions apis/v1/gateway_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ type GatewaySpec struct {
// logical endpoints that are bound on this Gateway's addresses.
// At least one Listener MUST be specified.
//
// ## Distinct Listeners
//
// Each Listener in a set of Listeners (for example, in a single Gateway)
// MUST be _distinct_, in that a traffic flow MUST be able to be assigned to
// exactly one listener. (This section uses "set of Listeners" rather than
Expand All @@ -80,74 +82,103 @@ type GatewaySpec struct {
// combination of Port, Protocol, and, if supported by the protocol, Hostname.
//
// Some combinations of port, protocol, and TLS settings are considered
// Core support and MUST be supported by implementations based on their
// targeted conformance profile:
// Core support and MUST be supported by implementations based on the objects
// they support:
//
// HTTP Profile
// HTTPRoute
//
// 1. HTTPRoute, Port: 80, Protocol: HTTP
// 2. HTTPRoute, Port: 443, Protocol: HTTPS, TLS Mode: Terminate, TLS keypair provided
//
// TLS Profile
// TLSRoute
//
// 1. TLSRoute, Port: 443, Protocol: TLS, TLS Mode: Passthrough
//
// "Distinct" Listeners have the following property:
//
// The implementation can match inbound requests to a single distinct
// Listener. When multiple Listeners share values for fields (for
// **The implementation can match inbound requests to a single distinct
// Listener**.
//
// When multiple Listeners share values for fields (for
// example, two Listeners with the same Port value), the implementation
// can match requests to only one of the Listeners using other
// Listener fields.
//
// For example, the following Listener scenarios are distinct:
// When multiple listeners have the same value for the Protocol field, then
// each of the Listeners with matching Protocol values MUST have different
// values for other fields.
//
// The set of fields that MUST be different for a Listener differs per protocol.
// The following rules define the rules for what fields MUST be considered for
// Listeners to be distinct with each protocol currently defined in the
// Gateway API spec.
//
// The set of listeners that all share a protocol value MUST have _different_
// values for _at least one_ of these fields to be distinct:
//
// * **HTTP, HTTPS, TLS**: Port, Hostname
// * **TCP, UDP**: Port
//
// One **very** important rule to call out involves what happens when an
// implementation:
//
// 1. Multiple Listeners with the same Port that all use the "HTTP"
// Protocol that all have unique Hostname values.
// 2. Multiple Listeners with the same Port that use either the "HTTPS" or
// "TLS" Protocol that all have unique Hostname values.
// 3. A mixture of "TCP" and "UDP" Protocol Listeners, where no Listener
// with the same Protocol has the same Port value.
// * Supports TCP protocol Listeners, as well as HTTP, HTTPS, or TLS protocol
// Listeners, and
// * sees HTTP, HTTPS, or TLS protocols with the same `port` as one with TCP
// Protocol.
//
// Some fields in the Listener struct have possible values that affect
// whether the Listener is distinct. Hostname is particularly relevant
// for HTTP or HTTPS protocols.
// In this case all the Listeners that share a port with the
// TCP Listener are not distinct and so MUST NOT be accepted.
//
// When using the Hostname value to select between same-Port, same-Protocol
// Listeners, the Hostname value must be different on each Listener for the
// Listener to be distinct.
// If an implementation does not support TCP Protocol Listeners, then the
// previous rule does not apply, and the TCP Listeners SHOULD NOT be
// accepted.
//
// When the Listeners are distinct based on Hostname, inbound request
// Note that the `tls` field is not used for determining if a listener is distinct, because
// Listeners that _only_ differ on TLS config will still conflict in all cases.
//
// ### Listeners that are distinct only by Hostname
//
// When the Listeners are distinct based only on Hostname, inbound request
// hostnames MUST match from the most specific to least specific Hostname
// values to choose the correct Listener and its associated set of Routes.
//
// Exact matches must be processed before wildcard matches, and wildcard
// matches must be processed before fallback (empty Hostname value)
// Exact matches MUST be processed before wildcard matches, and wildcard
// matches MUST be processed before fallback (empty Hostname value)
// matches. For example, `"foo.example.com"` takes precedence over
// `"*.example.com"`, and `"*.example.com"` takes precedence over `""`.
//
// Additionally, if there are multiple wildcard entries, more specific
// wildcard entries must be processed before less specific wildcard entries.
// For example, `"*.foo.example.com"` takes precedence over `"*.example.com"`.
//
// The precise definition here is that the higher the number of dots in the
// hostname to the right of the wildcard character, the higher the precedence.
//
// The wildcard character will match any number of characters _and dots_ to
// the left, however, so `"*.example.com"` will match both
// `"foo.bar.example.com"` _and_ `"bar.example.com"`.
//
// ## Handling indistinct Listeners
//
// If a set of Listeners contains Listeners that are not distinct, then those
// Listeners are Conflicted, and the implementation MUST set the "Conflicted"
// Listeners are _Conflicted_, and the implementation MUST set the "Conflicted"
// condition in the Listener Status to "True".
//
// The words "indistict" and "conflicted" are considered equivalent for the
// purpose of this documentation.
//
// Implementations MAY choose to accept a Gateway with some Conflicted
// Listeners only if they only accept the partial Listener set that contains
// no Conflicted Listeners. To put this another way, implementations may
// accept a partial Listener set only if they throw out *all* the conflicting
// Listeners. No picking one of the conflicting listeners as the winner.
// This also means that the Gateway must have at least one non-conflicting
// Listener in this case, otherwise it violates the requirement that at
// least one Listener must be present.
// no Conflicted Listeners.
//
// Specifically, an implementation MAY accept a partial Listener set subject to
// the following rules:
//
// * The implementation MUST NOT pick one conflicting Listener as the winner.
// ALL indistinct Listeners must not be accepted for processing.
// * At least one distinct Listener MUST be present, or else the Gateway effectively
// contains _no_ Listeners, and must be rejected from processing as a whole.
//
// The implementation MUST set a "ListenersNotValid" condition on the
// Gateway Status when the Gateway contains Conflicted Listeners whether or
Expand All @@ -156,7 +187,25 @@ type GatewaySpec struct {
// Accepted. Additionally, the Listener status for those listeners SHOULD
// indicate which Listeners are conflicted and not Accepted.
//
// A Gateway's Listeners are considered "compatible" if:
// ## General Listener behavior
//
// Note that, for all distinct Listeners, requests SHOULD match at most one Listener.
// For example, if Listeners are defined for "foo.example.com" and "*.example.com", a
// request to "foo.example.com" SHOULD only be routed using routes attached
// to the "foo.example.com" Listener (and not the "*.example.com" Listener).
//
// This concept is known as "Listener Isolation", and it is an Extended feature
// of Gateway API. Implementations that do not support Listener Isolation MUST
// clearly document this, and MUST NOT claim support for the
// `GatewayHTTPListenerIsolation` feature.
//
// Implementations that _do_ support Listener Isolation SHOULD claim support
// for the Extended `GatewayHTTPListenerIsolation` feature and pass the associated
// conformance tests.
//
// ## Compatible Listeners
//
// A Gateway's Listeners are considered _compatible_ if:
//
// 1. They are distinct.
// 2. The implementation can serve them in compliance with the Addresses
Expand All @@ -171,13 +220,6 @@ type GatewaySpec struct {
// on the same address, or cannot mix HTTPS and generic TLS listens on the same port
// would not consider those cases compatible, even though they are distinct.
//
// Note that requests SHOULD match at most one Listener. For example, if
// Listeners are defined for "foo.example.com" and "*.example.com", a
// request to "foo.example.com" SHOULD only be routed using routes attached
// to the "foo.example.com" Listener (and not the "*.example.com" Listener).
// This concept is known as "Listener Isolation". Implementations that do
// not support Listener Isolation MUST clearly document this.
//
// Implementations MAY merge separate Gateways onto a single set of
// Addresses if all Listeners across all Gateways are compatible.
//
Expand Down
Loading

0 comments on commit 27b4aa8

Please sign in to comment.