diff --git a/src/core/common/netutil/netutil.go b/src/core/common/netutil/netutil.go index 52d36266a..52796d095 100644 --- a/src/core/common/netutil/netutil.go +++ b/src/core/common/netutil/netutil.go @@ -429,3 +429,75 @@ func cidrOverlap(cidr1, cidr2 string) bool { _, net2, _ := net.ParseCIDR(cidr2) return net1.Contains(net2.IP) || net2.Contains(net1.IP) } + +// /////////////////////////////////////////////////////////////////////////////////// +// NextSubnet find and check the next subnet based on the base/parent network. +func NextSubnet(currentSubnetCIDR string, baseNetworkCIDR string) (string, error) { + // Parse the current subnet + _, currentNet, err := net.ParseCIDR(currentSubnetCIDR) + if err != nil { + return "", err + } + + // Parse the base network + _, baseNet, err := net.ParseCIDR(baseNetworkCIDR) + if err != nil { + return "", err + } + + // Convert the current subnet's IP to uint32 + currentIPInt := IpToUint32(currentNet.IP) + + // Calculate the size of the current subnet + maskSize, _ := currentNet.Mask.Size() + subnetSize := uint32(1 << (32 - maskSize)) + + // Calculate the next subnet's starting IP + nextIPInt := currentIPInt + subnetSize + + // Convert the next IP to net.IP + nextIP := Uint32ToIP(nextIPInt) + + // Check if the next subnet is within the base network range + if !baseNet.Contains(nextIP) { + return "", fmt.Errorf("the next subnet is outside the base network range") + } + + return fmt.Sprintf("%s/%d", nextIP.String(), maskSize), nil +} + + +// PreviousSubnet find and check the previous subnet based on the base/parent network. +func PreviousSubnet(currentSubnet string, baseNetworkCIDR string) (string, error) { + // Parse the current subnet + _, currentNet, err := net.ParseCIDR(currentSubnet) + if err != nil { + return "", err + } + + // Parse the base network + _, baseNet, err := net.ParseCIDR(baseNetworkCIDR) + if err != nil { + return "", err + } + + // Convert the current subnet's IP to uint32 + currentIPInt := IpToUint32(currentNet.IP) + + // Calculate the size of the current subnet + maskSize, _ := currentNet.Mask.Size() + subnetSize := uint32(1 << (32 - maskSize)) + + // Calculate the previous subnet's starting IP + previousIPInt := currentIPInt - subnetSize + + // Convert the previous IP to net.IP + previousIP := Uint32ToIP(previousIPInt) + + // Check if the previous subnet is within the base network range + if !baseNet.Contains(previousIP) { + return "", fmt.Errorf("the previous subnet is outside the base network range") + } + + return fmt.Sprintf("%s/%d", previousIP.String(), maskSize), nil +} \ No newline at end of file diff --git a/src/examples/netutil/netutil.go b/src/examples/netutil/netutil.go index 5ad5d1ed6..bd7880a29 100644 --- a/src/examples/netutil/netutil.go +++ b/src/examples/netutil/netutil.go @@ -217,4 +217,80 @@ func runExample(cmd *cobra.Command, args []string) { } fmt.Printf("[Subnetting result]\n%s\n", string(pretty)) + /////////////////////////////////////////////////////////////////////////////////////////////////// + fmt.Println("\n\nNextSubnet() test example") + + baseNetwork := "10.0.0.0/16" + currentSubnet0 := "10.0.0.0/18" + currentSubnet1 := "10.0.64.0/18" + currentSubnet2 := "10.0.128.0/18" + currentSubnet3 := "10.0.192.0/18" + + fmt.Printf("[NextSubnet() Case1] Base Network CIDR: %s, Current Subnet CIDR: %s\n", baseNetwork, currentSubnet0) + nextSubnet, err := netutil.NextSubnet(currentSubnet0, baseNetwork) + if err != nil { + fmt.Println(" Error:", err) + } else { + fmt.Println(" Next Subnet:", nextSubnet) + } + + fmt.Printf("[NextSubnet() Case2] Base Network CIDR: %s, Current Subnet CIDR: %s\n", baseNetwork, currentSubnet1) + nextSubnet, err = netutil.NextSubnet(currentSubnet1, baseNetwork) + if err != nil { + fmt.Println(" Error:", err) + } else { + fmt.Println(" Next Subnet:", nextSubnet) + } + + fmt.Printf("[NextSubnet() Case3] Base Network CIDR: %s, Current Subnet CIDR: %s\n", baseNetwork, currentSubnet2) + nextSubnet, err = netutil.NextSubnet(currentSubnet2, baseNetwork) + if err != nil { + fmt.Println(" Error:", err) + } else { + fmt.Println(" Next Subnet:", nextSubnet) + } + + fmt.Printf("[NextSubnet() Case4] Base Network CIDR: %s, Current Subnet CIDR: %s\n", baseNetwork, currentSubnet3) + nextSubnet, err = netutil.NextSubnet(currentSubnet3, baseNetwork) + if err != nil { + fmt.Println(" Error:", err) + } else { + fmt.Println(" Next Subnet:", nextSubnet) + } + + /////////////////////////////////////////////////////////////////////////////////////////////////// + fmt.Println("\n\nPreviousSubnet() test example") + + fmt.Printf("[PreviousSubnet() Case1] Base Network CIDR: %s, Current Subnet CIDR: %s\n", baseNetwork, currentSubnet0) + previousSubnet, err := netutil.PreviousSubnet(currentSubnet0, baseNetwork) + if err != nil { + fmt.Println(" Error:", err) + } else { + fmt.Println(" Previous Subnet:", previousSubnet) + } + + fmt.Printf("[PreviousSubnet() Case2] Base Network CIDR: %s, Current Subnet CIDR: %s\n", baseNetwork, currentSubnet1) + previousSubnet, err = netutil.PreviousSubnet(currentSubnet1, baseNetwork) + if err != nil { + fmt.Println(" Error:", err) + } else { + fmt.Println(" Previous Subnet:", previousSubnet) + } + + fmt.Printf("[PreviousSubnet() Case3] Base Network CIDR: %s, Current Subnet CIDR: %s\n", baseNetwork, currentSubnet2) + previousSubnet, err = netutil.PreviousSubnet(currentSubnet2, baseNetwork) + if err != nil { + fmt.Println(" Error:", err) + } else { + fmt.Println(" Previous Subnet:", previousSubnet) + } + + fmt.Printf("[PreviousSubnet() Case4] Base Network CIDR: %s, Current Subnet CIDR: %s\n", baseNetwork, currentSubnet3) + previousSubnet, err = netutil.PreviousSubnet(currentSubnet3, baseNetwork) + if err != nil { + fmt.Println(" Error:", err) + } else { + fmt.Println(" Previous Subnet:", previousSubnet) + } + }