Skip to content

http2: add keepalive observer hook#44299

Open
roll-no-21 wants to merge 1 commit intoenvoyproxy:mainfrom
roll-no-21:http2-keepalive-observer
Open

http2: add keepalive observer hook#44299
roll-no-21 wants to merge 1 commit intoenvoyproxy:mainfrom
roll-no-21:http2-keepalive-observer

Conversation

@roll-no-21
Copy link
Copy Markdown
Contributor

Expose HTTP/2 keepalive send and ack events through a small observer interface so higher layers can react to codec keepalives without coupling reverse-tunnel logic into the core codec.

Commit Message: http2: add keepalive observer hook
Additional Description:

Today, higher-level extensions (e.g. reverse tunnel lifecycle logging) that
need to react to HTTP/2 keepalive events must either parse raw HTTP/2 frames
from network filter buffers or embed extension-specific logic directly in the
codec. Both approaches are undesirable — the first is fragile and works against
Envoy's layered architecture, and the second couples domain logic into core
protocol code.

This PR introduces a lightweight KeepaliveObserver interface that the HTTP/2
codec queries via connection FilterState on keepalive ping send and ack events.
If no observer is registered, the codec does nothing (null-check only). If an
observer is present, it receives callbacks with the connection's StreamInfo
and the PING opaque data.

New interface (keepalive_observer.h)

KeepaliveObserver extends StreamInfo::FilterState::Object and defines:

  • onKeepalivePingSent(StreamInfo::StreamInfo&, uint64_t opaque_data) — called
    immediately after the codec submits an HTTP/2 PING frame via the adapter.
  • onKeepalivePingAck(StreamInfo::StreamInfo&, uint64_t opaque_data) — called
    when the codec receives a PING ACK frame from the peer.
  • pendingKeepalivePingId() — returns the opaque data of the outstanding PING,
    if any, allowing the observer to correlate send/ack pairs.

The observer is looked up from FilterState under the key
envoy.http2.keepalive_observer.

Codec changes (codec_impl.cc)

  • sendKeepalive(): after adapter_->SubmitPing(), checks for an observer
    and calls onKeepalivePingSent() (~3 lines added).
  • onPing() (ACK path): after logging the PING ACK, checks for an observer
    and calls onKeepalivePingAck() (~3 lines added).
  • New private helper keepaliveObserver() retrieves the observer from
    connection_.streamInfo().filterState() (~6 lines).

Usage pattern

An upstream network filter sets a KeepaliveObserver implementation in
the connection's FilterState during onNewConnection(). The codec picks it
up automatically on the next keepalive cycle. Example:

filter_state.setData(
    kKeepaliveObserverFilterStateKey,
    std::make_shared<MyObserverImpl>(),
    StreamInfo::FilterState::StateType::ReadOnly,
    StreamInfo::FilterState::LifeSpan::Connection);

No observer registered → zero overhead beyond a null-check per ping event.

Risk Level: Low — opt-in via FilterState; no behavioral change when no observer
  is registered. The null-check in the keepalive hot path is negligible.
Testing: New ConnectionKeepaliveObserver test in codec_impl_test.cc
  validates that onKeepalivePingSent and onKeepalivePingAck are called in
  correct sequence with proper timer interactions using a MockKeepaliveObserver.
Docs Changes: N/A
Release Notes: N/A
Platform Specific Features: N/A

Expose HTTP/2 keepalive send and ack events through a small observer interface so higher layers can react to codec keepalives without coupling reverse-tunnel logic into the core codec.

Signed-off-by: Krishna Sharma <krishnagpl2001@gmail.com>
@roll-no-21
Copy link
Copy Markdown
Contributor Author

cc: @ivpr

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.

2 participants