Routing Fundamentals

Updated

September 4, 2026

Routing Fundamentals

Routing is longest-prefix match to a next hop or interface, plus the glue that resolves the next hop to L2. This chapter ties RIB/FIB, metrics, and host vs router behavior into one model you will reuse for statics and dynamic protocols.

Learning goals

By the end of this chapter you can:

  • Explain longest prefix match with competing routes
  • Distinguish connected, static, and protocol routes
  • Resolve next hops (ARP/ND) and see failures when resolution dies
  • Use ip route get as a decision debugger
  • Describe host default-route behavior vs multi-interface routers

Concepts

Forwarding equation

For each packet:

  1. Look up destination in FIB
  2. Select winning route (longest prefix, then tie-breakers)
  3. Find egress interface and L2 rewrite target
  4. Decrement TTL / hop limit; drop if zero

RIB vs FIB

Store Role
RIB Routing information: all candidates, protocol owners
FIB What data plane uses for forward

On Linux, ip route shows kernel FIB. FRR holds protocol RIB and installs selected routes into the kernel via zebra.

ip route
vtysh -c 'show ip route'   # FRR RIB view

Longest prefix match

Routes:

  • 0.0.0.0/0 via gwA
  • 10.0.0.0/8 via gwB
  • 10.1.2.0/24 via gwC

Destination 10.1.2.5gwC. Destination 10.9.0.1gwB. Destination 1.2.3.4gwA.

ip route add 10.0.0.0/8 via 192.0.2.1
ip route add 10.1.2.0/24 via 192.0.2.2
ip route get 10.1.2.5

Metrics and distance (ideas)

Multiple protocols may offer the same prefix. Selection uses administrative preference (distance) then metric. Linux has metrics on routes; FRR has AD per protocol. Exact numbers differ—model is ranked sources.

Connected routes

Configuring 10.1.0.1/24 on eth1 installs connected route 10.1.0.0/24 dev eth1. Connected usually beats static/default for that space.

Host vs router

Host Router
Often one default route Many specific routes
Forwards? usually no ip_forward=1
ARP for on-link and gateway ARP for each next hop per interface
Care about DNS, apps Care about RIB scale, policy

Gateway ARP

When host sends off-link:

  • Destination IP stays the remote
  • Ethernet dest is gateway MAC
# host
ip route get 8.8.8.8
ip neigh show
tcpdump -ni eth1 -e host 8.8.8.8

Next-hop resolution failures

Symptom: route exists, ping fails.

ip route get 10.2.0.10
# shows via 10.0.0.2 dev eth1
ip neigh show dev eth1
# if FAILED/INCOMPLETE for 10.0.0.2 → L2 problem or peer down

Control vs data: Static route “up” in config does not guarantee next hop resolves.

Asymmetric routing

Forward path R1→R2→R3, return R3→R4→R1. Stateless ping may work; stateful firewalls and some reverse-path filters break.

Always verify both directions.

# from each side
ping -c 2 <other>
traceroute -n <other>

Lab: competing prefixes

name: l3-lpm

topology:
  nodes:
    h1:
      kind: linux
      image: alpine:3.20
      exec:
        - apk add --no-cache iproute2 iputils
        - ip addr add 192.168.0.10/24 dev eth1
        - ip link set eth1 up
        - ip route add default via 192.168.0.1
        - ip route add 10.1.2.0/24 via 192.168.0.2
    r1:
      kind: linux
      image: alpine:3.20
      exec:
        - apk add --no-cache iproute2 iputils
        - ip addr add 192.168.0.1/24 dev eth1
        - ip link set eth1 up
    r2:
      kind: linux
      image: alpine:3.20
      exec:
        - apk add --no-cache iproute2 iputils
        - ip addr add 192.168.0.2/24 dev eth1
        - ip link set eth1 up

  links:
    - endpoints: ["h1:eth1", "r1:eth1"]
    # NOTE: for a real multi-router demo, use a bridge multipoint or
    # connect h1-r1 and h1-r2 carefully; simplest teaching variant below.

Cleaner multipoint teaching lab: one LAN bridge with h1, gw1, gw2:

name: l3-lpm

topology:
  nodes:
    br0:
      kind: linux
      image: alpine:3.20
      binds: ["./config/br.sh:/startup.sh"]
      cmd: /bin/sh /startup.sh
    h1:
      kind: linux
      image: alpine:3.20
      exec:
        - apk add --no-cache iproute2 iputils
        - ip addr add 192.168.0.10/24 dev eth1 && ip link set eth1 up
        - ip route add default via 192.168.0.1
        - ip route add 10.1.2.0/24 via 192.168.0.2
    gw1:
      kind: linux
      image: alpine:3.20
      exec:
        - apk add --no-cache iproute2 iputils
        - ip addr add 192.168.0.1/24 dev eth1 && ip link set eth1 up
    gw2:
      kind: linux
      image: alpine:3.20
      exec:
        - apk add --no-cache iproute2 iputils
        - ip addr add 192.168.0.2/24 dev eth1 && ip link set eth1 up

  links:
    - endpoints: ["h1:eth1", "br0:eth1"]
    - endpoints: ["gw1:eth1", "br0:eth2"]
    - endpoints: ["gw2:eth1", "br0:eth3"]

Predict / observe

docker exec clab-l3-lpm-h1 ip route get 10.1.2.5
# expect via 192.168.0.2
docker exec clab-l3-lpm-h1 ip route get 10.9.0.1
# expect via 192.168.0.1 (default) if no better route

Lab: router with two interfaces

# r1
sysctl -w net.ipv4.ip_forward=1
ip addr add 10.1.0.1/24 dev eth1
ip addr add 10.2.0.1/24 dev eth2
# hosts with defaults via r1

Predict: Connected routes cover both LANs; hosts need default only; r1 needs no static for inter-LAN.

Observe:

ip route
ip route get 10.2.0.10 from 10.1.0.10 iif eth1

ARP/ND deep enough for routing

IPv4 IPv6
ARP request/reply NS/NA
ip neigh ip -6 neigh
Broadcast Multicast solicited-node
ip monitor neigh

Flush for drills:

ip neigh flush dev eth1

TTL and traceroute

Each hop decrements TTL. Traceroute infers path from ICMP time exceeded.

traceroute -n 10.2.0.10
# or
mtr -rwzc 20 10.2.0.10

Filters that drop ICMP break traceroute but not always data—note for ops.

Policy preview

Policy routing (ip rule) can select alternate tables. Out of scope for depth here; know it exists when “ip route get” surprises you with marks/fwmasks.

ip rule list

Predict → observe → fix drills

Drill: missing return route

Two routers between hosts; only one direction has statics.

Symptom: requests arrive, replies die.

Fix: install return route.

Harden: verify.sh pings both ways.

Drill: wrong gateway MAC path

Shut gateway interface; host neigh becomes FAILED.

ip neigh show
ping -c 2 <offlink>

Drill: more-specific shadow

Add junk more-specific blackhole:

ip route add 10.2.0.10/32 via 192.0.2.254
# 192.0.2.254 dead
ping 10.2.0.10  # fail despite broader working route
ip route del 10.2.0.10/32

Cheatsheet

ip route
ip route get 1.2.3.4
ip route add 10.0.0.0/8 via 192.168.0.1 metric 100
ip route del 10.0.0.0/8 via 192.168.0.1
ip neigh show
sysctl net.ipv4.ip_forward

Summary

  • Longest prefix match drives selection
  • Connected, static, and dynamic routes feed RIB→FIB
  • Next hop must resolve at L2
  • Hosts mostly default; routers interconnect prefixes
  • Bidirectional reachability is the real goal

Next: static routing labs—triangles, floating statics, and deliberate failover.