閱讀845 返回首頁    go 人物


網絡子係統27_橋接子係統初始化

//橋接子係統以模塊的形式提供
//函數主要任務:
//	1.轉發數據庫slab緩存
//	2.向socket的ioctl添加回調函數
//	3.在netif_receive_skb中路徑上添加回調函數
//	4.向netdev_chain注冊監聽塊
1.1 static int __init br_init(void)
{
	//轉發數據庫初始化
	br_fdb_init();
	//橋接子係統中有關netfilter的初始化
	...

	//向socket的ioctl注冊回調函數,處理對網橋的io命令
	brioctl_set(br_ioctl_deviceless_stub);
	//橋接入口skb處理,在netif_recive_skb中被調用
	br_handle_frame_hook = br_handle_frame;

	//netdev_chain上注冊一個監聽器
	register_netdevice_notifier(&br_device_notifier);

	return 0;
}


//監聽器
1.2 struct notifier_block br_device_notifier = {
	.notifier_call = br_device_event
};
//	橋接子係統處理的網絡配置事件:
//		前提:與事件相關的dev需要是網橋的端口
//			1.mtu改變,更新網橋設備的mtu
//			2.mac地址改變,在轉發數據庫中更新該端口的mac地址,重新計算網橋id
//			3.載波狀態改變,檢測到載波,使能端口;載波消失,disable端口
//			4.設備關閉,disable端口
//			5.設備開啟,enable端口
//			6.設備注銷,從網橋設備中刪除該端口
//		
1.3 static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{
	struct net_device *dev = ptr;
	struct net_bridge_port *p = dev->br_port;//一個設備如果為網橋的端口,則br_port指向端口控製塊
	struct net_bridge *br;
	//有事件產生的接口非網橋的接口
	if (p == NULL)
		return NOTIFY_DONE;
	//此端口所屬的網橋
	br = p->br;
	//獲取網橋的鎖,並且關軟中斷,對網橋上所有端口的事件,串行性執行
	spin_lock_bh(&br->lock);
	switch (event) {
	case NETDEV_CHANGEMTU://端口改變了mtu
		dev_set_mtu(br->dev, br_min_mtu(br));//br->dev指向網橋設備關聯的虛擬
		break;

	case NETDEV_CHANGEADDR://端口改變了mac地址
		br_fdb_changeaddr(p, dev->dev_addr);//更新轉發數據庫
		br_stp_recalculate_bridge_id(br);//由於網橋端口mac地址的改變,通過stp重新計算網橋的id
		break;

	case NETDEV_CHANGE:	//端口狀態的改變
		if (!(br->dev->flags & IFF_UP))//如果網橋處於關閉狀態,則忽略此消息
			break;

		if (netif_carrier_ok(dev)) {//如果端口有了載波信號
			if (p->state == BR_STATE_DISABLED)//端口之前為關閉狀態
				br_stp_enable_port(p);//使能端口
		} else {
			if (p->state != BR_STATE_DISABLED)//如果端口沒有了載波信號
				br_stp_disable_port(p);//不使能端口
		}
		break;

	case NETDEV_DOWN://端口關閉
		if (br->dev->flags & IFF_UP)//隻有在網橋處於開啟狀態才處理端口的關閉
			br_stp_disable_port(p);//不使能端口
		break;

	case NETDEV_UP://端口開啟
		if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) //端口存在載波信號,並且網橋處於開啟狀態
			br_stp_enable_port(p);//使能端口
		break;

	case NETDEV_UNREGISTER://端口注銷
		spin_unlock_bh(&br->lock);//釋放鎖,開啟軟中斷
		br_del_if(br, dev);//刪除接口
		goto done;
	} 
	spin_unlock_bh(&br->lock);

 done:
	return NOTIFY_DONE;
}

//向socket的ioctl注冊回調函數,處理io命令
2.1 void brioctl_set(int (*hook)(unsigned int, void __user *))
{
	down(&br_ioctl_mutex);
	br_ioctl_hook = hook;//鉤子函數,此鉤子函數會在sock_ioctl中被調用
	up(&br_ioctl_mutex);
}

最後更新:2017-04-03 15:22:11

  上一篇:go 深入理解JVM內幕:從基本結構到Java 7新特性
  下一篇:go Java中CallableStatement調用Oracle存儲過程總結