But it's not the only way to tackle the problem of resolving layer 2 addresses, and you can do so without introducing the layering violations and expansive broadcast traffic that ARP implies (along with the consequent problems with WiFi and such).
For instance, IPv6's NDP is built on actual IPv6 packets (ICMPv6), rather than some spoofed IP-lookalike thing. No layering violation, and, thanks to multicasting, no need to dump a bunch of broadcast traffic on the layer 2 network.
The ARP part of the article makes the case that there is no need for a protocol to resolve IP addresses to MAC addresses, with the argument that if only the default gateway was a MAC address rather than an IP address, there would be no need for such a protocol.
NDP may very well be a nicer protocol than ARP, but following the logic of the article, the neighbor solicitation part of NDP would be just as unnecessary as ARP.
> For instance, IPv6's NDP is built on actual IPv6 packets (ICMPv6), rather than some spoofed IP-lookalike thing. No layering violation, and, thanks to multicasting, no need to dump a bunch of broadcast traffic on the layer 2 network.
Only if the L2 network actually supports L2-multicast. Ethernet doesn't, except if your switches are intelligent enough. With cheap ethernet switches, multicast will be simulated by broadcast.
And actually, you can never avoid a layering violation. The only thing that NDP avoids is filling in the source/destination IP portions with placeholders. In NDP, you fill the destination with some multicast IPv6 address. But that is window dressing. You still need to know that this L3-multicast IPv6 address corresponds to a L2-multicast MAC address (or just do L2 broadcast). The NDP source you fill with an L3 IPv6 address that is directly derived from your L2 MAC address. And you still get back a MAC address for each IPv6 address and have to keep both in a table. So there are still tons of layering violations where the L2 addresses either have direct 1:1 correspondences to L3 addresses, or you have to keep L2/L3 translation tables and L3 protocols where the L3 part needs to know which L2 protocol it is running on, otherwise the table couldn't be filled.