Skip to content
academia.sh

Lesson 06 / 13

Reachability Tests

Reading echo and path-test tools correctly: no response from a remote address fits four separate candidate causes, three reachability tests plus a connection attempt together still cannot split two candidate pairs, and what splits them is reading the configuration.

Contents

The previous lesson measured the diagnosis order and showed that two tests in the layered order’s first steps looked weak: echo to the gateway eliminated only 2 candidates, echo to the remote address 4. These tests are diagnosis’s most commonly used tools, and their weakness is not the real problem. The real problem is that they are misread.

The misreading runs in two directions. In the first direction, silence is assumed to say too much: when no response arrives, the conclusion “the machine is down” or “there is no network” is reached, even though more than one cause produces the same silence. In the second direction, a response is assumed to say too much: when a response arrives, “reach is fine” is said, even though the layer that responded is not the layer being reached. This lesson meets both misreadings with numbers.

The Echo Test’s Two-Valued Response

An echo test sends a small request to an address and waits for a response in return. The mock setup reduces this to a two-valued response: response or no-response (SG6). Latency, loss rate, and response order are not measured in this lesson; what is measured is how many candidate causes the silence fits.

There are two separate echo tests, and they look at different distances. Gateway echo asks whether we can reach the local network at all; for a response, the interface being up and the address being assigned is enough. Remote echo asks about the path all the way to the target; for a response, the gateway also has to be correct and the route has to exist. The second test requires everything the first one requires, plus two more conditions. This nesting directly explains why the silence fits more than one cause.

Name resolution is kept out of these tests: echo is done with the address, not the name. An echo done by name mixes two mechanisms into a single response and blurs the cause of the silence by one more candidate. The protocol itself is the subject of the Computer Networks curriculum and is not built here.

Path Test: The Same Test Repeated at Increasing Distance

Traceroute-style path testing is the common name for tools that show the path to a target along with its intermediate stops. What it does is repeat the same reachability question at increasing distances: first one hop out, then two hops out. In the mock setup this corresponds to running gateway echo and remote echo back to back (SG7); the intermediate stops’ individual behavior is not modeled separately.

A third reachability test is a large-packet attempt that is not allowed to fragment (SG8). A path where small packets get through but large ones get lost looks sound to an echo test. This split comes from echo sending a small request: the packet size a test uses determines the fault it cannot see.

A fourth boundary needs to be written up front too: an echo response being deliberately withheld is not in the candidate-cause set (SG9). A target can be configured not to respond to echo at all, and in that case the silence corresponds to no fault on the list. This is the price of the closed-world assumption: a cause outside the list gives the same response as a cause inside it.

The most commonly misread part of path-test output is an intermediate stop’s silence. No response from a stop does not show that stop is broken; intermediate stops are not obligated to respond to requests not addressed to them, and most treat it as low-priority work. The only meaningful line in a path test is the last one: at what distance the path goes completely silent. Empty lines in the middle eliminate no candidate, they only add to the line count. The same mistake runs in reverse too: every stop responding while the target stays silent suggests the path is sound and the fault sits at the target, but the return direction is a separate path, and the outbound direction being sound does not prove the return is.

The mock setup’s reduction to a two-valued response is not a convenience, it is a deliberate boundary. A real echo test also says how many of three requests came back, and “3 lost out of 3” is not the same thing, diagnostically, as “1 lost out of 3”: the first points to a persistent fault, the second to an intermittent one. The mock setup does not cover this second case; intermittent faults are the fourth lesson’s subject. The point to hold onto here is this: every reading that drops the loss rate and reduces the response to two values shows an intermittent fault as either fully sound or fully broken.

# example dump , has not been run
$ ping -c 3 <gateway>                    # one hop out
$ ping -c 3 <target-address>             # all the way to the target
$ tracepath <target-address>             # repetition at increasing distance
$ ping -c 3 -M do -s 1400 <target-address>  # attempt that disallows fragmentation
HEALTHY = {"interface_up": True, "address_set": True, "gateway_correct": True,
           "route_present": True, "resolver_responds": True, "service_listening": True,
           "firewall_passes": True, "path_ok": True}
FAULT = {
    "interface-down":      {"interface_up": False, "address_set": False},
    "no-address":          {"address_set": False},
    "wrong-gateway":       {"gateway_correct": False},
    "missing-route":       {"route_present": False},
    "resolver-silent":     {"resolver_responds": False},
    "service-not-listening": {"service_listening": False},
    "firewall-dropping":   {"firewall_passes": False},
    "large-packet-lost":   {"path_ok": False},
}
CANDIDATES = tuple(FAULT)


def state(a=None):
    d = dict(HEALTHY)
    if a:
        d.update(FAULT[a])
    return d


def path(d):
    return (d["interface_up"] and d["address_set"]
            and d["gateway_correct"] and d["route_present"])


TEST = {                    # five of the common definition's eight used in this lesson
    "gateway-echo": lambda d: ("response" if d["interface_up"] and d["address_set"]
                               else "no-response"),
    "remote-echo": lambda d: "response" if path(d) else "no-response",
    "large-packet": lambda d: ("passes" if path(d) and d["path_ok"]
                               else "blocked"),
    "connection": lambda d: ("unreachable" if not path(d)
                             else "timeout" if not d["firewall_passes"]
                             else "refused" if not d["service_listening"]
                             else "established"),
    "route": lambda d: ("table-empty" if not d["address_set"]
                        else "complete" if d["route_present"] else "no-default"),
}
ECHO = ["gateway-echo", "remote-echo", "large-packet"]     # SG7: traceroute-style


def groups(kit, candidates=CANDIDATES):
    o = {}
    for a in candidates:
        o.setdefault(tuple(TEST[s](state(a)) for s in kit), []).append(a)
    return o


print("how many candidate causes a response fits")
for s in ECHO + ["connection"]:
    for response, fits in sorted(groups([s]).items()):
        print(f"  {s:14s} {response[0]:12s} {len(fits)}  {', '.join(sorted(fits))}")
print()
ORACLE = "wrong-gateway"
print("oracle:", ORACLE, "| tests applied in order")
remaining = CANDIDATES
for s in ECHO + ["connection", "route"]:
    response = TEST[s](state(ORACLE))
    new = tuple(a for a in remaining if TEST[s](state(a)) == response)
    print(f"  {s:14s} {response:12s} eliminated {len(remaining) - len(new)}  left {len(new)}"
          f"  {', '.join(sorted(new))}")
    remaining = new
print()
print("test kit                                       groups  unsplit  largest group")
for kit in (["gateway-echo"], ["remote-echo"], ["gateway-echo", "remote-echo"],
            ECHO, ["connection"], ECHO + ["connection"]):
    o = groups(kit)
    split = [v for v in o.values() if len(v) > 1]
    print(f"  {'+'.join(kit):45s} {len(o):4d} {len(split):12d}"
          f" {max(len(v) for v in o.values()):14d}")
print()
print("candidate set sweep: how many candidates 'remote-echo = no-response' fits")
kit = ["interface-down"]
for a in CANDIDATES:
    if a not in kit:
        kit.append(a)
        fits = [x for x in kit if TEST["remote-echo"](state(x)) == "no-response"]
        print(f"  candidate {len(kit)}  added {a:26s} fits {len(fits)}")
how many candidate causes a response fits
  gateway-echo   no-response  2  interface-down, no-address
  gateway-echo   response     6  firewall-dropping, large-packet-lost, missing-route, resolver-silent, service-not-listening, wrong-gateway
  remote-echo    no-response  4  interface-down, missing-route, no-address, wrong-gateway
  remote-echo    response     4  firewall-dropping, large-packet-lost, resolver-silent, service-not-listening
  large-packet   blocked      5  interface-down, large-packet-lost, missing-route, no-address, wrong-gateway
  large-packet   passes       3  firewall-dropping, resolver-silent, service-not-listening
  connection     established  2  large-packet-lost, resolver-silent
  connection     refused      1  service-not-listening
  connection     timeout      1  firewall-dropping
  connection     unreachable  4  interface-down, missing-route, no-address, wrong-gateway

oracle: wrong-gateway | tests applied in order
  gateway-echo   response     eliminated 2  left 6  firewall-dropping, large-packet-lost, missing-route, resolver-silent, service-not-listening, wrong-gateway
  remote-echo    no-response  eliminated 4  left 2  missing-route, wrong-gateway
  large-packet   blocked      eliminated 0  left 2  missing-route, wrong-gateway
  connection     unreachable  eliminated 0  left 2  missing-route, wrong-gateway
  route          complete     eliminated 1  left 1  wrong-gateway

test kit                                       groups  unsplit  largest group
  gateway-echo                                     2            2              6
  remote-echo                                      2            2              4
  gateway-echo+remote-echo                         3            3              4
  gateway-echo+remote-echo+large-packet            4            3              3
  connection                                       4            2              4
  gateway-echo+remote-echo+large-packet+connection    6            2              2

candidate set sweep: how many candidates 'remote-echo = no-response' fits
  candidate 2  added no-address                 fits 2
  candidate 3  added wrong-gateway              fits 3
  candidate 4  added missing-route              fits 4
  candidate 5  added resolver-silent            fits 4
  candidate 6  added service-not-listening      fits 4
  candidate 7  added firewall-dropping          fits 4
  candidate 8  added large-packet-lost          fits 4

Oracle, Test, Eliminated Candidate

Three numbers sit side by side. Oracle: the real fault is wrong-gateway, that is, the default gateway is set wrong. Test: remote echo returns no-response. Eliminated candidate: this response eliminates 4 of eight candidates and leaves 4 behind.

The silence fitting four candidates is this lesson’s first number. The sentence “no response from the remote address” is on its own consistent with all of interface-down, no-address, wrong-gateway, and missing-route. Reading the silence as “network’s down” lumps these four together as if they were one cause; fixing each of the four is different, and picking the wrong fix does not work.

When gateway echo stays silent, the picture is narrower: only 2 candidates fit (interface-down, no-address). A practical reading follows from this. Nearby silence is more informative than distant silence, because it depends on fewer conditions. This is exactly the path test’s real function too: finding at what distance silence begins, to narrow the number of candidates that fit.

What a Response Does Not Say

The second misreading is sneakier. Echo returning a response eliminates four candidates but leaves 4 behind: resolver-silent, service-not-listening, firewall-dropping, and large-packet-lost. That is, the sentence “the machine is responding” does not mean the service is reachable, and four separate faults are entirely consistent with that sentence.

What makes the difference is that silence and being refused are not the same thing. Two of the connection test’s four responses each pin down a single candidate: refused fits only service-not-listening, timeout only firewall-dropping. Being refused is a response, and the responding side also proves the path is sound; silence is ambiguous about the state of both the path and the target. So what diagnosis looks for is a test that can turn silence into a response.

The large-packet attempt splits off one of these four: in the large-packet-lost scenario, a small echo gets through, a large packet does not. This is diagnosis’s most commonly overlooked signature, because it is the one place two tests contradict each other — one says sound, the other broken, and both are correct.

The step-by-step table shows how this order runs. With the oracle at wrong-gateway, gateway echo eliminates 2 candidates, remote echo eliminates 4; after that, the large-packet attempt eliminates 0, and so does the connection attempt. A test being powerful is not enough: re-eliminating an already-eliminated candidate is not elimination. The connection attempt eliminated seven candidates in the previous lesson; here it eliminates zero, because the tests that ran before it had already made the same split.

The Wall Reachability Tests Hit

The last table is the lesson’s harshest result. Gateway echo alone splits the eight candidates into 2 groups, and the largest group holds 6. Remote echo alone gives 2 groups, largest 4. Together they produce 3 groups, and all three groups hold more than one candidate: these two tests cannot pin down even a single candidate on their own.

Adding the large-packet attempt brings the group count to 4 and the largest group down to 3; the number of unsplit groups is still 3. Adding the connection attempt too produces 6 groups, and 2 unsplit pairs remain: interface-down with no-address, and wrong-gateway with missing-route.

These two pairs stay unsplit no matter how many reachability tests are run. The reason is structural: both members of each pair cut the same path at the same place, so every test that looks at the path gives the same response. What splits them is not looking at the path, it is reading the configuration. The table’s last row does this: the routing-table test returns complete, eliminates the last candidate between wrong-gateway and missing-route, and the diagnosis drops to one candidate.

This is where the course’s second claim shows its first face: adding more tests does not add elimination power. Three reachability tests do not do what a single configuration reading does. What is needed is not multiplying tests but changing their kind.

The reason these tools get used this much is hidden in the same table: they are cheap. An echo test takes seconds, is a one-line command, changes nothing on the target, and its failure is harmless. Cheapness makes a tool the first choice; elimination power is what makes it the tool that finishes the diagnosis, and the two are not the same measure. The measurement counted every test as one step (SG5), that is, decisions were counted, not seconds. Measured in seconds, echo tests would look even more favorable, and it is exactly this appearance that leads to dozens of repeated echo tests once diagnosis stalls. Repeating the same test eliminates no new candidate; the information gained after the first run is fixed.

Candidate Set Sweep

The sweep shows how much the number of candidates the silence fits depends on the set. As the set grows from interface-down up to eight, the number of candidates fitting remote-echo = no-response climbs 1, 2, 3, 4, and stops at four: the four candidates added after that sit in an upper layer and produce a response to remote echo.

The table can also be read backward. Removing a candidate from the list is the same as reading the rows upward: with missing-route removed, the candidates fitting the silence drop from 4 to 3; with wrong-gateway also removed, to 2. Removing always looks like a gain, because the silence narrows; but if the removed candidate is the real fault, the diagnosis ends with zero candidates, and this shows up nowhere in the table.

The result cuts both ways. If the candidate list is short, silence looks more informative — in a three-candidate list, “no response” fits two candidates — but that information is bought at the cost of causes left outside the list. As the candidate list grows, silence’s discriminating power neither grows nor shrinks past a certain point: as long as added candidates give a different response, silence’s meaning stays fixed. What determines a test’s power is not the candidate count, it is which response the candidates fall into.

Summary

  • No response from a remote address fits 4 separate candidate causes; no response from the gateway fits 2. Nearby silence is more informative because it depends on fewer conditions.
  • Echo returning a response also leaves 4 candidates standing; “the machine is responding” does not say the service is reachable.
  • A path test is the same reachability question repeated at increasing distance; the large-packet attempt splits off the one fault a small echo cannot see.
  • Three reachability tests together cannot pin down even a single candidate; adding the connection attempt leaves 2 unsplit pairs, and only reading the configuration splits them.
  • Re-eliminating an already-eliminated candidate is not elimination: the connection attempt eliminates 0 candidates in this order; repeating the same test eliminates no new one either.
  • Being refused is a response and pins down a single candidate; silence is ambiguous about both the path and the target.

Next Step

When reachability tests hit a wall, the next step that comes to mind is usually the same one: looking at the traffic itself. Packet capture does not show a summary of responses, it shows every frame crossing the wire, and for that reason it is counted the “most detailed” tool. The next lesson measures that expectation: it sets the number of lines a capture produces against the number of candidate causes it eliminates, and compares elimination power per line against the connection attempt’s. That packet capture is a diagnosis tool, not a procedure for seizing someone else’s traffic, is also written there, along with its boundary.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close