Skip to content
Open
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
3 changes: 3 additions & 0 deletions cni/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,9 @@ func (plugin *NetPlugin) createEpInfo(opt *createEpInfoOpt) (*network.EndpointIn
AllowInboundFromHostToNC: opt.ifInfo.AllowHostToNCCommunication,
AllowInboundFromNCToHost: opt.ifInfo.AllowNCToHostCommunication,
}
if opt.ifInfo.NCResponse != nil {
endpointInfo.PrimaryInterfaceIdentifier = opt.ifInfo.NCResponse.PrimaryInterfaceIdentifier
}

if err = addSubnetToEndpointInfo(*opt.ifInfo, &endpointInfo); err != nil {
logger.Info("Failed to add subnets to endpointInfo", zap.Error(err))
Expand Down
3 changes: 2 additions & 1 deletion cni/network/network_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,8 @@
// should match with GetTestCNSResponse3
{
epInfo: &network.EndpointInfo{
ContainerID: "test-container",
PrimaryInterfaceIdentifier: "20.240.0.4/24",

Check failure on line 282 in cni/network/network_linux_test.go

View workflow job for this annotation

GitHub Actions / Lint (ubuntu-latest)

string `20.240.0.4/24` has 3 occurrences, make it a constant (goconst)
ContainerID: "test-container",
Data: map[string]interface{}{
"VlanID": 1, // Vlan ID used here
"localIP": "168.254.0.4/17",
Expand Down
6 changes: 4 additions & 2 deletions cni/network/network_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,8 @@
// should match with GetTestCNSResponse1
{
epInfo: &network.EndpointInfo{
ContainerID: "test-container",
PrimaryInterfaceIdentifier: "20.240.0.4/24",

Check failure on line 1032 in cni/network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

string `20.240.0.4/24` has 3 occurrences, make it a constant (goconst)
ContainerID: "test-container",
Data: map[string]interface{}{
"cnetAddressSpace": []string(nil),
},
Expand Down Expand Up @@ -1109,7 +1110,8 @@
// should match with GetTestCNSResponse2
{
epInfo: &network.EndpointInfo{
ContainerID: "test-container",
PrimaryInterfaceIdentifier: "10.240.0.4/24",

Check failure on line 1113 in cni/network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

string `10.240.0.4/24` has 3 occurrences, make it a constant (goconst)
ContainerID: "test-container",
Data: map[string]interface{}{
"cnetAddressSpace": []string(nil),
},
Expand Down
2 changes: 1 addition & 1 deletion cns/hnsclient/hnsclient_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func configureHostNCApipaNetwork(localIPConfiguration cns.IPConfiguration) (*hcn
Flags: hcn.EnableNonPersistent, // Set up the network in non-persistent mode
}

if netAdapterNamePolicy, err := policy.GetHcnNetAdapterPolicy(hostNCLoopbackAdapterName); err == nil {
if netAdapterNamePolicy, err := policy.GetHcnNetAdapterNamePolicy(hostNCLoopbackAdapterName); err == nil {
network.Policies = append(network.Policies, netAdapterNamePolicy)
} else {
return nil, fmt.Errorf("Failed to serialize network adapter policy. Error: %v", err)
Expand Down
3 changes: 2 additions & 1 deletion network/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,13 @@ type EndpointInfo struct {
Mode string
Subnets []SubnetInfo
BridgeName string
NetNs string // used in windows
NetNs string // used in windows
Options map[string]interface{} // populated only for InfraNIC; nil for non-infra NICs
DisableHairpinOnHostInterface bool
IsIPv6Enabled bool
HostSubnetPrefix string // can be used later to add an external interface
PnPID string
PrimaryInterfaceIdentifier string
}

// RouteInfo contains information about an IP route.
Expand Down
34 changes: 33 additions & 1 deletion network/network_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import (
"encoding/json"
"fmt"
"net"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -240,6 +241,7 @@
// per hns team, the hns calls fails if passed a vSwitch interface
// Pass adapter name here if it is not empty, this is cause if we don't tell HNS which adapter to use
// it will just pick one randomly, this is a problem for customers that have multiple adapters
isNetAdapterNamePolicyAdded := false
if nwInfo.AdapterName != "" || !strings.HasPrefix(extIf.Name, vEthernetAdapterPrefix) {
var adapterName string
if nwInfo.AdapterName != "" {
Expand All @@ -250,13 +252,43 @@

logger.Info("Adapter name used with HNS is", zap.String("adapterName", adapterName))

netAdapterNamePolicy, err := policy.GetHcnNetAdapterPolicy(adapterName)
netAdapterNamePolicy, err := policy.GetHcnNetAdapterNamePolicy(adapterName)
if err != nil {
logger.Error("Failed to serialize network adapter policy due to", zap.Error(err))
return nil, err
}

hcnNetwork.Policies = append(hcnNetwork.Policies, netAdapterNamePolicy)
isNetAdapterNamePolicyAdded = true
}

// Best effort to add IP policy in case adapter name is empty
// TODO estebanca improve logger messages with coordinates
if !isNetAdapterNamePolicyAdded {
primaryInterfaceIdentifier := nwInfo.PrimaryInterfaceIdentifier

if primaryInterfaceIdentifier != "" {

var providerAddress string
// Based on cns/NetworkContainerContract.go, PrimaryInterfaceIdentifier can be either an IP or a CIDR
if ip, _, err := net.ParseCIDR(primaryInterfaceIdentifier); err == nil {
providerAddress = ip.String()
} else if ip := net.ParseIP(primaryInterfaceIdentifier); ip != nil {
providerAddress = ip.String()
} else {
return nil, fmt.Errorf("PrimaryInterfaceIdentifier %q is not a valid IP or CIDR", primaryInterfaceIdentifier)

Check failure on line 279 in network/network_windows.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

do not define dynamic errors, use wrapped static errors instead: "fmt.Errorf(\"PrimaryInterfaceIdentifier %q is not a valid IP or CIDR\", primaryInterfaceIdentifier)" (err113)
}

adapterAddressPolicy, err := policy.GetHcnNetAdapterAddressPolicy(providerAddress)
if err != nil {
return nil, fmt.Errorf("Failed to serialize network adapter address policy: %w", err)

Check failure on line 284 in network/network_windows.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

ST1005: error strings should not be capitalized (staticcheck)
}

hcnNetwork.Policies = append(hcnNetwork.Policies, adapterAddressPolicy)
} else {
logger.Info("Unable to apply Adapter Address policy during network creation. Proceeding without it.")
}

}

// Set hcn subnet policy
Expand Down
55 changes: 55 additions & 0 deletions network/network_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"github.com/Azure/azure-container-networking/network/hnswrapper"
"github.com/Azure/azure-container-networking/platform"
"github.com/Microsoft/hcsshim/hcn"
"github.com/stretchr/testify/assert"
)

var (
Expand Down Expand Up @@ -560,6 +561,60 @@
}
}

func TestConfigureHCNNetworkUsesPrimaryInterfaceIdentifierFallback(t *testing.T) {
assert := assert.New(t)

Check failure on line 565 in network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

importShadow: shadow of imported from 'github.com/stretchr/testify/assert' package 'assert' (gocritic)

nm := &networkManager{
ExternalInterfaces: map[string]*externalInterface{},
}

extIf := externalInterface{
Name: "vEthernet (eth0)",
}

nwInfo := &EndpointInfo{
NetworkID: "d3e97a83-ba4c-45d5-ba88-dc56757ece28",
MasterIfName: "eth0",
NICType: cns.InfraNIC,
PrimaryInterfaceIdentifier: "10.240.0.4/24",
}

hostComputeNetwork, err := nm.configureHcnNetwork(nwInfo, &extIf)
assert.NoError(err)

Check failure on line 583 in network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

require-error: for error assertions use require (testifylint)
if !assert.NotNil(hostComputeNetwork) {
return
}
assert.Len(hostComputeNetwork.Policies, 1)
assert.Equal(hcn.ProviderAddress, hostComputeNetwork.Policies[0].Type)
assert.Contains(string(hostComputeNetwork.Policies[0].Settings), "10.240.0.4")
}

func TestConfigureHCNNetworkDoesNotUsePrimaryInterfaceIdentifierForEthernet(t *testing.T) {
assert := assert.New(t)

Check failure on line 593 in network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

importShadow: shadow of imported from 'github.com/stretchr/testify/assert' package 'assert' (gocritic)

nm := &networkManager{
ExternalInterfaces: map[string]*externalInterface{},
}

extIf := externalInterface{
Name: "Ethernet",
}

nwInfo := &EndpointInfo{
NetworkID: "d3e97a83-ba4c-45d5-ba88-dc56757ece28",
MasterIfName: "Ethernet",
NICType: cns.InfraNIC,
PrimaryInterfaceIdentifier: "10.240.0.4/24",
}

hostComputeNetwork, err := nm.configureHcnNetwork(nwInfo, &extIf)
assert.NoError(err)

Check failure on line 611 in network/network_windows_test.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

require-error: for error assertions use require (testifylint)
assert.NotNil(hostComputeNetwork)
assert.Len(hostComputeNetwork.Policies, 1)
assert.Equal(hcn.NetAdapterName, hostComputeNetwork.Policies[0].Type)
assert.NotEqual(hcn.ProviderAddress, hostComputeNetwork.Policies[0].Type)
}

// Test Configure HCN Network for Swiftv2 DelegatedNIC HostComputeNetwork fields
func TestConfigureHCNNetworkSwiftv2DelegatedNIC(t *testing.T) {
expectedSwiftv2NetworkMode := hcn.Transparent
Expand Down
29 changes: 27 additions & 2 deletions network/policy/policy_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@
return vlanSubnetPolicyBytes, nil
}

// GetHcnNetAdapterPolicy returns network adapter name policy.
func GetHcnNetAdapterPolicy(networkAdapterName string) (hcn.NetworkPolicy, error) {
// GetHcnNetAdapterNamePolicy returns network adapter name policy.
func GetHcnNetAdapterNamePolicy(networkAdapterName string) (hcn.NetworkPolicy, error) {
networkAdapterNamePolicy := hcn.NetworkPolicy{
Type: hcn.NetAdapterName,
}
Expand All @@ -318,6 +318,31 @@
return networkAdapterNamePolicy, nil
}

// TODO: estebanca: This type must be from hcsshim
type ProviderAddressNetworkPolicySetting struct {
ProviderAddress string `json:"ProviderAddress"`
}

func GetHcnNetAdapterAddressPolicy(networkAdapterAddress string) (hcn.NetworkPolicy, error) {
Comment thread
estebancams marked this conversation as resolved.

Check failure on line 327 in network/policy/policy_windows.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

File is not properly formatted (gofumpt)
networkAdapterAddressPolicy := hcn.NetworkPolicy{
Type: hcn.ProviderAddress,
}

netAdapterAddressPolicySetting := &ProviderAddressNetworkPolicySetting{
ProviderAddress: networkAdapterAddress,
}

netAdapterAddressPolicySettingBytes, err := json.Marshal(netAdapterAddressPolicySetting)
if err != nil {
return networkAdapterAddressPolicy, err

Check failure on line 338 in network/policy/policy_windows.go

View workflow job for this annotation

GitHub Actions / Lint (windows-latest)

error returned from external package is unwrapped: sig: func encoding/json.Marshal(v any) ([]byte, error) (wrapcheck)
}

networkAdapterAddressPolicy.Settings = netAdapterAddressPolicySettingBytes

return networkAdapterAddressPolicy, nil
}

// GetHcnOutBoundNATPolicy returns outBoundNAT policy.
func GetHcnOutBoundNATPolicy(policy Policy, epInfoData map[string]interface{}) (hcn.EndpointPolicy, error) {
outBoundNATPolicy := hcn.EndpointPolicy{
Expand Down
Loading