Skip to content

Commit 347c68a

Browse files
committed
Testing for proper handling of non-/32 routing
Will not work until networkservicemesh/sdk-kernel#383 is merged to fix networkservicemesh/sdk-kernel#354 Signed-off-by: Ed Warnicke <hagbard@gmail.com>
1 parent d8e4c9c commit 347c68a

File tree

9 files changed

+202
-28
lines changed

9 files changed

+202
-28
lines changed

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,9 @@ require (
2525
github.com/vishvananda/netlink v1.1.0
2626
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae
2727
google.golang.org/grpc v1.38.0
28+
google.golang.org/protobuf v1.26.0
2829
)
30+
31+
replace github.com/networkservicemesh/sdk-kernel => ./local/sdk-kernel
32+
replace github.com/networkservicemesh/sdk-vpp => ./local/sdk-vpp
33+
//replace github.com/networkservicemesh/api => ./local/api

internal/imports/imports_linux.go

Lines changed: 28 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/tests/routes/server.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) 2021 Cisco and/or its affiliates.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at:
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
// Package routes provides a simple cahin element for adding routes
18+
package routes
19+
20+
import (
21+
"context"
22+
23+
"google.golang.org/protobuf/types/known/emptypb"
24+
25+
"github.com/networkservicemesh/api/pkg/api/networkservice"
26+
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
27+
)
28+
29+
type testRoutesServer struct {
30+
srcRoutes []*networkservice.Route
31+
dstRoutes []*networkservice.Route
32+
}
33+
34+
// NewServer - add routes to response
35+
func NewServer(srcRoutes, dstRoutes []*networkservice.Route) networkservice.NetworkServiceServer {
36+
return &testRoutesServer{
37+
srcRoutes: srcRoutes,
38+
dstRoutes: dstRoutes,
39+
}
40+
}
41+
42+
func (r *testRoutesServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) {
43+
if request.GetConnection() == nil {
44+
request.Connection = &networkservice.Connection{}
45+
}
46+
if request.GetConnection().GetContext() == nil {
47+
request.GetConnection().Context = &networkservice.ConnectionContext{}
48+
}
49+
if request.GetConnection().GetContext().GetIpContext() == nil {
50+
request.GetConnection().GetContext().IpContext = &networkservice.IPContext{}
51+
}
52+
request.GetConnection().GetContext().GetIpContext().SrcRoutes = append(request.GetConnection().GetContext().GetIpContext().SrcRoutes, r.srcRoutes...)
53+
request.GetConnection().GetContext().GetIpContext().DstRoutes = append(request.GetConnection().GetContext().GetIpContext().DstRoutes, r.dstRoutes...)
54+
return next.Server(ctx).Request(ctx, request)
55+
}
56+
57+
func (r *testRoutesServer) Close(ctx context.Context, conn *networkservice.Connection) (*emptypb.Empty, error) {
58+
return next.Server(ctx).Close(ctx, conn)
59+
}

internal/tests/suite_combinatronics_test.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package tests
2020

2121
import (
2222
"context"
23+
"fmt"
2324
"net"
2425
"strings"
2526
"testing"
@@ -49,30 +50,59 @@ import (
4950
func (f *ForwarderTestSuite) TestCombinations() {
5051
_, prefix1, err := net.ParseCIDR("10.0.0.0/24")
5152
f.Require().NoError(err)
52-
_, prefix2, err := net.ParseCIDR("fc00::/7")
53+
_, prefix2, err := net.ParseCIDR("fc00::/64")
5354
f.Require().NoError(err)
55+
srcRoutes := []*networkservice.Route{}
56+
dstRoutes := []*networkservice.Route{}
57+
for i := 1; i < 6; i++ {
58+
srcRoutes = append(srcRoutes,
59+
&networkservice.Route{
60+
Prefix: fmt.Sprintf("10.0.%d.0/24", i),
61+
},
62+
&networkservice.Route{
63+
Prefix: fmt.Sprintf("fc00:0:%d::/64", i),
64+
},
65+
)
66+
dstRoutes = append(dstRoutes,
67+
&networkservice.Route{
68+
Prefix: fmt.Sprintf("10.0.%d.1/24", i),
69+
},
70+
&networkservice.Route{
71+
Prefix: fmt.Sprintf("fc00:0:%d::1/64", i),
72+
},
73+
)
74+
}
75+
5476
endpoints := map[string]func(ctx context.Context) verifiableEndpoint{
5577
kernel.MECHANISM: func(ctx context.Context) verifiableEndpoint {
5678
return newKernelVerifiableEndpoint(ctx,
5779
prefix1,
5880
prefix2,
81+
srcRoutes,
82+
dstRoutes,
5983
spiffejwt.TokenGeneratorFunc(f.x509source, f.config.MaxTokenLifetime),
6084
)
6185
},
6286
memif.MECHANISM: func(ctx context.Context) verifiableEndpoint {
6387
return newMemifVerifiableEndpoint(ctx, prefix1, prefix2,
88+
srcRoutes,
89+
dstRoutes,
6490
spiffejwt.TokenGeneratorFunc(f.x509source, f.config.MaxTokenLifetime),
6591
f.vppServerConn,
6692
)
6793
},
6894
vxlan.MECHANISM: func(ctx context.Context) verifiableEndpoint {
6995
return newVxlanVerifiableEndpoint(ctx, prefix1, prefix2,
96+
srcRoutes,
97+
dstRoutes,
7098
spiffejwt.TokenGeneratorFunc(f.x509source, f.config.MaxTokenLifetime),
7199
f.vppServerConn,
72100
)
73101
},
74102
wireguard.MECHANISM: func(ctx context.Context) verifiableEndpoint {
75103
return newWireguardVerifiableEndpoint(ctx, prefix1, prefix2,
104+
srcRoutes,
105+
dstRoutes,
76106
spiffejwt.TokenGeneratorFunc(f.x509source, f.config.MaxTokenLifetime),
77107
f.vppServerConn,
78108
)

internal/tests/suite_kernel_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ import (
3030
"github.com/vishvananda/netns"
3131
"google.golang.org/grpc"
3232

33+
"github.com/networkservicemesh/cmd-forwarder-vpp/internal/tests/routes"
34+
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
35+
3336
"github.com/networkservicemesh/api/pkg/api/networkservice"
3437
"github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/cls"
3538
"github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/kernel"
@@ -73,6 +76,7 @@ type kernelVerifiableEndpoint struct {
7376

7477
func newKernelVerifiableEndpoint(ctx context.Context,
7578
prefix1, prefix2 *net.IPNet,
79+
srcRoutes, dstRoutes []*networkservice.Route,
7680
tokenGenerator token.GeneratorFunc,
7781
) verifiableEndpoint {
7882
rootNSHandle, err := netns.Get()
@@ -100,6 +104,7 @@ func newKernelVerifiableEndpoint(ctx context.Context,
100104
endpoint.WithAdditionalFunctionality(
101105
point2pointipam.NewServer(prefix1),
102106
point2pointipam.NewServer(prefix2),
107+
routes.NewServer(srcRoutes, dstRoutes),
103108
mechanisms.NewServer(map[string]networkservice.NetworkServiceServer{
104109
kernel.MECHANISM: chain.NewNetworkServiceServer(
105110
kernelmechanism.NewServer(kernelmechanism.WithInterfaceName(endpointNSName)),
@@ -126,6 +131,9 @@ func (k *kernelVerifiableEndpoint) VerifyConnection(conn *networkservice.Connect
126131
if err := checkKernelInterface(namingConn, conn.GetContext().GetIpContext().GetDstIPNets(), k.endpointNSHandle); err != nil {
127132
return err
128133
}
134+
if err := checkRoutes(namingConn, k.endpointNSHandle, metadata.IsClient(k)); err != nil {
135+
return err
136+
}
129137
for _, ip := range conn.GetContext().GetIpContext().GetSrcIPNets() {
130138
if err := pingKernel(ip, k.endpointNSHandle); err != nil {
131139
return err
@@ -181,6 +189,9 @@ func (k *kernelVerifiableClient) VerifyConnection(conn *networkservice.Connectio
181189
if err := checkKernelInterface(conn, conn.GetContext().GetIpContext().GetSrcIPNets(), k.clientNSHandle); err != nil {
182190
return err
183191
}
192+
if err := checkRoutes(conn, k.clientNSHandle, metadata.IsClient(k)); err != nil {
193+
return err
194+
}
184195
for _, ip := range conn.GetContext().GetIpContext().GetDstIPNets() {
185196
if err := pingKernel(ip, k.clientNSHandle); err != nil {
186197
return err
@@ -263,3 +274,61 @@ func pingKernel(ipnet *net.IPNet, handle netns.NsHandle) error {
263274
}
264275
return nil
265276
}
277+
278+
func checkRoutes(conn *networkservice.Connection, nsHandle netns.NsHandle, isClient bool) error {
279+
if mechanism := kernel.ToMechanism(conn.GetMechanism()); mechanism != nil {
280+
curNetNS, err := netns.Get()
281+
if err != nil {
282+
return errors.Wrap(err, "unable to get current netns")
283+
}
284+
netlinkHandle, err := netlink.NewHandleAtFrom(nsHandle, curNetNS)
285+
if err != nil {
286+
return errors.Wrap(err, "unable to get netlink Handle in target netNs")
287+
}
288+
kernelRoutes, err := netlinkHandle.RouteList(nil, netlink.FAMILY_ALL)
289+
if err != nil {
290+
return errors.Wrap(err, "unable to get routes")
291+
}
292+
nsmRoutes := conn.GetContext().GetIpContext().GetDstRoutesWithExplicitNextHop()
293+
if isClient {
294+
nsmRoutes = conn.GetContext().GetIpContext().GetSrcRoutesWithExplicitNextHop()
295+
}
296+
297+
link, err := netlinkHandle.LinkByName((mechanism.GetInterfaceName()))
298+
if err != nil {
299+
return errors.Wrapf(err, "unable to find link %s", mechanism.GetInterfaceName())
300+
}
301+
302+
for _, nsmRoute := range nsmRoutes {
303+
routeFound := false
304+
for i := range kernelRoutes {
305+
if !(kernelRoutes[i].Dst.IP.Equal(nsmRoute.GetPrefixIPNet().IP.Mask(nsmRoute.GetPrefixIPNet().Mask))) {
306+
continue
307+
}
308+
kernelOnes, kernelBit := kernelRoutes[i].Dst.Mask.Size()
309+
nsmOnes, nsmBits := nsmRoute.GetPrefixIPNet().Mask.Size()
310+
if kernelOnes != nsmOnes {
311+
continue
312+
}
313+
if kernelBit != nsmBits {
314+
continue
315+
}
316+
317+
if !kernelRoutes[i].Gw.Equal(nsmRoute.GetNextHopIP()) {
318+
continue
319+
}
320+
321+
if kernelRoutes[i].LinkIndex != link.Attrs().Index {
322+
continue
323+
}
324+
325+
routeFound = true
326+
break
327+
}
328+
if !routeFound {
329+
return errors.Errorf("unable to find expected route: %s in routes %+v", nsmRoute, kernelRoutes)
330+
}
331+
}
332+
}
333+
return nil
334+
}

internal/tests/suite_memif_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/edwarnicke/vpphelper"
3131
"github.com/pkg/errors"
3232

33+
"github.com/networkservicemesh/cmd-forwarder-vpp/internal/tests/routes"
3334
"github.com/networkservicemesh/sdk/pkg/networkservice/common/mechanisms"
3435
"github.com/networkservicemesh/sdk/pkg/networkservice/common/mechanisms/sendfd"
3536
"github.com/networkservicemesh/sdk/pkg/networkservice/core/chain"
@@ -61,6 +62,7 @@ type memifVerifiableEndpoint struct {
6162

6263
func newMemifVerifiableEndpoint(ctx context.Context,
6364
prefix1, prefix2 *net.IPNet,
65+
srcRoutes, dstRoutes []*networkservice.Route,
6466
tokenGenerator token.GeneratorFunc,
6567
vppConn vpphelper.Connection,
6668
) verifiableEndpoint {
@@ -76,6 +78,7 @@ func newMemifVerifiableEndpoint(ctx context.Context,
7678
sendfd.NewServer(),
7779
point2pointipam.NewServer(prefix1),
7880
point2pointipam.NewServer(prefix2),
81+
routes.NewServer(srcRoutes, dstRoutes),
7982
mechanisms.NewServer(map[string]networkservice.NetworkServiceServer{
8083
memif.MECHANISM: chain.NewNetworkServiceServer(
8184
metadata.NewServer(),

internal/tests/suite_util_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
)
3232

3333
const (
34-
contextTimeout = 100 * time.Second
34+
contextTimeout = 10000 * time.Second
3535
forwarderIP = "10.0.2.1"
3636
clientIP = "10.0.2.2"
3737
serverIP = "10.0.2.3"

internal/tests/suite_vxlan_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"git.fd.io/govpp.git/api"
2424
"google.golang.org/grpc"
2525

26+
"github.com/networkservicemesh/cmd-forwarder-vpp/internal/tests/routes"
2627
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/pinhole"
2728

2829
"github.com/networkservicemesh/sdk/pkg/networkservice/common/mechanisms"
@@ -48,6 +49,7 @@ type vxlanVerifiableEndpoint struct {
4849

4950
func newVxlanVerifiableEndpoint(ctx context.Context,
5051
prefix1, prefix2 *net.IPNet,
52+
srcRoutes, dstRoutes []*networkservice.Route,
5153
tokenGenerator token.GeneratorFunc,
5254
vppConn api.Connection) verifiableEndpoint {
5355
rv := &vxlanVerifiableEndpoint{
@@ -63,6 +65,7 @@ func newVxlanVerifiableEndpoint(ctx context.Context,
6365
metadata.NewServer(),
6466
point2pointipam.NewServer(prefix1),
6567
point2pointipam.NewServer(prefix2),
68+
routes.NewServer(srcRoutes, dstRoutes),
6669
connectioncontext.NewServer(vppConn),
6770
pinhole.NewServer(vppConn),
6871
mechanisms.NewServer(map[string]networkservice.NetworkServiceServer{

0 commit comments

Comments
 (0)