We'll be having the same post 20 years from now. NAT, for all its problems, has more or less solved the IP address problem.
As a geek, one who has put the networking stack into the ETA-10 (yeah, I know, nobody knows that machine, CDC spinoff super computer) and SCO's unix (yeah, I know, it sucked), so as a geek who gets the stack pretty well, I've never warmed up to IPv6.
To me, it seems like it went too far. 64 bits not enough? Really? Unless I'm doing the math wrong 64 bits is enough for 2635249153 addresses for every human on the planet.
slovax ~/p bc
2^64
18446744073709551616
./(7*1000^3)
2635249153.38707880228571428571
So 128 bits is needed why? I get that people used to say that 16 bits would be enough and they were wrong and the 32 bit people were wrong. I just don't see how we run out of 64 bits in the next $BIG_PILE of years.
I don't get it. Seems over engineered. IPv4 works pretty well, seems like a slight improvement would have been enough.
> NAT, for all its problems, has more or less solved the IP address problem.
A bunch of very large-scale network operators (like Comcast, T-Mobile USA, Verizon, and Facebook) seem to strongly disagree with that, given how eagerly they've deployed IPv6 to get away from the hell that is IPv4 NAT and CGN.
Yes, IPv6 has lots of complexity/flaws/idiosyncrasies/weirdnesses (multicast, mobility, slaac, ndp, prettyprinting / the colons, extension headers, etc.) that mostly only look good through the rose-tinted glasses of the 90s and significantly slowed down deployment -- and in the end mostly ended up as "difference for difference's sake".
128 bits of addressing space and getting away from IPv4 NAT were unambiguously good. 128 bits is a lot, but memory/bandwidth is just going to get cheaper (for slow links you should use header-compression anyway), and it was better to go whole hog and skip 64 and go to 128 to avoid a future 64->128 transition. Given how the 32->128 transition is going, this seems like it was an excellent decision.
From an operator's perspective, 128 bits is more difficult to troubleshoot compared to the 32 bits of IPv4. RFC5962 makes things easier, though only marginally.
You can very easy end up with multilevel nat. The last mile (ie a apartment complex) can have one and then the customer router is the second.
But that assumes that the ISP has addresses to spare. If not, we have the three layers of nat. ISP->apartment complex->customer router->all customer devices.
And then we have intermediates, like ISP->municipal->apartment complex->customer router->customer devices. Now we have four layers of nat.
In the really worse case, ISP are split up into multiple ones, and you can get carrier grade NAT in the form of ISP->ISP->municipal->apartment complex->customer router->customer devices. Five layers of nat and up.
Multilevel NAT is a form of sadness that NAT never was designed to do.
NAT is also expensive to operate at the scale and reliability that large network operators need. If stateful NAT middleboxes go down, everything goes down -- it's a point of failure that's hard to route around!
Also there's the issue that you'll end up having multiple devices with the same RFC1918 addresses, which is an immense pain in the arse to deal with.
Of all the various reasons to define address lengths and wire formats (that'll get burned into billions of dollars of ASICs over decades), "C doesn't have a default type for it" is frankly the worst.
Which is a byte array. When you pass this to a function, it does not fit in a single register. The equality operator doesn't work, nor do other logical operators. Everything has to be defined. 64 bit would have been so easy. And it would still have been enough.
Edit: somebody replied and deleted their comment. Since I had written a response I am editing this comment.
> Then your real complaint... is that you don't have 128-bit machine registers
Agreed, although my real complaint is more towards IPv6, for not thinking about this real-life limitation.
> what the urgent need to pass IPv6 addresses in machine registers
It's much slower than IPv4 to deal with! 64 bit addresses wouldn't have had this problem and still would have enough space for everyone on earth.
> And how is it "irritating af"?
Apart from the speed concerns:
> The equality operator doesn't work, nor do other logical operators. Everything has to be defined.
So what? Didn't you notice that the 128 bits are split in half: {network|host}? Anything that needs to route things around is only concerned about the first 64 bits. Once you're hitting on the local scope the last 64 bits is what matters ~99.9% of the time. So you can have your efficient 64-bit comparison right there for most of the traffic.
> Everything has to be defined. 64 bit would have been so easy. And it would still have been enough
I agree. It sucks, 64 bits almost certainly would have worked and languages/libraries/OSes tend to not do their fair share at taking care of IPv6-related stuff. That, along with all the prettyprinting/parsing business with the colons is legitimately annoying.
However, IPv6 was designed not just to fix IPv4's sins, but to ensure that there'd never be an address exhaustion issue with IPv6, no matter how many decades it would be in use. That's why there's 128 bits of overkill; the IPv6 designers knew that the IPv4->IPv6 transition would be awful (they even underestimated just how awful it'd be), that IPv6 would keep running for a long time once it got deployed -- and wanted to do their best to avoid subjecting the world to a transition from IPv6.
> When you pass this to a function, it does not fit in a single register.
Depends on the architecture. On amd64 (the architecture I'm typing this comment on), a 128-bit struct, like defined above, will fit in registers — yes, in 64-bit registers. The amd64 ABI[1] will split them across two registers. For example, if we take the above struct and use it,
movabsq $578437695752307201, %rdi
xorl %esi, %esi
jmp bar
The nasty looking number is the initialization; it's easier to see in hex:
In [1]: hex(578437695752307201)
Out[1]: '0x807060504030201'
That ends up in %rdi, the first of the amd64 arg-passing registers. The next half is zeros, so it goes in %rsi (the compiler just zeros it). Then we "call" bar. (There is tail-call optimization here)
The non-optimized version is similar, but more drawn out:
# for some reason we zero it first
movq $0, -16(%rbp)
movq $0, -8(%rbp)
# then we init it again… okay gcc.
movb $1, -16(%rbp)
movb $2, -15(%rbp)
movb $3, -14(%rbp)
movb $4, -13(%rbp)
movb $5, -12(%rbp)
movb $6, -11(%rbp)
movb $7, -10(%rbp)
movb $8, -9(%rbp)
# move the struct into rdx/rax
movq -16(%rbp), %rdx
movq -8(%rbp), %rax
# just to move it into the arg-passing registers
movq %rdx, %rdi
movq %rax, %rsi
# call the function
call bar
> It's much slower than IPv4 to deal with! 64 bit addresses wouldn't have had this problem and still would have enough space for everyone on earth.
It's twice as wide, yes, but that doesn't necessarily mean you're needing to pass it in memory.
> still would have enough space for everyone on earth.
IP addresses aren't just numbers assigned to machines. They must also — effectively — encode the route to that machine; you can sort of imagine it as a tree, with each bit giving you successively more local directions on the Internet. Now, of course, that's not exactly how it works, but the point is that some parts of that tree are going to be sparsely populated. Having a wider address space means you can make bigger, but not necessarily full, allocations in the address space, allowing you to keep whole networks together in a common prefixes, which results in simpler routing tables. (At least, that's the idea as I understand it.)
And it's not just 1 per person: I have more than one device, and I move between networks during the course of a day. If all of the networks I frequented actually had IPv6, I'd bog down at least 6–8 IPv6 addresses during the course of a boring day, and that's not counting stuff like networking equipment.
It's not just a simple question of "are there enough bits to assign each person an address"
> The equality operator doesn't work, nor do other logical operators.
On amd64 at least, __int128_t exists, I believe, and I think it should come with operators. In higher-level languages, you can define < and == simply enough.
Now, I grant that the above is highly architecture specific, and there definitely exist architectures where this doesn't apply. And those, yes, 128-bit will be slower than a theoretical 64-bit. I just don't think it's worth worrying about.
> IP addresses aren't just numbers assigned to machines. They must also — effectively — encode the route to that machine; you can sort of imagine it as a tree, with each bit giving you successively more local directions on the Internet. Now, of course, that's not exactly how it works, but the point is that some parts of that tree are going to be sparsely populated. Having a wider address space means you can make bigger, but not necessarily full, allocations in the address space, allowing you to keep whole networks together in a common prefixes, which results in simpler routing tables. (At least, that's the idea as I understand it.)
Exactly, and the huge address space allows the standard to right out set some structure to it, with 48 bits for global routing, 16 bits for subnet addressing, plus 64 bits for link-local, interface identifier. Routing is only concerned about the first 64 bits (which has all the fast operations you could dream of) and global routing only the first 48 even. Obviously doing some work to match the topology to the address space in a smart way by leveraging CIDR to reduce the size of routing tables is always going to be useful.
* getting IPv6 provider-independent space is too hard
* extension headers are tricky, slow to parse, a source of tricky security issues, and thus are almost completely unused on the Internet in general
Basically almost all the moving parts in ipv6 (beyond the wire format and its 128-bit addresses) that aren't dangerously convoluted / mostly unused are pretty much just NIH'd reimplementations of the corresponding IPv4 protocols (like ARP, say).
Provider-independent space ought to be impossible - addresses should be addresses. If you want multiple routing paths to you, get an AS number and participate in actual global routing. Otherwise, accept that when you move your address will change.
NAT is pure evil. It adds huge complexity to anything wanting to do any kind of end-to-end or peer-to-peer connectivity, and it does not scale at carrier sizes very well. Even for regular client-server stuff it introduces performance and stability problems when you try to do it for millions of clients. Don't even get me started on the complexity it adds on the devops front. Layers and layers of cruft go away when everything can have an actual address.
It's a nasty hack to keep the net running until we can sunset IPv4. That's it.
64-bit IP would have been fine. If I were asked to extend IPv4 that's what I would do. I've ranted about the annoyance of 128-bit address lengths, but it's not a show stopper and it's something that could be fixed at the UI level and with better DNS management systems.
There are cool things about 128-bit addresses like SLAAC and cryptographically meaningful addressing.
We have IPv6. It works. It's getting deployed. There's absolutely nothing to be gained and a lot to be lost by bikeshedding about why 64-bit would have been veryveryslightly better. It's like arguing in 2017 about how PCs would be 0.5% faster if we were using the DEC Alpha instruction set instead of x86_64 or what the world would be like if Apple had stuck with PPC.
NAT has not solved the IP address problem, it has merely postponed it slightly. Multi-level NATs are a hell far beyond the single-level NATs that most consumers see (and single-level NATs already cause all sorts of problems for even moderately advanced network usage). So most people only have single-level NATs, which practically only extends the address space by a small multiple - 8 bits at most, in practice ~2-3 bits.
128 bits allows routing tables to be super small and fast. While RAM has gotten cheaper, it is still slow, and smaller routing tables are way more important than smaller addresses.
However, I agree with your central point - IPv4 was "good enough" that IPv6 is going to be a tougher battle than it ought to be. However, IPv6 is winning that battle already. 15% of google's users use IPv6, and it's increasing sigmoidally. [1]
It's only too big if you consider they would all be used. The large tracts of open unused space allow you to subdivide networks many times over - simplifying routing. If you just made the space bigger and expected to pack it very full, the routing would be very complex - worse than now.
Its amazing people still wanna bike-shed what is essentially a 20+ year old protocol at this point. Its time to give up on the nitpicking guys, ipv6 is the future regardless of if you like it or not.
You're right that ipv6 is the future. However that does not mean it is impossible to find flaws in it. For some people, having 128 bits instead of 64 is a flaw.
Its about as relevant at this point as arguing that traffic lights shouldn't be red and green, sure maybe, but its not a very useful discussion because its both a trivial aesthetic concern and never ever going to change.
But with WebAssembly, you'll not be locked into it, or into transpilers that produce it. Chances are, we'll see other reasonable languages being compiled to WebAssembly and getting mass adoption.
(WebAssembly is a stack machine with a bytecode interpreter, running in the browser, with code downloaded from the net. Java tried to be basically the same thing, only 25 years too early.)
Java also did it with 25x worse VM start times, 25x more security vulns, and a 25x more greedy and terrible company behind it (eventually). The legendary GC pause never helped. "Write once, run anywhere" then ironically becomes the specialty of Java...script.
Yeah I am really excited with Webassembly as the new JVM/CLR. But I was told this wasn't going to happen. As the downvote illustrates, there are many javascript militants who probably think we do not need any other language.
64 bits isn't enough for classful (pre-CIDR-style) routing. Remember that IP addresses aren't just arbitrary numbers, they're addresses. Note also that there's a fixed divide at 64 bits, so IPv6 is "really" only 64 bits of global routing, the last 64 bits are reserved for site-local routing.
> the last 64 bits are reserved for site-local routing.
No, the last 64 bits should never be involved in routing, /64 is the prefix length for a single ethernet segment. A site should by default have at least a /48.
Stop thinking about 64 bits as an address space that might get filled (like it did in IPv4). The 128 bit length of IPv6 allows them to be used differently - more like a UUID that can be randomly generated with low probability of collision (similar to Git hashes). This allows a number of features like self-assigning random IP addresses on private networks that would be infeasible with a smaller address space.
I was actually curious if it might not have been designed not for the number of addresses but for the average distance between any two addresses in use.
Won't this make scanning the address space nigh on untenable for the foreseeable future? The big thing is to retire IPv4 then.
Configuration systems for those typically do support symbolic prefixes for easy renumbering and deployment of sibling networks.
Also, most people dealing with rfc1918 networks would much rather get rid of addressing conflicts and other problems resulting from non-unique addresses, like security problems arising from ambiguous addressing. (Or don't know what they're missing...)
I remember 208.67.222.222 and 208.67.220.220 being someone who grew up in a country with DNS-level censorship way before Google announced their Public DNS.
Passing around an IP address in a single register. Today's CPUs are powerful enough to not need hardware forwarding chips to route up to 1Gbps of traffic easily, without much custom software optimisation. However that only holds true for IPv4 traffic. Throw in IPv6 traffic and suddenly each compare takes twice as much time in the CPU. Functions cannot pass addresses and masks in the registers, requiring stack juggling or worse, memory access.
> Throw in IPv6 traffic and suddenly each compare takes twice as much time in the CPU
So an operation responsible for less than 0.1% of the total time spent routing a packet now takes twice as much time... or it would if CPUs weren't superscalar for a long time now. That's paid back in tenfold just by the omission of the header checksum.
Depends on the ISA and optimization level - and the OS. Win32's x86-only __stdcall convention always passes arguments on the stack instead of in registers.
Ask yourself who benefits from this...slower networking on commodity hardware. Then look at who had the most influence over ipv6 in the IETF, etc. No big surprises.
Putting in 128 enables them to waste the address space the same way IPv4 was treated decades ago. "Oh, you want to hook up a classroom? Here's a /16 <-> /64". If address space is so plentiful the default home isp allocation is /64, there's something wrong here.
I can somewhat easily remember a bunch of IPv4 addresses. I'll probably never memorize an IPv6 one, unless it's one of the 0xface cafe babe 0000 ones. Which waste address space even more, see above.
If it is, then your ISP is incompetent. You should get a /48 by default, at the very least a /56.
> there's something wrong here.
Why?
> I'll probably never memorize an IPv6 one, unless it's one of the 0xface cafe babe 0000 ones. Which waste address space even more, see above.
Why would you want to? Except for a few special ones (routers and DNS servers, mostly), which you probably should configure to use easy to remember addresses, what's the point of remembering addresses when there is DNS?
> NAT, for all its problems, has more or less solved the IP address problem.
This is only kind of true if you can fit your network completely into the RFC1918 space (which many large companies, for example, can not). Again, given the aggressiveness many of the providers, like Verizon, have taken in their IPv6 roll-out, including internally, and given how much of a complete mess NAT is at scale (with CGN and statefulness), I am personally dubious that IPv4 has the capability to carry us much further forward.
As a geek, one who has put the networking stack into the ETA-10 (yeah, I know, nobody knows that machine, CDC spinoff super computer) and SCO's unix (yeah, I know, it sucked), so as a geek who gets the stack pretty well, I've never warmed up to IPv6.
To me, it seems like it went too far. 64 bits not enough? Really? Unless I'm doing the math wrong 64 bits is enough for 2635249153 addresses for every human on the planet.
So 128 bits is needed why? I get that people used to say that 16 bits would be enough and they were wrong and the 32 bit people were wrong. I just don't see how we run out of 64 bits in the next $BIG_PILE of years.I don't get it. Seems over engineered. IPv4 works pretty well, seems like a slight improvement would have been enough.