網絡應用基于容器化部署越來越多,同一主機上采用不同容器來隔離網絡業務,由于當前網絡業務采用的基本都是基于DPDK作為數據平面的開發組件進行報文傳輸,不同的容器之間通過部署不同的DPDK進程來實現各自的業務,為了使得不同容器之間實現通信,所以提供了一種采用內存交換的方式進行報文傳輸,這種傳輸接口叫做memif(shared memory packet interface)。Memif傳輸的報文是原始報文格式,支持配置為Ethernet模式,IP模式,Punt/Inject模式。在VPP(Vector Packet Process)中支持上述三種模式,DPDK只支持Ethernet模式,所以當VPP進程和DPDK進程進行通信時,需要使用Ethernet模式來傳輸報文。Memif接口有兩種身份,master和slave,二者通過unix socket傳遞控制類消息。Master和slave是一一對應關系,一個master對應一個slave,二者擁有相同的id。其中master負責創建socket連接并監聽slave的連接請求,slave負責創建共享內存和初始化共享內存,并主動發起sock連接。
1. Memif基于VPP簡單配置
master配置
[root@4cba99d94a68 /]# vppctl
_______ _ _ _____ ___
__/ __/ _ \ (_)__ | | / / _ \/ _ \
_/ _// // / / / _ \ | |/ / ___/ ___/
/_/ /____(_)_/\___/ |___/_/ /_/
vpp# create interface memif id 0 master
vpp# set interface state memif0/0 up
vpp# set interface ip addr memif0/0 192.168.1.1/24
slave配置
[root@4cba99d94a68 /]# vppctl
_______ _ _ _____ ___
__/ __/ _ \ (_)__ | | / / _ \/ _ \
_/ _// // / / / _ \ | |/ / ___/ ___/
/_/ /____(_)_/\___/ |___/_/ /_/
vpp# create interface memif id 0 slave
vpp# set interface state memif0/0 up
vpp# set interface ip addr memif0/0 192.168.1.2/24
聯通性驗證
vpp# ping 192.168.1.1
116 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=32.0338 ms
116 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=32.0211 ms
116 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=24.6519 ms
116 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=17.2863 ms
2. Memif原理介紹
memif采用unix域套接字來傳遞控制消息,每組memif在socket里面都有一個唯一的id,這個id也是用來識別對端接口的標識。slave接口在創建的時候,會在指定的socket上嘗試連接。socket的監聽進程即master接口所在的進程會提取連接請求,并創建一個連接控制信道,并通過此信道發送hello消息,這條消息包含了一些配置信息。slave收到hello消息之后,會根據消息所帶的配置來調整自己的配置,隨后回復init消息。init消息包含了接口id,監聽進程提取接口id,并將控制信道綁定到對應的接口上,之后回復ack。slave收到ack之后就開始創建內存區域(region)和環形隊列(ring),并針對每個region和ring都發送一條add消息,master收到后需要逐一回復ack。待slave收到最后一條add ring的ack回復之后,就會發送connect消息,表示slave已經準備就緒。master收到此消息之后,會將region映射到自己的地址空間,初始化ring并回復connected消息,之后就能進行數據報文傳輸。如果接口狀態出現異常,無論是master還是slave,都可以隨時發送斷開連接請求。
| Option | Description | Default | Valid value |
|---|---|---|---|
| id=0 | Used to identify peer interface | 0 | uint32_t |
| role=server | Set memif role | client | server|client |
| bsize=1024 | Size of single packet buffer | 2048 | uint16_t |
| rsize=11 | Log2 of ring size. If rsize is 10, actual ring size is 1024 | 10 | 1-14 |
| socket=/tmp/memif.sock | Socket filename | /tmp/memif.sock | string len 108 |
| socket-abstract=no | Set usage of abstract socket address | yes | yes|no |
| owner-uid=1000 | Set socket listener owner uid. Only relevant to server with socket-abstract=no | unchanged | uid_t |
| owner-gid=1000 | Set socket listener owner gid. Only relevant to server with socket-abstract=no | unchanged | gid_t |
| mac=01:23:45:ab:cd:ef | Mac address | 01:23:45:ab:cd:ef | |
| secret=abc123 | Secret is an optional security option, which if specified, must be matched by peer | string len 24 | |
| zero-copy=yes | Enable/disable zero-copy client mode. Only relevant to client, requires ‘–single-file-segments’ eal argument | no | yes|no |
slave非零拷貝 vs slave零拷貝
slave配置成非零拷貝模式時,需要在slave內存空間中單獨開辟一塊內存區域,slave輪詢讀取從master發送過來的報文時,需要將報文從region的buffer中拷到memseg當中,slave往master發送報文時,需要先將報文拷貝到region當中,然后由master輪詢讀取。master去讀寫報文時,始終都需要內存拷貝。
slave配置成零拷貝模式時,buffers直接在slave的memseg上分配,slave進程直接操作buffer描述符即可,無需額外內存拷貝,只需要master進程讀寫報文時進行內存拷貝。
3. 總結
優點:
-
高性能:memif基于共享內存的通信方式,可以在虛擬機和容器之間實現直接內存訪問,從而實現低延遲和高吞吐量的數據傳輸。它提供了一種高效的網絡傳輸機制,適用于需要處理大量數據的應用場景。
-
靈活性:memif接口可用于不同的虛擬化平臺和容器化環境,如KVM、Docker、OpenStack等。這使得它成為構建可擴展和靈活網絡功能的理想選擇。此外,它還支持多個應用程序之間的并發性,可以在同一主機上運行多個虛擬機或容器。
-
安全性:memif通過共享內存實現虛擬機和容器之間的數據傳輸,避免了在物理網絡中傳輸敏感信息的風險。這種機制可以確保數據的機密性和完整性,從而提高系統的安全性。
缺點:
-
配置復雜性:由于memif接口能夠連接多個應用程序,它的配置可能會比較復雜。需要確保正確配置和管理接口參數,以獲得最佳性能和穩定性。
-
限制:雖然memif在提供高性能的數據傳輸方面非常強大,但它可能并不適用于所有場景。在一些特殊情況下,可能需要考慮其他網絡接口類型。