PIXELBANKv9.1.0
Menu

Problem Statement

Before a VPC exists you have to size its subnets, and a /24 that "looks big enough" is how a training cluster runs out of addresses mid-scale-up. Given a CIDR block, derive its network address, broadcast address, netmask and usable host count, and say which of a list of IPs fall inside it.

Background

An IPv4 address is 32 bits. A CIDR block A.B.C.D/p fixes the leading p bits (the network part) and leaves 32 - p host bits free. The netmask is p ones followed by 32 - p zeros.

  • Network address: the address with all host bits 0 — ip & mask. Note the address you are given need not be the network address: 10.0.5.37/22 still describes the block 10.0.4.0/22.
  • Broadcast address: all host bits 1.
  • Membership: ip is inside the block exactly when ip & mask == network.
  • Usable hosts: 2 ** (32 - p) - 2 for p <= 30, since the network and broadcast addresses are not assignable. Two special cases: a /31 has 2 usable addresses (RFC 3021 point-to-point links) and a /32 has 1. Blindly subtracting 2 gives 0 and -1 there.

Solve this with integer bit arithmetic — do not use the ipaddress module.

Your Task

Implement:

def subnet_report(cidr, ips):

Return a dict with keys, in this order: "network", "broadcast", "netmask" (all dotted-quad strings), "usable_hosts" (int), and "in_subnet" (list of bools, one per entry of ips, in order).

Input Format

  • cidr: string like "10.0.5.37/22".
  • ips: list of dotted-quad strings to test.

Output Format

  • The dict described above.

Sample

print(subnet_report("10.0.5.37/22", ["10.0.4.9", "10.0.8.1", "10.0.7.255"]))

Output:

{'network': '10.0.4.0', 'broadcast': '10.0.7.255', 'netmask': '255.255.252.0', 'usable_hosts': 1022, 'in_subnet': [True, False, True]}

A /22 borrows 2 bits from the third octet, so the block spans 10.0.4.0-10.0.7.255: 1024 addresses, 1022 assignable.

Example:

Input:
print(subnet_report("10.0.5.37/22", ["10.0.4.9", "10.0.8.1", "10.0.7.255"]))
Output:
{'network': '10.0.4.0', 'broadcast': '10.0.7.255', 'netmask': '255.255.252.0', 'usable_hosts': 1022, 'in_subnet': [True, False, True]}
Reasoning:

A /22 mask is 255.255.252.0. ANDing 10.0.5.37 with it clears the low 10 host bits and gives the network 10.0.4.0; setting all host bits gives the broadcast 10.0.7.255. The block holds 2**10 = 1024 addresses, minus network and broadcast, so 1022 are assignable. 10.0.8.1 masks to 10.0.8.0, a different network, so it is outside; the broadcast address itself is still inside the block.

Constraints:

  • cidr is a valid IPv4 block, prefix length 0 to 32
  • The given address may have host bits set; normalise it to the network address
  • Usable hosts: 2 ** (32 - p) - 2 for p <= 30, 2 for a /31, 1 for a /32
  • 0 <= len(ips) <= 100
  • Use integer bit arithmetic, not the ipaddress module
solution.py

Test Results

0/0
Run code to see test results.