Skip to content

quic: refactor QUICHE flag implementation#18485

Closed
lkpdn wants to merge 12 commits intoenvoyproxy:mainfrom
lkpdn:eliminate-quic-flag-access-contention
Closed

quic: refactor QUICHE flag implementation#18485
lkpdn wants to merge 12 commits intoenvoyproxy:mainfrom
lkpdn:eliminate-quic-flag-access-contention

Conversation

@lkpdn
Copy link
Copy Markdown

@lkpdn lkpdn commented Oct 6, 2021

QUICHE QUIC_FLAG implementation should be backed by Envoy runtime features not only because it's the canonical way (*1) but also for performance reasons.

It is observed that some quiche::TypedFlag access on the QUICHE datapath becomes a major scaling bottleneck when downstream QUIC traffic is heavy.

Simply replacing absl::MutexLock in TypedFlag implementation with absl::(Reader|Writer)MutexLock where possible is not satisfactory. The bottleneck would just move from the contention on the MutexLock to the atomic operation on the refcount in the new ReaderMutexLock done by each Envoy worker thread. We need a truly scalable flag accessing. Unfortunately, Envoy::Runtime::runtimeFeatureEnabled is also not contention-free since the snapshot created by createNewSnapshot() is shared by every worker thread, which again leads to the refcount contention.

With this patch With this PR and #18601, Envoy QUIC performance scales quite well. Please see the attached plot of the scalability comparison between Envoy (as a) QUIC server with-and-without this patch.

(*1) https://github.com/envoyproxy/envoy/blob/1b9c688997f5/source/common/quic/platform/quiche_flags_impl.h#L22-L24


(As a side note, added on 2021/10/11)

Envoy::Runtime::runtimeFeatureEnabled is also not contention-free since the snapshot created by createNewSnapshot() is shared by every worker thread, which again leads to the refcount contention.

This is the reason why do we not only make QUICHE flag implementation backed by Envoy runtime features, but also "unshare" SnapshotImpl. But the contention really occurs? how to reproduce it? The way to reproduce it and its result are shown below:

  • How to reproduce it?
    • build envoy server for two commits
    • environment
      • launch two AWS EC2 c6gn.16xlarge instances (1 client + 1 server)
    • prepare a config file
    • start an Envoy server with the config above
    • pin each worker thread onto a cpu core
    • stress the server from the client, using h2load (https://github.com/nghttp2/nghttp2/tree/quic)
      $ sudo docker run --rm -t --network=host localhost/h2load-quic -c 64 -t 64 -m 800 --warm-up-time=40s -D 40s --tls13-ciphers=TLS_AES_128_GCM_SHA256 --npn-list h3 --connect-to {{ server_ip }}:443 https://127.0.0.1/f1m.dat
      
    • run perf-record on the server side while stressing
      $ sudo perf record -g -t {{ a worker tid }} -- sleep 15
      
  • Results
    • flamegraph
    • zoom into the hot spot, seen in the former (56152d2)
      Samples: 60K of event 'cycles', 4000 Hz, Event count (approx.): 30325457223
      Envoy::ThreadLocal::InstanceImpl::SlotImpl::get  /home/ubuntu/quic/envoy-dev/linux/arm64/build_envoy_debug/envoy [Percent: local period]
      Percent│
             │
             │
             │    Disassembly of section .text:
             │
             │    0000000003e1a040 <Envoy::ThreadLocal::InstanceImpl::SlotImpl::get()>:
             │    _ZN5Envoy11ThreadLocal12InstanceImpl8SlotImpl3getEv():
             │      stp  x29, x30, [sp, #-48]!
             │      str  x21, [sp, #16] 
             │      stp  x20, x19, [sp, #32]
             │      mov  x29, sp
             │      ldr  w20, [x0, #16]
             │      mov  x19, x8
             │      mov  x0, #0x10000                    // #65536
             │      movk x0, #0x3400
             │      nop  
             │      nop  
             │      mrs  x21, tpidr_el0
             │      ldrb w8, [x21, x0]
             │    ↓ cbz  w8, 80
             │34:   mov  x0, #0x10000                    // #65536
             │      movk x0, #0x33e0
             │      nop  
        0.00 │      nop  
             │      add  x8, x21, x0
             │      ldr  x8, [x8, #8] 
             │      add  x8, x8, x20, lsl #4
             │      ldp  x9, x8, [x8]
             │      stp  x9, x8, [x19]
             │    ↓ cbz  x8, 70
        0.00 │      add  x8, x8, #0x8
       28.44 │60:   ldxr x9, [x8]
       70.41 │      add  x9, x9, #0x1
             │      stxr w10, x9, [x8]
        0.05 │    ↑ cbnz w10, 60
        1.10 │70:   ldp  x20, x19, [sp, #32]
             │      ldr  x21, [sp, #16]
             │      ldp  x29, x30, [sp], #48
             │    ← ret  
             │80:   mov  x0, #0x10000                    // #65536
             │      movk x0, #0x3400
             │      nop
      

Risk Level: Low
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]

@repokitteh-read-only
Copy link
Copy Markdown

Hi @lkpdn, welcome and thank you for your contribution.

We will try to review your Pull Request as quickly as possible.

In the meantime, please take a look at the contribution guidelines if you have not done so already.

🐱

Caused by: #18485 was opened by lkpdn.

see: more, trace.

@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch from c47c097 to 375fe66 Compare October 7, 2021 04:36
@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 7, 2021

Forgot to run git pre-push. I've just force-pushed to clear up some formatting issues.
Please review, thanks.

@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch from 375fe66 to 8b9408a Compare October 7, 2021 06:17
@repokitteh-read-only repokitteh-read-only Bot added the deps Approval required for changes to Envoy's external dependencies label Oct 7, 2021
@repokitteh-read-only
Copy link
Copy Markdown

CC @envoyproxy/dependency-shepherds: Your approval is needed for changes made to (bazel/.*repos.*\.bzl)|(bazel/dependency_imports\.bzl)|(api/bazel/.*\.bzl)|(.*/requirements\.txt)|(.*\.patch).

🐱

Caused by: #18485 was synchronize by lkpdn.

see: more, trace.

@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch from 8b9408a to 58b0355 Compare October 7, 2021 09:56
@alyssawilk
Copy link
Copy Markdown
Contributor

Awesome find! Mind taking a look at the presubmits and seeing if you can sort them out?
/wait

@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 7, 2021

I'll look into it. Before that, let me rebase to the latest main branch.

@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch from 58b0355 to 87dffe0 Compare October 7, 2021 14:13
Comment thread source/common/runtime/runtime_impl.cc Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quick question: what is the contention that this part of the change solves? It's not immediately clear to me whether the contention is on just referencing the shared_ptr object (seems unlikely) or something internal to the snapshot? Can you add more details?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the former that seemed unlikely to me too. Each thread has a local slot in thread_local_data_.data_, though the stored snapshot is shared among them so the contention happens.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But contention on what? Actually accessing the shared_ptr just to return a reference? I would be curious to see a perf trace about this part specifically, because I would prefer to not change this unless it really provides a lot of benefit and if so we should understand it more.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just added a side note in this PR description. Could you take a look a it?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the perf trace! It looks like InstanceImpl::SlotImpl::getWorker(uint32_t index) has heavy contention. @jmarantz could take a look to see if the contention is expected?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are my opinion:

One thing I wonder is whether we could have an access variant that does not incref if we know it's safe

If each thread had a weak_ptr to a new snapshot, when the next createNewSnapshot() invoked and the old one destructor runs, each thread may have a dangling pointer to them until it'll be replaced with a new one.

the runtime system appears to be using the untyped variants of TLS slots. It would be great to change them to use the typed versions and eliminate dynamic casts.

I didn't consider this.

A good pattern is to use them when the code being locked is long-running (ie more than just returning a shared_ptr).

I agree.

But if I'm not mistaken this change creates separate shared pointers for every worker all pointing to the same snapshot instance. And this may cause races.

It creates separate shared pointers for every worker all pointing to the "copied" snapshot instance. (So, essentially It does not need to be shared_ptr now, but if we change the part in this PR, the diff would be too large I guess.)

Copy link
Copy Markdown
Member

@rojkov rojkov Oct 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It creates separate shared pointers for every worker all pointing to the "copied" snapshot instance. (So, essentially It does not need to be shared_ptr now, but if we change the part in this PR, the diff would be too large I guess.)

I see, I misread make_shared as shared_ptr. Can this part be split into a separate PR?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm suggesting something slightly different if this is actually a contention issue:

  1. Still share the data via shared_ptr.
  2. Have a variant which effectively returns the reference *shared_ptr.get().
  3. We know this is safe because of the RCU like semantics as long as the reference is only used during that function call.

I think this should avoid any atomic interaction.

Either way I agree with @rojkov let's please split this part out and discuss separately?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the comment. I'm not sure I understand your idea correctly so let me ask a few questions:

  • Coud you explain "RCU like semantics" in detail?
  • Looking at the second point you mentioned, I thought the idea is to avoid dynamic_pointer_cast from LoaderImpl::threadSnapshot() and change SnapshotConstSharedPtr to a more plain reference. Am I correct?

But anyway,

Either way I agree with @rojkov let's please split this part out and discuss separately?

Alright, I'll split this part out, leaving the "QUIC flags backed by runtime features" part in this PR 18485.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We sometimes use this in tests, can we just implement it somehow?

Copy link
Copy Markdown
Author

@lkpdn lkpdn Oct 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

56152d2 removed those call sites. And I think it should be done with Runtime::LoaderSingleton::getExisting()->mergeValues when some flags need to be tweaked in tests.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I was wrong. I didn't remove SetQuicheReloadableFlagImpl call sites in tests at all.
To be honest, I don't see any merit keeping these set/get testing if the quic flag implementation is to be integrated to Envoy runtime feature infrastructure.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do need SetQuicheReloadableFlagImpl() sometimes even in non-test code in case where Envoy needs a feature/fix in QUICHE which is not turned on yet.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I got it. I'll implement it. Thank you.

@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch from 87dffe0 to d4f01ac Compare October 8, 2021 06:44
@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 8, 2021

I looked into the presubmits failures, then I noticed that the copy constructor implementation of SnapshotImpl that I added was incomplete. Almost all failures looked like due to the empty EntryMap value_ (but of course generator_ and stats_ were incorrectly missing).

Rather than introducing the copy construction and messing the code base, just calling createNewSnapshot for each thread looks simple, so I pushed d4f01ac.

@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 8, 2021

It seems that multiple createNewSnapshot calls cause RuntimeStats' load_(success|error) counters to be incorrectly incremented multiple times, leading to the new presubmit failures. To summarize the current situtation,

  • The upstream implementation shares the whole SnapshotImpl, which is one of the causes of the scalability issue.
  • In this PR, the third commit tries to unshare the SnapshotImpl.
    • (1st try) 87dffe0 tried to copy the whole structure for each thread. Due to my incomplete implementation of SnapshotImpl copy constructor, it caused some failures.
    • (2nd try) d4f01ac also intends to copy the whole structure. Again, I noticed after I git-pushed it that it's problematic around RuntimeStats' load_(success|error) counting.

After thinking carefully, I realized that only EntryMap values_ needs to be unshared from performance perspective. I will make a patch (3rd try, in a more careful manner). I'd appreciate if you could give me some help/advice though.

@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch 2 times, most recently from 192a16f to be7ec15 Compare October 11, 2021 13:45
@danzh2010
Copy link
Copy Markdown
Contributor

danzh2010 commented Oct 11, 2021

/assign @RenjieTang who implemented QUICHE flags with Envoy runtime.

@RenjieTang
Copy link
Copy Markdown
Contributor

Wow an interesting find! Thanks for fixing this.

@jmarantz
Copy link
Copy Markdown
Contributor

Before diving in I want to say this is one of the crispest, most detailed, data-driven PR descriptions I have ever seen. Nice.

@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch from be7ec15 to d0186f0 Compare October 12, 2021 02:37
The currently used QUICHE for envoy integration already contains the
upstream commit 68b06f23af21 ("Refactor QUICHE platform flag accessors.")
so these accessor implementations are no longer needed.

Signed-off-by: Koichiro Den <den@valinux.co.jp>
@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch 2 times, most recently from 0ccb9d9 to bdbfd1c Compare October 12, 2021 10:08
@alyssawilk
Copy link
Copy Markdown
Contributor

side note, please don't force push as it complicates the review process. Please merge from main rather than rebase for updates. thanks!

Koichiro Den added 3 commits October 14, 2021 00:30
- As the flags are now backed by Envoy Runtime Configuration, updating
  those values online from inside should be prohibited. They should just
  be updated in the same way as other runtime features.
- QUIC_PROTOCOL_FLAG implementation is converted to plain global variables.

Signed-off-by: Koichiro Den <den@valinux.co.jp>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
…-access-contention

Signed-off-by: Koichiro Den <den@valinux.co.jp>
@lkpdn lkpdn force-pushed the eliminate-quic-flag-access-contention branch from e22e06e to 3786431 Compare October 13, 2021 15:31
@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 13, 2021

@mattklein123 Alright, done.

@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 13, 2021

Note that the reason I added a commit 850bb91 is not because I added some new code that is not covered by testing. It just seems that deleting some covered lines makes the final result down to 95.9%.

Copy link
Copy Markdown
Contributor

@danzh2010 danzh2010 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this! I left a few nits, but looks good overall!
@RenjieTang, do you mind take a look as well?

Comment thread source/common/quic/platform/quiche_flags_impl.h Outdated
Comment thread source/common/quic/active_quic_listener.cc
Comment thread source/common/quic/envoy_quic_dispatcher.cc
"//envoy/runtime:runtime_interface",
"//source/common/common:hash_lib",
"//source/common/singleton:const_singleton",
"@com_github_google_quiche//:quic_core_flags_list_lib",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will need envoy_select_enable_http3() for this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. I'll push a fix shortly. Thank you!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed that the quic platform tests had been executed successfully even when http3=False build.
quiche::FlagRegistry was holding quic flags even if http3=False.
So, in order to make it run even after making it backed by runtime features, in 3a13a02 I reverted this part.

Comment thread test/common/quic/platform/http2_platform_test.cc
testNewOverrides(*loader_, store_);
}

#ifdef ENVOY_ENABLE_QUIC
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this test removed?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just forgot to revert this dropping after #18485 (comment). Just my mistake. I'll push a fix, thanks!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In e4d8613, I modified and moved this test under RtdsLoaderImplTest . Now I wonder this PR somewhat would break backward compatibility. Some admin might expect they can override the QUICHE reloadable/restart flags from any layer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this why you added admin layer and called doOnConfigUpdateVerifyNoThrow(runtime, 0) in the test? I'm not familiar with the control plan, but updating flags from admin layer only seems fine to me. @htuch

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if something is a runtime flag, it should ideally be updatable from any runtime layer, otherwise we violate principle-of-least-surprise (every other runtime flag should have this capability). Is there a reason we can't do this for QUIC?

Copy link
Copy Markdown
Author

@lkpdn lkpdn Oct 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My comment #18485 (comment) was somewhat perplexing.

It's updatable from any runtime layer. The point is that QUICHE flag could be updated at an arbitrary timing from inside, on admin layer, if such an implementation will be merged. That's why I dropped the SetQuiche(Reloadable|Restart)FlagsImpl capability in my original PR (ref. #18485 (comment)) though.

The current upstream implementation calls SetQuic(Reloadable|Restart)Flag from inside (e.g., on ActiveQuicListener instantiation). With this PR, those places will be eliminated, except tests.

So, basically administrators can update those flags from any runtime layer without worry.

In that sense, in the SetQuiche(Reloadable|Restart)FlagImpl implementation, replacing ASSERT(Envoy::Thread::MainThread::isMainOrTestThread()); with something like ASSERT(Envoy::Thread::MainThread::isTestThread()); might help.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SG - as long as we are treating the flags uniformly with other runtime flags then no objections.

Ref: #18485 (review)

Signed-off-by: Koichiro Den <den@valinux.co.jp>
@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 14, 2021

@danzh2010 Thank you for the review!

Just pushed e4d8613.
PTAL, thanks.

Koichiro Den added 2 commits October 14, 2021 13:48
Signed-off-by: Koichiro Den <den@valinux.co.jp>
…-access-contention

Signed-off-by: Koichiro Den <den@valinux.co.jp>
@mattklein123 mattklein123 removed their assignment Oct 14, 2021
…if http3=False

Signed-off-by: Koichiro Den <den@valinux.co.jp>
danzh2010
danzh2010 previously approved these changes Oct 15, 2021
Copy link
Copy Markdown
Contributor

@danzh2010 danzh2010 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread source/server/listener_impl.cc Outdated
Comment thread test/per_file_coverage.sh
# for existing directories with low coverage.
declare -a KNOWN_LOW_COVERAGE=(
"source/common:95.9" # Raise when QUIC coverage goes up
"source/common:96.0" # Raise when QUIC coverage goes up
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! Does source/common/quic/ coverage changed?

Copy link
Copy Markdown
Author

@lkpdn lkpdn Oct 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest CI coverage run failed in bazel coverage stage so the actual output (artifact, including logs) is not available.

But anyway, #18591 (ref. #17479 (comment)) was merged a few days ago, so I think we better to re-run and look at the result, with the new 95.9% threshold being untouched.

Comment thread test/integration/http_integration.cc Outdated
Comment thread test/common/runtime/runtime_impl_test.cc
testNewOverrides(*loader_, store_);
}

#ifdef ENVOY_ENABLE_QUIC
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this why you added admin layer and called doOnConfigUpdateVerifyNoThrow(runtime, 0) in the test? I'm not familiar with the control plan, but updating flags from admin layer only seems fine to me. @htuch

Comment thread test/common/runtime/runtime_impl_test.cc Outdated
Signed-off-by: Koichiro Den <den@valinux.co.jp>
@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 18, 2021

We got two new failures even though a9d5b2b is tiny diff.

  1. linux_x64 release https://dev.azure.com/cncf/envoy/_build/results?buildId=92194&view=logs&j=8c169225-0ae8-53bd-947f-07cb81846cb5&t=6b0ace90-28b2-51d9-2951-b1fd35e67dec&l=88 : looks irrelevant to this PR. I cannot reproduce this locally.
  2. linux_arm64 release https://dev.azure.com/cncf/envoy/_build/results?buildId=92194&view=logs&j=767be981-567e-57d8-68c3-2140ede0a0bd&t=1fb0b72f-6293-562d-a4d1-bb649223eaca&l=18128 : I cannot reproduce this locally + the segfault backtrace seen in the link gives me no clue. Looks relevant (because it's about quic) so it might be that this becomes flaky because of this PR. Will dig into this one.

@lkpdn
Copy link
Copy Markdown
Author

lkpdn commented Oct 19, 2021

Network::Address::InstanceConstSharedPtr local_addr,
QuicStatNames& quic_stat_names, Stats::Scope& scope) {
// This flag fix a QUICHE issue which may crash Envoy during connection close.
SetQuicReloadableFlag(quic_single_ack_in_packet2, true);
Copy link
Copy Markdown
Contributor

@danzh2010 danzh2010 Oct 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Envoy runtime work for client side? @ggreenway
If not, we still need to set this flag here and quiche::FlagRegistry::getInstance() above.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answer to myself, yes, RuntimeFeature is a singleton instantiated upon fetching a feature.

@github-actions
Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@github-actions github-actions Bot added the stale stalebot believes this issue/PR has not been touched recently label Nov 25, 2021
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Dec 2, 2021

This pull request has been automatically closed because it has not had activity in the last 37 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions!

@github-actions github-actions Bot closed this Dec 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deps Approval required for changes to Envoy's external dependencies stale stalebot believes this issue/PR has not been touched recently waiting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants