Core CS · Computer Networks
We ran out of addresses, so the address got four times longer
IPv4 has 2³² addresses and the central pool was empty in 2011. IPv6 does not stretch the old header, it replaces it: 128 bits written in hex, one :: per address and never two, three kinds of address and no broadcast at all.
Compress one address to :: and expand it back, step by step →01 The idea
Thirty-two bits was never going to be enough
An IPv4 address is 32 bits, so there are 2³² = 4,294,967,296 of them. About 4.3 billion, on a planet with more than 8 billion people and several devices each. That number was fixed in 1981, when the entire network was a few hundred machines and nobody expected a phone to want one. It is not a design flaw so much as a design that outlived its assumptions.
Two things bought time and neither one added an address. CIDR, classless inter-domain routing, stopped the waste of handing an organisation a whole class B of 65,534 hosts when it needed 300; it made allocation finer-grained, which slows the burn rate. NAT, network address translation, lets a whole building share one public address by rewriting the port numbers on the way out. Both are rationing. Neither creates a thirty-third bit. IANA handed the last five blocks from its central pool to the regional registries on 3 February 2011, and the regional registries emptied one after another over the following years, starting with Asia-Pacific in April 2011.
NAT also costs something that does not show up on an invoice. Behind NAT your machine has no address the rest of the internet can reach, so anything that wants to connect to you needs a hole punched, a relay, or a server in the middle. The original design where any host could open a connection to any other host quietly stopped being true, and a generation of protocols was built around working past that.
So IPv6 does the only thing that actually fixes it: more bits. 128 of them, four times the length. Four times the bits is not four times the addresses, it is 2⁹⁶ times as many, and that number is hard to picture, so use a ratio instead of a decimal. One ordinary IPv6 LAN is a /64, which holds 2⁶⁴ addresses. Divide that by the whole IPv4 internet: 2⁶⁴ ÷ 2³² = 2³². One IPv6 subnet holds about 4.3 billion times every address IPv4 ever had. That is the scale, and it is why nobody subnets an IPv6 LAN to save space.
Having gone to the trouble, the designers also cleaned up everything else the twenty years of IPv4 had taught them was wrong. The header became a fixed size so a router can find the next field without arithmetic. The checksum went, because two other layers already check. Router fragmentation went, because it made routers do per-packet work for one badly sized sender. Broadcast went, because waking every card on a link to ask one of them a question is rude. And ARP was replaced by something that runs over ICMP instead of sitting beside IP as an odd little protocol of its own.
02 Worked example
One address, squeezed down and then put back
This is the address for the whole lesson, including the console in section 04 and every count in the cheat sheet. It sits in 2001:db8::/32, the block RFC 3849 reserves for documentation, so it can never collide with a real host: 2001:0db8:0000:0000:00ff:0000:0042:8329. Eight groups, four hex digits each, so 32 hex digits and 7 colons, 39 characters. Nobody writes an address like that, and the two rules that shorten it are the most commonly examined thing in the whole topic.
Do the character arithmetic yourself once, because it is the check that tells you the rules were applied and not guessed. Rule 1 removes 14 digits: one from 0db8, three from each of the three 0000 groups, two from 00ff, two from 0042, and nothing from 2001 or 8329. 1 + 3 + 3 + 2 + 3 + 2 = 14, and 39 − 14 = 25. Then rule 2 replaces the five characters :0:0: with the two characters ::, so 25 − 3 = 22. Notice that a group of all zeros collapses to a single 0 and not to nothing: dropping leading zeros can never leave a group empty, or the colons would run together and you would have made a second :: by accident.
The highlighted node is the one that decides the answer, and it is the one people get wrong. There were two zero runs to choose from and only one may be collapsed. Choosing the longer one is what makes the result short; choosing the leftmost when two runs are equally long is what makes it canonical, meaning that two people compressing the same address independently write the same string. RFC 5952 exists purely so that log files and access-control lists can be compared as text.
Now the trap, which is worth seeing rather than being told. Why not collapse both runs and write 2001:db8::ff::42:8329? Because expanding it has no unique answer. Five groups are actually written, so three are missing, and they have to be split across two gaps with at least one in each. That gives (2,1) and (1,2), which are two different, both perfectly legal addresses: 2001:0db8:0000:0000:00ff:0000:0042:8329 and 2001:0db8:0000:00ff:0000:0000:0042:8329. One string, two possible sets of 128 bits, and nothing in the notation to choose between them. That is the entire reason for the one-:: rule, and saying it that way in an interview is worth much more than reciting the rule.
03 Mechanics
The header, the three address types, and the two protocols that changed name
Four tables, in the order a packet meets them. First the header itself, because every design decision below is a decision about a field that is present or a field that is gone. Eight fields, always 40 bytes, and the last column is the IPv4 field each one replaced.
| Field | Bits | What it holds | What it replaced in IPv4 |
|---|---|---|---|
| Version | 4 | Always 6. First four bits on the wire, so a dual-stack card can branch immediately. | Version, unchanged in position and size. |
| Traffic Class | 8 | Priority and congestion marking, carrying DSCP and ECN exactly as IPv4 does. | Type of Service. Same job, renamed. |
| Flow Label | 20 | A tag the source picks so every packet of one conversation can be recognised as related without opening the transport header. | brand new — there is no IPv4 equivalent. |
| Payload Length | 16 | Bytes after this 40-byte header, extension headers included. Maximum 65,535; larger needs the jumbogram option of RFC 2675. | Total Length, but the definition changed: Total Length counted the IPv4 header too. |
| Next Header | 8 | What comes next. Either an upper-layer protocol (6 TCP, 17 UDP, 58 ICMPv6) or the type of the first extension header. | Protocol, with a second job: it also chains the extension headers. |
| Hop Limit | 8 | Decremented by one at each router; the packet is discarded at zero. Honestly named for what IPv4 always actually did. | Time To Live, which was never measured in time. |
| Source Address | 128 | 16 bytes. Must be a unicast address; an anycast or multicast address may never appear here. | Source Address, four times longer. |
| Destination Address | 128 | 16 bytes. Unicast, multicast or anycast. | Destination Address, four times longer. |
Forty bytes is bigger than twenty and simpler than twenty. Add the bits: 4 + 8 + 20 = 32 bits in the first word, 16 + 8 + 8 = 32 in the second, then 128 + 128 = 256 of address. 32 + 32 + 256 = 320 bits = 40 bytes, and it is 40 bytes for every packet that ever existed. IPv4's is 20 bytes only when there are no options; the IHL field is 4 bits counting 32-bit words, so 15 × 4 = 60 bytes is the maximum and a router has to read IHL before it knows where the payload starts. Now look at what the extra 20 bytes actually bought. Of IPv6's 40 bytes, 32 are the two addresses, leaving 40 − 32 = 8 bytes of everything else. IPv4 spends 20 − 8 = 12 bytes on everything else. So the non-address part of the header shrank, from 12 bytes to 8 and from 12 fixed fields down to 8. The header got larger only because the addresses did.
No header checksum, and that is not carelessness. IPv4 carried a 16-bit checksum over its own header, and because the TTL changes at every hop, every router had to recompute it for every packet. IPv6 deletes the field outright on the grounds that the layers on either side already check. Below, Ethernet's 4-byte FCS is a CRC-32 over the whole frame and a corrupt frame is dropped at the card. Above, TCP and UDP checksum their own header, their data, and a pseudo-header containing the IP addresses, so a flipped bit in an address is still caught end to end. There is one consequence worth knowing: the UDP checksum was optional in IPv4 and is mandatory in IPv6, precisely because it is now the only thing protecting the addresses of a UDP datagram.
Routers may not fragment. Only the source may. In IPv4 any router on the path could chop an oversized datagram into fragments, which meant per-packet work at exactly the device that is busiest and reassembly state at the destination for a problem the sender created. IPv6 forbids it: a router that cannot forward a packet on the next link discards it and sends an ICMPv6 Packet Too Big message, type 2, back to the source carrying that link's MTU. The source is expected to notice and either fragment the data itself using a Fragment extension header or send smaller packets from then on, which is why Path MTU Discovery stops being optional. As a floor, every IPv6 link must support an MTU of at least 1280 bytes, so a source that never listens to a single ICMPv6 message can still get data through by never exceeding 1280. Compare that with IPv4's minimum of 68 bytes and you can see the standard choosing a useful number over a permissive one.
Extension headers replace options. IPv4 options lived inside the header, up to 40 bytes of them, and every router had to parse them. IPv6 moves them out into a chain: Next Header in the fixed header names the first extension header, that one's own Next Header names the second, and the last names the transport protocol. So a plain TCP packet reads Next Header = 6 and the router is done after 40 bytes. The order RFC 8200 recommends is Hop-by-Hop Options first (protocol number 0, and the only one meant for every router on the path rather than for the destination alone — RFC 2460 had every router examine it, and RFC 8200 relaxed that to only routers configured to), then Destination Options, Routing (43), Fragment (44), then the IPsec headers AH (51) and ESP (50), then the upper layer. Everything except Hop-by-Hop is for the destination alone, which is the whole point: the fast path stays fast.
That is the packet. The bigger conceptual change is in the addresses it carries, because one of the four IPv4 kinds is gone outright and a new one has arrived.
| Type | Prefix you will recognise | Who receives a packet sent to it | What it is for |
|---|---|---|---|
| Unicast | 2000::/3 global, fe80::/10 link-local, fc00::/7 unique-local | Exactly one interface. | Ordinary traffic. ::1 is loopback and :: alone is the unspecified address a host uses before it has one. |
| Multicast | ff00::/8 — every multicast address starts ff | Every interface that has joined that group, and no others. | One-to-many. ff02::1 is all nodes on this link, ff02::2 is all routers on this link. |
| Anycast | No prefix of its own; an ordinary unicast address given to several machines | The nearest one, by the routing metric. The others are not disturbed. | Load spreading and proximity. Root DNS servers and public resolvers are anycast. The all-zeros interface identifier in every subnet is also reserved, as the Subnet-Router anycast address. |
| Broadcast | does not exist | Nothing. There is no address that means everyone. | Replaced by multicast to a well-known group, so a card that has not joined the group is never woken. |
Every interface has a link-local address, and it has it before anything else works. The block is fe80::/10, but the format defined by RFC 4291 requires the next 54 bits to be zero, so in practice every link-local address you will ever see begins fe80:: and then the 64-bit interface identifier. A host builds it entirely on its own: no router, no DHCP server, no cable to the outside world. That matters because the protocols that get the interface working are themselves IPv6 packets and have to come from somewhere. Neighbour discovery, router discovery and most routing-protocol adjacencies all run between link-local addresses. A router never forwards a packet with a link-local source or destination off the link, which is also why the same fe80::1 can exist on every interface of a machine and why Linux and Windows make you write a zone index like fe80::1%eth0 to say which link you mean. The private-address story is separate: unique local addresses, fc00::/7 and in practice always fd00::/8, are the IPv6 counterpart of RFC 1918's 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.
With broadcast gone, the protocol that leaned hardest on it had to be rebuilt. ARP asked its question by interrupting every card on the link; its replacement asks the same question of a multicast group that, in the normal case, exactly one card has joined.
| The job | IPv4 | IPv6 | The difference that matters |
|---|---|---|---|
| Find the MAC address for a neighbour's IP | ARP request, EtherType 0x0806, broadcast | Neighbor Solicitation, ICMPv6 type 135 | Sent to the solicited-node multicast address ff02::1:ff plus the target's low 24 bits, so uninterested cards filter it in hardware. |
| Answer with my MAC address | ARP reply, unicast | Neighbor Advertisement, ICMPv6 type 136 | Same idea, and it carries flags saying whether the sender is a router and whether this is a solicited answer. |
| Find a router | DHCP option, or a static default gateway | Router Solicitation 133, Router Advertisement 134 | Routers announce themselves. There is no configured default gateway on a normal host. |
| Tell a host about a better first hop | ICMP Redirect | Redirect, ICMPv6 type 137 | Same message, now part of one named protocol rather than a loose ICMP type. |
| Check nobody else has my address | Gratuitous ARP, optional | Duplicate Address Detection, built into NDP | A Neighbor Solicitation for the host's own tentative address, sourced from ::. Mandatory, not an add-on. |
| Get an address at all | DHCP, or 169.254.0.0/16 if the server never answers | SLAAC, or DHCPv6 when you want central control | The host builds its own address from the prefix in a Router Advertisement. No server is required. |
NDP is ICMPv6, and that is a real structural change. ARP sits beside IP: its own EtherType, its own frame format, no IP header at all, which always made it awkward to explain which layer it belongs to. NDP is carried in ordinary IPv6 packets with Next Header = 58, so it inherits IPv6's addressing, its hop limit and its ability to be authenticated with IPsec. A firewall that blocks all of ICMPv6 the way people habitually blocked ICMP in IPv4 breaks address resolution, router discovery and Path MTU Discovery in one move. That is a favourite exam question and a very common real outage.
SLAAC, and how a host invents its own address. Stateless address autoconfiguration, RFC 4862, runs in four moves. The host builds a link-local address and runs Duplicate Address Detection on it. It sends a Router Solicitation to ff02::2, all routers on this link. A router replies with a Router Advertisement carrying a /64 prefix. The host glues that prefix to its own 64-bit interface identifier and it has a global address, with no server anywhere in the story. The original way to build the identifier was modified EUI-64, and it is worth doing once by hand. Take the 48-bit MAC 00:1A:A0:00:00:0B, split it in the middle, insert FF:FE to get 00:1A:A0:FF:FE:00:00:0B, then complement the universal/local bit, which is the 0x02 bit of the first byte: 0x00 XOR 0x02 = 0x02. The identifier is 021a:a0ff:fe00:000b, which is why so many textbook addresses have ff:fe sitting in the middle. Modern hosts do not do this by default any more, because an identifier derived from the card would follow you across every network you joined and make you trivially trackable; Windows, macOS, Android and Linux now use the temporary addresses of RFC 8981 and the stable-but-opaque identifiers of RFC 7217 instead. Note also that a Router Advertisement can carry DNS servers directly, RFC 8106, which removes the last common reason to run DHCPv6 at all.
Everything above collapses into one table. This is the artefact to revise from, and it is worth being able to reproduce most of it from memory.
| Property | IPv4 | IPv6 |
|---|---|---|
| Address length | 32 bits, 4 bytes | 128 bits, 16 bytes |
| How many addresses | 2³² ≈ 4.3 billion | 2¹²⁸, which is 2⁹⁶ times as many |
| Written as | Four decimal octets, dotted: 192.168.1.1 | Eight hex groups, colons, one optional ::: 2001:db8::ff:0:42:8329 |
| Network part written as | Dotted mask 255.255.255.0 or /24 | prefix length only — /64. There is no mask notation. |
| Fixed header size | 20 to 60 bytes, read IHL to find out | 40 bytes, always |
| Header fields | 12 plus options | 8, options moved out to extension headers |
| Header checksum | yes, recomputed at every hop | none |
| Who may fragment | the source or any router | the source only, via a Fragment extension header |
| Minimum MTU a link must support | 68 bytes | 1280 bytes |
| Address types | unicast, multicast, broadcast | unicast, multicast, anycast — no broadcast |
| IP to MAC resolution | ARP, a broadcast beside IP | NDP, ICMPv6 multicast inside IP |
| Getting an address | DHCP, or 169.254.0.0/16 when it fails | SLAAC from a Router Advertisement; DHCPv6 optional |
| Private addressing | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 | Unique local fc00::/7, in practice fd00::/8 |
| Loopback | 127.0.0.1, and all of 127.0.0.0/8 | ::1, exactly one address |
| Typical LAN subnet | /24, 2⁸ − 2 = 254 usable hosts | /64, 2⁶⁴ addresses, always |
| Ethernet EtherType | 0x0800 | 0x86DD |
| IPsec | Bolted on afterwards, optional | Designed in as extension headers AH and ESP |
So why is the internet still mostly IPv4? Give the honest answer, because the honest answer is the interesting one: the two protocols are not interoperable. IPv6 is not a version negotiation on top of IPv4, it is a different packet with a different header and an address that does not fit in an IPv4 field. An IPv6-only host cannot open a connection to an IPv4-only server, full stop. There is no gradual upgrade in which half the path speaks the new protocol, so every device between the two ends has to support it before it is usable: the host, the switch, the router, the firewall, the load balancer, the middlebox nobody remembers buying. And NAT removed the pain that would have forced the issue, so the business case kept slipping. The transition therefore happens two ways at once. Dual stack is the main one, RFC 4213: a host runs both, gets both an IPv4 and an IPv6 address, and picks per destination, which is what your laptop is doing right now. Tunnelling carries IPv6 packets as the payload of something else across a stretch that does not speak it, which is what 6to4 and Teredo did and what a modern network does with a plain GRE or IPsec tunnel. Where a network really is IPv6-only, NAT64 with DNS64 and 464XLAT translate between the two at the edge, which is exactly how the large mobile carriers run IPv6-only cores and still let a handset reach an IPv4-only server. Google publishes the share of its own users arriving over IPv6, and it has sat in the forty-plus percent range for several years, which is the honest shape of the answer: not a switchover, a long overlap.
05 Cheat sheet
Thirteen answers to have ready
Every row is something you can be asked to state or work out in under ten seconds. The right-hand column is the specific wrong answer that gets given, not a general caution.
| What they ask | The answer | The trap |
|---|---|---|
| Address length | 128 bits = 16 bytes = 32 hex digits | saying 128 bytes, or halving it to 64 by confusing it with the interface identifier |
| How much bigger than IPv4 | 2⁹⁶ times, because 128 − 32 = 96 | Saying “four times”. Four times the bits, not four times the addresses. |
| How it is written | eight groups of four hex digits, colon-separated | calling a group an octet — a group is 16 bits, which is two octets |
| The two shortening rules | drop LEADING zeros per group; one run of all-zero groups becomes :: | Dropping trailing zeros. 0db0 shortens to db0, never to db. |
| How many :: in one address | one, or none | two — the string then has more than one expansion and means nothing |
| Fixed header size | 40 bytes, every packet | Answering “20 to 60”, which is IPv4's range. |
| Header checksum | there is none | naming a checksum field — the layers above and below already check |
| Who may fragment | the source only, using a Fragment extension header | Saying routers fragment. In IPv6 a router discards and reports instead. |
| Minimum MTU on any IPv6 link | 1280 bytes | 1500, which is Ethernet's MTU, or 576 and 68, which are IPv4's numbers |
| The address types | unicast, multicast, anycast | listing broadcast — it does not exist; ff02::1 reaches all nodes instead |
| Link-local prefix | fe80::/10, and every one you meet begins fe80:: | Confusing it with fc00::/7 unique-local, which is the private-address block. |
| What replaced ARP | NDP over ICMPv6: NS type 135, NA type 136 | saying ARP still runs — it cannot, because there is no broadcast to carry it |
| Loopback and unspecified | ::1 and :: | Answering 127.0.0.1, or forgetting that IPv6 reserves one loopback address and not a whole /8. |
06 Where & why
Real addresses on systems you can go and look at
None of this is theoretical. Every address below is one you can type into a resolver or read off a running machine, and the four systems between them cover all three of the changes that matter: the notation, the autoconfiguration, and the fact that IPv4 now costs money.
Google's public resolver answers on 8.8.8.8 and 8.8.4.4 over IPv4, and on 2001:4860:4860::8888 and 2001:4860:4860::8844 over IPv6. That first one is a real compressed address in the wild and it is worth expanding by hand rather than reading about — practice problem 2 asks you to. Note what it is not: it is not four times longer to type, because compression works hardest on exactly the kind of address a registry hands out.
ip -6 addr show prints an fe80:: address on every interface that is up, including one with no cable to anywhere. Alongside it you will see scope link for that one and scope global for anything SLAAC built from a Router Advertisement, often with temporary beside it. ip -6 neigh prints the neighbour table, which is the ARP cache under its new name, with the same REACHABLE and STALE states. ping -6 ff02::1%eth0 is how you make every node on the link answer now that broadcast is gone.
An AWS VPC gets a fixed /56 IPv6 block and each subnet a fixed /64, which tells you how firmly the /64-per-LAN convention is settled: you are not offered the choice. From 1 February 2024 AWS charges roughly $0.005 per hour for every public IPv4 address, in use or not, which is about $3.60 a month per address. That is the exhaustion of the address space arriving as an invoice, and it has moved more architectures to IPv6 than a decade of advocacy did.
Cloudflare publishes both A and AAAA records for a proxied site and accepts IPv6 connections whether or not the origin server speaks it, translating to IPv4 on the way back. The visitor is on IPv6 end to end as far as it can tell; the origin is a legacy IPv4 box that was never touched. That asymmetry is exactly the dual-stack transition in miniature, and it is why the client-side adoption numbers climbed years before most origin servers changed.
07 Interview questions
What they ask, and where they push
This is a standing question because it separates two kinds of candidate cleanly. Anyone can say “IPv6 has 128 bits”. The follow-up is always some version of “so what actually changed apart from the length”, and that is the one to be ready for.
Why did we need IPv6 at all? Weren’t CIDR and NAT enough?
How long is an IPv6 address and how do you write one down?
Give me the rules for shortening an address.
Why can an address contain only one ::?
What are the address types in IPv6?
What is a link-local address and why does every interface have one?
The IPv6 header is 40 bytes and IPv4’s is 20. How is that simpler?
Why did they remove the header checksum?
What replaced ARP, and what is actually better about it?
What is SLAAC, and does IPv6 still need DHCP?
If IPv6 is better in every way, why is the internet still mostly IPv4?
So how would you actually deploy it?
08 Practice problems
Six to work out on paper
For every one of these, write the intermediate form down before you write the answer. Three of them turn on counting something exactly — groups, digits, or bits — and the mistakes in this topic are almost always off-by-one rather than conceptual.