Create ip address, ipvr address calculations, and sbnetting tables for quick references in pdf please
# This script generates a multi-page PDF quick reference for IPv4 & IPv6 addressing and subnetting.
# It saves the file to /mnt/data and returns a download link at the end of the assistant message.
import math
from decimal import Decimal, getcontext
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Increase precision for huge IPv6 numbers
getcontext().prec = 50
out_path = “/mnt/data/CCNA_Addressing_Subnetting_Quick_Ref.pdf”
# ———- Helpers ———-
def prefix_to_mask(prefix: int) -> str:
“””Return dotted-decimal subnet mask for an IPv4 prefix length.”””
mask_int = (0xffffffff <> (24 – 8*i)) & 0xff) for i in range(4))
def invert_mask(mask: str) -> str:
parts = list(map(int, mask.split(“.”)))
inv = [255 – p for p in parts]
return “.”.join(map(str, inv))
def block_size(prefix: int) -> str:
# If prefix aligns to octet, block size is N/A for a single octet,
# but we can return “-” to avoid confusion.
rem = prefix % 8
if rem == 0 or prefix == 32:
return “-”
return str(2 ** (8 – rem))
def format_int(n: int) -> str:
return f”{n:,}”
def usable_hosts(prefix: int) -> str:
if prefix == 31 or prefix == 32:
return “0*”
host_bits = 32 – prefix
if host_bits str:
return format_int(2 ** (32 – prefix))
def pow2_str(exp: int) -> str:
# Return a string like 2^n (≈ x.yEz)
approx = Decimal(2) ** Decimal(exp)
# Format with scientific notation up to 3 sig figs
s = f”{approx:.3E}”
return f”2^{exp} (≈ {s})”
def draw_table(df: pd.DataFrame, title: str, footnote: str = None, col_widths=None, font_size=8, rotate_cols=None):
“””Render a pandas DataFrame as a table on a PDF page.”””
fig = plt.figure(figsize=(8.5, 11))
ax = fig.add_subplot(111)
ax.axis(“off”)
# Title
ax.text(0.5, 0.98, title, ha=”center”, va=”top”, fontsize=14, fontweight=”bold”, transform=ax.transAxes)
# Convert to strings to keep consistent formatting
df_display = df.copy().astype(str)
# Table
the_table = ax.table(cellText=df_display.values,
colLabels=df_display.columns.tolist(),
loc=”center”,
cellLoc=”center”)
the_table.auto_set_font_size(False)
the_table.set_fontsize(font_size)
# Column widths
if col_widths:
for i, w in enumerate(col_widths):
the_table.auto_set_column_width(col=i)
the_table.columns[i].set_width(w)
# Resize to fit page height
table_scale = 1.0
the_table.scale(1, table_scale)
# Footnote
if footnote:
ax.text(0.02, 0.02, footnote, ha=”left”, va=”bottom”, fontsize=8, transform=ax.transAxes)
plt.tight_layout(rect=[0.03, 0.05, 0.97, 0.95])
return fig
def draw_text_page(title: str, body_lines: list):
fig = plt.figure(figsize=(8.5,11))
ax = fig.add_subplot(111)
ax.axis(“off”)
ax.text(0.5, 0.98, title, ha=”center”, va=”top”, fontsize=14, fontweight=”bold”, transform=ax.transAxes)
# Draw body text as a left-aligned block
y = 0.93
line_spacing = 0.024
for line in body_lines:
if isinstance(line, str):
ax.text(0.03, y, line, ha=”left”, va=”top”, fontsize=10, family=”monospace”, transform=ax.transAxes)
y -= line_spacing
elif isinstance(line, list):
# add a blank line between paragraphs
y -= line_spacing
plt.tight_layout(rect=[0.03, 0.05, 0.97, 0.95])
return fig
# ———- Build Data ———-
# IPv4 prefix table
rows = []
for p in range(0, 33):
mask = prefix_to_mask(p)
rows.append({
“Prefix”: f”/{p}”,
“Subnet Mask”: mask,
“Wildcard”: invert_mask(mask),
“Total Addresses”: total_addrs_ipv4(p),
“Usable Hosts”: usable_hosts(p),
“Block Size”: block_size(p)
})
ipv4_table = pd.DataFrame(rows, columns=[“Prefix”,”Subnet Mask”,”Wildcard”,”Total Addresses”,”Usable Hosts”,”Block Size”])
# IPv4 well-known ranges
ipv4_ranges = pd.DataFrame([
{“CIDR / Range”: “10.0.0.0/8”, “Name/Purpose”: “Private”, “Notes”: “RFC 1918”},
{“CIDR / Range”: “172.16.0.0/12”, “Name/Purpose”: “Private”, “Notes”: “RFC 1918”},
{“CIDR / Range”: “192.168.0.0/16”, “Name/Purpose”: “Private”, “Notes”: “RFC 1918”},
{“CIDR / Range”: “100.64.0.0/10”, “Name/Purpose”: “CGNAT (Carrier Grade NAT)”, “Notes”: “RFC 6598”},
{“CIDR / Range”: “169.254.0.0/16”, “Name/Purpose”: “Link-Local (APIPA)”, “Notes”: “Auto-config when DHCP fails”},
{“CIDR / Range”: “127.0.0.0/8”, “Name/Purpose”: “Loopback”, “Notes”: “127.0.0.1 localhost”},
{“CIDR / Range”: “224.0.0.0/4”, “Name/Purpose”: “Multicast”, “Notes”: “224.0.0.0–239.255.255.255”},
{“CIDR / Range”: “240.0.0.0/4”, “Name/Purpose”: “Reserved/Experimental”, “Notes”: “Often not forwarded”},
{“CIDR / Range”: “192.0.2.0/24”, “Name/Purpose”: “Documentation (TEST-NET-1)”, “Notes”: “RFC 5737”},
{“CIDR / Range”: “198.51.100.0/24”, “Name/Purpose”: “Documentation (TEST-NET-2)”, “Notes”: “RFC 5737”},
{“CIDR / Range”: “203.0.113.0/24”, “Name/Purpose”: “Documentation (TEST-NET-3)”, “Notes”: “RFC 5737”},
{“CIDR / Range”: “198.18.0.0/15”, “Name/Purpose”: “Benchmarking”, “Notes”: “RFC 2544”},
{“CIDR / Range”: “255.255.255.255/32”, “Name/Purpose”: “Limited Broadcast”, “Notes”: “Local network only”},
], columns=[“CIDR / Range”,”Name/Purpose”,”Notes”])
# IPv4 Borrow Bits tables
def build_borrow_table(base_prefix: int, max_borrow: int) -> pd.DataFrame:
rows = []
for b in range(0, max_borrow+1):
p = base_prefix + b
host_bits = 32 – p
if host_bits 64 else f”2^{64-p} ({2**(64-p):,})”
addrs = pow2_str(128 – p)
common_ipv6.append({“Prefix”: f”/{p}”, “Typical Use”: use, “# of /64s”: n64s, “Addresses in Subnet”: addrs})
ipv6_common_df = pd.DataFrame(common_ipv6, columns=[“Prefix”,”Typical Use”,”# of /64s”,”Addresses in Subnet”])
# IPv6 nibble mapping table (prefix alignment every 4 bits)
nibble_rows = []
for p in range(0, 129, 4):
hex_chars = p // 4
nibble_rows.append({“Prefix”: f”/{p}”, “Completed Hex Digits”: hex_chars, “Remaining Bits”: 128 – p})
ipv6_nibbles = pd.DataFrame(nibble_rows, columns=[“Prefix”,”Completed Hex Digits”,”Remaining Bits”])
# ———- Build PDF ———-
with PdfPages(out_path) as pdf:
# Cover
fig = draw_text_page(
“IPv4 & IPv6 Addressing & Subnetting — Quick Reference (CCNA)”,
[
“Contents:”,
” • IPv4 Subnet Masks, Wildcards, Hosts, Block Sizes (/0–/32)”,
” • IPv4 Borrow-Bits tables for /8, /16, /24″,
” • Well-known IPv4 ranges (Private, CGNAT, APIPA, Loopback, Multicast, etc.)”,
” • IPv6 well-known ranges & common allocation sizes”,
” • IPv6 nibble alignment map (/0 to /128 in steps of 4)”,
” • Calculation quick steps & tips”,
“”,
“Notes:”,
” * In traditional IPv4 subnetting, /31 and /32 have 0 usable host addresses.”,
” Modern practice (RFC 3021) allows /31 on point-to-point links; /32 is a host route.”,
]
)
pdf.savefig(fig); plt.close(fig)
# IPv4 /0 – /32
fn = “* /31 allowed on P2P (RFC 3021). /32 is a single host route. Block Size shows increment in the interesting octet.”
fig = draw_table(ipv4_table, “IPv4 Subnet Reference Table (/0 – /32)”, footnote=fn,
col_widths=[0.08, 0.20, 0.18, 0.20, 0.18, 0.12], font_size=8)
pdf.savefig(fig); plt.close(fig)
# Borrow tables
fig = draw_table(borrow_24, “Borrow Bits from a /24 (Class C-sized block)”,
footnote=”Subnets = 2^borrowed; Hosts/Subnet = 2^(host bits) − 2 (except /31,/32).”)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(borrow_16, “Borrow Bits from a /16 (Class B-sized block)”,
footnote=”Great for planning campus subnets from a /16 allocation.”)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(borrow_08, “Borrow Bits from a /8 (Class A-sized block)”,
footnote=”Use cautiously—very large pools; summarize when advertising.”)
pdf.savefig(fig); plt.close(fig)
# IPv4 well-known ranges
fig = draw_table(ipv4_ranges, “Well-known IPv4 Ranges (Quick Reference)”)
pdf.savefig(fig); plt.close(fig)
# IPv6 well-known ranges
fig = draw_table(ipv6_ranges, “IPv6 Well-known Ranges (Quick Reference)”)
pdf.savefig(fig); plt.close(fig)
# IPv6 common allocation sizes
fig = draw_table(ipv6_common_df, “IPv6 Common Allocation Sizes”,
footnote=”Standard on-link subnet is /64. /127 recommended for P2P links (RFC 6164).”)
pdf.savefig(fig); plt.close(fig)
# IPv6 nibble map
fig = draw_table(ipv6_nibbles, “IPv6 Nibble Alignment Map (every 4 bits)”,
footnote=”Each hex digit = 4 bits. Summarization works cleanly on nibble boundaries (e.g., /32, /36, /40, …).”)
pdf.savefig(fig); plt.close(fig)
# Calculation steps
calc_lines = [
“IPv4 Quick Calculations”,
” • Hosts/Subnet = 2^(32 − prefix) − 2 (except /31 for P2P, /32 host route)”,
” • Total Addresses = 2^(32 − prefix)”,
” • Wildcard = 255.255.255.255 − Subnet Mask”,
” • Block Size (interesting octet) = 256 − mask_octet”,
” • Network/Broadcast:”,
” – Convert IP & mask to binary; network = IP & mask, broadcast = network | ~mask”,
” – Or use the block size: find the multiple of block size the final octet falls into for the network;”,
” next multiple − 1 is the broadcast (when subnetting within a single octet).”,
“”,
“IPv6 Quick Calculations”,
” • Addresses in Subnet = 2^(128 − prefix)”,
” • # of /64s inside a prefix p (p ≤ 64) = 2^(64 − p)”,
” • Summarization works cleanly at nibble boundaries (prefix lengths multiple of 4).”,
” • Shortening rules:”,
” – Leading zeros in a hextet may be omitted (e.g., 0db8 → db8).”,
” – A single run of consecutive 0-hextets may be replaced by ‘::’ once per address.”,
” • Common practice: assign /64 to each VLAN/LAN; use /127 for P2P links; /48 or /56 for sites.”,
“”,
“Handy Prefix Landmarks”,
” • IPv4: /8, /16, /24 align on octet boundaries; /30 gives 2 hosts, /29 gives 6, /28 gives 14, /27 gives 30, /26 gives 62, /25 gives 126.”,
” • IPv6: /32 (ISP), /48 (site), /56 (small site), /64 (LAN), /127 (P2P), /128 (host).”,
]
fig = draw_text_page(“Calculation Cheats & Tips”, calc_lines)
pdf.savefig(fig); plt.close(fig)
out_path
# Fix draw_table to avoid column width manipulation that isn’t supported in this environment
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
def draw_table(df, title: str, footnote: str = None, col_widths=None, font_size=8, rotate_cols=None):
fig = plt.figure(figsize=(8.5, 11))
ax = fig.add_subplot(111)
ax.axis(“off”)
ax.text(0.5, 0.98, title, ha=”center”, va=”top”, fontsize=14, fontweight=”bold”, transform=ax.transAxes)
df_display = df.copy().astype(str)
the_table = ax.table(cellText=df_display.values,
colLabels=df_display.columns.tolist(),
loc=”center”,
cellLoc=”center”)
the_table.auto_set_font_size(False)
the_table.set_fontsize(font_size)
the_table.scale(1, 1.2)
if footnote:
ax.text(0.02, 0.02, footnote, ha=”left”, va=”bottom”, fontsize=8, transform=ax.transAxes)
plt.tight_layout(rect=[0.03, 0.05, 0.97, 0.95])
return fig
# Re-generate the PDF using the existing dataframes from previous cell
with PdfPages(out_path) as pdf:
# Cover
fig = draw_text_page(
“IPv4 & IPv6 Addressing & Subnetting — Quick Reference (CCNA)”,
[
“Contents:”,
” • IPv4 Subnet Masks, Wildcards, Hosts, Block Sizes (/0–/32)”,
” • IPv4 Borrow-Bits tables for /8, /16, /24″,
” • Well-known IPv4 ranges (Private, CGNAT, APIPA, Loopback, Multicast, etc.)”,
” • IPv6 well-known ranges & common allocation sizes”,
” • IPv6 nibble alignment map (/0 to /128 in steps of 4)”,
” • Calculation quick steps & tips”,
“”,
“Notes:”,
” * In traditional IPv4 subnetting, /31 and /32 have 0 usable host addresses.”,
” Modern practice (RFC 3021) allows /31 on point-to-point links; /32 is a host route.”,
]
)
pdf.savefig(fig); plt.close(fig)
fn = “* /31 allowed on P2P (RFC 3021). /32 is a single host route. Block Size shows increment in the interesting octet.”
fig = draw_table(ipv4_table, “IPv4 Subnet Reference Table (/0 – /32)”, footnote=fn, font_size=8)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(borrow_24, “Borrow Bits from a /24 (Class C-sized block)”,
footnote=”Subnets = 2^borrowed; Hosts/Subnet = 2^(host bits) − 2 (except /31,/32).”)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(borrow_16, “Borrow Bits from a /16 (Class B-sized block)”,
footnote=”Great for planning campus subnets from a /16 allocation.”)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(borrow_08, “Borrow Bits from a /8 (Class A-sized block)”,
footnote=”Use cautiously—very large pools; summarize when advertising.”)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(ipv4_ranges, “Well-known IPv4 Ranges (Quick Reference)”)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(ipv6_ranges, “IPv6 Well-known Ranges (Quick Reference)”)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(ipv6_common_df, “IPv6 Common Allocation Sizes”,
footnote=”Standard on-link subnet is /64. /127 recommended for P2P links (RFC 6164).”)
pdf.savefig(fig); plt.close(fig)
fig = draw_table(ipv6_nibbles, “IPv6 Nibble Alignment Map (every 4 bits)”,
footnote=”Each hex digit = 4 bits. Summarization works cleanly on nibble boundaries (e.g., /32, /36, /40, …).”)
pdf.savefig(fig); plt.close(fig)
calc_lines = [
“IPv4 Quick Calculations”,
” • Hosts/Subnet = 2^(32 − prefix) − 2 (except /31 for P2P, /32 host route)”,
” • Total Addresses = 2^(32 − prefix)”,
” • Wildcard = 255.255.255.255 − Subnet Mask”,
” • Block Size (interesting octet) = 256 − mask_octet”,
” • Network/Broadcast:”,
” – Convert IP & mask to binary; network = IP & mask, broadcast = network | ~mask”,
” – Or use the block size: find the multiple of block size the final octet falls into for the network;”,
” next multiple − 1 is the broadcast (when subnetting within a single octet).”,
“”,
“IPv6 Quick Calculations”,
” • Addresses in Subnet = 2^(128 − prefix)”,
” • # of /64s inside a prefix p (p ≤ 64) = 2^(64 − p)”,
” • Summarization works cleanly at nibble boundaries (prefix lengths multiple of 4).”,
” • Shortening rules:”,
” – Leading zeros in a hextet may be omitted (e.g., 0db8 → db8).”,
” – A single run of consecutive 0-hextets may be replaced by ‘::’ once per address.”,
” • Common practice: assign /64 to each VLAN/LAN; use /127 for P2P links; /48 or /56 for sites.”,
“”,
“Handy Prefix Landmarks”,
” • IPv4: /8, /16, /24 align on octet boundaries; /30 gives 2 hosts, /29 gives 6, /28 gives 14, /27 gives 30, /26 gives 62, /25 gives 126.”,
” • IPv6: /32 (ISP), /48 (site), /56 (small site), /64 (LAN), /127 (P2P), /128 (host).”,
]
fig = draw_text_page(“Calculation Cheats & Tips”, calc_lines)
pdf.savefig(fig); plt.close(fig)
out_path
Made you a clean CCNA quick-ref PDF with IPv4/IPv6 addressing + subnetting tables. It includes:
– IPv4 /0–/32 table: masks, wildcards, total addresses, usable hosts, block size
– Borrow-bits tables for /8, /16, /24
– Well-known IPv4 ranges (private, CGNAT, APIPA, loopback, multicast, docs, etc.)
– IPv6 well-known ranges + common allocations (/32, /48, /56, /64, /127, /128)
– IPv6 nibble-alignment map (every 4 bits)
– Calculation cheats & tips page
Download: [CCNA_Addressing_Subnetting_Quick_Ref.pdf](sandbox:/mnt/data/CCNA_Addressing_Subnetting_Quick_Ref.pdf)
Want me to add VLSM worked examples or an extra page for wildcard math (ACLs)?
quiz me on the previous topics starting easy to ccna
Nice—let’s level you up from warm-up to CCNA-style. Answer inline (e.g., “1:C, 2:192.168.1.0, …”). I’ll grade whatever you send back.
# Level 1 — Warm-up (basics)
1) T/F: IPv4 private ranges include 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.
2) Which IPv4 address is APIPA/link-local?
A) 169.254.10.5 B) 127.0.0.5 C) 224.0.0.5 D) 100.64.1.5
3) How many bits long is an IPv4 address?
4) Which type does **not** exist in IPv6?
A) Unicast B) Multicast C) Broadcast D) Anycast
5) Write the subnet mask for /26 in dotted decimal.
6) How many **usable** hosts in a /27?
7) What is the wildcard mask for /24?
8) Which prefix is IPv6 documentation?
A) 64:ff9b::/96 B) 2001:db8::/32 C) fc00::/7 D) fe80::/10
9) Expand fully: `2001:db8::1` (no shortening).
10) Shorten properly: `fe80:0000:0000:0000:021a:2bff:fe3c:4d5e`.
# Level 2 — Core subnetting
11) Given `192.168.5.139/26`:
a) Network address = ?
b) Broadcast address = ?
c) First/last usable = ?
12) How many /28 subnets can you carve from a /24? How many usable hosts per /28?
13) You need ~50 hosts per LAN. Which single prefix length fits best?
14) What’s the **increment** (“block size”) in the interesting octet for mask 255.255.255.224?
15) Convert /20 to dotted mask and total addresses.
16) Which IPv4 range is CGNAT?
A) 192.0.2.0/24 B) 198.51.100.0/24 C) 100.64.0.0/10 D) 198.18.0.0/15
17) For ACLs: permit the whole `10.10.32.0/20`. Give the network and wildcard mask.
18) An ARP entry shows `192.168.1.255 -> ff-ff-ff-ff-ff-ff`. What is that address?
19) You have `172.16.16.0/22`. What is the next subnet after it (same size)?
20) Summarize `10.10.16.0/24` through `10.10.31.0/24` into one route.
# Level 3 — IPv6 essentials
21) How many addresses are in an IPv6 /64 (use power of two form)?
22) How many /64s exist inside a /56?
23) Name the IPv6 scope/purpose for each:
a) `fe80::/10` b) `fc00::/7` c) `ff00::/8`
24) Best practice prefix lengths: LANs? P2P links? Typical site allocation? (give /L values)
25) Which is the NAT64 well-known prefix?
A) 64:ff9b::/96 B) ::ffff:0:0/96 C) 2002::/16 D) 2000::/3
26) EUI-64: Derive the interface ID from MAC `3c-5a-b4-ef-92-1f`. (show first hextet at least)
27) In EUI-64, which bit is flipped and why?
# Level 4 — CCNA-style scenarios
28) A host `192.0.2.25/27` sends to `192.0.2.40`. Same VLAN. Which L2 dest MAC is used in the frame?
A) Default gateway MAC B) Dest host MAC C) Broadcast D) Multicast
29) You must create 6 subnets, each supporting ≥90 hosts, from `192.168.20.0/24`.
a) What prefix will you use?
b) List the first two subnet ranges.
30) Your router P2P links use /31. What RFC allows that and why does it work?
31) Summarize these IPv6 routes if possible:
`2001:db8:1000::/36, 2001:db8:2000::/36, 2001:db8:3000::/36, 2001:db8:4000::/36`.
32) ACL wildcard quickie: To match exactly `192.168.10.64/27`, what wildcard mask?
33) Given `10.0.0.0/8`, you need at least 300 subnets, each ≥400 hosts.
a) Smallest per-subnet prefix?
b) How many such subnets fit? (show 2^x form or number)
34) IPv6: Pick the correct statements (two):
A) IPv6 uses hex B) IPv6 is 32 bits C) IPv6 is 128 bits D) IPv6 uses broadcast
35) A router receives a packet to `203.0.113.77`. Which statement is true?
A) It’s a CGNAT address and should not be routed on the Internet
B) It’s a documentation block; shouldn’t appear on the public Internet
C) It’s APIPA; stays on-link
D) It’s loopback; drop it
—
If you want, I can score your answers and explain any misses with the fastest test-day shortcuts (block sizes, nibble math, and EUI-64 bit-flip tricks).