Every OSPF router carries the same map of its area and runs the same shortest-path calculation over it. This chapter is about the machinery that keeps those maps identical: how two routers decide to trust each other, how they compare databases, how a change floods reliably to everyone, and how areas stop the map from growing without limit.
Common mix-up: a neighbor sitting in 2-Way is not always broken. On a shared LAN, two routers that are neither the designated router nor its backup are meant to stop at 2-Way; they only become fully adjacent with the DR and BDR. The state that usually signals a real fault is ExStart or Exchange that never moves on, and the usual cause is an MTU mismatch.
If the idea of a link-state protocol is new, start with dynamic routing on networks.jelia.nyc: it shows OSPF flooding a map and running Dijkstra over a network you can break. This chapter assumes that picture and opens up the protocol that makes it work. The rules here come from RFC 2328, OSPF version 2, published in April 1998 and still the standard for IPv4.
OSPF does not use TCP or UDP. Its packets are carried directly inside IP with protocol number 89, which means OSPF has to provide its own reliability: it numbers, acknowledges and retransmits what matters. On broadcast links it sends to two reserved multicast groups, 224.0.0.5 (all OSPF routers) and 224.0.0.6 (the designated routers), with a TTL of 1 so nothing leaves the local link. OSPF for IPv6 uses FF02::5 and FF02::6 the same way.
Every OSPF packet starts with the same 24-byte header carrying the sender's router ID, a 32-bit number written like an IPv4 address that names the router for life, and the area ID of the link it was sent on. Behind the header is one of only five packet types. Everything the protocol does, from first contact to keeping a thousand-router database in step, is a conversation in these five.
| Type | Name | What it carries | When you see it |
|---|---|---|---|
| 1 | Hello | Timers, network mask, priority, the DR and BDR, and every neighbor this router has heard | Every HelloInterval, forever (10 s is the usual LAN value) |
| 2 | Database Description (DBD) | A list of LSA headers: a table of contents, not the LSAs | Once, while two routers compare databases |
| 3 | Link State Request (LSR) | "Send me these LSAs," by type, ID and advertising router | After the comparison, for whatever is missing or older |
| 4 | Link State Update (LSU) | One or more complete LSAs | Answering a request, and every time anything floods |
| 5 | Link State Acknowledgment | The headers of LSAs received | After every LSU, so the sender can stop retransmitting |
| Bytes | Field | Meaning |
|---|---|---|
| 0 | Version | 2 for OSPFv2, 3 for OSPFv3 |
| 1 | Type | 1 to 5, as in the table above |
| 2–3 | Packet length | In bytes, header included |
| 4–7 | Router ID | The sender's 32-bit identity, for example 192.0.2.1 |
| 8–11 | Area ID | The area of the interface the packet left by; 0.0.0.0 is the backbone |
| 12–13 | Checksum | Covers the packet, excluding the authentication field |
| 14–15 | AuType | 0 none, 1 simple password, 2 cryptographic |
| 16–23 | Authentication | A password, or a key ID and a sequence number for the cryptographic digest appended after the packet |
The plain-text password of AuType 1 is visible to anyone on the link and protects against accidents, not attackers. RFC 2328 defines keyed MD5 for AuType 2, and RFC 5709 added the HMAC-SHA family. The cryptographic sequence number never decreases, so a captured packet cannot simply be replayed later.
A router running OSPF on an interface multicasts a Hello every HelloInterval. A Hello is short, but it does three jobs. It announces "I am here." It states the parameters the sender insists on. And it lists every router the sender has heard on this link, which is how two routers find out that they can hear each other in both directions.
Before a router accepts a neighbor, it checks the received Hello against its own settings. If certain fields differ, the Hello is silently thrown away. Nothing is logged by the protocol itself, and the neighbor simply never appears. Most "OSPF won't come up" tickets are one of these fields.
| Field | Must match? | What happens if it doesn't |
|---|---|---|
| Area ID | Yes | Hello discarded; the neighbor never leaves Down |
| HelloInterval | Yes | Hello discarded |
| RouterDeadInterval | Yes | Hello discarded. Usually four times the HelloInterval, so 40 s with a 10 s Hello |
| Network mask | On broadcast and NBMA links | Hello discarded; not checked on point-to-point links or virtual links |
| Authentication | Yes | Packet fails authentication and is dropped before anything else is read |
| Stub-area flag (E bit) | Yes | Hello discarded: both ends must agree whether the area accepts external routes |
| Interface MTU | Checked later, in the DBD | Hellos are fine; the pair gets stuck in ExStart or Exchange |
| Router ID | Must differ | Two routers with the same ID corrupt each other's LSAs; the symptom is constant re-flooding |
After the 24-byte header, a Hello carries: the network mask of the sending interface (4 bytes); HelloInterval (2 bytes); Options (1 byte, including the E bit that says whether this area carries external routes); router priority (1 byte, used in the DR election); RouterDeadInterval (4 bytes); the designated router and backup designated router as the sender currently sees them (4 bytes each, by interface address); and then a list of the router IDs of every neighbor from which the sender has received a Hello within the dead interval.
That last list is the clever part. When R2 sees its own router ID in a Hello from R1, it knows R1 can hear R2. If R2 never sees itself listed, communication is one-way, perhaps because a filter or a broken transmitter drops traffic in one direction, and building an adjacency would be pointless.
Section 10 of RFC 2328 describes each neighbor relationship as a finite-state machine. Each router keeps one state per neighbor, and the two ends move through the states together as the conversation progresses. The names are worth learning, because they are what every router's show command prints, and the state a neighbor is stuck in tells you which step failed.
| State | What has happened | Stuck here usually means |
|---|---|---|
| Down | Nothing heard from this neighbor within the dead interval | No Hellos arriving, or arriving and being discarded: area, timers, mask, authentication or stub flag |
| Init | A Hello arrived, but it doesn't list me yet | One-way communication: my Hellos aren't reaching them, often a filter |
| 2-Way | Each side sees itself in the other's Hello | Nothing, if both are DROthers on a LAN. That is the correct final state for them |
| ExStart | Deciding who is master for the database exchange | MTU mismatch; sometimes a duplicate router ID |
| Exchange | Swapping DBD packets: the tables of contents | MTU mismatch, or large DBDs being lost |
| Loading | Requesting and receiving the LSAs that were missing or older | Corrupted or oversized LSAs repeatedly failing |
| Full | Both databases are identical | The goal. Only Full adjacencies appear in router LSAs and carry traffic |
The step from 2-Way to ExStart is where the routers decide whether to become adjacent at all. On a point-to-point link they always do. On a LAN, a router only forms adjacencies with the designated router and the backup, for reasons the next section explains. In ExStart, each side sends an empty DBD claiming to be master; the one with the higher router ID wins and sets the DBD sequence number. In Exchange, they trade DBDs listing every LSA header in their databases. Each compares the other's list with its own, and anything it lacks, or holds in an older version, goes on a request list. In Loading, the LSRs go out and the LSUs come back. When both request lists are empty, both are Full.
The MTU check happens in the DBD, not the Hello, which is why an MTU mismatch produces such a confusing symptom. Hellos are small and pass fine, so the routers reach 2-Way. Then each DBD carries the sender's interface MTU, and RFC 2328 section 10.6 says a router must reject a DBD whose MTU is larger than it can receive without fragmentation. The router with the smaller MTU keeps rejecting, the other keeps retransmitting, and the pair sits in ExStart or Exchange indefinitely. Instrument 1 lets you watch it happen.
Two routers, R1 (router ID 192.0.2.1) and R2 (192.0.2.2), on one link. Pick the link type, add any misconfigurations you like, then press Step to send the conversation one packet at a time. The program runs the RFC 2328 checks on each packet as it arrives: Hello fields first, then the bidirectional check, the master election, the MTU test, and finally a real comparison of the two databases by LSA sequence number to decide what each side must request.
Picture ten routers on one Ethernet segment. If every pair formed a full adjacency, that would be 10 × 9 ÷ 2 = 45 adjacencies, each with its own database exchange and its own copy of every flooded LSA. When one router announced a change, it would arrive at each of the others nine times. OSPF's answer is to elect one router on the segment as the designated router (DR) and a second as the backup designated router (BDR). Every other router, called a DROther, becomes fully adjacent with only those two.
A router sends an update to 224.0.0.6, which only the DR and BDR listen to. The DR then re-floods it to 224.0.0.5, where everyone hears it once. The DR has a second job: it originates a network LSA (type 2) for the segment, listing every router attached to it. In the SPF graph the LAN becomes a single "pseudo-node" with a spoke to each router, instead of a tangle of router-to-router links.
The election uses the priority field in the Hello (0 to 255, default 1). The highest priority wins; ties go to the highest router ID; priority 0 means "never elect me." Crucially, the election is not pre-emptive. If a router with priority 255 boots on a segment that already has a DR, it does not take over. It waits for the DR to fail, at which point the BDR is promoted and a new BDR is elected. That stability is deliberate, because every change of DR means new adjacencies and a new network LSA. It also means the DR is often whichever router happened to boot first, which surprises people who set priorities and expect them to apply immediately.
Not every link needs any of this. On a point-to-point link, such as a fiber between two routers or a /31, there is exactly one possible neighbor, so there is no election and no network LSA. Many operators configure their Ethernet links between two routers as point-to-point for exactly that reason: adjacencies form faster and the database is smaller. NBMA networks, such as old Frame Relay clouds, elect a DR but cannot multicast, so neighbors are configured by hand.
A shared segment of routers with router IDs 192.0.2.1 upward. Click or tap a router to cycle its priority (1, 0, 10, 100, 255); from the keyboard, Tab to the picture, pick a router with the arrow keys and press Enter. Then fail the DR, add a high-priority latecomer, or reboot everyone at once. The program applies the election rules each time: keep a working DR and BDR, promote the BDR if the DR fails, otherwise pick by priority then router ID, and never elect priority 0. It counts the adjacencies that result.
Once routers are Full, the job changes from catching up to keeping up. The unit of information is the LSA, a link-state advertisement: one router's statement about one thing, such as "these are my links and their costs." When something changes, the router responsible re-originates the LSA and floods it. Each neighbor that receives it checks whether it is new, installs it, acknowledges it, and passes it on out of every other interface in the same area. The same LSA reaches every router in the area within a few hops' worth of delay.
Because OSPF runs on bare IP, the flooding is made reliable by hand. A router keeps each LSA it sends on a retransmission list for that neighbor until an acknowledgement comes back, and resends every RxmtInterval (5 seconds is the RFC's sample value for a LAN). Acknowledgements can be explicit, a Link State Acknowledgment packet, or implicit: if the neighbor floods the same LSA back, that counts as receipt.
Every LSA starts with a 20-byte header, and three fields in it decide what "new" means.
| Bytes | Field | Purpose |
|---|---|---|
| 0–1 | LS age | Seconds since origination. Grows by one each second in the database and by InfTransDelay at each hop |
| 2 | Options | Capabilities, including the E bit (external routes) and N/P bits for NSSA |
| 3 | LS type | 1 to 5, or 7: see the LSA table below |
| 4–7 | Link State ID | What the LSA is about: a router ID, a DR's interface address, or a destination network |
| 8–11 | Advertising router | The router ID of the originator. Only it may change this LSA |
| 12–15 | LS sequence number | Starts at 0x80000001, goes up by one with every new instance, ends at 0x7FFFFFFF |
| 16–17 | LS checksum | Fletcher checksum over everything except the age |
| 18–19 | Length | Of the whole LSA, header included |
Type, Link State ID and advertising router together name an LSA. When two copies with the same name meet, the router compares them in a fixed order from section 13.1 of RFC 2328: the higher sequence number wins; if those are equal, the higher checksum wins; if still equal, a copy at MaxAge wins; otherwise, if the ages differ by more than 15 minutes (MaxAgeDiff), the younger copy wins. Otherwise they are the same instance.
The age field is what lets the database clean itself. An LSA's age climbs in every database. Its originator refreshes it every 30 minutes with a new sequence number, resetting the age to zero, so a healthy LSA never gets old. If the originator dies, nobody refreshes its LSAs, and after an hour they reach MaxAge and are flushed everywhere. A router that wants to withdraw an LSA on purpose does the same thing early: it sets the age to MaxAge and floods it, and every router deletes its copy. Engineers call this premature aging.
R1 holds the router LSA from 192.0.2.9 with sequence number 0x80000003. During a database exchange, R2's DBD lists the same LSA (type 1, ID 192.0.2.9, advertising router 192.0.2.9) with 0x80000005. Sequence numbers are compared as signed 32-bit integers, so 0x80000005 is the larger: R2's copy is newer, and R1 puts it on its request list. Instrument 1 performs exactly this comparison for each header it receives.
The sequence space starts at 0x80000001, which as a signed number is the most negative value plus one, and runs up to 0x7FFFFFFF. At one refresh every 30 minutes, the roughly four billion values would last about 245,000 years, but a router that floods a flapping link every few seconds could use them faster. When an originator needs to go past MaxSequenceNumber, it first flushes the LSA by setting its age to MaxAge, waits until every neighbor has acknowledged the flush, and then starts again at 0x80000001.
Two more constants stop storms. MinLSInterval (5 s) is the shortest time between two originations of the same LSA by its owner, and MinLSArrival (1 s) is the shortest time between accepting two instances of the same LSA from the network. Newer implementations replace these fixed numbers with back-off timers, which belong to Chapter 07.
OSPFv2 defines eleven LSA types once you count the extensions, but six of them carry ordinary IPv4 routing, and knowing those six is the difference between reading an OSPF database and staring at it. The important column is the last one: how far each type floods. That flooding scope is what areas exist to control.
| Type | Name | Originated by | Describes | Floods |
|---|---|---|---|---|
| 1 | Router | Every router | The router's own links in this area: neighbors, costs, stub networks | Within its area |
| 2 | Network | The DR of a LAN | The LAN as a pseudo-node and every router attached to it | Within its area |
| 3 | Summary (network) | An area border router | A destination in another area, and the ABR's cost to it | Within the area it is sent into |
| 4 | Summary (ASBR) | An area border router | How far it is to an ASBR in another area | Within the area it is sent into |
| 5 | AS-external | An ASBR | A route from outside OSPF: static, BGP, connected | The whole OSPF domain, except stub areas and NSSAs |
| 7 | NSSA-external | An ASBR inside an NSSA | The same as type 5, but allowed in an NSSA | Within the NSSA; an ABR translates it into type 5 |
Types 1 and 2 are the map: together they describe every router, every link and every cost inside an area, with enough detail to run Dijkstra. Types 3 and 4 are not maps at all. They are distance-vector style summaries, "I can reach this, at this cost," which the next section shows is a deliberate choice. Type 5 carries the outside world into OSPF, and since an external route is the same everywhere, one copy floods everywhere. In a network that redistributes a few thousand external prefixes, type 5s are usually most of the database.
OSPF for IPv6, specified in RFC 2740 and updated by RFC 5340 in July 2008, keeps the state machine, the flooding, the areas and the SPF almost unchanged. What it changes is where addresses live. In OSPFv2, router and network LSAs mix topology with IPv4 prefixes. In OSPFv3, router and network LSAs describe only topology, and prefixes move into new LSAs, so a renumbering doesn't force a new SPF.
Link state has a scaling problem built in. Every router stores every type 1 and 2 LSA for its area, every change floods to every router, and every router re-runs SPF. Double the network and you more than double the work on every box. Areas break the domain into pieces. Inside an area, routers share the full map. Between areas, only summaries cross.
Area 0 is the backbone. A router with interfaces in more than one area is an area border router (ABR) and keeps a separate database for each of its areas. A router that brings external routes into OSPF is an autonomous system boundary router (ASBR). An ABR runs SPF in each of its areas, then advertises each destination it found into the other areas as a type 3 summary carrying only the prefix and its cost. A router in area 1 that sees a type 3 from its ABR doesn't know the path inside area 2; it knows the ABR's cost to the destination and adds its own cost to reach the ABR.
That is distance vector, the same "trust my neighbor's number" logic as Chapter 04, and distance vector can loop. OSPF prevents loops by forcing a strict shape. All inter-area traffic passes through area 0, and an ABR only computes inter-area routes from summaries it heard over the backbone. With a hub-and-spoke shape there is no cycle of areas for a rumour to travel around, so no count-to-infinity. That is why every area must touch area 0. An area attached only to another non-backbone area receives no inter-area routes at all. The repair for that case is a virtual link: a configured tunnel through a transit area that makes a distant ABR count as attached to the backbone. It works, and it is usually a sign the design should be fixed instead.
Summaries are where areas pay off. An ABR can be configured with a range, such as 198.51.100.0/24 for area 1, and then advertises the whole area as one type 3 instead of one per subnet. A link flapping inside area 1 no longer changes anything outside it, because the range stays up while any part of it is reachable. That containment of churn is often worth more than the memory saved.
Many areas have only one or two ways out. For them, thousands of type 5 externals carry no information: every external destination is reached through the ABRs anyway. A stub area refuses type 5 and type 4 LSAs; its ABRs inject a single default route as a type 3 instead. RFC 2328 also lets the ABR suppress some or all of the other type 3 summaries into a stub, which vendors call a totally stubby area: the routers inside see their own area's map plus one default route per ABR, and nothing else. The price is that a stub area cannot contain an ASBR, and a virtual link cannot pass through it.
That restriction is awkward when a branch site's area should be stub but has one router redistributing a few local routes. RFC 3101 (January 2003) defined the not-so-stubby area, NSSA, for that case. An NSSA still blocks type 5 from outside, but an ASBR inside it may originate type 7 LSAs, which flood only within the NSSA. At the border, one ABR is elected translator (by highest router ID, unless configured) and re-originates each type 7 as a type 5 for the rest of the domain.
Take area 2 in Instrument 3's starting design: three routers (D1, D2, D3) on point-to-point links, with D1 as the only ABR. Its database starts with 3 type 1 LSAs and no type 2s, because there is no LAN.
D1 then sends in a type 3 for every destination elsewhere. Area 0 has six links and the loopbacks of the routers homed there, area 1 has its links, its LAN and its loopbacks, and area 3 likewise. Each becomes a type 3 from D1. Two ASBRs (C3 in area 0 and E3 in area 3) each redistribute 100 routes, so area 2 also holds 200 type 5s and a type 4 from D1 for each ASBR outside area 2.
Make area 2 stub and the 200 type 5s and the type 4s vanish, replaced by one default type 3. Make it totally stubby and the per-subnet type 3s vanish too: the database falls to 3 type 1s and 1 type 3. The instrument computes all of this live, area by area, as you change the design.
Fourteen routers and a LAN. Click (or tap) a link to move it to the next area: 0, 1, 2, 3, then switched off, then back to 0. Click a router to see its database. Set each area's type and whether its ABRs summarize it. The program works out which routers are ABRs and ASBRs, then counts every LSA each area must hold by type, using the origination and flooding rules from RFC 2328 and RFC 3101, and compares the total with the same topology as plain, unsummarized areas. It also checks the design: areas that don't touch area 0, areas split in two, and ASBRs stranded in stub areas.
Line color and the small number on each link give its area: area 0 solid blue, 1 amber, 2 teal, 3 dashed. Square router = ABR. Diamond tag = ASBR. A dotted grey line is switched off.
With a synchronised database, each router builds a graph from the type 1 and type 2 LSAs of each area, puts itself at the root, and runs Dijkstra's algorithm to find the cheapest path to every node. networks.jelia.nyc walks through Dijkstra step by step; here, what matters is what OSPF does around it. Intra-area routes come from the tree. Inter-area routes come from adding the cost to each ABR to the cost in its type 3s. External routes come from type 5s and type 7s, either adding the internal cost to the ASBR (external type 1) or ignoring it and using only the external metric (external type 2, the usual default). When the same prefix is learned more than one way, OSPF prefers, in order: intra-area, inter-area, external type 1, external type 2, regardless of cost.
Not every change needs a full SPF. If only type 3, 4 or 5 LSAs change, the tree inside the area is unchanged, and RFC 2328 section 16.5 lets a router recompute just the affected routes. That is called partial SPF. Implementations add incremental SPF, which repairs only the damaged part of the tree after a type 1 or 2 change. And because a burst of changes can trigger a burst of SPF runs, routers delay the first run a few milliseconds and back off when changes keep coming. RFC 8405 standardized such a back-off algorithm; how to tune it, and how to repair traffic before SPF even finishes, is the subject of Chapter 07.
The numbers Dijkstra adds up are interface costs, 16-bit values from 1 to 65535 that each router assigns to its own outgoing interfaces. You can set them by hand, but most networks let the router derive them from bandwidth.
That default was chosen when 100 Mb/s was fast. Today it makes every link of 100 Mb/s or more cost exactly 1, so OSPF sees a 100 Gb/s backbone link and a 100 Mb/s backup link as equal and picks paths by hop count. The fix is to raise the reference bandwidth above the fastest link you expect, and to do it on every router at once: the FRRouting documentation is blunt that the setting must be consistent across the domain, because routers that disagree about costs compute different shortest paths, and different paths in a hop-by-hop network can mean loops.
| Link speed | Cost, reference 100 Mb/s | Cost, reference 400 Gb/s |
|---|---|---|
| 10 Mb/s | 10 | 40,000 |
| 100 Mb/s | 1 | 4,000 |
| 1 Gb/s | 1 | 400 |
| 10 Gb/s | 1 | 40 |
| 100 Gb/s | 1 | 4 |
| 400 Gb/s | 1 | 1 |
Two paths from R1 to R4. Path A: R1 to R2 over 100 Gb/s, R2 to R4 over 100 Gb/s. Path B: R1 to R4 directly over a 1 Gb/s backup circuit. With the 100 Mb/s reference, path A costs 1 + 1 = 2 and path B costs 1, so all traffic takes the slow backup link. With a 400 Gb/s reference, path A costs 4 + 4 = 8 and path B costs 400, and traffic takes the fast path, as intended.
The ceiling matters too. Interface costs stop at 65535, so with a 400 Gb/s reference anything slower than about 6.1 Mb/s is pinned at the maximum. In practice that is rarely a problem, and many large networks set costs by hand from a plan rather than deriving them from bandwidth at all.
OSPF is not the only link-state protocol. Chapter 06 covers IS-IS, which solves the same problems with a different packet format and a different idea of areas, and which many of the largest networks prefer.