Linux
套接字綁定到設備時macvlan介面之間的通信問題
我有一個 Linux 設置,其中模式橋接中的兩個 macvlan 介面被添加到同一個物理介面上,在同一個 IP 子網中:
ip link add link eth2 dev mvl0 type macvlan mode bridge ip link add link eth2 dev mvl1 type macvlan mode bridge ip addr add 192.168.42.16/24 dev mvl0 ip addr add 192.168.42.17/24 dev mvl1 ip link set dev mvl0 up ip link set dev mvl1 up
我想在綁定到介面的套接字之間進行通信
mvl0
並mvl1
使用它們,但這不起作用。例如,# ping -I mvl0 192.168.42.17
沒有得到任何回复。我可以看到核心嘗試在 ARP 上執行 ARP
lo
,但這不起作用,因為它沒有得到回复。
- 有沒有辦法使這項工作,例如通過操縱路由或鄰居表?
- 這應該被認為是 Linux 核心中的錯誤嗎?畢竟
macvlan
模式下的介面bridge
應該是可以互相看到的。(*背景:*這是兩個嵌入式設備在同一個程序上下文中執行的模擬。我們的框架總是將套接字綁定到介面,以確保通信真正通過所需的介面。通信通常通過 UDP。)
(編輯:以前的版本只適用於傳出數據包(UDP),這個版本適用於兩個方向(TCP和ping)。)
像您這樣的設置有各種陷阱:Linux 將具有與網路介面地址匹配的源地址的傳入數據包視為路由錯誤(因為在正常情況下它表示路由循環)。此外,預設情況下,核心維護的
local
路由表具有最高優先級,這將防止您的數據包從它所綁定的介面發出。可以解決策略路由的第二個問題:首先,刪除重疊的路由(只會造成麻煩):
ip route list # overlapping routes should look like: ip route del 192.168.42.0/24 dev mvl0 proto kernel scope link src 192.168.42.16 ip route del 192.168.42.0/24 dev mvl1 proto kernel scope link src 192.168.42.17
接下來,給
local
表格一個較低的優先級(較高的數值):ip rule add pref 1000 lookup local ip rule del pref 0
我們需要通過將傳入的數據包發送到
local
表中來接受它們:ip rule add pref 100 to 192.168.42.16 iif mvl0 lookup local ip rule add pref 100 to 192.168.42.17 iif mvl1 lookup local
而所有其他(傳出)數據包到相應的。destination 將使用一個特殊的表來強制它們在另一個界面中出現:
ip rule add pref 200 to 192.168.42.17 lookup 100 ip rule add pref 200 to 192.168.42.16 lookup 101 ip route add default dev mvl0 table 100 ip route add default dev mvl1 table 101
此外,我們必須通過禁用反向路徑過濾(如果尚未禁用)並允許接受具有本地源的數據包來解決第一個問題:
echo "0" | tee /proc/sys/net/ipv4/conf/mvl{0,1}/rp_filter echo "1" | tee /proc/sys/net/ipv4/conf/mvl{0,1}/accept_local
ping
即使未綁定到其中一個mvl
介面,現在也可以使用。TCP 和 UDP 也可以工作,測試socat
:socat TCP4-LISTEN:9998,so-bindtodevice=mvl0 - echo foo | socat - TCP4:192.168.42.16:9998,so-bindtodevice=mvl1 socat UDP4-RECV:9900,so-bindtodevice=mvl0 - echo foo | socat - UDP4-SENDTO:192.168.42.16:9900,so-bindtodevice=mvl1