Skip to content

Commit

Permalink
fix: available ips calculation issues
Browse files Browse the repository at this point in the history
  • Loading branch information
oilbeater committed Jul 15, 2020
1 parent ceba61e commit d017f1f
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 5 deletions.
4 changes: 4 additions & 0 deletions pkg/controller/subnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func (c *Controller) enqueueUpdateSubnet(old, new interface{}) {
}

if oldSubnet.Spec.Private != newSubnet.Spec.Private ||
oldSubnet.Spec.CIDRBlock != newSubnet.Spec.CIDRBlock ||
!reflect.DeepEqual(oldSubnet.Spec.AllowSubnets, newSubnet.Spec.AllowSubnets) ||
!reflect.DeepEqual(oldSubnet.Spec.Namespaces, newSubnet.Spec.Namespaces) ||
oldSubnet.Spec.GatewayType != newSubnet.Spec.GatewayType ||
Expand Down Expand Up @@ -781,6 +782,9 @@ func calcSubnetStatusIP(subnet *kubeovnv1.Subnet, c *Controller) error {
toSubIPs = append(toSubIPs, podUsedIP.Spec.IPAddress)
}
availableIPs := util.AddressCount(cidr) - float64(len(util.UniqString(toSubIPs)))
if availableIPs < 0 {
availableIPs = 0
}
usingIPs := float64(len(podUsedIPs.Items))
subnet.Status.AvailableIPs = availableIPs
subnet.Status.UsingIPs = usingIPs
Expand Down
2 changes: 1 addition & 1 deletion pkg/ipam/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (ipam *IPAM) AddOrUpdateSubnet(name, cidrStr string, excludeIps []string) e
if subnet, ok := ipam.Subnets[name]; ok {
subnet.ReservedIPList = convertExcludeIps(excludeIps)
firstIP, _ := util.FirstSubnetIP(cidrStr)
lastIP, _ := util.LastSubnetIP(cidrStr)
lastIP, _ := util.LastIP(cidrStr)
subnet.FreeIPList = IPRangeList{&IPRange{Start: IP(firstIP), End: IP(lastIP)}}
subnet.joinFreeWithReserve()
for podName, ip := range subnet.PodToIP {
Expand Down
2 changes: 1 addition & 1 deletion pkg/ipam/subnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func NewSubnet(name, cidrStr string, excludeIps []string) (*Subnet, error) {
}

firstIP, _ := util.FirstSubnetIP(cidrStr)
lastIP, _ := util.LastSubnetIP(cidrStr)
lastIP, _ := util.LastIP(cidrStr)

subnet := Subnet{
Name: name,
Expand Down
4 changes: 3 additions & 1 deletion pkg/ovs/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ func trimCommandOutput(raw []byte) string {
// ExpandExcludeIPs parse ovn exclude_ips to ip slice
func ExpandExcludeIPs(excludeIPs []string, cidr string) []string {
rv := []string{}
subnetNum := util.SubnetNumber(cidr)
broadcast := util.SubnetBroadCast(cidr)
for _, excludeIP := range excludeIPs {
if strings.Index(excludeIP, "..") != -1 {
parts := strings.Split(excludeIP, "..")
s := util.Ip2BigInt(parts[0])
e := util.Ip2BigInt(parts[1])
for s.Cmp(e) <= 0 {
ipStr := util.BigInt2Ip(s)
if util.CIDRContainIP(cidr, ipStr) {
if ipStr != subnetNum && ipStr != broadcast && util.CIDRContainIP(cidr, ipStr) && !util.ContainsString(rv, ipStr) {
rv = append(rv, ipStr)
}
s.Add(s, big.NewInt(1))
Expand Down
22 changes: 21 additions & 1 deletion pkg/util/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ func BigInt2Ip(ipInt *big.Int) string {
return ip.String()
}

func SubnetNumber(subnet string) string {
_, cidr, _ := net.ParseCIDR(subnet)
return cidr.IP.String()
}

func SubnetBroadCast(subnet string) string {
_, cidr, _ := net.ParseCIDR(subnet)
var length uint
if CheckProtocol(subnet) == kubeovnv1.ProtocolIPv4 {
length = 32
} else {
length = 128
}
maskLength, _ := cidr.Mask.Size()
ipInt := Ip2BigInt(cidr.IP.String())
size := big.NewInt(0).Lsh(big.NewInt(1), length-uint(maskLength))
size = big.NewInt(0).Sub(size, big.NewInt(1))
return BigInt2Ip(ipInt.Add(ipInt, size))
}

func FirstSubnetIP(subnet string) (string, error) {
_, cidr, err := net.ParseCIDR(subnet)
if err != nil {
Expand All @@ -44,7 +64,7 @@ func FirstSubnetIP(subnet string) (string, error) {
return BigInt2Ip(ipInt.Add(ipInt, big.NewInt(1))), nil
}

func LastSubnetIP(subnet string) (string, error) {
func LastIP(subnet string) (string, error) {
_, cidr, err := net.ParseCIDR(subnet)
if err != nil {
return "", fmt.Errorf("%s is not a valid cidr", subnet)
Expand Down
72 changes: 71 additions & 1 deletion test/e2e/subnet/normal.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ var _ = Describe("[Subnet]", func() {
if err := f.OvnClientSet.KubeovnV1().Subnets().Delete(f.GetName(), &metav1.DeleteOptions{}); err != nil {
if !k8serrors.IsNotFound(err) {
klog.Fatalf("failed to delete subnet %s, %v", f.GetName(), err)

}
}
if err := f.KubeClientSet.CoreV1().Namespaces().Delete(f.GetName(), &metav1.DeleteOptions{}); err != nil {
Expand Down Expand Up @@ -211,4 +210,75 @@ var _ = Describe("[Subnet]", func() {
Expect(s.Spec.CIDRBlock).To(Equal("11.14.0.0/16"))
})
})

Describe("available ip calculation", func() {
It("no available cidr", func() {
name := f.GetName()
s := &kubeovn.Subnet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{"e2e": "true"},
},
Spec: kubeovn.SubnetSpec{
CIDRBlock: "19.0.0.0/31",
ExcludeIps: []string{"179.17.0.0..179.17.0.10"},
},
}
_, err := f.OvnClientSet.KubeovnV1().Subnets().Create(s)
Expect(err).NotTo(HaveOccurred())

err = f.WaitSubnetReady(name)
Expect(err).NotTo(HaveOccurred())

s, err = f.OvnClientSet.KubeovnV1().Subnets().Get(name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(s.Status.AvailableIPs).To(Equal(float64(0)))
})

It("small cidr", func() {
name := f.GetName()
s := &kubeovn.Subnet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{"e2e": "true"},
},
Spec: kubeovn.SubnetSpec{
CIDRBlock: "29.0.0.0/30",
ExcludeIps: []string{"179.17.0.0..179.17.0.10"},
},
}
_, err := f.OvnClientSet.KubeovnV1().Subnets().Create(s)
Expect(err).NotTo(HaveOccurred())

err = f.WaitSubnetReady(name)
Expect(err).NotTo(HaveOccurred())

s, err = f.OvnClientSet.KubeovnV1().Subnets().Get(name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(s.Status.AvailableIPs).To(Equal(float64(1)))
})

It("with excludeips", func() {
name := f.GetName()
s := &kubeovn.Subnet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{"e2e": "true"},
},
Spec: kubeovn.SubnetSpec{
CIDRBlock: "179.17.0.0/24",
ExcludeIps: []string{"179.17.0.0..179.17.0.10"},
},
}
_, err := f.OvnClientSet.KubeovnV1().Subnets().Create(s)
Expect(err).NotTo(HaveOccurred())

err = f.WaitSubnetReady(name)
Expect(err).NotTo(HaveOccurred())

s, err = f.OvnClientSet.KubeovnV1().Subnets().Get(name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(s.Status.AvailableIPs).To(Equal(float64(244)))
})
})
})

0 comments on commit d017f1f

Please sign in to comment.