Skip to content

Commit

Permalink
Parameters for vpp's host interface creation read from config file
Browse files Browse the repository at this point in the history
Signed-off-by: Laszlo Kiraly <[email protected]>
  • Loading branch information
ljkiraly committed Mar 11, 2024
1 parent 2bc4843 commit 13c1a73
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 13 deletions.
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
)
167 changes: 167 additions & 0 deletions internal/vppinit/apiparams/apiparams.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// 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 apiparams provides parsing factilty for configuration parameters
// file for vpp init
package apiparams

import (
"context"
"fmt"
"os"
"path"
"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"
)

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

func (c *ConfigYAML) 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:{")
strs = append(strs, fmt.Sprintf("%+v", c.AfXdp))
_, _ = sb.WriteString(strings.Join(strs, " "))
_, _ = sb.WriteString("},")
_, _ = sb.WriteString("}")
return sb.String()
}

// DumpToFile Dump the structure to a given file in yaml format
func (c *ConfigYAML) 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)
}

// 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"`
}

// 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
}

// DefaultAPIArgs default arguments used by create host interface APIs
var DefaultAPIArgs = &ConfigYAML{
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,
},
}

func getConfig(ctx context.Context) *ConfigYAML {
if _, err := os.Stat(confFilename); os.IsNotExist(err) {
log.FromContext(ctx).Infof("Configuration file: %q not found, using defaults", confFilename)
if err = DefaultAPIArgs.DumpToFile(confFilename); err != nil {
log.FromContext(ctx).Warnf("Failed to expose used vppapi AF_ interface default values %+v", err)
}
return DefaultAPIArgs
}
cfg, err := ReadConfig(ctx, confFilename)
if err != nil {
log.FromContext(ctx).Warnf("Failed to get vppapi AF_ interface default values %+v", err)
return DefaultAPIArgs
}
return cfg
}

// ReadConfig reads configuration from file
func ReadConfig(ctx context.Context, configFile string) (*ConfigYAML, error) {
cfg := &ConfigYAML{
&AfPacketParams{
Mode: DefaultAPIArgs.AfPacket.Mode,
RxFrameSize: DefaultAPIArgs.AfPacket.RxFrameSize,
TxFrameSize: DefaultAPIArgs.AfPacket.TxFrameSize,
RxFramesPerBlock: DefaultAPIArgs.AfPacket.RxFramesPerBlock,
TxFramesPerBlock: DefaultAPIArgs.AfPacket.TxFramesPerBlock,
NumRxQueues: DefaultAPIArgs.AfPacket.NumRxQueues,
NumTxQueues: DefaultAPIArgs.AfPacket.NumTxQueues,
Flags: DefaultAPIArgs.AfPacket.Flags,
},
&AfXDPParams{
Mode: DefaultAPIArgs.AfXdp.Mode,
RxqSize: DefaultAPIArgs.AfXdp.RxqSize,
TxqSize: DefaultAPIArgs.AfXdp.TxqSize,
Flags: DefaultAPIArgs.AfXdp.Flags,
},
}
bytes, err := os.ReadFile(filepath.Clean(configFile))
if err != nil {
return nil, errors.Wrapf(err, "error reading file: %v", configFile)
}
if err = yaml.Unmarshal(bytes, cfg); err != nil {
return nil, errors.Wrapf(err, "error unmarshalling yaml: %s", bytes)
}
log.FromContext(ctx).WithField("ReadConfig", configFile).Infof("unmarshalled Config: %+v", cfg)
return cfg, nil
}
81 changes: 81 additions & 0 deletions internal/vppinit/apiparams/apiparams_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// 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 apiparams_test

import (
"bytes"
"context"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"

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

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

const (
configFileName = "example-host-int-args.yaml"
defaultFileName = "default.yaml"
generatedFileName = "default-generated.yaml"
)

func TestReadConfigFile(t *testing.T) {
cfg, err := apiparams.ReadConfig(context.Background(), configFileName)
require.NoError(t, err)
require.Equal(t, &apiparams.ConfigYAML{
AfPacket: &apiparams.AfPacketParams{
Mode: af_packet.AF_PACKET_API_MODE_ETHERNET,
Flags: af_packet.AF_PACKET_API_FLAG_CKSUM_GSO,
RxFrameSize: 2048,
TxFrameSize: 10240,
RxFramesPerBlock: 32,
TxFramesPerBlock: 1024,
NumRxQueues: 1,
NumTxQueues: 1,
},
AfXdp: &apiparams.AfXDPParams{
Mode: af_xdp.AF_XDP_API_MODE_COPY,
RxqSize: 8192,
TxqSize: 8192,
Flags: af_xdp.AF_XDP_API_FLAGS_NO_SYSCALL_LOCK,
},
}, cfg)
}

func TestDumpDefaults(t *testing.T) {
err := apiparams.DefaultAPIArgs.DumpToFile(generatedFileName)
require.NoError(t, err)
defer func() {
if errRem := os.RemoveAll(generatedFileName); errRem != nil {
t.Fatalf("no file generated")
}
}()

generated, err := os.ReadFile(filepath.Clean(generatedFileName))
require.NoError(t, err)
want, err := os.ReadFile(filepath.Clean(defaultFileName))
require.NoError(t, err)

if !bytes.Equal(generated, want) {
t.Fatalf("%s: have:\n%s\nwant:\n%s\n%+v", generatedFileName, generated,
want, apiparams.DefaultAPIArgs)
}
}
23 changes: 23 additions & 0 deletions internal/vppinit/apiparams/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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 apiparams provides parsing factilty for configuration parameters
// file for vpp init
package apiparams

const (
confFilename = "/var/lib/networkservicemesh/vppapi-hostint-args.yaml"
)
14 changes: 14 additions & 0 deletions internal/vppinit/apiparams/default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
AF_PACKET:
mode: 1
rxFrameSize: 10240
txFrameSize: 10240
rxFramesPerBlock: 1024
txFramesPerBlock: 1024
numRxQueues: 1
numTxQueues: 0
flags: 8
AF_XDP:
mode: 0
rxqSize: 8192
txqSize: 8192
flags: 0
21 changes: 21 additions & 0 deletions internal/vppinit/apiparams/example-host-int-args.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
# DO NOT use this configuration in production
# This file is for testing and documentation purpose

# Arguments for create host-interface API calls

AF_PACKET:
mode: 1 # 1 - Ethernet (NSM default), 2 - IP
rxFrameSize: 2048 # frame size for RX
txFrameSize: 10240 # frame size for TX
rxFramesPerBlock: 32 # frames per block for RX
txFramesPerBlock: 1024 # frames per block for TX
flags: 2 # flags for the af_packet interface creation (1 - enable the qdisc bypass, 2 - nable checksum/gso, 8 - af packet v2 api /the default in NSM/ if it is not set af packet v3)
numRxQueues: 1 # number of rx queues
numTxQueues: 1 # number of tx queues (not considered in case of AF_PACKET_V2)

AF_XDP:
mode: 1 # operation mode
rxqSize: 8192 # receive queue size
txqSize: 8192 # transmit queue size
flags: 1 # flags
32 changes: 20 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,9 +43,10 @@ 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"

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

// AfType represents socket address family
Expand Down Expand Up @@ -285,13 +288,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,
var c apiparams.AfPacketParams = *apiparams.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 +324,13 @@ func createAfXDP(ctx context.Context, vppConn api.Connection, link netlink.Link)
if err != nil {
return 0, err
}

var c apiparams.AfXDPParams = *apiparams.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,
Prog: "/bin/afxdp.o",
}

Expand Down

0 comments on commit 13c1a73

Please sign in to comment.