-
Notifications
You must be signed in to change notification settings - Fork 40k
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
Detect CIDR IPv4 or IPv6 version to select nexthop #59749
Detect CIDR IPv4 or IPv6 version to select nexthop #59749
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, can we keep getAddressByName()?
Or use a small method since we are using the same thing 2 times, maybe use it at other function later.
@FengyunPan2 is it okay then if I pass |
877f937
to
a4c4dd2
Compare
@FengyunPan2 I pushed a new amended commit. Now the implementation uses the function and there is not code duplication. |
@@ -520,12 +521,12 @@ func getAddressByName(client *gophercloud.ServiceClient, name types.NodeName) (s | |||
} | |||
|
|||
for _, addr := range addrs { | |||
if addr.Type == v1.NodeInternalIP { | |||
if (addr.Type == v1.NodeInternalIP) && (govalidator.IsIPv6(addr.Address) == needIPv6) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be better to use the more generic 'net' package (instead of asaskevich/govalidator) to determine whether the address is IPv6, e.g.:
isIPv6 := net.ParseIP(addr.Address).To4() == nil
if addr.Type == v1.NodeInternalIP && isIPv6 == needIPv6 {
return addr.Address, nil
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hello @leblancd
I checked https://stackoverflow.com/questions/22751035/golang-distinguish-ipv4-ipv6
Please check in particular this answer: https://stackoverflow.com/a/48519490/1506396
It is the exaplanation why to use govalidator instead of the net package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @zioproto:
I would respectfully disagree with what the poster is claiming in this stackoverflow answer. Specifically, the list of addresses that are labeled "Valid IPv6 notations" should be labeled instead "IPv4-mapped IPv6 Notations" (RFC4291 and RFC4038). These addresses have an IPv6 format, but are intended to be internal representations of IPv4 addresses on the wire. They're essentially IPv4 addresses encapsulated in an IPv6 frame, and this is done so that dual-stack software can conveniently handle both IPv4 and IPv6 addresses as 16-byte entities. The net package's To4() takes care to look for this pattern in a 16-byte slice, and (correctly, I believe) creates an 4-byte (IPv4) slice from the lowest 4 bytes (since Golang can handle slices of arbitrary length, so there's no need to perpetuate the 16-byte internal representation of IPv4-mapped IPv6 addresses). In the examples given in the post, the only addresses that the net's To4() gets wrong, in my opinion, are the examples with :port appended, but To4() assumes that the caller has taken care of eliminating any :port (e.g. with splitHostPort()).
@@ -146,7 +148,10 @@ func (r *Routes) CreateRoute(ctx context.Context, clusterName string, nameHint s | |||
|
|||
onFailure := newCaller() | |||
|
|||
addr, err := getAddressByName(r.compute, route.TargetNode) | |||
IP, _, _ := net.ParseCIDR(route.DestinationCIDR) | |||
CIDRisV6 := govalidator.IsIPv6(IP.String()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as before, can use 'net' package to test for IPv6, e.g.:
CIDRisV6 := IP.To4() == nil
a4c4dd2
to
ad7089a
Compare
/ok-to-test |
Looks good to me. Thanks, @zioproto for taking care of this! |
/test pull-kubernetes-bazel-test |
@zioproto Yeah, nice work. |
@FengyunPan2: changing LGTM is restricted to assignees, and only kubernetes org members may be assigned issues. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/approve |
return addr.Address, nil | ||
} | ||
} | ||
|
||
return addrs[0].Address, nil | ||
return "", ErrNoAddressFound |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this last change, this function will only return InternalIPs. It should instead try ExternalIPs before giving up.
Aside: An alternate version might be to pass an address family down to getAddressesByName
and thence nodeAddresses
(with some value to indicate "all" families) and then do the filtering at the lowest level, when we know the address family from the openstack data structure. Happy to go with whatever version you think is best.
@@ -146,7 +147,10 @@ func (r *Routes) CreateRoute(ctx context.Context, clusterName string, nameHint s | |||
|
|||
onFailure := newCaller() | |||
|
|||
addr, err := getAddressByName(r.compute, route.TargetNode) | |||
IP, _, _ := net.ParseCIDR(route.DestinationCIDR) | |||
CIDRisV6 := IP.To4() == nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both IP
and CIDRisV6
should have (at least) a lowercased first letter, to conform with golang's public/private styleguide/rules.
@@ -219,7 +223,10 @@ func (r *Routes) DeleteRoute(ctx context.Context, clusterName string, route *clo | |||
|
|||
onFailure := newCaller() | |||
|
|||
addr, err := getAddressByName(r.compute, route.TargetNode) | |||
IP, _, _ := net.ParseCIDR(route.DestinationCIDR) | |||
CIDRisV6 := IP.To4() == nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto lowercased first letter of local variable.
/hold |
/lgtm cancel |
4c127c4
to
2eff8bf
Compare
/test pull-kubernetes-unit |
/hold cancel @anguslees please take another look |
/lgtm |
/lgtm cancel |
weird, i wanted to indicate lgtm without approving ... bot applied both! never ming. just waiting for @anguslees :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: anguslees, FengyunPan2, zioproto The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these OWNERS Files:
Approvers can indicate their approval by writing |
/test all [submit-queue is verifying that this PR is safe to merge] |
/retest Review the full test history for this PR. Silence the bot with an |
/test pull-kubernetes-e2e-kops-aws |
/test all [submit-queue is verifying that this PR is safe to merge] |
/test pull-kubernetes-unit |
/test all [submit-queue is verifying that this PR is safe to merge] |
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here. |
/cherrypick-candidate |
…pstream-release-1.9 Automatic merge from submit-queue. Automated cherry pick of #59749: Detect CIDR IPv4 or IPv6 version to select nexthop Cherry pick of #59749 on release-1.9. #59749: Detect CIDR IPv4 or IPv6 version to select nexthop ```release-note Fixing a bug in OpenStack cloud provider, where dual stack deployments (IPv4 and IPv6) did not work well when using kubenet as the network plugin. ```
What this PR does / why we need it:
The node
InternalIP
is used as nexthop by the Kubernetes master to create routes in the Neutron router for Pods reachability.If a node has more than one
InternalIP
s, eventually IPv4 and IPv6, a randomInternalIP
from the list is returned.This can lead to the bug described in #59421
We need to check when we build a route that the CIDR and the nexthop belong to the same IP Address Family (both IPv4 or both IPv6)
Which issue(s) this PR fixes :
Fixes #59421
It is related to #55202
Special notes for your reviewer:
This is the suggested way to fix the problem after the discussion in #59502
old release note: Issue #59421 was closed: the Openstack deployment with dual stack (IPv4 and IPv6) nodes and network-plugin=kubenet is now working properly.
Release note: