§5.2.2The Distance-Vector (DV) Algorithm

Network layer Kurose & Ross pp. 388–395 · ~23 min read

  • distance-vector algorithm
  • bellman-ford equation
  • distance vector
  • quiescent state
  • count-to-infinity
  • poisoned reverse

Where you are

  • Application layer
  • Transport layer
  • Network layer you are here
  • Link layer
  • Physical layer

No node knows the map: each one keeps a list of guessed costs, swaps it with its direct neighbours, and the guesses settle on the true least costs.

Words you will meet

  • Distance-vector algorithm — written DV (Distance-Vector) : the routing algorithm this section builds.

  • Distance vector — one node’s list of guessed costs, one number per destination.

  • Bellman-Ford equation — the one line of arithmetic the whole algorithm repeats.

  • Next-hop router — written v*(y): the neighbour that wins that arithmetic for destination y.

  • Quiescent state — nothing left to send, so the algorithm has quietly stopped.

  • Routing loop — two routers each forward the packet to the other, so it never arrives.

  • Count-to-infinity — two routers raising each other’s estimate, one small step at a time.

  • Poisoned reverse — a deliberate lie that stops one common loop.

Why this matters

Section 5.2.1 asked every router to hold a map of the whole network. That is a strong assumption. Somebody has to deliver that map, to everybody, every time anything changes.

This section removes the assumption. A router here talks only to the routers at the other end of its own links. It never learns the shape of the network, and it still ends up with correct least costs.

That is the design inside RIP (Routing Information Protocol) , inside BGP (Border Gateway Protocol) , and inside the original ARPAnet. It also has a failure that link-state routing does not have, and the failure is visible on this page: the estimates can climb upward together instead of settling.

Three words: iterative, asynchronous, distributed

The book describes the algorithm with three adjectives, and each one is a real property, not decoration.

Distributed. Each node receives information from its directly attached neighbours, performs a calculation, and sends the result back to those neighbours. No node collects everything.

Iterative. The exchange repeats until no more information passes between neighbours. Nobody counts the rounds in advance.

Asynchronous. The nodes do not have to move in step. One router may compute and send while another is still waiting.

There is a fourth property the book mentions in brackets, and it is the strange one. The algorithm is self-terminating. No signal says the computation is finished. It simply stops, because there is nothing left to send. That final silence is the quiescent state .

Everyday picture

Imagine a chain of villages, each connected to the next by a road, and nobody owns a map. Each village puts up one sign: “Nearest hospital: 12 km, take the east road.”

A village reads its neighbours’ signs, adds the length of the road to each neighbour, keeps the smallest total, and repaints its own sign. If the sign changed, the neighbours will read it and repaint theirs.

After a while every sign is correct, and no village ever saw a map.

Where the picture stops. Real villages would notice a sign that points back at the village the reader just came from. Routers do not. That blindness is exactly the count-to-infinity problem later on this page.

The Bellman-Ford equation

Before the algorithm, one piece of arithmetic. Let d_x(y) be the cost of the least-cost path from node x to node y. Then the least costs are related by the Bellman-Ford equation:

dx(y)=minv{c(x,v)+dv(y)}d_x(y) = \min_{v} \{\, c(x, v) + d_v(y) \,\}

where the minimum is taken over all of x’s neighbours.

In plain words

Any path out of x has to start by crossing one of x’s own links. So pick a neighbour v. Crossing that link costs c(x, v). The cheapest rest of the trip from v costs d_v(y). Add them.

Do that for every neighbour and keep the smallest answer. There is no other way out of x, so the smallest answer is the true least cost.

The book’s own check

The book verifies the equation by hand on Figure 5.3, the six-node graph from section 5.2.1. Source u, destination z.

Node u has three neighbours: v, x and w. Walking the graph gives d_v(z) = 5, d_x(z) = 3 and d_w(z) = 3. The link costs are c(u,v) = 2, c(u,x) = 1 and c(u,w) = 5. So:

du(z)=min{2+5,  5+3,  1+3}=4d_u(z) = \min\{\, 2 + 5,\; 5 + 3,\; 1 + 3 \,\} = 4

Four is exactly what Dijkstra’s algorithm produced for the same graph in the previous section. Two completely different methods, one answer.

The Bellman-Ford equation, for a node with three neighbours

What each symbol means

  • xthe node doing the calculation (a node)
  • ythe destination it wants to reach (a node)
  • vone neighbour of x, and the minimum runs over all of them (a node)
  • c(x, v)cost of the single link from x to that neighbour (cost)
  • d_v(y)that neighbour’s least cost to the destination (cost)
  • d_x(y)the answer: x’s least cost to the destination (cost)

Read aloud: To reach the destination I must start by crossing one of my links. So I add each link cost to what that neighbour says the rest of the trip costs, and I keep the smallest total.

d_u(z) — least cost from u to z4

d_x(y) = min over v of { c(x,v) + d_v(y) }
  through the first neighbour: 2 + 5 = 7
  through the second neighbour: 1 + 3 = 4   <- smallest
  through the third neighbour: 5 + 3 = 8
d_x(y) = 4
so v* is the second neighbour: that is the next hop this destination gets in the forwarding table

Change any number above and the arithmetic re-runs, carrying the units through.

The defaults are the book’s own check on Figure 5.3, page 388: source u, destination z, and u’s three neighbours v, x and w. The first pair is the link to v (cost 2) and v’s distance to z (5). The second is the link to x (cost 1) and x’s distance to z (3). The third is the link to w (cost 5) and w’s distance to z (3). Change any of the six numbers and watch which neighbour wins.

Why the equation is more than a curiosity

The book makes two practical points, and both matter more than the equation itself.

The solution fills in the forwarding table. Let v* be the neighbour that achieves the minimum. If x wants to send a packet to y along a least-cost path, it should forward that packet to v*. So x’s forwarding table lists v* as the next-hop router for destination y. The whole computation collapses into one neighbour per destination, exactly as it did for link-state routing.

The equation suggests what neighbours should say to each other. Node x needs d_v(y) — its neighbour’s distance to y. So that is what neighbours send.

What one node stores

Each node x keeps an estimate D_x(y) for every destination y in N, the set of nodes. The whole list is x’s distance vector , written D_x = [D_x(y): y in N].

Three things live in each node, and only one of them ever leaves.

What one node stores, and what it sends
The cost of my own linksstep 1 of 4
the network217xyzx is the node keeping the memorywhat node x keeps1 · the cost of each of my own linksc(x, y) = 2 c(x, z) = 7

x measures or is configured with the cost of each link it is attached to. It knows nothing about the link between y and z.

Node x never sees the graph. It sees two link costs, its own guesses, and the last thing each neighbour said.

Read all steps as text
  1. The cost of my own linksx measures or is configured with the cost of each link it is attached to. It knows nothing about the link between y and z.
  2. My own distance vectorOne estimate for every destination in N, including itself. At the start these are just the direct link costs, and ∞ for anything not directly attached.
  3. The vectors my neighbours sent meOne whole vector per neighbour. This is the only information x ever gets about the rest of the network, and it is second-hand.
  4. And what leaves the nodeOnly box 2, its own vector, and only to direct neighbours. Compare the link-state algorithm, which sends only box 1, but sends it to every node in the network.

N again, and D against d

N is the set of nodes, as it has been since section 5.2. It is not the port count of section 4.2.2 and not the flow count of section 4.2.4.

This section adds a second thing to watch. Small d_x(y) is the true least cost. Capital D_x(y) is one node’s current guess at it. The whole point of the algorithm is that every capital D converges to the matching small d. Until it does, they are different numbers, and the count-to-infinity problem below is entirely a story about capital D being wrong.

The algorithm

Here is the book’s own pseudocode, page 389, running at every node x.

Initialization:
  for all destinations y in N:
      Dx(y) = c(x,y)      /* if y is not a neighbour then c(x,y) = ∞ */
  for each neighbour w
      Dw(y) = ? for all destinations y in N
  for each neighbour w
      send distance vector Dx = [Dx(y): y in N] to w

loop
    wait (until I see a link cost change to some neighbour w or
              until I receive a distance vector from some neighbour w)

    for each y in N:
        Dx(y) = minv{c(x,v) + Dv(y)}

    if Dx(y) changed for any destination y
        send distance vector Dx = [Dx(y): y in N] to all neighbours

forever

In plain words

Start by guessing that every destination costs whatever the direct link to it costs, and ∞ for everything you are not attached to. Tell your neighbours.

Then wait. Two things can wake you: one of your own links changed cost, or a neighbour sent you a vector. Either way, redo the arithmetic for every destination. If any of your own numbers moved, tell your neighbours. Then wait again.

Line 14 is the Bellman-Ford equation with capital D instead of small d. That single line is the algorithm.

Two details are easy to read past.

Line 14 also produces the next hop. For each destination y, the neighbour v that achieves the minimum is v*(y), and x writes it into its forwarding table. If several neighbours tie, any of them will do.

Nothing is sent unless something changed. That is the test on line 16, and it is what makes the algorithm stop.

Figure 5.6: watching it converge

Three nodes, three links, costs 2, 1 and 7. Each node’s routing table holds three rows: its own distance vector, and the last vector received from each neighbour. At the start, the neighbour rows are all ∞, because nothing has arrived.

Figure 5.6 — the distance-vector algorithm in operation
step 0 of 2
217x[0, 2, 7]y[2, 0, 1]z[7, 1, 0]

Initialization. Each node knows only the cost of its own links. Its own row holds those costs, and ∞ for every node it is not attached to. The rows for its neighbours are all ∞, because nothing has arrived yet. Then everyone sends.

Node x table

initial · cost to
xyz
x027
y
z

Node y table

initial · cost to
xyz
x
y201
z

Node z table

initial · cost to
xyz
x
y
z710

Each table holds three rows: the node's own distance vector, in blue and bold, and the last vector it received from each neighbour. A value in amber changed in this round.

One table per node, one column per round, exactly as the book draws it. Every number here is checked against the page image by tools/check-dv-ch05.mjs — all 81 cells of the figure.

Follow node x through the first round. It has just received Dy = [2, 0, 1] and Dz = [7, 1, 0]. It applies line 14:

Dx(x)=0Dx(y)=min{c(x,y)+Dy(y),  c(x,z)+Dz(y)}=min{2+0,  7+1}=2Dx(z)=min{c(x,y)+Dy(z),  c(x,z)+Dz(z)}=min{2+1,  7+0}=3\begin{aligned} D_x(x) &= 0 \\ D_x(y) &= \min\{\, c(x,y) + D_y(y),\; c(x,z) + D_z(y) \,\} = \min\{\, 2 + 0,\; 7 + 1 \,\} = 2 \\ D_x(z) &= \min\{\, c(x,y) + D_y(z),\; c(x,z) + D_z(z) \,\} = \min\{\, 2 + 1,\; 7 + 0 \,\} = 3 \end{aligned}

Its estimate for z falls from 7 to 3. Node y won the minimum for both destinations, so at this point v*(y) = y and v*(z) = y: everything leaves x over the link to y.

Three things in that run are worth naming.

Silence is meaningful. After the first round, y’s vector did not change, so y sends nothing. Only x and z send. A node that has nothing new to say says nothing.

It stops without being told to. After the second round no node’s vector changed, so no messages are sent, so no calculation happens, so nothing will ever change again. Every node sits in the wait on lines 10–11. That is the quiescent state .

The example is synchronous, the algorithm is not. The book draws every node computing at the same moment because it is easier to follow. The real algorithm allows a node to compute and send at any time, and it still converges.

The algorithm sits quiet until a link cost changes. Figure 5.7 shows the same three nodes with different costs: c(x,y) = 4, c(y,z) = 1, c(x,z) = 50.

Before anything happens the estimates have settled: D_y(x) = 4, D_y(z) = 1, D_z(y) = 1, D_z(x) = 5. Both scenarios below follow only the estimates for destination x, which is what the book does.

A cost that falls spreads quickly

The cost of the link from y to x drops from 4 to 1.

Figure 5.7(a) — the cost of the link from y to x falls from 4 to 1
messages sent: 0step 0 of 3
4150xdestinationyD(x)=4 via xzD(x)=5 via y

t0. Before the change. Every estimate has settled and no messages are moving.

tnodeDy(x)Dz(x)sends
04 via x5 via y

Only the column for destination x is followed, which is what the book does. The green arrow out of a node is the neighbour it currently forwards to. Two messages and it is over.

Three moments, and then it is over.

  • At t₀, y detects the change, recomputes D_y(x) = 1, and tells its neighbours.
  • At t₁, z receives the update and recomputes. Its cost to x falls from 5 to 2, so it tells its neighbours.
  • At t₂, y receives z’s update. Its own least cost does not move, so y sends nothing. The algorithm is quiescent.

Two iterations. A cost that falls travels through the network fast.

A cost that rises spreads very slowly

Now the same link goes the other way: c(x,y) rises from 4 to 60.

At t₀, y detects it and recomputes:

Dy(x)=min{c(y,x)+Dx(x),  c(y,z)+Dz(x)}=min{60+0,  1+5}=6D_y(x) = \min\{\, c(y,x) + D_x(x),\; c(y,z) + D_z(x) \,\} = \min\{\, 60 + 0,\; 1 + 5 \,\} = 6

We can see that 6 is wrong, because we can see the whole network. Node y cannot. All y knows is that its own link to x now costs 60, and that z last said it could reach x for 5. So y decides to route through z.

And z routes to x through y. That is a routing loop . A packet for x that arrives at either node is passed to the other, and then back, and never leaves.

Figure 5.7(b) — the same link rises from 4 to 60, and the count begins
messages sent: 0step 0 of 48
4150xdestinationyD(x)=4 via xzD(x)=5 via y

t0. Before the change. Every estimate has settled and no messages are moving.

tnodeDy(x)Dz(x)sends
04 via x5 via y

Press Play and watch the two estimates climb by one each message. The arrows turn red whenever y points at z and z points at x through y — that is the routing loop. Press ⏭ End to jump to the moment z gives up and uses its own 50-cost link.

Watch the two numbers climb. z hears that y can reach x for 6, so z computes min{50 + 0, 1 + 6} = 7. y hears 7 and computes min{60, 1 + 7} = 8. Then 9, then 10, and so on, one step per message.

The loop ends only when z’s path through y finally costs more than z’s own direct 50-cost link. The book says this takes 44 iterations, and the trace above agrees: exactly 44 messages carry an estimate below 50. Three more messages follow — y announces 50, z switches to its direct link and announces 50, and y settles at 51 — and then the algorithm goes quiet.

This is the count-to-infinity problem. The name comes from how bad it can get. Had c(y,x) changed from 4 to 10,000 with c(z,x) at 9,999, the two nodes would have counted upward for thousands of messages.

Everyday picture

Two people are asked where the nearest pharmacy is. Neither knows. Each has heard the other mention one.

The first says “about six minutes that way”, pointing at the second. The second adds a minute for the walk over and answers “seven minutes”, pointing back. The first hears seven, adds a minute, and now says eight.

Nobody lies and nobody makes an arithmetic mistake. The number rises because each answer is built from the other person’s answer, and neither of them can tell.

Where the picture stops. A real person would notice being pointed back at themselves after two rounds. A distance vector carries a cost and nothing else — no list of which nodes the path goes through — so a router genuinely cannot detect it. Section 5.4 shows the fix: BGP puts the whole list of autonomous systems inside the advertisement.

Poisoned reverse

The specific loop above can be avoided, and the trick is small.

If z routes through y to reach destination x, then z tells y that its distance to x is ∞. Not 5, which is the truth. ∞. And z keeps saying it for as long as it routes to x through y.

Since y believes z has no path to x at all, y will never try to route to x via z. The loop cannot form.

The same rise from 4 to 60, with poisoned reverse switched on
messages sent: 0step 0 of 4
4150xdestinationyD(x)=4 via xzD(x)=5 via y

t0. Before the change. Every estimate has settled and no messages are moving.

tnodeDy(x)Dz(x)sends
04 via x5 via y

Three messages instead of 47, and the same final answer. Where a node reports ∞, the panel also prints the value it is hiding.

The same rise from 4 to 60, replayed with the lie switched on:

  • At t₀, y updates and keeps routing directly to x, at the higher cost of 60. It tells z that D_y(x) = 60.
  • At t₁, z receives it. Going through y would now cost 61, so z immediately switches to its own direct link, at cost 50.
  • At t₂, this is a new least-cost path that no longer passes through y, so z tells y the truth: D_z(x) = 50.
  • At t₃, y updates to D_y(x) = 51. Now z is on y’s least-cost path, so y poisons the reverse in turn and tells z that D_y(x) = ∞, although y knows it is 51.

Three messages instead of 47, and the same final answer.

Poisoned reverse does not solve the general problem

The book is careful here, and so is this page. Poisoned reverse fixes loops between two immediately neighbouring nodes. Loops involving three or more nodes are not detected by it at all.

Picture a loop y → z → w → y. y lies to z, z lies to w, w lies to y. But no node lies about the path it does not know it is on, because none of them can see the cycle. The counting begins again.

A book error to know about

Introducing poisoned reverse, the 8th edition writes: “let’s now see how poisoned reverse solves the particular looping problem we encountered before in Figure 5.5(b)”.

The looping problem is Figure 5.7(b), the link that rises from 4 to 60. Figure 5.5 is the route-oscillation figure from section 5.2.1, which is a different problem with a different cause. Verified against the page image of book page 394.

Both algorithms compute least-cost paths and neither one wins. The book’s own summary is a short list of trade-offs, and the opening sentence of that comparison is the cleanest statement of the difference:

In the DV algorithm, each node talks to only its directly connected neighbors, but it provides its neighbors with least-cost estimates from itself to all the nodes in the network. The LS algorithm requires global information — each node would need to communicate with all other nodes, but it tells them only the costs of its directly connected links.

Link-state and distance-vector compared
Link-state (LS)Dijkstra, in OSPFDistance-vector (DV)Bellman-Ford, in RIP and BGP
What one node knows
What one node says, and to whom
Message complexity
Speed of convergence
Robustness

Cells marked ⓘ have a reason behind them — click to read it.

The book’s three comparison points, plus the two facts its opening paragraph contrasts. Click any cell for the reason.

The book’s verdict is that neither algorithm is an obvious winner, and that both are used in the Internet. Section 5.3 covers OSPF (Open Shortest Path First) , which is link-state. Section 5.4 covers BGP (Border Gateway Protocol) , which is distance-vector at heart.

Where else distance vector is used

The book lists the protocols that use a distance-vector design: the Internet’s RIP (Routing Information Protocol) and BGP (Border Gateway Protocol) , ISO’s IDRP (Inter-Domain Routing Protocol), Novell’s IPX (Internetwork Packet Exchange), and the original ARPAnet.

That is a long list for an algorithm with a known failure. The reason is the first row of the matrix above. A distance-vector router needs no map. Delivering a map to every router in a large network is itself a hard problem.

Check yourself

Check yourself

0 of 7 answered
  1. 1.In the distance-vector algorithm, what does one node send, and to whom?

  2. 2.Node x has neighbours y and z, with c(x,y) = 2 and c(x,z) = 7. It has just received Dy = [2, 0, 1] and Dz = [7, 1, 0], where the entries are the costs to x, y and z. What is D_x(z)?

  3. 3.How does a distance-vector computation end?

  4. 4.predictIn the Figure 5.7(b) widget the cost of the link from y to x rises from 4 to 60. Set it running. What do the two estimates for destination x do?

  5. 5.Poisoned reverse: z reaches destination x through y. What does z tell y about its distance to x, and why?

  6. 6.Does poisoned reverse solve the count-to-infinity problem?

  7. 7.A router in the middle of a network starts advertising wrong least costs. Under which algorithm does the damage spread further?

What to remember

  • No node knows the graph. A node knows the cost of its own links and the last vector each neighbour sent. Nothing else.
  • A falling cost spreads fast; a rising cost can spread very slowly — 44 message exchanges in Figure 5.7(b) before the loop breaks. Count-to-infinity is not a bug in the arithmetic: every node computes correctly from information that is stale.
  • Link-state sends a little to everyone; distance-vector sends a lot to a few. That one sentence generates every row of the comparison.