%20%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%A6%E9%81%A9%E5%88%87%E3%81%AA%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%81%AB%E5%BF%9C%E7%AD%94%E3%81%99%E3%82%8B%E3%81%AE%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%81%8B%3F.png)
カーネルのソースコードを見ると、ARP要求を処理するときにnet_device
が から直接取得されskb
、その後、応答がそのデバイスに送信されるようです(arp.c#L679):
static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
...
arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
sip, dev, tip, sha,
dev->dev_addr, sha,
reply_dst);
}
しかし、パケットがブリッジを通過してskb
デバイスに到達した場合ブリッジデバイスで上書きされました:
static int br_pass_frame_up(struct sk_buff *skb)
{
...
skb->dev = brdev;
...
}
何らかの方法で元のデバイスを取得し、そこに応答を送信するべきではないでしょうか?
答え1
フレームがブリッジポートから到着した場合、それはフレッシュブリッジFDBエントリこの MAC アドレスにフレームを送信するときに、同じブリッジ ポートを使用するように指示します。応答は、クエリが到着した同じブリッジ ポートに送信されます。
したがって、ARP 層の観点からは、パケットはブリッジ インターフェイスで受信され、応答もブリッジ インターフェイスで送り返されます。
応答が下位層であるブリッジに到達すると、ブリッジコードは転送データベース(別名フィボナッチ) を実行し、すべてのポートに応答をフラッディングするのではなく、以前の着信ブリッジ ポートを送信ブリッジ ポートとして選択します (最近のエントリが見つかるため)。
netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { ... } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) { br_forward(dst->dst, skb, false, true); } else { br_flood(br, skb, BR_PKT_UNICAST, false, true);
前と逆のことを行うと、skb のデバイス ブリッジ インターフェイスがブリッジ ポートで上書きされます。
static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb, bool local_orig) { ... skb->dev = to->dev; ...