核心BGP-插入BGP

2020-07-06 11:18:44

BGP是支持Internet的众多协议之一。你很有可能听说过它,即使你不在计算机网络领域或周围工作。如果您不熟悉,我将尝试提供一些简短的背景知识:

在最后一个要点上展开,由于BGP的灵活性和可扩展性,很难准确总结它是如何/在哪里使用的。各个IETF工作组继续为90年代初形成的协议发布与BGP相关的RFC。随着BGP领域和应用范围的扩大,我们需要能够跟上形势的软件。

在这篇文章中,我将提供我使用BGP的一些个人经验和历史,并介绍一个新的BGP库CoreBGP,该库可用于构建下一代支持BGP的应用程序。

2010年10月,我第一次参加在佐治亚州亚特兰大举行的NANOG会议,原因是我在工作中意外陷入网络运营工程师的职位。当时我在一家中等规模的主机提供商工作,对BGP很感兴趣。据维基百科(Wikpedia)报道,一到亚特兰大,我就依稀记得有些困惑,因为我告诉一名出租车司机,我需要下车的酒店在桃树街(Peachtree St.)。后来我了解到,亚特兰大有71条街道的名字里有一个“桃树”(Peachtree)的变体。

最终,我到达了我需要去的地方,我参加的第一个演讲是菲利普·史密斯(Philip Smith)所著的互联网服务提供商的BGP技术。在深入了解ISP使用的技术之前,Philip先从基础开始。在这次演讲中,很多灯泡都为我熄灭了。我还没有看到任何其他的BGP演示涵盖如此广泛的信息,但仍然以初学者友好的方式进行,对任何专家来说都是有用的,而且非常有趣。

快进10年后,我在运营使用BGP的网络方面获得了相当多的经验。最近几年,我转向了软件工程,在那里我有机会实现各种支持BGP的应用程序,以实现网络可观察性、数据分析和SDN目的。

每次我启动一个新的支持BGP的应用程序时,我都必须回答以下问题--哪个现有的BGP实现应该是它的基础?

在为数不多的开放源码BGP实现中,我亲身体验过使用以下各项的项目:

鸟牌在需要丰富的政策语言的地方大放异彩。GoBGP有一个功能丰富的GRPC API,可以作为库嵌入。OpenDayLight的BGP实施是更大的SDN控制器解决方案的一部分,并广泛支持BGP-LS。Quagga可以可靠地产生MRT转储,并且已经存在很长时间了,尽管我相信FRRouting现在被认为是它的继任者。

这些都是成熟的、成熟的实现。其中一些已在大型ISP、云提供商和互联网交换点投入生产。它们是专门构建的,并进行各种权衡以适应其用例(编程语言、线程模型、数据结构、应用编程接口等…)。。

但是,如果我们构建的东西与这些广泛使用的实现的主要用例不一致,该怎么办呢?如果我们选择围绕它们建立,我们可能会被最终带来负担的决定所束缚。在我们自己的数据结构中交换路由表,或者添加新的NLRI都不是一件容易的事。即使一个实现打算以库的形式嵌入,它仍然会让我们陷入资源消耗的困境。显然需要插入或挂钩到BGP FSM的特定部分,而不需要继承进入成熟的BGP守护进程的决策。

在第27届IEEE国际网络协议会议(ICNP)上,卢万天主教大学的一个小组提交了一篇关于插件化路由协议案例的论文:

摘要路由协议(如BGP和OSPF)是Internet服务提供商(ISP)网络的关键组件。这些协议和运营商的要求会随着时间的推移而发展,但网络运营商通常需要很多年才能说服他们的不同路由器供应商和IETF扩展路由协议。一些网络运营商,特别是在企业和数据中心,已经采用了集中控制的软件定义网络(SDN),以使其更加灵活。我们提出了一种新的实现路由协议的方法,使网络运营商能够在创新的同时仍然使用分布式路由协议,从而保持了与集中式路由方法相比的所有优势。我们使用能够执行插件的虚拟机来扩展路由协议。这些插件通过简单的API扩展协议或修改其底层算法,以满足运营商的特定需求。我们修改了FRRouting提供的OSPF和BGP实现,并通过几个用例演示了我们方法的适用性。

在他们的论文中,他们提出了一种插入前面提到的开源BGP实现FRRouting的方法。插件存在于函数级别,或者在调用之前(PRE)、作为替换(REPLACE)或者就在返回之前(POST)。他们的BGP插件主要关注消息的接收,并在不久之后做出决定:

BGP守护进程也进行了类似的扩展。我们在从邻居接收BGP消息的函数、过滤器和决策过程内部添加插入点。我们还向uBPF VM执行的插件公开特定函数。

通过利用链接到FRRouting协议实现的用户空间eBPF VM(UBPF),他们对插件沙箱采取了一种聪明的方法。每个插件编译成eBPF字节码,并在所述VM内运行。可以加载和卸载插件,而不会影响主要协议实现。使用eBPF VM还允许他们利用所有先前存在的Linux内核工具。

我发现这种方法很鼓舞人心,但仍然与我的用例不太匹配:

插件似乎是围绕“传入”事件或消息构建的。如果我想要向对等设备注入更新消息,而不管FRRouting想要发送什么,该怎么办?

FRRouting在构建时并没有考虑到这个插件模型。对FRRouting的更改/更新将导致VM钩点的维护难题。

eBPF字节码通常从C编译而来,与更现代的语言相比,编写C可能会很耗时。

这种经验和研究使我创建了CoreBGP,这是一个BGP库,我可以在支持BGP的应用程序中重用它。

CoreBGP是用GO编写的BGP库,它使用事件驱动的可插拔模型实现BGP FSM。它公开了一个API,使用户能够:

CoreBGP不解码更新消息(除了报头验证)、管理路由表或发送自己的更新消息。这些责任都向下传递给用户。因此,目标用户是希望承担该责任的人。

//Plugin是BGP对端插件。当对等方的FSM在发送Open消息之前//处于连接状态时,类型插件接口{//GetCapability被激发。返回的功能包含在发送给对等体的//Open消息中。GetCapability(Peer*PeerConfig)[]*Capability//在OpenSent状态下,当收到对端//的Open消息时,会触发OnOpenMessage。返回非NIL通知将导致将其发送到//对等方,并且FSM将转换到空闲状态。/根据RFC5492,BGP扬声器应仅在缺少所需功能//时发送通知;应//忽略未知或不支持的功能。OnOpenMessage(Peer*PeerConfig,Capability[]*Capability)*Notification//Onestablished在对等方的FSM转换到ESTABLISHED//状态时触发。当从对等体接收到Update//消息时,将触发返回的UpdateMessageHandler。/提供的编写器可用于在//FSM当前已建立状态的生存期内向对等方发送更新消息。一旦OnClose()激发,就应该//丢弃它。Onestabled(Peer*PeerConfig,Writer UpdateMessageWriter)UpdateMessageHandler//OnClose在对等方的FSM从ESTABLISHED//状态转换出来时触发。OnClose(Peer*PeerConfig)}

下面是一个示例插件,它在对等点进入/离开已建立状态以及接收到更新消息时进行记录:

type plugin struct{}func(p*plugin)GetCapability(c*corebp.PeerConfig)[]*corebp.Capability{caps:=make([]*corebp.Capability,0)return caps}func(p*plugin)OnOpenMessage(Peer*coregp.PeerConfig,Capability[]*corebackgp.Capability)*coregp.Notification{return nil}func(p*plugin)OnOpenMessage(Peer*corebgp.PeerConfig,Capability[]*corebp.Capability)*coregp.Notification{return nil}func(p*plugin)。Println(";Peer establed";)//发送肋骨末尾编写器。WriteUpdate([]byte{0,0,0,0})return p.handleUpdate}func(p*plugin)OnClose(Peer*coregp.PeerConfig){log.。Println(";Peer Closed";)}func(p*plugin)handleUpdate(Peer*coregp.PeerConfig,u[]byte)*corebp.Notification{log.。Printf(";获取len的更新消息:%d";,len(U))返回空}。

插件在添加到管理其生存期的服务器时会附加到对等方:

路由器ID:=网络。ParseIP(";192.0.2.1";)srv,错误:=corebgp。如果err!=nil{log.。Fatalf(";构造服务器时出错:%v";,err)}p:=&;plugin{}err=srv。AddPeer(&;corebgp.PeerConfig{IP:NET.。解析IP(";198.51.100.10";),本地服务器:65001,远程服务器:65010,},p)如果错误!=无{log.。Fatalf(";添加对等方时出错:%v";,错误)}。

CoreBGP足够灵活,可以作为成熟的BGP守护进程的基础。相反,它也适合简单地记录更新消息的用例,如上面的示例所暗示的那样。

有关更多示例,请查看示例目录和pkg.go.dev以获取完整的API。CoreBGP是开源的,可以在GitHub上获得。请试一试,报告错误,并贡献自己的力量!