github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/drivers/windows/overlay/ov_endpoint_windows.go (about) 1 package overlay 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net" 8 "sync" 9 10 "github.com/Microsoft/hcsshim" 11 "github.com/Microsoft/hcsshim/osversion" 12 "github.com/containerd/log" 13 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/driverapi" 14 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/drivers/windows" 15 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/netlabel" 16 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/types" 17 ) 18 19 type endpointTable map[string]*endpoint 20 21 const overlayEndpointPrefix = "overlay/endpoint" 22 23 type endpoint struct { 24 id string 25 nid string 26 profileID string 27 remote bool 28 mac net.HardwareAddr 29 addr *net.IPNet 30 disablegateway bool 31 portMapping []types.PortBinding // Operation port bindings 32 } 33 34 var ( 35 // Server 2016 (RS1) does not support concurrent add/delete of endpoints. Therefore, we need 36 // to use this mutex and serialize the add/delete of endpoints on RS1. 37 endpointMu sync.Mutex 38 windowsBuild = osversion.Build() 39 ) 40 41 func validateID(nid, eid string) error { 42 if nid == "" { 43 return fmt.Errorf("invalid network id") 44 } 45 46 if eid == "" { 47 return fmt.Errorf("invalid endpoint id") 48 } 49 50 return nil 51 } 52 53 func (n *network) endpoint(eid string) *endpoint { 54 n.Lock() 55 defer n.Unlock() 56 57 return n.endpoints[eid] 58 } 59 60 func (n *network) addEndpoint(ep *endpoint) { 61 n.Lock() 62 n.endpoints[ep.id] = ep 63 n.Unlock() 64 } 65 66 func (n *network) deleteEndpoint(eid string) { 67 n.Lock() 68 delete(n.endpoints, eid) 69 n.Unlock() 70 } 71 72 func (n *network) removeEndpointWithAddress(addr *net.IPNet) { 73 var networkEndpoint *endpoint 74 n.Lock() 75 for _, ep := range n.endpoints { 76 if ep.addr.IP.Equal(addr.IP) { 77 networkEndpoint = ep 78 break 79 } 80 } 81 82 if networkEndpoint != nil { 83 delete(n.endpoints, networkEndpoint.id) 84 } 85 n.Unlock() 86 87 if networkEndpoint != nil { 88 log.G(context.TODO()).Debugf("Removing stale endpoint from HNS") 89 _, err := endpointRequest("DELETE", networkEndpoint.profileID, "") 90 if err != nil { 91 log.G(context.TODO()).Debugf("Failed to delete stale overlay endpoint (%.7s) from hns", networkEndpoint.id) 92 } 93 } 94 } 95 96 func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, 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 log.G(context.TODO()).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 if err != nil { 152 return err 153 } 154 155 hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy) 156 157 natPolicy, err := json.Marshal(hcsshim.PaPolicy{Type: "OutBoundNAT"}) 158 if err != nil { 159 return err 160 } 161 162 hnsEndpoint.Policies = append(hnsEndpoint.Policies, natPolicy) 163 164 epConnectivity, err := windows.ParseEndpointConnectivity(epOptions) 165 if err != nil { 166 return err 167 } 168 169 ep.portMapping = epConnectivity.PortBindings 170 ep.portMapping, err = windows.AllocatePorts(n.portMapper, ep.portMapping, ep.addr.IP) 171 if err != nil { 172 return err 173 } 174 175 defer func() { 176 if err != nil { 177 windows.ReleasePorts(n.portMapper, ep.portMapping) 178 } 179 }() 180 181 pbPolicy, err := windows.ConvertPortBindings(ep.portMapping) 182 if err != nil { 183 return err 184 } 185 hnsEndpoint.Policies = append(hnsEndpoint.Policies, pbPolicy...) 186 187 ep.disablegateway = true 188 189 configurationb, err := json.Marshal(hnsEndpoint) 190 if err != nil { 191 return err 192 } 193 194 hnsresponse, err := endpointRequest("POST", "", string(configurationb)) 195 if err != nil { 196 return err 197 } 198 199 ep.profileID = hnsresponse.Id 200 201 if ep.mac == nil { 202 ep.mac, err = net.ParseMAC(hnsresponse.MacAddress) 203 if err != nil { 204 return err 205 } 206 207 if err := ifInfo.SetMacAddress(ep.mac); err != nil { 208 return err 209 } 210 } 211 212 ep.portMapping, err = windows.ParsePortBindingPolicies(hnsresponse.Policies) 213 if err != nil { 214 endpointRequest("DELETE", hnsresponse.Id, "") 215 return err 216 } 217 218 n.addEndpoint(ep) 219 220 return nil 221 } 222 223 func (d *driver) DeleteEndpoint(nid, eid string) error { 224 if err := validateID(nid, eid); err != nil { 225 return err 226 } 227 228 n := d.network(nid) 229 if n == nil { 230 return fmt.Errorf("network id %q not found", nid) 231 } 232 233 ep := n.endpoint(eid) 234 if ep == nil { 235 return fmt.Errorf("endpoint id %q not found", eid) 236 } 237 238 windows.ReleasePorts(n.portMapper, ep.portMapping) 239 240 n.deleteEndpoint(eid) 241 242 _, err := endpointRequest("DELETE", ep.profileID, "") 243 if err != nil { 244 return err 245 } 246 247 return nil 248 } 249 250 func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) { 251 if err := validateID(nid, eid); err != nil { 252 return nil, err 253 } 254 255 n := d.network(nid) 256 if n == nil { 257 return nil, fmt.Errorf("network id %q not found", nid) 258 } 259 260 ep := n.endpoint(eid) 261 if ep == nil { 262 return nil, fmt.Errorf("endpoint id %q not found", eid) 263 } 264 265 data := make(map[string]interface{}, 1) 266 data["hnsid"] = ep.profileID 267 data["AllowUnqualifiedDNSQuery"] = true 268 269 if ep.portMapping != nil { 270 // Return a copy of the operational data 271 pmc := make([]types.PortBinding, 0, len(ep.portMapping)) 272 for _, pm := range ep.portMapping { 273 pmc = append(pmc, pm.GetCopy()) 274 } 275 data[netlabel.PortMap] = pmc 276 } 277 278 return data, nil 279 } 280 281 func endpointRequest(method, path, request string) (*hcsshim.HNSEndpoint, error) { 282 if windowsBuild == 14393 { 283 endpointMu.Lock() 284 } 285 hnsresponse, err := hcsshim.HNSEndpointRequest(method, path, request) 286 if windowsBuild == 14393 { 287 endpointMu.Unlock() 288 } 289 return hnsresponse, err 290 }