Skip to content

Commit 90fb864

Browse files
author
OpenShift Bot
authored
Merge pull request #13200 from danwinship/ovs-flake-1.5
Merged by openshift-bot
2 parents 1681de3 + 876affc commit 90fb864

File tree

2 files changed

+107
-51
lines changed

2 files changed

+107
-51
lines changed

Diff for: pkg/sdn/plugin/subnets.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package plugin
33
import (
44
"fmt"
55
"net"
6+
"sort"
67
"strconv"
8+
"strings"
79

810
log "github.com/golang/glog"
911

@@ -266,13 +268,14 @@ func (plugin *OsdnNode) updateVXLANMulticastRules(subnets hostSubnetMap) {
266268
otx := plugin.ovs.NewTransaction()
267269

268270
// Build the list of all nodes for multicast forwarding
269-
tun_dsts := ""
271+
tun_dsts := make([]string, 0, len(subnets))
270272
for _, subnet := range subnets {
271273
if subnet.HostIP != plugin.localIP {
272-
tun_dsts += fmt.Sprintf(",set_field:%s->tun_dst,output:1", subnet.HostIP)
274+
tun_dsts = append(tun_dsts, fmt.Sprintf(",set_field:%s->tun_dst,output:1", subnet.HostIP))
273275
}
274276
}
275-
otx.AddFlow("table=111, priority=100, actions=move:NXM_NX_REG0[]->NXM_NX_TUN_ID[0..31]%s,goto_table:120", tun_dsts)
277+
sort.Strings(sort.StringSlice(tun_dsts))
278+
otx.AddFlow("table=111, priority=100, actions=move:NXM_NX_REG0[]->NXM_NX_TUN_ID[0..31]%s,goto_table:120", strings.Join(tun_dsts, ""))
276279

277280
if err := otx.EndTransaction(); err != nil {
278281
log.Errorf("Error updating OVS VXLAN multicast flows: %v", err)

Diff for: test/extended/networking/ovs.go

+101-48
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package networking
22

33
import (
4+
"fmt"
45
"net"
56
"reflect"
67
"regexp"
@@ -12,6 +13,7 @@ import (
1213

1314
kapi "k8s.io/kubernetes/pkg/api"
1415
kapiunversioned "k8s.io/kubernetes/pkg/api/unversioned"
16+
utilwait "k8s.io/kubernetes/pkg/util/wait"
1517
e2e "k8s.io/kubernetes/test/e2e/framework"
1618

1719
. "github.com/onsi/ginkgo"
@@ -40,27 +42,20 @@ var _ = Describe("[networking] OVS", func() {
4042
ipPort := e2e.LaunchWebserverPod(f1, podName, deployNodeName)
4143
ip := strings.Split(ipPort, ":")[0]
4244

43-
newFlows := getFlowsForAllNodes(oc, nodes.Items)
44-
for _, node := range nodes.Items {
45-
if node.Name != deployNodeName {
46-
Expect(reflect.DeepEqual(origFlows[node.Name], newFlows[node.Name])).To(BeTrue(), "Flows on non-deployed-to nodes should be unchanged")
47-
}
48-
}
49-
50-
foundPodFlow := false
51-
for _, flow := range newFlows[deployNodeName] {
52-
if strings.Contains(flow, "="+ip+",") || strings.Contains(flow, "="+ip+" ") {
53-
foundPodFlow = true
54-
break
45+
checkFlowsForAllNodes(oc, nodes.Items, func(nodeName string, newFlows []string) error {
46+
if nodeName == deployNodeName {
47+
return findFlowOrError("Should have flows referring to pod IP address", newFlows, ip)
48+
} else {
49+
return matchFlowsOrError("Flows on non-deployed-to nodes should be unchanged", newFlows, origFlows[nodeName])
5550
}
56-
}
57-
Expect(foundPodFlow).To(BeTrue(), "Should have flows referring to pod IP address")
51+
})
5852

5953
err := f1.ClientSet.Core().Pods(f1.Namespace.Name).Delete(podName, &kapi.DeleteOptions{})
6054
Expect(err).NotTo(HaveOccurred())
6155

62-
postDeleteFlows := getFlowsForNode(oc, deployNodeName)
63-
Expect(reflect.DeepEqual(origFlows[deployNodeName], postDeleteFlows)).To(BeTrue(), "Flows after deleting pod should be same as before creating it")
56+
checkFlowsForNode(oc, deployNodeName, func(nodeName string, flows []string) error {
57+
return matchFlowsOrError("Flows after deleting pod should be same as before creating it", flows, origFlows[nodeName])
58+
})
6459
})
6560

6661
It("should add and remove flows when nodes are added and removed", func() {
@@ -122,17 +117,9 @@ var _ = Describe("[networking] OVS", func() {
122117
}
123118
Expect(err).NotTo(HaveOccurred())
124119

125-
newFlows := getFlowsForAllNodes(oc, nodes.Items)
126-
for nodeName := range newFlows {
127-
foundNodeFlow := false
128-
for _, flow := range newFlows[nodeName] {
129-
if strings.Contains(flow, "="+newNodeIP+",") || strings.Contains(flow, "="+newNodeIP+" ") {
130-
foundNodeFlow = true
131-
break
132-
}
133-
}
134-
Expect(foundNodeFlow).To(BeTrue(), "Should have flows referring to node IP address")
135-
}
120+
checkFlowsForAllNodes(oc, nodes.Items, func(nodeName string, newFlows []string) error {
121+
return findFlowOrError("Should have flows referring to node IP address", newFlows, newNodeIP)
122+
})
136123

137124
err = f1.ClientSet.Core().Nodes().Delete(node.Name, &kapi.DeleteOptions{})
138125
Expect(err).NotTo(HaveOccurred())
@@ -145,8 +132,9 @@ var _ = Describe("[networking] OVS", func() {
145132
}
146133
Expect(err).NotTo(BeNil())
147134

148-
postDeleteFlows := getFlowsForAllNodes(oc, nodes.Items)
149-
Expect(reflect.DeepEqual(origFlows, postDeleteFlows)).To(BeTrue(), "Flows after deleting node should be same as before creating it")
135+
checkFlowsForAllNodes(oc, nodes.Items, func(nodeName string, flows []string) error {
136+
return matchFlowsOrError("Flows after deleting node should be same as before creating it", flows, origFlows[nodeName])
137+
})
150138
})
151139
})
152140

@@ -163,29 +151,49 @@ var _ = Describe("[networking] OVS", func() {
163151
ipPort := launchWebserverService(f1, serviceName, deployNodeName)
164152
ip := strings.Split(ipPort, ":")[0]
165153

166-
newFlows := getFlowsForAllNodes(oc, nodes.Items)
167-
for _, node := range nodes.Items {
168-
foundServiceFlow := false
169-
for _, flow := range newFlows[node.Name] {
170-
if strings.Contains(flow, "nw_dst="+ip+",") || strings.Contains(flow, "nw_dst="+ip+" ") {
171-
foundServiceFlow = true
172-
break
173-
}
174-
}
175-
Expect(foundServiceFlow).To(BeTrue(), "Each node contains a rule for the service")
176-
}
154+
checkFlowsForAllNodes(oc, nodes.Items, func(nodeName string, newFlows []string) error {
155+
return findFlowOrError("Should have flows referring to service IP address", newFlows, ip)
156+
})
177157

178158
err := f1.ClientSet.Core().Pods(f1.Namespace.Name).Delete(serviceName, &kapi.DeleteOptions{})
179159
Expect(err).NotTo(HaveOccurred())
180160
err = f1.ClientSet.Core().Services(f1.Namespace.Name).Delete(serviceName, &kapi.DeleteOptions{})
181161
Expect(err).NotTo(HaveOccurred())
182162

183-
postDeleteFlows := getFlowsForAllNodes(oc, nodes.Items)
184-
Expect(reflect.DeepEqual(origFlows, postDeleteFlows)).To(BeTrue(), "Flows after deleting service should be same as before creating it")
163+
checkFlowsForAllNodes(oc, nodes.Items, func(nodeName string, flows []string) error {
164+
return matchFlowsOrError("Flows after deleting service should be same as before creating it", flows, origFlows[nodeName])
165+
})
185166
})
186167
})
187168
})
188169

170+
type FlowError struct {
171+
msg string
172+
flows []string
173+
expected []string
174+
}
175+
176+
func (err FlowError) Error() string {
177+
return err.msg
178+
}
179+
180+
func matchFlowsOrError(msg string, flows, expected []string) error {
181+
if reflect.DeepEqual(flows, expected) {
182+
return nil
183+
} else {
184+
return FlowError{msg, flows, expected}
185+
}
186+
}
187+
188+
func findFlowOrError(msg string, flows []string, ip string) error {
189+
for _, flow := range flows {
190+
if strings.Contains(flow, "="+ip+",") || strings.Contains(flow, "="+ip+" ") {
191+
return nil
192+
}
193+
}
194+
return FlowError{fmt.Sprintf("%s (%s)", msg, ip), flows, nil}
195+
}
196+
189197
func doGetFlowsForNode(oc *testexutil.CLI, nodeName string) ([]string, error) {
190198
pod := &kapi.Pod{
191199
TypeMeta: kapiunversioned.TypeMeta{
@@ -252,12 +260,6 @@ func doGetFlowsForNode(oc *testexutil.CLI, nodeName string) ([]string, error) {
252260
return flows, nil
253261
}
254262

255-
func getFlowsForNode(oc *testexutil.CLI, nodeName string) []string {
256-
flows, err := doGetFlowsForNode(oc, nodeName)
257-
expectNoError(err)
258-
return flows
259-
}
260-
261263
func getFlowsForAllNodes(oc *testexutil.CLI, nodes []kapi.Node) map[string][]string {
262264
var err error
263265
flows := make(map[string][]string, len(nodes))
@@ -267,3 +269,54 @@ func getFlowsForAllNodes(oc *testexutil.CLI, nodes []kapi.Node) map[string][]str
267269
}
268270
return flows
269271
}
272+
273+
type CheckFlowFunc func(nodeName string, flows []string) error
274+
275+
var checkFlowBackoff = utilwait.Backoff{
276+
Duration: time.Second,
277+
Factor: 2,
278+
Steps: 5,
279+
}
280+
281+
func checkFlowsForNode(oc *testexutil.CLI, nodeName string, checkFlow CheckFlowFunc) {
282+
var lastCheckErr error
283+
e2e.Logf("Checking OVS flows for node %q up to %d times", nodeName, checkFlowBackoff.Steps)
284+
err := utilwait.ExponentialBackoff(checkFlowBackoff, func() (bool, error) {
285+
flows, err := doGetFlowsForNode(oc, nodeName)
286+
if err != nil {
287+
return false, err
288+
}
289+
if lastCheckErr = checkFlow(nodeName, flows); lastCheckErr != nil {
290+
e2e.Logf("Check failed (%v)", lastCheckErr)
291+
return false, nil
292+
}
293+
return true, nil
294+
})
295+
if err != nil && lastCheckErr != nil {
296+
err = lastCheckErr
297+
}
298+
expectNoError(err)
299+
}
300+
301+
func checkFlowsForAllNodes(oc *testexutil.CLI, nodes []kapi.Node, checkFlow CheckFlowFunc) {
302+
var lastCheckErr error
303+
e2e.Logf("Checking OVS flows for all nodes up to %d times", checkFlowBackoff.Steps)
304+
err := utilwait.ExponentialBackoff(checkFlowBackoff, func() (bool, error) {
305+
lastCheckErr = nil
306+
for _, node := range nodes {
307+
flows, err := doGetFlowsForNode(oc, node.Name)
308+
if err != nil {
309+
return false, err
310+
}
311+
if lastCheckErr = checkFlow(node.Name, flows); lastCheckErr != nil {
312+
e2e.Logf("Check failed for node %q (%v)", node.Name, lastCheckErr)
313+
return false, nil
314+
}
315+
}
316+
return true, nil
317+
})
318+
if err != nil && lastCheckErr != nil {
319+
err = lastCheckErr
320+
}
321+
expectNoError(err)
322+
}

0 commit comments

Comments
 (0)