




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、#1 Linux網(wǎng)橋?qū)崿F(xiàn)分析-第三部份,STP的實(shí)現(xiàn)分析初步Linux網(wǎng)橋?qū)崿F(xiàn)分析作者:kendo版權(quán)所有,轉(zhuǎn)載請(qǐng)注冊(cè)出處第三部份,STP的實(shí)現(xiàn)分析初步一、STP的框架結(jié)構(gòu)STP發(fā)送的是wikiBPDU/wiki包,該包有所有兩種類型:配置和TCN(拓樸變更通知);對(duì)于BPDU包的處理,有兩種:接收和發(fā)送(廢話),對(duì)于配置類型的BPDU包的發(fā)送,它是靠定時(shí)器來完成的,參BPDU包的幾個(gè)定時(shí)器參數(shù);對(duì)于wikiTCP/wiki類型的BPDU包的發(fā)送,從名字可以看出來,它是當(dāng)發(fā)現(xiàn)拓樸結(jié)構(gòu)發(fā)生變更時(shí)發(fā)送的,如本機(jī)網(wǎng)橋配置的變化,物理接口的變動(dòng),分析其它機(jī)器變動(dòng)后發(fā)出來的STP包
2、等等。BPDU的封包采用的是IEEE802封包(本想把封包結(jié)構(gòu)的圖片貼上來,找不著在哪兒上傳圖片)。前面分析過, br_handle_frame函數(shù)中,當(dāng)網(wǎng)橋開啟了STP,且根據(jù)目的物理地址判斷出這是一個(gè)STP包,則交給br_stp_handle_bpdu函數(shù)處理。br_stp_handle_bpdu函數(shù)主要是判斷是哪種類型的BPDU包,然后調(diào)用相關(guān)的處理函數(shù),即:if(type=config) br_received_config_bpdu();else if(type=tcn) br_received_tcn_bpdu();這是對(duì)接收到B
3、PDU包的處理,關(guān)于config類型的BPDU包的發(fā)送,后面再分析;TCN包的發(fā)送,有一部份是在接收包處理過程中處理的(因?yàn)榉治鯿onfig類型的BPDU包的時(shí)候,發(fā)現(xiàn)拓樸變更,當(dāng)然要發(fā)送TCN包了),所以這里一起來分析。二、Config類型的BPDU包的接收處理這個(gè)處理過程是在拆完BPDU包后,調(diào)用br_received_config_bpdu函數(shù)完成的。還是得先交待一些理論的東西:STPwiki協(xié)議/wiki最終是為了在網(wǎng)絡(luò)中生成一棵無環(huán)狀的樹,以期消除廣播風(fēng)暴以及單播數(shù)據(jù)幀對(duì)網(wǎng)絡(luò)的影響。它始終在選舉三樣?xùn)|東:1、根網(wǎng)橋;2、根端口;3、“指定端口”和“指定網(wǎng)橋”(這三個(gè)概念非常重要,如果
4、你還不清楚,建議查閱相關(guān)文檔先,否則下邊的代碼分析也無從談起了)然后再根據(jù)選舉出來的這三個(gè)東東,確定端口的狀態(tài):阻塞、轉(zhuǎn)發(fā)、學(xué)習(xí)、監(jiān)聽、禁用要選舉出這三樣?xùn)|東,得有一個(gè)判斷標(biāo)志,即算法,STP的判斷標(biāo)準(zhǔn)是:1、判斷根橋ID,以最小的為優(yōu);2、判斷到根橋的最小路徑開銷;3、確定最小發(fā)送發(fā)BID(Sender BID)4、確定最小的端口ID如果前面你查閱了BPDU的封包結(jié)構(gòu),根橋ID、最小路徑開銷、發(fā)送方網(wǎng)橋的ID、端口ID這幾個(gè)概念應(yīng)該沒有問題了,不過這里還是簡單交一下:1、根橋ID,我們配置了網(wǎng)橋后,用brctl命令會(huì)發(fā)現(xiàn)8000.XXXXXX這樣一串,這就是網(wǎng)橋的ID號(hào),用一標(biāo)識(shí)每一個(gè)網(wǎng)橋,
5、后面的XXXX一般的橋的MAC地址,這樣ID值就不會(huì)重復(fù)。根橋ID,是指網(wǎng)絡(luò)中所有網(wǎng)橋的ID值最小的那一個(gè),對(duì)應(yīng)的具有根橋ID的橋,當(dāng)然也是網(wǎng)絡(luò)的根橋了;2、最小路徑開銷動(dòng)態(tài)路由中也類似這個(gè)概念,不過這里用的不是跳數(shù)(局域網(wǎng)不比廣域網(wǎng),不一定跳數(shù)大就慢,比如跳數(shù)小,是10M鏈路,跳數(shù)大的卻是千兆鏈路),最初的開銷定義為1000M/鏈種帶寬,當(dāng)然,這種方式不適用于萬兆網(wǎng)了所以后來又有一個(gè)新的,對(duì)每一種鏈路定義一個(gè)常數(shù)值詳請(qǐng)請(qǐng)查閱相關(guān)資料;3、發(fā)送方ID網(wǎng)橋之前要收斂出一個(gè)無環(huán)狀拓樸,就需要互相發(fā)送BPDU包,當(dāng)然需要把自己的ID告訴對(duì)方,這樣對(duì)方好拿來互相比較;4、端口ID端口ID由優(yōu)先級(jí)+端口
6、編號(hào)組成,用于標(biāo)識(shí)某個(gè)橋的某個(gè)端口,后面比較時(shí)好用。生成樹算法就是利用上述四個(gè)參數(shù)在判斷,判斷過程總是相同的:1、確定根橋,橋ID最小的(即把包中的橋ID,同自己以前記錄的那個(gè)最小的橋ID相比,機(jī)器加電時(shí),總是以自己的橋ID為根橋ID)的為根橋;2、確定最小路徑開銷;3、確定最小發(fā)送方ID;4、確定最小的端口ID:這四步非常地重要,后面的所以比較都是這四個(gè)步驟。有了這些概念,來看看對(duì)config類型的BPDU包的處理:void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
7、; struct net_bridge *br; int was_root; if (p->state = BR_STATE_wikiDIS/wikiABLED) return;
8、br = p->br; read_lock(&br->lock); /*自己是根橋嗎?用自己的br_ID和BPDU包中的根ID相比較*/ was_root = br_is_root_bridge(br); /
9、*比橋BPDU包中的信息(bpdu)和原先的對(duì)應(yīng)的信息(p),如果需要更新,返回1,相同返回0,不需更新返回-1*/ if (br_supersedes_port_info(p, bpdu) /*刷新自己的相關(guān)信息*/ br_record_config_infor
10、mation(p, bpdu); /*進(jìn)行root_bridge、port的選舉*/ br_configuration_update(br); /*設(shè)置端口狀態(tài)*/
11、60; br_port_state_selection(br);以上這一段的邏輯概念很簡單:1、把收到的BPDU包中的參數(shù)同自己原先記錄的相比較,(遵循前面說的四個(gè)比較步驟),以判斷是否需要進(jìn)行更新br_supersedes_port_info(p, bpdu)。2、如果判斷需要進(jìn)行更新,即上述四個(gè)步驟中,有任意一項(xiàng)有變動(dòng),則刷新自己的保存記錄:br_record_config_information(p, bpdu);3、因?yàn)橛凶儎?dòng),就需要改變自己的配置了:br_configuration_update(br);即
12、前面說的,根據(jù)四步判斷后選舉根橋(注:根橋不是在這里選舉的,前文說過,它是定時(shí)器定時(shí)發(fā)送BPDU包,然后收到的機(jī)器只需改變自己的記錄即可)、根端口、指定端口;4、設(shè)置物理端口的轉(zhuǎn)發(fā)狀態(tài):br_port_state_selection2.1 br_supersedes_port_info(p, bpdu)/* called under bridge lock */static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
13、160; int t;/*第一步*/ t = memcmp(&bpdu->root, &p->designated_root, ; if (t < 0) return 1; else if (t >
14、 0) return 0;/*第二步*/ if (bpdu->root_path_cost < p->designated_cost) return 1; else if (
15、bpdu->root_path_cost > p->designated_cost) return 0;/*第三步,要同兩個(gè)橋ID比:已記錄的最小發(fā)送ID和自己的ID*/ t = memcmp(&bpdu->bridge_id, &p->designated_bridge, ;
16、0;if (t < 0) return 1; else if (t > 0) return 0; if (memcmp(&bpdu->bridge_id, &
17、p->br->bridge_id, ) return 1;/*第四步*/ if (bpdu->port_id <= p->designated_port) return 1;
18、; return 0;2.2 br_record_config_information如果檢測(cè)到有變動(dòng),則刷新自己的記錄先:/* called under bridge lock */static void br_record_config_information(struct net_bridge_port *p, struct br_config_bpdu *bpdu) p->designated_root = bpdu->root;
19、; p->designated_cost = bpdu->root_path_cost; p->designated_bridge = bpdu->bridge_id; p->designated_port = bpdu->port_id;/*設(shè)置時(shí)間戳,關(guān)于STP的時(shí)間處理,后面來分析*/ br_timer_set(&p
20、->message_age_timer, jiffies - bpdu->message_age);p對(duì)應(yīng)的四個(gè)成員的概念對(duì)照BPDU封包結(jié)構(gòu),不難理解其含義: p->designated_root: 指定的根網(wǎng)橋的網(wǎng)橋ID p->designated_cost :
21、60; 指定的到根橋的鏈路花銷 p->designated_bridge: 指定的發(fā)送當(dāng)前BPDU包的網(wǎng)橋的ID p->designated_port:
22、 指定的發(fā)送當(dāng)前BPDU包的網(wǎng)橋的端口的ID2。3 br_configuration_update前面說過,根橋的選舉不是在這里進(jìn)行,這里進(jìn)行根端口和指定端口的選舉/* called under bridge lock */void br_configuration_update(struct net_bridge *br) b
23、r_root_selection(br);/*選舉根端口*/ br_designated_port_selection(br);/*選舉指定端口*/2.3.1 根端口的選舉br_root_selection根端口的選舉同樣是以上四個(gè)步驟,只是有一點(diǎn)小技巧:它逐個(gè)遍歷橋的每一個(gè)所屬端口,找出一個(gè)符合條件的,保存下來,再用下一個(gè)來與之做比較,用變量root_port 來標(biāo)志:/* called under bridge lock */static void br_root_selection(struct net_bridg
24、e *br) struct net_bridge_port *p; int root_port; root_port = 0;/*獲得橋的所屬端口列表*/ p = br->port_list;/*這個(gè)循環(huán)非常重要,它遍歷橋的每一個(gè)端口,進(jìn)行以上四步判斷,找到一個(gè),將其“保存”下來,然后再用下一個(gè)與
25、保存的相比較,直至遍歷完,找到最優(yōu)的那個(gè),這個(gè)“保存”打了引號(hào),是因?yàn)樗鼉H僅是記當(dāng)了端口編號(hào):root_port = p->port_no;,然后再將其傳遞給比較函數(shù)br_should_become_root_port*/ while (p != NULL) if (br_should_become_root_port(p, root_port)
26、 root_port = p->port_no; p = p->next; br->root_port = root_port;/*找完
27、了還沒有找到,則認(rèn)為自己就是根橋*/ if (!root_port) br->designated_root = br->bridge_id; br->root_path_cost = 0;
28、160; /*否則記錄相應(yīng)的值*/ else p = br_get_port(br, root_port); br->designated_root = p->designated_ro
29、ot; br->root_path_cost = p->designated_cost + p->path_cost; br_should_become_root_port函數(shù)用以判斷端口p是否應(yīng)該變成根端口,與它相比較的是原來那個(gè)根端口,函數(shù)第二個(gè)參數(shù)則為此的ID號(hào),在函數(shù)中調(diào)用 br_get_port獲取該端口:/* called under bridge lock */
30、static int br_should_become_root_port(struct net_bridge_port *p, int root_port) struct net_bridge *br; struct net_bridge_port *rp; int t; br = p->br;
31、/*若當(dāng)前端口是關(guān)閉狀態(tài)或?yàn)橐粋€(gè)指定端口,則不參與選舉,返回*/ if (p->state = BR_STATE_DISABLED | br_is_designated_port(p) return 0;/*在根端口的選舉中,根橋是沒有選舉權(quán)的*/
32、 if (memcmp(&br->bridge_id, &p->designated_root, <= 0) return 0;/*沒有指定等比較的端口ID(因?yàn)榈谝淮嗡跏蓟癁?的)*/ if (!root_port)
33、0; return 1;/*獲取待比較的根端口*/ rp = br_get_port(br, root_port);/*又是四大步,像打藍(lán)球*/ t = memcmp(&p->designated_root, &rp->designated_root, ; if (t < 0)
34、 return 1; else if (t > 0) return 0; if (p->designated_cost + p->path_cost < &
35、#160; rp->designated_cost + rp->path_cost) return 1; else if (p->designated_cost + p->path_cost >
36、160; rp->designated_cost + rp->path_cost) return 0; t = memcmp(&p->designated_bridge, &rp->designated_bridge, ; if (t < 0)
37、; return 1; else if (t > 0) return 0; if (p->designated_port < rp->designated_port)
38、 return 1; else if (p->designated_port > rp->designated_port) return 0; if (p->port_id <
39、 rp->port_id) return 1; return 0;這樣,遍歷完成后,根端口就被選出來了。2。3。2 指定端口的選舉br_designated_port_selection/* called under bridge lock */static void br_designated_port_selection(struct net_bridge *br)
40、160; struct net_bridge_port *p; p = br->port_list; while (p != NULL) if (p->state != BR_STATE_DISABLED &&
41、0; br_should_become_designated_port(p) br_become_designated_port(p);
42、 p = p->next; 事實(shí)上這個(gè)過程與根端口的選舉過程極為類似,沒有分析的必要了!2。3。3 端口狀態(tài)選擇/* called under bridge lock */void br_port_state_selection(struct net_bridge *br) struct net_bridge_port *p; p = br->port
43、_list; while (p != NULL) if (p->state != BR_STATE_DISABLED) if (p->port_no = br->roo
44、t_port) p->config_pending = 0; &
45、#160; p->topology_change_ack = 0; br_make_forwarding(p);
46、0; else if (br_is_designated_port(p) br_timer_clear(&p->message_age_timer);
47、0; br_make_forwarding(p); else
48、0; p->config_pending = 0; p->topology_change_ack = 0;
49、0; br_make_blocking(p);
50、; p = p->next; 函數(shù)的邏輯結(jié)構(gòu)也很簡單:遍歷整個(gè)橋所屬端口:while (p != NULL)如果端口已經(jīng)DISABLED,則沒有判斷的必要了:p->state != BR_STATE_DISABLED如果端口是根端口,或者是指定端口,就讓讓它forwarding,否則就讓它blocking:
51、; if (p->port_no = br->root_port) p->config_pending = 0;
52、160; p->topology_change_ack = 0; br_make_forwarding(p);
53、; else if (br_is_designated_port(p) br_timer_clear(&p->messa
54、ge_age_timer); br_make_forwarding(p); else
55、; p->config_pending = 0; p-&
56、gt;topology_change_ack = 0; br_make_blocking(p); /* call
57、ed under bridge lock */static void br_make_forwarding(struct net_bridge_port *p) if (p->state = BR_STATE_BLOCKING) printk(KERN_INFO "%s: port %i(%s) entering %s staten",
58、160; p->br->, p->port_no, p->dev->name, "listening"); p->state = BR_STATE_LISTENING;
59、 br_timer_set(&p->forward_delay_timer, jiffies); /* called under bridge lock */static void br_make_blocking(struct net_bridge_port *p) if (p->state != BR_STATE_DISABLED &&
60、0; p->state != BR_STATE_BLOCKING) if (p->state = BR_STATE_FORWARDING | p->state = BR_STATE_
61、LEARNING) br_topology_change_detection(p->br); printk(KERN_INFO "%s: port %i(%s) entering %s staten",
62、; p->br->, p->port_no, p->dev->name, "blocking"); p->state = BR_STATE_BLOCKING;
63、0; br_timer_clear(&p->forward_delay_timer); 都是設(shè)置p->state 相應(yīng)狀態(tài)位就可以了! 三、選舉完成之后實(shí)在不會(huì)取名字了,前面分析了br_received_config_bpdu中前面的判斷、刷新、選舉、設(shè)置端口狀態(tài)的過程,然而,如果橋認(rèn)為當(dāng)前這個(gè)BPDU是一個(gè)“最優(yōu)的”(即符合前面判斷四步中的某一步),所作的動(dòng)作不止于此:1、如果因?yàn)檫@個(gè)BPDU導(dǎo)致拓樸變化了,如自己以前是根橋,現(xiàn)在不是了,需要發(fā)送T
64、CN包,進(jìn)行通告;2、需要把這個(gè)BPDU包繼續(xù)轉(zhuǎn)發(fā)下去(如果自己收到數(shù)據(jù)的端口是根端口的話,那么就有可能有許多交換機(jī)(網(wǎng)橋)串在自己的指定端口下邊,總得把這個(gè)包能過指定端口再發(fā)給它們吧,否則交換機(jī)就不叫交換機(jī)了)指下來繼續(xù)看代碼:/*前面說的第1步*/ if (!br_is_root_bridge(br) && was_root)
65、160; br_timer_clear(&br->hello_timer); if (br->topology_change_detected)
66、0; br_timer_clear(&br->topology_change_timer); br_transmit_tcn(br); &
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 農(nóng)村公路養(yǎng)護(hù)部門加強(qiáng)財(cái)務(wù)管理工作的對(duì)策實(shí)踐探究
- 煙草一號(hào)工程中DB2的性能優(yōu)化及應(yīng)用性研究
- 農(nóng)莊餐廳租賃合同范例
- fob英文合同范例
- 2025屆高考數(shù)學(xué)大二輪復(fù)習(xí)層級(jí)二專題二三角函數(shù)及解三角形第2講三角恒等變換與解三角形教學(xué)案
- 農(nóng)村收購木材合同范例
- 農(nóng)業(yè)訂單生產(chǎn)合同范例
- 倉庫供貨合同范例
- 業(yè)主拍照物業(yè)合同范本
- 書驗(yàn)收合同范例范例
- 中小學(xué)生心理健康檔案(表格)電子教案
- 廣東省五年一貫制語文考試題目
- 江蘇省南京市2023屆高三第一學(xué)期期初考試英語試題和答案
- 10kV電力線路改造工程量清單
- 紅樓春趣劇本新編
- FLUX系統(tǒng)用戶手冊(cè)
- WB/T 1066-2017貨架安裝及驗(yàn)收技術(shù)條件
- GB/T 40806-2021機(jī)床發(fā)射空氣傳播噪聲金屬切削機(jī)床的操作條件
- 打起手鼓唱起歌二聲部改編簡譜
- 新外研版高二英語選擇性必修二unit6 PlanB life on Mars 課件
- 電除顫完整版課件
評(píng)論
0/150
提交評(píng)論