github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/ipbits/ipbits.go (about)

     1  // Package ipbits contains utilities for manipulating [netip.Addr] values as
     2  // numbers or bitfields.
     3  package ipbits
     4  
     5  import (
     6  	"encoding/binary"
     7  	"net/netip"
     8  )
     9  
    10  // Add returns ip + (x << shift).
    11  func Add(ip netip.Addr, x uint64, shift uint) netip.Addr {
    12  	if ip.Is4() {
    13  		a := ip.As4()
    14  		addr := binary.BigEndian.Uint32(a[:])
    15  		addr += uint32(x) << shift
    16  		binary.BigEndian.PutUint32(a[:], addr)
    17  		return netip.AddrFrom4(a)
    18  	} else {
    19  		a := ip.As16()
    20  		addr := uint128From16(a)
    21  		addr = addr.add(uint128From(x).lsh(shift))
    22  		addr.fill16(&a)
    23  		return netip.AddrFrom16(a)
    24  	}
    25  }
    26  
    27  // Field returns the value of the bitfield [u, v] in ip as an integer,
    28  // where bit 0 is the most-significant bit of ip.
    29  //
    30  // The result is undefined if u > v, if v-u > 64, or if u or v is larger than
    31  // ip.BitLen().
    32  func Field(ip netip.Addr, u, v uint) uint64 {
    33  	if ip.Is4() {
    34  		mask := ^uint32(0) >> u
    35  		a := ip.As4()
    36  		return uint64((binary.BigEndian.Uint32(a[:]) & mask) >> (32 - v))
    37  	} else {
    38  		mask := uint128From(0).not().rsh(u)
    39  		return uint128From16(ip.As16()).and(mask).rsh(128 - v).uint64()
    40  	}
    41  }