-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add connectioncontextkernel chain elements for ipaddress and routes
Signed-off-by: Ed Warnicke <hagbard@gmail.com>
- Loading branch information
1 parent
6ec28c5
commit 08a927b
Showing
8 changed files
with
480 additions
and
0 deletions.
There are no files selected for viewing
73 changes: 73 additions & 0 deletions
73
pkg/networkservice/connectioncontextkernel/ipcontext/ipaddress/client.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright (c) 2020 Cisco and/or its affiliates. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package ipaddress | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/golang/protobuf/ptypes/empty" | ||
"github.com/networkservicemesh/api/pkg/api/networkservice" | ||
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next" | ||
"google.golang.org/grpc" | ||
|
||
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata" | ||
) | ||
|
||
type ipaddressClient struct{} | ||
|
||
// NewClient provides a NetworkServiceClient that sets the IP on a kernel interface | ||
// It sets the IP Address on the *kernel* side of an interface leaving the | ||
// Client. Generally only used by privileged Clients like those implementing | ||
// the Cross Connect Network Service for K8s (formerly known as NSM Forwarder). | ||
// Client | ||
// +---------------------------+ | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | +-------------------+ | ||
// | | ipaddress.NewClient() | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// +---------------------------+ | ||
// | ||
func NewClient() networkservice.NetworkServiceClient { | ||
return &ipaddressClient{} | ||
} | ||
|
||
func (i *ipaddressClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) { | ||
conn, err := next.Client(ctx).Request(ctx, request, opts...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err := create(ctx, conn, metadata.IsClient(i)); err != nil { | ||
_, _ = i.Close(ctx, conn, opts...) | ||
return nil, err | ||
} | ||
return conn, nil | ||
} | ||
|
||
func (i *ipaddressClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) { | ||
return next.Client(ctx).Close(ctx, conn, opts...) | ||
} |
66 changes: 66 additions & 0 deletions
66
pkg/networkservice/connectioncontextkernel/ipcontext/ipaddress/common.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (c) 2020 Cisco and/or its affiliates. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package ipaddress | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/networkservicemesh/api/pkg/api/networkservice" | ||
"github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/kernel" | ||
"github.com/networkservicemesh/sdk/pkg/networkservice/core/trace" | ||
"github.com/pkg/errors" | ||
"github.com/vishvananda/netlink" | ||
|
||
"github.com/networkservicemesh/sdk-vpp/pkg/tools/link" | ||
"github.com/networkservicemesh/sdk-vpp/pkg/tools/netlinkhandle" | ||
) | ||
|
||
func create(ctx context.Context, conn *networkservice.Connection, isClient bool) error { | ||
if mechanism := kernel.ToMechanism(conn.GetMechanism()); mechanism != nil { | ||
l, ok := link.Load(ctx, isClient) | ||
if !ok { | ||
return nil | ||
} | ||
handle, ok := netlinkhandle.Load(ctx, isClient) | ||
if !ok { | ||
return errors.Errorf("did not find netlink handle with which to program routes") | ||
} | ||
// Note: These are switched from normal because if we are the client, we need to assign the IP | ||
// in the Endpoints NetNS for the Dst. If we are the *server* we need to assign the IP for the | ||
// clients NetNS (ie the source). | ||
ipNet := conn.GetContext().GetIpContext().GetSrcIPNet() | ||
if isClient { | ||
ipNet = conn.GetContext().GetIpContext().GetDstIPNet() | ||
} | ||
if ipNet == nil { | ||
return nil | ||
} | ||
now := time.Now() | ||
if err := handle.AddrAdd(l, &netlink.Addr{ | ||
IPNet: ipNet, | ||
}); err != nil { | ||
return err | ||
} | ||
trace.Log(ctx). | ||
WithField("link.Name", l.Attrs().Name). | ||
WithField("Addr", ipNet.String()). | ||
WithField("duration", time.Since(now)). | ||
WithField("netlink", "AddrAdd").Debug("completed") | ||
} | ||
return nil | ||
} |
18 changes: 18 additions & 0 deletions
18
pkg/networkservice/connectioncontextkernel/ipcontext/ipaddress/doc.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright (c) 2020 Cisco and/or its affiliates. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// Package ipaddress provides networkservice chain elements that support setting ip addresses on kernel interfaces | ||
package ipaddress |
68 changes: 68 additions & 0 deletions
68
pkg/networkservice/connectioncontextkernel/ipcontext/ipaddress/server.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright (c) 2020 Cisco and/or its affiliates. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package ipaddress | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/golang/protobuf/ptypes/empty" | ||
"github.com/networkservicemesh/api/pkg/api/networkservice" | ||
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next" | ||
|
||
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata" | ||
) | ||
|
||
type ipaddressServer struct { | ||
} | ||
|
||
// NewServer provides a NetworkServiceServer that sets the IP on a kernel interface | ||
// It sets the IP Address on the *kernel* side of an interface plugged into the | ||
// Endpoint. Generally only used by privileged Endpoints like those implementing | ||
// the Cross Connect Network Service for K8s (formerly known as NSM Forwarder). | ||
// Endpoint | ||
// +---------------------------+ | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// +-------------------+ | | ||
// ipaddress.NewServer() | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// | | | ||
// +---------------------------+ | ||
// | ||
func NewServer() networkservice.NetworkServiceServer { | ||
return &ipaddressServer{} | ||
} | ||
|
||
func (i *ipaddressServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) { | ||
if err := create(ctx, request.GetConnection(), metadata.IsClient(i)); err != nil { | ||
return nil, err | ||
} | ||
return next.Server(ctx).Request(ctx, request) | ||
} | ||
|
||
func (i *ipaddressServer) Close(ctx context.Context, conn *networkservice.Connection) (*empty.Empty, error) { | ||
return next.Server(ctx).Close(ctx, conn) | ||
} |
75 changes: 75 additions & 0 deletions
75
pkg/networkservice/connectioncontextkernel/ipcontext/routes/client.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright (c) 2020 Cisco and/or its affiliates. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// +build linux | ||
|
||
package routes | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/golang/protobuf/ptypes/empty" | ||
"github.com/networkservicemesh/api/pkg/api/networkservice" | ||
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next" | ||
"google.golang.org/grpc" | ||
|
||
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata" | ||
) | ||
|
||
type routesClient struct{} | ||
|
||
// NewClient creates a NetworkServiceClient that will put the routes from the connection context into | ||
// the kernel network namespace kernel interface being inserted iff the | ||
// selected mechanism for the connection is a kernel mechanism | ||
// Client | ||
// +- - - - - - - - - - - - - - - -+ +---------------------------+ | ||
// | | | kernel network namespace | | ||
// | | | ||
// | | | | | ||
// | | | ||
// | | | | | ||
// | | | ||
// | | | | | ||
// +--------- ---------+ | | ||
// | | | | | ||
// | | | ||
// | | | | | ||
// | routes.Client() | | ||
// | | | | | ||
// | | | ||
// | | | | | ||
// +- - - - - - - - - - - - - - - -+ +---------------------------+ | ||
// | ||
func NewClient() networkservice.NetworkServiceClient { | ||
return &routesClient{} | ||
} | ||
|
||
func (i *routesClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) { | ||
conn, err := next.Client(ctx).Request(ctx, request, opts...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err := create(ctx, conn, metadata.IsClient(i)); err != nil { | ||
_, _ = i.Close(ctx, conn, opts...) | ||
return nil, err | ||
} | ||
return conn, nil | ||
} | ||
|
||
func (i *routesClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) { | ||
// We do not have to delete routes here because the kernel deletes routes for us when we delete the interface | ||
return next.Client(ctx).Close(ctx, conn, opts...) | ||
} |
92 changes: 92 additions & 0 deletions
92
pkg/networkservice/connectioncontextkernel/ipcontext/routes/common.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Copyright (c) 2020 Cisco and/or its affiliates. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// +build linux | ||
|
||
package routes | ||
|
||
import ( | ||
"context" | ||
"net" | ||
"time" | ||
|
||
"github.com/networkservicemesh/sdk/pkg/networkservice/core/trace" | ||
|
||
"github.com/networkservicemesh/api/pkg/api/networkservice" | ||
"github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/kernel" | ||
"github.com/pkg/errors" | ||
"github.com/vishvananda/netlink" | ||
|
||
"github.com/networkservicemesh/sdk-vpp/pkg/tools/link" | ||
"github.com/networkservicemesh/sdk-vpp/pkg/tools/netlinkhandle" | ||
) | ||
|
||
func create(ctx context.Context, conn *networkservice.Connection, isClient bool) error { | ||
if mechanism := kernel.ToMechanism(conn.GetMechanism()); mechanism != nil { | ||
l, ok := link.Load(ctx, isClient) | ||
if !ok { | ||
return nil | ||
} | ||
handle, ok := netlinkhandle.Load(ctx, isClient) | ||
if !ok { | ||
return errors.Errorf("did not find netlink handle with which to program routes") | ||
} | ||
from := conn.GetContext().GetIpContext().GetSrcIPNet() | ||
to := conn.GetContext().GetIpContext().GetDstIPNet() | ||
if isClient { | ||
from = conn.GetContext().GetIpContext().GetDstIPNet() | ||
to = conn.GetContext().GetIpContext().GetSrcIPNet() | ||
} | ||
routes := conn.GetContext().GetIpContext().GetDstRoutes() | ||
if isClient { | ||
routes = conn.GetContext().GetIpContext().GetSrcRoutes() | ||
} | ||
for _, route := range routes { | ||
if err := routeAdd(ctx, handle, l, netlink.SCOPE_UNIVERSE, route.GetPrefixIPNet(), to); err != nil { | ||
return err | ||
} | ||
} | ||
if to != nil && !to.Contains(from.IP) { | ||
if err := routeAdd(ctx, handle, l, netlink.SCOPE_LINK, to, nil); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func routeAdd(ctx context.Context, handle *netlink.Handle, l netlink.Link, scope netlink.Scope, prefix, gw *net.IPNet) error { | ||
route := &netlink.Route{ | ||
LinkIndex: l.Attrs().Index, | ||
Scope: scope, | ||
Dst: prefix, | ||
} | ||
if gw != nil { | ||
route.Gw = gw.IP | ||
} | ||
now := time.Now() | ||
if err := handle.RouteAdd(route); err != nil { | ||
return errors.WithStack(err) | ||
} | ||
trace.Log(ctx). | ||
WithField("link.Name", l.Attrs().Name). | ||
WithField("route.Dst", route.Dst). | ||
WithField("route.Gw", route.Gw). | ||
WithField("route.Scope", route.Scope). | ||
WithField("duration", time.Since(now)). | ||
WithField("netlink", "RouteAdd").Debug("completed") | ||
return nil | ||
} |
Oops, something went wrong.