SD-WAN Address Planner: Plan IPv4 Addressing for 8 to 10,000 Sites
The address plan is the part of an SD-WAN project that is hardest to change later. Tunnels can be rebuilt, policies can be rewritten, and hubs can be moved, but renumbering a few hundred sites that already carry traffic is a project in its own right. Most of the renumbering I have seen traced back to the same few decisions made in the first week: a parent range that was too small, site blocks that did not leave room to grow, or ranges that collided with something nobody checked.
I built the SD-WAN Address Planner to make those decisions with numbers in front of me. It runs entirely in your browser, nothing you type is sent anywhere, and it is listed with my other tools on the projects page. There is also a command line and Python library version, on GitHub, covered near the end.
What it does
You give it a parent range, then describe the design: how many regions and hubs, how many cloud networks, how many transports each site has, and how much growth to allow. Then you describe your site types. Each type has a site count and its own segments, for example Corporate, Voice, Guest, IoT, Management, Servers or Cameras. Each segment has a host count, and you can force a prefix length or set a VLAN ID if you need to.
From that it produces:
- A subnet for every segment, sized to the hosts, the growth and the reserved addresses per subnet.
- A block for every site type, packed so each block sits on its natural boundary.
- A summary route per region and one for the whole design.
- Hub LAN, cloud network, overlay tunnel and loopback pools.
- A count of overlay tunnels, and how many each hub has to terminate.
- The free space left in your parent, as aligned blocks.
- Warnings for non-private space, for ranges that often clash, such as Docker, Kubernetes, AWS and GCP defaults, home routers and the FortiOS SSL VPN default tunnel range, and for any range you tell it you already use.
How the sizing works
Every block is a power of two, and everything is packed largest first. That is what keeps the plan summarisable. A site’s segments are packed into one site block. Site blocks of the same type are grouped into a pool sized for the planned site count, including growth. Pools are grouped by region. Because each level starts on its own boundary, each one advertises as a single route.
Take the small preset, eight branches. A branch has 30 corporate hosts, 20 guest, 10 voice and 5 management. After 25% host growth and three reserved addresses per subnet, those become a /26, a /27, a /28 and a /28. Together they fit a /25 per site. With 50% site growth the planner reserves room for 16 sites, a /21 pool starting at 10.20.0.0/21. Overlay addressing for 24 tunnels takes a /26, 13 loopbacks take a /28, and the whole design needs a /20.
The formula for any site is simple: the pool base plus the site number times the site size. For the branch pool that is 10.20.0.0 plus n times 128. That is the part I care about most, because it can be dropped straight into a Jinja template or an Ansible variable file, and every site’s subnet is then predictable instead of looked up.
Three sizes, side by side
| Design | Sites | Regions | Needs | Tunnels | Tunnels per hub |
|---|---|---|---|---|---|
| Mid-size | 50 now, 66 planned | 1 | /16 | 264 | 132 |
| Large enterprise | 1,000 now, 1,200 planned | 3 | /11 | 6,000 | 1,000 |
| ISP or MSSP | 10,000 now, 12,000 planned | 4 | /9 | 48,000 | 6,000 |
Those tunnel counts assume every spoke builds a tunnel to each hub in its own region on every transport. That is the plain hub-and-spoke case. Partial meshes and dual-device sites will change the real number, so treat it as a starting point and check it against your hub platform’s published limits. If you run Fortinet ADVPN, switch the tunnel model, described below.
Ranges you already use
You can paste the ranges that are already taken on your network, one per line with an optional label, for example 10.1.0.0/16 Head office. The planner checks every planned block against them and names the blocks that overlap, role by role. It also checks what is left free in the parent, and the “Suggest a quiet range” button keeps clear of your ranges as well as its built-in list.
It does not pack around your ranges. Blocks have to stay contiguous to summarise to a single route, so the planner tells you what overlaps and leaves the decision to you: move the parent, or take the suggestion. The ranges stay in your browser like everything else you type.
Fortinet ADVPN
The tunnel model setting switches between plain hub-and-spoke and Fortinet ADVPN. It changes two things.
Overlay addressing. In Fortinet’s ADVPN examples the hub and all of its spokes share one overlay subnet, with a /32 on each tunnel interface. So instead of a pair of addresses per tunnel, the planner reserves one shared subnet per hub per transport, sized for every spoke on it plus the hub. For the mid-size preset that takes the overlay pool from a /22 to a /23.
Shortcut tunnels. Spoke-to-spoke shortcuts are built on demand from an existing tunnel and reuse its address, so they add no addressing. They do count against the IPsec tunnel limits on your spokes. You enter your own estimate of peak concurrent shortcuts per spoke, because the planner cannot know your traffic pattern, and it turns that into a peak tunnels-per-spoke figure and a design-wide estimate. Check both numbers against your platform’s documented limits. The ADVPN design itself is covered in NSE7 Part 12.
Where I would use it
Sizing a new rollout before the first site goes live. The most useful number is the smallest parent that fits. If the plan needs a /20 and the business has offered you a /22, you find that out in a meeting, not after site 40.
Comparing designs. Changing a number is instant, so what-if questions are cheap. On the large preset, dropping from three transports to two takes the tunnel count from 6,000 to 4,800, and each hub from 1,000 tunnels to 800. That is the kind of difference that decides whether one pair of hubs per region is enough. It pairs with the hub placement question I covered in Fortinet SDWAN Hub Placement, Part 1.
Enterprise design with regional summarisation. In the large preset each region gets one aligned block, 10.0.0.0/13, 10.8.0.0/13 and 10.16.0.0/13. A region then advertises one route toward the rest of the network instead of hundreds, which keeps routing tables small and makes a regional failure easier to reason about.
Reserving space for the cloud. The planner lets you set a number of cloud networks and a prefix for each, and sets that space aside next to the site pools. That stops the situation where a VPC or VNet is created later in a range that overlaps a branch. The decisions behind those networks are in Cloud On-Ramp, Part 1.
Avoiding clashes. The large and ISP presets use 10.0.0.0/8 as the parent, and the planner flags that the allocation overlaps 10.0.0.0/24, 10.1.1.0/24 and 10.10.10.0/24, all very common default LANs. Add your own ranges and it flags those too. The suggestion button picks an aligned block of the size you need that avoids everything it knows about. It still only knows what you tell it, so it is a starting point, not a substitute for checking your IPAM.
Mergers and renumbering. When two networks have to be joined, the first question is where the combined plan fits. List one side’s ranges, describe the target design and ask for a quiet range, and you have a candidate parent to test against the other side.
Feeding automation and an IPAM. The site list export has one row per site per segment, with generated names such as BRANCH-001, the region, the VLAN and the subnet. The plan CSV and JSON exports hold the pools and the templates. I cover the IPAM options on the tool page itself, from a spreadsheet in Git through phpIPAM, NetBox and Nautobot to commercial DDI platforms. I treat the IPAM as the record and the planner as the tool that designs what goes into it.
The Python version
The same engine is available as a command line tool and a Python library: sdwan-address-planner on GitHub. It is MIT licensed, needs nothing beyond the Python standard library, and runs on Python 3.9 and newer.
pip install git+https://github.com/MichealGarner/sdwan-address-planner.git
sdwan-planner plan --preset medium --model advpn --avoid "10.60.3.0/24 Old HQ LAN"
sdwan-planner sites --preset medium -o sites.csv
It is for the cases where a browser page is the wrong shape: a plan kept in Git next to your templates, a CI job that fails when a design stops fitting or a new range collides, or a site list generated straight into a script. plan writes text, JSON or CSV, sites writes the per-site CSV, and suggest finds a quiet parent. The exit status is usable as a check: 0 is fine, 2 means the design does not fit the parent, and 3 means there are warnings when you pass --strict.
I wanted the two versions to give the same answers, so the repository includes a set of results generated by the JavaScript engine on this site for 39 plans, covering every preset, the ADVPN variants, ranges you already use, odd parents, forced prefixes and error cases. The Python tests require an exact match, down to the warning text and the subnet of every site. The test workflow runs on Python 3.9 to 3.13.
What it does not do
It is IPv4 only. It does not know what is already in use on your network beyond the ranges you give it, and the clash check otherwise compares against a short list of well-known defaults. It models hub-and-spoke and ADVPN tunnel counts, not every overlay topology, and the ADVPN shortcut figure is only as good as your estimate. And it designs address space, it does not track assignments afterwards, which is the job of an IPAM.
Try it
The planner is at michealgarner.co.uk/tools/sdwan-planner. Pick a preset, change the numbers until they match your design, and use the link button to share the exact plan with a colleague. If you would rather script it, the code is on GitHub. If you find a case it gets wrong, or a segment type or export you would want, get in touch and I will take a look.