Skip to content
LookupOwl

VLSM subnet planner

Split a network into subnets sized for what each team needs, see the free space that is left, and export the plan.

A CIDR block, IPv4 or IPv6.

need: subnets sized for the requirements, largest first. equal: equal subnets of one size.

One per line: name: hosts, or name: /prefix. Up to 256 lines.

More options

Equal subnets: the prefix length, for example 26.

split equal: how many equal subnets (a power of two is used). Give this or `equalPrefix`.

Reserved addresses to leave in every subnet: none, aws (5), azure (5) or gcp (4).

IPv6: align subnets on a hex digit (4-bit) boundary. Default on for IPv6, off for IPv4.

Results for 10.20.0.0/23

Planned just now

JSON

Planned

5 subnets fit in 10.20.0.0/23, with 44 addresses left

The plan uses 468 of 512 addresses (91.4%). Free space stays in 3 aligned blocks.

Allocation
1 Servers 10.20.0.0/24, 2 Office 10.20.1.0/25, 3 Guests 10.20.1.128/26, 4 Printers 10.20.1.192/28, 5 Uplink 10.20.1.208/30. Free: 10.20.1.212/30, 10.20.1.216/29, 10.20.1.224/27.
10.20.0.010.20.0.0/2310.20.1.255

1 Servers 10.20.0.0/24, 2 Office 10.20.1.0/25, 3 Guests 10.20.1.128/26, 4 Printers 10.20.1.192/28, 5 Uplink 10.20.1.208/30. Free: 10.20.1.212/30, 10.20.1.216/29, 10.20.1.224/27.

Used
91.4%

468 of 512 addresses

Subnets5
NameNeedsBlockFirst to lastUsableSpare
Servers200 hosts10.20.0.0/24 10.20.0.0 to 10.20.0.25525454
Office120 hosts10.20.1.0/25 10.20.1.0 to 10.20.1.1271266
Guests50 hosts10.20.1.128/26 10.20.1.128 to 10.20.1.1916212
Printers12 hosts10.20.1.192/28 10.20.1.192 to 10.20.1.207142
Uplink2 hosts10.20.1.208/30 10.20.1.208 to 10.20.1.21120

Free: 3 blocks, 44 addresses

  • 10.20.1.212/30 · 4
  • 10.20.1.216/29 · 8
  • 10.20.1.224/27 · 32
Why this order

Largest first keeps every block aligned, so nothing is left unusable.

  • Servers: 10.20.0.0/24

    200 hosts + 2 (network and broadcast) = 202, the next power of two is 256, so a /24.

  • Office: 10.20.1.0/25

    120 hosts + 2 (network and broadcast) = 122, the next power of two is 128, so a /25.

  • Guests: 10.20.1.128/26

    50 hosts + 2 (network and broadcast) = 52, the next power of two is 64, so a /26.

  • Printers: 10.20.1.192/28

    12 hosts + 2 (network and broadcast) = 14, the next power of two is 16, so a /28.

  • Uplink: 10.20.1.208/30

    2 hosts + 2 (network and broadcast) = 4, which is a power of two, so a /30.

Export
Terraform (aws_subnet)resource "aws_subnet" "servers" { vpc_id = aws_vpc.main.id cidr_block = "10.20.0.0/24" } resource "aws_subnet" "office" { vpc_id = aws_vpc.main.id cidr_block = "10.20.1.0/25" } resource "aws_subnet" "guests" { vpc_id = aws_vpc.main.id cidr_block = "10.20.1.128/26" } resource "aws_subnet" "printers" { vpc_id = aws_vpc.main.id cidr_block = "10.20.1.192/28" } resource "aws_subnet" "uplink" { vpc_id = aws_vpc.main.id cidr_block = "10.20.1.208/30" }
Terraform (azurerm_subnet)resource "azurerm_subnet" "servers" { name = "servers" resource_group_name = azurerm_resource_group.main.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.20.0.0/24"] } resource "azurerm_subnet" "office" { name = "office" resource_group_name = azurerm_resource_group.main.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.20.1.0/25"] } resource "azurerm_subnet" "guests" { name = "guests" resource_group_name = azurerm_resource_group.main.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.20.1.128/26"] } resource "azurerm_subnet" "printers" { name = "printers" resource_group_name = azurerm_resource_group.main.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.20.1.192/28"] } resource "azurerm_subnet" "uplink" { name = "uplink" resource_group_name = azurerm_resource_group.main.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.20.1.208/30"] }
CSVname,need,cidr,first,last,usable "Servers",200,10.20.0.0/24,10.20.0.0,10.20.0.255,254 "Office",120,10.20.1.0/25,10.20.1.0,10.20.1.127,126 "Guests",50,10.20.1.128/26,10.20.1.128,10.20.1.191,62 "Printers",12,10.20.1.192/28,10.20.1.192,10.20.1.207,14 "Uplink",2,10.20.1.208/30,10.20.1.208,10.20.1.211,2
JSON[ { "name": "Servers", "need": 200, "cidr": "10.20.0.0/24", "first": "10.20.0.0", "last": "10.20.0.255", "usable": "254" }, { "name": "Office", "need": 120, "cidr": "10.20.1.0/25", "first": "10.20.1.0", "last": "10.20.1.127", "usable": "126" }, { "name": "Guests", "need": 50, "cidr": "10.20.1.128/26", "first": "10.20.1.128", "last": "10.20.1.191", "usable": "62" }, { "name": "Printers", "need": 12, "cidr": "10.20.1.192/28", "first": "10.20.1.192", "last": "10.20.1.207", "usable": "14" }, { "name": "Uplink", "need": 2, "cidr": "10.20.1.208/30", "first": "10.20.1.208", "last": "10.20.1.211", "usable": "2" } ]

Worked out on our server. With JavaScript on, it is worked out in your browser and nothing you paste is sent to us.

Structured result (JSON) · 2.3 KB
{
  "network": "10.20.0.0/23",
  "family": 4,
  "cloud": "none",
  "strategy": "largest_first",
  "allocations": [
    {
      "name": "Servers",
      "need": 200,
      "cidr": "10.20.0.0/24",
      "first": "10.20.0.0",
      "last": "10.20.0.255",
      "usable": "254",
      "unusedUsable": "54",
      "why": "200 hosts + 2 (network and broadcast) = 202, the next power of two is 256, so a /24.",
      "addresses": "256",
      "offset": "0"
    },
    {
      "name": "Office",
      "need": 120,
      "cidr": "10.20.1.0/25",
      "first": "10.20.1.0",
      "last": "10.20.1.127",
      "usable": "126",
      "unusedUsable": "6",
      "why": "120 hosts + 2 (network and broadcast) = 122, the next power of two is 128, so a /25.",
      "addresses": "128",
      "offset": "256"
    },
    {
      "name": "Guests",
      "need": 50,
      "cidr": "10.20.1.128/26",
      "first": "10.20.1.128",
      "last": "10.20.1.191",
      "usable": "62",
      "unusedUsable": "12",
      "why": "50 hosts + 2 (network and broadcast) = 52, the next power of two is 64, so a /26.",
      "addresses": "64",
      "offset": "384"
    },
    {
      "name": "Printers",
      "need": 12,
      "cidr": "10.20.1.192/28",
      "first": "10.20.1.192",
      "last": "10.20.1.207",
      "usable": "14",
      "unusedUsable": "2",
      "why": "12 hosts + 2 (network and broadcast) = 14, the next power of two is 16, so a /28.",
      "addresses": "16",
      "offset": "448"
    },
    {
      "name": "Uplink",
      "need": 2,
      "cidr": "10.20.1.208/30",
      "first": "10.20.1.208",
      "last": "10.20.1.211",
      "usable": "2",
      "unusedUsable": "0",
      "why": "2 hosts + 2 (network and broadcast) = 4, which is a power of two, so a /30.",
      "addresses": "4",
      "offset": "464"
    }
  ],
  "free": [
    {
      "cidr": "10.20.1.212/30",
      "addresses": "4",
      "offset": "468"
    },
    {
      "cidr": "10.20.1.216/29",
      "addresses": "8",
      "offset": "472"
    },
    {
      "cidr": "10.20.1.224/27",
      "addresses": "32",
      "offset": "480"
    }
  ],
  "utilisation": {
    "allocated": "468",
    "total": "512",
    "free": "44",
    "percentAllocated": 91.4
  },
  "unplaced": [],
  "suggestion": null,
  "notes": [],
  "exports": [
    "csv",
    "json",
    "terraform-aws",
    "terraform-azure"
  ]
}

Next step

What VLSM means

Variable length subnet masking means not every subnet in a network has to be the same size. A server network of 200 hosts and a point-to-point link of 2 hosts do not need the same block, and giving both a /24 wastes most of the address space. A VLSM plan gives each one the smallest block that holds it.

This planner takes a network, such as 10.20.0.0/22, and a list of needs, such as Servers: 200 or Guests: /26. It sorts them, gives each the right size, places them without gaps, and shows what is left over as free blocks you can use later.

How the sizes and the order are chosen

A subnet needs room for its hosts plus two addresses that cannot be given to a host, the network address and the broadcast address. So 200 hosts need 202 addresses, and the next power of two is 256, which is a /24. Fifty hosts need 52, which rounds up to 64, a /26.

The planner places the biggest subnets first. A block must start on an address that is a multiple of its own size, so putting small blocks first can leave a hole that no larger block can use. Largest first keeps every block aligned and the free space in as few pieces as possible.

Hosts neededAddresses neededBlock
200202, rounds to 256/24
120122, rounds to 128/25
5052, rounds to 64/26
1214, rounds to 16/28
24/30

When the plan does not fit

A plan that is too big is not an error. The subnets that fit are placed, the ones that did not are listed with how much room they needed and how much was left in the largest free block, and the page says how large a network would hold everything. Plan the same needs in a /24 instead of a /22 and you see at once which teams do not fit.

Cloud networks and IPv6

Cloud providers keep addresses in every subnet for themselves. Amazon VPC and Azure keep five, Google Cloud keeps four. Choose the provider under More options and the planner adds those addresses to each need, so a subnet for 60 hosts becomes a /25 in AWS, not a /26. Providers also set the smallest subnet they allow, and the planner raises smaller needs to that size and tells you.

IPv6 is different. Subnets are not sized by host count, because a /64 already holds more addresses than any link will use, and features such as SLAAC need a /64. Every IPv6 subnet here gets a /64 and the plan counts subnets. The equal split can also line each subnet up on a hex digit boundary, so the addresses read cleanly.

Export and privacy

The plan can be copied as CSV, as JSON, or as Terraform aws_subnet or azurerm_subnet blocks. With JavaScript on, the plan is worked out in your browser and nothing you type is sent to us. Without JavaScript the form sends your network and needs to our server in the page address. The subnet calculator shows the details of any one block from the plan.

Questions people ask

What is the difference between VLSM and fixed-size subnetting?

Fixed-size subnetting cuts a network into equal pieces. VLSM lets each subnet have the size it needs, so less address space is wasted. This page does both: sized by need, or an equal split.

Why are the largest subnets placed first?

Blocks must start on a multiple of their own size. Placing large blocks first keeps them aligned and leaves the free space in a few large pieces. Placing small blocks first can fragment the space so that a later large block no longer fits.

How many hosts does a /24 hold?

A /24 has 256 addresses and 254 usable hosts, because the network address and the broadcast address are not given to hosts. In AWS and Azure it holds 251, and in Google Cloud 252, because the provider keeps some.

Why does every IPv6 subnet get a /64?

IPv6 hosts configure themselves on a /64, and a /64 holds about 18 quintillion addresses. Sizing IPv6 subnets by host count does not save anything, so the planner counts subnets instead.

Can I write a size as a prefix instead of a host count?

Yes. Write Guests: /26 and that subnet is exactly a /26. A line such as Servers: 200 means 200 hosts. You can mix both in one list.

How many subnets can I plan at once?

Up to 256 named needs, or an equal split into up to 4,096 subnets. A split that would make more is refused with a note to choose a bigger prefix.

Use it from AI, the API or the command line

Every LookupOwl tool is also a free API and an MCP tool, with no key and no account. This one is subnet_plan. Please be kind to the rate limits.

curl
curl "https://lookupowl.com/api/v1/tools/subnet-plan?q=10.20.0.0%2F22&requirements=Servers%3A+200%0AOffice%3A+120%0AGuests%3A+50%0APrinters%3A+12%0AUplink%3A+2"
MCP
claude mcp add --transport http lookupowl https://lookupowl.com/mcp