-
Notifications
You must be signed in to change notification settings - Fork 788
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
bridge: Add support for IPv6 to bridge plugin #10
Conversation
@@ -392,7 +454,7 @@ func cmdDel(args *skel.CmdArgs) error { | |||
var ipn *net.IPNet | |||
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error { | |||
var err error | |||
ipn, err = ip.DelLinkByNameAddr(args.IfName, netlink.FAMILY_V4) |
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.
wow :-)
plugins/main/bridge/bridge.go
Outdated
// Add a default route for this family using the current | ||
// gateway address if necessary. | ||
if n.IsDefaultGW && !gws.defaultRouteFound { | ||
defaultNet.Mask = net.IPMask(defaultNet.IP) |
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.
Any reason you wouldn't do this above, where defaultNet.IP gets set?
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.
Hmmm... I think I was looking at execution efficiency and only executing the line when necessary, but I see your point that it's much clearer to just set the defaultNet fields in one place... so I'll move it.
plugins/main/bridge/bridge.go
Outdated
// Multiple IPv6 addresses are allowed. For IPv4, if | ||
// forceAddress is set to true then reconfigure IP address, | ||
// otherwise throw error. | ||
if family == netlink.FAMILY_V4 { |
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.
Is there a reason we wouldn't want to force the IPv6 address too? Obvoiusly the bridge could have an LL and a non-LL address, but I would expect ForceAddress to work for the IPv6 non-LL address as well.
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.
Yes, good point. It is a little complicated since we're allowing multiple V6 addresses on the bridge. Let's say we're adding addresses for two V6 subnets: subnet A and subnet B. When this function wants to set a V6 address on the bridge, and the new address happens to be within subnet A... then we'd only want to clear (force) the existing address that corresponds to subnet A (or declare error if ForceAddress is false).
plugins/main/bridge/bridge.go
Outdated
&types.Route{Dst: *defaultNet, GW: ipc.Gateway}, | ||
) | ||
} | ||
// Temporary workaround for Kubernetes Issue #32291. Disable |
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.
While this is fine for now, soon kubelet won't do anything hairpin related (see kubernetes/kubernetes#45790 (comment)) and that'll get punted to this plugin. So we'll know in the plugin if hairpin is enabled, and if so, whether we need to disable DAD or not. Can be a follow-on PR.
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.
if err := ip.SetHWAddrByIP(args.IfName, result.IPs[0].Address.IP, nil /* TODO IPv6 */); err != nil { | ||
return err | ||
if result.IPs[0].Address.IP.To4() != nil { | ||
if err := ip.SetHWAddrByIP(args.IfName, result.IPs[0].Address.IP, nil /* TODO IPv6 */); err != 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.
Also probably fine by now, but containernetworking/cni#448 removes this whole set-HW-addr-by-IP thing. But we can make @squeed rebase that onto this :)
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.
Or I can rebase onto his change. Either way works for me. :)
2372076
to
0ddcdd7
Compare
@dcbw I've made changes according to your suggestions:
|
0ddcdd7
to
9abe113
Compare
Test failures appear to be due to Travis test config issue fixed with PR #13. |
FWIW, once this is merged, I will have a PR that stops changing the mac address. |
@squeed, thanks, I saw your PR for retaining MAC address (using arp) in the containernetworking/cni repo. Looks good. I did some testing with your MAC address changes patched in with the changes here to make sure that it'll work when your arp changes merge. By the way, what is the best way to trigger a new round of travis tests? |
4804d31
to
37f8c0a
Compare
Hmm, I'm curious why you are adding the "local" route via the gateway - isn't one of the points of using a bridge that the packets don't need to be routed twice? |
@squeed : Can you clarify where the local route is being added? I am adding a default route (dest = ::0/0, not a /128) in the container via one of the addresses on the bridge. (I could have set the container's default route via the bridge's link local address, but I figured it was easier to just grab an address that I had on hand). I could be missing something. |
Ah, you're right - I misread the calcGateways function. The IsDefaultGateway flag in the bridge configuration strikes me as kind of useless (it should have been part of ipam), but oh well - now I understand why you need all that code. LGTM. |
@dcbw want to give this the second seal of approval? |
37f8c0a
to
9a8bc97
Compare
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.
This change adds support for IPv6 container/pod addresses to the CNI bridge plugin, both for dual-stack (IPv4 + IPv6) and for IPv6-only network configurations. The proposed changes support multiple IPv6 addresses on a container interface. If isGW is configured, the bridge will also be configured with gateway addresses for each IPv6 subnet. Please note that both the dual-stack functionality and support for multiple IPv6 container/gateway addresses depends upon containernetworking/cni PR 451 "ipam/host-local: support multiple IP ranges". This change could potentially be committed independently from this host-local plugin change, however the dual-stack and multiple IPv6 address functionality that is enabled by this change can't be exercised/tested until the host-local plugin change is committed. There are some IPv6 unit test cases that are currently commented out in the proposed changes because these test cases will fail without the prior commits of the multiple IP range host-local change. This pull request includes a temporary workaround for Kubernetes Issue #32291 (Container IPv6 address is marked as duplicate, or dadfailed). The problem is that kubelet enables hairpin mode on bridge veth interfaces. Hairpin mode causes the container/pod to see echos of its IPv6 neighbor solicitation packets, so that it declares duplicate address detection (DAD) failure. The long-term fix is to use enhanced-DAD when that feature is readily available in kernels. The short-term fix is to disable IPv6 DAD in the container. Unfortunately, this has to be done unconditionally (i.e. without a check for whether hairpin mode is enabled) because hairpin mode is turned on by kubelet after the CNI bridge plugin has completed cmdAdd processing. Disabling DAD should be okay if IPv6 addresses are guaranteed to be unique (which is the case for host-local IPAM plugin).
9a8bc97
to
ffdc748
Compare
LGTM |
…evert Reverts change to build_linux.sh to build.sh
This change adds support for IPv6 container/pod addresses to the CNI
bridge plugin, both for dual-stack (IPv4 + IPv6) and for IPv6-only
network configurations.
The proposed changes support multiple IPv6 addresses on a container
interface. If isGW is configured, the bridge will also be configured with
gateway addresses for each IPv6 subnet.
Please note that both the dual-stack functionality and support for multiple
IPv6 container/gateway addresses depends upon containernetworking/cni
PR #451 "ipam/host-local: support multiple IP ranges".
The bridge plugin changes being proposed here could potentially be committed
independently from this host-local plugin change; however the dual-stack and
multiple IPv6 address functionality that is enabled by this change can't be
exercised/tested until the host-local plugin change is committed.
There are some dual-stack/multiple-IPv6 unit test cases that are
currently commented out in the proposed changes because these
test cases will fail without the prior commits of the multiple IP
range host-local change.
This pull request includes a temporary workaround for Kubernetes
Issue #32291 (Container IPv6 address is marked as duplicate (dadfailed).
The problem is that kubelet enables hairpin mode on bridge veth
interfaces. Hairpin mode causes the container/pod to see echos of its
IPv6 neighbor solicitation packets, so that it declares duplicate address
detection (DAD) failure. The long-term fix is to use enhanced-DAD
when that feature is readily available in kernels. The short-term fix is
to disable IPv6 DAD in the container. Unfortunately, this has to be done
unconditionally (i.e. without a check for whether hairpin mode is enabled)
because hairpin mode is turned on by kubelet after the CNI bridge plugin
has completed cmdAdd processing. Disabling DAD should be okay if
IPv6 addresses are guaranteed to be unique (which is the case for
host-local IPAM plugin).