Foundations to FrontierPart IX: The graduate coreBezhig

G07: Network design, routing, and queueing

6 exercises, each with a complete solution. 1 figure. 1 code listing.

On this page
  1. Prerequisites and observable goals
  2. The central question: where does a request wait?
  3. Address blocks and longest-prefix routing
  4. Worked delay and capacity budgets
  5. Queueing assumptions before queueing formulas
  6. An exact finite trace
  7. Design under faults and trust boundaries
  8. Independent practice
  9. Smallest useful hints
  10. Complete solutions: G07
  11. Readiness and continuation

Prerequisites and observable goals#

Before

foundation C12–C13; binary addresses, protocol framing, and G04’s probability assumptions.

After

Trace an address through a route table, budget transmission and queueing delay, and distinguish an offline model from a deployed secure network.

The central question: where does a request wait?#

A request crosses application code, transport, addressing, links, queues, and remote service work. “The network is slow” does not identify the layer or the delay. Draw an end-to-end path and label each queue, trust boundary, timeout, and message size. Then state which parts you observed rather than treating a local simulation as a network deployment.

A useful decomposition for one message is serialization delay plus propagation delay plus queueing and processing delays. Serialization of LL bits over a link of rate RR bits/s takes L/RL/R seconds. Propagation depends on distance and medium; it does not become shorter because the link can transmit more bits each second. Throughput, goodput, latency, and jitter answer different questions. Goodput excludes protocol overhead and retransmitted data. Jitter describes variation in delay, with the precise statistic needing a definition.

Address blocks and longest-prefix routing#

IPv4 uses 32 address bits. A prefix /pp fixes the first pp bits and leaves 32−p32-p bits for addresses in the block. A /24 contains 28=2562^8=256 addresses. Conventional subnet host-allocation rules may reserve particular addresses, but routing matches the whole address block. Do not confuse total block size with a promised count of assignable hosts under every deployment rule.

A route table can contain overlapping blocks. With routes 0.0.0.0/0 to an edge gateway, 10.0.0.0/8 to a private router, and 10.2.0.0/16 to a lab router, destination 10.2.1.8 matches all three. The longest matching prefix, /16, wins. This favors the most specific available rule, not the most recently listed rule. Equal-prefix policies, administrative preferences, and routing protocols require additional mechanisms; the lab rejects duplicate prefixes instead of silently inventing a tie-break.

The offline implementation parses addresses using the standard library and rejects mixed IP families in one lookup. IPv6 follows the same longest-prefix idea over a different address width and notation, but IPv4-specific broadcast assumptions should not be copied into IPv6. The lab is not a routing daemon and sends no packets. [G-IPADDRESS]

Worked delay and capacity budgets#

A 1,500-byte message contains 12,000 bits. At 100 megabits/s, serialization is 12000/108=.0001212000/10^8=.00012 s, or .12 ms. If propagation is 2 ms one way and there is no queueing or processing, one-way completion is approximately 2.12 ms for that message under this simple model. Doubling bandwidth halves serialization to .06 ms, not the 2 ms propagation term.

The bandwidth-delay product is R⋅RTTR\cdot\mathrm{RTT}. At 100 Mb/s and round-trip time .02 s, it is 2,000,000 bits or 250,000 bytes. A sender may need roughly that much in flight to fill the path under the model. This is not automatically the correct socket buffer size: congestion control, receive windows, packet overhead, loss, and implementation limits matter.

TCP provides a reliable ordered byte stream, not application message boundaries. A successful read can return a prefix of a logical message, and multiple writes can be coalesced. Application framing must be bounded and explicit. Timeouts and connection resets can still leave a remote request outcome unknown. TLS adds authentication/confidentiality/integrity properties under correct certificate and key handling; encryption does not define your business authorization rules. [G-TCP]

Queueing assumptions before queueing formulas#

Little’s law relates long-run averages in a stable system: L=λWL=\lambda W, where LL is average number in the system, λ\lambda the appropriate throughput, and WW mean time in the system. Boundaries and populations must match. Counting only waiting jobs while using total service-plus-wait time mixes definitions. In a dropping queue, offered arrival rate and admitted throughput are different.

For an M/M/1 model with Poisson arrivals of rate λ\lambda, independent exponential service of rate μ\mu, one server, an unlimited waiting room, and λ<μ\lambda<\mu, utilization is ρ=λ/μ\rho=\lambda/\mu and mean system time is W=1/(μ−λ)W=1/(\mu-\lambda). The distributional assumptions are substantial. At λ=80\lambda=80 jobs/s and μ=100\mu=100, W=.05W=.05 s and L=4L=4. At λ=95\lambda=95, W=.2W=.2 s and L=19L=19. Raising utilization from .8 to .95 quadruples mean time in this model. This motivates headroom; it does not predict every tail latency distribution from utilization alone.

The lab uses deterministic service and a finite capacity, so it is not an M/M/1 simulator. It traces exact provided arrivals instead. Capacity counts both the active job and waiting jobs. A completion at exactly an arrival time occurs first. These definitions remove ambiguity before implementation.

An exact finite trace#

Arrivals are 0,.1,.2,10,.1,.2,1 seconds; service takes one second; capacity is two. At time 0, accept job A, start at 0, finish at 1. At .1, accept B and schedule it from 1 to 2. At .2, two jobs are already in the system, so reject C. At 1, complete A before processing D’s arrival; B is active until 2, so accept D and schedule it from 2 to 3. The accepted jobs have response times 1, 1.9, and 2 seconds. Rejected C has no completed response latency in this model and must be counted separately, not silently omitted from a success-rate report.

Solid segments are service, dashed segments waiting. The horizontal axis has real model time; vertical rows identify jobs, not simultaneous servers. This picture explains why a finite buffer can reject work even when service itself remains correct.

Design under faults and trust boundaries#

For a small service, separate public ingress from private data access and administrative control. Specify allowed communication directions, authenticated identities, and failure behavior. A load balancer can distribute traffic but can also be a shared failure point. DNS caching can retain an old destination after a change. Retry storms can increase offered load during an outage. A deployment diagram should show these dependencies instead of simply drawing three identical boxes and calling them independent.

Use bounded request sizes, bounded work queues, admission control, connection/read deadlines, and explicit failure responses. Backpressure asks an upstream producer to slow down or stop; dropping and retrying without a bound may amplify load instead. Validate protocols with malformed/truncated inputs on local or authorized systems only. Security tests in this book are defensive contract checks, not scanning unrelated networks.

Independent practice#

F foundation C standard course work T transfer S optional stretch L runnable lab or project. Attempt the complete set before opening its solutions.

G07.01FSolution

For routes 0.0.0.0/0, 10.0.0.0/8, and 10.2.0.0/16, select the prefix for 10.2.1.8, 10.9.1.8, and 8.8.8.8. Give the address count of a /20 block.

G07.02CSolution

Compute serialization delay for 12,000 bits on a 200 Mb/s link and bandwidth-delay product for that link at 30 ms RTT. State units and distinguish the two quantities.

G07.03CSolution

Under the M/M/1 assumptions, compare mean time in system at (λ,μ)=(80,100)(\lambda,\mu)=(80,100) and (95,100)(95,100) jobs/s. Why should you not use the same formula to certify the lab’s finite deterministic queue?

G07.04TSolution

Trace arrivals (0,0,0,4)(0,0,0,4) with service 1 second and capacity three. Give accepted start/finish times and explain the simultaneous-arrival policy.

G07.05TSolution

A client writes a 500-byte message and a server assumes its next read returns exactly 500 bytes. Explain the fault and design a bounded framing rule that handles partial and coalesced reads.

G07.06LSolution

Implement route and queue_trace in starters/network.py. Use strict network-prefix parsing, reject duplicate prefixes, validate sorted finite arrival times, and enforce the completion-before-arrival boundary rule. Compare predicted traces with output; perform no external network activity.

Smallest useful hints#

For .02, RTT is .03 seconds and a byte is eight bits. For .04, arrivals retain their input order at the same timestamp. For .05, parsing must retain an incomplete prefix between reads rather than discard it.

Complete solutions: G07#

Compare the first step where your work differs. A corrected answer is not yet an independent success.

G07.01Show solution

The most specific matching block

The selections are /16, /8, and /0 respectively. A /20 has 32−20=1232-20=12 free bits, hence 212=40962^{12}=4096 addresses. This count describes the prefix’s address set, not a universal usable-host allocation rule.

Back to G07.01
G07.02Show solution

Transmission time versus in-flight capacity

Serialization is 12000/(200⋅106)=.0000612000/(200\cdot10^6)=.00006 seconds, or .06 ms. Bandwidth-delay product is (200⋅106)(.03)=6⋅106(200\cdot10^6)(.03)=6\cdot10^6 bits, or 750,000 bytes. The first is a time for a fixed message; the second is an amount of data associated with filling the path over one RTT. Neither includes all congestion and protocol effects.

Back to G07.02
G07.03Show solution

Model mismatch invalidates a precise-looking answer

At 80/100, W=1/20=.05W=1/20=.05 s; at 95/100, W=1/5=.2W=1/5=.2 s. The lab has specified deterministic service, finite capacity, and a chosen arrival list; it does not satisfy the exponential service and unlimited-room premises. Its exact trace should be computed from its transition rules. A queueing formula can guide a design only after its assumptions and desired statistics match the modeled system.

Back to G07.03
G07.04Show solution

FIFO with enough capacity

The first three arrivals are accepted in input order and run over intervals [0,1][0,1], [1,2][1,2], and [2,3][2,3]. At time 4 the system is empty, so the fourth runs over [4,5][4,5]. All are accepted. The equal arrival times do not imply simultaneous service because there is one server. Changing tie order would exchange job identities but not these start/finish times for identical service durations.

Back to G07.04
G07.05Show solution

A stream is not a record protocol

The next read may return fewer bytes, or bytes belonging to multiple application messages if the buffer is larger. One bounded design uses a fixed-width length header followed by that many payload bytes, with a strict maximum length. Accumulate bytes until the header is complete, validate length before allocating, then accumulate exactly the payload and preserve any subsequent bytes for the next frame. Define EOF mid-frame as a protocol error. A timeout does not prove that a previously sent request had no effect.

Back to G07.05
G07.06Show solution

Complete offline reference

The route function chooses by prefix length rather than input order. The queue records acceptance and both service endpoints, making waiting and response time reconstructible. The finite buffer policy is explicit in the code and the tests; no simulator output is claimed as real network evidence.

graduate_code/solutions/network.pyPython
"""G07: offline prefix lookup and a one-server finite-capacity FIFO trace."""
from collections import deque
import ipaddress
import math


def route(address, routes):
    address = ipaddress.ip_address(address)
    parsed, seen = [], set()
    for prefix, destination in routes:
        network = ipaddress.ip_network(prefix,strict=True)
        if network in seen:
            raise ValueError("duplicate prefix")
        seen.add(network)
        if network.version != address.version:
            raise ValueError("mixed address families are outside this lab contract")
        parsed.append((network,destination))
    matches = [(n,d) for n,d in parsed if address in n]
    if not matches:
        return None
    network,destination = max(matches,key=lambda item:item[0].prefixlen)
    return str(network),destination


def queue_trace(arrivals, service=1., capacity=3):
    arrivals = list(arrivals)
    if len(arrivals) > 100000 or any(not math.isfinite(t) or t < 0 for t in arrivals):
        raise ValueError("bounded finite nonnegative arrival times required")
    if any(b < a for a,b in zip(arrivals,arrivals[1:])):
        raise ValueError("arrivals must be nondecreasing")
    if not math.isfinite(service) or service <= 0:
        raise ValueError("positive finite service duration required")
    if type(capacity) is not int or not 1 <= capacity <= 100000:
        raise ValueError("capacity counts waiting plus in-service jobs")
    finishes, records = deque(), []
    for job,arrival in enumerate(arrivals):
        while finishes and finishes[0] <= arrival:
            finishes.popleft()  # completions precede arrivals at the same time
        if len(finishes) >= capacity:
            records.append({"job":job,"arrival":arrival,"accepted":False,
                            "start":None,"finish":None})
            continue
        start = max(arrival,finishes[-1] if finishes else arrival)
        finish = start+service
        if not math.isfinite(finish) or finish <= start:
            raise ValueError("service endpoint overflow or no represented progress")
        finishes.append(finish)
        records.append({"job":job,"arrival":arrival,"accepted":True,
                        "start":start,"finish":finish})
    return records


if __name__ == "__main__":
    print(route("10.2.1.8",[("0.0.0.0/0","default"),("10.2.0.0/16","local")]))
    print(queue_trace([0,0,0,4]))
Back to G07.06

Readiness and continuation#

Explain the difference between offered load and admitted throughput, then compute a trace where a completion and arrival coincide. Continue with routing protocols, congestion control, network namespaces, TLS certificate operations, and measured authorized deployment. The lab prepares reasoning about those systems but does not configure a production network. [G-TCP][G-IPADDRESS]