Search code examples
gocidr

Go - calculate the cidr below one bit of the cidr provided


Ask

How do you calculate the cidr below one bit of the cidr provided?

Given:

a network CIDR : (192.168.0.0/16)

wanted result

192.168.0.0/17, 192.168.128.0/17

Using packages such as the default net package and github.com/brotherpowers/ipsubnet, github.com/seancfoley/ipaddress-go/ipaddr did not get the desired results.


Solution

  • To split a network in two, increment the length of the prefix by one. That gives you the lower half. To compute the second half, increment the network part by one (error handling omitted for brevity):

    package main
    
    import (
        "fmt"
        "math/big"
        "net/netip"
    )
    
    func main() {
        p := netip.MustParsePrefix("192.168.0.0/16")
        lo, hi := split(p)
        fmt.Println(lo, hi) // 192.168.0.0/17 192.168.128.0/17
    }
    
    func split(p netip.Prefix) (lo, hi netip.Prefix) {
        p = p.Masked()
        lo, _ = p.Addr().Prefix(p.Bits() + 1)
    
        delta := big.NewInt(1)
        delta.Lsh(delta, uint(lo.Addr().BitLen()-lo.Bits()))
    
        n := new(big.Int).SetBytes(lo.Addr().AsSlice())
        n.Add(n, delta)
    
        hiIP, _ := netip.AddrFromSlice(n.Bytes())
        hi = netip.PrefixFrom(hiIP, lo.Bits())
    
        return lo, hi
    }
    
    

    https://go.dev/play/p/0HLqUK0RmVC