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 }