Ipv6 Subnet Calculator

IPv6 Subnet Calculator

Example: 2001:db8:1234::/48
Common values: 64 for host networks, 56 for smaller sites.

Understanding IPv6 Subnetting

IPv6 subnetting is the process of dividing a larger IPv6 network into smaller, more manageable subnetworks. Unlike IPv4, which often requires complex calculations to conserve addresses, IPv6 offers an abundance of addresses (2128), simplifying subnetting considerably.

Why Subnet IPv6?

  • Network Organization: Subnetting helps in logically segmenting a network, making it easier to manage and troubleshoot.
  • Security: Isolating different parts of a network into separate subnets can enhance security by limiting broadcast domains and controlling traffic flow.
  • Performance: Smaller broadcast domains can reduce network congestion.
  • Standard Practices: Common IPv6 allocation practices, such as assigning a /64 prefix to every end-user segment, make subnetting a fundamental part of IPv6 network design.

Key Concepts:

  • IPv6 Address Format: IPv6 addresses are 128-bit numbers, typically represented as eight groups of four hexadecimal digits separated by colons (e.g., 2001:0db8:85a3:0000:0000:8a2e:0370:7334). Shorthand notations like omitting leading zeros in a group or using :: for a contiguous block of zero groups are common.
  • Prefix Length (CIDR): Similar to IPv4, IPv6 uses CIDR (Classless Inter-Domain Routing) notation to denote the network portion of an address. A prefix length (e.g., /64) indicates how many bits from the left are part of the network address, with the remaining bits available for host addresses or further subnetting.
  • Common Prefix Lengths:
    • /128: A single host address (e.g., loopback ::1/128).
    • /64: The standard prefix length for end-user subnets. It provides 264 host addresses, which is an enormous number, ensuring enough addresses for any conceivable local network.
    • /56: Often used by ISPs to assign to smaller customer sites, allowing them to create 2(64-56) = 28 = 256 /64 subnets.
    • /48: Typically assigned to larger customer sites or organizations, allowing them to create 2(64-48) = 216 = 65,536 /64 subnets.

How to Use This Calculator:

  1. Enter IPv6 Network Address (CIDR): Input the IPv6 network address you want to subnet, including its current prefix length. For example, if your ISP assigned you 2001:db8:1234::/48, enter that.
  2. Enter Desired Subnet Prefix Length: Specify the prefix length you want for your new subnets. For instance, if you want to create /64 subnets from your /48 allocation, enter 64.
  3. Click "Calculate Subnets": The calculator will then display:
    • The original network.
    • The desired subnet prefix length.
    • The total number of subnets you can create.
    • The number of assignable addresses within each new subnet.
    • A list of the first few generated subnets.

Example:

Suppose you have been allocated the IPv6 network 2001:db8:abcd::/48 and you want to create /64 subnets for your various departments.

  • IPv6 Network Address (CIDR): 2001:db8:abcd::/48
  • Desired Subnet Prefix Length: 64

The calculator would show that you can create 2(64-48) = 216 = 65,536 subnets, each with 264 assignable addresses. The first few subnets would be:

  • 2001:db8:abcd:0000::/64
  • 2001:db8:abcd:0001::/64
  • 2001:db8:abcd:0002::/64
  • …and so on.
// Helper to expand IPv6 address to its full 8 hextets function expandIPv6(ipv6) { var parts = ipv6.split('::'); var expanded = []; if (parts.length === 1) { // No '::' expanded = parts[0].split(':'); } else if (parts.length === 2) { // Contains '::' var left = parts[0].split(':').filter(function(p) { return p !== "; }); var right = parts[1].split(':').filter(function(p) { return p !== "; }); var missing = 8 – (left.length + right.length); for (var i = 0; i < left.length; i++) { expanded.push(left[i]); } for (var i = 0; i < missing; i++) { expanded.push('0000'); } for (var i = 0; i < right.length; i++) { expanded.push(right[i]); } } else { return null; // Invalid IPv6 format } // Pad each part to 4 hex digits for (var i = 0; i < expanded.length; i++) { expanded[i] = ('0000' + expanded[i]).slice(-4); } return expanded.join(':'); } // Helper to compress IPv6 address (basic compression for longest zero sequence) function compressIPv6(expandedIPv6) { var hextets = expandedIPv6.split(':'); var bestStart = -1; var bestLen = 0; var currentStart = -1; var currentLen = 0; for (var i = 0; i bestLen) { bestStart = currentStart; bestLen = currentLen; } currentStart = -1; currentLen = 0; } } if (currentLen > bestLen) { // Check for trailing zeros bestStart = currentStart; bestLen = currentLen; } if (bestLen > 1) { // Only compress if more than one '0000' var compressedParts = []; for (var i = 0; i < hextets.length; i++) { if (i === bestStart) { compressedParts.push(''); // Placeholder for :: i += bestLen – 1; } else { compressedParts.push(parseInt(hextets[i], 16).toString(16)); // Remove leading zeros } } var result = compressedParts.join(':'); // Handle edge cases like ":::" becoming "::" result = result.replace(':::', '::'); // Handle leading/trailing :: if (result.startsWith(':') && !result.startsWith('::')) result = ':' + result; if (result.endsWith(':') && !result.endsWith('::')) result = result + ':'; return result; } else { // No compression, just remove leading zeros from hextets return hextets.map(function(h) { return parseInt(h, 16).toString(16); }).join(':'); } } // Convert IPv6 address string to BigInt function ipv6ToBigInt(ipv6) { var expanded = expandIPv6(ipv6); if (!expanded) return null; var hexString = expanded.replace(/:/g, ''); return BigInt('0x' + hexString); } // Convert BigInt to IPv6 address string function bigIntToIPv6(bigIntVal) { var hexString = bigIntVal.toString(16); // Pad with leading zeros to 32 characters (128 bits) while (hexString.length < 32) { hexString = '0' + hexString; } var hextets = []; for (var i = 0; i < hexString.length; i += 4) { hextets.push(hexString.substring(i, i + 4)); } return compressIPv6(hextets.join(':')); } function calculateIPv6Subnets() { var ipv6AddressInput = document.getElementById('ipv6AddressInput').value.trim(); var desiredPrefixLengthInput = document.getElementById('desiredPrefixLengthInput').value.trim(); var resultDisplay = document.getElementById('resultDisplay'); resultDisplay.innerHTML = ''; // Clear previous results // 1. Validate IPv6 Address format var parts = ipv6AddressInput.split('/'); if (parts.length !== 2) { resultDisplay.innerHTML = 'Error: IPv6 Address must be in CIDR format (e.g., 2001:db8::/48).'; return; } var baseIPv6 = parts[0]; var originalPrefix = parseInt(parts[1], 10); if (isNaN(originalPrefix) || originalPrefix 128) { resultDisplay.innerHTML = 'Error: Original prefix length must be a number between 0 and 128.'; return; } // Basic IPv6 address validation (more robust regex could be used, but expandIPv6 handles some) if (!/^[0-9a-fA-F:]+$/.test(baseIPv6)) { resultDisplay.innerHTML = 'Error: Invalid IPv6 address format.'; return; } // Check if expandIPv6 returns null for truly invalid addresses if (expandIPv6(baseIPv6) === null) { resultDisplay.innerHTML = 'Error: Invalid IPv6 address format.'; return; } // 2. Validate Desired Prefix Length var desiredPrefix = parseInt(desiredPrefixLengthInput, 10); if (isNaN(desiredPrefix) || desiredPrefix 128) { resultDisplay.innerHTML = 'Error: Desired Subnet Prefix Length must be a number between 1 and 128.'; return; } if (desiredPrefix <= originalPrefix) { resultDisplay.innerHTML = 'Error: Desired Subnet Prefix Length must be greater than the original prefix length.'; return; } // Convert base IPv6 to BigInt var ipv6BigInt = ipv6ToBigInt(baseIPv6); if (ipv6BigInt === null) { // Should be caught by expandIPv6 check above, but good to double check resultDisplay.innerHTML = 'Error: Invalid IPv6 address format.'; return; } // Mask the IPv6 address to its network portion based on originalPrefix // Create a mask for the network portion: all 1s for network bits, all 0s for host bits // Example: for /48, mask is 48 ones, then 80 zeros. // (1 << (128 – originalPrefix)) creates a 1 at the (128 – originalPrefix) position. // Subtracting 1 makes all bits to the right of that 1 into 1s. // So, (BigInt(1) << BigInt(128 – originalPrefix)) – BigInt(1) creates a mask of all 0s for network, all 1s for host. // We need to invert this to get all 1s for network, all 0s for host. var hostMask = (BigInt(1) << BigInt(128 – originalPrefix)) – BigInt(1); var networkAddressBigInt = ipv6BigInt & (~hostMask); // Apply the network mask // Calculate subnetting details var subnetBits = desiredPrefix – originalPrefix; var numberOfSubnets = BigInt(1) << BigInt(subnetBits); var addressesPerSubnet = BigInt(1) << BigInt(128 – desiredPrefix); var incrementStep = BigInt(1) << BigInt(128 – desiredPrefix); var output = '

IPv6 Subnetting Results

'; output += 'Original Network: ' + bigIntToIPv6(networkAddressBigInt) + '/' + originalPrefix + "; output += 'Desired Subnet Prefix Length: /' + desiredPrefix + "; output += 'Number of Subnets Created: ' + numberOfSubnets.toLocaleString() + "; output += 'Assignable Addresses per Subnet: ' + addressesPerSubnet.toLocaleString() + ' (2' + (128 – desiredPrefix) + ')'; output += '

First 20 Subnets:

'; output += '
    '; var currentSubnetBigInt = networkAddressBigInt; for (var i = 0; i < Math.min(20, Number(numberOfSubnets)); i++) { output += '
  • ' + bigIntToIPv6(currentSubnetBigInt) + '/' + desiredPrefix + '
  • '; currentSubnetBigInt += incrementStep; } if (numberOfSubnets > 20) { output += '
  • … (' + (numberOfSubnets – 20).toLocaleString() + ' more subnets)
  • '; } output += '
'; resultDisplay.innerHTML = output; }

Leave a Comment