Skip to content

Commit

Permalink
Added vppinit to connect vpp to tunnel ip interface. (#25)
Browse files Browse the repository at this point in the history
Signed-off-by: Ed Warnicke <hagbard@gmail.com>
  • Loading branch information
edwarnicke authored Jan 13, 2021
1 parent 546dba3 commit 4f550e8
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 12 deletions.
4 changes: 4 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,7 @@ issues:
linters:
- funlen
text: "Function 'SetupSuite'"
- path: internal/vppinit/vppinit.go
linters:
- gocritic
text: "each iteration copies 216 bytes"
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ require (
github.com/antonfisher/nested-logrus-formatter v1.3.0
github.com/edwarnicke/debug v1.0.0
github.com/edwarnicke/exechelper v1.0.3
github.com/edwarnicke/govpp v0.0.0-20201111163523-106f68b6ba26
github.com/edwarnicke/grpcfd v0.0.0-20201107002751-f220aed0c5c8
github.com/edwarnicke/log v1.0.0
github.com/edwarnicke/signalctx v0.0.0-20201105214533-3a35840b3011
github.com/edwarnicke/vpphelper v0.0.0-20201125015206-ce96ab6dfb2e
github.com/golang/protobuf v1.4.3
github.com/kelseyhightower/envconfig v1.4.0
github.com/networkservicemesh/api v0.0.0-20201204203731-4294f67deaa4
github.com/networkservicemesh/sdk v0.0.0-20201209081426-89944c40ef4d
github.com/networkservicemesh/sdk-vpp v0.0.0-20201209081928-bc4b4c86151f
github.com/networkservicemesh/api v0.0.0-20210112152104-45029fb10e27
github.com/networkservicemesh/sdk v0.0.0-20210109184324-006d62c50a0a
github.com/networkservicemesh/sdk-vpp v0.0.0-20210113003323-54ae665f4e4e
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0
github.com/spiffe/go-spiffe/v2 v2.0.0-beta.2
Expand Down
13 changes: 7 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,13 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nats-io/stan.go v0.6.0/go.mod h1:eIcD5bi3pqbHT/xIIvXMwvzXYElgouBvaVRftaE+eac=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/networkservicemesh/api v0.0.0-20201204203731-4294f67deaa4 h1:2HsHa5QtuMh5mjIqLWkiQx2cxFZMiYtQCvM8N7LjFVU=
github.com/networkservicemesh/api v0.0.0-20201204203731-4294f67deaa4/go.mod h1:qvxdY1Zt4QTtiG+uH1XmjpegeHjlt5Jj4A8iK55iJPI=
github.com/networkservicemesh/sdk v0.0.0-20201209081426-89944c40ef4d h1:sUVW+0ojn4+kY+Mw0MgZoIsLHqzyQBRExvQhJdlrYdM=
github.com/networkservicemesh/sdk v0.0.0-20201209081426-89944c40ef4d/go.mod h1:Mh4ETI2Sw9MJ4VSdTyvRYCP1SBtFy7EeRwxfJW7MvQ8=
github.com/networkservicemesh/sdk-vpp v0.0.0-20201209081928-bc4b4c86151f h1:oenCJ8zZQU665UtdtaigMFcb/VLmn+V9zaVTOAo7iqg=
github.com/networkservicemesh/sdk-vpp v0.0.0-20201209081928-bc4b4c86151f/go.mod h1:IS9ZkozEEeDYEYM+v+wQfDU40+nImBOa1mzJ4Syqqfw=
github.com/networkservicemesh/api v0.0.0-20201229064852-7d9663ff679a/go.mod h1:qvxdY1Zt4QTtiG+uH1XmjpegeHjlt5Jj4A8iK55iJPI=
github.com/networkservicemesh/api v0.0.0-20210112152104-45029fb10e27 h1:J0UPj3sYfEvXwMHyAOiQ++NU7a3cZGZST1s1ftyC0uQ=
github.com/networkservicemesh/api v0.0.0-20210112152104-45029fb10e27/go.mod h1:qvxdY1Zt4QTtiG+uH1XmjpegeHjlt5Jj4A8iK55iJPI=
github.com/networkservicemesh/sdk v0.0.0-20210109184324-006d62c50a0a h1:8LZ+feSJ/aQNZR1FAVMiMDsTT+9UZ0aruXV7VoIA0X8=
github.com/networkservicemesh/sdk v0.0.0-20210109184324-006d62c50a0a/go.mod h1:Zpdjr7DejxfXXbZJyCFkJGwj4zG/vOsGJsRu8Raf3nw=
github.com/networkservicemesh/sdk-vpp v0.0.0-20210113003323-54ae665f4e4e h1:owIEjketZf5T/YjaVz2RAh3eAQwaS8WJNHszPu8FZ0Q=
github.com/networkservicemesh/sdk-vpp v0.0.0-20210113003323-54ae665f4e4e/go.mod h1:upi35zE+gOMjcW7H5cytitZVYfC7/Sxvnrk6B+IgG5s=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nishanths/exhaustive v0.0.0-20200811152831-6cf413ae40e0/go.mod h1:wBEpHwM2OdmeNpdCvRPUlkEbBuaFmcK4Wv8Q7FuGW3c=
Expand Down
11 changes: 10 additions & 1 deletion internal/imports/imports_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ import (
_ "bytes"
_ "context"
_ "fmt"
_ "git.fd.io/govpp.git/api"
_ "git.fd.io/govpp.git/binapi/vpe"
_ "github.com/antonfisher/nested-logrus-formatter"
_ "github.com/edwarnicke/debug"
_ "github.com/edwarnicke/exechelper"
_ "github.com/edwarnicke/govpp/binapi/af_packet"
_ "github.com/edwarnicke/govpp/binapi/fib_types"
_ "github.com/edwarnicke/govpp/binapi/interface"
_ "github.com/edwarnicke/govpp/binapi/interface_types"
_ "github.com/edwarnicke/govpp/binapi/ip"
_ "github.com/edwarnicke/grpcfd"
_ "github.com/edwarnicke/log"
_ "github.com/edwarnicke/signalctx"
Expand All @@ -24,6 +31,7 @@ import (
_ "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/memif"
_ "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/tag"
_ "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/up"
_ "github.com/networkservicemesh/sdk-vpp/pkg/tools/types"
_ "github.com/networkservicemesh/sdk/pkg/networkservice/chains/client"
_ "github.com/networkservicemesh/sdk/pkg/networkservice/chains/endpoint"
_ "github.com/networkservicemesh/sdk/pkg/networkservice/common/authorize"
Expand All @@ -33,15 +41,16 @@ import (
_ "github.com/networkservicemesh/sdk/pkg/networkservice/common/mechanisms/sendfd"
_ "github.com/networkservicemesh/sdk/pkg/networkservice/core/chain"
_ "github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
_ "github.com/networkservicemesh/sdk/pkg/networkservice/core/trace"
_ "github.com/networkservicemesh/sdk/pkg/networkservice/ipam/point2pointipam"
_ "github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
_ "github.com/networkservicemesh/sdk/pkg/registry/common/expire"
_ "github.com/networkservicemesh/sdk/pkg/registry/common/memory"
_ "github.com/networkservicemesh/sdk/pkg/registry/common/recvfd"
_ "github.com/networkservicemesh/sdk/pkg/registry/common/sendfd"
_ "github.com/networkservicemesh/sdk/pkg/registry/common/setid"
_ "github.com/networkservicemesh/sdk/pkg/registry/core/adapters"
_ "github.com/networkservicemesh/sdk/pkg/registry/core/chain"
_ "github.com/networkservicemesh/sdk/pkg/registry/memory"
_ "github.com/networkservicemesh/sdk/pkg/tools/grpcutils"
_ "github.com/networkservicemesh/sdk/pkg/tools/log"
_ "github.com/networkservicemesh/sdk/pkg/tools/spiffejwt"
Expand Down
4 changes: 2 additions & 2 deletions internal/tests/suite_setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ import (

"github.com/networkservicemesh/api/pkg/api/registry"
"github.com/networkservicemesh/sdk/pkg/registry/common/expire"
"github.com/networkservicemesh/sdk/pkg/registry/common/memory"
registryrecvfd "github.com/networkservicemesh/sdk/pkg/registry/common/recvfd"
"github.com/networkservicemesh/sdk/pkg/registry/common/setid"
"github.com/networkservicemesh/sdk/pkg/registry/core/adapters"
registrychain "github.com/networkservicemesh/sdk/pkg/registry/core/chain"
"github.com/networkservicemesh/sdk/pkg/registry/memory"
"github.com/networkservicemesh/sdk/pkg/tools/log"
"github.com/networkservicemesh/sdk/pkg/tools/spire"

Expand Down Expand Up @@ -116,7 +116,7 @@ func (f *ForwarderTestSuite) SetupSuite() {
memrg := memory.NewNetworkServiceEndpointRegistryServer()
registryServer := registrychain.NewNetworkServiceEndpointRegistryServer(
setid.NewNetworkServiceEndpointRegistryServer(),
expire.NewNetworkServiceEndpointRegistryServer(),
expire.NewNetworkServiceEndpointRegistryServer(time.Hour),
registryrecvfd.NewNetworkServiceEndpointRegistryServer(),
memrg,
)
Expand Down
213 changes: 213 additions & 0 deletions internal/vppinit/vppinit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
// 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 vppinit contains initialization code for vpp
package vppinit

import (
"context"
"fmt"
"net"
"time"

"git.fd.io/govpp.git/api"
"github.com/edwarnicke/govpp/binapi/af_packet"
"github.com/edwarnicke/govpp/binapi/fib_types"
interfaces "github.com/edwarnicke/govpp/binapi/interface"
"github.com/edwarnicke/govpp/binapi/interface_types"
"github.com/edwarnicke/govpp/binapi/ip"
"github.com/pkg/errors"
"github.com/vishvananda/netlink"

"github.com/networkservicemesh/sdk-vpp/pkg/tools/types"
"github.com/networkservicemesh/sdk/pkg/networkservice/core/trace"
)

// Must - simple wrapper to panic in the event of an error
func Must(tunnelIP net.IP, err error) net.IP {
if err != nil {
panic(fmt.Sprintf("error: %+v", err))
}
return tunnelIP
}

// LinkToAfPacket - will link vpp via af_packet to the interface having the tunnelIP
// if tunnelIP is nil, it will find the interface for the default route and use that instead.
// It returns the resulting tunnelIP
func LinkToAfPacket(ctx context.Context, vppConn api.Connection, tunnelIP net.IP) (net.IP, error) {
link, addrs, routes, err := linkAddrsRoutes(ctx, tunnelIP)
if err != nil {
return nil, err
}
if link == nil {
return tunnelIP, nil
}
afPacketCreate := &af_packet.AfPacketCreate{
HwAddr: types.ToVppMacAddress(&link.Attrs().HardwareAddr),
HostIfName: link.Attrs().Name,
}
now := time.Now()
afPacketCreateRsp, err := af_packet.NewServiceClient(vppConn).AfPacketCreate(ctx, afPacketCreate)
if err != nil {
return nil, err
}
trace.Log(ctx).
WithField("swIfIndex", afPacketCreateRsp.SwIfIndex).
WithField("duration", time.Since(now)).
WithField("vppapi", "AfPacketCreate").Debug("completed")

now = time.Now()
_, err = interfaces.NewServiceClient(vppConn).SwInterfaceSetFlags(ctx, &interfaces.SwInterfaceSetFlags{
SwIfIndex: afPacketCreateRsp.SwIfIndex,
Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
})
if err != nil {
return nil, err
}
trace.Log(ctx).
WithField("swIfIndex", afPacketCreateRsp.SwIfIndex).
WithField("duration", time.Since(now)).
WithField("vppapi", "SwInterfaceSetFlags").Debug("completed")

for _, addr := range addrs {
if addr.IPNet != nil && addr.IPNet.IP.IsGlobalUnicast() && tunnelIP == nil {
tunnelIP = addr.IPNet.IP
}
if addr.IPNet != nil && addr.IPNet.IP.Equal(tunnelIP) {
now = time.Now()
_, err = interfaces.NewServiceClient(vppConn).SwInterfaceAddDelAddress(ctx, &interfaces.SwInterfaceAddDelAddress{
SwIfIndex: afPacketCreateRsp.SwIfIndex,
IsAdd: true,
Prefix: types.ToVppAddressWithPrefix(addr.IPNet),
})
if err != nil {
return nil, err
}
trace.Log(ctx).
WithField("swIfIndex", afPacketCreateRsp.SwIfIndex).
WithField("prefix", addr.IPNet).
WithField("isAdd", true).
WithField("duration", time.Since(now)).
WithField("vppapi", "SwInterfaceAddDelAddress").Debug("completed")
}
}
ipRouteAddDel := &ip.IPRouteAddDel{
IsAdd: true,
Route: ip.IPRoute{
StatsIndex: 0,
NPaths: 1,
Paths: []fib_types.FibPath{
{
SwIfIndex: uint32(afPacketCreateRsp.SwIfIndex),
TableID: 0,
RpfID: 0,
Weight: 1,
Type: fib_types.FIB_API_PATH_TYPE_NORMAL,
Flags: fib_types.FIB_API_PATH_FLAG_NONE,
Proto: types.IsV6toFibProto(tunnelIP.To4() == nil),
},
},
},
}
for _, route := range routes {
ipRouteAddDel.Route.Prefix = types.ToVppPrefix(route.Dst)
if route.Gw != nil {
ipRouteAddDel.Route.Paths[0].Nh.Address = types.ToVppAddress(route.Gw).Un
}
now = time.Now()
_, err = ip.NewServiceClient(vppConn).IPRouteAddDel(ctx, ipRouteAddDel)
if err != nil {
return nil, err
}
trace.Log(ctx).
WithField("swIfIndex", afPacketCreateRsp.SwIfIndex).
WithField("prefix", ipRouteAddDel.Route.Prefix).
WithField("isAdd", true).
WithField("duration", time.Since(now)).
WithField("vppapi", "IPRouteAddDel").Debug("completed")
}
return tunnelIP, nil
}

func linkAddrsRoutes(ctx context.Context, tunnelIP net.IP) (netlink.Link, []netlink.Addr, []netlink.Route, error) {
link, err := linkByIP(ctx, tunnelIP)
if err != nil {
return nil, nil, nil, err
}
if link == nil {
return nil, nil, nil, nil
}
addrs, err := netlink.AddrList(link, netlink.FAMILY_ALL)
if err != nil {
return nil, nil, nil, errors.Wrapf(err, "error getting addrs for link %s", link.Attrs().Name)
}
routes, err := netlink.RouteList(link, netlink.FAMILY_ALL)
if err != nil {
return nil, nil, nil, errors.Wrapf(err, "could not find routes for link %s", link.Attrs().Name)
}
return link, addrs, routes, nil
}

func defaultRouteLink(ctx context.Context) (netlink.Link, error) {
now := time.Now()
routes, err := netlink.RouteList(nil, netlink.FAMILY_ALL)
if err != nil {
return nil, errors.Wrap(err, "unable to get routes")
}

trace.Log(ctx).
WithField("duration", time.Since(now)).
WithField("netlink", "RouteList").Debug("completed")

for _, route := range routes {
// Is it a default route?
if route.Dst != nil {
ones, _ := route.Dst.Mask.Size()
if ones == 0 && (route.Dst.IP.Equal(net.IPv4zero) || route.Dst.IP.Equal(net.IPv6zero)) {
return netlink.LinkByIndex(route.LinkIndex)
}
continue
}
if route.Scope == netlink.SCOPE_UNIVERSE {
return netlink.LinkByIndex(route.LinkIndex)
}
}
return nil, errors.New("no link found for default route")
}

func linkByIP(ctx context.Context, ipaddress net.IP) (netlink.Link, error) {
if ipaddress == nil {
return defaultRouteLink(ctx)
}
links, err := netlink.LinkList()
if err != nil {
return nil, errors.Wrap(err, "unable to get links")
}
for _, link := range links {
addrs, err := netlink.AddrList(link, netlink.FAMILY_ALL)
if err != nil {
return nil, errors.Wrap(err, "could not find links for default routes")
}
for _, addr := range addrs {
if addr.IPNet != nil && addr.IPNet.IP.Equal(ipaddress) {
return link, nil
}
}
}
return nil, nil
}
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ import (
registrychain "github.com/networkservicemesh/sdk/pkg/registry/core/chain"
"github.com/networkservicemesh/sdk/pkg/tools/grpcutils"
"github.com/networkservicemesh/sdk/pkg/tools/spiffejwt"

"github.com/networkservicemesh/cmd-forwarder-vpp/internal/vppinit"
)

// Config - configuration for cmd-forwarder-vpp
Expand Down Expand Up @@ -155,6 +157,7 @@ func main() {
&config.ConnectTo,
vppConn,
memifSocketDir,
vppinit.Must(vppinit.LinkToAfPacket(ctx, vppConn, config.TunnelIP)),
grpc.WithTransportCredentials(grpcfd.TransportCredentials(credentials.NewTLS(tlsconfig.MTLSClientConfig(source, source, tlsconfig.AuthorizeAny())))),
grpc.WithDefaultCallOptions(grpc.WaitForReady(true)),
)
Expand Down

0 comments on commit 4f550e8

Please sign in to comment.