- 論壇徽章:
- 1
|
最近在做linux 網(wǎng)橋的相關(guān)配置測(cè)試,發(fā)現(xiàn)ebtables的redirect target 不能把帶vlan的信息的skb傳到三層,其分析過(guò)程如下
環(huán)境:
linux 內(nèi)核版本:3.14.31
機(jī)器有兩個(gè)網(wǎng)卡分別是eth2,eth3,兩個(gè)網(wǎng)卡作為網(wǎng)橋br0的端口,
而且這個(gè)兩個(gè)端口接著都是交換機(jī)的trunk口,就是通過(guò)br0的幀都打了vlan tag, 可以帶不同的vlan id
ebtables的規(guī)則如下
-A BROUTING -p 802_1Q --vlan-encap IPv4 -j redirect --redirect-target DROP
當(dāng)帶著vlan 信息的ip包過(guò)來(lái)的時(shí)候,碰到上面的ebtables規(guī)則,數(shù)據(jù)包經(jīng)過(guò)的路徑如下
netif_receive_skb( )->skb_vlan_untag( )->br_handle_frame( )->ebt_broute( )->ebt_do_table( )->ebt_redirect_tg( )->netif_receive_skb( )->ip_rcv( )
skb_vlan_untag( ) 會(huì)把802.1q的vlan tag的信息,放到 skb->vlan_tci 和skb->vlan_proto 這兩個(gè)值中,這時(shí)候, vlan_tx_tag_present(skb) 就會(huì)為真
ebt_redirect_tg( ) 這個(gè)函數(shù)會(huì)修改eth_hdr(skb)->h_dest 和skb->pkt_type=PACKET_HOST,讓其在網(wǎng)橋中做bridged 的判斷的時(shí)候,數(shù)據(jù)包能上到上層 ;
ebt_broute ( ) 如果返回 NF_DROP,就是規(guī)則中的標(biāo)準(zhǔn)target ,br_handle_frame 就會(huì)返回RX_HANDLER_PASS 給 netif_receive_skb()這個(gè)函數(shù)
netif_receive_skb 的主要實(shí)現(xiàn)代碼在__netif_receive_skb_core 這個(gè)函數(shù),所以把這個(gè)函數(shù)的代碼的幾個(gè)關(guān)鍵點(diǎn)調(diào)出來(lái)分析了
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc){
..........................
another_round:
skb->skb_iif = skb->dev->ifindex;
__this_cpu_inc(softnet_data.processed);
if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
skb = skb_vlan_untag(skb);
if (unlikely(!skb))
goto unlock;
}
............................................
if (vlan_tx_tag_present(skb)) {
if (pt_prev) {
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = NULL;
}
if (vlan_do_receive(&skb))
goto another_round;
else if (unlikely(!skb))
goto unlock;
}
rx_handler = rcu_dereference(skb->dev->rx_handler);
if (rx_handler) {
if (pt_prev) {
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = NULL;
}
switch (rx_handler(&skb)) { ------------->這里調(diào)用的實(shí)際函數(shù)就是br_handle_frame( )
case RX_HANDLER_CONSUMED:
ret = NET_RX_SUCCESS;
goto unlock;
case RX_HANDLER_ANOTHER:
goto another_round;
case RX_HANDLER_EXACT:
deliver_exact = true;
case RX_HANDLER_PASS:---->當(dāng)broute鏈返回NF_DROP的時(shí)候br_handle_frame 就返回RX_HANDLER_PASS
break;
default:
BUG();
}
if (unlikely(vlan_tx_tag_present(skb))) { -----> 當(dāng)從網(wǎng)橋的相關(guān)代碼返回的時(shí)候,就會(huì)走到這里,如果在網(wǎng)橋的代碼里面沒(méi)有對(duì)skb->vlan_tci 做任何處理的話
------->這個(gè)判斷就會(huì)是真 ,下面的那個(gè)判斷也是一樣 ,因此skb->pkt_type就會(huì)被改成PACKET_OTHERHOST,
if (vlan_tx_tag_get_id(skb)) ----->但是這個(gè)在ebt_redirect_tg()才剛把這把skb->pkt_type改為PACKET_HOST
skb->pkt_type = PACKET_OTHERHOST;
/* Note: we might in the future use prio bits
* and set skb->priority like in vlan_do_receive()
* For the time being, just ignore Priority Code Point
*/
skb->vlan_tci = 0;
}
.....................................
}
如果 skb->pkt_type =PACKET_OTHERHOST, 當(dāng)skb傳到 ip_rcv , 這個(gè)skb會(huì)因?yàn)閟kb->pkt_type 不是PACKET_HOST,而被ip_rcv 丟掉,
上面就是整個(gè)分析過(guò)程,后來(lái)我想想,會(huì)不會(huì)有什么參數(shù)可以讓網(wǎng)橋在skb上傳到上層協(xié)議棧的時(shí)候清空skb->vlan_tci ,找了個(gè)遍,都沒(méi)有找到,
我就在ebt_redirect_tg()中做了個(gè)修改,驗(yàn)證上面的分析,結(jié)果,概率之后skb就真的能上傳到三層了,修改如下
static unsigned int ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ebt_redirect_info *info = par->targinfo;
if (!skb_make_writable(skb, 0))
return EBT_DROP;
if (par->hooknum != NF_BR_BROUTING)
/* rcu_read_lock()ed by nf_hook_slow */
memcpy(eth_hdr(skb)->h_dest,
br_port_get_rcu(par->in)->br->dev->dev_addr, ETH_ALEN);
else
memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN);
skb->pkt_type = PACKET_HOST;
if (unlikely(vlan_tx_tag_present(skb))) { --->加了這個(gè)判斷和清空的操作
skb->vlan_tci = 0;
}
return info->target;
}
有點(diǎn)想不明白的,為什么在__netif_receive_skb_core 中,rx_handle 返回后,要根據(jù)skb是否帶有vlan 信息把skb->pkt_type修改為PACKET_OTHERHOST呢?
難道linux 協(xié)議棧認(rèn)為,都要到三層了,skb中的vlan 信息就沒(méi)用啦,所以傳給三層的skb就應(yīng)該帶vlan 信息的了??如果是這樣的話,那么ebt_redirect_tg()這個(gè)函數(shù)
是不是應(yīng)該考慮一下skb帶vlan信息的情況,然后做處理呢??
另外,我試過(guò)在ebtables的nat表中的PREROUTING 添加一條同樣效果的規(guī)則,一樣存在同樣的問(wèn)題。
后來(lái)查了ebtables 中dnat的代碼,也是一樣的,沒(méi)有考慮skb帶vlan的情況的
發(fā)email到netfilter的maillist,被退信了,寫給代碼的作者又沒(méi)有回復(fù),
大家討論一下吧,到底怎么回事,會(huì)不會(huì)是我有什么地方理解錯(cuò)誤了????
|
|