Skip to content

quiche: modify some envoy quic implementation for code sharing#8349

Merged
mattklein123 merged 39 commits intoenvoyproxy:masterfrom
danzh2010:refactorquiche
Oct 2, 2019
Merged

quiche: modify some envoy quic implementation for code sharing#8349
mattklein123 merged 39 commits intoenvoyproxy:masterfrom
danzh2010:refactorquiche

Conversation

@danzh2010
Copy link
Copy Markdown
Contributor

@danzh2010 danzh2010 commented Sep 24, 2019

Refactor EnvoyQuicServerSession to inherit from QuicFilterManagerConnectionImpl which implements most of the Network::FilterManagerConnection interface. This base class can be shared with client side implementation. Also split out some server side logic from EnvoyQuicConnection into EnvoyQuicServerConnection. So that EnvoyQuicConnection can be shared with client connection implementation

Modify EnvoyQuicPacketWriter to wrap a Socket& rather than Listener& because client side doesn't have listener. Extract socket write code from UdpListenerImpl::send() to Network::Utility so that writer can use same code for writing.

Alike wise, move some socket read logic in UdpListenerImpl::handleReadCallback() into Utility for code sharing with client connection later.

Made a slight change in EnvoyQuicServerSession to raiseEvent with type Connected when handshake is done.

Convert some ASSERT of not implemented feature to NOT_IMPLEMENT or NOT_REACHED.

Risk Level: low, refactor to unused code
Testing: existing tests
Part of #2557

Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
@danzh2010
Copy link
Copy Markdown
Contributor Author

/assign @alyssawilk

@mattklein123 mattklein123 self-assigned this Sep 26, 2019
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thanks, flushing out a few more comments.

/wait


void QuicFilterManagerConnectionImpl::addBytesSentCallback(
Network::Connection::BytesSentCb /*cb*/) {
// TODO(danzh): implement to support proxy. This interface is only called from
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 would prefer that we either crash hard if things should not happen, or actually implement stuff. Since QUIC is not production ready yet, can we just make everything that shouldn't happen NOT_IMPLEMENTED for now? Same elsewhere?

}

std::chrono::milliseconds QuicFilterManagerConnectionImpl::delayedCloseTimeout() const {
// Not called outside of Network::ConnectionImpl. Maybe remove this interface
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.

That's fine, please make this an actual TODO.

const Network::ConnectionSocket::OptionsSharedPtr&
QuicFilterManagerConnectionImpl::socketOptions() const {
ENVOY_CONN_LOG(
error,
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.

Per elsewhere, let's please not log at error, etc. Let's either implement or NOT_IMPLEMENTED everywhere in this file.

Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Signed-off-by: Dan Zhang <danzh@google.com>
Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Sorry to keep going back and forth on this but I would still like to tighten up the interfaces a bit more in terms of the things we need to implement, the things that can't happen, etc. Thank you!

/wait

}

void QuicFilterManagerConnectionImpl::enableHalfClose(bool enabled) {
ASSERT(!enabled, "Quic connection doesn't support half close.");
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.

Does this get called? Can this be NOT_IMPLEMENTED?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This should only be called with enable == true. This is the implementation desired.

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 would make this a RELEASE_ASSERT then just to check our assumption.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

// TODO(danzh): add interface to quic for connection level buffer throttling.
// Currently read buffer is capped by connection level flow control. And
// write buffer is not capped.
ENVOY_CONN_LOG(error, "Quic manages its own buffer currently.", *this);
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.

Does this get called? Can this be NOT_IMPLEMENTED? If it does get called can we just have this be an empty function with the TODO?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

According to my next PR, this method shouldn't be called. I changed it to NOT_REACHED here.

void QuicFilterManagerConnectionImpl::close(Network::ConnectionCloseType type) {
if (type != Network::ConnectionCloseType::NoFlush) {
// TODO(danzh): Implement FlushWrite and FlushWriteAndDelay mode.
ENVOY_CONN_LOG(error, "Flush write is not implemented for QUIC.", *this);
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.

Same here? Basically can we remove the error logs and just crash or have a TODO?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We don't want to crash, as it's called by HCM with other CloseType. Removed the error log. The empty if block looks weird though...

}

Ssl::ConnectionInfoConstSharedPtr QuicFilterManagerConnectionImpl::ssl() const {
// TODO(danzh): construct Ssl::ConnectionInfo from crypto stream
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.

Per the comments above can we just remove the error logs? If something will be implemented later I think it's fine to just leave a TODO?

Essentially what I would like to see is:

  1. No error logs in this type of code
  2. NOT_IMPLEMENTED if it can't happen with a comment why.
  3. Or a default implementation with a TODO to implement the real thing.

void setDelayedCloseTimeout(std::chrono::milliseconds timeout) override;
std::chrono::milliseconds delayedCloseTimeout() const override;
void readDisable(bool disable) override {
ASSERT(!disable, "Quic connection should be able to read through out its life time.");
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.

For these normal asserts, do these functions get called? Or should they not get called at all? Same elsewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It shouldn't be called for multiplexing case according to my reading of the HCM implementation. I might be wrong, but NOT_REACHED for now.

Signed-off-by: Dan Zhang <danzh@google.com>
Copy link
Copy Markdown
Contributor Author

@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.

I changed error log and ASSERT to NOT_REACHED in most of the places according to my current understanding. But I'm not sure how meaningful it would be to tighten the interface at this point, considering they might get reverted in integration tests if it turns out those places are reachable.

}

void QuicFilterManagerConnectionImpl::enableHalfClose(bool enabled) {
ASSERT(!enabled, "Quic connection doesn't support half close.");
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This should only be called with enable == true. This is the implementation desired.

void QuicFilterManagerConnectionImpl::close(Network::ConnectionCloseType type) {
if (type != Network::ConnectionCloseType::NoFlush) {
// TODO(danzh): Implement FlushWrite and FlushWriteAndDelay mode.
ENVOY_CONN_LOG(error, "Flush write is not implemented for QUIC.", *this);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We don't want to crash, as it's called by HCM with other CloseType. Removed the error log. The empty if block looks weird though...

// TODO(danzh): add interface to quic for connection level buffer throttling.
// Currently read buffer is capped by connection level flow control. And
// write buffer is not capped.
ENVOY_CONN_LOG(error, "Quic manages its own buffer currently.", *this);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

According to my next PR, this method shouldn't be called. I changed it to NOT_REACHED here.

void setDelayedCloseTimeout(std::chrono::milliseconds timeout) override;
std::chrono::milliseconds delayedCloseTimeout() const override;
void readDisable(bool disable) override {
ASSERT(!disable, "Quic connection should be able to read through out its life time.");
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It shouldn't be called for multiplexing case according to my reading of the HCM implementation. I might be wrong, but NOT_REACHED for now.

@danzh2010
Copy link
Copy Markdown
Contributor Author

/retest

@repokitteh-read-only
Copy link
Copy Markdown

🤷‍♀️ nothing to rebuild.

🐱

Caused by: a #8349 (comment) was created by @danzh2010.

see: more, trace.

@danzh2010
Copy link
Copy Markdown
Contributor Author

/azp envoy-linux(bazel release)

@azure-pipelines
Copy link
Copy Markdown

Command 'envoy-linux(bazel' is not supported by Azure Pipelines.

Supported commands
  • help:
    • Get descriptions, examples and documentation about supported commands
    • Example: help "command_name"
  • list:
    • List all pipelines for this repository using a comment.
    • Example: "list"
  • run:
    • Run all pipelines or a specific pipeline for this repository using a comment. Use this command by itself to trigger all related pipelines, or specify a pipeline to run.
    • Example: "run" or "run pipeline_name"
  • where:
    • Report back the Azure DevOps orgs that are related to this repository and org
    • Example: "where"

See additional documentation.

Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Thanks, almost there. Just a few more small comments. Also, can you please make it consistent between NOT_REACHED/NOT_IMPLEMENTED, or better, use NOT_REACHED when it for real should never happen and NOT_IMPLEMENTED/RELEASE_ASSERT when we need to implement it later as we add tests? Thank you!

/wait

}

void QuicFilterManagerConnectionImpl::enableHalfClose(bool enabled) {
ASSERT(!enabled, "Quic connection doesn't support half close.");
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 would make this a RELEASE_ASSERT then just to check our assumption.

}

Ssl::ConnectionInfoConstSharedPtr QuicFilterManagerConnectionImpl::ssl() const {
// TODO(danzh): construct Ssl::ConnectionInfo from crypto stream
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.

Sorry I'm not following what is going on here. Presumably this does need to be implemented eventually but if you NOT_IMPLEMENTED this now it crashes? I would remove the error log and just track with a TODO.

const Network::Address::InstanceConstSharedPtr& localAddress() const override;
absl::optional<Network::Connection::UnixDomainSocketPeerCredentials>
unixSocketPeerCredentials() const override {
ASSERT(false, "Unix domain socket is not supported.");
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.

Swap with NOT_IMPLEMENTED

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

NOT_REACHED_GCOVR_EXCL_LINE;
}
bool localAddressRestored() const override {
// SO_ORIGINAL_DST not supported by QUIC.
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'm pretty sure this will never get called. NOT_IMPLEMENTED?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

// them.
std::list<Network::ConnectionCallbacks*> network_connection_callbacks_;
std::string transport_failure_reason_;
uint64_t id_;
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.

nit: const

Signed-off-by: Dan Zhang <danzh@google.com>
Copy link
Copy Markdown
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

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

Nice, let's ship and iterate!

@mattklein123 mattklein123 merged commit 57ac960 into envoyproxy:master Oct 2, 2019
danzh2010 added a commit to danzh2010/envoy that referenced this pull request Oct 4, 2019
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.

4 participants