同じIPサブネット上の同じ物理インターフェイスに、ブリッジモードの2つのmacvlanインターフェイスを追加したLinux設定があります。
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 を実行しようとしていることがわかりますが、lo
応答を受け取っていないため動作しません。
たとえば、ルーティングまたはネイバーテーブルを操作してこれを行う方法はありますか?
これをLinuxカーネルのバグと見なすべきですか?結局のところ、
macvlan
モードのインターフェースはbridge
お互いを見ることができるはずです。
(背景:これは、同じプロセスコンテキストで実行される2つの組み込みデバイスのシミュレーションです。私たちのフレームワークは、通信が実際に必要なインターフェイスを通過することを確認するために、常にソケットをインターフェイスにバインドします。通信は通常UDPを介して行われます。 )
答え1
(編集する:以前のバージョンは発信パケット(UDP)でのみ機能しましたが、このバージョンは双方向(TCPとping)で動作します。 )
あなたのような設定にはさまざまな問題があります。 Linuxは、ソースアドレスがネットワークインターフェイスアドレスと一致する受信パケットをルーティングエラーと見なします(通常の状況ではルーティングループを示すため)。また、デフォルトでは、local
カーネルが維持するルーティングテーブルの優先順位が最も高く、パケットがバインドされたインターフェイスの外部に放出されるのを防ぎます。
ポリシー ルーティングは、2 番目の問題を解決できます。まず、重複するパスを削除します(問題のみが発生する可能性があります)。
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
そして、他のすべての(発信)パケットはそのパケットに移動します。ターゲットは特殊テーブルを使用して他のインターフェイスで強制的に終了します。
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
の1つにバインドされていない場合でも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