Linux
arp_process() 如何回復正確的設備?
查看核心原始碼,我看到在處理 ARP 請求時,直接
net_device
從skb
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; ... }
不應該是如何檢索原始設備並在那裡發送回复嗎?
如果幀從橋接埠到達,這意味著現在有一個新的橋接 fdb 條目告訴在向此 MAC 地址發送幀時使用同一橋接埠:回復將發送到查詢到達的同一橋接埠。
所以從 ARP 層的角度來看,數據包是在網橋介面上接收的,並且應答也在網橋介面上發回。
當回復到達較低層時:bridge,即在其轉發數據庫(又名FIB)中進行查找並選擇前一個傳入網橋埠作為傳出網橋埠的網橋程式碼,而不是將答案泛洪到其所有埠(因為那裡是這樣一個最近的條目被發現):
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; ...