Newer
Older
"github.com/bio-routing/bio-rd/net/api"
// Dedup gets a copy of Prefix from the cache
func (p *Prefix) Dedup() *Prefix {
return pfxc.get(p)
}
// DedupWithIP gets a copy of Prefix from the cache and dedups the IP part
func (p *Prefix) DedupWithIP() *Prefix {
p.addr = p.addr.Dedup()
return pfxc.get(p)
}
func NewPrefixFromProtoPrefix(pfx api.Prefix) *Prefix {
return &Prefix{
addr: IPFromProtoIP(*pfx.Address),
pfxlen: uint8(pfx.Pfxlen),
}
}
// PrefixFromString converts prefix from string representation to Prefix
func PrefixFromString(s string) (*Prefix, error) {
parts := strings.Split(s, "/")
if len(parts) != 2 {
return nil, fmt.Errorf("Invalid format: %q", s)
}
ip, err := IPFromString(parts[0])
if err != nil {
}
l, err := strconv.Atoi(parts[1])
if err != nil {
return nil, errors.Wrap(err, "Unable to convert to int")
addr: ip,
pfxlen: uint8(l),
}, nil
}
func (p *Prefix) ToProto() *api.Prefix {
Address: p.addr.ToProto(),
Pfxlen: uint32(p.pfxlen),
func NewPfx(addr *IP, pfxlen uint8) *Prefix {
return &Prefix{
// NewPfxFromIPNet creates a Prefix object from an gonet.IPNet object
func NewPfxFromIPNet(ipNet *gonet.IPNet) *Prefix {
ones, _ := ipNet.Mask.Size()
ip, _ := IPFromBytes(ipNet.IP)
// StrToAddr converts an IP address string to it's uint32 representation
func StrToAddr(x string) (uint32, error) {
parts := strings.Split(x, ".")
if len(parts) != 4 {
return 0, fmt.Errorf("Invalid format")
}
ret := uint32(0)
for i := 0; i < 4; i++ {
y, err := strconv.Atoi(parts[i])
if err != nil {
return 0, errors.Wrapf(err, "Unable to convert %q to int", parts[i])
}
if y > 255 {
return 0, fmt.Errorf("%d is too big for a uint8", y)
}
}
return ret, nil
}
// Addr returns the address of the prefix
func (pfx *Prefix) Addr() *IP {
return pfx.addr
}
// Pfxlen returns the length of the prefix
func (pfx *Prefix) Pfxlen() uint8 {
return pfx.pfxlen
}
// String returns a string representation of pfx
func (pfx *Prefix) String() string {
return fmt.Sprintf("%s/%d", pfx.addr, pfx.pfxlen)
// GetIPNet returns the gonet.IP object for a Prefix object
func (pfx *Prefix) GetIPNet() *gonet.IPNet {
dstNetwork.IP = pfx.Addr().Bytes()
pfxLen := int(pfx.Pfxlen())
if pfx.Addr().IsIPv4() {
func (pfx *Prefix) Contains(x *Prefix) bool {
return pfx.containsIPv4(x)
}
func (pfx *Prefix) containsIPv4(x *Prefix) bool {
mask := uint32((math.MaxUint32 << (32 - pfx.pfxlen)))
return (pfx.addr.ToUint32() & mask) == (x.addr.ToUint32() & mask)
func (pfx *Prefix) containsIPv6(x *Prefix) bool {
var maskHigh, maskLow uint64
if pfx.pfxlen <= 64 {
maskHigh = math.MaxUint32 << (64 - pfx.pfxlen)
maskLow = uint64(0)
} else {
maskHigh = math.MaxUint32
maskLow = math.MaxUint32 << (128 - pfx.pfxlen)
}
return pfx.addr.higher&maskHigh&maskHigh == x.addr.higher&maskHigh&maskHigh &&
pfx.addr.lower&maskHigh&maskLow == x.addr.lower&maskHigh&maskLow
}
func (pfx *Prefix) Equal(x *Prefix) bool {
func (pfx *Prefix) GetSupernet(x *Prefix) *Prefix {
return pfx.supernetIPv4(x)
}
return pfx.supernetIPv6(x)
func (pfx *Prefix) supernetIPv4(x *Prefix) *Prefix {
a := pfx.addr.ToUint32() >> (32 - maxPfxLen)
b := x.addr.ToUint32() >> (32 - maxPfxLen)
for i := 0; a != b; i++ {
a = a >> 1
b = b >> 1
maxPfxLen--
}
addr: IPv4(a << (32 - maxPfxLen)),
func (pfx *Prefix) supernetIPv6(x *Prefix) *Prefix {
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
maxPfxLen := min(pfx.pfxlen, x.pfxlen)
a := pfx.addr.BitAtPosition(1)
b := x.addr.BitAtPosition(1)
pfxLen := uint8(0)
mask := uint64(0)
for a == b && pfxLen < maxPfxLen {
a = pfx.addr.BitAtPosition(pfxLen + 2)
b = x.addr.BitAtPosition(pfxLen + 2)
pfxLen++
if pfxLen == 64 {
mask = 0
}
m := pfxLen % 64
mask = mask + uint64(1)<<(64-m)
}
if pfxLen == 0 {
return NewPfx(IPv6(0, 0), pfxLen)
}
if pfxLen > 64 {
return NewPfx(IPv6(pfx.addr.higher, pfx.addr.lower&mask), pfxLen)
}
return NewPfx(IPv6(pfx.addr.higher&mask, 0), pfxLen)
}