Skip to content
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
26 changes: 21 additions & 5 deletions cni/network/network_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/Azure/azure-container-networking/network"
"github.com/Azure/azure-container-networking/network/policy"
Copy link
Contributor

Choose a reason for hiding this comment

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

Also share what all testing has been performed? Just containerd or docker has been tested to make HnsV1 is working as earlier too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Please confirm?

Copy link
Contributor

Choose a reason for hiding this comment

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

Specifically the portmapping scenario

"github.com/Microsoft/hcsshim"
hnsv2 "github.com/Microsoft/hcsshim/hcn"
"golang.org/x/sys/windows/registry"

cniSkel "github.com/containernetworking/cni/pkg/skel"
Expand Down Expand Up @@ -239,17 +240,32 @@ func getEndpointDNSSettings(nwCfg *cni.NetworkConfig, result *cniTypesCurr.Resul
func getPoliciesFromRuntimeCfg(nwCfg *cni.NetworkConfig) []policy.Policy {
log.Printf("[net] RuntimeConfigs: %+v", nwCfg.RuntimeConfig)
var policies []policy.Policy
var protocol uint32
for _, mapping := range nwCfg.RuntimeConfig.PortMappings {
rawPolicy, _ := json.Marshal(&hcsshim.NatPolicy{
Type: "NAT",

cfgProto := strings.ToUpper(strings.TrimSpace(mapping.Protocol))
switch cfgProto {
case "TCP":
protocol = policy.ProtocolTcp
case "UDP":
protocol = policy.ProtocolUdp
}

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

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

policy := policy.Policy{
Type: policy.EndpointPolicy,
Data: rawPolicy,
Data: hnsv2Policy,
}
log.Printf("[net] Creating port mapping policy: %+v", policy)

Expand All @@ -268,7 +284,7 @@ func addIPV6EndpointPolicy(nwInfo network.NetworkInfo) (policy.Policy, error) {
return eppolicy, fmt.Errorf("network state doesn't have ipv6 subnet")
}

// Everything should be snat'd except podcidr
// Everything should be snat'd except podcidr
exceptionList := []string{nwInfo.Subnets[1].Prefix.String()}
rawPolicy, _ := json.Marshal(&hcsshim.OutboundNatPolicy{
Policy: hcsshim.Policy{Type: hcsshim.OutboundNat},
Expand Down
97 changes: 55 additions & 42 deletions network/policy/policy_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ package policy
import (
"encoding/json"
"fmt"
"strings"

"github.com/Azure/azure-container-networking/log"
"github.com/Microsoft/hcsshim"
"github.com/Microsoft/hcsshim/hcn"
)

const (
// protocolTcp indicates tcp protocol id for portmapping
protocolTcp = 6
// ProtocolTcp indicates tcp protocol id for portmapping
ProtocolTcp = 6

// protocolUdp indicates udp protocol id for portmapping
protocolUdp = 17
// ProtocolUdp indicates udp protocol id for portmapping
ProtocolUdp = 17

// CnetAddressSpace indicates constant for the key string
CnetAddressSpace = "cnetAddressSpace"
Expand All @@ -27,13 +26,6 @@ type KVPairRoutePolicy struct {
NeedEncap json.RawMessage `json:"NeedEncap"`
}

type KVPairPortMapping struct {
Type CNIPolicyType `json:"Type"`
ExternalPort uint16 `json:"ExternalPort"`
InternalPort uint16 `json:"InternalPort"`
Protocol string `json:"Protocol"`
}

type KVPairOutBoundNAT struct {
Type CNIPolicyType `json:"Type"`
ExceptionList json.RawMessage `json:"ExceptionList"`
Expand Down Expand Up @@ -64,6 +56,13 @@ func SerializePolicies(policyType CNIPolicyType, policies []Policy, epInfoData m
jsonPolicies = append(jsonPolicies, serializedOutboundNatPolicy)
}
}
} else if isPolicyTypeNAT := IsPolicyTypeNAT(policy); isPolicyTypeNAT {
// NATPolicy comes as a HNSv2 type, it needs to be converted to HNSv1
if serializedNatPolicy, err := SerializeNATPolicy(policy); err != nil {
log.Printf("Failed to serialize NatPolicy")
} else {
jsonPolicies = append(jsonPolicies, serializedNatPolicy)
}
} else {
jsonPolicies = append(jsonPolicies, policy.Data)
}
Expand Down Expand Up @@ -117,6 +116,45 @@ func IsPolicyTypeOutBoundNAT(policy Policy) bool {
return false
}

// IsPolicyTypeNAT returns true if the policy type is NAT
func IsPolicyTypeNAT(policy Policy) bool {
if policy.Type == EndpointPolicy {
var endpointPolicy hcn.EndpointPolicy
if err := json.Unmarshal(policy.Data, &endpointPolicy); err != nil {
return false
}
if endpointPolicy.Type == hcn.PortMapping {
return true
}
}
return false
}

func SerializeNATPolicy(policy Policy) (json.RawMessage, error) {
var (
endpointPolicy hcn.EndpointPolicy
portMappingPolicy hcn.PortMappingPolicySetting
)
if err := json.Unmarshal(policy.Data, &endpointPolicy); err != nil {
return nil, err
}
if err := json.Unmarshal(endpointPolicy.Settings, &portMappingPolicy); err != nil {
return nil, err
}
natPolicy := hcsshim.NatPolicy{
Type: "NAT",
Copy link
Contributor

Choose a reason for hiding this comment

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

please use constant here.

Copy link
Contributor

Choose a reason for hiding this comment

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

?

InternalPort: portMappingPolicy.InternalPort,
ExternalPort: portMappingPolicy.ExternalPort,
}
switch portMappingPolicy.Protocol {
case ProtocolTcp:
natPolicy.Protocol = "TCP"
case ProtocolUdp:
natPolicy.Protocol = "UDP"
}
return json.Marshal(natPolicy)
}

// SerializeOutBoundNATPolicy formulates OutBoundNAT policy and returns serialized json
func SerializeOutBoundNATPolicy(policy Policy, epInfoData map[string]interface{}) (json.RawMessage, error) {
outBoundNatPolicy := hcsshim.OutboundNatPolicy{}
Expand Down Expand Up @@ -169,9 +207,9 @@ func GetPolicyType(policy Policy) CNIPolicyType {
}

// Check if the type if Port mapping / NAT
var dataPortMapping KVPairPortMapping
var dataPortMapping hcn.EndpointPolicy
if err := json.Unmarshal(policy.Data, &dataPortMapping); err == nil {
if dataPortMapping.Type == PortMappingPolicy {
if dataPortMapping.Type == hcn.PortMapping {
return PortMappingPolicy
}
}
Expand Down Expand Up @@ -308,37 +346,12 @@ func GetHcnRoutePolicy(policy Policy) (hcn.EndpointPolicy, error) {

// GetHcnPortMappingPolicy returns port mapping policy.
func GetHcnPortMappingPolicy(policy Policy) (hcn.EndpointPolicy, error) {
portMappingPolicy := hcn.EndpointPolicy{
Type: hcn.PortMapping,
}

var dataPortMapping KVPairPortMapping
if err := json.Unmarshal(policy.Data, &dataPortMapping); err != nil {
var portMappingPolicy hcn.EndpointPolicy
if err := json.Unmarshal(policy.Data, &portMappingPolicy); err != nil {
return portMappingPolicy,
fmt.Errorf("Invalid policy: %+v. Expecting PortMapping policy. Error: %v", policy, err)
}

portMappingPolicySetting := &hcn.PortMappingPolicySetting{
InternalPort: dataPortMapping.InternalPort,
ExternalPort: dataPortMapping.ExternalPort,
}

protocol := strings.ToUpper(strings.TrimSpace(dataPortMapping.Protocol))
switch protocol {
case "TCP":
portMappingPolicySetting.Protocol = protocolTcp
case "UDP":
portMappingPolicySetting.Protocol = protocolUdp
default:
return portMappingPolicy, fmt.Errorf("Invalid protocol: %s for port mapping", protocol)
}

portMappingPolicySettingBytes, err := json.Marshal(portMappingPolicySetting)
if err != nil {
return portMappingPolicy, err
}

portMappingPolicy.Settings = portMappingPolicySettingBytes
portMappingPolicy.Type = hcn.PortMapping

return portMappingPolicy, nil
}
Expand Down