Skip to content

network: add socket interface#11278

Merged
mattklein123 merged 5 commits into
envoyproxy:masterfrom
florincoras:sock_interface
May 22, 2020
Merged

network: add socket interface#11278
mattklein123 merged 5 commits into
envoyproxy:masterfrom
florincoras:sock_interface

Conversation

@florincoras
Copy link
Copy Markdown
Member

Move socket calls that involve raw fds from address to socket.

Risk Level: Medium
Testing: unit tests
Docs Changes: n/a
Release Notes: n/a

Move socket calls that involve raw fds from address to socket.

Signed-off-by: Florin Coras <fcoras@cisco.com>
Signed-off-by: Florin Coras <fcoras@cisco.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.

Epic thanks, I can see the tech debt evaporating in front of me. :)

A few high level comments. Thank you!

/wait

return {getVersionFromAddress(socket.localAddress())};
} else {
return {getVersionFromAddress(Address::addressFromFd(socket.ioHandle().fd()))};
return {getVersionFromAddress(SocketInterface::addressFromFd(socket.ioHandle().fd()))};
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.

Do you want to fix this fd indirection in this PR or a follow up?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was planning on doing it in a subsequent PR (after the last in this series). Obviously, if that's fine with you :-)

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.

Yes that's fine.

Comment thread include/envoy/network/address.h Outdated
Comment on lines +95 to +98
/**
* @return true if address is Ipv6 and Ipv4 compatibility is disabled, false otherwise
*/
virtual bool v6only() const PURE;
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.

Can't this just be on the IPv6 interface? Why do we need it on the top level IP interface?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

At a high level, I didn't want to change the semantics of one of the existing socket functions which looks at "v6only()" property of the address to setsockopt(,IPV6_V6ONLY,). Not sure if this still makes sense after we finish moving everything to socket, but that's probably for a later time discussion.

So, with respect to the comment above, I did things this way because I didn't know how else to extract the field from the private IpHelper struct. Note though that I am somewhat C++ challenged :-(

I guess that one alternative would be to move the field to the Ipv6Helper struct and that should be then retrievable via a new function, e.g., address.ip().ipv6().v6only(). I didn't do this because I couldn't tell if somebody else relies on Ipv6Helper being nothing more than sockaddr_in6.

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 guess that one alternative would be to move the field to the Ipv6Helper struct and that should be then retrievable via a new function, e.g., address.ip().ipv6().v6only(). I didn't do this because I couldn't tell if somebody else relies on Ipv6Helper being nothing more than sockaddr_in6.

Right this is what I would do. The helper is just an implementation of an interface and I think this can live on the IPv6 interface?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done!

namespace Envoy {
namespace Network {

namespace SocketInterface {
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.

Do you want this to be an actual abstract class that you can inject later? Or you want to do that as a follow up? Ultimately I suspect you want this to hang off of the Api interface where we can handle platform injection more easily. Not sure if it's better to do it now or wait until later. I don't feel strongly about it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was planning on leaving it for later, especially because I'm not entirely sure about the best approach.

Originally, I was hoping I could hide all of the "raw" socket calls behind the SocketImpl constructors, but then I stumbled upon some places that only care about the IoHandles (and rely on syscalls to retrieve addresses and whatnot). So, I decided to postpone the decision until I completely migrate everything to SocketImpl.

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.

OK we can do the injection later.

return io_handle;
}

bool SocketInterface::ipFamilySupported(int domain) {
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.

This is a dup of the function in the address file, right? Can we collapse this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yup, it tries to reproduce what Ipv6Instance::socket() was doing. I think that the v6 specific logic should eventually be handled with socket->setOption(setv6only) so this could be cleaned up. However, v6only is true by default, so that could mean a lot of changes.

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 what I mean is this is the same function as https://github.com/envoyproxy/envoy/pull/11278/files#diff-3a2eb9279fdb086a43b5b47dcbe278cdR22-R32, right? Can you just have this be a utility function in network::utility or something?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sorry, I completely missed that you were pointing at ipFamilySupported.

I was about to mark this as done, but then noticed that the socket functions were built such that they cannot fail (RELEASE_ASSERT on the socket() return value), therefore we can't rely on this logic in the utility function to test if a socket type is usable.

So we're left with three options:

  • change SocketInterface::socket() to allow for failures (not sure about the impact in the rest of the codebase ..)
  • do the af test in a different way, but that will probably involve introducing a new SocketInterface function, i.e., something like SocketInterface::socket() that can fail.
  • keep on using this for now ...

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 really confused. AFAICT the body of this function is exactly the same as the one I pointed to. Why can't they be shared?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

As usual, I'm the one confused (I thought you felt this function didn't belong to SocketInterface).

The duplication is actually a byproduct of how I split the original PR. In the next PR, I'll completely remove the validateIpvXSupported check from the address, together with the remaining socket api calls, and wanted to have that conversation once we get there. If you think we shouldn't remove the validations, I can add a utility function now.

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.

OK if you are going to deal with this in a follow up it's fine to leave. SGTM. Can you push the other change and I can take a look?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Here's a draft patch

I can also rebase the patch and push a separate PR if that works better.

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.

We can just do it as a follow up. Thank you!

Copy link
Copy Markdown
Member 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 quick replies! And apologies again for the confusion.

- move v6only to the Ipv6 interface

Signed-off-by: Florin Coras <fcoras@cisco.com>
Signed-off-by: Florin Coras <fcoras@cisco.com>
mattklein123
mattklein123 previously approved these changes May 21, 2020
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!

@mattklein123
Copy link
Copy Markdown
Member

/retest

@repokitteh-read-only
Copy link
Copy Markdown

🔨 rebuilding ci/circleci: coverage (failed build)

🐱

Caused by: a #11278 (comment) was created by @mattklein123.

see: more, trace.

@mattklein123
Copy link
Copy Markdown
Member

This has failed coverage twice, so might not be a flake. Can you see if any coverage is missing now? The report should be in CI artifacts.

/wait

Signed-off-by: Florin Coras <fcoras@cisco.com>
@florincoras
Copy link
Copy Markdown
Member Author

/retest

@repokitteh-read-only
Copy link
Copy Markdown

🔨 rebuilding ci/circleci: coverage (failed build)

🐱

Caused by: a #11278 (comment) was created by @florincoras.

see: more, trace.

@florincoras
Copy link
Copy Markdown
Member Author

Seems to be passing now but not sure if this is just a fluke or not. From the logs, it appears the hot restart tests did not run and because of that the overall code coverage dropped under 97%.

I managed to run the coverage script on one of my severs and, the one time I tried it, the hot restart test did fail. Weirdly enough, it does not fail when running it in isolation or as part of the whole test suite (timeouts maybe?).

I also tried the coverage script with the next PR and, again only one sample, that one passed.

@mattklein123
Copy link
Copy Markdown
Member

OK thanks. I think there is a known flake where hot restart coverage is not always being counted. cc @lizan

@mattklein123 mattklein123 merged commit 89150d1 into envoyproxy:master May 22, 2020
@florincoras
Copy link
Copy Markdown
Member Author

Thanks a lot, @mattklein123! Pushed last PR in this first series.

@florincoras florincoras deleted the sock_interface branch May 28, 2020 15:47
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