diff --git a/libnetwork/drivers/windows/overlay/joinleave_windows.go b/libnetwork/drivers/windows/overlay/joinleave_windows.go index cded48af64..83bee5ad93 100644 --- a/libnetwork/drivers/windows/overlay/joinleave_windows.go +++ b/libnetwork/drivers/windows/overlay/joinleave_windows.go @@ -39,6 +39,11 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil { logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err) } + + if ep.disablegateway { + jinfo.DisableGatewayService() + } + return nil } diff --git a/libnetwork/drivers/windows/overlay/ov_endpoint_windows.go b/libnetwork/drivers/windows/overlay/ov_endpoint_windows.go index 47af64cb9a..b7bda4a6b2 100644 --- a/libnetwork/drivers/windows/overlay/ov_endpoint_windows.go +++ b/libnetwork/drivers/windows/overlay/ov_endpoint_windows.go @@ -6,7 +6,11 @@ import ( "net" "github.com/Microsoft/hcsshim" + "github.com/docker/docker/pkg/system" "github.com/docker/libnetwork/driverapi" + "github.com/docker/libnetwork/drivers/windows" + "github.com/docker/libnetwork/netlabel" + "github.com/docker/libnetwork/types" "github.com/sirupsen/logrus" ) @@ -15,12 +19,14 @@ type endpointTable map[string]*endpoint const overlayEndpointPrefix = "overlay/endpoint" type endpoint struct { - id string - nid string - profileId string - remote bool - mac net.HardwareAddr - addr *net.IPNet + id string + nid string + profileID string + remote bool + mac net.HardwareAddr + addr *net.IPNet + disablegateway bool + portMapping []types.PortBinding // Operation port bindings } func validateID(nid, eid string) error { @@ -71,7 +77,7 @@ func (n *network) removeEndpointWithAddress(addr *net.IPNet) { if networkEndpoint != nil { logrus.Debugf("Removing stale endpoint from HNS") - _, err := hcsshim.HNSEndpointRequest("DELETE", networkEndpoint.profileId, "") + _, err := hcsshim.HNSEndpointRequest("DELETE", networkEndpoint.profileID, "") if err != nil { logrus.Debugf("Failed to delete stale overlay endpoint (%s) from hns", networkEndpoint.id[0:7]) @@ -96,7 +102,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, logrus.Debugf("Deleting stale endpoint %s", eid) n.deleteEndpoint(eid) - _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "") + _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "") if err != nil { return err } @@ -113,17 +119,19 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, return fmt.Errorf("create endpoint was not passed interface IP address") } - if s := n.getSubnetforIP(ep.addr); s == nil { - return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid) + s := n.getSubnetforIP(ep.addr) + if s == nil { + return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid) } // Todo: Add port bindings and qos policies here hnsEndpoint := &hcsshim.HNSEndpoint{ Name: eid, - VirtualNetwork: n.hnsId, + VirtualNetwork: n.hnsID, IPAddress: ep.addr.IP, EnableInternalDNS: true, + GatewayAddress: s.gwIP.String(), } if ep.mac != nil { @@ -141,6 +149,31 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy) + if system.GetOSVersion().Build > 16236 { + natPolicy, err := json.Marshal(hcsshim.PaPolicy{ + Type: "OutBoundNAT", + }) + + if err != nil { + return err + } + + hnsEndpoint.Policies = append(hnsEndpoint.Policies, natPolicy) + + epConnectivity, err := windows.ParseEndpointConnectivity(epOptions) + if err != nil { + return err + } + + pbPolicy, err := windows.ConvertPortBindings(epConnectivity.PortBindings) + if err != nil { + return err + } + hnsEndpoint.Policies = append(hnsEndpoint.Policies, pbPolicy...) + + ep.disablegateway = true + } + configurationb, err := json.Marshal(hnsEndpoint) if err != nil { return err @@ -151,7 +184,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, return err } - ep.profileId = hnsresponse.Id + ep.profileID = hnsresponse.Id if ep.mac == nil { ep.mac, err = net.ParseMAC(hnsresponse.MacAddress) @@ -164,6 +197,12 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, } } + ep.portMapping, err = windows.ParsePortBindingPolicies(hnsresponse.Policies) + if err != nil { + hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "") + return err + } + n.addEndpoint(ep) return nil @@ -186,7 +225,7 @@ func (d *driver) DeleteEndpoint(nid, eid string) error { n.deleteEndpoint(eid) - _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "") + _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "") if err != nil { return err } @@ -210,7 +249,17 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro } data := make(map[string]interface{}, 1) - data["hnsid"] = ep.profileId + data["hnsid"] = ep.profileID data["AllowUnqualifiedDNSQuery"] = true + + if ep.portMapping != nil { + // Return a copy of the operational data + pmc := make([]types.PortBinding, 0, len(ep.portMapping)) + for _, pm := range ep.portMapping { + pmc = append(pmc, pm.GetCopy()) + } + data[netlabel.PortMap] = pmc + } + return data, nil } diff --git a/libnetwork/drivers/windows/overlay/ov_network_windows.go b/libnetwork/drivers/windows/overlay/ov_network_windows.go index 70c4f02eda..9cc46f8cfe 100644 --- a/libnetwork/drivers/windows/overlay/ov_network_windows.go +++ b/libnetwork/drivers/windows/overlay/ov_network_windows.go @@ -37,7 +37,7 @@ type subnetJSON struct { type network struct { id string name string - hnsId string + hnsID string providerAddress string interfaceName string endpoints endpointTable @@ -108,7 +108,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d case "com.docker.network.windowsshim.interface": interfaceName = value case "com.docker.network.windowsshim.hnsid": - n.hnsId = value + n.hnsID = value case netlabel.OverlayVxlanIDList: vniStrings := strings.Split(value, ",") for _, vniStr := range vniStrings { @@ -181,7 +181,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d if err != nil { d.deleteNetwork(id) } else { - genData["com.docker.network.windowsshim.hnsid"] = n.hnsId + genData["com.docker.network.windowsshim.hnsid"] = n.hnsID } return err @@ -197,7 +197,7 @@ func (d *driver) DeleteNetwork(nid string) error { return types.ForbiddenErrorf("could not find network with id %s", nid) } - _, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsId, "") + _, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsID, "") if err != nil { return types.ForbiddenErrorf(err.Error()) } @@ -242,7 +242,7 @@ func (d *driver) network(nid string) *network { // } // for _, endpoint := range hnsresponse { -// if endpoint.VirtualNetwork != n.hnsId { +// if endpoint.VirtualNetwork != n.hnsID { // continue // } @@ -260,7 +260,7 @@ func (d *driver) network(nid string) *network { func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint { ep := &endpoint{ id: v.Name, - profileId: v.Id, + profileID: v.Id, nid: n.id, remote: v.IsRemoteEndpoint, } @@ -311,6 +311,7 @@ func (d *driver) createHnsNetwork(n *network) error { Type: d.Type(), Subnets: subnets, NetworkAdapterName: n.interfaceName, + AutomaticDNS: true, } configurationb, err := json.Marshal(network) @@ -326,7 +327,7 @@ func (d *driver) createHnsNetwork(n *network) error { return err } - n.hnsId = hnsresponse.Id + n.hnsID = hnsresponse.Id n.providerAddress = hnsresponse.ManagementIP return nil diff --git a/libnetwork/drivers/windows/overlay/overlay_windows.go b/libnetwork/drivers/windows/overlay/overlay_windows.go index d415bebcbd..65ad62ae0d 100644 --- a/libnetwork/drivers/windows/overlay/overlay_windows.go +++ b/libnetwork/drivers/windows/overlay/overlay_windows.go @@ -104,7 +104,7 @@ func (d *driver) restoreHNSNetworks() error { func (d *driver) convertToOverlayNetwork(v *hcsshim.HNSNetwork) *network { n := &network{ id: v.Name, - hnsId: v.Id, + hnsID: v.Id, driver: d, endpoints: endpointTable{}, subnets: []*subnet{}, diff --git a/libnetwork/drivers/windows/overlay/peerdb_windows.go b/libnetwork/drivers/windows/overlay/peerdb_windows.go index 0abc232432..159bfd6ed1 100644 --- a/libnetwork/drivers/windows/overlay/peerdb_windows.go +++ b/libnetwork/drivers/windows/overlay/peerdb_windows.go @@ -33,7 +33,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, hnsEndpoint := &hcsshim.HNSEndpoint{ Name: eid, - VirtualNetwork: n.hnsId, + VirtualNetwork: n.hnsID, MacAddress: peerMac.String(), IPAddress: peerIP, IsRemoteEndpoint: true, @@ -78,7 +78,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, nid: nid, addr: addr, mac: peerMac, - profileId: hnsresponse.Id, + profileID: hnsresponse.Id, remote: true, } @@ -108,7 +108,7 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMas } if updateDb { - _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "") + _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "") if err != nil { return err } diff --git a/libnetwork/drivers/windows/windows.go b/libnetwork/drivers/windows/windows.go index 45f835ee07..0b15b2aa49 100644 --- a/libnetwork/drivers/windows/windows.go +++ b/libnetwork/drivers/windows/windows.go @@ -55,7 +55,8 @@ type endpointOption struct { DisableICC bool } -type endpointConnectivity struct { +// EndpointConnectivity stores the port bindings and exposed ports that the user has specified in epOptions. +type EndpointConnectivity struct { PortBindings []types.PortBinding ExposedPorts []types.TransportPort } @@ -67,7 +68,7 @@ type hnsEndpoint struct { Type string macAddress net.HardwareAddr epOption *endpointOption // User specified parameters - epConnectivity *endpointConnectivity // User specified parameters + epConnectivity *EndpointConnectivity // User specified parameters portMapping []types.PortBinding // Operation port bindings addr *net.IPNet gateway net.IP @@ -95,7 +96,7 @@ const ( errNotFound = "HNS failed with error : The object identifier does not represent a valid object. " ) -// IsBuiltinWindowsDriver vaidates if network-type is a builtin local-scoped driver +// IsBuiltinLocalDriver validates if network-type is a builtin local-scoped driver func IsBuiltinLocalDriver(networkType string) bool { if "l2bridge" == networkType || "l2tunnel" == networkType || "nat" == networkType || "ics" == networkType || "transparent" == networkType { return true @@ -396,7 +397,8 @@ func convertQosPolicies(qosPolicies []types.QosPolicy) ([]json.RawMessage, error return qps, nil } -func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) { +// ConvertPortBindings converts PortBindings to JSON for HNS request +func ConvertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) { var pbs []json.RawMessage // Enumerate through the port bindings specified by the user and convert @@ -431,7 +433,8 @@ func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, e return pbs, nil } -func parsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) { +// ParsePortBindingPolicies parses HNS endpoint response message to PortBindings +func ParsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) { var bindings []types.PortBinding hcsPolicy := &hcsshim.NatPolicy{} @@ -505,12 +508,13 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointOption, er return ec, nil } -func parseEndpointConnectivity(epOptions map[string]interface{}) (*endpointConnectivity, error) { +// ParseEndpointConnectivity parses options passed to CreateEndpoint, specifically port bindings, and store in a endpointConnectivity object. +func ParseEndpointConnectivity(epOptions map[string]interface{}) (*EndpointConnectivity, error) { if epOptions == nil { return nil, nil } - ec := &endpointConnectivity{} + ec := &EndpointConnectivity{} if opt, ok := epOptions[netlabel.PortMap]; ok { if bs, ok := opt.([]types.PortBinding); ok { @@ -550,7 +554,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, if err != nil { return err } - epConnectivity, err := parseEndpointConnectivity(epOptions) + epConnectivity, err := ParseEndpointConnectivity(epOptions) if err != nil { return err } @@ -561,7 +565,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1) } - endpointStruct.Policies, err = convertPortBindings(epConnectivity.PortBindings) + endpointStruct.Policies, err = ConvertPortBindings(epConnectivity.PortBindings) if err != nil { return err } @@ -615,7 +619,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, endpoint.profileID = hnsresponse.Id endpoint.epConnectivity = epConnectivity endpoint.epOption = epOption - endpoint.portMapping, err = parsePortBindingPolicies(hnsresponse.Policies) + endpoint.portMapping, err = ParsePortBindingPolicies(hnsresponse.Policies) if err != nil { hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")