Skip to content

Commit

Permalink
set mellanox reg key (#1768)
Browse files Browse the repository at this point in the history
  • Loading branch information
rajvinar committed Jun 13, 2023
1 parent f687dee commit fa2de6d
Show file tree
Hide file tree
Showing 10 changed files with 505 additions and 1 deletion.
3 changes: 2 additions & 1 deletion cns/configuration/cns_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
"MSISettings": {
"ResourceID": ""
},
"PopulateHomeAzCacheRetryIntervalSecs": 15
"PopulateHomeAzCacheRetryIntervalSecs": 15,
"MellanoxMonitorIntervalSecs": 30
}
1 change: 1 addition & 0 deletions cns/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type CNSConfig struct {
EnableCNIConflistGeneration bool
CNIConflistFilepath string
PopulateHomeAzCacheRetryIntervalSecs int
MellanoxMonitorIntervalSecs int
}

type TelemetrySettings struct {
Expand Down
11 changes: 11 additions & 0 deletions cns/service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,17 @@ func main() {
return
}

// We are only setting the PriorityVLANTag in 'cns.Direct' mode, because it neatly maps today, to 'isUsingMultitenancy'
// In the future, we would want to have a better CNS flag, to explicitly say, this CNS is using multitenancy
if config.ChannelMode == cns.Direct {
// Set Mellanox adapter's PriorityVLANTag value to 3 if adapter exists
// reg key value for PriorityVLANTag = 3 --> Packet priority and VLAN enabled
// for more details goto https://docs.nvidia.com/networking/display/winof2v230/Configuring+the+Driver+Registry+Keys#ConfiguringtheDriverRegistryKeys-GeneralRegistryKeysGeneralRegistryKeys
if platform.HasMellanoxAdapter() {
go platform.MonitorAndSetMellanoxRegKeyPriorityVLANTag(rootCtx, cnsconfig.MellanoxMonitorIntervalSecs)
}
}

// Initialze state in if CNS is running in CRD mode
// State must be initialized before we start HTTPRestService
if config.ChannelMode == cns.CRD {
Expand Down
11 changes: 11 additions & 0 deletions platform/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
REPO_ROOT = $(shell git rev-parse --show-toplevel)
TOOLS_BIN_DIR = $(REPO_ROOT)/build/tools/bin
MOCKGEN = $(TOOLS_BIN_DIR)/mockgen

.PHONY: generate

generate: $(MOCKGEN) ## Generate mock clients
$(MOCKGEN) -source=$(REPO_ROOT)/platform/windows/adapter/network_adapter.go -package=mocks NetworkAdapter > windows/adapter/mocks/networkadapter_generated.go

$(MOCKGEN):
@make -C $(REPO_ROOT) $(MOCKGEN)
8 changes: 8 additions & 0 deletions platform/os_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,11 @@ func PrintDependencyPackageDetails() {
func ReplaceFile(source, destination string) error {
return os.Rename(source, destination)
}

// Mellanox adapter not applicable for linux
func HasMellanoxAdapter() bool {
return false
}

// Not needed for Linux
func MonitorAndSetMellanoxRegKeyPriorityVLANTag(_ context.Context, _ int) {}
73 changes: 73 additions & 0 deletions platform/os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package platform

import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
Expand All @@ -13,6 +14,8 @@ import (
"time"

"github.com/Azure/azure-container-networking/log"
"github.com/Azure/azure-container-networking/platform/windows/adapter"
"github.com/Azure/azure-container-networking/platform/windows/adapter/mellanox"
"golang.org/x/sys/windows"
)

Expand Down Expand Up @@ -65,6 +68,14 @@ const (

// Command to restart HNS service
RestartHnsServiceCommand = "Restart-Service -Name hns"

// Interval between successive checks for mellanox adapter's PriorityVLANTag value
defaultMellanoxMonitorInterval = 30 * time.Second

// Value for reg key: PriorityVLANTag for adapter
// reg key value for PriorityVLANTag = 3 --> Packet priority and VLAN enabled
// for more details goto https://learn.microsoft.com/en-us/windows-hardware/drivers/network/standardized-inf-keywords-for-ndis-qos
desiredVLANTagForMellanox = 3
)

// Flag to check if sdnRemoteArpMacAddress registry key is set
Expand Down Expand Up @@ -189,6 +200,68 @@ func SetSdnRemoteArpMacAddress() error {
return nil
}

func HasMellanoxAdapter() bool {
m := &mellanox.Mellanox{}
return hasNetworkAdapter(m)
}

func hasNetworkAdapter(na adapter.NetworkAdapter) bool {
adapterName, err := na.GetAdapterName()
if err != nil {
log.Errorf("Error while getting network adapter name: %v", err)
return false
}
log.Printf("Name of the network adapter : %v", adapterName)
return true
}

// Regularly monitors the Mellanox PriorityVLANGTag registry value and sets it to desired value if needed
func MonitorAndSetMellanoxRegKeyPriorityVLANTag(ctx context.Context, intervalSecs int) {
m := &mellanox.Mellanox{}
interval := defaultMellanoxMonitorInterval
if intervalSecs > 0 {
interval = time.Duration(intervalSecs) * time.Second
}
err := updatePriorityVLANTagIfRequired(m, desiredVLANTagForMellanox)
if err != nil {
log.Errorf("Error while monitoring mellanox, continuing: %v", err)
}
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
log.Printf("context cancelled, stopping Mellanox Monitoring: %v", ctx.Err())
return
case <-ticker.C:
err := updatePriorityVLANTagIfRequired(m, desiredVLANTagForMellanox)
if err != nil {
log.Errorf("Error while monitoring mellanox, continuing: %v", err)
}
}
}
}

// Updates the priority VLAN Tag of mellanox adapter if not already set to the desired value
func updatePriorityVLANTagIfRequired(na adapter.NetworkAdapter, desiredValue int) error {
currentVal, err := na.GetPriorityVLANTag()
if err != nil {
return fmt.Errorf("error while getting Priority VLAN Tag value: %w", err)
}

if currentVal == desiredValue {
log.Printf("Adapter's PriorityVLANTag is already set to %v, skipping reset", desiredValue)
return nil
}

err = na.SetPriorityVLANTag(desiredValue)
if err != nil {
return fmt.Errorf("error while setting Priority VLAN Tag value: %w", err)
}

return nil
}

func GetOSDetails() (map[string]string, error) {
return nil, nil
}
Expand Down
83 changes: 83 additions & 0 deletions platform/os_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package platform

import (
"errors"
"testing"

"github.com/Azure/azure-container-networking/platform/windows/adapter/mocks"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)

var errTestFailure = errors.New("test failure")

// Test if hasNetworkAdapter returns false on actual error or empty adapter name(an error)
func TestHasNetworkAdapterReturnsError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockNetworkAdapter := mocks.NewMockNetworkAdapter(ctrl)
mockNetworkAdapter.EXPECT().GetAdapterName().Return("", errTestFailure)

result := hasNetworkAdapter(mockNetworkAdapter)
assert.False(t, result)
}

// Test if hasNetworkAdapter returns false on actual error or empty adapter name(an error)
func TestHasNetworkAdapterAdapterReturnsEmptyAdapterName(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockNetworkAdapter := mocks.NewMockNetworkAdapter(ctrl)
mockNetworkAdapter.EXPECT().GetAdapterName().Return("Ethernet 3", nil)

result := hasNetworkAdapter(mockNetworkAdapter)
assert.True(t, result)
}

// Test if updatePriorityVLANTagIfRequired returns error on getting error on calling getpriorityvlantag
func TestUpdatePriorityVLANTagIfRequiredReturnsError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockNetworkAdapter := mocks.NewMockNetworkAdapter(ctrl)
mockNetworkAdapter.EXPECT().GetPriorityVLANTag().Return(0, errTestFailure)
result := updatePriorityVLANTagIfRequired(mockNetworkAdapter, 3)
assert.EqualError(t, result, "error while getting Priority VLAN Tag value: test failure")
}

// Test if updatePriorityVLANTagIfRequired returns nil if currentval == desiredvalue (SetPriorityVLANTag not being called)
func TestUpdatePriorityVLANTagIfRequiredIfCurrentValEqualDesiredValue(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockNetworkAdapter := mocks.NewMockNetworkAdapter(ctrl)
mockNetworkAdapter.EXPECT().GetPriorityVLANTag().Return(4, nil)
result := updatePriorityVLANTagIfRequired(mockNetworkAdapter, 4)
assert.NoError(t, result)
}

// Test if updatePriorityVLANTagIfRequired returns nil if SetPriorityVLANTag being called to set value
func TestUpdatePriorityVLANTagIfRequiredIfCurrentValNotEqualDesiredValAndSetReturnsNoError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockNetworkAdapter := mocks.NewMockNetworkAdapter(ctrl)
mockNetworkAdapter.EXPECT().GetPriorityVLANTag().Return(1, nil)
mockNetworkAdapter.EXPECT().SetPriorityVLANTag(2).Return(nil)
result := updatePriorityVLANTagIfRequired(mockNetworkAdapter, 2)
assert.NoError(t, result)
}

// Test if updatePriorityVLANTagIfRequired returns error if SetPriorityVLANTag throwing error

func TestUpdatePriorityVLANTagIfRequiredIfCurrentValNotEqualDesiredValAndSetReturnsError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockNetworkAdapter := mocks.NewMockNetworkAdapter(ctrl)
mockNetworkAdapter.EXPECT().GetPriorityVLANTag().Return(1, nil)
mockNetworkAdapter.EXPECT().SetPriorityVLANTag(5).Return(errTestFailure)
result := updatePriorityVLANTagIfRequired(mockNetworkAdapter, 5)
assert.EqualError(t, result, "error while setting Priority VLAN Tag value: test failure")
}
Loading

0 comments on commit fa2de6d

Please sign in to comment.