Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Locally listen on IPv4 and IPv6 addresses #775

Closed
wants to merge 2 commits into from

Conversation

markmandel
Copy link
Member

What type of PR is this?

Uncomment only one /kind <> line, press enter to put that in a new line, and remove leading whitespace from that line:

/kind breaking
/kind bug
/kind cleanup
/kind documentation

/kind feature

/kind hotfix

What this PR does / Why we need it:

Implemented the DualStackLocalSocket for the locally listening socket, and updated the code base and fixed several issues that existed for handling IPv6 addresses in the code base.

This included updating the test_utils framework to provide coverage in tests for both ipv4 and ipv6 by allowing for either an IPv4 or IPv6 address to be created from the framework.

Which issue(s) this PR fixes:

Closes #666

Special notes for your reviewer:

Let me know what you think of the Random address type approach. Felt like the easiest way to get general coverage and force testing of both paths, without having to have some kind of dual-run test harness.

@markmandel markmandel added kind/feature New feature or request area/user-experience Pertaining to developers trying to use Quilkin, e.g. cli interface, configuration, etc labels Aug 16, 2023
Implemented the `DualStackLocalSocket` for the locally listening socket,
and updated the code base and fixed several issues that existed for
handling IPv6 addresses in the code base.

This included updating the `test_utils` framework to provide coverage in
tests for both ipv4 and ipv6 by allowing for either an IPv4 or IPv6
address to be created from the framework.

Closes googleforgames#666
@markmandel
Copy link
Member Author

markmandel commented Aug 16, 2023

Huh weird. Testing locally with cargo seems to work just fine, but when running inside the container test suite, it falls over.

At least I can replicate locally.

@markmandel
Copy link
Member Author

If I run the tests in the container with --network=host, everything passes! So I'm thinking it's something to do with binding to 0.0.0.0 / [::] or something like that in the container? 🤔

@markmandel
Copy link
Member Author

Now I'm actually wondering if I can use a socket with set_only_v6(false); to be a dual stack socket, without all this extra work.... which may be why this is failing in (potentially) a slightly different kernel/network setup.

I'll take it for a spin and let you know how I go.

@XAMPPRocky
Copy link
Collaborator

XAMPPRocky commented Aug 17, 2023

Now I'm actually wondering if I can use a socket with set_only_v6(false); to be a dual stack socket

I think I tried that before, I believe that won't work cross-platform. Maybe we can find a compromise that's good enough.

Copy link
Collaborator

@XAMPPRocky XAMPPRocky left a comment

Choose a reason for hiding this comment

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

LGTM! Small nits and questions, but overall the approach is good.

Comment on lines +138 to +141
let len = value.len();
if len > 2 && value.starts_with('[') && value.ends_with(']') {
return value[1..len - 1].to_string();
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do the brackets not work when passed in? 🤔 Isn't that part of the address?

Copy link
Member Author

Choose a reason for hiding this comment

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

If the brackets are still there in the host when it gets to

let host = host.parse::<AddressKind>().unwrap();

Then it parses it as as AddressKind(Name("[::]")) rather than AddressKind(Ip(V6("::"))), which is not what we want.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Right, but I think a better solution would be to update the FromStr implementation of AddressKind to handle that instead of EndpointAddress, so that it's always correct, rather than EndpointAddress::parse and AddressKind::parse providing different results.

Copy link
Member Author

Choose a reason for hiding this comment

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

Aaah gotcha. I will make that change 👍🏻

Comment on lines +66 to +72
let mut rng = thread_rng();
// sometimes give ipv6, sometimes ipv4.
match rng.gen_range(0..2) {
0 => socket.local_ipv6_addr().unwrap(),
1 => socket.local_ipv4_addr().unwrap(),
_ => unreachable!(),
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can simplify this by using rand::random.

Suggested change
let mut rng = thread_rng();
// sometimes give ipv6, sometimes ipv4.
match rng.gen_range(0..2) {
0 => socket.local_ipv6_addr().unwrap(),
1 => socket.local_ipv4_addr().unwrap(),
_ => unreachable!(),
}
match rand::random() {
true => socket.local_ipv6_addr().unwrap(),
false => socket.local_ipv4_addr().unwrap(),
}

@markmandel
Copy link
Member Author

I think I tried that before, I believe that won't work cross-platform. Maybe we can find a compromise that's good enough.

That was my conclusion as well from research, but now I don't actually know. I'm trying some small experiments.

@markmandel
Copy link
Member Author

Just dropping research so I can also find it later:

Seems to indicate that a dual stack socket will work on windows, but the default for a socket is different on Windows (IPV6_V6ONLY is true by default on windows, but false on Linux).

So I think we can do this with one ipv6 socket -- but the testing changes through here will still be useful at least.

Making updates and will see how we go.

@markmandel
Copy link
Member Author

Initial tests with a ipv6 socket with IPV6_V6ONLY set to false look very promising! (saves us a select on each socket, so that is nice!)

But that helped me narrow down the issue - within a Docker container, it seems that it hates sending traffic to [::].

I may just force it to run on --network=host and call it a day.

@quilkin-bot
Copy link
Collaborator

Build Failed 😭

Build Id: e339579e-921b-42a6-b240-718d8994cf27

Status: FAILURE

To get permission to view the Cloud Build view, join the quilkin-discuss Google Group.

Filter with the Git Commit 0757e1d within us-docker.pkg.dev/quilkin/ci//quilkin to see if a development image is available from this build, and can be used for debugging purposes.

Development images are retained for at least 30 days.

@markmandel
Copy link
Member Author

I've got work on this going on a separate branch (using purely ipv6 sockets). Will likely close this PR and resubmit, but just keeping it open since there's some feedback I want to make sure I capture in here.

@markmandel
Copy link
Member Author

New PR incoming using ipv6 sockets, shortly, closing this one to avoid the noise. Also incorporates the feedback in here.

@markmandel markmandel closed this Sep 13, 2023
@markmandel markmandel deleted the feature/ipv6nv4 branch September 21, 2023 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/user-experience Pertaining to developers trying to use Quilkin, e.g. cli interface, configuration, etc kind/feature New feature or request size/l
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Listening on IPv4 and IPv6 addresses
3 participants