# Python playground

> Real CPython 3.14 in your browser, for the arithmetic of networks: subnets, masks, EUI-64, DNS headers in struct, HMAC, latency statistics, transfer times. A 13.5 MB engine downloads once, when you say so; nothing you type leaves the page.

- Tool: https://ronutz.com/en/tools/python-playground
- Family: Operations & Fieldcraft

---

## What it does

Real CPython 3.14 runs in your browser. The engine is Pyodide 314.0.7, the Pyodide project's build of CPython for WebAssembly, served from this origin and pinned by version and SHA-256 digest. You write a program, optionally give it some standard input, press Run, and read stdout, stderr and the value of the last expression, the way a REPL would show it. Nothing you type leaves the page: the interpreter lives in a Web Worker on your device, has no network and no processes, and the page's own policy would refuse them anyway.

It is the first tool on this site that runs code which is not the site's own. Three things follow, and the page says each of them out loud rather than hiding them:

- **A download happens, once, when you say so.** The engine is about 13.5 MB in five files. The page opens with the editor and an example but without the engine; one button, which names the size, starts the download with a progress bar. Your browser caches the files (they are versioned and marked immutable), so a second visit costs nothing.
- **A third-party engine runs.** The site's own checks cover the harness around it: the preflight, the limits, the examples (which are re-run through the real engine at every build), and the pinned files' digests. The interpreter's behaviour is the Pyodide project's.
- **The standard library is what is available.** The Pyodide distribution offers 357 packages (numpy, pandas, requests and the rest); none of them is loaded in this version. Forty standard-library modules are absent from the WebAssembly build (tkinter, curses, pwd, grp, readline, among others) and the preflight names them if you import one.

## The preflight

Before anything is sent to the engine, the program text is read (never executed) and you are told what will not work here and why, in the engine's own terms:

- an import of a standard-library module this build lacks, with the error the engine raises;
- an import of a package the Pyodide distribution offers but this version does not load, named by its package name (PIL is Pillow, yaml is pyyaml);
- an import of something nobody can install here, or a relative import, which has no package to be relative to;
- network modules (socket, urllib, http, requests...) and process modules (subprocess, multiprocessing, os.system), which Emscripten refuses;
- zoneinfo, which finds no time zone database here and raises ZoneInfoNotFoundError;
- input() with an empty stdin box, which raises EOFError on the first read;
- a time.sleep longer than the wall-clock limit, an unbounded while True, modules whose output changes between runs (random, time, uuid, datetime.now);
- files, which live in the engine's memory and vanish with the run; a program that prints nothing (the last expression's value is shown instead); tabs and spaces mixed in indentation.

Items marked as errors block the run; the rest are notes.

## Limits

- Program: 20,000 characters. Standard input: 20,000 characters.
- Wall clock: 30 seconds per run. At the limit the Worker is terminated and a fresh one is started from the cached files.
- Output: 200,000 characters per stream, then cut and marked.
- Stop terminates the Worker at once (the only way to interrupt synchronous Python without a cross-origin-isolated interrupt buffer, which this static site does not carry) and starts a new one.
- Each run starts in a fresh global namespace with `__name__` set to `"__main__"`, so runs do not leak variables into each other and the main-guard idiom works.

## Standard input

The stdin box feeds `input()` and `sys.stdin`, one line per read, then end of file. A trailing newline does not add an empty line. `for line in sys.stdin:` reads all of it.

## The examples

Thirteen programs written for the people this site is for: splitting a /24 into /26s, aggregating prefixes, netmasks and wildcards in binary, a modified EUI-64 from a MAC, a DNS header built with struct, HMAC-SHA256 in hex and base64url, latency statistics with p95, jitter and two standard deviations, transfer times at three line rates, a syslog count by severity from pasted log text, lines read from the stdin box, fields picked from an API response, Dijkstra's shortest path first on six routers, and the bare last expression. Their exact output is recorded as golden vectors and re-measured through the real engine under Node at every build; an engine upgrade that changes any of them fails the build and is looked at on purpose.

The latency example prints both standard deviations and labels each one. `statistics.pstdev` returns "the population standard deviation", which is what ping prints as mdev: the ping(8) manual page says "Population standard deviation (mdev)", and iputils computes it by dividing the summed squared deviations by the number of replies. `statistics.stdev` returns "the sample standard deviation", which is larger for the same samples (8.34 against 7.99 ms in the example). Compare the pstdev line with ping's `rtt min/avg/max/mdev` summary, not the stdev line.

The SPF example runs Dijkstra's shortest path first (SPF) from router R1 over the six routers and eight links of the [Dijkstra article](https://ronutz.com/en/learn/dijkstra-and-the-twenty-minute-algorithm), with a `heapq` candidate list, and prints every step in the order RFC 2328 section 16.1 describes: "the paths to the candidate vertex that is closest to the root are guaranteed to be shortest", so that router joins the tree and its links are examined; a shorter path replaces a candidate's cost and next hops, an equal-cost path adds its next hops to those listed, and the run ends when the candidate list is empty. It finishes with each router's cost, next hops and parents, and the order in which the costs became final (R1 R3 R2 R4 R5 R6), which is Dijkstra's 1959 idea in his own words: "the minimal paths from P to the other nodes are constructed in order of increasing length". Candidates of equal cost leave the heap in router-name order, a rule the program states in a comment, so the output is the same on every run. Change one cost (R2 to R4 from 1 to 20, say) and run it again to watch the next hops move; the [OSPF primer](https://ronutz.com/en/learn/ospf-primer) covers the protocol that runs this calculation.

## What the API does not do

This tool is not exposed on the HTTP API. Executing arbitrary Python on shared infrastructure would be remote code execution; the engine runs in your browser only. The preflight is a teaching aid around the editor, not a stable contract.

## Sources

The Pyodide documentation (web worker and standard-stream pages, version 314.0.7), the package's own package.json, pyodide-lock.json and typings on the npm registry, the CPython 3.14 documentation for the modules the examples use, RFC 1035 section 4.1.1, RFC 4291 Appendix A and RFC 5424 section 6.2.1 for the examples' arithmetic, and MDN for the module Worker and the Content Security Policy source list, read on 2026-10-04. The Python 3.14 statistics page (pstdev and stdev), the ping(8) manual page on man7.org and the iputils source of ping's summary line (ping/ping_output.c) were read on 2026-10-19, as were RFC 2328 sections 16.1 and 16.1.1 (rfc-editor.org) and Dijkstra's 1959 note, A Note on Two Problems in Connexion with Graphs, Numerische Mathematik 1, pages 269 to 271 (the scan in the CWI repository that the Dijkstra article cites), for the SPF example. All are listed on the tool page.

## Standards and references

- [Pyodide documentation: Using Pyodide in a web worker](https://pyodide.org/en/stable/usage/webworker.html) - Pyodide requires a module-type worker because pyodide.asm.mjs is an ES module; classic workers using importScripts() are not supported.
- [Pyodide documentation: Redirecting standard streams](https://pyodide.org/en/stable/usage/streams.html) - The stdin callback returns one full line per call and null for end of file; batched stdout handlers receive lines without their newline or flushed partial lines.
- [pyodide 314.0.7 on the npm registry (package.json, pyodide-lock.json, pyodide.d.ts)](https://www.npmjs.com/package/pyodide/v/314.0.7) - Version, MPL-2.0 licence, the embedded Python 3.14.2, the 357-package lock, and the loadPyodide, runPythonAsync, setStdin, setStdout and setStderr signatures.
- [pyodide/pyodide on GitHub](https://github.com/pyodide/pyodide) - The engine's source repository.
- [Python 3.14 documentation: sys.stdlib_module_names](https://docs.python.org/3.14/library/sys.html#sys.stdlib_module_names) - The names classified as standard library are the engine's own sys.stdlib_module_names, read at generation time.
- [Python 3.14 documentation: ipaddress](https://docs.python.org/3.14/library/ipaddress.html) - ip_network, subnets, hosts, collapse_addresses, netmask and hostmask used by the examples.
- [Python 3.14 documentation: struct](https://docs.python.org/3.14/library/struct.html) - Big-endian packing of the DNS header example.
- [Python 3.14 documentation: hmac and hashlib](https://docs.python.org/3.14/library/hmac.html) - HMAC-SHA256 as the examples compute it.
- [Python 3.14 documentation: statistics](https://docs.python.org/3.14/library/statistics.html) - mean, median, pstdev (the population standard deviation) and stdev (the sample standard deviation) in the latency example.
- [ping(8), iputils manual page on man7.org: "Population standard deviation (mdev)"](https://man7.org/linux/man-pages/man8/ping.8.html) - What ping's mdev is: the population standard deviation of the round-trip times, which the latency example prints as pstdev.
- [iputils ping/ping_output.c, ping_print_statistics (master branch)](https://github.com/iputils/iputils/blob/master/ping/ping_output.c) - tmvar = (tsum2 - tsum * tsum / total) / total, then its integer square root printed as the mdev of rtt min/avg/max/mdev: a population (divide by the count) standard deviation.
- [Python 3.14 documentation: zoneinfo (data sources)](https://docs.python.org/3.14/library/zoneinfo.html#data-sources) - zoneinfo reads the system tz database or the tzdata package; the engine has neither unless the tzdata package is loaded, and raises ZoneInfoNotFoundError saying so (measured 2026-10-04).
- [RFC 1035, Domain names: implementation and specification, section 4.1.1 (header section format)](https://www.rfc-editor.org/rfc/rfc1035#section-4.1.1) - The 12-byte header the struct example builds.
- [RFC 4291, IP Version 6 Addressing Architecture, Appendix A (modified EUI-64 interface identifiers)](https://www.rfc-editor.org/rfc/rfc4291#appendix-A) - The universal/local bit flip and the FF FE insertion in the EUI-64 example.
- [RFC 5424, The Syslog Protocol, section 6.2.1 (PRI = facility times 8 plus severity)](https://www.rfc-editor.org/rfc/rfc5424#section-6.2.1) - The severity derived as PRI modulo 8 in the syslog example.
- [RFC 2328, OSPF Version 2, section 16.1 (calculating the shortest-path tree for an area) and 16.1.1 (the next hop calculation)](https://www.rfc-editor.org/rfc/rfc2328.txt) - The spf-dijkstra example follows section 16.1: the closest candidate joins the tree, its links are examined, an equal-cost path adds its next hops to those listed, a shorter one replaces them, and the run ends when the candidate list is empty; a destination behind another router inherits its parent's next hops (16.1.1).
- [E. W. Dijkstra, A Note on Two Problems in Connexion with Graphs, Numerische Mathematik 1, pages 269 to 271, 1959 (scan in the CWI repository)](https://ir.cwi.nl/pub/9256/9256D.pdf) - Problem 2, the path of minimum total length: the minimal paths from P to the other nodes are constructed in order of increasing length, which is the order the spf-dijkstra example prints.
- [MDN: Worker() constructor, the type option](https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker) - type: module makes the worker a module worker; the worker is created on the main thread and terminated with Worker.terminate().
- [MDN: Content-Security-Policy script-src, the wasm-unsafe-eval source](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src) - The page policy already carries wasm-unsafe-eval for Pagefind; the engine was measured to load and run under that policy without unsafe-eval.

## Related reading

- [A VLSM allocation, worked end to end](https://ronutz.com/en/learn/vlsm-worked-example.md): One documentation block, 203.0.113.0/24, carved into five subnets of different sizes for a small site, with every network address, mask, host range and broadcast address written out and checked, the leftover accounted for, the same two router links as /31 prefixes, the failure that the arrival order produces, and the one route that reaches the whole plan. After reading, you can repeat the procedure on a block of your own by hand, with the CIDR / Subnet Calculator and with a few lines of Python.
- [BFD: when a link is up and dead at the same time](https://ronutz.com/en/learn/bfd-when-a-link-is-up-and-dead.md): Bidirectional Forwarding Detection (BFD) is a small Hello protocol between two forwarding engines that notices a path has stopped carrying packets, including when both interfaces stay up, long before a routing protocol's own timers would. After reading, you can compute a detection time from the two timers and the multiplier, read a session in FRRouting field by field, choose which protocol should be its client, and say where BFD itself can be fooled.
- [CGNAT: what breaks when a thousand subscribers share one address](https://ronutz.com/en/learn/cgnat-address-sharing-and-attribution.md): Carrier-grade NAT (CGN) is a NAT in the provider's network that shares one public IPv4 address among many subscribers, with the shared address space 100.64.0.0/10 numbering the link behind it. After reading, you can state what RFC 6888 requires of a CGN, name what the published tests found broken, explain why an address alone no longer identifies a subscriber, compute the log volume and a deterministic port block, place NAT444 among DS-Lite and the A+P designs, and check whether your own connection sits behind one.
- [Dijkstra: the twenty-minute algorithm your routers run every day](https://ronutz.com/en/learn/dijkstra-and-the-twenty-minute-algorithm.md): In 1956 Edsger W. Dijkstra designed a shortest-path algorithm on a café terrace in Amsterdam, without pencil and paper, to demonstrate a new computer; every router running Open Shortest Path First (OSPF) or Intermediate System to Intermediate System (IS-IS) computes the tree that algorithm produces. After reading, you can tell the story from his own words, run the algorithm by hand on six routers, explain why link costs must be positive and why equal costs give several next hops, and find the result and the SPF throttle on a router.
- [First-hop redundancy: VRRP, HSRP, and the gateway that is a fiction](https://ronutz.com/en/learn/first-hop-redundancy-vrrp-and-hsrp.md): First-hop redundancy protocols such as VRRP and HSRP let several routers share one default gateway address and one virtual MAC address, so that hosts keep forwarding when the router behind that address fails. After reading, you can say what a host can and cannot do on its own, compute a VRRPv3 failover time from priority and interval, compare HSRP's defaults, recognise the usual failures and the attack surface, and find both protocols in a capture and in router output.
- [How a WebAssembly tool works: what runs, where it comes from, and what leaves the page](https://ronutz.com/en/learn/how-a-webassembly-tool-works.md): Most tools on this site are small pure functions written here and tested with golden vectors. A Python playground cannot be that: the thing you want is a real interpreter, and the honest way to give you one on a static site is CPython compiled to WebAssembly, downloaded by your browser and run in its sandbox. This article explains what changes when a tool runs third-party code: the download and why it waits for your consent, the Worker and why Stop is a termination, the Content Security Policy and what was measured against it, the pinned files and their digests, the wall clock, and which checks are the site's and which are the engine's. With the engine's own documentation cited for each claim.
- [How an Access Point Finds Its Controller](https://ronutz.com/en/learn/dhcp-option-43-discovery.md): Dynamic Host Configuration Protocol (DHCP) option 43 carries vendor-specific information whose meaning the vendor named in option 60 defines, so the same option holds binary addresses for one access point and text for another, while a third reads its controller from option 138 instead. After reading, you can build and decode the value each documented vendor expects byte by byte, get the server to return it to the right vendor class, recognise the silent failure and the rogue-server risk, and read the value back from a capture or a DHCP server.
- [How IPv4 addresses work](https://ronutz.com/en/learn/ipv4-addressing.md): Every IPv4 header carries two addresses, source and destination, each one 32-bit number written as four decimal octets, with a prefix length that splits it into network and host. After reading, you can convert an address to binary and to an integer by hand, apply a mask the way a host does to decide whether a destination is on its link, recognise the special-purpose blocks and their rules, and say who hands addresses out and when the free pool ran out.
- [How IPv6 hosts get addresses: SLAAC and DHCPv6](https://ronutz.com/en/learn/ipv6-address-configuration.md): An IPv6 host configures itself from what routers advertise: a link-local address it checks for duplicates, global addresses it builds by stateless autoconfiguration from each prefix marked for it, and, where the network offers them, addresses, prefixes and DNS servers leased by DHCPv6. After reading, you can read the flags and lifetimes of a router advertisement, derive EUI-64, stable and temporary interface identifiers, tell stateful, stateless and prefix-delegation DHCPv6 apart, predict which source address a host uses, recognise rogue advertisements, duplicate addresses and stale prefixes, and watch each step with ip, rdisc6, tcpdump and Wireshark.
- [ICMP, ping, and traceroute: the Control Messages That Explain Your Network](https://ronutz.com/en/learn/icmp-ping-and-traceroute.md): The Internet Control Message Protocol (ICMP) is the part of IP that reports on delivery instead of carrying data: Echo and Echo Reply are ping, Time Exceeded is traceroute, and Destination Unreachable names what failed. After reading, you can read a ping line and its summary field by field, follow a traceroute probe by probe from TTL 1 to the final Port Unreachable, tell a filtered path from a dead one, say whose address a hop line prints, and decode the Unreachable codes in IPv4 and ICMPv6.
- [IPv6 subnetting and the /64 boundary](https://ronutz.com/en/learn/ipv6-subnetting.md): IPv6 subnetting divides the upper 64 bits of an address between registry, provider, site and link, because on almost every link the lower 64 bits belong to the interface identifier. After reading, you can explain why a link is a /64 and what stateless autoconfiguration has to do with it, size an end site's prefix and follow its delegation, count and number subnets on nibble boundaries, number router links and loopbacks with /127 and /128, build a unique local prefix, and avoid the mistakes that break an addressing plan.
- [IS-IS: the routing protocol hiding under the internet](https://ronutz.com/en/learn/isis-primer.md): Intermediate System to Intermediate System (IS-IS) is the link-state routing protocol ISO wrote for OSI and RFC 1195 extended to IP: it floods link state as OSPF does, but its packets travel on the link layer, not inside IP. After reading, you can build a NET from a loopback address, tell Level 1 from Level 2 routing, predict which router becomes the DIS on a LAN, read show isis neighbor and show isis database in FRRouting, and say what its authentication protects and what it leaves open.
- [MPLS: labels, stacks, and the BGP-free core](https://ronutz.com/en/learn/mpls-primer.md): Multiprotocol Label Switching (MPLS) classifies a packet once, at the edge of a network, and from then on routers forward it on a short label they swap, pop or push, without reading the IP header again. After reading, you can decode a label stack entry in hex, name the special-purpose labels, follow one label-switched path through a real Label Distribution Protocol (LDP) binding table, say exactly what a BGP-free core keeps and drops, and explain the two labels of a layer 3 virtual private network (VPN) packet.
- [Multicast: what it costs to not flood](https://ronutz.com/en/learn/multicast-what-it-costs-to-not-flood.md): IP multicast sends one datagram to a group address and lets the network make the copies, and the price is state in every switch and router that must know where the members are. After reading, you can map a group address to its media access control (MAC) address, compute the Internet Group Management Protocol (IGMP) timeouts, explain why a switch floods multicast and what a missing querier does, read Protocol Independent Multicast (PIM) state in FRRouting, and say what Source-Specific Multicast removes.
- [NAT Explained: Source, Destination, and Why the Internet Still Works](https://ronutz.com/en/learn/nat-explained.md): Network Address Translation maps addresses from one address realm to another and keeps a table so that replies find their way back; NAPT, the form a home router runs, maps the port as well. After reading, you can read a translation table and a conntrack listing field by field, follow the checksum adjustment, predict how long a mapping lives and which packets it lets in, name what NAT breaks, and say precisely why NAT is not a firewall.
- [Neighbor Discovery: how IPv6 replaces ARP](https://ronutz.com/en/learn/ipv6-neighbor-discovery.md): Neighbor Discovery is the ICMPv6 protocol every IPv6 node runs on its link: five messages that take over from ARP, ICMP router discovery and redirects, and also handle unreachability and duplicate-address detection. After reading, you can decode the five messages, compute a solicited-node group and its Ethernet address by hand, follow a resolution through the neighbour cache, recognise rogue advertisements and cache exhaustion and their defences, and watch it all with ip, ndisc6, tcpdump and Wireshark.
- [OSPF: the map, the math, and area 0](https://ronutz.com/en/learn/ospf-primer.md): OSPF is the Internet Standard link-state interior gateway protocol: each router floods a description of its own links, every router in an area holds the same database, and each one computes its own shortest-path tree from it. After reading, you can work out a route by hand from link costs, say why two routers will not become neighbours, explain the designated router election and the rules for areas, set costs without the reference-bandwidth trap, and read FRRouting's neighbour, database, route and interface output.
- [Port blocks and port sets: the arithmetic of sharing one IPv4 address](https://ronutz.com/en/learn/port-blocks-and-port-sets.md): When a carrier-grade NAT or a MAP domain shares one public IPv4 address, what it divides is the 16-bit port field, by blocks, by a deterministic formula or by bit fields. After reading, you can work out how many subscribers an address and a pool hold, what block logging saves, which subscriber held a given address, port and time under RFC 7422, and which ports a MAP PSID owns.
- [Private IPv4 address space and RFC 1918](https://ronutz.com/en/learn/private-address-space.md): RFC 1918, Best Current Practice 5 since February 1996, reserves 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 for addresses any enterprise may use internally: unique only inside it, and kept out of the internet's routing and its DNS. After reading, you can give each block's exact bounds and size, apply RFC 1918's rules for border routers and DNS, explain why merging two private networks forces renumbering, tell a reverse lookup answered locally from one that leaked to the AS112 sink, and check each point with ip, dig and Python.
- [Private, Reserved, and Public IP Ranges](https://ronutz.com/en/learn/private-vs-public-ip-ranges.md): IANA records every special-purpose IPv4 and IPv6 block, from loopback, link-local and private-use space to shared address space, documentation and the translation prefixes, and two columns of its registries, Destination and Globally Reachable, decide whether an address is a public destination. After reading, you can read those columns, classify an address only after turning its spelling into the number a client connects to, explain how a public destination can still lead inside through a second DNS lookup or a redirect, name the cloud metadata addresses, and test an SSRF filter.
- [Public DNS resolvers: what you are actually choosing](https://ronutz.com/en/learn/choosing-a-public-dns-resolver.md): A public resolver is a recursive resolver anyone may use, and switching to one hands the operator every name your device looks up. What separates 1.1.1.1, 8.8.8.8, 9.9.9.9 and 208.67.222.222 is policy, not speed: what is logged and for how long, which addresses filter and how a block answers, whether DNSSEC is validated, whether your subnet is passed to authoritative servers, and which encrypted transports are offered. After reading, you can read an operator's pages against the list RFC 8932 asks it to publish, choose by those criteria, and test each one with dig and curl.
- [Python as a network engineer's calculator: the standard library already knows your arithmetic](https://ronutz.com/en/learn/python-as-a-network-engineers-calculator.md): Subnet splits, route aggregation, wildcard masks, EUI-64, a DNS header in bytes, an HMAC, a p95 of latency samples, a transfer time at line rate: each is a few lines of Python with nothing installed, because ipaddress, struct, hmac, statistics and re ship with the interpreter. This article walks the twelve examples the Python playground opens with, says which module does the work in each and why it is the right one, points at the pitfalls (hosts() on a /31, round-half-even, the universal/local bit), and shows where the same answers come from by hand on this site's other tools, so you can check one against the other.
- [Route summarization](https://ronutz.com/en/learn/route-summarization.md): Route summarisation advertises one prefix across a routing boundary in place of the many it covers, so the routers beyond it hold one entry and never see the components come and go. After reading, you can work out an exact summary in binary, configure and check OSPF area ranges, external summaries, EIGRP interface summaries and static summaries, explain the discard route that keeps a summary from looping, and recognise how a summary hides failures and bends paths.
- [Routing Tables and the Default Gateway: How a Packet Picks Its Next Hop](https://ronutz.com/en/learn/routing-tables-and-default-gateway.md): A routing table answers the one question every host and router asks of a packet: where does it go next. The host decides local or remote by its mask and hands the rest to a default gateway; the router prunes its table to one entry by basic match and longest match, with the default route of prefix length zero as the entry of last resort. After reading, you can run the longest-match decision by hand, read a Linux or Windows table line by line, say how a host learned its default (by hand, by DHCP, by Router Discovery or by an IPv6 Router Advertisement) and recognise a missing, dead or rogue default from its symptoms.
- [Running IPv6 and IPv4 together: dual-stack and translation](https://ronutz.com/en/learn/ipv6-transition.md): IPv4 and IPv6 cannot exchange packets, so networks run both side by side, carry IPv6 inside IPv4, or translate one protocol into the other. After reading, you can predict which family a dual-stack host tries first, build 6to4, Teredo, 6rd and NAT64 addresses by hand, follow a NAT64 and DNS64 session step by step, explain why 464XLAT translates rather than tunnels, and recognise the failures these mechanisms cause with IPv4 literals, signed DNS answers and packet sizes.
- [Sizing BFD timers: the arithmetic of detection](https://ronutz.com/en/learn/bfd-timers-the-arithmetic-of-detection.md): Bidirectional Forwarding Detection (BFD) never sends its detection time: each receiver computes it from the other side's multiplier and the interval the two sides agree, separately in each direction. After reading, you can work backwards from a detection target to intervals and a multiplier, predict both directions of a session from its six configured numbers, and recognise the slow start, jitter, hardware and Echo effects that stretch the result.
- [Subnet overlaps and gaps](https://ronutz.com/en/learn/subnet-overlap-and-gaps.md): Two IPv4 prefixes overlap when some address belongs to both, and with classless prefixes that can only mean one lies wholly inside the other, by design or by mistake; gaps are the addresses inside a parent block that no prefix covers. After reading, you can prove the nest-or-disjoint rule in binary, tell a deliberate more-specific route from a fault, list the gaps of an allocation as aligned blocks that account for every address, and explain why tunnels and cloud peering refuse overlapping ranges and how translation works around them.
- [Supernetting and route aggregation](https://ronutz.com/en/learn/supernetting-and-aggregation.md): Supernetting shortens a prefix so that one route covers several aligned IPv4 blocks, and route aggregation announces that route in place of the longer ones. After reading, you can test in binary whether blocks merge, tell an exact aggregate from a covering supernet and say when the covering one is legitimate, read how BGP marks an aggregate and why AS_SET was deprecated in May 2025, recognise how aggregation fails, and check it with the CIDR calculator, Python, FRRouting, Junos and Cisco.
- [The DNS Header: Opcode, Status, and Flags](https://ronutz.com/en/learn/dns-message-header-and-flags.md): Every DNS message opens with the same 12-byte header: a 16-bit ID, a flags word that holds the opcode, seven named flags, a reserved bit and the response code, and four section counts, which dig prints as its header and flags lines. After reading, you can decode a header from its hexadecimal bytes, say what each flag, opcode and status tells a diagnosis, recognise a truncated answer and test the TCP retry it needs, and explain why the ID and the source port must be unpredictable.
- [Understanding IPv6 Addressing](https://ronutz.com/en/learn/ipv6-addressing.md): An IPv6 address is a 128-bit identifier of an interface, written in hexadecimal with one canonical spelling, split into a prefix and an interface identifier, and typed by its first bits. After reading, you can write any address canonically, tell its type and scope, give a link-local address its zone, recover the hardware address inside an identifier derived from it, and name the reverse DNS record that maps an address to a host.
- [VLSM: splitting a block into unequal subnets](https://ronutz.com/en/learn/vlsm.md): Variable-length subnet masks let the subnets carved from one parent block have different prefix lengths, each sized to the hosts it must hold, instead of one mask for the whole network. After reading, you can size each subnet from its host count, place the blocks largest first so that none skips ahead, say which routing protocols can carry the plan and why longest match keeps mixed masks safe, account for the free space as aligned blocks, and check the allocation in the CIDR calculator's VLSM mode.
