Skip to content
Snippets Groups Projects
Commit e5d0158e authored by Daniel Czerwonk's avatar Daniel Czerwonk
Browse files

added implementation for IPv6 supernet calculation

parent 8f513c82
No related branches found
No related tags found
No related merge requests found
......@@ -312,6 +312,12 @@ func TestBitAtPosition(t *testing.T) {
position uint8
expected bool
}{
{
name: "IPv4: all ones -> 0",
input: IPv4FromOctets(255, 255, 255, 255),
position: 1,
expected: true,
},
{
name: "IPv4: Bit 8 from 1.0.0.0 -> 0",
input: IPv4FromOctets(10, 0, 0, 0),
......@@ -348,6 +354,12 @@ func TestBitAtPosition(t *testing.T) {
position: 115,
expected: false,
},
{
name: "IPv6: all ones -> 1",
input: IPv6FromBlocks(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF),
position: 1,
expected: true,
},
}
for _, test := range tests {
......
......@@ -89,7 +89,7 @@ func (pfx Prefix) GetSupernet(x Prefix) Prefix {
return pfx.supernetIPv4(x)
}
panic("No IPv6 support yet!")
return pfx.supernetIPv6(x)
}
func (pfx Prefix) supernetIPv4(x Prefix) Prefix {
......@@ -109,6 +109,37 @@ func (pfx Prefix) supernetIPv4(x Prefix) Prefix {
}
}
func (pfx Prefix) supernetIPv6(x Prefix) Prefix {
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)
}
func min(a uint8, b uint8) uint8 {
if a < b {
return a
......
......@@ -63,7 +63,7 @@ func TestGetSupernet(t *testing.T) {
expected Prefix
}{
{
name: "Test 1",
name: "Supernet of 10.0.0.0 and 11.100.123.0 -> 10.0.0.0/7",
a: Prefix{
addr: IPv4FromOctets(10, 0, 0, 0),
pfxlen: 8,
......@@ -78,7 +78,7 @@ func TestGetSupernet(t *testing.T) {
},
},
{
name: "Test 2",
name: "Supernet of 10.0.0.0 and 192.168.0.0 -> 0.0.0.0/0",
a: Prefix{
addr: IPv4FromOctets(10, 0, 0, 0),
pfxlen: 8,
......@@ -88,15 +88,64 @@ func TestGetSupernet(t *testing.T) {
pfxlen: 24,
},
expected: Prefix{
addr: IPv4(0), // 0.0.0.0/0
addr: IPv4(0),
pfxlen: 0,
},
},
{
name: "Supernet of 2001:678:1e0:100:23::/64 and 2001:678:1e0:1ff::/64 -> 2001:678:1e0:100::/56",
a: Prefix{
addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x100, 0x23, 0, 0, 0),
pfxlen: 64,
},
b: Prefix{
addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x1ff, 0, 0, 0, 0),
pfxlen: 64,
},
expected: Prefix{
addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x100, 0, 0, 0, 0),
pfxlen: 56,
},
},
{
name: "Supernet of 2001:678:1e0::/128 and 2001:678:1e0::1/128 -> 2001:678:1e0:100::/127",
a: Prefix{
addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0),
pfxlen: 128,
},
b: Prefix{
addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 1),
pfxlen: 128,
},
expected: Prefix{
addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0),
pfxlen: 127,
},
},
{
name: "Supernet of all ones and all zeros -> ::/0",
a: Prefix{
addr: IPv6FromBlocks(0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF),
pfxlen: 128,
},
b: Prefix{
addr: IPv6(0, 0),
pfxlen: 128,
},
expected: Prefix{
addr: IPv6FromBlocks(0, 0, 0, 0, 0, 0, 0, 0),
pfxlen: 0,
},
},
}
t.Parallel()
for _, test := range tests {
s := test.a.GetSupernet(test.b)
assert.Equal(t, s, test.expected)
t.Run(test.name, func(t *testing.T) {
s := test.a.GetSupernet(test.b)
assert.Equal(t, test.expected, s)
})
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment