BaGPipe-BGP

BaGPipe-BGP 是 networking-bagpipe 的一个组件,用于计算节点上,Neutron 代理以及该代理的 bagpipe 代理扩展中。

它是一个轻量级的 BGP VPN(IP VPN 和 E-VPN)实现,面向在托管 VM 的计算节点上的部署,特别是针对 Openstack/KVM 平台。

BaGPipe-BGP 的目标不是完全实现 BGP 规范,而是仅实现实现 IP VPN VRF 和 E-VPN EVI 所需的规范子集(RFC4364 又名 RFC2547bis,RFC7432/draft-ietf-bess-evpn-overlay,以及 RFC4684)。

BaGPipe-BGP 设计用于使用基于 IP 的封装(例如 MPLS-over-GRE 或 VXLAN),因此不需要使用 LDP。 裸 MPLS over Ethernet 也受支持,如果计算节点/路由器具有直接以太网连接,则可以使用它。

典型用法/部署

BaGPipe-BGP 设计用于为在 Openstack 计算节点上运行的本地 VM 提供 VPN(IP VPN 或 E-VPN)连接。

BaGPipe-BGP 通常通过其 HTTP REST 接口由 Openstack Neutron 代理扩展驱动,这些扩展包含在此包中。

此外,BaGPipe-BGP 也可以独立使用(特别是用于测试目的),例如使用 VM tap 接口或与网络命名空间的 veth 接口(参见 下方)。

BGP 和路由反射

如果您只想测试如何互连运行 bagpipe-bgp 的一个计算节点和一个 IP/MPLS 路由器,则无需设置 BGP 路由反射器。

但是,在计算节点之间使用 BaGPipe-BGP 当前需要设置 BGP 路由反射器(参见 BGP 实现注意事项)。 通常,需要以被动模式使用 BGP 对等连接。

术语“BGP 路由反射器”是指在 iBGP 对等体之间重新分发路由的 BGP 实现 RFC4456

在使用多个计算节点上的 bagpipe-bgp 时,因此我们需要将 BaGPipe-BGP 的每个实例配置为至少与一个路由反射器对等(参见 配置)。

我们提供了一个工具,可用于模拟路由反射器以互连 2 个 BaGPipe-BGP 实现,通常用于测试目的(参见 Fake RR)。

对于运行 BaGPipe-BGP 的两个以上计算节点,您需要一个支持 RFC4364 和 BGP 路由反射的真实 BGP 实现(并且理想情况下也支持 RFC4684),可以考虑不同的选项

  • 其他开源项目中的 BGP 实现可能适用,但我们尚未详尽地探索这些实现

  • 可以使用来自 Alcatel-Lucent、Cisco 或 Juniper 等厂商的商业路由器;其中一些厂商还将其操作系统作为虚拟机提供

配置

bagpipe-bgp 配置文件默认位置是:/etc/bagpipe-bgp/bgp.conf

需要对其进行自定义,至少要进行以下配置

  • local_address:用于 BGP 会话和流量封装的本地地址(也可以指定为接口,例如“eth0”,在这种情况下将使用此接口的 IPv4 地址)

  • peers:BGP 对等体的列表,具体取决于您选择的 BGP 设置(参见上方 BGP 路由反射

  • 数据平面配置,如果您真的希望数据包能够通过(参见 数据平面配置

使用两个计算节点并依赖 bagpipe 假路由反射器的示例

  • 在计算节点 A 上(local_address=10.0.0.1)

    • 运行 bagpipe-fakerr

    • 使用 peers=127.0.0.1 运行 bagpipe-bgp(因此,计算节点 A 将连接到本地运行的假路由反射器)

  • 在计算节点 B 上(local_address=10.0.0.2)

    • 使用 peers=10.0.0.1 运行 bagpipe-bgp

数据平面驱动程序配置

请注意,示例配置文件中提出的数据平面驱动程序是虚拟驱动程序,实际上不会驱动任何数据平面状态。 要真正转发到 IP VPN 或 E-VPN 的流量,您需要选择真实的数据平面驱动程序。

例如,您可以为 IP VPN 使用 ovs 数据平面驱动程序,并为 E-VPN 使用 linux 驱动程序。

请注意,IP VPN 的数据平面驱动程序适用特定的约束或依赖项

  • ovs 驱动程序可以在大多数最新的 Linux 内核上使用,但需要具有合适的 MPLS 代码的 OpenVSwitch(测试了 OVS 2.4 到 2.6);此驱动程序可以执行裸 MPLS 或 MPLS-over-GRE(但请参见 注意事项 以获取 MPLS-over-GRE);对于裸 MPLS,此驱动程序要求将 OVS 桥与 IP 地址关联,并且在调用 BaGPipe-BGP API 附加它们之前将 VRF 接口插入 OVS

  • linux 驱动程序依赖于 Linux 内核的本机 MPLS 堆栈,当前需要内核 4.4+ 并使用允许通过 Netlink 定义所有状态的 pyroute2 模块,而不是通过执行“ip”命令

对于 E-VPN,linux 驱动程序受支持,无需任何额外的配置,并且只需 Linux 内核 >=3.10 (linux_vxlan.py)。

用法

BaGPipe-BGP 本地服务

如果安装了 systemd 初始化脚本(参见 samples/systemd),则通常使用以下命令启动 bagpipe-bgpsystemctl start bagpipe-bgp

也可以使用 bagpipe-bgp 命令直接启动(--help 查看可以使用哪些参数)。

默认情况下,它将日志输出到 stdin(如果由 systemd 运行,则由 systemd 捕获)。

BaGPipe 假 BGP 路由反射器

如果您选择使用我们的假 BGP 路由反射器(参见 BGP 路由反射),可以使用 bagpipe-fakerr 命令启动它,或者如果您安装了启动脚本,可以使用 service bagpipe-fakerr start。 请注意,此工具需要额外安装 python 包 twisted

没有什么需要配置的,日志将在 syslog 中。

此工具不是 BGP 实现,只是将两个 TCP 连接面对面地连接在一起。

用于接口附件的 REST API 工具

bagpipe-rest-attach 工具允许您通过命令行使用 REST API 来附加和分离接口到 IP VPN VRF 和 E-VPN EVI。

参见 bagpipe-rest-attach --help

使用 VM tap 接口的 IP VPN 示例

此示例假定存在预先存在的 tap 接口“tap42”。

  • 在计算节点 A 上,将 tap 接口 tap42,MAC de:ad:00:00:be:ef,IP 11.11.11.1 插入具有路由目标 64512:77 的 IP VPN VRF

    bagpipe-rest-attach --attach --port tap42 --mac de:ad:00:00:be:ef --ip 11.11.11.1 --gateway-ip 11.11.11.254 --network-type ipvpn --rt 64512:77
    
  • 在计算节点 B 上,将 tap 接口 tap56,MAC ba:d0:00:00:ca:fe,IP 11.11.11.2 插入具有路由目标 64512:77 的 IP VPN VRF

    bagpipe-rest-attach --attach --port tap56 --mac ba:d0:00:00:ca:fe --ip 11.11.11.2 --gateway-ip 11.11.11.254 --network-type ipvpn --rt 64512:77
    

请注意,此示例只是一个教科书示例,但除非您尝试使用两个 Linux 数据平面驱动程序之一,否则它实际上无法工作。

另请注意,假设 VM 位于这些 tap 接口之后,这些 VM 需要具有适当的 IP 配置。 当 BaGPipe-BGP 独立使用时,不提供 DHCP 服务,并且 IP 配置必须是静态的。

另一个 IP VPN 示例…

在此示例中,bagpipe-rest-attach 工具将为您构建一个网络命名空间和一个配置良好的 veth 接口对,并将其中一个 veth 插入 VRF

  • 在计算节点 A 上,将具有 IP 12.11.11.1 的 netns 接口插入名为“test”的新 IP VPN VRF,路由目标为 64512:78

    bagpipe-rest-attach --attach --port netns --ip 12.11.11.1 --network-type ipvpn --vpn-instance-id test --rt 64512:78
    
  • 在计算节点 B 上,将具有 IP 12.11.11.2 的 netns 接口插入名为“test”的新 IP VPN VRF,路由目标为 64512:78

    bagpipe-rest-attach --attach --port netns --ip 12.11.11.2 --network-type ipvpn --vpn-instance-id test --rt 64512:78
    

对于最后一个示例,假设您已配置 bagpipe-bgp 使用 ovs 数据平面驱动程序用于 IP VPN,您实际上能够在这两个网络命名空间之间交换流量

ip netns exec test ping 12.11.11.2
PING 12.11.11.2 (12.11.11.2) 56(84) bytes of data.
64 bytes from 12.11.11.2: icmp_req=6 ttl=64 time=1.08 ms
64 bytes from 12.11.11.2: icmp_req=7 ttl=64 time=0.652 ms

一个 E-VPN 示例

在此示例中,与前一个示例类似,bagpipe-rest-attach 工具将为您构建一个网络命名空间和一个配置良好的 veth 接口对,并将其中一个 veth 插入 E-VPN 实例

  • 在计算节点 A 上,将具有 IP 12.11.11.1 的 netns 接口插入名为“test2”的新 E-VPN,路由目标为 64512:79

    bagpipe-rest-attach --attach --port netns --ip 12.11.11.1 --network-type evpn --vpn-instance-id test2 --rt 64512:79
    
  • 在计算节点 B 上,将具有 IP 12.11.11.2 的 netns 接口插入名为“test2”的新 E-VPN,路由目标为 64512:79

    bagpipe-rest-attach --attach --port netns --ip 12.11.11.2 --network-type evpn --vpn-instance-id test2 --rt 64512:79
    

对于最后一个示例,假设您已配置 bagpipe-bgp 使用 linux 数据平面驱动程序用于 E-VPN,您实际上能够在这两个网络命名空间之间交换流量

ip netns exec test2 ping 12.11.11.2
PING 12.11.11.2 (12.11.11.2) 56(84) bytes of data.
64 bytes from 12.11.11.2: icmp_req=1 ttl=64 time=1.71 ms
64 bytes from 12.11.11.2: icmp_req=2 ttl=64 time=1.06 ms

观察玻璃

REST API(默认端口 8082)通过 /looking-glass URL 以只读方式提供故障排除信息。

可以使用浏览器访问它:例如 http://10.0.0.1:8082/looking-glasshttp://127.0.0.1:8082/looking-glass(建议使用一个浏览器扩展程序来漂亮地显示 JSON 数据)。

也可以使用 bagpipe-looking-glass 工具访问它

# bagpipe-looking-glass
bgp:  (...)
vpns:  (...)
config:  (...)
logs:  (...)
summary:
  warnings_and_errors: 2
  start_time: 2014-06-11 14:52:32
  local_routes_count: 1
  BGP_established_peers: 0
  vpn_instances_count: 1
  received_routes_count: 0
# bagpipe-looking-glass bgp peers
* 192.168.122.1 (...)
  state: Idle
# bagpipe-looking-glass bgp routes
match:IPv4/mpls-vpn,*:
  * RD:192.168.122.101:1 12.11.11.1/32 MPLS:[129-B]:
      attributes:
        next_hop: 192.168.122.101
        extended_community: target:64512:78
      afi-safi: IPv4/mpls-vpn
      source: VRF 1 (...)
      route_targets:
        * target:64512:78
match:IPv4/rtc,*:
  * RTC<64512>:target:64512:78:
      attributes:
        next_hop: 192.168.122.101
      afi-safi: IPv4/rtc
      source: BGPManager (...)
match:L2VPN/evpn,*: -

设计概述

BaGPipe-BGP 的主要组件是

  • 调度与 BGP 路由相关的事件在工作线程之间的引擎

  • 为每个 BGP 对等体的工作线程

  • 管理 VRF、EVI 生命周期的 VPN 管理器

  • 为每个 IP VPN VRF 或 E-VPN EVI 的工作线程

  • REST API

    • 用于附加/分离接口到 VRF 并控制所述 VRF 的参数

    • 用于访问对故障排除有用的内部信息(/looking-glass/ URL 子树)

发布/订阅设计

调度与 BGP 路由相关的事件的引擎设计具有基于 RFC4684 原则的发布/订阅模式。 工作线程(工作线程可以是 BGP 对等体或负责 IP VPN VRF 的本地工作线程)使用指定的路由目标发布 BGP VPN 路由,并订阅他们需要接收的路由目标。 引擎负责根据订阅和 BGP 语义(例如,BGP 对等会话之间不重新分发)在工作线程之间传播通告和撤销事件。

最佳路径选择

核心引擎不执行任何 BGP 最佳路径选择。 对于从外部 BGP 对等体接收的路由,最佳路径选择发生在 VRF 工作线程中。 对于本地工作线程通告的路由,不进行最佳路径选择,因为两个不同的工作线程永远不会通告具有相同 BGP NLRI 的路由。

多线程

为了方便实现,设计选择是使用 Python 本机线程和 python 队列来管理 API、本地工作线程和 BGP 对等体工作负载

  • 引擎(RouteTableManager)作为单个线程运行

  • 每个本地 VPN 工作线程都有自己的线程来处理路由事件

  • 每个 BGP 对等体 worker 都有两个线程来处理传出的路由事件和接收 socket 数据,以及一些定时器。

  • VPN 端口附加操作在处理初始设置和 API 调用的主线程中完成,这些调用受到 Python 锁的保护。

VPN 和端口附件的非持久性

目前设计的 BaGPipe-BGP 服务不会持久化 VPN(VRF 或 EVI)及其附加端口的信息。 在重启时,负责触发接口附加到 VPN 的组件可以检测到 BGP 的重启并重新触发这些附加操作。

BGP 实现

BGP 协议实现重用了 ExaBGP 中的 BGP 代码。 BaGPipe-BGP 仅重用用于消息编码和连接设置的低级类。

此 BGP 实现的非目标

  • 功能完善的 BGP 实现

  • BGP 对等体之间的路由重分发(因此,没有路由反射,也没有 eBGP)

  • 接受传入的 BGP 连接

  • 扩展到超过在运行 BaGPipe-BGP 的计算节点上托管的 VM 中路由流量所需的路由数量

数据平面

BaGPipe-BGP 被设计为允许模块化的数据平面实现。 对于每种类型的 VPN(IP VPN、E-VPN),数据平面驱动程序通过配置选择。 数据平面驱动程序负责根据端口附件信息和 BGP 路由设置传入和传出流量的转发状态。

(参见 数据平面驱动程序配置)

注意事项

  • BGP 实现并非为了符合标准而编写

    • BaGPipe-BGP 服务不监听传入的 BGP 连接(使用 BGP 路由反射器才能互连 bagpipe-bgp 实例,通常使用 BGP 对等体的被动模式)

    • 状态机,特别是重试定时器可能并非完全符合标准

    • 但是,已经与相当多的实现进行了互操作性测试

  • 标准 MPLS-over-GRE,与路由器互操作,需要 OVS >= 2.8(之前的 OpenVSwitch 版本执行 MPLS-o-Ethernet-o-GRE 而不是 MPLS-o-GRE)