github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/drivers/windows/overlay/ov_endpoint_windows.go (about)

     1  package overlay
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net"
     7  	"sync"
     8  
     9  	"github.com/Microsoft/hcsshim"
    10  	"github.com/Microsoft/hcsshim/osversion"
    11  	"github.com/docker/docker/libnetwork/driverapi"
    12  	"github.com/docker/docker/libnetwork/drivers/windows"
    13  	"github.com/docker/docker/libnetwork/netlabel"
    14  	"github.com/docker/docker/libnetwork/types"
    15  	"github.com/sirupsen/logrus"
    16  )
    17  
    18  type endpointTable map[string]*endpoint
    19  
    20  const overlayEndpointPrefix = "overlay/endpoint"
    21  
    22  type endpoint struct {
    23  	id             string
    24  	nid            string
    25  	profileID      string
    26  	remote         bool
    27  	mac            net.HardwareAddr
    28  	addr           *net.IPNet
    29  	disablegateway bool
    30  	portMapping    []types.PortBinding // Operation port bindings
    31  }
    32  
    33  var (
    34  	//Server 2016 (RS1) does not support concurrent add/delete of endpoints.  Therefore, we need
    35  	//to use this mutex and serialize the add/delete of endpoints on RS1.
    36  	endpointMu   sync.Mutex
    37  	windowsBuild = osversion.Build()
    38  )
    39  
    40  func validateID(nid, eid string) error {
    41  	if nid == "" {
    42  		return fmt.Errorf("invalid network id")
    43  	}
    44  
    45  	if eid == "" {
    46  		return fmt.Errorf("invalid endpoint id")
    47  	}
    48  
    49  	return nil
    50  }
    51  
    52  func (n *network) endpoint(eid string) *endpoint {
    53  	n.Lock()
    54  	defer n.Unlock()
    55  
    56  	return n.endpoints[eid]
    57  }
    58  
    59  func (n *network) addEndpoint(ep *endpoint) {
    60  	n.Lock()
    61  	n.endpoints[ep.id] = ep
    62  	n.Unlock()
    63  }
    64  
    65  func (n *network) deleteEndpoint(eid string) {
    66  	n.Lock()
    67  	delete(n.endpoints, eid)
    68  	n.Unlock()
    69  }
    70  
    71  func (n *network) removeEndpointWithAddress(addr *net.IPNet) {
    72  	var networkEndpoint *endpoint
    73  	n.Lock()
    74  	for _, ep := range n.endpoints {
    75  		if ep.addr.IP.Equal(addr.IP) {
    76  			networkEndpoint = ep
    77  			break
    78  		}
    79  	}
    80  
    81  	if networkEndpoint != nil {
    82  		delete(n.endpoints, networkEndpoint.id)
    83  	}
    84  	n.Unlock()
    85  
    86  	if networkEndpoint != nil {
    87  		logrus.Debugf("Removing stale endpoint from HNS")
    88  		_, err := endpointRequest("DELETE", networkEndpoint.profileID, "")
    89  		if err != nil {
    90  			logrus.Debugf("Failed to delete stale overlay endpoint (%.7s) from hns", networkEndpoint.id)
    91  		}
    92  	}
    93  }
    94  
    95  func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
    96  	epOptions map[string]interface{}) error {
    97  	var err error
    98  	if err = validateID(nid, eid); err != nil {
    99  		return err
   100  	}
   101  
   102  	n := d.network(nid)
   103  	if n == nil {
   104  		return fmt.Errorf("network id %q not found", nid)
   105  	}
   106  
   107  	ep := n.endpoint(eid)
   108  	if ep != nil {
   109  		logrus.Debugf("Deleting stale endpoint %s", eid)
   110  		n.deleteEndpoint(eid)
   111  		_, err := endpointRequest("DELETE", ep.profileID, "")
   112  		if err != nil {
   113  			return err
   114  		}
   115  	}
   116  
   117  	ep = &endpoint{
   118  		id:   eid,
   119  		nid:  n.id,
   120  		addr: ifInfo.Address(),
   121  		mac:  ifInfo.MacAddress(),
   122  	}
   123  
   124  	if ep.addr == nil {
   125  		return fmt.Errorf("create endpoint was not passed interface IP address")
   126  	}
   127  
   128  	s := n.getSubnetforIP(ep.addr)
   129  	if s == nil {
   130  		return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
   131  	}
   132  
   133  	// Todo: Add port bindings and qos policies here
   134  
   135  	hnsEndpoint := &hcsshim.HNSEndpoint{
   136  		Name:              eid,
   137  		VirtualNetwork:    n.hnsID,
   138  		IPAddress:         ep.addr.IP,
   139  		EnableInternalDNS: true,
   140  		GatewayAddress:    s.gwIP.String(),
   141  	}
   142  
   143  	if ep.mac != nil {
   144  		hnsEndpoint.MacAddress = ep.mac.String()
   145  	}
   146  
   147  	paPolicy, err := json.Marshal(hcsshim.PaPolicy{
   148  		Type: "PA",
   149  		PA:   n.providerAddress,
   150  	})
   151  
   152  	if err != nil {
   153  		return err
   154  	}
   155  
   156  	hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy)
   157  
   158  	natPolicy, err := json.Marshal(hcsshim.PaPolicy{
   159  		Type: "OutBoundNAT",
   160  	})
   161  
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	hnsEndpoint.Policies = append(hnsEndpoint.Policies, natPolicy)
   167  
   168  	epConnectivity, err := windows.ParseEndpointConnectivity(epOptions)
   169  	if err != nil {
   170  		return err
   171  	}
   172  
   173  	ep.portMapping = epConnectivity.PortBindings
   174  	ep.portMapping, err = windows.AllocatePorts(n.portMapper, ep.portMapping, ep.addr.IP)
   175  	if err != nil {
   176  		return err
   177  	}
   178  
   179  	defer func() {
   180  		if err != nil {
   181  			windows.ReleasePorts(n.portMapper, ep.portMapping)
   182  		}
   183  	}()
   184  
   185  	pbPolicy, err := windows.ConvertPortBindings(ep.portMapping)
   186  	if err != nil {
   187  		return err
   188  	}
   189  	hnsEndpoint.Policies = append(hnsEndpoint.Policies, pbPolicy...)
   190  
   191  	ep.disablegateway = true
   192  
   193  	configurationb, err := json.Marshal(hnsEndpoint)
   194  	if err != nil {
   195  		return err
   196  	}
   197  
   198  	hnsresponse, err := endpointRequest("POST", "", string(configurationb))
   199  	if err != nil {
   200  		return err
   201  	}
   202  
   203  	ep.profileID = hnsresponse.Id
   204  
   205  	if ep.mac == nil {
   206  		ep.mac, err = net.ParseMAC(hnsresponse.MacAddress)
   207  		if err != nil {
   208  			return err
   209  		}
   210  
   211  		if err := ifInfo.SetMacAddress(ep.mac); err != nil {
   212  			return err
   213  		}
   214  	}
   215  
   216  	ep.portMapping, err = windows.ParsePortBindingPolicies(hnsresponse.Policies)
   217  	if err != nil {
   218  		endpointRequest("DELETE", hnsresponse.Id, "")
   219  		return err
   220  	}
   221  
   222  	n.addEndpoint(ep)
   223  
   224  	return nil
   225  }
   226  
   227  func (d *driver) DeleteEndpoint(nid, eid string) error {
   228  	if err := validateID(nid, eid); err != nil {
   229  		return err
   230  	}
   231  
   232  	n := d.network(nid)
   233  	if n == nil {
   234  		return fmt.Errorf("network id %q not found", nid)
   235  	}
   236  
   237  	ep := n.endpoint(eid)
   238  	if ep == nil {
   239  		return fmt.Errorf("endpoint id %q not found", eid)
   240  	}
   241  
   242  	windows.ReleasePorts(n.portMapper, ep.portMapping)
   243  
   244  	n.deleteEndpoint(eid)
   245  
   246  	_, err := endpointRequest("DELETE", ep.profileID, "")
   247  	if err != nil {
   248  		return err
   249  	}
   250  
   251  	return nil
   252  }
   253  
   254  func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
   255  	if err := validateID(nid, eid); err != nil {
   256  		return nil, err
   257  	}
   258  
   259  	n := d.network(nid)
   260  	if n == nil {
   261  		return nil, fmt.Errorf("network id %q not found", nid)
   262  	}
   263  
   264  	ep := n.endpoint(eid)
   265  	if ep == nil {
   266  		return nil, fmt.Errorf("endpoint id %q not found", eid)
   267  	}
   268  
   269  	data := make(map[string]interface{}, 1)
   270  	data["hnsid"] = ep.profileID
   271  	data["AllowUnqualifiedDNSQuery"] = true
   272  
   273  	if ep.portMapping != nil {
   274  		// Return a copy of the operational data
   275  		pmc := make([]types.PortBinding, 0, len(ep.portMapping))
   276  		for _, pm := range ep.portMapping {
   277  			pmc = append(pmc, pm.GetCopy())
   278  		}
   279  		data[netlabel.PortMap] = pmc
   280  	}
   281  
   282  	return data, nil
   283  }
   284  
   285  func endpointRequest(method, path, request string) (*hcsshim.HNSEndpoint, error) {
   286  	if windowsBuild == 14393 {
   287  		endpointMu.Lock()
   288  	}
   289  	hnsresponse, err := hcsshim.HNSEndpointRequest(method, path, request)
   290  	if windowsBuild == 14393 {
   291  		endpointMu.Unlock()
   292  	}
   293  	return hnsresponse, err
   294  }