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

[release-4.15] OCPBUGS-32972: Deploy dual stack with IPv6 on top of bond/vlan fails #6245

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions internal/network/connectivity_groups.go
Expand Up @@ -376,6 +376,11 @@ type l2Query struct {
connectivityReport models.ConnectivityReport
}

func (l *l2Query) isIPv6() bool {
_, bits := l.parsedCidr.Mask.Size()
return bits == net.IPv6len*8
}

func (l *l2Query) next() strfmt.UUID {
for l.current != len(l.connectivityReport.RemoteHosts) {
rh := l.connectivityReport.RemoteHosts[l.current]
Expand All @@ -386,6 +391,17 @@ func (l *l2Query) next() strfmt.UUID {
return rh.HostID
}
}
if l.isIPv6() {
// nmap uses NDP (Network Discovery Protocol) for IPv6 L2 discovery. There are cases that NDP responses do not
// arrive and parsed by nmap, but still there is connectivity between the hosts. In this case we fallback to L3
// check and verify that the remote address is in the required subnet.
for _, l3 := range rh.L3Connectivity {
ip := net.ParseIP(l3.RemoteIPAddress)
if ip != nil && l.parsedCidr.Contains(ip) && l3.Successful {
return rh.HostID
}
}
}
}
return ""
}
Expand Down
49 changes: 49 additions & 0 deletions internal/network/connectivity_groups_test.go
Expand Up @@ -515,6 +515,55 @@ func GenerateL2ConnectivityGroupTests(ipV4 bool, net1CIDR, net2CIDR string) {
})
}

var _ = Describe("L2 Ipv6 with L3 fallback", func() {
var (
nodes []*node
net1CIDR string
hosts []*models.Host
)

BeforeEach(func() {
net1CIDR = "2001:db8::/120"
nodes = generateIPv6Nodes(7, "2001:db8::/120", "fe80:5054::/120")
hosts = []*models.Host{
{
ID: nodes[0].id,
Connectivity: createConnectivityReport(
createL2Remote(nodes[1], l2LinkNet1),
createL2Remote(nodes[2], l2LinkNet1)),
},
{
ID: nodes[1].id,
Connectivity: createConnectivityReport(
createL2Remote(nodes[0], l2LinkNet1),
createL2Remote(nodes[2], l2LinkNet1)),
},
{
ID: nodes[2].id,
Connectivity: createConnectivityReport(
createL2Remote(nodes[0], l2LinkNet1)),
},
}
})
It("Missing L2 connectivity", func() {
ret, err := CreateL2MajorityGroup(net1CIDR, hosts)
Expect(err).ToNot(HaveOccurred())
Expect(ret).To(HaveLen(0))
})

It("Missing L2 connectivity. Add L3 connectivity", func() {
hosts[2].Connectivity = createConnectivityReport(
createL2Remote(nodes[0], l2LinkNet1),
createL3Remote(nodes[1], l3LinkNet1))
ret, err := CreateL2MajorityGroup(net1CIDR, hosts)
Expect(err).ToNot(HaveOccurred())
Expect(ret).To(HaveLen(3))
Expect(ret).To(ContainElement(*nodes[0].id))
Expect(ret).To(ContainElement(*nodes[1].id))
Expect(ret).To(ContainElement(*nodes[2].id))
})
})

var _ = Describe("L3 connectivity groups all", func() {
GenerateL3ConnectivityGroupTests(true, "1.2.3.0/24", "2.2.3.0/24")
GenerateL3ConnectivityGroupTests(false, "2001:db8::/120", "fe80:5054::/120")
Expand Down