VLSM (Variable Length Subnet Masking) Calculator
ANA›Life Services Authority›National Calculator Authority›VLSM (Variable Length Subnet Masking) Calculator
.calc-container { max-width: 640px; margin: 2rem 0; padding: 1.5rem; background: #fff; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); font-family: system-ui, -apple-system, sans-serif; } .calc-container h3 { font-family: Georgia, serif; font-size: 1.15rem; color: #1a1a1a; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 2px solid var(--ac, #3d5a80); } .calc-row { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem; flex-wrap: wrap; } .calc-row label { min-width: 160px; font-size: 0.9rem; color: #333; font-weight: 500; } .calc-row input[type="number"], .calc-row select { flex: 1; min-width: 120px; max-width: 200px; padding: 0.5rem 0.6rem; border: 1px solid #ccc; border-radius: 4px; font-size: 0.9rem; font-family: system-ui, sans-serif; color: #1a1a1a; background: #fafaf8; } .calc-row input:focus, .calc-row select:focus { outline: none; border-color: var(--ac, #3d5a80); box-shadow: 0 0 0 2px rgba(26,74,138,0.12); } .calc-row .unit { font-size: 0.82rem; color: #888; min-width: 30px; } .calc-btn { display: inline-block; margin-top: 0.5rem; padding: 0.55rem 1.5rem; background: var(--ac, #3d5a80); color: #fff; border: none; border-radius: 4px; font-size: 0.9rem; font-weight: 600; cursor: pointer; font-family: system-ui, sans-serif; } .calc-btn:hover { opacity: 0.9; } .calc-result { margin-top: 1.25rem; padding: 1rem 1.25rem; background: #f0f6fc; border-left: 3px solid var(--ac, #3d5a80); border-radius: 0 6px 6px 0; display: none; } .calc-result.visible { display: block; } .calc-result-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; color: #666; margin-bottom: 0.25rem; } .calc-result-value { font-size: 1.6rem; font-weight: 700; color: var(--ac, #3d5a80); } .calc-result-detail { font-size: 0.85rem; color: #555; margin-top: 0.5rem; line-height: 1.5; } .calc-note { margin-top: 1rem; font-size: 0.8rem; color: #888; font-style: italic; } .calc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin-top: 0.75rem; } .calc-grid-item { padding: 0.6rem 0.8rem; background: #f8f9fa; border-radius: 4px; border: 1px solid #eee; } .calc-grid-item .label { font-size: 0.75rem; color: #888; text-transform: uppercase; letter-spacing: 0.04em; } .calc-grid-item .value { font-size: 1.1rem; font-weight: 600; color: #1a1a1a; } @media (max-width: 720px) { .calc-row { flex-direction: column; align-items: flex-start; gap: 0.3rem; } .calc-row label { min-width: auto; } .calc-row input[type="number"], .calc-row select { max-width: 100%; width: 100%; } .calc-grid { grid-template-columns: 1fr; } } .calc-chart { margin: 1rem 0; text-align: center; } .calc-chart svg { max-width: 100%; height: auto; } .calc-chart-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem 1.2rem; margin-top: 0.6rem; font-size: 0.8rem; color: #555; } .calc-chart-legend span { display: inline-flex; align-items: center; gap: 0.3rem; } .calc-chart-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; font-style: normal; } .calc-related { max-width: 640px; margin: 2rem 0 1rem; padding: 1.25rem 1.5rem; background: #f8f9fa; border: 1px solid #e8e8e8; border-radius: 8px; } .calc-related h3 { font-family: Georgia, serif; font-size: 1rem; color: #1a1a1a; margin: 0 0 0.75rem; padding-bottom: 0.4rem; border-bottom: 2px solid var(--ac, #3d5a80); } .calc-related-list { list-style: none; padding: 0; margin: 0 0 0.75rem; display: grid; grid-template-columns: 1fr 1fr; gap: 0.4rem 1.5rem; } .calc-related-list li a { font-size: 0.88rem; color: var(--ac, #3d5a80); text-decoration: none; } .calc-related-list li a:hover { text-decoration: underline; } .calc-browse-all { margin: 0.5rem 0 0; font-size: 0.9rem; font-weight: 600; } .calc-browse-all a { color: var(--ac, #3d5a80); text-decoration: none; } .calc-browse-all a:hover { text-decoration: underline; } @media (max-width: 720px) { .calc-related-list { grid-template-columns: 1fr; } }
VLSM (Variable Length Subnet Masking) Calculator
Efficiently allocate IP address space by dividing a network into subnets of varying sizes based on your host requirements. Enter a base network and the number of hosts needed for each subnet.
Base Network Address (e.g. 192.168.1.0/24)
Subnet Host Requirements (one per line, e.g. "Sales 50" or just "50") Sales 50 HR 25 IT 10 Management 5
Calculate Subnets
...
function vlsCalc() { const resultDiv = document.getElementById('vls-result');
// --- Parse base network --- const networkInput = document.getElementById('vls-network').value.trim(); const cidrMatch = networkInput.match(/^(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\/(\d{1,2})$/); if (!cidrMatch) { resultDiv.innerHTML = '❌ Invalid network format. Use CIDR notation, e.g. 192.168.1.0/24'; return; }
const baseIP = cidrMatch[1]; const basePrefixLen = parseInt(cidrMatch[2]);
if (basePrefixLen 30) { resultDiv.innerHTML = '❌ Prefix length must be between 0 and 30.'; return; }
// Validate base IP octets const octets = baseIP.split('.').map(Number); if (octets.some(o => o 255)) { resultDiv.innerHTML = '❌ Invalid IP address octets.'; return; }
// Convert IP to 32-bit integer function ipToInt(ip) { const parts = ip.split('.').map(Number); return ((parts[0] >> 0; }
function intToIp(n) { n = n >>> 0; return [(n >>> 24) & 0xFF, (n >>> 16) & 0xFF, (n >>> 8) & 0xFF, n & 0xFF].join('.'); }
function prefixToMask(prefix) { if (prefix === 0) return 0; return (0xFFFFFFFF >> 0; }
function maskToWildcard(mask) { return (~mask) >>> 0; }
// --- Parse subnet requirements --- const subnetLines = document.getElementById('vls-subnets').value.trim().split('\n').filter(l => l.trim() !== ''); if (subnetLines.length === 0) { resultDiv.innerHTML = '❌ Please enter at least one subnet requirement.'; return; }
const subnets = []; for (let i = 0; i ❌ Invalid entry on line ' + (i+1) + ': "' + line + '". Use format "Name Hosts" or just "Hosts".'; return; } const name = match[1].trim() || ('Subnet ' + (i+1)); const hosts = parseInt(match[2]); if (hosts 16777214) { resultDiv.innerHTML = '❌ Host count on line ' + (i+1) + ' must be between 1 and 16,777,214.'; return; } subnets.push({ name, hosts }); }
// --- VLSM Algorithm --- // Sort subnets by host count descending (largest first) subnets.sort((a, b) => b.hosts - a.hosts);
// Calculate required prefix for each subnet // Hosts needed = 2^(32-prefix) - 2 >= hosts required // So 32-prefix >= ceil(log2(hosts+2)) // prefix >> 0;
if (actualBaseNet !== baseNetInt) { resultDiv.innerHTML = '❌ The IP address is not a valid network address for /' + basePrefixLen + '. Did you mean ' + intToIp(actualBaseNet) + '/' + basePrefixLen + '?'; return; }
// Total available addresses in base network const totalAvailable = Math.pow(2, 32 - basePrefixLen);
// Check if all subnets fit let totalRequired = 0; const subnetPrefixes = []; for (const s of subnets) { const prefix = requiredPrefix(s.hosts); if (prefix ❌ Subnet "' + s.name + '" requires /' + prefix + ' which is larger than the base network /' + basePrefixLen + '.'; return; } if (prefix > 30) { resultDiv.innerHTML = '❌ Subnet "' + s.name + '" requires too many hosts for a valid subnet (max 2 hosts per /30).'; return; } const size = Math.pow(2, 32 - prefix); totalRequired += size; subnetPrefixes.push(prefix); }
if (totalRequired > totalAvailable) { resultDiv.innerHTML = '❌ Insufficient address space. Required: ' + totalRequired + ' addresses, Available: ' + totalAvailable + ' addresses in /' + basePrefixLen + '.'; return; }
// Allocate subnets let currentIP = actualBaseNet; const results = [];
for (let i = 0; i >> 0; currentIP = aligned;
const networkAddr = currentIP; const broadcastAddr = (currentIP + size - 1) >>> 0; const firstHost = (networkAddr + 1) >>> 0; const lastHost = (broadcastAddr - 1) >>> 0; const usableHosts = size - 2;
results.push({ name: s.name, hostsRequired: s.hosts, prefix, size, networkAddr: intToIp(networkAddr), broadcastAddr: intToIp(broadcastAddr), firstHost: intToIp(firstHost), lastHost: intToIp(lastHost), subnetMask: intToIp(mask), wildcardMask: intToIp(wildcard), usableHosts, cidr: intToIp(networkAddr) + '/' + prefix });
currentIP = (broadcastAddr + 1) >>> 0; }
// Calculate address utilization const usedAddresses = results.reduce((sum, r) => sum + r.size, 0); const utilization = ((usedAddresses / totalAvailable) * 100).toFixed(2); const wastedAddresses = usedAddresses - subnets.reduce((sum, s) => sum + s.hosts, 0);
// Build result table let html = '### VLSM Allocation Results '; html += 'Base Network: ' + intToIp(actualBaseNet) + '/' + basePrefixLen; html += ' | Total Addresses: ' + totalAvailable.toLocaleString(); html += ' | Used: ' + usedAddresses.toLocaleString(); html += ' | Utilization: ' + utilization + '%
';
html += ''; html += ''; html += 'Subnet Name'; html += 'Hosts Req.'; html += 'Prefix'; html += 'Network Address'; html += 'Subnet Mask'; html += 'Wildcard Mask'; html += 'First Host'; html += 'Last Host'; html += 'Broadcast'; html += 'Usable Hosts'; html += 'Total Addr.'; html += '';
results.forEach((r, idx) => { const bg = idx % 2 === 0 ? '#f9f9f9' : '#fff'; html += ''; html += '' + r.name + ''; html += '' + r.hostsRequired.toLocaleString() + ''; html += '/' + r.prefix + ''; html += '' + r.cidr + ''; html += '' + r.subnetMask + ''; html += '' + r.wildcardMask + ''; html += '' + r.firstHost + ''; html += '' + r.lastHost + ''; html += '' + r.broadcastAddr + ''; html += '' + r.usableHosts.toLocaleString() + ''; html += '' + r.size.toLocaleString() + ''; html += ''; });
html += '';
// Summary stats html += ''; html += 'Summary: '; html += results.length + ' subnets allocated | '; html += 'Total hosts required: ' + subnets.reduce((s,r) => s + r.hosts, 0).toLocaleString() + ' | '; html += 'Total usable hosts allocated: ' + results.reduce((s,r) => s + r.usableHosts, 0).toLocaleString() + ' | '; html += 'Address waste (overhead): ' + wastedAddresses.toLocaleString() + ' addresses | '; const remaining = totalAvailable - usedAddresses; html += 'Remaining unallocated: ' + remaining.toLocaleString() + ' addresses'; html += '';
resultDiv.innerHTML = html; }
#### Formula
Required Prefix Length:
prefix = 32 - ⌈log₂(hosts_required + 2)⌉ subnet_size = 2^(32 - prefix) usable_hosts = subnet_size - 2 network_address = base_ip & subnet_mask broadcast_address = network_address + subnet_size - 1 first_host = network_address + 1 last_host = broadcast_address - 1 subnet_mask = 0xFFFFFFFF << (32 - prefix) wildcard_mask = ~subnet_mask
The +2 accounts for the network address and broadcast address which cannot be assigned to hosts. Subnets are sorted largest-to-smallest and allocated sequentially to minimize wasted address space.
#### Assumptions & References
- VLSM allocates subnets in descending order of host requirements (largest first) to minimize fragmentation and wasted address space.
- Each subnet requires at least 2 extra addresses: one for the network address and one for the broadcast address.
- Subnet sizes are always powers of 2 (e.g., /30 = 4 addresses, /29 = 8, /28 = 16, etc.).
- The minimum usable subnet is /30 (2 usable hosts). /31 and /32 are excluded as they are special-purpose (RFC 3021 and loopback).
- Each subnet is boundary-aligned: the network address must be a multiple of the subnet size.
- RFC 950 – Internet Standard Subnetting Procedure.
- RFC 1009 – Requirements for Internet Gateways (VLSM support).
- RFC 1519 – Classless Inter-Domain Routing (CIDR).
More Calculators
- Hydro Jetting Pressure & Flow Rate Calculator
- Yahtzee Probability Calculator
- Watershed Runoff Calculator
- Drain Flow Rate & Blockage Severity Calculator
- D&D 5e Spell Slot Calculator
- Child Support Estimate Calculator
- Rock Density and Porosity Calculator
- Diminished Value Calculator
- Subrogation Recovery Calculator
- Bad Faith Damages Estimator
- General Liability Coverage Limit Calculator
- Umbrella Policy Coverage Gap Calculator
Read Next
Study Time Planner ANA › Life Services Authority › National Calculator Authority › Study Time Planner .calc-container { max-width: 640px; margin:...