Skip to content

feat(tonic-xds): compute gRFC A42 request hash from header hash policy#2686

Merged
YutaoMa merged 8 commits into
grpc:masterfrom
madhurishgupta:madhurishgupta/a42-pr1-request-hash
Jun 18, 2026
Merged

feat(tonic-xds): compute gRFC A42 request hash from header hash policy#2686
YutaoMa merged 8 commits into
grpc:masterfrom
madhurishgupta:madhurishgupta/a42-pr1-request-hash

Conversation

@madhurishgupta

@madhurishgupta madhurishgupta commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Implement gRFC A42: xDS Ring Hash LB Policy in tonic-xds. It lands the per-request hash computation.

What this PR does

  • Adds a xds::resource::hash_policy module with HashPolicyConfig and the request-hash logic as impl methods:
    • HashPolicyConfig::request_hash(headers, policies) — folds each matching policy's hash into one value using XXH64 (seed 0, per A42) and Envoy's reference rotate-XOR combination (combined = rotl(combined, 1) ^ new), honoring the terminal flag; returns None if no policy produced a hash (picker then uses a random hash).
  • Adds RouteDecision.request_hash: Option, carried from the routing layer to the LB picker via request extensions.
  • resolve_route computes request_hash (currently with an empty policy list — TODO to populate from RDS RouteAction.hash_policy in a later PR).

Tests

Added UTs.
Currently this path won't be called in production.

Plan (A42 series)

  1. (this PR) Request-hash computation + plumbing.
  2. Ring-hash picker + member tracking — builds an A42-conformant ring (min/max ring size, XXH64-keyed vnodes) over the cluster's healthy endpoints and routes each request by its hash; falls through to the next ready endpoint on a miss.
  3. CDS wiring — parse lb_policy: RING_HASH and ring_hash_lb_config (validating hash_function == XX_HASH), and select the ring-hash picker from the cluster's LB policy.
  4. RDS wiring — parse RouteAction.hash_policy to populate the policy list (replacing the empty scaffold here).

@linux-foundation-easycla

linux-foundation-easycla Bot commented Jun 15, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: madhurishgupta / name: Madhurish Nitish Gupta (45848fb)

@madhurishgupta madhurishgupta force-pushed the madhurishgupta/a42-pr1-request-hash branch from 45848fb to 5745c41 Compare June 15, 2026 20:19
Comment thread tonic-xds/src/xds/routing.rs Outdated
Comment thread tonic-xds/src/xds/routing.rs Outdated
Comment thread tonic-xds/src/xds/resource/route_config.rs Outdated
Comment thread tonic-xds/src/xds/routing.rs Outdated
Comment thread tonic-xds/src/xds/routing.rs Outdated
Comment thread tonic-xds/src/xds/routing.rs Outdated
@YutaoMa

YutaoMa commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Specify this is scoped for tonic-xds in PR title for better discoverability.

@madhurishgupta madhurishgupta changed the title Compute gRFC A42 request hash from header hash policy feat(tonic-xds): compute gRFC A42 request hash from header hash policy Jun 17, 2026
Adds the request-hash computation that the ring-hash LB picker (A42) will
consume, ahead of the picker itself:

- HashPolicyConfig::Header type (RDS parsing deferred to a later PR)
- RouteDecision.request_hash field
- compute_request_hash(): XXH64 seed-0 with Envoy's rotate-XOR combination
  and terminal short-circuit
- resolve_route populates request_hash from a default header policy
  ("x-ring-hash-key") as scaffolding until RDS hash_policy parsing lands

Adds the xxhash-rust dependency. Core-first sequencing: the data plane is
built and tested before xDS config wiring.
@madhurishgupta madhurishgupta force-pushed the madhurishgupta/a42-pr1-request-hash branch from 5745c41 to 6ad7479 Compare June 17, 2026 21:40
madhurishgupta and others added 4 commits June 17, 2026 14:59
content-type is hashed correctly by the generic header path (tonic always
sets content-type=application/grpc before routing), matching grpc-go, so no
special-casing is owed.
Per gRFC A42, a terminal hash policy stops further combination once any
hash has been generated, even if the terminal policy itself produced no
hash (e.g. its header is absent). The previous code only short-circuited
when the terminal policy matched, diverging from Envoy/grpc-go.

Move the terminal check out of the matched branch and gate it on the
accumulated hash. Add a test covering a terminal policy with an absent
header following a matching policy.
@madhurishgupta madhurishgupta force-pushed the madhurishgupta/a42-pr1-request-hash branch from c7e951e to 1dea873 Compare June 17, 2026 23:25
Comment thread tonic-xds/src/xds/resource/hash_policy.rs Outdated
…ffer

Hash the comma-joined header values straight into a streaming Xxh64 hasher
instead of building a concatenated Vec. XXH64 is boundary-independent, so the
digest is unchanged (existing pinned-digest tests still pass); this removes
the multi-value allocation and unifies the single- and multi-value paths.
@YutaoMa YutaoMa merged commit 57d0526 into grpc:master Jun 18, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants