Skip to content

Instantly share code, notes, and snippets.

@jakubtomsu
Created May 14, 2024 10:17
Show Gist options
  • Save jakubtomsu/2765647b29004284a16824b6e09c0cca to your computer and use it in GitHub Desktop.
Save jakubtomsu/2765647b29004284a16824b6e09c0cca to your computer and use it in GitHub Desktop.
Simple Variable Length Subnet Mask solver
package vlsm
import "core:fmt"
import "core:intrinsics"
import "core:net"
import "core:slice"
Subnet :: struct {
prefix: u8,
num_hosts: u32,
max_hosts: u32,
address: net.IP4_Address,
}
generate :: proc(address: net.IP4_Address, prefix: u8, hosts: []u32, allocator := context.allocator) -> (result: []Subnet) {
slice.reverse_sort(hosts)
result = make([]Subnet, len(hosts), allocator)
addr_counter := cast(u32)transmute(u32be)address
for num_hosts, i in hosts {
assert(num_hosts > 0)
// +2 for local network and broadcast domain
// -1 to account for pow2 numbers
sub_prefix := intrinsics.count_leading_zeros(num_hosts + 2 - 1)
sub_exp := 32 - sub_prefix
sub := Subnet {
prefix = u8(sub_prefix),
num_hosts = num_hosts,
max_hosts = 1 << sub_exp,
address = transmute(net.IP4_Address)cast(u32be)addr_counter,
}
addr_counter += u32(sub.max_hosts)
result[i] = sub
}
return result
}
prefix_to_mask :: proc(prefix: u8) -> net.IP4_Address {
return transmute(net.IP4_Address)~u32be(0xffffffff >> prefix)
}
offset_address :: proc(addr: net.IP4_Address, #any_int offset: i32) -> net.IP4_Address {
return transmute(net.IP4_Address)u32be(cast(i32)transmute(u32be)addr + offset)
}
main :: proc() {
address := net.IP4_Address{172, 16, 0, 0}
prefix: u8 = 16
hosts := []u32{120, 100, 50, 50, 35, 20, 4, 2}
fmt.printfln("Network: {}/{}, Subnets: {}", net.address_to_string(address), prefix, hosts)
subnets := generate(address, prefix, hosts)
for sub, i in subnets {
fmt.printfln(
"[#%i] IP:{}/{}, Mask:{}, First Host:{}, Last Host:{}, Broadcast:{}, NumHosts:{}, MaxHosts:{}",
i,
net.address_to_string(sub.address),
sub.prefix,
net.address_to_string(prefix_to_mask(sub.prefix)),
net.address_to_string(offset_address(sub.address, 1)),
net.address_to_string(offset_address(sub.address, sub.max_hosts - 2)),
net.address_to_string(offset_address(sub.address, sub.max_hosts - 1)),
sub.num_hosts,
sub.max_hosts,
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment