W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
一個多播報文是一個會被多個主機(jī)接收的網(wǎng)絡(luò)報文, 但不是所有主機(jī). 這個功能通過給一組主機(jī)分配特殊的硬件地址來獲得. 發(fā)向一個特殊地址的報文應(yīng)當(dāng)被那個組當(dāng)中的所有主機(jī)接收. 在以太網(wǎng)的情況下, 一個多播地址在目的地址的第一個字節(jié)的最低位為 1, 而每個設(shè)備板在它自己的硬件地址的這一位上為 0.
處理主機(jī)組和硬件地址的技巧由應(yīng)用程序和內(nèi)核處理, 接口驅(qū)動不必處理這個問題.
多播報文的傳送是一個簡單問題, 因為它們看起來就如同其他的報文. 接口發(fā)送它們通過通訊媒介, 不查看目的地址. 內(nèi)核必須要安排一個正確的硬件目的地址; hard_header 設(shè)備方法, 如果定義了, 不必查看它安排的數(shù)據(jù).
內(nèi)核來跟蹤在任何給定時間對哪些多播地址感興趣. 這個列表可能經(jīng)常改變, 因為它是在任何給定時間和按照用戶意愿運行的應(yīng)用程序的功能. 驅(qū)動的工作是接收感興趣的多播地址列表并遞交給內(nèi)核任何發(fā)向這些地址的報文. 驅(qū)動如何實現(xiàn)多播列表是依賴于底層硬件是如何工作的. 典型地, 在多播的角度上, 硬件屬于 3 類中的 1 種:
不能處理多播的接口. 這樣的接口要么接收特別地發(fā)向它們的硬件地址(加上廣播報文)的報文, 要么接收每一個報文. 它們只能通過接收每一個報文來接收多播報文, 因此, 潛在地壓垮操作系統(tǒng), 使用大量的"不感興趣"報文. 你不經(jīng)常認(rèn)為這樣的接口是有多播能力的, 驅(qū)動不會在 dev->flags 設(shè)置 IFF_MULTICAST.
點對點接口是特殊情況, 因為它們一直接收每個報文, 不進(jìn)行任何硬件過濾.
能夠區(qū)別多播報文和其他報文(主機(jī)到主機(jī), 或者廣播). 這些接口能夠被命令來接收每個多播報文, 讓軟件決定地址是否是主機(jī)感興趣的. 這種情況下的開銷是可接受的, 因為在一個典型網(wǎng)絡(luò)上的多播報文的數(shù)目是少的.
可以進(jìn)行硬件檢測多播地址的接口. 可以傳遞一個多播地址的列表給這些接口, 這些地址的報文接收, 并忽略其他多播地址的報文. 對內(nèi)核這是優(yōu)化的情況, 因為它不浪費處理器時間來丟棄接口收到的"不感興趣"的報文.
內(nèi)核盡力利用高級接口的能力, 通過支持第 3 種設(shè)備類型, 它是最通用的. 因此, 內(nèi)核通知驅(qū)動, 在任何有效多播地址列表發(fā)生改變時, 并且它傳遞新的列表給驅(qū)動, 因此它能夠根據(jù)新的信息來更新硬件過濾器.
對多播報文的支持有幾項組成:一個設(shè)備方法, 一個數(shù)據(jù)結(jié)構(gòu), 以及設(shè)備標(biāo)識:
void (dev->set_multicast_list)(struct net_device dev);
設(shè)備方法, 在與設(shè)備相關(guān)的機(jī)器地址改變時調(diào)用. 它也在 dev->flags 被修改時調(diào)用, 因為一些標(biāo)志(例如, IFF_PROMISC) 可能也要求你重新編程硬件過濾器. 這個方法接收一個 struct net_device 指針作為一個參數(shù), 并返回 void. 一個對實現(xiàn)這個方法不感興趣的驅(qū)動可以聽任它為 NULL.
struct dev_mc_list *dev->mc_list;
所有設(shè)備相關(guān)的多播地址的列表. 這個結(jié)構(gòu)的實際定義在本節(jié)的末尾介紹.
int dev->mc_count;
鏈表里的項數(shù). 這個信息有些重復(fù), 但是用 0 來檢查 mc_count 是檢查這個列表的有用的方法.
IFF_MULTICAST
除非驅(qū)動在 dev->flags 中設(shè)置這個標(biāo)志, 接口不會被要求來處理多播報文. 然而, 內(nèi)核調(diào)用驅(qū)動的 set_multicast_list 方法, 當(dāng) dev->flags 改變時, 因為多播列表可能在接口未激活時改變了.
IFF_ALLMULTI
在 dev->flags 中設(shè)置的標(biāo)志, 網(wǎng)絡(luò)軟件來告知驅(qū)動從網(wǎng)絡(luò)上接收所有多播報文. 這發(fā)生在當(dāng)多播路由激活時. 如果標(biāo)志設(shè)置了, dev->ma_list 不該用來過濾多播報文.
IFF_PROMISC
在 dev->flags 中設(shè)置的標(biāo)志, 當(dāng)接口在混雜模式下. 接口應(yīng)當(dāng)接收每個報文, 不管 dev->ma_list.
驅(qū)動開發(fā)者需要的最后一點信息是 struct dev_mc_list 的定義, 在 <linux/netdevice.h>:
struct dev_mc_list { struct dev_mc_list *next; /* Next address in list */
__u8 dmi_addr[MAX_ADDR_LEN]; /* Hardware address */
unsigned char dmi_addrlen; /* Address length */
int dmi_users; /* Number of users */
int dmi_gusers; /* Number of groups */
};
因為多播和硬件地址是獨立于真正的報文發(fā)送, 這個結(jié)構(gòu)在網(wǎng)絡(luò)實現(xiàn)中是可移植的, 每個地址由一個字符串和一個長度標(biāo)識, 就像 dev->dev_addr.
描述 set_multicast_list 的設(shè)計的最好方法是給你看一些偽碼.
下面的函數(shù)是一個典型函數(shù)實現(xiàn)在一個全特性(ff)驅(qū)動中. 這個驅(qū)動是全模式的, 它控制的接口有一個復(fù)雜的硬件報文過濾器, 它能夠持有一個主機(jī)要接收的多播地址表. 表的最大尺寸是 FF_TABLE_SIZE.
所有以 ff_ 前綴的函數(shù)是給特定硬件操作的占位者:
void ff_set_multicast_list(struct net_device *dev) { struct dev_mc_list *mcptr;
if (dev->flags & IFF_PROMISC) {
ff_get_all_packets();
return;
}
/* If there's more addresses than we handle, get all multicast
packets and sort them out in software. */
if (dev->flags & IFF_ALLMULTI || dev->mc_count > FF_TABLE_SIZE) {
ff_get_all_multicast_packets();
return;
}
/* No multicast? Just get our own stuff */
if (dev->mc_count == 0) {
ff_get_only_own_packets();
return;
}
/* Store all of the multicast addresses in the hardware filter */
ff_clear_mc_list();
for (mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next)
ff_store_mc_address(mc_ptr->dmi_addr);
ff_get_packets_in_multicast_list();
}
這個實現(xiàn)可以簡化, 如果接口不能為進(jìn)入報文存儲多播表在硬件過濾器中. 這種情況下, FF_TABLE_SIZE 減為 0, 并且代碼的最后 4 行不需要了.
如同前面提過的, 不能處理多播報文的接口不需要實現(xiàn) set_multicast_list 方法來獲取 dev->flags 改變的通知. 這個辦法可能被稱為一個"非特性的"(nf)實現(xiàn). 實現(xiàn)非常簡單, 如下面代碼所示:
void nf_set_multicast_list(struct net_device *dev)
{
if (dev->flags & IFF_PROMISC)
nf_get_all_packets();
else
nf_get_only_own_packets();
}
實現(xiàn) IFF_PROMISC 是非常重要的, 因為不這樣用戶就不能運行 tcpdump 或任何其他網(wǎng)絡(luò)分析器. 如果接口運行一個點對點連接, 另一方面, 根本沒有必要實現(xiàn) set_multicast_list, 因為用戶接收每個報文.
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: