如何用Python/Pandas计算子网中已用/可用IP地址数量?
子网层级IP统计解决方案
核心思路:从最底层的叶子子网(无下级子网)开始统计已用IP,上层子网的已用IP等于其所有直接下级子网的已用IP之和,而非自身总IP。这种方式可适配任意层级的子网结构(n-3、n-4层级均适用)。
具体实现步骤
1. 计算每个子网的总IP数
每个子网的总IP数公式为 2^(32 - 前缀长度),比如1.1.1.0/20的前缀是20,总IP数为2^(32-20)=4096。用函数实现:
def calculate_total_ip(subnet): prefix = int(subnet.split('/')[1]) return 2 ** (32 - prefix)
2. 构建子网层级映射
用字典存储子网的父子关系,方便后续向上汇总:
import pandas as pd # 原始数据 data = [ ["1.1.1.0/20", "master", "/"], ["1.1.1.0/22", "subnet n-1, no further subnets", "1.1.1.0/20"], ["1.1.2.0/24", "subnet n-1, further subnets", "1.1.1.0/20"], ["1.1.3.0/29", "subnet n-2", "1.1.2.0/24"], ["1.1.3.1/29", "subnet n-2", "1.1.2.0/24"] ] df = pd.DataFrame(data, columns=["ip", "description", "master subnet"]) # 生成total列 df['total'] = df['ip'].apply(calculate_total_ip) # 构建子节点映射:key为主子网,value为直接子节点列表 subnet_children = {} for idx, row in df.iterrows(): master = row['master subnet'] subnet_children.setdefault(master, []).append(row['ip']) # 构建子网-主子网的反向映射 subnet_parent = df.set_index('ip')['master subnet'].to_dict()
3. 递归计算已用IP数
从叶子节点开始递归:叶子节点的used等于自身total;非叶子节点的used累加所有直接子节点的used值。
# 存储每个子网的已用IP数 used_dict = {} def calculate_used(subnet): if subnet in used_dict: return used_dict[subnet] # 叶子节点(无下级子网):已用IP=总IP if subnet not in subnet_children or len(subnet_children[subnet]) == 0: used = df.loc[df['ip'] == subnet, 'total'].values[0] used_dict[subnet] = used return used # 非叶子节点:累加所有子节点的已用IP total_used = 0 for child in subnet_children[subnet]: total_used += calculate_used(child) used_dict[subnet] = total_used return total_used # 遍历所有子网计算已用IP for subnet in df['ip']: calculate_used(subnet) # 填充used和free列 df['used'] = df['ip'].map(used_dict) df['free'] = df['total'] - df['used']
4. 输出结果
执行后得到的df与预期结果完全一致:
| ip | description | master subnet | total | used | free |
|---|---|---|---|---|---|
| 1.1.1.0/20 | master | / | 4096 | 1040 | 3056 |
| 1.1.1.0/22 | subnet n-1, no further subnets | 1.1.1.0/20 | 1024 | 1024 | 0 |
| 1.1.2.0/24 | subnet n-1, further subnets | 1.1.1.0/20 | 256 | 16 | 240 |
| 1.1.3.0/29 | subnet n-2 | 1.1.2.0/24 | 8 | 8 | 0 |
| 1.1.3.1/29 | subnet n-2 | 1.1.2.0/24 | 8 | 8 | 0 |
内容的提问来源于stack exchange,提问作者spsstataR-guy
相关产品推荐
相关产品推荐

