Chapter 01 · Part I · Inside a router

How a router forwards a packet

A routing table says where packets should go. A router is the machine that makes them go there, one packet at a time, millions of times a second. This chapter opens the box: the brain that decides, the muscle that forwards, the tables that connect them, and the dozen small things that happen to every packet in the few hundred nanoseconds it spends inside.

148.8 Mminimum-size packets per second that a single 100 Gb/s Ethernet port can deliver: one every 6.7 nanoseconds
8 bitsthe size of the IPv4 time-to-live field, so no packet can cross more than 255 routers; every router must lower it by at least one (RFC 1812)
20 byteswhat the IPv4 header checksum covers: the header only, never the data, which is why every router can patch it in one step (RFC 791, RFC 1624)

Common mix-up: a router does not change the IP addresses of the packets it forwards. The source and destination addresses name the two ends of the whole journey and stay the same at every hop. What changes at every hop is the Ethernet frame around the packet, plus two small fields inside it: the time-to-live and the checksum. (Address translation, NAT, is a separate job some routers also do; it is not part of forwarding.)

Brain and muscle

Three planes in one box

If longest-prefix match, connected routes and the time-to-live are new to you, start with routing tables on networks.jelia.nyc; and if you have not met Ethernet frames and ARP, read Ethernet there first. This chapter assumes both and goes inside the machine.

Every router, from a home gateway to a chassis the size of a refrigerator, is built around one division of labour. The control plane works out where packets should go. It is software on a general-purpose processor: the routing protocols (OSPF, IS-IS, BGP), the static routes an operator typed in, and the process that merges all of them into one answer per destination. It talks to neighboring routers, it changes its mind when links fail, and it takes milliseconds to seconds to do anything.

The data plane, also called the forwarding plane, moves packets. It does not run protocols or hold opinions. It holds a table the control plane gave it and applies that table to every packet that arrives, at whatever rate the wires deliver them. On a software router the data plane is a tight loop in the operating system kernel; on a large router it is custom silicon on every line card.

A third, quieter layer is the management plane: how people and systems operate the router. Remote shell sessions, configuration pushes, SNMP and streaming telemetry, logs, software upgrades. It shares the control-plane processor on most boxes, but it is useful to name separately because it has different users and different security needs: it should be reachable only from the operator's own network.

PlaneJobRuns onTime scaleExamples
ControlDecide where each destination should goGeneral-purpose CPU, ordinary softwareMilliseconds to secondsOSPF, IS-IS, BGP, static routes, building the RIB and FIB
DataMove every packet according to the tableKernel fast path, network processor or forwarding ASICNanoseconds per packetHeader checks, FIB lookup, TTL, rewrite, queueing
ManagementLet people and systems operate the routerUsually the same CPU as the control planeHuman speedSSH, configuration, SNMP and telemetry, logs, upgrades

The split exists for two reasons. The first is speed. Deciding a route can involve running Dijkstra's algorithm over a whole network or comparing a dozen BGP attributes; doing that per packet would be hopeless. Deciding once, then compiling the decision into a table that a dumb, fast engine can apply, is the only way to keep up with modern links.

The second is failure isolation. Because the forwarding table is a copy, the data plane can keep forwarding on its last good copy while the control plane is busy, overloaded or even restarting. Protocols were later extended to take advantage of this on purpose: BGP's graceful restart mechanism (RFC 4724) lets a router tell its neighbors "my routing process is restarting but my forwarding state is preserved; keep sending me traffic for a while," and OSPF and IS-IS have similar extensions.

Go deeper: seeing the planes on a Linux box

A Linux machine becomes a router when you set the kernel parameter net.ipv4.ip_forward to 1 (and net.ipv6.conf.all.forwarding for IPv6). From then on the kernel is the data plane: packets that are not addressed to the machine are looked up in the kernel's forwarding table and sent on, without ever reaching a user program.

The control plane is whatever writes routes into that table. You can do it by hand with ip route add, or run a routing suite such as FRRouting, whose daemons (ospfd, bgpd and so on) learn routes and hand them to a manager process called zebra, which keeps the combined RIB and installs the winners into the kernel. ip route show displays the result; the proto field on each line records which source installed it (kernel, static, ospf, bgp…). Kill the routing daemons and, unless they are configured to clean up, the kernel goes on forwarding with the routes it already has: the plane split in miniature.

The general architecture, a control element driving one or more forwarding elements across a defined interface, was written down by the IETF in RFC 3746 (the ForCES framework). Software-defined networking took the same idea further and moved the control plane off the box altogether.

From many opinions to one table

RIB, FIB and the adjacency table

A router hears about destinations from several places at once. It knows the subnets on its own interfaces (connected routes). An operator may have typed some in (static routes). An interior protocol like OSPF reports routes inside the organization, and BGP reports routes to the rest of the internet. Each source hands its routes to a central store called the routing information base, the RIB.

The RIB is allowed to be messy. It can hold three different routes to the same prefix from three protocols, routes whose next hop is currently unreachable, and routes whose next hop is not even on a connected network. That last case is normal for BGP: a route learned from a router across the network names that router's loopback address as the next hop, and the router has to look up that address to find out which way to send the packet. This is a recursive next hop.

Out of this mess the control plane compiles the forwarding information base, the FIB. For each prefix it keeps exactly one winner (or a set of equal winners, which Chapter 3 covers along with the rules for choosing), and it resolves every next hop all the way down to something the hardware can act on: an outgoing interface and a directly connected neighbor. The FIB has no protocol names, no metrics and no losers. It is built for one question only, asked at line rate: "for this destination address, which way?"

The last step, from neighbor's IP address to neighbor's hardware address, lives in a third table, the adjacency table, filled by ARP for IPv4 (RFC 826) and Neighbor Discovery for IPv6 (RFC 4861). Keeping it separate matters. Thousands of FIB entries usually share a handful of next hops; when a neighbor's hardware address changes, the router updates one adjacency entry instead of rewriting thousands of routes.

TableHoldsBuilt byUsed for
RIBEvery candidate route from every source, with protocol, distance, metric and the next hop as learnedThe control plane, as routes arrive and leaveChoosing the best route per prefix
FIBOne resolved entry per prefix: outgoing interface and directly connected next hopCompiled from the RIB's winnersThe per-packet lookup in the data plane
AdjacencyNext-hop IP address to link-layer (MAC) address, per interfaceARP (IPv4) and Neighbor Discovery (IPv6)Writing the new Ethernet header on the way out
Instrument 1

Compile a RIB into a FIB

Below is the RIB of a router, R1, with two uplinks: eth1 toward R2 and eth2 toward R3. Both reach R7, an internal router whose loopback address 198.51.100.200 is the next hop for the BGP routes. Switch whole sources off, withdraw single routes, or fail the eth1 link, and watch the FIB rebuild. Tap or click a FIB row to see its resolution chain drawn on the map. The rule used here to pick a winner is the simplest one in common use: lowest administrative distance, then lowest metric; Chapter 3 explains it properly.

In RIBSourcePrefixLearned next hopDistance / metricStatus
FIB prefixOut interfaceForward toFromResolution
Routes in RIB–
Entries in FIB–
Unusable routes–

Go deeper: why recursion is worth the trouble

Try failing eth1 above and look at what changes. The BGP routes themselves do not move: they still say "next hop 198.51.100.200," because R7 is still the exit. What changes is how 198.51.100.200 is reached, and so every BGP route's resolved forwarding switches from eth1 to eth2 in one move. On a real internet edge router there might be a million BGP routes behind a few next hops. If the FIB is organised the same way, with routes pointing at a shared next-hop object rather than each carrying its own copy of the outgoing interface, the router can repair forwarding for all of them by rewriting one object. Vendors market this under names like "prefix-independent convergence," and Chapter 7 returns to it.

Implementations differ on one detail you can see in this instrument: whether a next hop may be resolved through the default route. Resolving via the default route can let a route appear usable when the next hop is actually gone, so many operators turn it off; FRRouting exposes the choice as ip nht resolve-via-default. This instrument never resolves through a default route, and it resolves BGP next hops only through connected, static and OSPF routes.

Twelve steps in a few hundred nanoseconds

The per-packet pipeline

RFC 1812, the 1995 requirements document for IPv4 routers, describes the forwarding algorithm as a list of twelve steps. It also says, wisely, that no implementation has to follow the list literally; it only has to have the same effect. Real routers merge, reorder and parallelise the steps, but every one of them still does these things to every packet.

Receive and validate. The packet arrives from the link layer, and the router checks that the header makes sense: long enough to hold an IP header (20 bytes), version 4, a header-length field of at least 5 words, a total-length field no larger than what actually arrived, and a correct header checksum. A packet that fails any of these is silently discarded. No error message goes back, because the router cannot trust the header enough to know whom to tell.

Options and destination. If the header carries IP options, they are processed now. Then the destination address is examined. If it belongs to the router itself, the packet is not forwarded at all: it is handed up to the router's own software, the control plane, for local delivery. That is how routing protocol messages, pings to the router and management sessions reach it.

Lookup. Otherwise the destination is looked up in the FIB, which answers with an outgoing interface and the next hop's address. If there is no matching route, not even a default, the packet is dropped and the router sends an ICMP Destination Unreachable, code 0 (network unreachable), back to the source. How that lookup can be made fast enough is the whole of Chapter 2.

Time to live. The router lowers the TTL by one. If that takes it to zero, the packet is discarded and an ICMP Time Exceeded message (type 11, code 0) goes back to the source. This is what stops a packet circling forever in a routing loop, and it is also what traceroute uses to discover each hop.

Checksum. Changing the TTL changes the header, so the header checksum must change too. Instead of recomputing it over all twenty bytes, routers patch it using the arithmetic in the next section.

Fit the link. If the packet is larger than the outgoing link's maximum transmission unit (MTU), it either has to be split into fragments or, if the sender set the Don't Fragment (DF) bit, dropped with an ICMP Destination Unreachable, code 4 ("fragmentation needed and DF set"), which since RFC 1191 carries the MTU of the next hop so that the sender can shrink its packets. That conversation is called path MTU discovery.

Rewrite, queue, transmit. Finally the router looks up the next hop's hardware address in the adjacency table, builds a new link-layer header (its own interface's address as the source, the next hop's as the destination) and places the frame on the output queue for that interface. The IP addresses inside are untouched.

The IPv4 header (RFC 791). A forwarding router reads every field but writes only the two outlined ones, plus the fragment fields if it has to fragment.

Instrument 2

Step a packet through a router

Here is R1 again, with three interfaces: eth0 (192.0.2.1, toward the host that sends the packet), eth1 (198.51.100.1, MTU 1500, toward R2) and eth2 (198.51.100.129, MTU 1400, toward R3). The packet comes from 192.0.2.10. Pick a destination or type your own, set the TTL, size and DF bit, then step it through. The header bytes are real: the checksum is computed from them, recomputed in full after the TTL changes, and also patched with the RFC 1624 formula, and the two results must agree.

R1 FIB prefixTypeOut interfaceNext hop

Keyboard: focus the canvas and press the right arrow (or space) to step, R to start over. Addresses are the documentation blocks of RFC 5737; MAC addresses are locally administered (they start 02).

One line of arithmetic

Patching the checksum incrementally

The IPv4 header checksum is the one's complement of the one's complement sum of the header's 16-bit words (RFC 791, with the computation explained in RFC 1071). One's complement addition is ordinary addition where any carry out of the top bit is wrapped around and added back in at the bottom. The receiver adds up all the words, checksum included, and a correct header sums to all ones, 0xFFFF.

A router changes exactly one byte of the header, the TTL, which shares a 16-bit word with the protocol number. Rather than adding up all ten words again, it can take the old checksum and adjust it for the one word that changed. RFC 1624 gives the safe form of that adjustment:

HC′ = ~( ~HC + ~m + m′ )
HC is the old checksum, m the old 16-bit word (TTL and protocol), m′ the new word, ~ means flip every bit, and + is one's complement addition. In words: take the old checksum back out of the sum, remove the old word, add the new one, and turn the result back into a checksum.

A worked example, using the packet in Instrument 2's default setting: a 1,000-byte UDP packet from 192.0.2.10 to 203.0.113.9 with DF set. Its header checksum is 0xFE74. The word holding TTL 64 and protocol 17 (UDP) is 0x4011; after the TTL drops to 63 it is 0x3F11. Then ~HC = 0x018B, ~m = 0xBFEE and m′ = 0x3F11. Their one's complement sum is 0x008B (0x018B + 0xBFEE = 0xC179, plus 0x3F11 = 0x1008A, and the carry wraps around to make 0x008B), and flipping its bits gives HC′ = 0xFF74: the same value a full recomputation of all ten words produces. The pattern is easy to see: m′ is m minus 0x0100, so the checksum goes up by 0x0100. The TTL went down by one in the high byte, and the checksum goes up by one in the high byte. Step the instrument through and it shows both computations side by side.

Why the complicated form instead of the obvious "subtract the old word, add the new one"? One's complement arithmetic has two zeros, 0x0000 and 0xFFFF. RFC 1141, the earlier incremental-update document, used a formula that could produce 0xFFFF where a full recomputation produces 0x0000. A receiver checking the header would still accept it, but the result differed from a full recomputation; RFC 1624 corrected the formula so the two always agree.

Go deeper: IPv6 dropped the header checksum

The IPv6 header (RFC 8200) has no checksum at all. Its designers reasoned that the link layer already protects every frame with a strong CRC, and that transport protocols such as TCP and UDP checksum the data and a pseudo-header containing the addresses. Removing the field saved every router on the path the patch step, and it means a router changing the hop limit has nothing else to update. It is also why the UDP checksum, optional in IPv4, is mandatory in IPv6.

The exceptions

Punting to the slow path

The forwarding pipeline is fast because it is simple. Anything that would need judgement, memory or a reply is handed upward to the control-plane processor. Router engineers call this punting, and the route a packet takes to get there the slow path. The processor is a general-purpose CPU that may be orders of magnitude slower than the forwarding hardware beneath it, so on a large router punted packets are the rare exception that must stay rare.

ExceptionWhy it can't stay on the fast pathWhat normally happens
For the routerAddressed to one of the router's own addresses: routing protocol messages, pings, management sessionsDelivered to the router's software, after filtering
TTL expiredThe router must build and send a new packet, ICMP Time ExceededDropped; an ICMP error is generated, subject to a rate limit
IP optionsOptions such as Router Alert or Record Route ask each router to look at or modify the packetProcessed in software, or dropped by policy on many networks
Too big, DF setThe router must report the next-hop MTU back to the senderDropped; ICMP "fragmentation needed" (IPv4) or Packet Too Big (IPv6) sent back
Too big, DF clearFragmentation means building several new headersIPv4 only: fragmented, often in software. IPv6 routers never fragment
Next hop unresolvedNo adjacency entry yet: the router must ask with ARP or Neighbor DiscoveryA request is sent ("glean"); the packet is held briefly or dropped
No routeThe router must reply with an errorDropped; ICMP Destination Unreachable, code 0, rate-limited

The slow path is also the router's soft spot. If anyone can make the router punt packets, then a large enough stream of them could keep the processor busy answering exceptions while the routing protocols starve, and a router whose protocols time out loses its neighbors and its routes. So the path to the processor is protected, and the protection lives in the data plane where there is capacity to spare. RFC 6192 describes the standard defence: identify the traffic the control plane legitimately needs (routing protocol sessions from known neighbors, management from the operator's own addresses, a modest amount of ICMP), filter everything else that is addressed to the router, and put a rate limit, a policer, on each class that is allowed through. Generating ICMP errors is rate-limited too; RFC 1812 explicitly allows routers to limit how many they send.

The practical consequence for anyone debugging a network: a router that answers ping slowly, or drops some traceroute probes, is often perfectly healthy. Replies to packets addressed to the router are produced on the slow path and deliberately limited, while traffic passing through the router never touches it. Chapter 15 comes back to what that does to traceroute.

Go deeper: a defensive checklist for the control plane
  • Write down every protocol the router itself must receive, from whom: BGP from configured neighbors, OSPF or IS-IS on internal interfaces, management only from a management network. Everything else addressed to the router is denied (RFC 6192).
  • Give each permitted class its own rate limit, sized from normal traffic plus headroom, and alert on drops at those limits: an exceeded policer is an early warning.
  • Rate-limit the router's own ICMP error generation, as RFC 1812 permits, but do not block ICMP "fragmentation needed" or Packet Too Big outright; path MTU discovery depends on them (RFC 1191, RFC 8201).
  • Use protocol protections where they exist, such as authentication on routing sessions and the Generalized TTL Security Mechanism for BGP (RFC 5082), so that spoofed protocol packets from far away are discarded before they cost anything.
  • Monitor control-plane CPU and punt counters. Most routers report punted packets per reason; a sudden rise in one reason is worth investigating.
How fast is fast

The line-rate budget

A router port runs at line rate when it can forward every packet the wire can deliver, even when all of them are the smallest legal size. That worst case is the one router designers plan for, because the work per packet barely depends on size: a 64-byte packet needs the same checks, lookup and rewrite as a 1,500-byte one.

The smallest Ethernet frame is 64 bytes, counting its header and its 4-byte frame check sequence. On the wire every frame also costs 8 bytes of preamble and start-of-frame delimiter and a minimum gap of 12 byte-times before the next frame, so a minimum frame occupies 84 bytes, or 672 bits, of the link's time.

100 × 10⁹ b/s ÷ (84 B × 8 b/B) ≈ 148.8 × 10⁶ packets/s
One minimum-size packet every 6.72 nanoseconds. In that time light in fiber travels about 1.4 metres, and a processor running at 3 GHz completes about 20 clock cycles.

With full-size 1,500-byte packets the frame is 1,518 bytes and occupies 1,538 on the wire, so the same port carries only about 8.1 million packets a second, one every 123 ns. Real traffic is a mixture, but a router that only coped with big packets could be knocked over by small ones, so specifications quote the small-packet number. RFC 3222 defines terms for benchmarking FIB-based router performance, such as FIB size and how forwarding is measured as the FIB grows.

The budget explains a great deal about how routers are built. A random access to ordinary DRAM costs tens of nanoseconds, several times the whole per-packet budget at 100 Gb/s. A design that needs several memory reads per lookup must therefore either use faster on-chip memory, spread the work over many lookups running in parallel, or both. Try it below.

Instrument 3

Count the nanoseconds

Choose a port speed and a frame size; the calculator adds the 20 bytes of preamble and gap and works out the packet rate and the time between packets. Then pick a memory access time and see how many dependent memory reads one packet could afford if the router did everything for that packet before starting the next. The strip shows packets arriving (top) against back-to-back memory reads (bottom) over the same stretch of time.

Bytes on the wire–
Packets per second–
Time per packet–
Memory reads per packet–

Go deeper: pipelining, or how routers cheat the budget

No fast router finishes one packet before starting the next. The pipeline is cut into stages, each with its own memory, so that at any moment dozens of packets are in flight at different stages, the way a car factory has a car at every station. The time per packet then only has to cover the slowest single stage, not the whole job. The cost is latency (a packet spends longer in total inside the router) and complexity. Network processors take a different route to the same end: many simple cores, each working on a different packet, switching to another packet whenever one is waiting for memory.

How the box is built

From a PC to a chassis

The pipeline is the same everywhere; where it runs is not. Router hardware has gone through a few broad generations, and all of them are still in use somewhere.

Software router. An ordinary computer with several network interfaces. The kernel does the forwarding: it receives the packet into memory, looks up the destination in its FIB (on Linux, a compressed trie), rewrites the headers and hands the packet to the outgoing driver. It is flexible and cheap, and with batching and kernel-bypass techniques a modern server can forward many millions of packets a second, but every packet still costs CPU cycles and memory bandwidth.

Shared bus. Early dedicated routers put interface cards on a common backplane bus with a central processor and a central FIB. Every packet crossed the bus at least twice, in and out, so the bus capacity was a hard ceiling for the whole box.

Distributed forwarding with a switched fabric. The design used by large routers today. Each line card carries its own ports, its own forwarding engine and its own copy of the FIB, so lookups happen in parallel on every card. Cards are joined by a switch fabric, a crossbar or multistage network that can connect any input card to any output card at the same time as others. The control-plane processor sits on a separate route processor card, computes the RIB, and pushes FIB updates down to every line card.

ASICs and network processors. The forwarding engines themselves are either fixed-function application-specific chips (ASICs), in which parsing, lookup and rewrite are hard-wired pipeline stages, or network processors (NPUs): programmable chips with many cores and specialised memory, slower per watt than an ASIC but able to take new features through software. Many modern switch chips sit in between, with a pipeline whose parsing and match-action stages can be reprogrammed.

DesignWhere the lookup happensLimitStrength
Software routerThe host CPU, kernel FIB in DRAMCPU cycles and memory bandwidth per packetFlexibility, cost, easy to inspect
Shared busCentral processor, central FIBThe bus: every packet crosses itSimple
Switched fabricEach line card, local FIB copyFabric capacity, power, costScales by adding cards; lookups in parallel
ASIC pipelineHard-wired stages on the chipFeatures fixed at design timeHighest rate per watt
Network processorMany programmable coresLower rate per watt than an ASICNew features in software
Go deeper: queues, and where packets wait

Lookup decides where a packet goes; queueing decides when. If two input cards both send traffic toward one output port faster than it can transmit, packets must wait somewhere. Early fabric designs queued at the input, which suffers from head-of-line blocking: a packet waiting for a busy output blocks the packets behind it that want idle outputs. The common fix is virtual output queues: each input keeps a separate queue per output, and a scheduler matches inputs to outputs across the fabric. Output buffers then absorb bursts, and the size of those buffers, and whether a big buffer helps or hurts, is a long-running debate in router design. The order in which queues are served is where quality-of-service markings in the DSCP field take effect.

Same job, cleaner header

What changes for IPv6

An IPv6 router does the same job in the same order, but its designers removed several things that made IPv4 forwarding slow or awkward.

StepIPv4IPv6
Lifetime fieldTime to live, 8 bitsHop limit, 8 bits, decremented the same way (RFC 8200)
Expiry errorICMP Time Exceeded, type 11ICMPv6 Time Exceeded, type 3 (RFC 4443)
Header checksumYes, patched at every hopNone: nothing to patch
FragmentationRouters may fragment unless DF is setRouters never fragment; only the source may (RFC 8200)
Too-big errorDestination Unreachable, code 4, with next-hop MTUPacket Too Big, type 2, with the MTU (RFC 4443, RFC 8201)
Minimum link MTU68 bytes1,280 bytes
Next-hop hardware addressARP broadcast (RFC 826)Neighbor Discovery over ICMPv6 multicast (RFC 4861)
OptionsIn the main header, variable lengthSeparate extension headers; most are not examined by routers, but Hop-by-Hop options are meant for every router

The net effect on the data plane: a fixed 40-byte header, one field to change, no checksum to patch, and no fragmentation work. The price is paid elsewhere. Because routers will not fragment, path MTU discovery has to work, which means the Packet Too Big messages it depends on must not be filtered out. A network that drops all ICMPv6 breaks IPv6 in confusing ways, typically with connections that open fine and then hang when the first large packet is sent.

Cheat sheet

Terms from this chapter

Control plane
The part of a router that decides where traffic should go: routing protocols and route computation, running as software on a general-purpose processor.
Data plane
The part that moves packets, applying the forwarding table to each one at line rate. Also called the forwarding plane.
Management plane
How people and systems operate the router: configuration, remote access, monitoring and logs.
RIB
Routing information base: every candidate route from every source, before a winner is chosen.
FIB
Forwarding information base: one resolved entry per prefix, compiled from the RIB's winners and used for the per-packet lookup.
Adjacency table
The map from each directly connected next hop's IP address to its link-layer address, filled by ARP or Neighbor Discovery.
Recursive next hop
A next hop that is not on a connected network, so the router must look it up in turn to find the real outgoing interface. Normal for BGP.
Punt
To hand a packet from the fast forwarding path up to the control-plane processor because it needs special handling.
Slow path
The software route a punted packet takes through the router's CPU; filtered and rate-limited to protect the control plane.
Incremental checksum update
Patching the IPv4 header checksum for a changed field instead of recomputing it: HC′ = ~(~HC + ~m + m′) (RFC 1624).
Line rate
Forwarding every packet a link can deliver, even when all are minimum size: 148.8 million packets a second at 100 Gb/s.
Line card
A board in a modular router carrying ports and its own forwarding engine and FIB copy, joined to the others by a switch fabric.
Where this comes from

Sources