Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read parameters for vpp host interface creation from config file #1027

Merged
merged 6 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ require (
go.fd.io/govpp v0.10.0-alpha.0.20240110141843-761adec77524
golang.org/x/text v0.14.0
google.golang.org/grpc v1.59.0
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand Down Expand Up @@ -94,6 +95,5 @@ require (
gopkg.in/fsnotify.v1 v1.4.7 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/kubelet v0.28.3 // indirect
)
15 changes: 9 additions & 6 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) 2020-2023 Cisco and/or its affiliates.
// Copyright (c) 2020-2024 Cisco and/or its affiliates.
//
// Copyright (c) 2021-2023 Doc.ai and/or its affiliates.
// Copyright (c) 2021-2024 Doc.ai and/or its affiliates.
//
// Copyright (c) 2024 Nordix and/or its affiliates.
//
// SPDX-License-Identifier: Apache-2.0
//
Expand Down Expand Up @@ -46,10 +48,11 @@ type Config struct {
OpenTelemetryEndpoint string `default:"otel-collector.observability.svc.cluster.local:4317" desc:"OpenTelemetry Collector Endpoint"`
MetricsExportInterval time.Duration `default:"10s" desc:"interval between mertics exports" split_words:"true"`

TunnelIP net.IP `desc:"IP to use for tunnels" split_words:"true"`
VxlanPort uint16 `default:"0" desc:"VXLAN port to use" split_words:"true"`
VppAPISocket string `default:"/var/run/vpp/external/vpp-api.sock" desc:"filename of socket to connect to existing VPP instance. If empty a VPP instance is run in forwarder" split_words:"true"`
VppInit vppinit.Func `default:"AF_PACKET" desc:"type of VPP initialization. Must be AF_XDP, AF_PACKET or NONE" split_words:"true"`
TunnelIP net.IP `desc:"IP to use for tunnels" split_words:"true"`
VxlanPort uint16 `default:"0" desc:"VXLAN port to use" split_words:"true"`
VppAPISocket string `default:"/var/run/vpp/external/vpp-api.sock" desc:"filename of socket to connect to existing VPP instance. If empty a VPP instance is run in forwarder" split_words:"true"`
VppInit vppinit.Func `default:"AF_PACKET" desc:"type of VPP initialization. Must be AF_XDP, AF_PACKET or NONE" split_words:"true"`
VppInitParams string `desc:"Configuration file path containing VPP API parameters for initialization" split_words:"true"`

ResourcePollTimeout time.Duration `default:"30s" desc:"device plugin polling timeout" split_words:"true"`
DevicePluginPath string `default:"/var/lib/kubelet/device-plugins/" desc:"path to the device plugin directory" split_words:"true"`
Expand Down
1 change: 1 addition & 0 deletions internal/imports/imports_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

127 changes: 127 additions & 0 deletions internal/tests/apiparams_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright (c) 2024 Nordix Foundation.
//
// 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 tests

import (
"context"
"os"
"path"
"testing"

"github.com/stretchr/testify/require"
yaml "gopkg.in/yaml.v3"

"github.com/networkservicemesh/govpp/binapi/af_packet"

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

const (
configFilePath = "/var/lib/networkservicemesh/vppapi-hostint-args.yaml"
)

type SomeValuesType struct {
AfPacket *SomeAfPacketParams `yaml:"AF_PACKET"`
AfXdp *SomeAfXDPParams `yaml:"AF_XDP"`
}

type SomeAfPacketParams struct {
RxFrameSize uint32 `yaml:"rxFrameSize"`
RxFramesPerBlock uint32 `yaml:"rxFramesPerBlock"`
}

type SomeAfXDPParams struct {
RxqSize uint16 `yaml:"rxqSize"`
}

var someValues = &SomeValuesType{
AfPacket: &SomeAfPacketParams{
RxFrameSize: 20480,
RxFramesPerBlock: 2048,
},
AfXdp: &SomeAfXDPParams{
RxqSize: 16384,
},
}

func (c *SomeValuesType) DumpToFile(filename string) error {
contents, err := yaml.Marshal(c)
if err != nil {
return err
}
if err := os.MkdirAll(path.Dir(filename), 0o700); err != nil {
return err
}
return os.WriteFile(filename, contents, 0o600)
}

func TestDefaults(t *testing.T) {
packetValues := vppinit.GetAfPacketValues(context.Background())
require.Equal(t, &vppinit.AfPacketParams{
Mode: af_packet.AF_PACKET_API_MODE_ETHERNET,
Flags: af_packet.AF_PACKET_API_FLAG_VERSION_2,
RxFrameSize: 10240,
TxFrameSize: 10240,
RxFramesPerBlock: 1024,
TxFramesPerBlock: 1024,
NumRxQueues: 1,
NumTxQueues: 0,
},
packetValues)

xdpValues := vppinit.GetAfXdpValues(context.Background())
require.Equal(t, &vppinit.AfXDPParams{
Mode: 0,
RxqSize: 8192,
TxqSize: 8192,
Flags: 0,
},
xdpValues)
}

func TestSomeValuesSet(t *testing.T) {
_ = os.Setenv("NSM_VPP_INIT_PARAMS", configFilePath)
err := someValues.DumpToFile(configFilePath)
require.NoError(t, err)
defer func() {
if errRem := os.RemoveAll(configFilePath); errRem != nil {
t.Fatalf("no file generated or the generated file cannot removed")
}
}()

packetValues := vppinit.GetAfPacketValues(context.Background())
require.Equal(t, &vppinit.AfPacketParams{
Mode: af_packet.AF_PACKET_API_MODE_ETHERNET,
Flags: af_packet.AF_PACKET_API_FLAG_VERSION_2,
RxFrameSize: 20480,
TxFrameSize: 10240,
RxFramesPerBlock: 2048,
TxFramesPerBlock: 1024,
NumRxQueues: 1,
NumTxQueues: 0,
},
packetValues)

xdpValues := vppinit.GetAfXdpValues(context.Background())
require.Equal(t, &vppinit.AfXDPParams{
Mode: 0,
RxqSize: 16384,
TxqSize: 8192,
Flags: 0,
},
xdpValues)
}
140 changes: 140 additions & 0 deletions internal/vppinit/apiparams.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright (c) 2024 Nordix Foundation.
//
// 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 vppinit

import (
"context"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/pkg/errors"
yaml "gopkg.in/yaml.v3"

"github.com/networkservicemesh/govpp/binapi/af_packet"
"github.com/networkservicemesh/govpp/binapi/af_xdp"
"github.com/networkservicemesh/sdk/pkg/tools/log"
)

// Parameters contains parameters for various AF types
type Parameters struct {
AfPacket *AfPacketParams `yaml:"AF_PACKET"`
AfXdp *AfXDPParams `yaml:"AF_XDP"`
}

func (c *Parameters) String() string {
sb := &strings.Builder{}
_, _ = sb.WriteString("&{")
_, _ = sb.WriteString("AF_PACKET:{")
var strs []string
strs = append(strs, fmt.Sprintf("%+v", c.AfPacket))
_, _ = sb.WriteString(strings.Join(strs, " "))
_, _ = sb.WriteString("},")

_, _ = sb.WriteString("AF_XDP:{")
var xdpStrs []string
xdpStrs = append(xdpStrs, fmt.Sprintf("%+v", c.AfXdp))
_, _ = sb.WriteString(strings.Join(xdpStrs, " "))
_, _ = sb.WriteString("},")
_, _ = sb.WriteString("}")
return sb.String()
}

// AfPacketParams contains configuration parameters for AF_PACKET interface
type AfPacketParams struct {
Mode af_packet.AfPacketMode `yaml:"mode"`
RxFrameSize uint32 `yaml:"rxFrameSize"`
TxFrameSize uint32 `yaml:"txFrameSize"`
RxFramesPerBlock uint32 `yaml:"rxFramesPerBlock"`
TxFramesPerBlock uint32 `yaml:"txFramesPerBlock"`
NumRxQueues uint16 `yaml:"numRxQueues"`
NumTxQueues uint16 `yaml:"numTxQueues"`
Flags af_packet.AfPacketFlags `yaml:"flags"`
}

// AfXDPParams contains configuration parameters for AF_XDP interface
type AfXDPParams struct {
Mode af_xdp.AfXdpMode `yaml:"mode"`
RxqSize uint16 `yaml:"rxqSize"`
TxqSize uint16 `yaml:"txqSize"`
Flags af_xdp.AfXdpFlag `yaml:"flags"`
}

func getDefaults() *Parameters {
return &Parameters{
AfPacket: &AfPacketParams{
Mode: af_packet.AF_PACKET_API_MODE_ETHERNET,
RxFrameSize: 10240,
TxFrameSize: 10240,
RxFramesPerBlock: 1024,
TxFramesPerBlock: 1024,
NumRxQueues: 1,
NumTxQueues: 0,
Flags: af_packet.AF_PACKET_API_FLAG_VERSION_2,
},
AfXdp: &AfXDPParams{
Mode: af_xdp.AF_XDP_API_MODE_AUTO,
RxqSize: 8192,
TxqSize: 8192,
Flags: 0,
},
}
}

// GetAfPacketValues get parameter values for af-packet interface creation
func GetAfPacketValues(ctx context.Context) *AfPacketParams {
return getConfig(ctx).AfPacket
}

// GetAfXdpValues get parameter values for af-xdp interface creation
func GetAfXdpValues(ctx context.Context) *AfXDPParams {
return getConfig(ctx).AfXdp
}

func getConfig(ctx context.Context) *Parameters {
cfg := getDefaults()
confFilename := os.Getenv("NSM_VPP_INIT_PARAMS")
logger := log.FromContext(ctx).WithField("ReadConfig", confFilename)
if confFilename == "" {
logger.Infof("Using default VPP init parameters %+v", cfg)
return cfg
}
if _, err := os.Stat(confFilename); os.IsNotExist(err) {
logger.Infof("Configuration file: %q not found, using default VPP init parameters (%+v)", confFilename, cfg)
return cfg
}
err := readConfig(confFilename, cfg)
if err != nil {
defaultCfg := getDefaults()
logger.Warnf("Failed to read VPP init parameters %+v Using: %+v", err, defaultCfg)
return defaultCfg
}
logger.Infof("Unmarshalled VPP init parameters: %s", cfg)
return cfg
}

func readConfig(configFile string, cfg *Parameters) error {
bytes, err := os.ReadFile(filepath.Clean(configFile))
if err != nil {
return errors.Wrapf(err, "error reading file: %v", configFile)
}
if err = yaml.Unmarshal(bytes, cfg); err != nil {
return errors.Wrapf(err, "error unmarshalling yaml: %s", bytes)
}
return nil
}
31 changes: 19 additions & 12 deletions internal/vppinit/vppinit.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) 2020-2023 Cisco and/or its affiliates.
//
// Copyright (c) 2024 Nordix Foundation.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -41,7 +43,6 @@ import (
"github.com/networkservicemesh/govpp/binapi/ip"
"github.com/networkservicemesh/govpp/binapi/ip6_nd"
"github.com/networkservicemesh/govpp/binapi/ip_neighbor"

"github.com/networkservicemesh/sdk-vpp/pkg/tools/types"
"github.com/networkservicemesh/sdk/pkg/tools/log"
)
Expand Down Expand Up @@ -285,13 +286,18 @@ func LinkToSocket(ctx context.Context, vppConn api.Connection, tunnelIP net.IP,
}

func createAfPacket(ctx context.Context, vppConn api.Connection, link netlink.Link) (interface_types.InterfaceIndex, error) {
afPacketCreate := &af_packet.AfPacketCreateV3{
Mode: af_packet.AF_PACKET_API_MODE_ETHERNET,
HwAddr: types.ToVppMacAddress(&link.Attrs().HardwareAddr),
HostIfName: link.Attrs().Name,
RxFrameSize: 10240,
TxFrameSize: 10240,
Flags: af_packet.AF_PACKET_API_FLAG_VERSION_2,
c := GetAfPacketValues(ctx)
var afPacketCreate *af_packet.AfPacketCreateV3 = &af_packet.AfPacketCreateV3{
Mode: c.Mode,
HwAddr: types.ToVppMacAddress(&link.Attrs().HardwareAddr),
HostIfName: link.Attrs().Name,
RxFrameSize: c.RxFrameSize,
TxFrameSize: c.TxFrameSize,
RxFramesPerBlock: c.RxFramesPerBlock,
TxFramesPerBlock: c.TxFramesPerBlock,
NumRxQueues: c.NumRxQueues,
NumTxQueues: c.NumTxQueues,
Flags: c.Flags,
}
now := time.Now()
afPacketCreateRsp, err := af_packet.NewServiceClient(vppConn).AfPacketCreateV3(ctx, afPacketCreate)
Expand All @@ -316,13 +322,14 @@ func createAfXDP(ctx context.Context, vppConn api.Connection, link netlink.Link)
if err != nil {
return 0, err
}

c := GetAfXdpValues(ctx)
afXDPCreate := &af_xdp.AfXdpCreate{
HostIf: link.Attrs().Name,
RxqSize: 8192,
TxqSize: 8192,
RxqSize: c.RxqSize,
TxqSize: c.TxqSize,
RxqNum: rxqNum,
Mode: af_xdp.AF_XDP_API_MODE_AUTO,
Mode: c.Mode,
Flags: c.Flags,
Prog: "/bin/afxdp.o",
}

Expand Down
Loading