XMPP是一个用于通讯和表示的开放标准协议。从本质上讲,它是一个允许实体交换信息和进行聊天的协议。
XMPP就在我们身边……比我们想象的要多得多。WhatsApp使用了XMPP的一个变种,Zoom使用XMPP以及一些扩展来实现其聊天功能。XMPP是一些最常用和最著名的应用程序的背后技术。那么,XMPP是如何工作的呢?
如前所述,它允许实体交换信息和聊天。我说的是实体,因为这种聊天和信息交换可能涉及两个人,也可能是两个服务器/软件之间的对话。
XMPP利用了TCP。我们可以说XMPP是一个使用TCP作为底层L4协议的L7协议(就像HTTP)。
到这里为止,XMPP可能看起来就像任何其它协议一样,将消息带入其有效负载。
围绕XMPP值得注意的是,交换的数据是XML格式的。这就导致了两大优势:第一,XML是一种结构化的标准语言,可以很容易地被编程语言消化/处理;第二,只要用XML来格式化这些信息,就可以很容易地扩展XMPP可以传输哪些信息。
关于后面一点,请看以下链接,了解这些年发展了多少扩展:
https://xmpp.org/extensions/
XMPP与TF如何共同工作
让我们简单看下XMPP对话是如何工作的吧!详细的解释并不在本文讨论范围内,但我将尝试划出一些相关方面的重点,这将有助于理解Tungsten Fabric中的XMPP是如何工作的。
访问资源的用户由所谓的JID来识别:
[ node “@” ] domain [ “/” resource ]
例如,“iosonounrouter@whatsapp/mobilechat”可能代表我(iosonounrouter)使用whatsapp并访问mobilechat资源。
资源可以被看成是我想访问的一类聊天室/话题/频道。想象一下,某个软件要从互联网上检索信息,它可能使用XMPP来访问不同的资源:
client@infohub/sport
client@infohub/finance
第一个JID可以用来访问资源以查找和检索体育新闻,而第二个JID将相同的功能用于金融数据。
通常情况下,XMPP遵循客户端-服务器的交互方式(即使p2p也是可能的)。客户端和服务器发送/接收所谓的XMPP节段(stanzas)——节段有不同的用于客户端和服务器的类型。XMPP核心主要有三种类型的节段:
消息(message):顾名思义,它带来消息。采用的是“fire and send”的模式,也就是说,没有可靠的方法来确保消息在另一端被收到。某种程度上,我们可能会把这个节段看作是UDP:发送出去,并希望它能成功!当然,这个节段可以包含XML格式的结构化数据。
表示(presence):用于宣布系统内有某种东西的存在
IQ:代表消息(info)/查询(query),允许实现类似于http的请求/响应机制(例如GET)。使用IQ,我们可以获取/设置数据。不同于消息,IQ使用了确认通知,以提供更可靠的通信。
下图总结了目前为止所看到的概念:
比如我们有两个客户(Ivano和Carmela)访问一台服务器(infohub)。服务器上有两个资源(金融和体育)。如前所述,可以将资源看作是聊天室/主题/频道。客户端通过JID访问这两个资源,总共会有四个“对话”。在每一个对话里面,客户端和服务器将使用节段来交换信息,即IQ、MESSAGE、PRESENCE等…
现在,有一个问题出现了:Tungsten Fabric在这里做了什么?
如果你有一些Tungsten Fabric的知识,可能知道TF使用XMPP在控制节点和计算节点之间交换数据。控制节点和计算节点会聊天,谈论TF集群内发生的事情。控制节点作为XMPP服务器,而计算节点作为客户端。
XMPP带来了什么样的信息?大多数时候,我们说XMPP取代BGP进行控制节点-计算节点通信,说明它是用来携带路由信息的。这是事实,但不完全正确。
XMPP也被用来携带配置信息(我们将在后面看到这意味着什么)。这里的关键概念是,XMPP既是一个信令协议,也是一个配置协议。
如何转化为XMPP术语呢?很简单,这里有两个资源:一个是配置资源,一个是路由资源。
把控制节点-计算节点对(pair)看成是两个朋友在互联网上聊天。他们聊的是两个话题:配置和路由。当一个人有关于配置方面的事情要讲时,就会通过配置通道(资源)来讲。另一方面,当有一些路由信息需要沟通时,会使用路由通道。
下图说明了这种互动关系:
节点通过两个不同的通道交换信息,将数据编码成XML格式的负载。
现在,有关XMPP和Tungsten Fabric如何共同工作所需的最基础知识,我们就都已经掌握了。
为了学习XMPP,我们将继续进行以下步骤:
一开始,我们有一个空的计算节点,上面没有虚拟机运行。
接下来,终端用户(通过GUI、Heat……)创建一个虚拟网络和一个连接到该虚拟网络的虚拟机。
因此,控制节点将向虚拟机运行的控制节点发送XMPP消息,以便告诉它配置和路由信息。
创建虚拟机后,我使用tcpdump捕获计算节点上的XMPP数据包。
先来看看pcap。首先,我们要告诉Wireshark将5269端口解码为XMPP。
此时,过滤XMPP数据包,检查信息栏。
它们看起来像JID……确实也是!
用户(计算节点)为网络控制(network-control)
服务器(控制节点)为contrailsystems.com
两个资源为:bgp-peer和config
它们就在这里!就是之前提到的两个通道:一个承载配置信息,一个承载路由信息。
为什么要两个通道?
XMPP会带来一些配置信息,因为控制节点要通知vRouter必须创建一些对象:其中包括代表虚拟网络的VRF,以及连接VRF与虚拟机的虚拟机接口。简单地说,config数据包将指示vRouter必须创建的所有这些Tungsten Fabric对象,以便将新的虚拟机整合到虚拟网络生态系统中。
同时,XMPP也会带来路由信息。新的虚拟机被分配了一个IP地址。关于vnic(虚拟机接口)的IP地址和MAC地址的信息必须传输到计算节点,这样它就可以更新相应的路由表(例如在收到config XMPP消息后刚创建的VRF)。
正如你所看到的,config和bgp-peer消息经常是相关联的!
配置信息里都有什么
现在,让我们来看看这些XMPP信息里面有什么。拿下面这个消息来说:
这是一个IQ“type:set”的消息。使用IQ是很聪明的,因为它需要确认信息;这样Tungsten Fabric可以“验证”计算节点是否真的收到了信息,并且它也避免了计算节点收到路由数据,但没有足够的底层配置对象来使用这些数据的情况。
IQ数据包应该使用一个ID字段,这样便于跟踪响应。无论如何,Tungsten Fabric不会填充ID属性。
核心部分已经标蓝。大家可以看到信息是CONFIG UPDATE,意思是“如果存在则更新,否则就创建”。
接下来,我们有一个要创建的节点和链接列表。可以很容易地发现虚拟网络对象。下面好好观察一下它的内部情况:
如果你熟悉Tungsten Fabric,就会发现我们在配置虚拟网络时可以设置的那些设置。例如,VN名称为xmpp_net1,属于juniper-project项目。
这部分的有效负载基本上是告诉vRouter创建一个新的对象(节点),一个虚拟网络,并告知它的参数和属性。
对于其它对象(节点)也可以看到类似的输出信息。
我们看到XMPP数据包中还携带了LINK的信息:
顾名思义,链接(link)是将两个节点连接起来,以便在配置层代表这些对象之间的“参考”关系。
例如,在上面的输出内容中,表明要将虚拟路由器与新虚拟机的虚拟机接口“链接”起来。
这些链接不是随机的,它们与Tungsten Fabric配置模式一致,该模式定义了对象(及其属性)以及对象之间可能的关系,称为链接。这个模式就像Junos XSD模式一样。
同样,我们希望看到虚拟网络和路由实例对象、实例IP和虚拟网络对象等之间的链接。
这些信息也可以通过introspect获得。在这里,从Tungsten Fabric GUI中,我“访问”了计算节点introspect web服务器,并请求获得Sandesh Trace Buffer List。
从结果输出中,我们检测到四个相关的轨迹(trace):
其中两个包含接收到的config xmpp消息的信息,其它的是接收到的bgp xmpp消息。每种类型(路由或配置)都有两个轨迹(trace),因为每个计算节点都与两个控制节点进行了XMPP对话(冗余原因)。
点击“Rx Config Xmpp Message”,选择XSD GRID视图。在那里,我们可以寻找有趣的XMPP消息。
例如,这个是指示vRouter必须创建新的虚拟网络对象的消息。如你所见,正文是XML。我们可以将它复制粘贴,并以一种格式友好的方式来查看:
这些都是我们在Wireshark中看到的信息。
同样,也可以找到关于链接创建的日志:
并提取XML主体:
这是第一个例子,说明XMPP是如何被扩展以携带我们能想到的最多样化的数据集的。鉴于它对XML的原生支持,可以添加想要的信息,只要确保符合XML-syntax即可。同时,作为XML结构的数据,接收端将很容易解析和处理数据。
扒一扒XMPP路由信息
接下来进入第二个“通道”:路由。
虚拟机被分配的地址是172.30.1.3/32。三条XMPP路由消息从控制节点发送到计算节点:
为什么是三条?因为虚拟网络是L3+L2,我们会有一条inet路由,一条evpn mac路由和一条evpn mac:ip路由。
让我们到内部去看一看:
与以前看到的有一些不同。我们使用的是MESSAGE节段而不是IQ节段。在它里面,BGP路由广告被编码为一个EVENT消息的ENTRY ITEM。
除了这些方面,上面的输出内容应该是网络工作人员所熟悉的。项目id是路由:172.30.1.3/32。接下来,我们还有NLRI信息。AFI 1 / SAFI 1表示IPv4。然后,是下一跳的信息以及路由所属的虚拟网络名称。
基本上,我们将BGP UPDATE消息编码成了XMPP有效负载。这又一次证明了XMPP的可扩展性如何使这个协议变得非常灵活。从软件的角度来看,用一个协议(XMPP)就能同时管理配置和路由。除了有些必需的情况(例如与不支持XMPP的SDN网关通信)外,一般不需要有两个协议栈(xmpp和bgp)。
同样,我们也可以用introspect来提取同样的信息:
最后,将虚拟机删除。结果就是,我们又触发了一次XMPP数据包的交换。
这次它们将不是UPDATE消息,而是DELETE消息:
因为不再需要,节点和链接都被删除了。
同样,也会有模仿BGP withdraw消息的routing XMPP消息。我们认识它们是因为RETRACT关键字的存在。这次我们在introspect上看到了这个:
就是这样!现在我们知道了XMPP是如何允许Tungsten Fabric节点创建/删除配置对象和路由的。说到底,这就是一个聊天:)
作者:Umberto Manferdini 译者:TF编译组
原文链接:https://iosonounrouter.wordpress.com/2020/12/07/a-look-inside-xmpp-in-contrail/