Topic Overview
Subnetting & CIDR
Master subnetting and CIDR notation for efficient IP address allocation, network segmentation, and network design.
Subnetting divides a network into smaller subnetworks, enabling efficient IP address allocation, improved security through network segmentation, and better network management. CIDR (Classless Inter-Domain Routing) provides a flexible way to represent subnet masks.
What is Subnetting?
Subnetting is the process of dividing a network into smaller logical networks called subnets. Each subnet has its own network address, broadcast address, and range of usable host addresses.
Benefits:
- Efficient IP usage: Allocate only needed addresses
- Network segmentation: Isolate traffic, improve security
- Reduced broadcast domains: Smaller broadcast domains improve performance
- Better organization: Logical grouping of devices
CIDR Notation
CIDR (Classless Inter-Domain Routing) uses slash notation to specify the network prefix:
192.168.1.0/24
- 192.168.1.0: Network address
- /24: Prefix length (24 bits for network, 8 bits for hosts)
- Subnet mask: 255.255.255.0
CIDR to Subnet Mask Conversion
| CIDR | Subnet Mask | Host Bits | Usable Hosts |
|---|---|---|---|
| /24 | 255.255.255.0 | 8 | 254 |
| /25 | 255.255.255.128 | 7 | 126 |
| /26 | 255.255.255.192 | 6 | 62 |
| /27 | 255.255.255.224 | 5 | 30 |
| /28 | 255.255.255.240 | 4 | 14 |
| /30 | 255.255.255.252 | 2 | 2 (point-to-point) |
Subnetting Process
Step 1: Determine Requirements
- Number of subnets needed
- Number of hosts per subnet
- Future growth requirements
Step 2: Calculate Subnet Mask
- Determine number of subnet bits needed
- Calculate new prefix length
- Verify host count meets requirements
Step 3: Calculate Subnet Addresses
- Network address (all host bits = 0)
- Broadcast address (all host bits = 1)
- Usable host range
Examples
Example 1: Subnet 192.168.1.0/24 into 4 Subnets
Original Network: 192.168.1.0/24
- Network bits: 24
- Host bits: 8
- Total addresses: 256
- Usable hosts: 254
Requirement: 4 subnets
- Need 2 additional bits (2^2 = 4 subnets)
- New prefix: /26 (24 + 2)
- Hosts per subnet: 2^(32-26) - 2 = 64 - 2 = 62
Subnets:
| Subnet | Network | Broadcast | Usable Range | Hosts |
|---|---|---|---|---|
| 1 | 192.168.1.0/26 | 192.168.1.63 | 192.168.1.1 - 192.168.1.62 | 62 |
| 2 | 192.168.1.64/26 | 192.168.1.127 | 192.168.1.65 - 192.168.1.126 | 62 |
| 3 | 192.168.1.128/26 | 192.168.1.191 | 192.168.1.129 - 192.168.1.190 | 62 |
| 4 | 192.168.1.192/26 | 192.168.1.255 | 192.168.1.193 - 192.168.1.254 | 62 |
Calculation:
Subnet size = 256 / 4 = 64 addresses per subnet
Subnet 1: 192.168.1.0 - 192.168.1.63
Subnet 2: 192.168.1.64 - 192.168.1.127
Subnet 3: 192.168.1.128 - 192.168.1.191
Subnet 4: 192.168.1.192 - 192.168.1.255
Example 2: Variable Length Subnetting (VLSM)
Network: 10.0.0.0/16 Requirements:
- Subnet A: 1000 hosts → /22 (1022 hosts)
- Subnet B: 500 hosts → /23 (510 hosts)
- Subnet C: 250 hosts → /24 (254 hosts)
- Subnet D: 100 hosts → /25 (126 hosts)
Allocation:
10.0.0.0/16
├── 10.0.0.0/22 (Subnet A: 1000 hosts)
│ └── 10.0.0.0 - 10.0.3.255
├── 10.0.4.0/23 (Subnet B: 500 hosts)
│ └── 10.0.4.0 - 10.0.5.255
├── 10.0.6.0/24 (Subnet C: 250 hosts)
│ └── 10.0.6.0 - 10.0.6.255
└── 10.0.7.0/25 (Subnet D: 100 hosts)
└── 10.0.7.0 - 10.0.7.127
Subnetting Calculator (Python)
import ipaddress
def calculate_subnet(base_network, num_subnets):
"""Calculate subnets from base network"""
network = ipaddress.IPv4Network(base_network, strict=False)
# Calculate prefix length for num_subnets
subnet_bits = (num_subnets - 1).bit_length()
new_prefix = network.prefixlen + subnet_bits
subnets = list(network.subnets(new_prefix=new_prefix))
results = []
for i, subnet in enumerate(subnets[:num_subnets], 1):
results.append({
'subnet': i,
'network': str(subnet.network_address),
'broadcast': str(subnet.broadcast_address),
'netmask': str(subnet.netmask),
'cidr': f"{subnet.network_address}/{subnet.prefixlen}",
'hosts': subnet.num_addresses - 2,
'first_host': str(subnet.network_address + 1),
'last_host': str(subnet.broadcast_address - 1)
})
return results
# Usage
subnets = calculate_subnet("192.168.1.0/24", 4)
for s in subnets:
print(f"Subnet {s['subnet']}: {s['cidr']}")
print(f" Network: {s['network']}")
print(f" Broadcast: {s['broadcast']}")
print(f" Hosts: {s['hosts']}")
print(f" Range: {s['first_host']} - {s['last_host']}")
print()
Determine if IP is in Subnet
def is_ip_in_subnet(ip, subnet_cidr):
"""Check if IP address belongs to subnet"""
ip_obj = ipaddress.IPv4Address(ip)
network = ipaddress.IPv4Network(subnet_cidr, strict=False)
return ip_obj in network
# Usage
print(is_ip_in_subnet("192.168.1.100", "192.168.1.0/24")) # True
print(is_ip_in_subnet("192.168.2.100", "192.168.1.0/24")) # False
Common Pitfalls
- Forgetting network and broadcast addresses: Usable hosts = 2^n - 2, not 2^n. Fix: Always subtract 2
- Incorrect subnet mask calculation: Wrong binary math. Fix: Use subnet calculators or verify with tools
- Overlapping subnets: Subnets that overlap cause routing issues. Fix: Plan subnets carefully, verify no overlap
- Not accounting for growth: Subnets too small for future needs. Fix: Plan for 20-30% growth
- Wasting IP addresses: Using /24 when /26 would suffice. Fix: Use VLSM for efficient allocation
- Confusing network bits and host bits: /24 means 24 network bits, not 24 host bits. Fix: Remember CIDR = network prefix length
- Not reserving addresses: Forgetting to reserve IPs for routers, gateways. Fix: Reserve first few IPs in each subnet
Interview Questions
Beginner
Q: What is subnetting and why is it used?
A:
Subnetting is dividing a network into smaller logical networks (subnets). Each subnet has its own network address, broadcast address, and range of usable host addresses.
Why used:
- Efficient IP allocation: Allocate only needed addresses, reduce waste
- Network segmentation: Isolate traffic, improve security
- Reduce broadcast domains: Smaller broadcast domains improve performance
- Better organization: Logical grouping of devices (departments, floors)
- Security: Isolate sensitive networks, control traffic flow
Example:
Original: 192.168.1.0/24 (254 hosts)
Subnetted: 4 subnets of /26 (62 hosts each)
- Sales: 192.168.1.0/26
- Engineering: 192.168.1.64/26
- Marketing: 192.168.1.128/26
- Admin: 192.168.1.192/26
Benefits:
- Better security (isolate departments)
- Reduced broadcast traffic
- Easier management
- Efficient IP usage
Intermediate
Q: Given the network 172.16.0.0/16, create 8 subnets. What are the network addresses, subnet masks, and usable host ranges?
A:
Original Network: 172.16.0.0/16
- Network bits: 16
- Host bits: 16
- Total addresses: 65,536
- Usable hosts: 65,534
Requirement: 8 subnets
- Need 3 additional bits (2^3 = 8 subnets)
- New prefix: /19 (16 + 3)
- Hosts per subnet: 2^(32-19) - 2 = 8,192 - 2 = 8,190
Calculation:
Subnet size = 65,536 / 8 = 8,192 addresses per subnet
Increment = 8,192
Subnets:
| Subnet | Network | Subnet Mask | Broadcast | Usable Range | Hosts |
|---|---|---|---|---|---|
| 1 | 172.16.0.0/19 | 255.255.224.0 | 172.16.31.255 | 172.16.0.1 - 172.16.31.254 | 8,190 |
| 2 | 172.16.32.0/19 | 255.255.224.0 | 172.16.63.255 | 172.16.32.1 - 172.16.63.254 | 8,190 |
| 3 | 172.16.64.0/19 | 255.255.224.0 | 172.16.95.255 | 172.16.64.1 - 172.16.95.254 | 8,190 |
| 4 | 172.16.96.0/19 | 255.255.224.0 | 172.16.127.255 | 172.16.96.1 - 172.16.127.254 | 8,190 |
| 5 | 172.16.128.0/19 | 255.255.224.0 | 172.16.159.255 | 172.16.128.1 - 172.16.159.254 | 8,190 |
| 6 | 172.16.160.0/19 | 255.255.224.0 | 172.16.191.255 | 172.16.160.1 - 172.16.191.254 | 8,190 |
| 7 | 172.16.192.0/19 | 255.255.224.0 | 172.16.223.255 | 172.16.192.1 - 172.16.223.254 | 8,190 |
| 8 | 172.16.224.0/19 | 255.255.224.0 | 172.16.255.255 | 172.16.224.1 - 172.16.255.254 | 8,190 |
Verification:
- All subnets are /19 (consistent)
- No overlapping addresses
- Total addresses: 8 × 8,192 = 65,536 ✓
- Usable hosts: 8 × 8,190 = 65,520
Senior
Q: Design a subnetting scheme for a cloud provider that needs to allocate subnets to customers dynamically. How do you handle variable subnet sizes, prevent IP exhaustion, and ensure efficient allocation?
A:
class DynamicSubnetAllocator {
private ipPool: IPPool;
private allocations: Map<string, Allocation>;
private subnetTree: SubnetTree; // Binary tree for efficient search
constructor() {
// Large IP pool (e.g., 10.0.0.0/8)
this.ipPool = new IPPool("10.0.0.0/8");
this.subnetTree = new SubnetTree();
}
// 1. Variable Length Subnet Allocation (VLSM)
async allocateSubnet(customerId: string, size: number): Promise<Allocation> {
// Calculate required CIDR
const requiredCIDR = this.calculateCIDR(size);
// Find smallest available subnet that fits
const subnet = await this.findSmallestFit(requiredCIDR);
if (!subnet) {
// Try to split larger subnet
const largerSubnet = await this.findLargerSubnet(requiredCIDR);
if (largerSubnet) {
return await this.splitAndAllocate(largerSubnet, requiredCIDR, customerId);
}
throw new Error("IP pool exhausted");
}
// Allocate and track
const allocation = {
customerId,
subnet,
allocatedAt: Date.now(),
status: 'active'
};
this.allocations.set(customerId, allocation);
this.subnetTree.markAllocated(subnet);
return allocation;
}
// 2. Calculate Required CIDR
calculateCIDR(hosts: number): number {
// Add 2 for network and broadcast
// Add 10% buffer for growth
const required = Math.ceil(hosts * 1.1) + 2;
const bits = Math.ceil(Math.log2(required));
return 32 - bits;
}
// 3. Find Smallest Fit (Efficient Search)
async findSmallestFit(requiredCIDR: number): Promise<Subnet | null> {
// Use binary tree for O(log n) search
return await this.subnetTree.findSmallestAvailable(requiredCIDR);
}
// 4. Subnet Splitting
async splitAndAllocate(
parentSubnet: Subnet,
requiredCIDR: number,
customerId: string
): Promise<Allocation> {
// Split parent subnet
const subnets = this.splitSubnet(parentSubnet);
// Allocate first subnet to customer
const allocated = subnets[0];
this.subnetTree.markAllocated(allocated);
// Add remaining subnets back to pool
for (let i = 1; i < subnets.length; i++) {
this.subnetTree.addAvailable(subnets[i]);
}
return {
customerId,
subnet: allocated,
allocatedAt: Date.now()
};
}
// 5. Subnet Reclamation
async deallocateSubnet(customerId: string): Promise<void> {
const allocation = this.allocations.get(customerId);
if (!allocation) return;
// Mark as available
this.subnetTree.markAvailable(allocation.subnet);
// Try to merge with adjacent subnets
await this.mergeAdjacentSubnets(allocation.subnet);
this.allocations.delete(customerId);
}
// 6. Subnet Merging (Defragmentation)
async mergeAdjacentSubnets(subnet: Subnet): Promise<void> {
// Find adjacent subnets that can be merged
const parent = this.getParentSubnet(subnet);
const siblings = this.getSiblingSubnets(parent);
// If all siblings are available, merge
if (siblings.every(s => this.isAvailable(s))) {
this.subnetTree.removeAvailable(siblings);
this.subnetTree.addAvailable(parent);
}
}
// 7. IP Exhaustion Prevention
async checkPoolHealth(): Promise<HealthStatus> {
const stats = await this.subnetTree.getStats();
return {
totalAddresses: stats.total,
allocatedAddresses: stats.allocated,
availableAddresses: stats.available,
utilization: stats.allocated / stats.total,
fragmentation: this.calculateFragmentation()
};
}
// 8. Efficient Data Structure
class SubnetTree {
private root: SubnetNode;
findSmallestAvailable(requiredCIDR: number): Subnet | null {
// Traverse tree to find smallest available subnet
// that can accommodate requiredCIDR
return this.traverse(this.root, requiredCIDR);
}
markAllocated(subnet: Subnet): void {
// Mark node as allocated, update tree
this.updateNode(subnet, 'allocated');
}
markAvailable(subnet: Subnet): void {
// Mark node as available, update tree
this.updateNode(subnet, 'available');
}
}
}
Features:
- VLSM: Variable length subnetting for efficient allocation
- Smallest fit: Allocate smallest subnet that fits requirements
- Subnet splitting: Split larger subnets when needed
- Subnet merging: Merge adjacent subnets when deallocated (defragmentation)
- Efficient search: Binary tree for O(log n) subnet search
- Pool health: Monitor utilization, prevent exhaustion
- Growth buffer: Allocate 10% extra for future growth
Key Takeaways
- Subnetting: Divides network into smaller logical networks for efficient IP allocation
- CIDR notation: /n specifies network prefix length (e.g., /24 = 24 network bits)
- Subnet calculation: Number of subnets = 2^(subnet_bits - network_bits), hosts = 2^(32 - prefix) - 2
- Network and broadcast: Network address (all host bits 0), broadcast (all host bits 1) are not usable
- VLSM: Variable Length Subnet Masking for efficient allocation of different sized subnets
- Subnet planning: Account for growth, reserve IPs for routers/gateways, avoid overlapping
- Efficient allocation: Use smallest subnet that fits, merge when deallocated, monitor pool health
- Best practices: Plan carefully, verify no overlaps, use subnet calculators, document allocations