歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核分析 - 網絡[五]:vlan協議-802.1q

Linux內核分析 - 網絡[五]:vlan協議-802.1q

日期:2017/3/1 11:09:18   编辑:Linux內核

內核版本:2.6.34

802.1q

1. 注冊vlan網絡系統子空間,

  1. err = register_pernet_subsys(&vlan_net_ops);
  2. static struct pernet_operations vlan_net_ops = {
  3. .init = vlan_init_net,
  4. .exit = vlan_exit_net,
  5. .id = &vlan_net_id,
  6. .size = sizeof(struct vlan_net),
  7. };

每個子空間注冊成功都會分配一個ID,在register_pernet_subsys() -> register_pernet_operations() -> ida_get_new_above()獲得,而vlan_net_ops中的vlan_net_id記錄了這個ID。注冊子空間的最後會調用子空間的初始化函數vlan_init_net(),它會把vlan_net(有關vlan的proc文件系統信息)加到全局的net->gen->ptr數組中去,下標為之前分配的ID。這樣,通過vlan_net_id便可隨時查到vlan_net的信息,主要與proc有關。

2. 注冊vlan_notifier_block

  1. err = register_netdevice_notifier(&vlan_notifier_block);
  2. static struct notifier_block vlan_notifier_block __read_mostly = {
  3. .notifier_call = vlan_device_event,
  4. };

關於register_netdevice_notifier()做的工作並不復雜,首先會注冊vlan_notifier_block到netdev_chain:

  1. err = raw_notifier_chain_register(&netdev_chain, nb);

然後通知事件NETDEV_REGISTER和NETDEV_UP事件到網絡系統的中的每個設備:

  1. for_each_net(net) {
  2. for_each_netdev(net, dev) {
  3. err = nb->notifier_call(nb, NETDEV_REGISTER, dev);
  4. err = notifier_to_errno(err);
  5. if (err)
  6. goto rollback;
  7. if (!(dev->flags & IFF_UP))
  8. continue;
  9. nb->notifier_call(nb, NETDEV_UP, dev);
  10. }
  11. }

此時nb就是vlan_notifier_block,調用通知函數vlan_device_event()。假設此時主機上擁有設備lo[環回接口], eth1[網卡], eth1.1[虛擬接口],來看vlan_device_event()函數:
判斷是否為vlan虛擬接口,則執行__vlan_device_event(),這個函數的作用就是在proc文件系統中添加或刪除vlan虛擬設備的相應項。顯然,符合條件的是eth1.1,而事件NETDEV_REGISTER會在/proc/net目錄下創建eth1.1的文件。

  1. if (is_vlan_dev(dev))
  2. __vlan_device_event(dev, event);

然後判斷dev是否在vlan_group_hash表中[參考最後”vlan設備組織結構”],它以dev->ifindex為hash值,顯然,只有eth1才有正確的ifindex,lo和eth1.1會因查詢失敗而退出vlan_device_event。

  1. grp = __vlan_find_group(dev);
  2. if (!grp)
  3. goto out;
Copyright © Linux教程網 All Rights Reserved