Skip to content

Commit 01bbbe6

Browse files
authored
Use PortMappingPolicySetting (#689)
In order to support VIPs for container Port Mappings, we should use PortMappingPolicySetting type from HNSv2 instead of the old NatPolicy from HNSv1.
1 parent 61fb84d commit 01bbbe6

File tree

2 files changed

+75
-46
lines changed

2 files changed

+75
-46
lines changed

cni/network/network_windows.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/Azure/azure-container-networking/network"
1616
"github.com/Azure/azure-container-networking/network/policy"
1717
"github.com/Microsoft/hcsshim"
18+
hnsv2 "github.com/Microsoft/hcsshim/hcn"
1819
"golang.org/x/sys/windows/registry"
1920

2021
cniSkel "github.com/containernetworking/cni/pkg/skel"
@@ -254,17 +255,32 @@ func getEndpointDNSSettings(nwCfg *cni.NetworkConfig, result *cniTypesCurr.Resul
254255
func getPoliciesFromRuntimeCfg(nwCfg *cni.NetworkConfig) []policy.Policy {
255256
log.Printf("[net] RuntimeConfigs: %+v", nwCfg.RuntimeConfig)
256257
var policies []policy.Policy
258+
var protocol uint32
257259
for _, mapping := range nwCfg.RuntimeConfig.PortMappings {
258-
rawPolicy, _ := json.Marshal(&hcsshim.NatPolicy{
259-
Type: "NAT",
260+
261+
cfgProto := strings.ToUpper(strings.TrimSpace(mapping.Protocol))
262+
switch cfgProto {
263+
case "TCP":
264+
protocol = policy.ProtocolTcp
265+
case "UDP":
266+
protocol = policy.ProtocolUdp
267+
}
268+
269+
rawPolicy, _ := json.Marshal(&hnsv2.PortMappingPolicySetting{
260270
ExternalPort: uint16(mapping.HostPort),
261271
InternalPort: uint16(mapping.ContainerPort),
262-
Protocol: mapping.Protocol,
272+
VIP: mapping.HostIp,
273+
Protocol: protocol,
274+
})
275+
276+
hnsv2Policy, _ := json.Marshal(&hnsv2.EndpointPolicy{
277+
Type: hnsv2.PortMapping,
278+
Settings: rawPolicy,
263279
})
264280

265281
policy := policy.Policy{
266282
Type: policy.EndpointPolicy,
267-
Data: rawPolicy,
283+
Data: hnsv2Policy,
268284
}
269285
log.Printf("[net] Creating port mapping policy: %+v", policy)
270286

network/policy/policy_windows.go

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@ package policy
33
import (
44
"encoding/json"
55
"fmt"
6-
"strings"
76

87
"github.com/Azure/azure-container-networking/log"
98
"github.com/Microsoft/hcsshim"
109
"github.com/Microsoft/hcsshim/hcn"
1110
)
1211

1312
const (
14-
// protocolTcp indicates tcp protocol id for portmapping
15-
protocolTcp = 6
13+
// ProtocolTcp indicates tcp protocol id for portmapping
14+
ProtocolTcp = 6
1615

17-
// protocolUdp indicates udp protocol id for portmapping
18-
protocolUdp = 17
16+
// ProtocolUdp indicates udp protocol id for portmapping
17+
ProtocolUdp = 17
1918

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

30-
type KVPairPortMapping struct {
31-
Type CNIPolicyType `json:"Type"`
32-
ExternalPort uint16 `json:"ExternalPort"`
33-
InternalPort uint16 `json:"InternalPort"`
34-
Protocol string `json:"Protocol"`
35-
}
36-
3729
type KVPairOutBoundNAT struct {
3830
Type CNIPolicyType `json:"Type"`
3931
ExceptionList json.RawMessage `json:"ExceptionList"`
@@ -64,6 +56,13 @@ func SerializePolicies(policyType CNIPolicyType, policies []Policy, epInfoData m
6456
jsonPolicies = append(jsonPolicies, serializedOutboundNatPolicy)
6557
}
6658
}
59+
} else if isPolicyTypeNAT := IsPolicyTypeNAT(policy); isPolicyTypeNAT {
60+
// NATPolicy comes as a HNSv2 type, it needs to be converted to HNSv1
61+
if serializedNatPolicy, err := SerializeNATPolicy(policy); err != nil {
62+
log.Printf("Failed to serialize NatPolicy")
63+
} else {
64+
jsonPolicies = append(jsonPolicies, serializedNatPolicy)
65+
}
6766
} else {
6867
jsonPolicies = append(jsonPolicies, policy.Data)
6968
}
@@ -117,6 +116,45 @@ func IsPolicyTypeOutBoundNAT(policy Policy) bool {
117116
return false
118117
}
119118

119+
// IsPolicyTypeNAT returns true if the policy type is NAT
120+
func IsPolicyTypeNAT(policy Policy) bool {
121+
if policy.Type == EndpointPolicy {
122+
var endpointPolicy hcn.EndpointPolicy
123+
if err := json.Unmarshal(policy.Data, &endpointPolicy); err != nil {
124+
return false
125+
}
126+
if endpointPolicy.Type == hcn.PortMapping {
127+
return true
128+
}
129+
}
130+
return false
131+
}
132+
133+
func SerializeNATPolicy(policy Policy) (json.RawMessage, error) {
134+
var (
135+
endpointPolicy hcn.EndpointPolicy
136+
portMappingPolicy hcn.PortMappingPolicySetting
137+
)
138+
if err := json.Unmarshal(policy.Data, &endpointPolicy); err != nil {
139+
return nil, err
140+
}
141+
if err := json.Unmarshal(endpointPolicy.Settings, &portMappingPolicy); err != nil {
142+
return nil, err
143+
}
144+
natPolicy := hcsshim.NatPolicy{
145+
Type: "NAT",
146+
InternalPort: portMappingPolicy.InternalPort,
147+
ExternalPort: portMappingPolicy.ExternalPort,
148+
}
149+
switch portMappingPolicy.Protocol {
150+
case ProtocolTcp:
151+
natPolicy.Protocol = "TCP"
152+
case ProtocolUdp:
153+
natPolicy.Protocol = "UDP"
154+
}
155+
return json.Marshal(natPolicy)
156+
}
157+
120158
// SerializeOutBoundNATPolicy formulates OutBoundNAT policy and returns serialized json
121159
func SerializeOutBoundNATPolicy(policy Policy, epInfoData map[string]interface{}) (json.RawMessage, error) {
122160
outBoundNatPolicy := hcsshim.OutboundNatPolicy{}
@@ -169,9 +207,9 @@ func GetPolicyType(policy Policy) CNIPolicyType {
169207
}
170208

171209
// Check if the type if Port mapping / NAT
172-
var dataPortMapping KVPairPortMapping
210+
var dataPortMapping hcn.EndpointPolicy
173211
if err := json.Unmarshal(policy.Data, &dataPortMapping); err == nil {
174-
if dataPortMapping.Type == PortMappingPolicy {
212+
if dataPortMapping.Type == hcn.PortMapping {
175213
return PortMappingPolicy
176214
}
177215
}
@@ -313,37 +351,12 @@ func GetHcnRoutePolicy(policy Policy) (hcn.EndpointPolicy, error) {
313351

314352
// GetHcnPortMappingPolicy returns port mapping policy.
315353
func GetHcnPortMappingPolicy(policy Policy) (hcn.EndpointPolicy, error) {
316-
portMappingPolicy := hcn.EndpointPolicy{
317-
Type: hcn.PortMapping,
318-
}
319-
320-
var dataPortMapping KVPairPortMapping
321-
if err := json.Unmarshal(policy.Data, &dataPortMapping); err != nil {
354+
var portMappingPolicy hcn.EndpointPolicy
355+
if err := json.Unmarshal(policy.Data, &portMappingPolicy); err != nil {
322356
return portMappingPolicy,
323357
fmt.Errorf("Invalid policy: %+v. Expecting PortMapping policy. Error: %v", policy, err)
324358
}
325-
326-
portMappingPolicySetting := &hcn.PortMappingPolicySetting{
327-
InternalPort: dataPortMapping.InternalPort,
328-
ExternalPort: dataPortMapping.ExternalPort,
329-
}
330-
331-
protocol := strings.ToUpper(strings.TrimSpace(dataPortMapping.Protocol))
332-
switch protocol {
333-
case "TCP":
334-
portMappingPolicySetting.Protocol = protocolTcp
335-
case "UDP":
336-
portMappingPolicySetting.Protocol = protocolUdp
337-
default:
338-
return portMappingPolicy, fmt.Errorf("Invalid protocol: %s for port mapping", protocol)
339-
}
340-
341-
portMappingPolicySettingBytes, err := json.Marshal(portMappingPolicySetting)
342-
if err != nil {
343-
return portMappingPolicy, err
344-
}
345-
346-
portMappingPolicy.Settings = portMappingPolicySettingBytes
359+
portMappingPolicy.Type = hcn.PortMapping
347360

348361
return portMappingPolicy, nil
349362
}

0 commit comments

Comments
 (0)