OVS(Open vSwitch)注包

OVS注包的場景:

UCloud的SDN網路是基於OVS做的。為了進行內網監控,需要測試用戶的兩台雲主機通信是否正常。但是,作為服務方我們是無法登陸到用戶的雲主機的。因此,採用了向源端的OVS中注入一個ping包的方法測試網路是否正常。

基本原理

  • 實驗環境示意圖:實現不登陸進SRC VM的前提下,發送Ping的請求包給DST VM,並捕獲返回的應答包Ping Response。

  • 染色:

用戶有可能自己也會發送Ping包,為了區分用戶的應答包和注入方式得到的應答包,需要對注入的Ping Request進行染色。首先看下ICMP包的格式,如下所示。

黃色標記起來的Identifier欄位含義如下(RFC 792)

The identifier and sequence number may be used by the echo sender to aid in matching the replies with the echo requests

通過設置Identifier的值,可以區分不同的請求對應的應答包。

這裡我們設置Identifier=111,捕獲數據包時,需要指定ICMP包 icmp[4:2]=111,表明ICMP的第四、第五個位元組的值等於111.

  • 注入Ping Request包

需要使用ovs-ofctl packet-out進行注包操作,命令格式如下:

ovs-ofctl packet-out switch in_port actions packet...

說明:

1、packet-out:連接到OVS,並且讓OVS對Packet執行某個Action

Connects to switch and instructs it to execute the OpenFlow actions on each packet

2、switch:交換機的名字,比如實驗環境中的br0

3、in_port:SRC VM連接到OVS的埠號,就是實驗環境示意圖中的In Port

4、packet:數據包,實驗中就是染了色的Ping Request數據包。

5、Action:關鍵是Action的選擇,我們採用的是resubmit,說明如下。resubmit會找到數據包對應的流表,替換掉in_port並執行流表中的Action。

  • resubmit([port],[table]):Re-searches this OpenFlow flow table with the in_port field replaced by port and executes the actions found

  • 捕獲Ping的Response包

採用tcpdump進行捕獲染了色的Ping數據包。命令如下

tcpdump -c 1 -i VIRTUAL_INTERFACE icmp and src host SRC_IP and dst host DST_IP and icmp[4:2]=111

1. VIRTUAL_INTERFACE: 雲主機使用虛擬網卡的名字

2. SRC_IP:源雲主機的IP地址

3. DST_IP:目的雲主機的IP地址

4. 111:染色標記

golang實現的主邏輯

injectICMPCmd = util.GetInjectICMPPacket(srcIp, dstIp, srcMac, dstMac) //構造染了色的Ping Request包,以及注入命令tcpDumpCmd = util.TcpDumpICMPCommand(iface, srcIp, dstIp) //構造tcpdump的抓包命令tcpDumpResponse := make(chan string)srcHostIp := "XXX" //宿主機的IP地址go func() { command := fmt.Sprintf( "ssh %s@%s %s", "root", srcHostIp, tcpDumpCmd) util.SshRunWithChannelResponse(command, tcpDumpResponse)}() // inject Packet into OVStime.Sleep(100 * time.Millisecond)go func() { command := fmt.Sprintf( "ssh %s@%s %s", "root", srcHostIp, injectICMPCmd) util.SshRun(command)}() success := trueselect {case msg := <-tcpDumpResponse: if strings.Contains(msg, dstIp) { fmt.Printf("Checking Success, Response: %s
"
, msg) } else { success = false fmt.Printf("Checking Fail, Response: %s
"
, msg) }}return success

推薦閱讀:

Inside Cisco IOS Software Architecture(第八章,QoS)
浩方等對戰平台的原理是什麼?
怎麼在移動端調試web前端?
蘋果自家的 Web 伺服器和開發語言用的是什麼方案?
Cookie 從哪裡來,網站用它來幹嘛?

TAG:计算机网络 | SDN | 数据包 |