G07: Network design, routing, and queueing
On this page
- Prerequisites and observable goals
- The central question: where does a request wait?
- Address blocks and longest-prefix routing
- Worked delay and capacity budgets
- Queueing assumptions before queueing formulas
- An exact finite trace
- Design under faults and trust boundaries
- Independent practice
- Smallest useful hints
- Complete solutions: G07
- Readiness and continuation
Prerequisites and observable goals#
foundation C12–C13; binary addresses, protocol framing, and G04’s probability assumptions.
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 bits over a link of rate bits/s takes 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 / fixes the first bits and leaves bits for addresses in the block. A /24 contains 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 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 . 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: , where is average number in the system, the appropriate throughput, and 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 , independent exponential service of rate , one server, an unlimited waiting room, and , utilization is and mean system time is . The distributional assumptions are substantial. At jobs/s and , s and . At , s and . 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 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.
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.
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.
Under the M/M/1 assumptions, compare mean time in system at and jobs/s. Why should you not use the same formula to certify the lab’s finite deterministic queue?
Trace arrivals with service 1 second and capacity three. Give accepted start/finish times and explain the simultaneous-arrival policy.
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.
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 free bits, hence addresses. This count describes the prefix’s address set, not a universal usable-host allocation rule.
Back to G07.01G07.02Show solution
Transmission time versus in-flight capacity
Serialization is seconds, or .06 ms. Bandwidth-delay product is 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.02G07.03Show solution
Model mismatch invalidates a precise-looking answer
At 80/100, s; at 95/100, 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.03G07.04Show solution
FIFO with enough capacity
The first three arrivals are accepted in input order and run over intervals , , and . At time 4 the system is empty, so the fourth runs over . 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.04G07.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.05G07.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.
"""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]))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]