github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/drivers/windows/windows.go (about)

     1  // +build windows
     2  
     3  // Shim for the Host Network Service (HNS) to manage networking for
     4  // Windows Server containers and Hyper-V containers. This module
     5  // is a basic libnetwork driver that passes all the calls to HNS
     6  // It implements the 4 networking modes supported by HNS L2Bridge,
     7  // L2Tunnel, NAT and Transparent(DHCP)
     8  //
     9  // The network are stored in memory and docker daemon ensures discovering
    10  // and loading these networks on startup
    11  
    12  package windows
    13  
    14  import (
    15  	"encoding/json"
    16  	"fmt"
    17  	"net"
    18  	"strconv"
    19  	"strings"
    20  	"sync"
    21  
    22  	"github.com/Microsoft/hcsshim"
    23  	log "github.com/Sirupsen/logrus"
    24  	"github.com/docker/libnetwork/datastore"
    25  	"github.com/docker/libnetwork/discoverapi"
    26  	"github.com/docker/libnetwork/driverapi"
    27  	"github.com/docker/libnetwork/netlabel"
    28  	"github.com/docker/libnetwork/types"
    29  )
    30  
    31  // networkConfiguration for network specific configuration
    32  type networkConfiguration struct {
    33  	ID                 string
    34  	Type               string
    35  	Name               string
    36  	HnsID              string
    37  	RDID               string
    38  	VLAN               uint
    39  	VSID               uint
    40  	DNSServers         string
    41  	DNSSuffix          string
    42  	SourceMac          string
    43  	NetworkAdapterName string
    44  }
    45  
    46  // endpointConfiguration represents the user specified configuration for the sandbox endpoint
    47  type endpointConfiguration struct {
    48  	MacAddress   net.HardwareAddr
    49  	PortBindings []types.PortBinding
    50  	ExposedPorts []types.TransportPort
    51  	QosPolicies  []types.QosPolicy
    52  	DNSServers   []string
    53  }
    54  
    55  type hnsEndpoint struct {
    56  	id          string
    57  	profileID   string
    58  	macAddress  net.HardwareAddr
    59  	config      *endpointConfiguration // User specified parameters
    60  	portMapping []types.PortBinding    // Operation port bindings
    61  	addr        *net.IPNet
    62  }
    63  
    64  type hnsNetwork struct {
    65  	id        string
    66  	config    *networkConfiguration
    67  	endpoints map[string]*hnsEndpoint // key: endpoint id
    68  	driver    *driver                 // The network's driver
    69  	sync.Mutex
    70  }
    71  
    72  type driver struct {
    73  	name     string
    74  	networks map[string]*hnsNetwork
    75  	sync.Mutex
    76  }
    77  
    78  func isValidNetworkType(networkType string) bool {
    79  	if "l2bridge" == networkType || "l2tunnel" == networkType || "nat" == networkType || "ics" == networkType || "transparent" == networkType {
    80  		return true
    81  	}
    82  
    83  	return false
    84  }
    85  
    86  // New constructs a new bridge driver
    87  func newDriver(networkType string) *driver {
    88  	return &driver{name: networkType, networks: map[string]*hnsNetwork{}}
    89  }
    90  
    91  // GetInit returns an initializer for the given network type
    92  func GetInit(networkType string) func(dc driverapi.DriverCallback, config map[string]interface{}) error {
    93  	return func(dc driverapi.DriverCallback, config map[string]interface{}) error {
    94  		if !isValidNetworkType(networkType) {
    95  			return types.BadRequestErrorf("Network type not supported: %s", networkType)
    96  		}
    97  
    98  		return dc.RegisterDriver(networkType, newDriver(networkType), driverapi.Capability{
    99  			DataScope: datastore.LocalScope,
   100  		})
   101  	}
   102  }
   103  
   104  func (d *driver) getNetwork(id string) (*hnsNetwork, error) {
   105  	d.Lock()
   106  	defer d.Unlock()
   107  
   108  	if nw, ok := d.networks[id]; ok {
   109  		return nw, nil
   110  	}
   111  
   112  	return nil, types.NotFoundErrorf("network not found: %s", id)
   113  }
   114  
   115  func (n *hnsNetwork) getEndpoint(eid string) (*hnsEndpoint, error) {
   116  	n.Lock()
   117  	defer n.Unlock()
   118  
   119  	if ep, ok := n.endpoints[eid]; ok {
   120  		return ep, nil
   121  	}
   122  
   123  	return nil, types.NotFoundErrorf("Endpoint not found: %s", eid)
   124  }
   125  
   126  func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string) (*networkConfiguration, error) {
   127  	config := &networkConfiguration{}
   128  
   129  	for label, value := range genericOptions {
   130  		switch label {
   131  		case NetworkName:
   132  			config.Name = value
   133  		case HNSID:
   134  			config.HnsID = value
   135  		case RoutingDomain:
   136  			config.RDID = value
   137  		case Interface:
   138  			config.NetworkAdapterName = value
   139  		case DNSSuffix:
   140  			config.DNSSuffix = value
   141  		case DNSServers:
   142  			config.DNSServers = value
   143  		case VLAN:
   144  			vlan, err := strconv.ParseUint(value, 10, 32)
   145  			if err != nil {
   146  				return nil, err
   147  			}
   148  			config.VLAN = uint(vlan)
   149  		case VSID:
   150  			vsid, err := strconv.ParseUint(value, 10, 32)
   151  			if err != nil {
   152  				return nil, err
   153  			}
   154  			config.VSID = uint(vsid)
   155  		}
   156  	}
   157  
   158  	config.ID = id
   159  	config.Type = d.name
   160  	return config, nil
   161  }
   162  
   163  func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
   164  	if len(ipamV6Data) > 0 {
   165  		return types.ForbiddenErrorf("windowsshim driver doesn't support v6 subnets")
   166  	}
   167  
   168  	if len(ipamV4Data) == 0 {
   169  		return types.BadRequestErrorf("network %s requires ipv4 configuration", id)
   170  	}
   171  
   172  	return nil
   173  }
   174  
   175  func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
   176  }
   177  
   178  // Create a new network
   179  func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
   180  	if _, err := d.getNetwork(id); err == nil {
   181  		return types.ForbiddenErrorf("network %s exists", id)
   182  	}
   183  
   184  	genData, ok := option[netlabel.GenericData].(map[string]string)
   185  	if !ok {
   186  		return fmt.Errorf("Unknown generic data option")
   187  	}
   188  
   189  	// Parse and validate the config. It should not conflict with existing networks' config
   190  	config, err := d.parseNetworkOptions(id, genData)
   191  	if err != nil {
   192  		return err
   193  	}
   194  
   195  	err = config.processIPAM(id, ipV4Data, ipV6Data)
   196  	if err != nil {
   197  		return err
   198  	}
   199  
   200  	network := &hnsNetwork{
   201  		id:        config.ID,
   202  		endpoints: make(map[string]*hnsEndpoint),
   203  		config:    config,
   204  		driver:    d,
   205  	}
   206  
   207  	d.Lock()
   208  	d.networks[config.ID] = network
   209  	d.Unlock()
   210  
   211  	// A non blank hnsid indicates that the network was discovered
   212  	// from HNS. No need to call HNS if this network was discovered
   213  	// from HNS
   214  	if config.HnsID == "" {
   215  		subnets := []hcsshim.Subnet{}
   216  
   217  		for _, ipData := range ipV4Data {
   218  			subnet := hcsshim.Subnet{
   219  				AddressPrefix: ipData.Pool.String(),
   220  			}
   221  
   222  			if ipData.Gateway != nil {
   223  				subnet.GatewayAddress = ipData.Gateway.IP.String()
   224  			}
   225  
   226  			subnets = append(subnets, subnet)
   227  		}
   228  
   229  		network := &hcsshim.HNSNetwork{
   230  			Name:               config.Name,
   231  			Type:               d.name,
   232  			Subnets:            subnets,
   233  			DNSServerList:      config.DNSServers,
   234  			DNSSuffix:          config.DNSSuffix,
   235  			SourceMac:          config.SourceMac,
   236  			NetworkAdapterName: config.NetworkAdapterName,
   237  		}
   238  
   239  		if config.VLAN != 0 {
   240  			vlanPolicy, err := json.Marshal(hcsshim.VlanPolicy{
   241  				Type: "VLAN",
   242  				VLAN: config.VLAN,
   243  			})
   244  
   245  			if err != nil {
   246  				return err
   247  			}
   248  			network.Policies = append(network.Policies, vlanPolicy)
   249  		}
   250  
   251  		if config.VSID != 0 {
   252  			vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
   253  				Type: "VSID",
   254  				VSID: config.VSID,
   255  			})
   256  
   257  			if err != nil {
   258  				return err
   259  			}
   260  			network.Policies = append(network.Policies, vsidPolicy)
   261  		}
   262  
   263  		if network.Name == "" {
   264  			network.Name = id
   265  		}
   266  
   267  		configurationb, err := json.Marshal(network)
   268  		if err != nil {
   269  			return err
   270  		}
   271  
   272  		configuration := string(configurationb)
   273  		log.Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)
   274  
   275  		hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
   276  		if err != nil {
   277  			return err
   278  		}
   279  
   280  		config.HnsID = hnsresponse.Id
   281  		genData[HNSID] = config.HnsID
   282  	}
   283  
   284  	return nil
   285  }
   286  
   287  func (d *driver) DeleteNetwork(nid string) error {
   288  	n, err := d.getNetwork(nid)
   289  	if err != nil {
   290  		return types.InternalMaskableErrorf("%s", err)
   291  	}
   292  
   293  	n.Lock()
   294  	config := n.config
   295  	n.Unlock()
   296  
   297  	// Cannot remove network if endpoints are still present
   298  	if len(n.endpoints) != 0 {
   299  		return fmt.Errorf("network %s has active endpoint", n.id)
   300  	}
   301  
   302  	_, err = hcsshim.HNSNetworkRequest("DELETE", config.HnsID, "")
   303  	if err != nil {
   304  		return err
   305  	}
   306  
   307  	d.Lock()
   308  	delete(d.networks, nid)
   309  	d.Unlock()
   310  
   311  	return nil
   312  }
   313  
   314  func convertQosPolicies(qosPolicies []types.QosPolicy) ([]json.RawMessage, error) {
   315  	var qps []json.RawMessage
   316  
   317  	// Enumerate through the qos policies specified by the user and convert
   318  	// them into the internal structure matching the JSON blob that can be
   319  	// understood by the HCS.
   320  	for _, elem := range qosPolicies {
   321  		encodedPolicy, err := json.Marshal(hcsshim.QosPolicy{
   322  			Type: "QOS",
   323  			MaximumOutgoingBandwidthInBytes: elem.MaxEgressBandwidth,
   324  		})
   325  
   326  		if err != nil {
   327  			return nil, err
   328  		}
   329  		qps = append(qps, encodedPolicy)
   330  	}
   331  	return qps, nil
   332  }
   333  
   334  func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) {
   335  	var pbs []json.RawMessage
   336  
   337  	// Enumerate through the port bindings specified by the user and convert
   338  	// them into the internal structure matching the JSON blob that can be
   339  	// understood by the HCS.
   340  	for _, elem := range portBindings {
   341  		proto := strings.ToUpper(elem.Proto.String())
   342  		if proto != "TCP" && proto != "UDP" {
   343  			return nil, fmt.Errorf("invalid protocol %s", elem.Proto.String())
   344  		}
   345  
   346  		if elem.HostPort != elem.HostPortEnd {
   347  			return nil, fmt.Errorf("Windows does not support more than one host port in NAT settings")
   348  		}
   349  
   350  		if len(elem.HostIP) != 0 {
   351  			return nil, fmt.Errorf("Windows does not support host IP addresses in NAT settings")
   352  		}
   353  
   354  		encodedPolicy, err := json.Marshal(hcsshim.NatPolicy{
   355  			Type:         "NAT",
   356  			ExternalPort: elem.HostPort,
   357  			InternalPort: elem.Port,
   358  			Protocol:     elem.Proto.String(),
   359  		})
   360  
   361  		if err != nil {
   362  			return nil, err
   363  		}
   364  		pbs = append(pbs, encodedPolicy)
   365  	}
   366  	return pbs, nil
   367  }
   368  
   369  func parsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) {
   370  	var bindings []types.PortBinding
   371  	hcsPolicy := &hcsshim.NatPolicy{}
   372  
   373  	for _, elem := range policies {
   374  
   375  		if err := json.Unmarshal([]byte(elem), &hcsPolicy); err != nil || hcsPolicy.Type != "NAT" {
   376  			continue
   377  		}
   378  
   379  		binding := types.PortBinding{
   380  			HostPort:    hcsPolicy.ExternalPort,
   381  			HostPortEnd: hcsPolicy.ExternalPort,
   382  			Port:        hcsPolicy.InternalPort,
   383  			Proto:       types.ParseProtocol(hcsPolicy.Protocol),
   384  			HostIP:      net.IPv4(0, 0, 0, 0),
   385  		}
   386  
   387  		bindings = append(bindings, binding)
   388  	}
   389  
   390  	return bindings, nil
   391  }
   392  
   393  func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) {
   394  	if epOptions == nil {
   395  		return nil, nil
   396  	}
   397  
   398  	ec := &endpointConfiguration{}
   399  
   400  	if opt, ok := epOptions[netlabel.MacAddress]; ok {
   401  		if mac, ok := opt.(net.HardwareAddr); ok {
   402  			ec.MacAddress = mac
   403  		} else {
   404  			return nil, fmt.Errorf("Invalid endpoint configuration")
   405  		}
   406  	}
   407  
   408  	if opt, ok := epOptions[netlabel.PortMap]; ok {
   409  		if bs, ok := opt.([]types.PortBinding); ok {
   410  			ec.PortBindings = bs
   411  		} else {
   412  			return nil, fmt.Errorf("Invalid endpoint configuration")
   413  		}
   414  	}
   415  
   416  	if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
   417  		if ports, ok := opt.([]types.TransportPort); ok {
   418  			ec.ExposedPorts = ports
   419  		} else {
   420  			return nil, fmt.Errorf("Invalid endpoint configuration")
   421  		}
   422  	}
   423  
   424  	if opt, ok := epOptions[QosPolicies]; ok {
   425  		if policies, ok := opt.([]types.QosPolicy); ok {
   426  			ec.QosPolicies = policies
   427  		} else {
   428  			return nil, fmt.Errorf("Invalid endpoint configuration")
   429  		}
   430  	}
   431  
   432  	if opt, ok := epOptions[netlabel.DNSServers]; ok {
   433  		if dns, ok := opt.([]string); ok {
   434  			ec.DNSServers = dns
   435  		} else {
   436  			return nil, fmt.Errorf("Invalid endpoint configuration")
   437  		}
   438  	}
   439  
   440  	return ec, nil
   441  }
   442  
   443  func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
   444  	n, err := d.getNetwork(nid)
   445  	if err != nil {
   446  		return err
   447  	}
   448  
   449  	// Check if endpoint id is good and retrieve corresponding endpoint
   450  	ep, err := n.getEndpoint(eid)
   451  	if err == nil && ep != nil {
   452  		return driverapi.ErrEndpointExists(eid)
   453  	}
   454  
   455  	endpointStruct := &hcsshim.HNSEndpoint{
   456  		VirtualNetwork: n.config.HnsID,
   457  	}
   458  
   459  	ec, err := parseEndpointOptions(epOptions)
   460  
   461  	macAddress := ifInfo.MacAddress()
   462  	// Use the macaddress if it was provided
   463  	if macAddress != nil {
   464  		endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1)
   465  	}
   466  
   467  	endpointStruct.Policies, err = convertPortBindings(ec.PortBindings)
   468  	if err != nil {
   469  		return err
   470  	}
   471  
   472  	qosPolicies, err := convertQosPolicies(ec.QosPolicies)
   473  	if err != nil {
   474  		return err
   475  	}
   476  	endpointStruct.Policies = append(endpointStruct.Policies, qosPolicies...)
   477  
   478  	if ifInfo.Address() != nil {
   479  		endpointStruct.IPAddress = ifInfo.Address().IP
   480  	}
   481  
   482  	endpointStruct.DNSServerList = strings.Join(ec.DNSServers, ",")
   483  
   484  	if n.driver.name == "nat" {
   485  		endpointStruct.EnableInternalDNS = true
   486  	}
   487  
   488  	configurationb, err := json.Marshal(endpointStruct)
   489  	if err != nil {
   490  		return err
   491  	}
   492  
   493  	hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb))
   494  	if err != nil {
   495  		return err
   496  	}
   497  
   498  	mac, err := net.ParseMAC(hnsresponse.MacAddress)
   499  	if err != nil {
   500  		return err
   501  	}
   502  
   503  	// TODO For now the ip mask is not in the info generated by HNS
   504  	endpoint := &hnsEndpoint{
   505  		id:         eid,
   506  		addr:       &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()},
   507  		macAddress: mac,
   508  	}
   509  
   510  	endpoint.profileID = hnsresponse.Id
   511  	endpoint.config = ec
   512  	endpoint.portMapping, err = parsePortBindingPolicies(hnsresponse.Policies)
   513  
   514  	if err != nil {
   515  		hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
   516  		return err
   517  	}
   518  
   519  	n.Lock()
   520  	n.endpoints[eid] = endpoint
   521  	n.Unlock()
   522  
   523  	if ifInfo.Address() == nil {
   524  		ifInfo.SetIPAddress(endpoint.addr)
   525  	}
   526  
   527  	if macAddress == nil {
   528  		ifInfo.SetMacAddress(endpoint.macAddress)
   529  	}
   530  
   531  	return nil
   532  }
   533  
   534  func (d *driver) DeleteEndpoint(nid, eid string) error {
   535  	n, err := d.getNetwork(nid)
   536  	if err != nil {
   537  		return types.InternalMaskableErrorf("%s", err)
   538  	}
   539  
   540  	ep, err := n.getEndpoint(eid)
   541  	if err != nil {
   542  		return err
   543  	}
   544  
   545  	n.Lock()
   546  	delete(n.endpoints, eid)
   547  	n.Unlock()
   548  
   549  	_, err = hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
   550  	if err != nil {
   551  		return err
   552  	}
   553  
   554  	return nil
   555  }
   556  
   557  func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
   558  	network, err := d.getNetwork(nid)
   559  	if err != nil {
   560  		return nil, err
   561  	}
   562  
   563  	ep, err := network.getEndpoint(eid)
   564  	if err != nil {
   565  		return nil, err
   566  	}
   567  
   568  	data := make(map[string]interface{}, 1)
   569  	if network.driver.name == "nat" {
   570  		data["AllowUnqualifiedDNSQuery"] = true
   571  	}
   572  
   573  	data["hnsid"] = ep.profileID
   574  	if ep.config.ExposedPorts != nil {
   575  		// Return a copy of the config data
   576  		epc := make([]types.TransportPort, 0, len(ep.config.ExposedPorts))
   577  		for _, tp := range ep.config.ExposedPorts {
   578  			epc = append(epc, tp.GetCopy())
   579  		}
   580  		data[netlabel.ExposedPorts] = epc
   581  	}
   582  
   583  	if ep.portMapping != nil {
   584  		// Return a copy of the operational data
   585  		pmc := make([]types.PortBinding, 0, len(ep.portMapping))
   586  		for _, pm := range ep.portMapping {
   587  			pmc = append(pmc, pm.GetCopy())
   588  		}
   589  		data[netlabel.PortMap] = pmc
   590  	}
   591  
   592  	if len(ep.macAddress) != 0 {
   593  		data[netlabel.MacAddress] = ep.macAddress
   594  	}
   595  	return data, nil
   596  }
   597  
   598  // Join method is invoked when a Sandbox is attached to an endpoint.
   599  func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
   600  	network, err := d.getNetwork(nid)
   601  	if err != nil {
   602  		return err
   603  	}
   604  
   605  	// Ensure that the endpoint exists
   606  	_, err = network.getEndpoint(eid)
   607  	if err != nil {
   608  		return err
   609  	}
   610  
   611  	// This is just a stub for now
   612  
   613  	jinfo.DisableGatewayService()
   614  	return nil
   615  }
   616  
   617  // Leave method is invoked when a Sandbox detaches from an endpoint.
   618  func (d *driver) Leave(nid, eid string) error {
   619  	network, err := d.getNetwork(nid)
   620  	if err != nil {
   621  		return types.InternalMaskableErrorf("%s", err)
   622  	}
   623  
   624  	// Ensure that the endpoint exists
   625  	_, err = network.getEndpoint(eid)
   626  	if err != nil {
   627  		return err
   628  	}
   629  
   630  	// This is just a stub for now
   631  
   632  	return nil
   633  }
   634  
   635  func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
   636  	return nil
   637  }
   638  
   639  func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
   640  	return nil
   641  }
   642  
   643  func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
   644  	return nil, types.NotImplementedErrorf("not implemented")
   645  }
   646  
   647  func (d *driver) NetworkFree(id string) error {
   648  	return types.NotImplementedErrorf("not implemented")
   649  }
   650  
   651  func (d *driver) Type() string {
   652  	return d.name
   653  }
   654  
   655  // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
   656  func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
   657  	return nil
   658  }
   659  
   660  // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
   661  func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
   662  	return nil
   663  }