Skip to content

Commit 2af07d3

Browse files
committed
Add unit tests for the vxlan cable driver
Signed-off-by: Tom Pantelis <[email protected]>
1 parent 3b8fecf commit 2af07d3

File tree

2 files changed

+224
-4
lines changed

2 files changed

+224
-4
lines changed

pkg/cable/vxlan/vxlan.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const (
4242
VxlanVTepNetworkPrefix = 241
4343
CableDriverName = "vxlan"
4444
TableID = 100
45-
defaultPort = 4500
45+
DefaultPort = 4500
4646
)
4747

4848
type vxLan struct {
@@ -75,7 +75,7 @@ func NewDriver(localEndpoint *types.SubmarinerEndpoint, localCluster *types.Subm
7575
logger.Warning("VxLan cable-driver is supported only with no NAT deployments")
7676
}
7777

78-
port, err := localEndpoint.Spec.GetBackendPort(v1.UDPPortConfig, defaultPort)
78+
port, err := localEndpoint.Spec.GetBackendPort(v1.UDPPortConfig, DefaultPort)
7979
if err != nil {
8080
return nil, errors.Wrap(err, "failed to get the UDP port configuration")
8181
}
@@ -184,8 +184,6 @@ func (v *vxLan) ConnectToEndpoint(endpointInfo *natdiscovery.NATEndpointInfo) (s
184184
} else {
185185
logger.Errorf(nil, "Failed to get the CNI interface IP for cluster CIDR %q, host-networking use-cases may not work",
186186
v.localCluster.Spec.ClusterCIDR[0])
187-
188-
ipAddress = nil
189187
}
190188

191189
err = v.vxlanIface.AddRoutes(remoteVtepIP, ipAddress, TableID, allowedIPs...)

pkg/cable/vxlan/vxlan_test.go

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*
2+
SPDX-License-Identifier: Apache-2.0
3+
4+
Copyright Contributors to the Submariner project.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package vxlan_test
20+
21+
import (
22+
"flag"
23+
"fmt"
24+
"testing"
25+
26+
. "github.com/onsi/ginkgo/v2"
27+
. "github.com/onsi/gomega"
28+
"github.com/submariner-io/admiral/pkg/log/kzerolog"
29+
subv1 "github.com/submariner-io/submariner/pkg/apis/submariner.io/v1"
30+
"github.com/submariner-io/submariner/pkg/cable"
31+
"github.com/submariner-io/submariner/pkg/cable/vxlan"
32+
"github.com/submariner-io/submariner/pkg/natdiscovery"
33+
netlinkAPI "github.com/submariner-io/submariner/pkg/netlink"
34+
fakeNetlink "github.com/submariner-io/submariner/pkg/netlink/fake"
35+
"github.com/submariner-io/submariner/pkg/routeagent_driver/cni"
36+
"github.com/submariner-io/submariner/pkg/types"
37+
"github.com/vishvananda/netlink"
38+
)
39+
40+
func init() {
41+
kzerolog.AddFlags(nil)
42+
}
43+
44+
var _ = BeforeSuite(func() {
45+
flags := flag.NewFlagSet("kzerolog", flag.ExitOnError)
46+
kzerolog.AddFlags(flags)
47+
_ = flags.Parse([]string{"-v=4"})
48+
49+
kzerolog.InitK8sLogging()
50+
})
51+
52+
func TestVxlan(t *testing.T) {
53+
RegisterFailHandler(Fail)
54+
RunSpecs(t, "Vxlan Cable Driver Suite")
55+
}
56+
57+
const cniIPAddress = "192.168.5.1"
58+
59+
var _ = Describe("Vxlan", func() {
60+
t := newTestDriver()
61+
62+
var natInfo *natdiscovery.NATEndpointInfo
63+
64+
BeforeEach(func() {
65+
natInfo = &natdiscovery.NATEndpointInfo{
66+
Endpoint: subv1.Endpoint{
67+
Spec: subv1.EndpointSpec{
68+
ClusterID: "east",
69+
CableName: "submariner-cable-east-192-68-2-1",
70+
PrivateIP: "192.68.2.1",
71+
Subnets: []string{"20.0.0.0/16", "21.0.0.0/16"},
72+
},
73+
},
74+
UseIP: "172.93.2.1",
75+
UseNAT: true,
76+
}
77+
})
78+
79+
JustBeforeEach(func() {
80+
link := t.netLink.AwaitLink(vxlan.VxlanIface)
81+
vxLan, ok := link.(*netlink.Vxlan)
82+
Expect(ok).To(BeTrue(), "Unexpected Link type: %T", link)
83+
84+
Expect(vxLan.Port).To(Equal(vxlan.DefaultPort))
85+
86+
t.netLink.AwaitRule(vxlan.TableID, "", "")
87+
})
88+
89+
Specify("ConnectToEndpoint should create a Connection and add expected data-plane components", func() {
90+
ip, err := t.driver.ConnectToEndpoint(natInfo)
91+
Expect(err).To(Succeed())
92+
Expect(ip).To(Equal(natInfo.UseIP))
93+
94+
t.assertConnection(natInfo)
95+
t.netLink.AwaitNeighbors(0, natInfo.UseIP)
96+
97+
link, err := t.netLink.LinkByName(vxlan.VxlanIface)
98+
Expect(err).To(Succeed())
99+
100+
routes, err := t.netLink.RouteList(link, 0)
101+
Expect(err).To(Succeed())
102+
103+
var actualRoutes []map[string]string
104+
for i := range routes {
105+
actualRoutes = append(actualRoutes, routeFieldMap(routes[i].Src.String(), routes[i].Gw.String(), routes[i].Dst.String()))
106+
}
107+
108+
gw := fmt.Sprintf("%d.68.2.1", vxlan.VxlanVTepNetworkPrefix)
109+
Expect(actualRoutes).To(HaveExactElements(routeFieldMap(cniIPAddress, gw, natInfo.Endpoint.Spec.Subnets[0]),
110+
routeFieldMap(cniIPAddress, gw, natInfo.Endpoint.Spec.Subnets[1])))
111+
})
112+
113+
Specify("DisconnectFromEndpoint should remove the Connection and its data-plane components", func() {
114+
_, err := t.driver.ConnectToEndpoint(natInfo)
115+
Expect(err).To(Succeed())
116+
117+
Expect(t.driver.DisconnectFromEndpoint(&types.SubmarinerEndpoint{Spec: natInfo.Endpoint.Spec})).To(Succeed())
118+
t.assertNoConnection(natInfo)
119+
t.netLink.AwaitNoNeighbors(0, natInfo.UseIP)
120+
121+
link, err := t.netLink.LinkByName(vxlan.VxlanIface)
122+
Expect(err).To(Succeed())
123+
124+
routes, err := t.netLink.RouteList(link, 0)
125+
Expect(err).To(Succeed())
126+
Expect(routes).To(BeEmpty())
127+
})
128+
129+
Specify("Cleanup should remove the VxLAN link device", func() {
130+
Expect(t.driver.Cleanup()).To(Succeed())
131+
t.netLink.AwaitNoLink(vxlan.VxlanIface)
132+
t.netLink.AwaitNoRule(vxlan.TableID, "", "")
133+
})
134+
})
135+
136+
func routeFieldMap(src, gw, dst string) map[string]string {
137+
return map[string]string{
138+
"Src": src,
139+
"Gw": dst,
140+
"Dst": gw,
141+
}
142+
}
143+
144+
type testDriver struct {
145+
localEndpoint *types.SubmarinerEndpoint
146+
localCluster *types.SubmarinerCluster
147+
netLink *fakeNetlink.NetLink
148+
driver cable.Driver
149+
}
150+
151+
func newTestDriver() *testDriver {
152+
t := &testDriver{}
153+
154+
BeforeEach(func() {
155+
t.localCluster = &types.SubmarinerCluster{
156+
Spec: subv1.ClusterSpec{
157+
ClusterID: "local",
158+
ServiceCIDR: []string{"10.0.0.0/16"},
159+
ClusterCIDR: []string{"11.0.0.0/16"},
160+
},
161+
}
162+
163+
t.localEndpoint = &types.SubmarinerEndpoint{Spec: subv1.EndpointSpec{
164+
ClusterID: t.localCluster.Spec.ClusterID,
165+
CableName: "submariner-cable-local-192-68-1-1",
166+
PrivateIP: "192.68.1.1",
167+
Subnets: append(t.localCluster.Spec.ServiceCIDR, t.localCluster.Spec.ClusterCIDR...),
168+
}}
169+
170+
t.netLink = fakeNetlink.New()
171+
netlinkAPI.NewFunc = func() netlinkAPI.Interface {
172+
return t.netLink
173+
}
174+
175+
cni.DiscoverFunc = func(_ string) (*cni.Interface, error) {
176+
return &cni.Interface{
177+
Name: "veth0",
178+
IPAddress: cniIPAddress,
179+
}, nil
180+
}
181+
})
182+
183+
JustBeforeEach(func() {
184+
d, err := vxlan.NewDriver(t.localEndpoint, t.localCluster)
185+
Expect(err).To(Succeed())
186+
187+
Expect(d.Init()).To(Succeed())
188+
Expect(d.GetName()).To(Equal(vxlan.CableDriverName))
189+
190+
t.driver = d
191+
})
192+
193+
return t
194+
}
195+
196+
func (t *testDriver) assertConnection(natInfo *natdiscovery.NATEndpointInfo) {
197+
conn := subv1.Connection{
198+
Status: subv1.Connected,
199+
Endpoint: natInfo.Endpoint.Spec,
200+
UsingIP: natInfo.UseIP,
201+
UsingNAT: natInfo.UseNAT,
202+
}
203+
204+
conns, err := t.driver.GetActiveConnections()
205+
Expect(err).To(Succeed())
206+
Expect(conns).To(HaveExactElements(conn))
207+
208+
conns, err = t.driver.GetConnections()
209+
Expect(err).To(Succeed())
210+
Expect(conns).To(HaveExactElements(conn))
211+
}
212+
213+
func (t *testDriver) assertNoConnection(natInfo *natdiscovery.NATEndpointInfo) {
214+
conn, err := t.driver.GetActiveConnections()
215+
Expect(err).To(Succeed())
216+
Expect(conn).ToNot(HaveExactElements(subv1.Connection{
217+
Status: subv1.Connected,
218+
Endpoint: natInfo.Endpoint.Spec,
219+
UsingIP: natInfo.UseIP,
220+
UsingNAT: natInfo.UseNAT,
221+
}))
222+
}

0 commit comments

Comments
 (0)