From 76d281993ac42136bc3c79279f7168adf713b220 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Tue, 21 Aug 2018 23:29:43 -0700 Subject: [PATCH 1/5] Implement multitenancy for windows --- cni/network/network.go | 96 ++++++++++++++++++++++---------- cni/network/network_linux.go | 7 +++ cni/network/network_windows.go | 46 +++++++++++++++ network/endpoint_windows.go | 48 +++++++++++++--- network/manager.go | 5 +- network/network.go | 16 +++++- network/network_linux.go | 2 - network/network_windows.go | 34 ++++++++--- network/policy/policy.go | 35 ++++++++++++ network/policy/policy_windows.go | 7 --- 10 files changed, 239 insertions(+), 57 deletions(-) delete mode 100644 network/policy/policy_windows.go diff --git a/cni/network/network.go b/cni/network/network.go index 3cb056b03a..a643e484c5 100644 --- a/cni/network/network.go +++ b/cni/network/network.go @@ -131,6 +131,31 @@ func GetEndpointID(args *cniSkel.CmdArgs) string { return infraEpId } +// getPodInfo returns POD info by parsing the CNI args. +func (plugin *netPlugin) getPodInfo(args string) (string, string, error) { + podCfg, err := cni.ParseCniArgs(args) + if err != nil { + log.Printf("Error while parsing CNI Args %v", err) + return "", "", err + } + + k8sNamespace := string(podCfg.K8S_POD_NAMESPACE) + if len(k8sNamespace) == 0 { + errMsg := "Pod Namespace not specified in CNI Args" + log.Printf(errMsg) + return "", "", plugin.Errorf(errMsg) + } + + k8sPodName := string(podCfg.K8S_POD_NAME) + if len(k8sPodName) == 0 { + errMsg := "Pod Name not specified in CNI Args" + log.Printf(errMsg) + return "", "", plugin.Errorf(errMsg) + } + + return k8sPodName, k8sNamespace, nil +} + // // CNI implementation // https://github.com/containernetworking/cni/blob/master/SPEC.md @@ -192,26 +217,11 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { }() // Parse Pod arguments. - podCfg, err := cni.ParseCniArgs(args.Args) + k8sPodName, k8sNamespace, err := plugin.getPodInfo(args.Args) if err != nil { - log.Printf("Error while parsing CNI Args %v", err) return err } - k8sNamespace := string(podCfg.K8S_POD_NAMESPACE) - if len(k8sNamespace) == 0 { - errMsg := "Pod Namespace not specified in CNI Args" - log.Printf(errMsg) - return plugin.Errorf(errMsg) - } - - k8sPodName := string(podCfg.K8S_POD_NAME) - if len(k8sPodName) == 0 { - errMsg := "Pod Name not specified in CNI Args" - log.Printf(errMsg) - return plugin.Errorf(errMsg) - } - k8sContainerID := args.ContainerID if len(k8sContainerID) == 0 { errMsg := "Container ID not specified in CNI Args" @@ -234,10 +244,6 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { } } - // Initialize values from network config. - networkId := nwCfg.Name - endpointId := GetEndpointID(args) - result, cnsNetworkConfig, subnetPrefix, azIpamResult, err = GetMultiTenancyCNIResult(enableInfraVnet, nwCfg, plugin, k8sPodName, k8sNamespace, args.IfName) if err != nil { log.Printf("GetMultiTenancyCNIResult failed with error %v", err) @@ -252,6 +258,15 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { log.Printf("Result from multitenancy %+v", result) + // Initialize values from network config. + networkId, err := getNetworkName(k8sPodName, k8sNamespace, args.IfName, nwCfg) + if err != nil { + log.Printf("[cni-net] Failed to extract network name from network config. error: %v", err) + return err + } + + endpointId := GetEndpointID(args) + policies := cni.GetPoliciesFromNwCfg(nwCfg.AdditionalArgs) // Check whether the network already exists. @@ -265,13 +280,13 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { */ epInfo, _ := plugin.nm.GetEndpointInfo(networkId, endpointId) if epInfo != nil { - result, err = handleConsecutiveAdd(args.ContainerID, endpointId, nwInfo, nwCfg) - if err != nil { - log.Printf("handleConsecutiveAdd failed with error %v", err) - return err + resultConsAdd, errConsAdd := handleConsecutiveAdd(args.ContainerID, endpointId, nwInfo, nwCfg) + if errConsAdd != nil { + log.Printf("handleConsecutiveAdd failed with error %v", errConsAdd) + return errConsAdd } - if result != nil { + if resultConsAdd != nil { return nil } } @@ -335,11 +350,14 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { } log.Printf("[cni-net] nwDNSInfo: %v", nwDNSInfo) + // Update subnet prefix for multi-tenant scenario + updateSubnetPrefix(cnsNetworkConfig, &subnetPrefix) // Create the network. nwInfo := network.NetworkInfo{ - Id: networkId, - Mode: nwCfg.Mode, + Id: networkId, + Mode: nwCfg.Mode, + MasterIfName: masterIfName, Subnets: []network.SubnetInfo{ network.SubnetInfo{ Family: platform.AfINET, @@ -492,8 +510,18 @@ func (plugin *netPlugin) Get(args *cniSkel.CmdArgs) error { log.Printf("[cni-net] Read network configuration %+v.", nwCfg) + // Parse Pod arguments. + k8sPodName, k8sNamespace, err := plugin.getPodInfo(args.Args) + if err != nil { + return err + } + // Initialize values from network config. - networkId := nwCfg.Name + networkId, err := getNetworkName(k8sPodName, k8sNamespace, args.IfName, nwCfg) + if err != nil { + log.Printf("[cni-net] Failed to extract network name from network config. error: %v", err) + } + endpointId := GetEndpointID(args) // Query the network. @@ -552,8 +580,18 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error { log.Printf("[cni-net] Read network configuration %+v.", nwCfg) + // Parse Pod arguments. + k8sPodName, k8sNamespace, err := plugin.getPodInfo(args.Args) + if err != nil { + return err + } + // Initialize values from network config. - networkId := nwCfg.Name + networkId, err := getNetworkName(k8sPodName, k8sNamespace, args.IfName, nwCfg) + if err != nil { + log.Printf("[cni-net] Failed to extract network name from network config. error: %v", err) + } + endpointId := GetEndpointID(args) // Query the network. diff --git a/cni/network/network_linux.go b/cni/network/network_linux.go index 5927345256..6a8ccbf88d 100644 --- a/cni/network/network_linux.go +++ b/cni/network/network_linux.go @@ -108,3 +108,10 @@ func getEndpointDNSSettings(nwCfg *cni.NetworkConfig, result *cniTypesCurr.Resul func getPoliciesFromRuntimeCfg(nwCfg *cni.NetworkConfig) []policy.Policy { return nil } + +func updateSubnetPrefix(cnsNetworkConfig *cns.GetNetworkContainerResponse, subnetPrefix *net.IPNet) { +} + +func getNetworkName(podName, podNs, ifName string, nwCfg *cni.NetworkConfig) (string, error) { + return nwCfg.Name, nil +} diff --git a/cni/network/network_windows.go b/cni/network/network_windows.go index a495894369..ec21be87ca 100644 --- a/cni/network/network_windows.go +++ b/cni/network/network_windows.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net" + "strconv" "strings" "github.com/Azure/azure-container-networking/cni" @@ -70,14 +71,59 @@ func addInfraRoutes(azIpamResult *cniTypesCurr.Result, result *cniTypesCurr.Resu } func setNetworkOptions(cnsNwConfig *cns.GetNetworkContainerResponse, nwInfo *network.NetworkInfo) { + if cnsNwConfig != nil && cnsNwConfig.MultiTenancyInfo.ID != 0 { + log.Printf("Setting Network Options") + vlanMap := make(map[string]interface{}) + vlanMap[network.VlanIDKey] = strconv.Itoa(cnsNwConfig.MultiTenancyInfo.ID) + nwInfo.Options[dockerNetworkOption] = vlanMap + } } func setEndpointOptions(cnsNwConfig *cns.GetNetworkContainerResponse, epInfo *network.EndpointInfo, vethName string) { + if cnsNwConfig != nil && cnsNwConfig.MultiTenancyInfo.ID != 0 { + log.Printf("Setting Endpoint Options") + var cnetAddressMap []string + for _, ipSubnet := range cnsNwConfig.CnetAddressSpace { + cnetAddressMap = append(cnetAddressMap, ipSubnet.IPAddress+"/"+strconv.Itoa(int(ipSubnet.PrefixLength))) + } + epInfo.Data[network.CnetAddressSpace] = cnetAddressMap + } } func addSnatInterface(nwCfg *cni.NetworkConfig, result *cniTypesCurr.Result) { } +func updateSubnetPrefix(cnsNwConfig *cns.GetNetworkContainerResponse, subnetPrefix *net.IPNet) { + if cnsNwConfig != nil && cnsNwConfig.MultiTenancyInfo.ID != 0 { + ipconfig := cnsNwConfig.IPConfiguration + ipAddr := net.ParseIP(ipconfig.IPSubnet.IPAddress) + + if ipAddr.To4() != nil { + *subnetPrefix = net.IPNet{IP: ipAddr, Mask: net.CIDRMask(int(ipconfig.IPSubnet.PrefixLength), 32)} + } else { + *subnetPrefix = net.IPNet{IP: ipAddr, Mask: net.CIDRMask(int(ipconfig.IPSubnet.PrefixLength), 128)} + } + + subnetPrefix.IP = subnetPrefix.IP.Mask(subnetPrefix.Mask) + log.Printf("Updated subnetPrefix: %s", subnetPrefix.String()) + } +} + +func getNetworkName(podName, podNs, ifName string, nwCfg *cni.NetworkConfig) (string, error) { + if nwCfg.MultiTenancy { + _, cnsNetworkConfig, _, err := getContainerNetworkConfiguration(nwCfg, "", podName, podNs, ifName) + if err != nil { + log.Printf("GetContainerNetworkConfiguration failed for podname %v namespace %v with error %v", podName, podNs, err) + return "", err + } + + networkName := fmt.Sprintf("%s-vlanid%v", nwCfg.Name, cnsNetworkConfig.MultiTenancyInfo.ID) + return networkName, nil + } + + return nwCfg.Name, nil +} + func setupInfraVnetRoutingForMultitenancy( nwCfg *cni.NetworkConfig, azIpamResult *cniTypesCurr.Result, diff --git a/network/endpoint_windows.go b/network/endpoint_windows.go index 1d894ca143..ebba430c94 100644 --- a/network/endpoint_windows.go +++ b/network/endpoint_windows.go @@ -44,6 +44,14 @@ func ConstructEndpointID(containerID string, netNsPath string, ifName string) (s // newEndpointImpl creates a new endpoint in the network. func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) { + var vlanid int + + if epInfo.Data != nil { + if _, ok := epInfo.Data[VlanIDKey]; ok { + vlanid = epInfo.Data[VlanIDKey].(int) + } + } + // Get Infrastructure containerID. Handle ADD calls for workload container. var err error infraEpName, _ := ConstructEndpointID(epInfo.ContainerID, epInfo.NetNsPath, epInfo.IfName) @@ -53,9 +61,31 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) { VirtualNetwork: nw.HnsId, DNSSuffix: epInfo.DNS.Suffix, DNSServerList: strings.Join(epInfo.DNS.Servers, ","), - Policies: policy.SerializePolicies(policy.EndpointPolicy, epInfo.Policies), } + // Set outbound NAT policy + outBoundNatPolicy := hcsshim.OutboundNatPolicy{} + outBoundNatPolicy.Policy.Type = hcsshim.OutboundNat + + exceptionList, err := policy.GetOutBoundNatExceptionList(epInfo.Policies) + if err != nil { + log.Printf("[net] Failed to parse outbound NAT policy %v", err) + return nil, err + } + + for _, ipAddress := range exceptionList { + outBoundNatPolicy.Exceptions = append(outBoundNatPolicy.Exceptions, ipAddress) + } + + if cnetAddressSpace := epInfo.Data[CnetAddressSpace].([]string); cnetAddressSpace != nil { + for _, ipAddress := range cnetAddressSpace { + outBoundNatPolicy.Exceptions = append(outBoundNatPolicy.Exceptions, ipAddress) + } + } + + serializedOutboundNatPolicy, _ := json.Marshal(outBoundNatPolicy) + hnsEndpoint.Policies = append(hnsEndpoint.Policies, serializedOutboundNatPolicy) + // HNS currently supports only one IP address per endpoint. if epInfo.IPAddresses != nil { hnsEndpoint.IPAddress = epInfo.IPAddresses[0].IP @@ -96,13 +126,15 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) { // Create the endpoint object. ep := &endpoint{ - Id: infraEpName, - HnsId: hnsResponse.Id, - SandboxKey: epInfo.ContainerID, - IfName: epInfo.IfName, - IPAddresses: epInfo.IPAddresses, - Gateways: []net.IP{net.ParseIP(hnsResponse.GatewayAddress)}, - DNS: epInfo.DNS, + Id: infraEpName, + HnsId: hnsResponse.Id, + SandboxKey: epInfo.ContainerID, + IfName: epInfo.IfName, + IPAddresses: epInfo.IPAddresses, + Gateways: []net.IP{net.ParseIP(hnsResponse.GatewayAddress)}, + DNS: epInfo.DNS, + VlanID: vlanid, + EnableSnatOnHost: epInfo.EnableSnatOnHost, } for _, route := range epInfo.Routes { diff --git a/network/manager.go b/network/manager.go index cdf03befab..3a6e9e5974 100644 --- a/network/manager.go +++ b/network/manager.go @@ -15,8 +15,9 @@ import ( const ( // Network store key. - storeKey = "Network" - VlanIDKey = "VlanID" + storeKey = "Network" + VlanIDKey = "VlanID" + genericData = "com.docker.network.generic" ) type NetworkClient interface { diff --git a/network/network.go b/network/network.go index 0e68c490b4..d60a0275b6 100644 --- a/network/network.go +++ b/network/network.go @@ -46,6 +46,7 @@ type network struct { // NetworkInfo contains read-only information about a container network. type NetworkInfo struct { + MasterIfName string Id string Mode string Subnets []SubnetInfo @@ -121,6 +122,17 @@ func (nm *networkManager) findExternalInterfaceBySubnet(subnet string) *external return nil } +// FindExternalInterfaceByName finds an external interface by name. +func (nm *networkManager) findExternalInterfaceByName(name string) *externalInterface { + for _, extIf := range nm.ExternalInterfaces { + if extIf != nil && extIf.Name == name { + return extIf + } + } + + return nil +} + // NewNetwork creates a new container network. func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) { var nw *network @@ -138,8 +150,8 @@ func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) { nwInfo.Mode = opModeDefault } - // Find the external interface for this subnet. - extIf := nm.findExternalInterfaceBySubnet(nwInfo.Subnets[0].Prefix.String()) + // Find the external interface by name. + extIf := nm.findExternalInterfaceByName(nwInfo.MasterIfName) if extIf == nil { err = errSubnetNotFound return nil, err diff --git a/network/network_linux.go b/network/network_linux.go index 4d49a634d2..25217d5b92 100644 --- a/network/network_linux.go +++ b/network/network_linux.go @@ -21,8 +21,6 @@ const ( // Virtual MAC address used by Azure VNET. virtualMacAddress = "12:34:56:78:9a:bc" - genericData = "com.docker.network.generic" - SnatBridgeIPKey = "snatBridgeIP" LocalIPKey = "localIP" diff --git a/network/network_windows.go b/network/network_windows.go index 0a1bc6ca76..b3ecd5e5dd 100644 --- a/network/network_windows.go +++ b/network/network_windows.go @@ -5,6 +5,7 @@ package network import ( "encoding/json" + "strconv" "strings" "time" @@ -15,8 +16,9 @@ import ( const ( // HNS network types. - hnsL2bridge = "l2bridge" - hnsL2tunnel = "l2tunnel" + hnsL2bridge = "l2bridge" + hnsL2tunnel = "l2tunnel" + CnetAddressSpace = "cnetAddressSpace" ) // Windows implementation of route. @@ -24,6 +26,7 @@ type route interface{} // NewNetworkImpl creates a new container network. func (nm *networkManager) newNetworkImpl(nwInfo *NetworkInfo, extIf *externalInterface) (*network, error) { + var vlanid int networkAdapterName := extIf.Name // FixMe: Find a better way to check if a nic that is selected is not part of a vSwitch if strings.HasPrefix(networkAdapterName, "vEthernet") { @@ -37,6 +40,21 @@ func (nm *networkManager) newNetworkImpl(nwInfo *NetworkInfo, extIf *externalInt Policies: policy.SerializePolicies(policy.NetworkPolicy, nwInfo.Policies), } + // Set the VLAN and OutboundNAT policies + opt, _ := nwInfo.Options[genericData].(map[string]interface{}) + if opt != nil && opt[VlanIDKey] != nil { + vlanPolicy := hcsshim.VlanPolicy{ + Type: "VLAN", + } + vlanID, _ := strconv.ParseUint(opt[VlanIDKey].(string), 10, 32) + vlanPolicy.VLAN = uint(vlanID) + + serializedVlanPolicy, _ := json.Marshal(vlanPolicy) + hnsNetwork.Policies = append(hnsNetwork.Policies, serializedVlanPolicy) + + vlanid = (int)(vlanPolicy.VLAN) + } + // Set network mode. switch nwInfo.Mode { case opModeBridge: @@ -74,11 +92,13 @@ func (nm *networkManager) newNetworkImpl(nwInfo *NetworkInfo, extIf *externalInt // Create the network object. nw := &network{ - Id: nwInfo.Id, - HnsId: hnsResponse.Id, - Mode: nwInfo.Mode, - Endpoints: make(map[string]*endpoint), - extIf: extIf, + Id: nwInfo.Id, + HnsId: hnsResponse.Id, + Mode: nwInfo.Mode, + Endpoints: make(map[string]*endpoint), + extIf: extIf, + VlanId: vlanid, + EnableSnatOnHost: nwInfo.EnableSnatOnHost, } globals, err := hcsshim.GetHNSGlobals() diff --git a/network/policy/policy.go b/network/policy/policy.go index 3143184a62..340a24e351 100644 --- a/network/policy/policy.go +++ b/network/policy/policy.go @@ -2,6 +2,13 @@ package policy import ( "encoding/json" + "fmt" +) + +const ( + NetworkPolicy CNIPolicyType = "NetworkPolicy" + EndpointPolicy CNIPolicyType = "EndpointPolicy" + OutBoundNatPolicy CNIPolicyType = "OutBoundNAT" ) type CNIPolicyType string @@ -21,3 +28,31 @@ func SerializePolicies(policyType CNIPolicyType, policies []Policy) []json.RawMe } return jsonPolicies } + +// GetOutBoundNatExceptionList returns exception list for outbound nat policy +func GetOutBoundNatExceptionList(policies []Policy) ([]string, error) { + type KVPair struct { + Type CNIPolicyType `json:"Type"` + ExceptionList json.RawMessage `json:"ExceptionList"` + } + + for _, policy := range policies { + if policy.Type == EndpointPolicy { + var data KVPair + if err := json.Unmarshal(policy.Data, &data); err != nil { + return nil, err + } + + if data.Type == OutBoundNatPolicy { + var exceptionList []string + if err := json.Unmarshal(data.ExceptionList, &exceptionList); err != nil { + return nil, err + } + + return exceptionList, nil + } + } + } + + return nil, fmt.Errorf("OutBoundNAT policy not set") +} diff --git a/network/policy/policy_windows.go b/network/policy/policy_windows.go deleted file mode 100644 index 9121d45927..0000000000 --- a/network/policy/policy_windows.go +++ /dev/null @@ -1,7 +0,0 @@ -package policy - -const ( - NetworkPolicy CNIPolicyType = "NetworkPolicy" - EndpointPolicy CNIPolicyType = "EndpointPolicy" - OutBoundNatPolicy CNIPolicyType = "OutBoundNatPolicy" -) From 3f3b4e09e268932415e686afbe04325b7878fc76 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Tue, 30 Oct 2018 09:21:40 -0700 Subject: [PATCH 2/5] Address review comments --- cni/network/network.go | 2 ++ network/network.go | 9 ++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cni/network/network.go b/cni/network/network.go index a643e484c5..eb9c134725 100644 --- a/cni/network/network.go +++ b/cni/network/network.go @@ -283,10 +283,12 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error { resultConsAdd, errConsAdd := handleConsecutiveAdd(args.ContainerID, endpointId, nwInfo, nwCfg) if errConsAdd != nil { log.Printf("handleConsecutiveAdd failed with error %v", errConsAdd) + result = resultConsAdd return errConsAdd } if resultConsAdd != nil { + result = resultConsAdd return nil } } diff --git a/network/network.go b/network/network.go index d60a0275b6..f2e0baa1ad 100644 --- a/network/network.go +++ b/network/network.go @@ -123,11 +123,10 @@ func (nm *networkManager) findExternalInterfaceBySubnet(subnet string) *external } // FindExternalInterfaceByName finds an external interface by name. -func (nm *networkManager) findExternalInterfaceByName(name string) *externalInterface { - for _, extIf := range nm.ExternalInterfaces { - if extIf != nil && extIf.Name == name { - return extIf - } +func (nm *networkManager) findExternalInterfaceByName(ifName string) *externalInterface { + extIf, exists := nm.ExternalInterfaces[ifName] + if exists && extIf != nil { + return extIf } return nil From 2b2cb10f0eb4bb2dfa2b951520c88b41b4d25233 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Tue, 30 Oct 2018 13:59:01 -0700 Subject: [PATCH 3/5] Fix for single tenancy to work --- network/endpoint_windows.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/network/endpoint_windows.go b/network/endpoint_windows.go index ebba430c94..5e678b4c6f 100644 --- a/network/endpoint_windows.go +++ b/network/endpoint_windows.go @@ -77,9 +77,11 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) { outBoundNatPolicy.Exceptions = append(outBoundNatPolicy.Exceptions, ipAddress) } - if cnetAddressSpace := epInfo.Data[CnetAddressSpace].([]string); cnetAddressSpace != nil { - for _, ipAddress := range cnetAddressSpace { - outBoundNatPolicy.Exceptions = append(outBoundNatPolicy.Exceptions, ipAddress) + if epInfo.Data[CnetAddressSpace] != nil { + if cnetAddressSpace := epInfo.Data[CnetAddressSpace].([]string); cnetAddressSpace != nil { + for _, ipAddress := range cnetAddressSpace { + outBoundNatPolicy.Exceptions = append(outBoundNatPolicy.Exceptions, ipAddress) + } } } From c09c7efa9b2652f788c01749b461b648c4c43eba Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Tue, 30 Oct 2018 22:57:15 -0700 Subject: [PATCH 4/5] Fix for cnm --- network/network.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/network/network.go b/network/network.go index f2e0baa1ad..cbf177e47a 100644 --- a/network/network.go +++ b/network/network.go @@ -5,6 +5,7 @@ package network import ( "net" + "strings" "github.com/Azure/azure-container-networking/log" "github.com/Azure/azure-container-networking/network/policy" @@ -149,8 +150,14 @@ func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) { nwInfo.Mode = opModeDefault } - // Find the external interface by name. - extIf := nm.findExternalInterfaceByName(nwInfo.MasterIfName) + // If the master interface name is provided, find the external interface by name + // else use subnet to to find the interface + var extIf *externalInterface + if len(strings.TrimSpace(nwInfo.MasterIfName)) > 0 { + extIf = nm.findExternalInterfaceByName(nwInfo.MasterIfName) + } else { + extIf = nm.findExternalInterfaceBySubnet(nwInfo.Subnets[0].Prefix.String()) + } if extIf == nil { err = errSubnetNotFound return nil, err From e9ab22b0bafa5798dcf7a9ff99cb87923ba34c00 Mon Sep 17 00:00:00 2001 From: Ashvin Deodhar Date: Wed, 31 Oct 2018 11:00:21 -0700 Subject: [PATCH 5/5] NULL Checks for hnspolicy code --- network/endpoint_windows.go | 12 ++++++++---- network/policy/policy.go | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/network/endpoint_windows.go b/network/endpoint_windows.go index 5e678b4c6f..f9527944ee 100644 --- a/network/endpoint_windows.go +++ b/network/endpoint_windows.go @@ -73,8 +73,10 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) { return nil, err } - for _, ipAddress := range exceptionList { - outBoundNatPolicy.Exceptions = append(outBoundNatPolicy.Exceptions, ipAddress) + if exceptionList != nil { + for _, ipAddress := range exceptionList { + outBoundNatPolicy.Exceptions = append(outBoundNatPolicy.Exceptions, ipAddress) + } } if epInfo.Data[CnetAddressSpace] != nil { @@ -85,8 +87,10 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) { } } - serializedOutboundNatPolicy, _ := json.Marshal(outBoundNatPolicy) - hnsEndpoint.Policies = append(hnsEndpoint.Policies, serializedOutboundNatPolicy) + if outBoundNatPolicy.Exceptions != nil { + serializedOutboundNatPolicy, _ := json.Marshal(outBoundNatPolicy) + hnsEndpoint.Policies = append(hnsEndpoint.Policies, serializedOutboundNatPolicy) + } // HNS currently supports only one IP address per endpoint. if epInfo.IPAddresses != nil { diff --git a/network/policy/policy.go b/network/policy/policy.go index 340a24e351..355aae6663 100644 --- a/network/policy/policy.go +++ b/network/policy/policy.go @@ -2,7 +2,7 @@ package policy import ( "encoding/json" - "fmt" + "log" ) const ( @@ -54,5 +54,6 @@ func GetOutBoundNatExceptionList(policies []Policy) ([]string, error) { } } - return nil, fmt.Errorf("OutBoundNAT policy not set") + log.Printf("OutBoundNAT policy not set.") + return nil, nil }