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

[cni]: dualstack overlay hostIP issue hotfix #2290

Merged
merged 16 commits into from
Oct 27, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ stages:
dns: true
portforward: true
service: true
hostport: true
hybridWin: true

- job: failedE2ELogs
Expand Down
7 changes: 6 additions & 1 deletion cni/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,12 @@ func (plugin *NetPlugin) createEndpointInternal(opt *createEndpointInternalOpt)
}

isIPv6Enabled := opt.resultV6 != nil
epPolicies := getPoliciesFromRuntimeCfg(opt.nwCfg, isIPv6Enabled)
epPolicies, err := getPoliciesFromRuntimeCfg(opt.nwCfg, isIPv6Enabled)
if err != nil {
logger.Error("failed to get policies from runtime configurations", zap.Error(err))
return epInfo, plugin.Errorf(err.Error())
}

epInfo.Policies = append(epInfo.Policies, epPolicies...)

// Populate addresses.
Expand Down
4 changes: 2 additions & 2 deletions cni/network/network_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ func getEndpointPolicies(PolicyArgs) ([]policy.Policy, error) {

// getPoliciesFromRuntimeCfg returns network policies from network config.
// getPoliciesFromRuntimeCfg is a dummy function for Linux platform.
func getPoliciesFromRuntimeCfg(_ *cni.NetworkConfig, _ bool) []policy.Policy {
return nil
func getPoliciesFromRuntimeCfg(_ *cni.NetworkConfig, _ bool) ([]policy.Policy, error) {
return nil, nil
}

func addIPV6EndpointPolicy(nwInfo network.NetworkInfo) (policy.Policy, error) {
Expand Down
73 changes: 36 additions & 37 deletions cni/network/network_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,8 @@ func getEndpointDNSSettings(nwCfg *cni.NetworkConfig, result *cniTypesCurr.Resul
}

// getPoliciesFromRuntimeCfg returns network policies from network config.
func getPoliciesFromRuntimeCfg(nwCfg *cni.NetworkConfig, isIPv6Enabled bool) []policy.Policy {
logger.Info("Runtime Info",
zap.Any("config", nwCfg.RuntimeConfig))
func getPoliciesFromRuntimeCfg(nwCfg *cni.NetworkConfig, isIPv6Enabled bool) ([]policy.Policy, error) {
logger.Info("Runtime Info", zap.Any("config", nwCfg.RuntimeConfig))
var policies []policy.Policy
var protocol uint32

Expand All @@ -266,57 +265,57 @@ func getPoliciesFromRuntimeCfg(nwCfg *cni.NetworkConfig, isIPv6Enabled bool) []p

// To support hostport policy mapping
// uint32 NatFlagsLocalRoutedVip = 1
rawPolicy, _ := json.Marshal(&hnsv2.PortMappingPolicySetting{
// To support hostport policy mapping for ipv6 in dualstack overlay mode
// uint32 NatFlagsIPv6 = 2

flag := hnsv2.NatFlagsLocalRoutedVip
if mapping.HostIp != "" {
hostIP, err := netip.ParseAddr(mapping.HostIp)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse hostIP %v", hostIP)
}

if hostIP.Is6() && isIPv6Enabled {
flag = hnsv2.NatFlagsIPv6
}

if hostIP.Is6() && !isIPv6Enabled {
logger.Info("Do not use ipv6 hostIP to create windows pod on ipv4 cluster")
}
}

rawPolicy, err := json.Marshal(&hnsv2.PortMappingPolicySetting{
ExternalPort: uint16(mapping.HostPort),
InternalPort: uint16(mapping.ContainerPort),
VIP: mapping.HostIp,
Protocol: protocol,
Flags: hnsv2.NatFlagsLocalRoutedVip,
Flags: flag,
})

hnsv2Policy, _ := json.Marshal(&hnsv2.EndpointPolicy{
if err != nil {
return nil, errors.Wrap(err, "failed to marshal HNS portMappingPolicySetting")
}

hnsv2Policy, err := json.Marshal(&hnsv2.EndpointPolicy{
Type: hnsv2.PortMapping,
Settings: rawPolicy,
})

policyv4 := policy.Policy{
if err != nil {
return nil, errors.Wrap(err, "failed to marshal HNS endpointPolicy")
}

hnsPolicy := policy.Policy{
Type: policy.EndpointPolicy,
Data: hnsv2Policy,
}

logger.Info("Creating port mapping policyv4",
zap.Any("policy", policyv4))
policies = append(policies, policyv4)

// add port mapping policy for v6 if we have IPV6 enabled
if isIPv6Enabled {
// To support hostport policy mapping for ipv6 in dualstack overlay mode
// uint32 NatFlagsIPv6 = 2
rawPolicyv6, _ := json.Marshal(&hnsv2.PortMappingPolicySetting{ // nolint
ExternalPort: uint16(mapping.HostPort),
InternalPort: uint16(mapping.ContainerPort),
VIP: mapping.HostIp,
Protocol: protocol,
Flags: hnsv2.NatFlagsIPv6,
})

hnsv2Policyv6, _ := json.Marshal(&hnsv2.EndpointPolicy{ // nolint
Type: hnsv2.PortMapping,
Settings: rawPolicyv6,
})

policyv6 := policy.Policy{
Type: policy.EndpointPolicy,
Data: hnsv2Policyv6,
}
logger.Info("Creating port mapping policy", zap.Any("policy", hnsPolicy))

logger.Info("Creating port mapping policyv6",
zap.Any("policy", policyv6))
policies = append(policies, policyv6)
}
policies = append(policies, hnsPolicy)
}

return policies
return policies, nil
}

func getEndpointPolicies(args PolicyArgs) ([]policy.Policy, error) {
Expand Down
27 changes: 23 additions & 4 deletions cni/network/network_windows_test.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add more test cases involving ipv6 hostip as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added an ipv6 UT test

Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,9 @@ func TestSetEndpointOptions(t *testing.T) {

func TestSetPoliciesFromNwCfg(t *testing.T) {
tests := []struct {
name string
nwCfg cni.NetworkConfig
name string
nwCfg cni.NetworkConfig
isIPv6Enabled bool
}{
{
name: "Runtime network polices",
Expand All @@ -234,6 +235,7 @@ func TestSetPoliciesFromNwCfg(t *testing.T) {
},
},
},
isIPv6Enabled: false,
},
{
name: "Runtime hostPort mapping polices",
Expand All @@ -248,13 +250,30 @@ func TestSetPoliciesFromNwCfg(t *testing.T) {
},
},
},
isIPv6Enabled: false,
},
{
name: "Runtime hostPort mapping polices with ipv6 hostIP",
nwCfg: cni.NetworkConfig{
RuntimeConfig: cni.RuntimeConfig{
PortMappings: []cni.PortMapping{
{
Protocol: "tcp",
HostPort: 44000,
ContainerPort: 80,
HostIp: "2001:2002:2003::1",
},
},
},
},
isIPv6Enabled: true,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
isIPv6Enabled := false
policies := getPoliciesFromRuntimeCfg(&tt.nwCfg, isIPv6Enabled)
policies, err := getPoliciesFromRuntimeCfg(&tt.nwCfg, tt.isIPv6Enabled)
require.NoError(t, err)
require.Condition(t, assert.Comparison(func() bool {
return len(policies) > 0 && policies[0].Type == policy.EndpointPolicy
}))
Expand Down