Skip to content

Commit 9bd54cf

Browse files
committed
added loopbackDSR support to all IPAMs
1 parent 1d00493 commit 9bd54cf

File tree

3 files changed

+72
-4
lines changed

3 files changed

+72
-4
lines changed

common/core/network.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,22 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
219219
// Apply the Network Policy for Endpoint
220220
epInfo.Policies = append(epInfo.Policies, networkInfo.Policies...)
221221

222-
// If LoopbackDSR is set, add to policies
222+
hnsIPAM := false
223+
// If LoopbackDSR is set and IP is already allocated via IPAM, add to policies before endpoint creation
223224
if cniConfig.OptionalFlags.LoopbackDSR {
224-
hcnLoopbackRoute, _ := network.GetLoopbackDSRPolicy(&epInfo.IPAddress)
225-
epInfo.Policies = append(epInfo.Policies, hcnLoopbackRoute)
225+
if epInfo.IPAddress != nil && len(epInfo.IPAddress) > 0 {
226+
hcnLoopbackRoute, err := network.GetLoopbackDSRPolicy(epInfo.IPAddress)
227+
if err != nil {
228+
logrus.Errorf("[cni-net] Failed to create loopbackDSR policy: %v, IPAddress: %v", err, epInfo.IPAddress)
229+
return err
230+
}
231+
logrus.Debugf("[cni-net] Created loopbackDSR policy for IP: %v", epInfo.IPAddress)
232+
epInfo.Policies = append(epInfo.Policies, hcnLoopbackRoute)
233+
} else {
234+
// IP will be assigned by HCN, add the loopbackDSR policy after endpoint creation
235+
hnsIPAM = true
236+
logrus.Debugf("[cni-net] IP not yet assigned, add loopbackDSR policy after endpoint creation")
237+
}
226238
}
227239

228240
epInfo, err = plugin.nm.CreateEndpoint(nwConfig.ID, epInfo, args.Netns)
@@ -231,6 +243,28 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) (resultError error) {
231243
return err
232244
}
233245

246+
// If LoopbackDSR is set but IP wasn't allocated via IPAM, add the policy after endpoint creation
247+
if hnsIPAM {
248+
if epInfo.IPAddress == nil || len(epInfo.IPAddress) == 0 {
249+
logrus.Errorf("[cni-net] LoopbackDSR is enabled but endpoint IP address is not set after endpoint creation")
250+
return errors.New("loopbackDSR requires IP address to be allocated")
251+
}
252+
253+
logrus.Debugf("[cni-net] Adding loopbackDSR policy for IP: %v after endpoint creation", epInfo.IPAddress)
254+
hcnLoopbackRoute, err := network.GetLoopbackDSRPolicy(epInfo.IPAddress)
255+
if err != nil {
256+
logrus.Errorf("[cni-net] Failed to create loopbackDSR policy after endpoint creation: %v, IPAddress: %v", err, epInfo.IPAddress)
257+
return err
258+
}
259+
260+
err = plugin.nm.ApplyPolicy(epInfo.ID, hcnLoopbackRoute)
261+
if err != nil {
262+
logrus.Errorf("[cni-net] Failed to apply loopbackDSR policy to endpoint: %v", err)
263+
return err
264+
}
265+
logrus.Debugf("[cni-net] Successfully applied loopbackDSR policy to endpoint")
266+
}
267+
234268
// Convert result to the requested CNI version.
235269
res := cni.GetCurrResult(nwConfig, epInfo, args.IfName, cniConfig)
236270
result, err := res.GetAsVersion(cniConfig.CniVersion)

network/manager.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package network
55

66
import (
7+
"encoding/json"
78
"fmt"
89
"github.com/Microsoft/hcsshim/hcn"
910
"github.com/Microsoft/windows-container-networking/common"
@@ -33,6 +34,7 @@ type Manager interface {
3334
DeleteEndpoint(endpointID string) error
3435
GetEndpoint(endpointID string, withIpv6 bool) (*EndpointInfo, error)
3536
GetEndpointByName(endpointName string, withIpv6 bool) (*EndpointInfo, error)
37+
ApplyPolicy(endpointID string, policy Policy) error
3638
}
3739

3840
// NewManager creates a new networkManager.
@@ -210,3 +212,31 @@ func (nm *networkManager) GetEndpointByName(endpointName string, withIpv6 bool)
210212

211213
return GetEndpointInfoFromHostComputeEndpoint(hcnEndpoint, withIpv6), nil
212214
}
215+
216+
// ApplyPolicy applies a policy to an existing endpoint.
217+
func (nm *networkManager) ApplyPolicy(endpointID string, policy Policy) error {
218+
nm.Lock()
219+
defer nm.Unlock()
220+
221+
hcnEndpoint, err := hcn.GetEndpointByID(endpointID)
222+
if err != nil {
223+
return fmt.Errorf("failed to get endpoint %s: %v", endpointID, err)
224+
}
225+
226+
var endpointPolicy hcn.EndpointPolicy
227+
err = json.Unmarshal(policy.Data, &endpointPolicy)
228+
if err != nil {
229+
return fmt.Errorf("failed to unmarshal policy: %v", err)
230+
}
231+
232+
policyRequest := hcn.PolicyEndpointRequest{
233+
Policies: []hcn.EndpointPolicy{endpointPolicy},
234+
}
235+
236+
err = hcnEndpoint.ApplyPolicy(hcn.RequestTypeAdd, policyRequest)
237+
if err != nil {
238+
return fmt.Errorf("failed to apply policy to endpoint: %v", err)
239+
}
240+
241+
return nil
242+
}

network/policy.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package network
66
import (
77
"encoding/json"
88
"errors"
9+
"fmt"
910
"net"
1011
"strconv"
1112
"strings"
@@ -81,7 +82,10 @@ func GetPortMappingPolicy(externalPort int, internalPort int, protocol string, h
8182
}
8283

8384
// GetLoopbackDSRPolicy creates a policy to support loopback direct server return.
84-
func GetLoopbackDSRPolicy(ip *net.IP) (Policy, error) {
85+
func GetLoopbackDSRPolicy(ip net.IP) (Policy, error) {
86+
if ip == nil || len(ip) == 0 {
87+
return Policy{}, fmt.Errorf("IP address cannot be nil for loopbackDSR policy")
88+
}
8589
hcnLoopbackRoute := hcn.OutboundNatPolicySetting{
8690
Destinations: []string{ip.String()},
8791
}

0 commit comments

Comments
 (0)