github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/drivers/windows/overlay/ov_network_windows.go (about) 1 package overlay 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net" 8 "strconv" 9 "strings" 10 "sync" 11 12 "github.com/Microsoft/hcsshim" 13 "github.com/containerd/log" 14 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/driverapi" 15 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/netlabel" 16 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/portmapper" 17 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/types" 18 ) 19 20 var ( 21 hostMode bool 22 networkMu sync.Mutex 23 ) 24 25 type networkTable map[string]*network 26 27 type subnet struct { 28 vni uint32 29 subnetIP *net.IPNet 30 gwIP *net.IP 31 } 32 33 type subnetJSON struct { 34 SubnetIP string 35 GwIP string 36 Vni uint32 37 } 38 39 type network struct { 40 id string 41 name string 42 hnsID string 43 providerAddress string 44 interfaceName string 45 endpoints endpointTable 46 driver *driver 47 initEpoch int 48 initErr error 49 subnets []*subnet 50 secure bool 51 portMapper *portmapper.PortMapper 52 sync.Mutex 53 } 54 55 func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) { 56 return nil, types.NotImplementedErrorf("not implemented") 57 } 58 59 func (d *driver) NetworkFree(id string) error { 60 return types.NotImplementedErrorf("not implemented") 61 } 62 63 func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { 64 var ( 65 networkName string 66 interfaceName string 67 staleNetworks []string 68 ) 69 70 if id == "" { 71 return fmt.Errorf("invalid network id") 72 } 73 74 if nInfo == nil { 75 return fmt.Errorf("invalid network info structure") 76 } 77 78 if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" { 79 return types.InvalidParameterErrorf("ipv4 pool is empty") 80 } 81 82 staleNetworks = make([]string, 0) 83 vnis := make([]uint32, 0, len(ipV4Data)) 84 85 existingNetwork := d.network(id) 86 if existingNetwork != nil { 87 log.G(context.TODO()).Debugf("Network preexists. Deleting %s", id) 88 err := d.DeleteNetwork(id) 89 if err != nil { 90 log.G(context.TODO()).Errorf("Error deleting stale network %s", err.Error()) 91 } 92 } 93 94 n := &network{ 95 id: id, 96 driver: d, 97 endpoints: endpointTable{}, 98 subnets: []*subnet{}, 99 portMapper: portmapper.New(), 100 } 101 102 genData, ok := option[netlabel.GenericData].(map[string]string) 103 104 if !ok { 105 return fmt.Errorf("Unknown generic data option") 106 } 107 108 for label, value := range genData { 109 switch label { 110 case "com.docker.network.windowsshim.networkname": 111 networkName = value 112 case "com.docker.network.windowsshim.interface": 113 interfaceName = value 114 case "com.docker.network.windowsshim.hnsid": 115 n.hnsID = value 116 case netlabel.OverlayVxlanIDList: 117 vniStrings := strings.Split(value, ",") 118 for _, vniStr := range vniStrings { 119 vni, err := strconv.Atoi(vniStr) 120 if err != nil { 121 return fmt.Errorf("invalid vxlan id value %q passed", vniStr) 122 } 123 124 vnis = append(vnis, uint32(vni)) 125 } 126 } 127 } 128 129 // If we are getting vnis from libnetwork, either we get for 130 // all subnets or none. 131 if len(vnis) < len(ipV4Data) { 132 return fmt.Errorf("insufficient vnis(%d) passed to overlay. Windows driver requires VNIs to be prepopulated", len(vnis)) 133 } 134 135 for i, ipd := range ipV4Data { 136 s := &subnet{ 137 subnetIP: ipd.Pool, 138 gwIP: &ipd.Gateway.IP, 139 } 140 141 if len(vnis) != 0 { 142 s.vni = vnis[i] 143 } 144 145 d.Lock() 146 for _, network := range d.networks { 147 found := false 148 for _, sub := range network.subnets { 149 if sub.vni == s.vni { 150 staleNetworks = append(staleNetworks, network.id) 151 found = true 152 break 153 } 154 } 155 if found { 156 break 157 } 158 } 159 d.Unlock() 160 161 n.subnets = append(n.subnets, s) 162 } 163 164 for _, staleNetwork := range staleNetworks { 165 d.DeleteNetwork(staleNetwork) 166 } 167 168 n.name = networkName 169 if n.name == "" { 170 n.name = id 171 } 172 173 n.interfaceName = interfaceName 174 175 if nInfo != nil { 176 if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil { 177 return err 178 } 179 } 180 181 d.addNetwork(n) 182 183 err := d.createHnsNetwork(n) 184 185 if err != nil { 186 d.deleteNetwork(id) 187 } else { 188 genData["com.docker.network.windowsshim.hnsid"] = n.hnsID 189 } 190 191 return err 192 } 193 194 func (d *driver) DeleteNetwork(nid string) error { 195 if nid == "" { 196 return fmt.Errorf("invalid network id") 197 } 198 199 n := d.network(nid) 200 if n == nil { 201 return types.ForbiddenErrorf("could not find network with id %s", nid) 202 } 203 204 _, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsID, "") 205 if err != nil { 206 return types.ForbiddenErrorf(err.Error()) 207 } 208 209 d.deleteNetwork(nid) 210 211 return nil 212 } 213 214 func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error { 215 return nil 216 } 217 218 func (d *driver) RevokeExternalConnectivity(nid, eid string) error { 219 return nil 220 } 221 222 func (d *driver) addNetwork(n *network) { 223 d.Lock() 224 d.networks[n.id] = n 225 d.Unlock() 226 } 227 228 func (d *driver) deleteNetwork(nid string) { 229 d.Lock() 230 delete(d.networks, nid) 231 d.Unlock() 232 } 233 234 func (d *driver) network(nid string) *network { 235 d.Lock() 236 defer d.Unlock() 237 return d.networks[nid] 238 } 239 240 // func (n *network) restoreNetworkEndpoints() error { 241 // log.G(ctx).Infof("Restoring endpoints for overlay network: %s", n.id) 242 243 // hnsresponse, err := hcsshim.HNSListEndpointRequest("GET", "", "") 244 // if err != nil { 245 // return err 246 // } 247 248 // for _, endpoint := range hnsresponse { 249 // if endpoint.VirtualNetwork != n.hnsID { 250 // continue 251 // } 252 253 // ep := n.convertToOverlayEndpoint(&endpoint) 254 255 // if ep != nil { 256 // log.G(ctx).Debugf("Restored endpoint:%s Remote:%t", ep.id, ep.remote) 257 // n.addEndpoint(ep) 258 // } 259 // } 260 261 // return nil 262 // } 263 264 func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint { 265 ep := &endpoint{ 266 id: v.Name, 267 profileID: v.Id, 268 nid: n.id, 269 remote: v.IsRemoteEndpoint, 270 } 271 272 mac, err := net.ParseMAC(v.MacAddress) 273 if err != nil { 274 return nil 275 } 276 277 ep.mac = mac 278 ep.addr = &net.IPNet{ 279 IP: v.IPAddress, 280 Mask: net.CIDRMask(32, 32), 281 } 282 283 return ep 284 } 285 286 func (d *driver) createHnsNetwork(n *network) error { 287 subnets := []hcsshim.Subnet{} 288 289 for _, s := range n.subnets { 290 subnet := hcsshim.Subnet{ 291 AddressPrefix: s.subnetIP.String(), 292 } 293 294 if s.gwIP != nil { 295 subnet.GatewayAddress = s.gwIP.String() 296 } 297 298 vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{ 299 Type: "VSID", 300 VSID: uint(s.vni), 301 }) 302 if err != nil { 303 return err 304 } 305 306 subnet.Policies = append(subnet.Policies, vsidPolicy) 307 subnets = append(subnets, subnet) 308 } 309 310 network := &hcsshim.HNSNetwork{ 311 Name: n.name, 312 Type: d.Type(), 313 Subnets: subnets, 314 NetworkAdapterName: n.interfaceName, 315 AutomaticDNS: true, 316 } 317 318 configurationb, err := json.Marshal(network) 319 if err != nil { 320 return err 321 } 322 323 configuration := string(configurationb) 324 log.G(context.TODO()).Infof("HNSNetwork Request =%v", configuration) 325 326 hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration) 327 if err != nil { 328 return err 329 } 330 331 n.hnsID = hnsresponse.Id 332 n.providerAddress = hnsresponse.ManagementIP 333 334 return nil 335 } 336 337 // contains return true if the passed ip belongs to one the network's 338 // subnets 339 func (n *network) contains(ip net.IP) bool { 340 for _, s := range n.subnets { 341 if s.subnetIP.Contains(ip) { 342 return true 343 } 344 } 345 346 return false 347 } 348 349 // getSubnetforIP returns the subnet to which the given IP belongs 350 func (n *network) getSubnetforIP(ip *net.IPNet) *subnet { 351 for _, s := range n.subnets { 352 // first check if the mask lengths are the same 353 i, _ := s.subnetIP.Mask.Size() 354 j, _ := ip.Mask.Size() 355 if i != j { 356 continue 357 } 358 if s.subnetIP.Contains(ip.IP) { 359 return s 360 } 361 } 362 return nil 363 } 364 365 // getMatchingSubnet return the network's subnet that matches the input 366 func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet { 367 if ip == nil { 368 return nil 369 } 370 for _, s := range n.subnets { 371 // first check if the mask lengths are the same 372 i, _ := s.subnetIP.Mask.Size() 373 j, _ := ip.Mask.Size() 374 if i != j { 375 continue 376 } 377 if s.subnetIP.IP.Equal(ip.IP) { 378 return s 379 } 380 } 381 return nil 382 }