多协议标签交换(MPLS)解释

这个博客分为两个子部分,第一部分我们将了解MPLS到底是什么,第二部分我们将看到如何使用Golang制作MPLS数据包。

多协议标签交换(MPLS)并不是一项新技术。它已经存在了好几年了。许多人必须熟悉数据如何以网络数据包的形式从一个地方传输到另一个地方。这些数据包包含源IP地址和目标IP地址。数据包通过其间的多个路由器传递,这些路由器包含路由表,该路由表向数据包提供下一跳信息,然后数据包最终到达目的地。这就是 IP转发的 工作原理。它是第3层协议。

MPLS转发不同于IP转发,因为代替IP地址,转发是基于分组上存在的标签完成的,因此称为标签交换。它是多协议的,因为它支持多种协议,如Internet协议(IP),异步传输模式(ATM)和帧中继网络协议。我们稍后会看到MPLS转发是如何完成的。

如果熟悉计算机网络,则必须知道TCP / IP模型中有5个层。MPLS层位于模型的第2层和第3层之间,即数据链路和网络层。这就是为什么它也被称为2.5层协议或“垫片”协议。

MPLS报头为32位。它包含以下信息: -

现在我们将看到典型的MPLS网络如何:

MPLS网络包含标签交换路由器(LSR)。这些路由器能够理解MPLS标签以及接收和发送带标签的数据包。

MPLS网络中存在三种标签交换路由器: -

入口和出口也称为边缘路由器

因此,在任何特定路由器处,标签的三个步骤PUSH,POP或SWAP中的任何一个发生。

标签交换路径(LSP)

标签交换路径(LSP)可以定义为在MPLS网络内传输分组的标签交换路由器(LSR)的序列。基本上,LSP是数据包在传输过程中所采用的预定义路径。LSP中的第一个LSR是Ingress LSR,类似LSP中的最后一个LSR是Egress路由器,其后是中间的LSR。

这里的主要内容是,在IP转发中,没有固定路径,数据包必须遵循,而在MPLS转发中,我们预定义路径,即在数据包传输过程中必须遵循的LSP。

MPLS转发

因此,现在我们可以很容易地看到如何在网络中转发MPLS数据包,并结合我们学到的上述概念。

当网络数据包进入MPLS网络时,入口路由器会在其上面放置一个标签。该标签对应于分组需要遵循的特定路径,即LSP。不同的LSP对应不同的标签栈。使用诸如标签分发协议(TDP),标签分发协议(LDP)和资源预留协议(RSVP)的不同协议来分发标签。

与IP转发一样,每个路由器在MPLS网络中类似地包含路由表,每个LSR包含标签转发信息库(LFIB)。此信息库指导LSR将标签与其相应的传出标签交换,从而允许数据包通过网络传输。这里的主要内容是路由器只需要在传入数据包的顶部看到标签,它不关心数据包内存在的IP地址(源和目标),从而允许更快地通过网络路由。

以下是LFIB中存在的信息的示例

在LSP的末尾,Egress LSR弹出数据包的标签,数据包被路由为普通的IP数据包。

这是高级视图如何进行MPLS转发以深入了解您可以参考 <a href="https://doc.lagout.org/network/Cisco/CCIE/CCIE%20SP/CiscoPress%20-%20MPLS%20Fundamentals.pdf" style="box-sizing: inherit; text-decoration-line: none; -webkit-tap-highlight-color: transparent; background-repeat: repeat-x; background-image: url("data:image/svg+xml;utf8,"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);"> CISCO MPLS基础书籍

制作MPLS数据包

转到下一部分,我们将在这里看到如何使用Golang创建MPLS数据包。为什么Golang?因为它具有高度可扩展性,具有内置的并发性和对服务器端编程的强大支持,并且还具有一组很棒的库。我们将使用 <a href="https://github.com/google/gopacket" style="box-sizing: inherit; text-decoration-line: none; -webkit-tap-highlight-color: transparent; background-repeat: repeat-x; background-image: url("data:image/svg+xml;utf8,"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);"> GoPacket 库来制作数据包。

所以这里是代码

package main    
import (    
"fmt"    
"net"    
"encoding/hex"    
"github.com/google/gopacket"    
"github.com/google/gopacket/layers"    
)    
func getMplsPacket() []byte {    
ipaddr := net.ParseIP("1.1.1.1")    
payload := gopacket.Payload("payload")    
udp := &layers.UDP{SrcPort: layers.UDPPort(2000), DstPort: layers.UDPPort(3000)}    
ip := &layers.IPv4{Version: 4, DstIP: ipaddr, SrcIP: ipaddr, Protocol: layers.IPProtocolUDP}    
hw, _  := net.ParseMAC("c8:b3:02:c0:b9:1b")    
eth := &layers.Ethernet{SrcMAC: hw, DstMAC: hw, EthernetType: 0x8847}    
mpls := &layers.MPLS{    
Label:        17,    
TrafficClass: 0,    
StackBottom:  true,    
TTL:          64,    
}    
if err := udp.SetNetworkLayerForChecksum(ip); err != nil {    
return nil    
}    
buffer := gopacket.NewSerializeBuffer()    
if err := gopacket.SerializeLayers(buffer,    
gopacket.SerializeOptions{ComputeChecksums: true, FixLengths: true},    
eth, mpls, ip, udp, payload); err != nil {    
return nil    
}    
str := hex.EncodeToString(buffer.Bytes())    
fmt.Println(str)    
return buffer.Bytes()    
}    
func main() {    
fmt.Println(getMplsPacket())    
}

代码是不言自明的,我们正在为IP,UDP,Payload,MPLS和以太网创建单独的层,并按以下顺序将这些层堆叠在一起并返回创建的字节对象。

MPLS数据包层堆栈

如果我们执行上面的代码,我们将获得以下输出

c8b302c0b91bc8b302c0b91b88470001114045000023000000000011b6c7010101010101010107d00bb8000f2b157061796c6f616400000000000000

这是形成的数据包的输出,我们可以使用 <a href="https://hpd.gasmi.net/" style="box-sizing: inherit; text-decoration-line: none; -webkit-tap-highlight-color: transparent; background-repeat: repeat-x; background-image: url("data:image/svg+xml;utf8,"); background-size: 1px 1px; background-position: 0px calc(1em + 1px);"> https://hpd.gasmi.net/ 或Wireshark 等在线工具解码数据包。

对上述数据包进行解码会得到预期的以下结果。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章