首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >#WorkBuddy# 实战:我把融合IP网络的 IP 规划从 8 小时手工填表,压到了 3 分钟

#WorkBuddy# 实战:我把融合IP网络的 IP 规划从 8 小时手工填表,压到了 3 分钟

原创
作者头像
Zack_C
发布于 2026-09-13 22:15:56
发布于 2026-09-13 22:15:56
1190
举报

作者从事煤矿信息化工作,常年和井下环网、切片网络、设备割接打交道。本文记录如何用 WorkBuddy 从零搭一个「切片网络 IP 规划工具」,把 Excel 模板里的 IPv4/IPv6 Loopback、设备互联地址、SRv6 Locator 自动生成并回填。

一、先说痛点:最贵的不是设备,是填表

一次典型的切片网络(SPN / 切片分组网)项目交付,网络规划阶段要交出一整套《切片网络规划模板.xlsx》。其中地址规划部分大概长这样:

表号

内容

手工做法

表 2.3

站点设备清单

人工录入,基线数据

表 2.4

IPv4 地址规划

每台设备一个 /32 Loopback,手敲

表 2.5

IPv6 地址规划

每台设备一个 /128 Loopback,手敲

表 2.6

设备互联地址

按 /30 分段,首尾可用地址分给两端

表 2.7

SRv6 Locator 规划

每个节点一段 /64,还要算 End SID

一个中等规模的矿井,核心 + 汇聚 + 接入设备 30~80 台,链路几十条。手工做的真实情况是:

  1. 敲到手麻还容易重号。/30 互联地址每段只有两个可用地址,多填一个就串段,串段在割接当天才会暴露。
  2. 改一处要全表重排。中间插一台设备,后面所有 Loopback 和互联地址全部顺延,等于重做一遍。
  3. SRv6 Locator 手算容易错。Locator 是 /48 前缀 + 16bit 节点号拼成 /64,人工换算 hex 极易出错,而它一旦错,整网的 SRv6 Policy 都通不了。
  4. 没有校验。Excel 不会告诉你哪个地址重复、哪条链路越界。

所以这个项目最值得自动化的,恰恰是看起来最"没技术含量"的填表。

二、设计思路:表 2.3 是唯一输入

我把整个工具的输入收敛成一句话:只认表 2.3,其余全推导。

代码语言:bash
复制
表2.3 站点设备清单(站点/设备名称/设备角色/接入环/区域)
        │
        ├─→ 拓扑推导:环内互联 → 汇聚上联核心 → 核心间全互联
        │
        ├─→ 地址分配:Loopback v4 / Loopback v6 / 互联 /30 / SRv6 Locator
        │
        ├─→ 冲突校验:重复检测 + 越界检测 + 地址池容量检测
        │
        └─→ 回填输出:2.4 / 2.5 / 2.6 / 2.7 + 校验报告

这么设计的好处是:站前设计一变,改表 2.3 再跑一次脚本就行,不用碰任何公式。

地址分配规则(可调)

代码语言:python
复制
PLAN = {
    "area_id": 10,                      # 区域编号,参与拼装 IPv4 第二段与 IPv6 区域位
    "loopback_v4": "10.10.0.0/16",      # IPv4 Loopback 地址池
    "loopback_v4_start": 1,             # 起始主机位
    "loopback_v6": "fd00:a::/32",       # IPv6 Loopback 地址池
    "link_v4": "10.10.200.0/24",        # 设备互联地址池,按 /30 划分
    "srv6_locator": "2001:db8:a::/48",  # SRv6 Locator 前缀
    "uplink_mask": 30,                  # 互联链路掩码
}

换项目只改这个字典,其余逻辑不动。

三、环境准备

代码语言:bash
复制
python -m venv .venv
.venv\Scripts\activate        # Linux/macOS 用 source .venv/bin/activate
pip install openpyxl

内网环境小贴士:煤矿项目现场常常没有外网。在有网的机器上 pip download openpyxl -d ./pkgs 把 wheel 拷进去,然后 pip install --no-index --find-links=./pkgs openpyxl 离线安装,屡试不爽。

四、四步实现

第 1 步:解析表 2.3(别被列名坑了)

规划模板每次版本都不一样,列名可能叫"设备名称"也可能叫"网元名称","设备角色"也可能写成"网络层次"。所以我没用固定列号,而是做了别名匹配 + 长名优先:

代码语言:python
复制
HEADER_ALIAS = {
    "site": ["站点", "站点名称", "机房", "所属站点"],
    "name": ["设备名称", "网元名称", "设备", "NE名称"],
    "role": ["设备角色", "角色", "层级", "网络层次"],
    "ring": ["接入环", "所属环", "环", "环网"],
    "area": ["区域", "区域编号", "所属区域"],
}

def _match_header(cell_value):
    """按别名长度降序匹配,避免「设备名称」被短别名「设备」抢先命中"""
    v = re.sub(r"\s+", "", str(cell_value)) if cell_value is not None else ""
    flat = [(a, std) for std, aliases in HEADER_ALIAS.items() for a in aliases]
    for alias, std in sorted(flat, key=lambda x: -len(x[0])):
        if alias in v:
            return std
    return None

这里是我踩的第一个坑:一开始按字典顺序遍历别名,"设备角色" 会被 "设备" 抢先匹配成 name,结果整列角色丢失,所有设备都被当成接入层,拓扑直接错。改成按别名长度降序匹配后解决。

第 2 步:从角色和接入环推导拓扑

不需要画拓扑图,角色 + 环号就够了:

代码语言:python
复制
def build_topology(devices):
    links, seen = [], set()
    rings = defaultdict(list)
    for d in devices:
        if d.ring:
            rings[d.ring].append(d)

    for ring, devs in rings.items():          # 环内互联,3 个点以上闭合
        devs = sorted(devs, key=lambda x: x.name)
        pairs = list(zip(devs, devs[1:]))
        if len(devs) >= 3:
            pairs.append((devs[-1], devs[0]))
        for a, b in pairs:
            key = frozenset((a.name, b.name))
            if key not in seen:
                seen.add(key)
                links.append(Link("接入环", ring, a, b))

    cores = [d for d in devices if d.role == "核心"]
    aggs = [d for d in devices if d.role == "汇聚"]
    for ag in aggs:                            # 汇聚双上联核心
        for c in cores:
            key = frozenset((ag.name, c.name))
            if key not in seen:
                seen.add(key)
                links.append(Link("上联", f"{ag.ring or ag.site}-上联", ag, c))
    for a, b in combinations(sorted(cores, key=lambda x: x.name), 2):
        links.append(Link("核心互联", "核心", a, b))
    return links

接口编号按设备已用数量顺序分配(GE0/0/1、GE0/0/2…),输出时直接带上,割接时照表配就行。

第 3 步:地址分配(用 ipaddress,别自己算)

Python 标准库 ipaddress 是这类工具的核心武器,加减、子网划分、越界判断全包了:

代码语言:python
复制
def allocate(devices, links):
    lo4_pool = ipaddress.ip_network(PLAN["loopback_v4"])
    lo6_net  = ipaddress.ip_network(PLAN["loopback_v6"])
    link_pool = ipaddress.ip_network(PLAN["link_v4"])
    loc_net  = ipaddress.ip_network(PLAN["srv6_locator"])

    for i, d in enumerate(devices, start=PLAN["loopback_v4_start"]):
        d.idx = i
        d.lo_v4 = f"{lo4_pool.network_address + i}/32"
        d.lo_v6 = f"{lo6_net.network_address + i}/128"
        # Locator:/48 前缀 + 16bit 节点号 → /64;End SID 固定 function ::1
        d.locator = f"{loc_net.network_address + (i << 64)}/64"
        d.end_sid = str(ipaddress.ip_network(d.locator, strict=False).network_address + 1)

    subnets = list(link_pool.subnets(new_prefix=PLAN["uplink_mask"]))
    if len(links) > len(subnets):
        raise RuntimeError(f"互联地址池 {link_pool} 仅可划分 {len(subnets)} 段 /30,实际需要 {len(links)} 段")

    for n, lk in enumerate(links):
        net = subnets[n]
        hosts = list(net.hosts())          # /30 只有两个可用地址,恰好一端一个
        lk.net, lk.a_ip, lk.b_ip = str(net), f"{hosts[0]}/30", f"{hosts[1]}/30"
        lk.a_if, lk.b_if = lk.a.next_iface(), lk.b.next_iface()

两个关键点:

  • SRv6 Locator 的位宽:节点号要左移 64 位(128 - 64)拼进 IPv6 地址,写成 i << 64。手算十六进制是事故高发区。
  • /30 只有两个可用地址:net.hosts() 正好返回这两个,hosts[0] 给 A 端、hosts[1] 给 B 端,永远不会串段。

第 4 步:回填 Excel 并输出校验报告

代码语言:python
复制
def write_sheet(wb, title, headers, rows, widths=None):
    ws = wb.create_sheet(title)
    ws.append(headers)
    for c in ws[1]:
        c.fill, c.font = HEAD_FILL, HEAD_FONT
        c.alignment, c.border = Alignment(horizontal="center"), BORDER
    for r in rows:
        ws.append(r)
    for i, w in enumerate(widths or [16] * len(headers), start=1):
        ws.column_dimensions[get_column_letter(i)].width = w
    ws.freeze_panes = "A2"
    return ws

校验部分做的是规划交付前必查的三件事:

代码语言:python
复制
def validate(devices, links):
    issues = []
    # 1. Loopback / Locator 全局唯一性
    # 2. 地址是否落在预设地址池内(越界检测)
    # 3. 每条链路的两端地址是否真属于该 /30 子网
    return issues

五、实际运行效果

代码语言:bash
复制
$ python ip_plan.py --demo
[demo] 已生成示例基线:表2.3_站点设备清单_示例.xlsx
设备 10 台 / 链路 13 条
校验:全部通过
已输出:切片网络规划_已填充.xlsx

生成的 2.4 表(节选):

序号

站点

设备名称

设备角色

所属环

IPv4 Loopback

1

地面中心站

Core-01

核心

—

10.10.0.1

2

地面中心站

Core-02

核心

—

10.10.0.2

3

中央变电所

Agg-01

汇聚

中央变电所环

10.10.0.3

4

风井场地

Agg-02

汇聚

风井环

10.10.0.4

生成的 2.6 设备互联地址(节选):

链路类型

环

A端设备

A端接口

A端IP

B端设备

B端接口

B端IP

子网

接入环

中央变电所环

Acc-01

GE0/0/1

10.10.200.1/30

Acc-02

GE0/0/1

10.10.200.2/30

10.10.200.0/30

接入环

中央变电所环

Acc-02

GE0/0/2

10.10.200.5/30

Acc-03

GE0/0/1

10.10.200.6/30

10.10.200.4/30

接入环

中央变电所环

Acc-03

GE0/0/2

10.10.200.9/30

Agg-01

GE0/0/1

10.10.200.10/30

10.10.200.8/30

接入环

中央变电所环

Agg-01

GE0/0/2

10.10.200.13/30

Acc-01

GE0/0/2

10.10.200.14/30

10.10.200.12/30

生成的 2.7 SRv6 Locator(节选):

设备名称

设备角色

SRv6 Locator

掩码

End SID

Core-01

核心

2001:db8:a:1::

/64

2001:db8:a:1::1

Core-02

核心

2001:db8:a:2::

/64

2001:db8:a:2::1

Agg-01

汇聚

2001:db8:a:3::

/64

2001:db8:a:3::1

六、踩坑记录

坑 1:表头别名抢占匹配。 已在上文说明,"设备" 会抢走 "设备角色",必须长名优先。这个坑的隐蔽之处在于——它不报错,只是默默把角色识别错,输出看起来"很正常"。

坑 2:load_workbook 默认读公式不读值。 如果表 2.3 里有公式(比如站点名用 VLOOKUP 拼出来),必须加 data_only=True,否则读到的全是 =VLOOKUP(...) 字符串。

坑 3:合并单元格读不到值。 合并区域只有左上角单元格有值,其余是 None。表 2.3 若有合并的站点名,需要做前向填充(ffill)。

坑 4:地址池容量要在分配前算。 /24 的互联池最多划分 64 段 /30,链路一多就溢出。必须提前 raise,否则会静默丢链路。

坑 5:分配顺序要稳定。 设备按 核心 → 汇聚 → 接入 + 环名 + 设备名 排序后再编号,否则同一份清单两次运行会得到两套地址,交付件无法复现。

七、和 WorkBuddy 怎么协作

这个工具是在 WorkBuddy 里对话式迭代出来的,我的实际用法是:

  1. 先给结构,再要代码。 把《切片网络规划模板.xlsx》的结构(表 2.3 有哪些列、2.4~2.7 要输出什么)讲清楚,再让它写脚本。只说"帮我做个 IP 规划工具",它只会给你一个玩具。
  2. 让它边写边跑。 直接要求"写完立刻运行验证,把输出贴给我"。上面"设备角色被误识别成设备名称"的 bug 就是这么第一轮跑出来的。
  3. 用真实数据做回归。 把脱敏后的真实站点清单丢进去跑,比造数据更能暴露问题。
  4. 让它写文档。 代码定稿后让 WorkBuddy 直接按社区投稿的格式整理成文,省掉一半写作时间。

八、收益

指标

手工

工具

80 台设备地址规划

6~8 小时

约 30 秒(含校验)

插入设备后重排

重做一遍

改表 2.3 重跑

重号/越界错误

割接时才发现

生成时直接拦截

交付一致性

依赖个人习惯

模板统一,可复现

更实在的收益是:地址规划不再是割接前夜的风险项。脚本跑完那一刻,地址冲突就已经排除了。

九、还能怎么扩展

  • 增加 业务切片地址池(不同切片独立网段),表 2.3 加一列切片 ID 即可;
  • 输出 设备配置片段(华为/华三的 interface + ip address + segment-routing ipv6 locator),直接粘到割接脚本;
  • 接 IPAM/CMDB,规划结果入库,避免多人维护多张 Excel;
  • 增加 增量模式:已分配的地址保持不变,只给新增设备分配,避免整网重编。

完整代码:ip_plan.py(单文件,约 300 行,仅依赖 openpyxl)。

代码语言:bash
复制
# 跑通示例
python ip_plan.py --demo

# 用真实模板
python ip_plan.py -i 切片网络规划模板.xlsx -o 切片网络规划_已填充.xlsx

如果你也在做煤矿或其他工业场景的网络规划,欢迎交流地址池划分和切片隔离的做法。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、先说痛点:最贵的不是设备,是填表
  • 二、设计思路:表 2.3 是唯一输入
    • 地址分配规则(可调)
  • 三、环境准备
  • 四、四步实现
    • 第 1 步:解析表 2.3(别被列名坑了)
    • 第 2 步:从角色和接入环推导拓扑
    • 第 3 步:地址分配(用 ipaddress,别自己算)
    • 第 4 步:回填 Excel 并输出校验报告
  • 五、实际运行效果
  • 六、踩坑记录
  • 七、和 WorkBuddy 怎么协作
  • 八、收益
  • 九、还能怎么扩展
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档