func getIPRange(nwCfg *mastercfg.CfgNetworkState, startIdx, endIdx uint) string { startAddress, err := netutils.GetSubnetIP(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, startIdx) if err != nil { log.Errorf("GetAllocatedIPs: getting ipAddress for idx %d: %s", startIdx, err) startAddress = "" } if startIdx == endIdx { return startAddress } endAddress, err := netutils.GetSubnetIP(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, endIdx) if err != nil { log.Errorf("GetAllocatedIPs: getting ipAddress for idx %d: %s", endIdx, err) endAddress = "" } return startAddress + "-" + endAddress }
// Allocate a new subnet. Returns an interface{} which for this method is always // SubnetIPLenPair. func (r *AutoSubnetCfgResource) Allocate() (interface{}, error) { oper := &AutoSubnetOperResource{} oper.StateDriver = r.StateDriver err := oper.Read(r.ID) if err != nil { return nil, err } subnet, ok := oper.FreeSubnets.NextSet(0) if !ok { return nil, core.Errorf("no subnets available.") } oper.FreeSubnets.Clear(subnet) var subnetIP string subnetIP, err = netutils.GetSubnetIP(r.SubnetPool.String(), r.SubnetPoolLen, r.AllocSubnetLen, subnet) if err != nil { return nil, err } pair := SubnetIPLenPair{IP: net.ParseIP(subnetIP), Len: r.AllocSubnetLen} err = oper.Write() if err != nil { return nil, err } return pair, nil }
// Allocate an address from the network func networkAllocAddress(nwCfg *mastercfg.CfgNetworkState, reqAddr string) (string, error) { var ipAddress string var ipAddrValue uint var found bool var err error // alloc address if reqAddr == "" { ipAddrValue, found = nwCfg.IPAllocMap.NextClear(0) if !found { log.Errorf("auto allocation failed - address exhaustion in subnet %s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) err = core.Errorf("auto allocation failed - address exhaustion in subnet %s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) return "", err } ipAddress, err = netutils.GetSubnetIP(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, ipAddrValue) if err != nil { log.Errorf("create eps: error acquiring subnet ip. Error: %s", err) return "", err } // Docker, Mesos issue a Alloc Address first, followed by a CreateEndpoint // Kubernetes issues a create endpoint directly // since networkAllocAddress is called from both AllocAddressHandler and CreateEndpointHandler, // we need to make sure that the EpCount is incremented only when we are allocating // a new IP. In case of Docker, Mesos CreateEndPoint will already request a IP that // allocateAddress had allocated in the earlier call. nwCfg.EpAddrCount++ } else if reqAddr != "" && nwCfg.SubnetIP != "" { ipAddrValue, err = netutils.GetIPNumber(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, reqAddr) if err != nil { log.Errorf("create eps: error getting host id from hostIP %s Subnet %s/%d. Error: %s", reqAddr, nwCfg.SubnetIP, nwCfg.SubnetLen, err) return "", err } ipAddress = reqAddr } // Set the bitmap nwCfg.IPAllocMap.Set(ipAddrValue) err = nwCfg.Write() if err != nil { log.Errorf("error writing nw config. Error: %s", err) return "", err } return ipAddress, nil }
// Allocate an address from the network func networkAllocAddress(nwCfg *mastercfg.CfgNetworkState, reqAddr string) (string, error) { var ipAddress string var ipAddrValue uint var found bool var err error // alloc address if reqAddr == "" { ipAddrValue, found = nwCfg.IPAllocMap.NextClear(0) if !found { log.Errorf("auto allocation failed - address exhaustion in subnet %s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) err = core.Errorf("auto allocation failed - address exhaustion in subnet %s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) return "", err } ipAddress, err = netutils.GetSubnetIP(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, ipAddrValue) if err != nil { log.Errorf("create eps: error acquiring subnet ip. Error: %s", err) return "", err } } else if reqAddr != "" && nwCfg.SubnetIP != "" { ipAddrValue, err = netutils.GetIPNumber(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, reqAddr) if err != nil { log.Errorf("create eps: error getting host id from hostIP %s Subnet %s/%d. Error: %s", reqAddr, nwCfg.SubnetIP, nwCfg.SubnetLen, err) return "", err } ipAddress = reqAddr } // Set the bitmap nwCfg.IPAllocMap.Set(ipAddrValue) err = nwCfg.Write() if err != nil { log.Errorf("error writing nw config. Error: %s", err) return "", err } return ipAddress, nil }
// CreateNetwork creates a network from intent func CreateNetwork(network intent.ConfigNetwork, stateDriver core.StateDriver, tenantName string) error { var extPktTag, pktTag uint gCfg := gstate.Cfg{} gCfg.StateDriver = stateDriver err := gCfg.Read(tenantName) if err != nil { log.Errorf("error reading tenant cfg state. Error: %s", err) return err } tempRm, err := resources.GetStateResourceManager() if err != nil { return err } rm := core.ResourceManager(tempRm) // Create network state networkID := network.Name + "." + tenantName nwCfg := &mastercfg.CfgNetworkState{} nwCfg.StateDriver = stateDriver if nwCfg.Read(networkID) == nil { // TODO: check if parameters changed and apply an update if needed return nil } subnetIP, subnetLen, _ := netutils.ParseCIDR(network.SubnetCIDR) // construct and update network state nwCfg = &mastercfg.CfgNetworkState{ Tenant: tenantName, NetworkName: network.Name, PktTagType: network.PktTagType, SubnetIP: subnetIP, SubnetLen: subnetLen, Gateway: network.Gateway, } nwCfg.ID = networkID nwCfg.StateDriver = stateDriver if network.PktTagType == "" { nwCfg.PktTagType = gCfg.Deploy.DefaultNetType } if network.PktTag == 0 { if nwCfg.PktTagType == "vlan" { pktTag, err = gCfg.AllocVLAN(rm) if err != nil { return err } } else if nwCfg.PktTagType == "vxlan" { extPktTag, pktTag, err = gCfg.AllocVXLAN(rm) if err != nil { return err } } nwCfg.ExtPktTag = int(extPktTag) nwCfg.PktTag = int(pktTag) } else if network.PktTagType == "vxlan" { if !isTagInRange(uint(network.PktTag), "vxlan", gCfg.Auto.VXLANs, stateDriver, tenantName) { return fmt.Errorf("vxlan %d does not adhere to tenant's vxlan range %s", network.PktTag, gCfg.Auto.VXLANs) } nwCfg.ExtPktTag = network.PktTag nwCfg.PktTag = network.PktTag } else if network.PktTagType == "vlan" { if !isTagInRange(uint(network.PktTag), "vlan", gCfg.Auto.VLANs, stateDriver, tenantName) { return fmt.Errorf("vlan %d does not adhere to tenant's vlan range %s", network.PktTag, gCfg.Auto.VLANs) } nwCfg.PktTag = network.PktTag } if nwCfg.SubnetIP == "" { nwCfg.SubnetLen = gCfg.Auto.AllocSubnetLen nwCfg.SubnetIP, err = gCfg.AllocSubnet(rm) if err != nil { return err } nwCfg.SubnetIsAllocated = true } defaultNwName, err := gCfg.AssignDefaultNetwork(network.Name) if err != nil { log.Errorf("error assigning the default network. Error: %s", err) return err } if network.Name == defaultNwName { // For auto derived subnets assign gateway ip be the last valid unicast ip the subnet if nwCfg.Gateway == "" && nwCfg.SubnetIsAllocated { var ipAddrValue uint ipAddrValue = (1 << (32 - nwCfg.SubnetLen)) - 2 nwCfg.Gateway, err = netutils.GetSubnetIP(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, ipAddrValue) if err != nil { return err } nwCfg.IPAllocMap.Set(ipAddrValue) } } netutils.InitSubnetBitset(&nwCfg.IPAllocMap, nwCfg.SubnetLen) err = nwCfg.Write() if err != nil { return err } if GetClusterMode() == "docker" { // Create the network in docker subnetCIDR := fmt.Sprintf("%s/%d", nwCfg.SubnetIP, nwCfg.SubnetLen) err = createDockNet(tenantName, network.Name, "", subnetCIDR, nwCfg.Gateway) if err != nil { log.Errorf("Error creating network %s in docker. Err: %v", nwCfg.ID, err) return err } // Attach service container endpoint to the network err = attachServiceContainer(tenantName, network.Name, stateDriver) if err != nil { log.Errorf("Error attaching service container to network: %s. Err: %v", networkID, err) return err } } return nil }