Linux igmp snooping 學習筆記 之一 相應的資料結構與初始化__html

來源:互聯網
上載者:User


一、igmpsnooping相關的資料結構

組播相關的資料結構主要有三個,下面分別分析:

 

1、struct net_bridge_mdb_htable

 

 

/*組播組資料庫轉寄表,該結構體將所有的組播組資料庫轉寄項通過hash數組串連到一起*/

struct net_bridge_mdb_htable

{

       structhlist_head            *mhash; //hash數組,將所有的net_bridge_mdb_entry連結到一起

       structrcu_head                     rcu;

       structnet_bridge_mdb_htable       *old;

       u32                       size; //hash數組中所有hash鏈表中存在的所有net_bridge_mdb_entry項的總數

       u32                       max;//hash數組的最大值

       u32                       secret;

       u32                       ver;

};

 

2、net_bridge_mdb_entry

 

/*一個組播組資料庫轉寄項,描述一個組播組的詳細資料*/

struct net_bridge_mdb_entry

{

       structhlist_node            hlist[2];

       structhlist_node            mglist;

       structnet_bridge           *br;//橋

       structnet_bridge_port_group *ports;//

       structrcu_head                     rcu;

       structtimer_list             timer;//組播組資料庫項失效定時器,若逾時,則會將該組播連接埠從組播組資料庫項的組播連接埠列表中刪除

       structtimer_list             query_timer;//查詢定時

       __be32                         addr;//組播組地址

       u32                       queries_sent;

};

其中port指向所有加入到組播組addr的組播連接埠

mglist用於將通過橋br接收到的igmp 加入報文建立的組播組資料庫轉寄項串連起來

 

3、struct net_bridge_port_group

/*加入一個組播組的組播連接埠資訊結構體*/

struct net_bridge_port_group {

       structnet_bridge_port           *port;//加入該組播組的橋連接埠

       structnet_bridge_port_group *next;//下一個組播組詳細參數結構體(可以有多個連接埠加入到同一個組播組)

       structhlist_node            mglist;

       structrcu_head                     rcu;//rcu表頭

       structtimer_list             timer;//組播連接埠失效定時器,若逾時,則會將該組播連接埠從組播組資料庫項的組播連接埠列表中刪除

       structtimer_list             query_timer;//查詢計時器

       __be32                         addr;//組播組地址,每一個組播連接埠也要一個組播組的原因是,通過這個值可以快速尋找到其關聯的組播組資料庫項

       u32                       queries_sent;//已發送查詢包的次數

};

其中,port鏈表用於將所有加入到組播組addr的對應橋端

Next指向下一個組播連接埠,該下一個組播組地址也為addr,僅僅是port值不同。

其中mglist用於將該組播連接埠加入到port的mglist鏈表中,通過橋連接埠的mglist鏈表,能夠尋找到該橋連接埠加入的所有組播組。

下面是這3個資料結構之間的關係

 

 

二、Igmpsnooping的初始化

Igmp snooping的初始化是使用函數br_multicast_init來實現的,在該函數裡,主要組播組轉寄資料庫表的hash數組的最大值進行設定,設定發送查詢報文的間隔時間,以及發送查詢報文的次數,並初始化橋的igmp查詢的定時器。

void br_multicast_init(struct net_bridge*br)

{

       br->hash_elasticity= 4;//每個組播組 ip中所能關聯的連接埠個數

       br->hash_max= 512; //mdb中hash數組的最大值

 

       br->multicast_router= 1;

       br->multicast_last_member_count= 2;

       br->multicast_startup_query_count= 2;

 

       br->multicast_last_member_interval= HZ;

       br->multicast_query_response_interval= 10 * HZ; //組播查詢最大回複時間

       br->multicast_startup_query_interval= 125 * HZ / 4;  //開啟發送查詢報文的間隔時間

       br->multicast_query_interval= 125 * HZ; //查詢包的發送間隔時間

       br->multicast_querier_interval= 255 * HZ;

       br->multicast_membership_interval= 260 * HZ;

 

       spin_lock_init(&br->multicast_lock);

       setup_timer(&br->multicast_router_timer,

                  br_multicast_local_router_expired, 0);

       setup_timer(&br->multicast_querier_timer,

                  br_multicast_local_router_expired, 0);

       setup_timer(&br->multicast_query_timer,br_multicast_query_expired,

                  (unsigned long)br);

}

 

2、橋與橋連接埠的查詢定時器

對於橋與橋連接埠的查詢定時器,主要是用來實現igmp snooping組播資料庫轉寄表的持續更新的。

 

a)Br橋的查詢定時器

對於定時器br->multicast_query_timer,在開啟igmp snooping功能後就會開啟橋連接埠的組播查詢功能,主要分為如下情況:

i)當br裝置up且開啟igmp snooping時,就會調用函數br_multicast_open,開啟一個立即逾時的查詢定時器

ii) 重新開始igmp snooping時,也會調用函數br_multicast_open,開啟一個立即逾時的查詢定時器。

/*

開啟一個橋的igmpsnooping功能

1、重設發送查詢資料包計數

2、修改橋的查詢定時器

*/

void br_multicast_open(struct net_bridge*br)

{

       br->multicast_startup_queries_sent= 0;

 

       if(br->multicast_disabled)

              return;

 

       mod_timer(&br->multicast_query_timer,jiffies);

}

 

 

當橋的查詢定時器逾時,就會調用函數br_multicast_query_expired進行處理,對於橋裝置,該函數會發送一個組播通用查詢包給上層進行處理,這時如果上層協議棧開啟了igmp proxy功能,就會觸發上層協議棧對lan側的裝置萬用群組播查詢功能。對於上層開啟igmp proxy功能,通過橋的查詢定時器就能對lan側裝置進行周期的通用查詢,然後就可以間接實現igmp snooping組播轉寄資料庫的更新。

 

       對於橋的查詢定時器,因為其需要上層開啟igmp proxy功能,且當上層開啟igmp proxy功能後,如果開啟了igmp snooping功能,就能通過發送通用的組播查詢報文,實現快速的建立組播組資料庫轉寄表。

       從上面的程式可以看出,其是依賴上層是否開啟igmp proxy,而不是直接發送萬用群組播組查詢報文,這樣也滿足了igmp協議的要求,即只有組播組路由器才能發送組播查詢報文。

 

B)橋連接埠的查詢定時器

那如果上層協議棧不支援igmpproxy功能,上層協議棧收到通用查詢報文就會丟棄掉,就不會觸發上層協議棧對lan側裝置的通用查詢,那不就沒有辦法更新igmp snooping的組播組轉寄資料庫了。

       代碼編寫者顯然也注意到了這個問題,所以又增加了橋連接埠的組播查詢定時器功能,在開啟igmp snooping功能後就會開啟橋連接埠的組播查詢功能,分為下面兩種情況:

1、  在一個橋連接埠up起來且開啟igmp snooping時,通過間接調用__br_multicast_enable_port,啟動一個立即到期的橋連接埠的查詢定時器

2、  在重新開啟igmp snooping功能時,通過調用__br_multicast_enable_port,啟動一個立即到期的橋連接埠的查詢定時器。

下面我們分析一下函數__br_multicast_enable_port。

static void__br_multicast_enable_port(struct net_bridge_port *port)

{

       port->multicast_startup_queries_sent= 0;

 

       if(try_to_del_timer_sync(&port->multicast_query_timer) >= 0 ||

          del_timer(&port->multicast_query_timer))

              mod_timer(&port->multicast_query_timer,jiffies);

}

該函數還是比較簡單的,主要是開啟一個立即逾時的橋連接埠定時器,逾時後即會執行逾時處理函數br_multicast_port_query_expired。

 

 

static voidbr_multicast_port_query_expired(unsigned long data)

{

       structnet_bridge_port *port = (void *)data;

       structnet_bridge *br = port->br;

 

       spin_lock(&br->multicast_lock);

       if(port->state == BR_STATE_DISABLED ||

           port->state == BR_STATE_BLOCKING)

              gotoout;

 

       if(port->multicast_startup_queries_sent <

           br->multicast_startup_query_count)

              port->multicast_startup_queries_sent++;

 

       br_multicast_send_query(port->br,port,

                            port->multicast_startup_queries_sent);

 

out:

       spin_unlock(&br->multicast_lock);

}

該函數的結構還是比較簡單的,主要是判斷橋連接埠是否處於forward狀態,接著就會調用函數br_multicast_send_query發送一個通用查詢報文。

 

       對於函數br_multicast_send_query,其既可以向本地上層協議棧發送組播組查詢報文,也可以將組播組通用查詢報文從指定的橋連接埠發送出去。

       下面分析一下函數br_multicast_send_query

/*

1、  調用函數br_multicast_alloc_query構造一個萬用群組播組查詢報文

2、  對於橋連接埠不為空白時,則將該查詢報文從相應的連接埠發送出去

3、  對於橋連接埠為空白時,則將該查詢報文發送給上層協議棧

4、  更新橋或者橋連接埠的查詢定時器。

*/

static void br_multicast_send_query(structnet_bridge *br,

                                struct net_bridge_port *port, u32 sent)

{

       unsignedlong time;

       structsk_buff *skb;

 

       if(!netif_running(br->dev) || br->multicast_disabled ||

          timer_pending(&br->multicast_querier_timer))

              return;

       /*構造一個通用查詢資料包*/

       skb= br_multicast_alloc_query(br, 0);

       if(!skb)

              gototimer;

 

       if(port) {

              __skb_push(skb,sizeof(struct ethhdr));

              skb->dev= port->dev;

              NF_HOOK(PF_BRIDGE,NF_BR_LOCAL_OUT, skb, NULL, skb->dev,

                     dev_queue_xmit);

       }else

              netif_rx(skb);

 

timer:

       time= jiffies;

       time+= sent < br->multicast_startup_query_count ?

              br->multicast_startup_query_interval:

              br->multicast_query_interval;

       mod_timer(port? &port->multicast_query_timer :

                      &br->multicast_query_timer, time);

}

以上就是橋與橋連接埠的組播查詢定時器的工作原理。

 

三、igmpsnooping 的開啟與關閉

Igmp snooping的開啟與關閉是通過函數br_multicast_toggle實現

對於igmp snooping的開啟與關閉,目前是通過sysfs實現igmpsnooping的開啟與關閉。

我們可以通過添加ioctl介面,實現通過brctl來開啟或者關閉igmp SNOOPING

 

/*

功能:開啟或者關閉igmpSNOOPING的函數。

只有當要設定的值與br->multicast_disabled的當前值不同時才允許修改。

當開啟igmpsnooping功能時,則重新建立組播組轉寄資料庫表,並調用br_multicast_open與__br_multicast_enable_port啟動橋與橋連接埠的組播查詢定時器。

*/

int br_multicast_toggle(struct net_bridge*br, unsigned long val)

{

       structnet_bridge_port *port;

       interr = -ENOENT;

 

       spin_lock(&br->multicast_lock);

       if(!netif_running(br->dev))

              gotounlock;

 

       err= 0;

       /*如果要設定的值與當前的值相同,則直接返回*/

       if(br->multicast_disabled == !val)

              gotounlock;

 

       br->multicast_disabled= !val;

       /*當關閉igmp SNOOPING時,並沒有釋放br->mdb*/

       if(br->multicast_disabled)

              gotounlock;

   /*

 

    1、當開啟IGMP SNOOPING時,如果br->mdb、br->mdb->old均不為0,

          則說明br->mdb值有問題,此時則會關閉IGMP SNOOPING功能

    2、當開啟IGMP SNOOPING時,如果br->mdb不為0,且br->mdb->old為0,

           則調用br_mdb_rehash,將原br->mdb中的組播組項重新計算hash值

           並存放在新的br->mdb中,釋放原br->mdb佔用的空間*/

       if(br->mdb) {

              if(br->mdb->old) {

                     err= -EEXIST;

rollback:

                     br->multicast_disabled= !!val;

                     gotounlock;

              }

 

              err= br_mdb_rehash(&br->mdb, br->mdb->max,

                                br->hash_elasticity);

              if(err)

                     gotorollback;

       }

       /*

     1、reset br的發送查詢包統計計數

     2、修改br的組播查詢定時器multicast_query_timer的值

       */

       br_multicast_open(br);

       /*

       對於br橋組上的每一個連接埠

     1、reset port的發送查詢包統計計數

     2、刪除連接埠的查詢定時器,並重新調度

       */

       list_for_each_entry(port,&br->port_list, list) {

              if(port->state == BR_STATE_DISABLED ||

                  port->state == BR_STATE_BLOCKING)

                     continue;

 

              __br_multicast_enable_port(port);

       }

 

unlock:

       spin_unlock(&br->multicast_lock);

 

       returnerr;

}

至此完成了igmpsnooping的資料結構與初始化的介紹,下節分析igmp snooping的接收處理函數。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.