
Hat
译者
⚠️ 注意
如果您发现了错误,欢迎 参与贡献。
💡 摘要 (Powered by OpenAI)
本文深入介绍了 BIRD 中 BGP 协议的内部实现,包括 bgp.c/packets.c/attrs.c 三模块架构、bucket 出站路由调度、BGP 属性双向编解码和双角色优雅重启机制。
BIRD 的 BGP 实现分为三个源文件:
| 文件 | 职责 |
|---|---|
bgp.c | 连接管理和与 BIRD 核心的接口:邻居建立、状态机、定时器 |
packets.c | 数据包处理:入站解析 (bgp_rx) 和出站生成 (bgp_fire_tx) |
attrs.c | 属性操作:BGP 属性 ↔ BIRD 扩展属性的转换 |
💡 译者注
BIRD 的 BGP 实现与其他路由软件有一个关键架构区别:不维护中央 BGP 路由表 (Adj-RIB-In/Out)。所有 BGP 路由信息直接存储在 BIRD 的主路由表中。这意味着:
Socket 数据到达
│
▼
bgp_rx()
│ 解码包头和 Marker
▼
bgp_rx_packet()
│ 按键类型分发
├── OPEN → bgp_rx_open()
├── KEEPALIVE→ bgp_rx_keepalive()
├── UPDATE → bgp_decode_attrs() → bgp_rx_update()
└── NOTIFY → bgp_rx_notify()BIRD 的出站路由更新使用精巧的 bucket 机制:
路由更新排队
│
▼
按属性 (rta) 分配到 bucket (bgp_bucket)
│ - 通过哈希表快速匹配相同 rta
│ - 通过 FIB 检测同一目的地的旧路由 (覆写而非重复发送)
▼
特殊 bucket: 路由撤回 (无属性, 独立处理)
│
▼
bgp_schedule_packet()
│ 设置 packet_to_send 位掩码
▼
Socket TX Buffer 清空时 → bgp_fire_tx()
│ 检查位掩码 → bgp_create_xxx() 生成数据包💡 译者注
为什么需要 bucket? 在 BGP 大规模路由通告场景(如路由反射器向数百个客户端发送全表),同一属性的路由可能成千上万。如果没有 bucket 机制,每条路由都需要独立编码属性字段,导致 UPDATE 消息体积极度膨胀。通过按属性分桶,具有相同 BGP 属性的路由可以共享一个属性块,数据包体积可减少数倍。这是 BIRD BGP 实现最重要的性能优化之一。
解码 (bgp_decode_attrs()):BGP UPDATE 属性块 → BIRD 扩展属性 (EAF)
bgp_attr_table 描述数组,定义所有已知属性的特性EAF_TYPE_OPAQUE 字节流附加到路由编码 (bgp_encode_attrs()):BIRD 扩展属性 → BGP UPDATE 属性块
BIRD 实现了完整的双角色优雅重启:
| 角色 | 说明 |
|---|---|
| 重启方 (Restarting) | BIRD 自身重启时,通过能力协商标记 Graceful Restart,设置 gr_wait,等待邻居重发 End-of-RIB |
| 接收方 (Receiving) | 邻居重启时,内部将 BGP 状态重置为 BS_IDLE、协议状态重置为 PS_START,但从核心角度保持协议 Up,维持已收路由不撤 |
过期路由清理:会话重建后通过 rt_refresh_begin() / rt_refresh_end() 周期清理。

译者
原文作者: <Ondrej Filip>, <Martin Mares>, <Maria Matejka>, <Ondrej Zajicek> 原文链接: https://bird.network.cz/?get_doc&v=20&f=prog-5.html#ss5.3 原文标题: 5.3 Border Gateway Protocol
遵循协议: CC BY-NC-SA 4.0 译者: hat 翻译时间: 2026-05-01 更新时间: 2026-05-01 本文链接: https://bird.xmsl.dev/docs/developer-guide/5-3-bgp.html