Linux内核分析 - 网络[五]:vlan协议-802.1q


内核版本: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.   
  8.   if (!(dev->flags & IFF_UP))  
  9.    continue;  
  10.   
  11.   nb->notifier_call(nb, NETDEV_UP, dev);  
  12.  }  
  13. }  

        此时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;  
  • 1
  • 2
  • 3
  • 4
  • 下一页

相关内容