X Xerobit

IPv6 Subnetting — Addresses, Prefixes, and Network Planning

IPv6 subnetting uses 128-bit addresses and /64 prefix lengths for LAN segments. Learn IPv6 address format, how to calculate subnet ranges, common prefix allocations, and the...

Mian Ali Khalid · · 5 min read
Use the tool
Subnet / CIDR Calculator
Calculate IPv4 subnets — network, broadcast, usable range, wildcard mask. Input CIDR (/24) or dotted mask (255.255.255.0). Binary visualization.
Open Subnet / CIDR Calculator →

IPv6 uses 128-bit addresses written in hexadecimal. A typical home network gets a /48 prefix from their ISP and divides it into /64 subnets — one per network segment.

Calculate subnet ranges with the Subnet Calculator.

IPv6 address format

Full address:  2001:0db8:0000:0042:0000:8a2e:0370:7334
Compressed:    2001:db8::42:0:8a2e:370:7334

Rules:
- 8 groups of 4 hex digits, separated by colons
- Leading zeros in a group can be omitted: 0042 → 42
- One consecutive run of all-zero groups can be replaced with ::
  2001:0db8:0000:0000:0000:0000:0000:0001
  → 2001:db8::1

Parts:
  [Global routing prefix][Subnet ID][Interface ID]
  2001:db8:1234    :0001  :0000:0000:0000:0001
  ──────────────── ──────  ─────────────────────
  48-bit ISP prefix 16-bit  64-bit host (interface)
                   subnet

Common prefix lengths

/32   — Regional Internet Registry (RIR) allocation
/40   — Large enterprise minimum allocation
/48   — Standard ISP allocation to a customer
/56   — Some ISPs allocate to residential customers
/64   — Single LAN segment (standard subnet size)
/128  — Single host (like IPv4's /32)

Rule: Always use /64 for subnets with hosts.
SLAAC (auto-address configuration) requires a /64.

IPv6 vs IPv4 subnetting

FeatureIPv4IPv6
Address length32 bits128 bits
Address formatDecimal dottedHex colon-separated
Subnet notation192.168.1.0/242001:db8::/32
Typical LAN subnet/24 (254 hosts)/64 (18 quintillion hosts)
Private addresses10.0.0.0/8, etc.fc00::/7 (ULA)
Auto-configurationDHCPSLAAC (stateless)
NATCommonNot needed
BroadcastYesReplaced by multicast

Calculate IPv6 subnet range

// IPv6 subnet calculator (simplified for /64 networks)
function parseIPv6(addr) {
  // Expand :: shorthand
  const parts = addr.split('::');
  const left = parts[0] ? parts[0].split(':') : [];
  const right = parts[1] ? parts[1].split(':') : [];
  const middle = Array(8 - left.length - right.length).fill('0000');
  return [...left, ...middle, ...right].map(p => p.padStart(4, '0'));
}

function ipv6NetworkRange(prefix) {
  const [addr, prefixLen] = prefix.split('/');
  const len = parseInt(prefixLen);
  const groups = parseIPv6(addr);
  
  // Network address: zero host bits
  const networkBits = groups.join('').split('').map((bit, i) => {
    // Position i corresponds to bit i in the 128-bit address
    const bitIndex = Math.floor(i / 4) * 16 + (i % 4) * 4;  // Simplified
    return i < len ? bit : '0';
  });
  
  // For /64: first 64 bits are network, last 64 are host
  const networkGroups = groups.map((g, i) => {
    if (i < len / 16) return g;           // Full group in network part
    if (i >= Math.ceil(len / 16)) return '0000';  // Full group in host part
    // Partial group (at boundary):
    const bitsInGroup = len % 16;
    const mask = 0xFFFF & (0xFFFF << (16 - bitsInGroup));
    return (parseInt(g, 16) & mask).toString(16).padStart(4, '0');
  });
  
  const lastGroups = groups.map((g, i) => {
    if (i < len / 16) return g;
    if (i >= Math.ceil(len / 16)) return 'ffff';
    const bitsInGroup = len % 16;
    const mask = 0xFFFF & (0xFFFF << (16 - bitsInGroup));
    const hostMask = ~mask & 0xFFFF;
    return ((parseInt(g, 16) & mask) | hostMask).toString(16).padStart(4, '0');
  });
  
  return {
    network: networkGroups.join(':'),
    last: lastGroups.join(':'),
    hosts: prefixLen === '128' ? 1 : `2^${128 - len}`,
  };
}

// /64 subnet:
ipv6NetworkRange('2001:db8:1:1::/64');
// { network: '2001:0db8:0001:0001:0000:0000:0000:0000',
//   last:    '2001:0db8:0001:0001:ffff:ffff:ffff:ffff',
//   hosts:   '2^64' }

ISP allocation hierarchy

ISP gets: 2001:db8::/32

Customer 1 gets: 2001:db8:1000::/48
  Subnet 1:      2001:db8:1000:0001::/64  (office LAN)
  Subnet 2:      2001:db8:1000:0002::/64  (DMZ)
  Subnet 3:      2001:db8:1000:0003::/64  (management)
  Available:     2001:db8:1000:0004::/64 ... 2001:db8:1000:ffff::/64
                 = 65,532 more /64 subnets

Customer 2 gets: 2001:db8:2000::/48
  ...

The /48 gives each customer 2^16 = 65,536 /64 subnets.
Even assigning one /64 per device is fine — no NAT needed.

Unique Local Addresses (ULA) — IPv6 equivalent of RFC1918

fc00::/7 — Unique Local Addresses (not routable on internet)
  fd00::/8 — Locally assigned (most common)

Generate a random ULA prefix:
fd + random 40 bits + ::/48

Example: fd12:3456:7890::/48
  Subnets: fd12:3456:7890:0001::/64
           fd12:3456:7890:0002::/64
           ...

JavaScript ULA generator:
function generateULA() {
  const bytes = crypto.getRandomValues(new Uint8Array(5));
  const hex = [...bytes].map(b => b.toString(16).padStart(2, '0')).join('');
  return `fd${hex.slice(0,2)}:${hex.slice(2,6)}:${hex.slice(6,10)}::/48`;
}

SLAAC: stateless address auto-configuration

SLAAC lets devices generate their own IPv6 addresses:
1. Router advertises prefix: 2001:db8:1:1::/64
2. Device generates 64-bit interface ID from MAC or random
3. Full address: 2001:db8:1:1:[interface-id]

EUI-64 (older): interface ID derived from MAC address
  MAC: 00:1A:2B:3C:4D:5E
  EUI-64: 021A:2BFF:FE3C:4D5E
  Address: 2001:db8:1:1:021a:2bff:fe3c:4d5e

Privacy extension (RFC 4941, default in most OSes):
  Random 64-bit suffix, changes periodically → prevents tracking
  Address: 2001:db8:1:1:[random]::[random]

Related posts

Related tool

Subnet / CIDR Calculator

Calculate IPv4 subnets — network, broadcast, usable range, wildcard mask. Input CIDR (/24) or dotted mask (255.255.255.0). Binary visualization.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.