Learn › Linux networking › Measure a network path

Chapter 6. Measure a network path

A real three-machine networking investigation with chapter-specific checks.

Chapter 6. Measure a network path

Problem: a route exists and the Server is listening, yet a transfer may take longer or lose packets. Measure the healthy path, introduce one controlled queue fault, then remove that fault and check what recovered. The goal is to explain what each measurement shows, not to produce one impressive speed number.

Chapters 1 and 2 taught routes and replies. Chapter 3 separated a permitted service from a blocked one, Chapter 4 separated DNS from an application response, and Chapter 5 compared packets of different sizes. Here we compare time, missing replies and received data rate. No VPN or advanced queue configuration is assumed.

Use the named Client, Router and Server terminals. Check the terminal name before entering a command. Client traffic toward Server leaves Router through eth2; return traffic leaves through eth1. eth0 carries management and must stay unchanged. Use the real terminal output and save each run with its direction and state.

Setup gives Client 10.71.10.10, Server 10.71.20.20, the routes between them, and an iperf3 listener on Server. Read /etc/lab/chapter.json for this session's title, displayed chapter number, port and recovery limits. It should identify Chapter 6. If the addresses, route or listener differ from the descriptor, stop and report the setup mismatch. Do not repair setup by changing routes or starting a new listener.

Round-trip time (RTT) is the time from a ping request until its reply reaches Client. It includes the outward and return paths. If a reply takes 50 ms, that is a complete outward-and-back time, not 50 ms in each direction. Loss in a ping sample means a request did not receive a reply before its bounded wait ended. A missing reply does not, by itself, identify where the packet went.

For example, if one eight-request ping shows seven replies, the sample has one missing reply. That is an example of how to read a result, not a measurement from your machines. A configured 1% random-loss chance need not produce any missing reply in eight tries. Compare repeated live runs and say when the evidence is inconclusive.

6.1 Read the healthy path and its queue

The descriptor is a file of this session's settings. Read it on Client with the command below. JSON displays settings as names paired with values. The output can be long because it also contains setup and calibration records. Find the fields below; you do not need to interpret every setup record. Those records were collected while preparing the lab and are not your measurements.

Median is the middle value after sorting measurements. With an even count, the conventional median averages the two middle values. For illustration only, 1, 2, 3, 4, 5, 6, 7, 8 ms has a median of 4.5 ms. This lab's checker uses the higher middle value, 5 ms in that invented example, as a conservative comparison with its RTT ceiling. It calculates this automatically. You do not need to reproduce the calculation: record ping's displayed minimum and maximum as the RTT range. Ping's average is a different calculation from either median convention.

On Client, the later route lookup should select Router through the exercise interface. It is a route decision, not a successful transfer.

python3 -m json.tool /etc/lab/chapter.json

machine: client prompt: admin@client:~$ answer: python3 -m json.tool /etc/lab/chapter.json output:

hint: Find the port, Router interface, owned handle and recovery limits.

The route result should name Client's exercise interface and Router's next hop. Read those fields before testing traffic.

ip -4 route get 10.71.20.20 from 10.71.10.10

machine: client prompt: admin@client:~$ answer: ip -4 route get 10.71.20.20 from 10.71.10.10 output:

hint: Check that traffic from Client's exercise address uses Router as the next hop.

Router eth2 has an outgoing packet queue. Linux calls its queue rule a qdisc. Netem is a Linux network emulator that can hold or drop packets in a controlled exercise. A handle is the queue's identifier; 707: belongs to this chapter so it can find and remove its own change. The chapter's one fault puts a netem rule at 707: on Router eth2, adding a configured 40 ms delay and 1% random loss. Those are settings, not promised observed results. Packets leaving Router toward Server cross this queue. Bulk reverse-transfer data leaves Router through eth1, although its acknowledgments can cross eth2 on the way back to Server.

On Router, save the original eth2 queue output. For illustration only, the output prefix qdisc fq_codel 0: root ... names the kind fq_codel, the handle 0: and a top-level queue marked root. The dots mean that other output follows. This is a reading example, not a capture from your Router.

This lab accepts setup queue kinds noqueue, fq_codel, pfifo_fast or mq, with handle 0: and one top-level root. The names describe different Linux queue policies; you do not need to configure those policies here. Compare the output with the descriptor's queueBaseline and save the actual starting state. Stop if another kind or handle appears, the baseline does not match, or 707: is already present. Packet counters can change as traffic passes; they do not identify who owns a queue rule.

/sbin/tc -s qdisc show dev eth2

machine: router prompt: admin@router:~$ answer: /sbin/tc -s qdisc show dev eth2 output:

hint: Record the original root before the chapter changes it.

On Router, also save the management route and eth0 queue before the fault. These reads provide a comparison after repair. Never shape eth0.

ip -4 route show default
/sbin/tc -s qdisc show dev eth0

6.2 Predict the direction of the queue fault

6.3 Check the listener and load its port

On Server, check that the listener uses the exercise address and the port from the descriptor. In the ss result, read the local address and port. A listening socket does not prove Client can reach it.

ss -H -lnt '( sport = :5207 )'

machine: server prompt: admin@server:~$ answer: ss -H -lnt '( sport = :5207 )' output:

hint: Compare the bound address and port with the descriptor. If the port differs, stop.

Load the port in this Client shell. The variable lasts only in this shell, so load it again after a new session. This command saves the port as PORT; it does not start a transfer. In 6.4, predict the result before running the transfers.

PORT=$(python3 -c 'import json; print(json.load(open("/etc/lab/chapter.json"))["iperfPort"])')

machine: client prompt: admin@client:~$ answer: PORT=$(python3 -c 'import json; print(json.load(open("/etc/lab/chapter.json"))["iperfPort"])') output:

hint: Use the assigned port in this Client shell.

6.4 Record a bounded healthy baseline

Before running traffic, predict whether Client will receive all eight ping replies and whether forward and reverse TCP transfers will both complete. Write down why. Compare your live samples with the healthy setup. If the baseline is unhealthy, do not add a fault.

On Client, run the bounded ping three times, separately. -c 8 sends eight requests, -i 0.2 spaces them, -W 1 bounds each reply wait, and -I eth1 uses Client's exercise interface. Record the sent and received counts and RTT values for each run.

ping -n -I eth1 -c 8 -i 0.2 -W 1 10.71.20.20

machine: client prompt: admin@client:~$ answer: ping -n -I eth1 -c 8 -i 0.2 -W 1 10.71.20.20 output:

hint: Save the count of replies and the observed times, then repeat for three labeled runs.

Received throughput is how many bits the receiver reports getting per second during a transfer. An iperf3 target of 2M asks this exercise to send at about 2 megabits per second. If the receiver reports about 2 Mbit/s, this offered load worked; the test did not ask how much more the path could carry. It is not a provider or Internet capacity measurement.

Run a five-second Client-to-Server transfer, then use the following card for the reverse direction. timeout 20 bounds a failed connection. -B chooses Client's exercise source address, -p uses the assigned Server port, -t 5 runs five seconds, and -b 2M requests the bounded offered rate. Repeat each direction three times without overlapping runs, waiting for the prompt after each run. Compare runs with the same direction and settings.

At the end of each successful transfer, find the summary line ending in receiver. Record its Bitrate value and unit. Earlier interval lines are parts of the same run, not separate trials. For illustration only, if the final row reports 1.90 Mbits/sec and ends in receiver, record 1.90 Mbit/s for that direction and run. This is an invented reading example, not a promised result. Record whether the command completed and any error. If the sender summary reports Retr, record that count separately: a retransmission means TCP sent data again because delivery had not been confirmed. It does not locate the fault by itself.

timeout 20 iperf3 -4 -c 10.71.20.20 -B 10.71.10.10 -p "$PORT" -t 5 -b 2M

machine: client prompt: admin@client:~$ answer: timeout 20 iperf3 -4 -c 10.71.20.20 -B 10.71.10.10 -p "$PORT" -t 5 -b 2M output:

hint: Read the receiver's bitrate and the command status; repeat for three labeled runs.

For the reverse run, keep the same Client command and add -R. It reverses the bulk data direction; it does not move the command to Server. The receiver is now Client.

timeout 20 iperf3 -4 -c 10.71.20.20 -B 10.71.10.10 -p "$PORT" -t 5 -b 2M -R

machine: client prompt: admin@client:~$ answer: timeout 20 iperf3 -4 -c 10.71.20.20 -B 10.71.10.10 -p "$PORT" -t 5 -b 2M -R output:

hint: The reverse transfer sends bulk data toward Client; repeat separately three times.

An error such as connection refused is not a zero-bitrate sample. Check the actual error and Server's listener. Keep the failed attempt in your notes, but do not mix it with completed transfer results.

6.5 Add one controlled queue fault

The chapter adds only one owned rule: Router eth2, root handle 707:, with 40 ms delay and 1% random loss. labnet is a privilege broker that passes the permitted tc arguments on Router. It is not an alias for unrestricted sudo. Never replace an unknown root or change eth0.

Before using that scoped action, predict which evidence should change. RTT may rise because Client's request crosses eth2. Short-run ping loss may remain at zero despite the configured chance. Forward and reverse received rates may differ, and a 2 Mbit/s offered rate may still be met. State what would make the run inconclusive.

On Router, add the approved fault. If the command fails, stop and inspect the error and current root rather than broadening the command.

labnet tc qdisc add dev eth2 root handle 707: netem delay 40ms loss random 1% limit 1000

machine: router prompt: admin@router:~$ answer: labnet tc qdisc add dev eth2 root handle 707: netem delay 40ms loss random 1% limit 1000 output:

hint: This exact brokered command applies the combined fault to Router eth2 only.

6.6 Distinguish configured loss from measured loss

After adding the fault, wait for its automatic machine verification to finish before starting your own measurement set. It runs probes that can change queue counters; those probes are not part of your labeled samples. Then read Router's queue again and confirm the exact netem owner. First observe the fault, then repair it; an unchanged healthy baseline cannot demonstrate repair. Repeat the same three ping runs and three transfers in each direction. Keep baseline and fault runs separate. tc -s counters describe the queue, not a complete trace of every packet or an application response. Label counter reads around your own test.

For a closer look at loss, an optional Client UDP test uses the same listener. TCP tracks delivery and can resend data; UDP sends individual messages called datagrams without TCP's resend mechanism. -u selects UDP, -b 1M asks for a 1 Mbit/s rate, -t 8 runs eight seconds, and -J prints JSON with measurement names and values. Run it three times separately.

Near the end of each JSON result, find the end section, then sum_received. Confirm that this receiver summary says sender: false; sum_sent describes the sender. Read packets as the reported datagram count, lost_packets as the reported missing count, lost_percent as the reported loss percentage, and jitter_ms as variation in arrival timing, in milliseconds. If you cannot identify the receiver result, keep the output and ask for help instead of guessing. Keep these optional UDP results separate from the required TCP measurements.

An observed percentage can differ from the configured 1% chance. UDP arrival-time variation, TCP retransmissions, ping timeouts and queue drops are different observations. Do not treat one as a substitute for another.

timeout 20 iperf3 -4 -c 10.71.20.20 -B 10.71.10.10 -p "$PORT" -u -b 1M -t 8 -J

Read Router's queue kind and handle again. The illustrative prefix qdisc netem 707: root ... shows the expected kind and owned handle after the fault. Also check the displayed 40 ms delay and 1% loss settings. Compare counters with a labeled run; this example is not a capture of your queue.

/sbin/tc -s qdisc show dev eth2

machine: router prompt: admin@router:~$ answer: /sbin/tc -s qdisc show dev eth2 output:

hint: Confirm a netem root with handle 707: on eth2 only.

The manual measurement cards record command completion without running another full set of iperf3 probes. The fault-add, fault-removal and final-queue cards trigger full automatic machine verification. Wait for each verification to finish before starting or resuming your own measurements. During the fault, recovery checks should remain incomplete. That is expected: the task is to observe the change, then repair it. A state indicator describes this machine at this moment; it does not explain your measurements for you.

6.7 Remove only the owned fault and verify

Compare the fault queue with the original root saved in 6.1. If the only chapter change is the owned 707: root, justify removing it. labnet checks ownership before passing the removal arguments to Router. If the root is unfamiliar, stop rather than deleting it.

labnet tc qdisc del dev eth2 root handle 707:

machine: router prompt: admin@router:~$ answer: labnet tc qdisc del dev eth2 root handle 707: output:

hint: Remove only the chapter-owned 707: root after confirming its kind and interface.

After removing the fault, wait for automatic verification to finish, then read eth2 again and compare its root with the saved baseline. The final queue card also starts verification, so wait for it before your next labeled run. Repeat the same ping and both TCP directions three times. Compare ranges, not one best result. The descriptor's RTT ceiling and 1.5 Mbit/s received threshold in each 2 Mbit/s direction are exercise checks, not production guarantees. Check that Router's management route and eth0 queue still match the saved reads. Automatic verification also inspects reachability, removal of 707:, original root policy and management/routing preservation. Keep its traffic separate from your own measurements.

/sbin/tc -s qdisc show dev eth2

machine: router prompt: admin@router:~$ answer: /sbin/tc -s qdisc show dev eth2 output:

hint: Match the original root, not a memorized default qdisc name.

6.8 Explain the measured result

Save a table in your notes of the actual baseline, combined-fault and repaired runs. For each state include the three ping counts and RTT ranges, three forward and reverse received rates, command errors, and Router eth2 queue state. Explain which traffic crossed eth2, which result supports the queue diagnosis, and what your short samples cannot establish. If the faulty RTT is not clearly separate from baseline, record an inconclusive environment instead of inventing a performance effect.

6.9 Plan for a changed listener problem

Optional reasoning prompt: later, suppose Router's queue and ping RTT match baseline, but iperf3 cannot connect. Predict the Client error and Server listener observation that would distinguish an unavailable listener from the guided queue fault. Explain why deleting a healthy qdisc would be the wrong repair. This is a plan for a different situation, not a test you ran in this session.

References: ESnet iperf3 manual and tc-netem manual. These explain the tools; your descriptor gives this exercise's addresses and recovery limits.

Practice Chapter 6. Measure a network path in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.