github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/client/rootd/vip/vip.go (about) 1 package vip 2 3 import ( 4 "fmt" 5 "net" 6 "sync/atomic" 7 8 "github.com/telepresenceio/telepresence/v2/pkg/subnet" 9 ) 10 11 type Generator interface { 12 Next() (net.IP, error) 13 Subnet() *net.IPNet 14 } 15 16 // NewGenerator creates a generator for virtual IPs with in the given subnet. 17 func NewGenerator(sn *net.IPNet) Generator { 18 lo := sn.IP.Mask(sn.Mask) 19 hi := subnet.MaxIP(sn) 20 if len(lo) == 4 { 21 return &ip4Generator{ 22 subnet: *sn, 23 nextVirtualIP: intFromIPV4(lo), 24 maxVirtualIP: intFromIPV4(hi) + 1, 25 } 26 } else { 27 fixed, lo := intsFromIPV6(lo) 28 _, maxLo := intsFromIPV6(hi) 29 return &vip6Provider{ 30 subnet: *sn, 31 fixedHi: fixed, 32 nextLo: lo, 33 maxLo: maxLo, 34 } 35 } 36 } 37 38 type ip4Generator struct { 39 subnet net.IPNet 40 maxVirtualIP uint32 // Immutable 41 nextVirtualIP uint32 42 } 43 44 func (v *ip4Generator) Next() (net.IP, error) { 45 nxt := atomic.AddUint32(&v.nextVirtualIP, 1) 46 if nxt >= v.maxVirtualIP { 47 return nil, fmt.Errorf("virtual subnet CIDR %s is exhausted", v.Subnet()) 48 } 49 return ipV4FromInt(nxt), nil 50 } 51 52 func (v *ip4Generator) Subnet() *net.IPNet { 53 return &v.subnet 54 } 55 56 func ipV4FromInt(v uint32) net.IP { 57 return net.IP{ 58 byte(v & 0xff000000 >> 24), 59 byte(v & 0x00ff0000 >> 16), 60 byte(v & 0x0000ff00 >> 8), 61 byte(v & 0x000000ff), 62 } 63 } 64 65 func intFromIPV4(v net.IP) uint32 { 66 return uint32(v[0])<<24 | uint32(v[1])<<16 | uint32(v[2])<<8 | uint32(v[3]) 67 } 68 69 type vip6Provider struct { 70 subnet net.IPNet 71 fixedHi uint64 72 maxLo uint64 // Immutable 73 nextLo uint64 74 } 75 76 func (v *vip6Provider) Next() (net.IP, error) { 77 nxt := atomic.AddUint64(&v.nextLo, 1) 78 if nxt >= v.maxLo { 79 return nil, fmt.Errorf("virtual subnet CIDR %s is exhausted", v.Subnet()) 80 } 81 return ipV6FromInts(v.fixedHi, nxt), nil 82 } 83 84 func (v *vip6Provider) Subnet() *net.IPNet { 85 return &v.subnet 86 } 87 88 func ipV6FromInts(hi, lo uint64) net.IP { 89 return net.IP{ 90 byte(hi & 0xff00000000000000 >> 56), 91 byte(hi & 0x00ff000000000000 >> 48), 92 byte(hi & 0x0000ff0000000000 >> 40), 93 byte(hi & 0x000000ff00000000 >> 32), 94 byte(hi & 0x00000000ff000000 >> 24), 95 byte(hi & 0x0000000000ff0000 >> 16), 96 byte(hi & 0x000000000000ff00 >> 8), 97 byte(hi & 0x00000000000000ff), 98 byte(lo & 0xff00000000000000 >> 56), 99 byte(lo & 0x00ff000000000000 >> 48), 100 byte(lo & 0x0000ff0000000000 >> 40), 101 byte(lo & 0x000000ff00000000 >> 32), 102 byte(lo & 0x00000000ff000000 >> 24), 103 byte(lo & 0x0000000000ff0000 >> 16), 104 byte(lo & 0x000000000000ff00 >> 8), 105 byte(lo & 0x00000000000000ff), 106 } 107 } 108 109 func intsFromIPV6(v net.IP) (uint64, uint64) { 110 return uint64(v[0])<<56 | uint64(v[1])<<48 | uint64(v[2])<<40 | uint64(v[3])<<32 | uint64(v[4])<<24 | uint64(v[5])<<16 | uint64(v[6])<<8 | uint64(v[7]), 111 uint64(v[8])<<56 | uint64(v[9])<<48 | uint64(v[10])<<40 | uint64(v[11])<<32 | uint64(v[12])<<24 | uint64(v[13])<<16 | uint64(v[14])<<8 | uint64(v[15]) 112 }