in plugins/vpc-shared-eni/network/bridge_windows.go [129:272]
func (nb *BridgeBuilder) FindOrCreateEndpoint(nw *Network, ep *Endpoint) error {
// This plugin does not yet support IPv6, or multiple IPv4 addresses.
if len(ep.IPAddresses) > 1 || ep.IPAddresses[0].IP.To4() == nil {
return fmt.Errorf("Only a single IPv4 address per endpoint is supported on Windows")
}
// Query the infrastructure container ID.
isInfraContainer, infraContainerID, err := nb.getInfraContainerID(ep)
if err != nil {
return err
}
// Check if the endpoint already exists.
endpointName := nb.generateHNSEndpointName(ep, infraContainerID)
hnsEndpoint, err := hcsshim.GetHNSEndpointByName(endpointName)
if err == nil {
log.Infof("Found existing HNS endpoint %s.", endpointName)
if isInfraContainer {
// This is a benign duplicate create call for an existing endpoint.
// The endpoint was already attached in a previous call. Ignore and return success.
log.Infof("HNS endpoint %s is already attached to container ID %s.",
endpointName, ep.ContainerID)
} else {
// Attach the existing endpoint to the container's network namespace.
err = nb.attachEndpoint(hnsEndpoint, ep.ContainerID)
}
ep.MACAddress, _ = net.ParseMAC(hnsEndpoint.MacAddress)
return err
} else {
if !isInfraContainer {
// The endpoint referenced in the container netns does not exist.
log.Errorf("Failed to find endpoint %s for container %s.", endpointName, ep.ContainerID)
return fmt.Errorf("failed to find endpoint %s: %v", endpointName, err)
}
}
// Initialize the HNS endpoint.
hnsEndpoint = &hcsshim.HNSEndpoint{
Name: endpointName,
VirtualNetworkName: nb.generateHNSNetworkName(nw),
DNSSuffix: strings.Join(nw.DNSSuffixSearchList, ","),
DNSServerList: strings.Join(nw.DNSServers, ","),
}
// Set the endpoint IP address.
hnsEndpoint.IPAddress = ep.IPAddresses[0].IP
pl, _ := ep.IPAddresses[0].Mask.Size()
hnsEndpoint.PrefixLength = uint8(pl)
// SNAT endpoint traffic to ENI primary IP address...
var snatExceptions []string
if nw.VPCCIDRs == nil {
// ...except if the destination is in the same subnet as the ENI.
snatExceptions = []string{vpc.GetSubnetPrefix(&nw.ENIIPAddresses[0]).String()}
} else {
// ...or, if known, the same VPC.
for _, cidr := range nw.VPCCIDRs {
snatExceptions = append(snatExceptions, cidr.String())
}
}
if nw.ServiceCIDR != "" {
// ...or the destination is a service endpoint.
snatExceptions = append(snatExceptions, nw.ServiceCIDR)
}
err = nb.addEndpointPolicy(
hnsEndpoint,
hcsshim.OutboundNatPolicy{
Policy: hcsshim.Policy{Type: hcsshim.OutboundNat},
// Implicit VIP: nw.ENIIPAddresses[0].IP.String(),
Exceptions: snatExceptions,
})
if err != nil {
log.Errorf("Failed to add endpoint SNAT policy: %v.", err)
return err
}
// Route traffic sent to service endpoints to the host. The load balancer running
// in the host network namespace then forwards traffic to its final destination.
if nw.ServiceCIDR != "" {
// Set route policy for service subnet.
// NextHop is implicitly the host.
err = nb.addEndpointPolicy(
hnsEndpoint,
hnsRoutePolicy{
Policy: hcsshim.Policy{Type: hcsshim.Route},
DestinationPrefix: nw.ServiceCIDR,
NeedEncap: true,
})
if err != nil {
log.Errorf("Failed to add endpoint route policy for service subnet: %v.", err)
return err
}
// Set route policy for host primary IP address.
err = nb.addEndpointPolicy(
hnsEndpoint,
hnsRoutePolicy{
Policy: hcsshim.Policy{Type: hcsshim.Route},
DestinationPrefix: nw.ENIIPAddresses[0].IP.String() + "/32",
NeedEncap: true,
})
if err != nil {
log.Errorf("Failed to add endpoint route policy for host: %v.", err)
return err
}
}
// Encode the endpoint request.
buf, err := json.Marshal(hnsEndpoint)
if err != nil {
return err
}
hnsRequest := string(buf)
// Create the HNS endpoint.
log.Infof("Creating HNS endpoint: %+v", hnsRequest)
hnsResponse, err := hcsshim.HNSEndpointRequest("POST", "", hnsRequest)
if err != nil {
log.Errorf("Failed to create HNS endpoint: %v.", err)
return err
}
log.Infof("Received HNS endpoint response: %+v.", hnsResponse)
// Attach the HNS endpoint to the container's network namespace.
err = nb.attachEndpoint(hnsResponse, ep.ContainerID)
if err != nil {
// Cleanup the failed endpoint.
log.Infof("Deleting the failed HNS endpoint %s.", hnsResponse.Id)
_, delErr := hcsshim.HNSEndpointRequest("DELETE", hnsResponse.Id, "")
if delErr != nil {
log.Errorf("Failed to delete HNS endpoint: %v.", delErr)
}
return err
}
// Return network interface MAC address.
ep.MACAddress, _ = net.ParseMAC(hnsResponse.MacAddress)
return nil
}