Linux内核分析 - 网络[五]:vlan协议-802.1q
Linux内核分析 - 网络[五]:vlan协议-802.1q
内核版本:2.6.34
802.1q
1. 注册vlan网络系统子空间,
- err = register_pernet_subsys(&vlan_net_ops);
- static struct pernet_operations vlan_net_ops = {
- .init = vlan_init_net,
- .exit = vlan_exit_net,
- .id = &vlan_net_id,
- .size = sizeof(struct vlan_net),
- };
每个子空间注册成功都会分配一个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
- err = register_netdevice_notifier(&vlan_notifier_block);
- static struct notifier_block vlan_notifier_block __read_mostly = {
- .notifier_call = vlan_device_event,
- };
关于register_netdevice_notifier()做的工作并不复杂,首先会注册vlan_notifier_block到netdev_chain:
- err = raw_notifier_chain_register(&netdev_chain, nb);
然后通知事件NETDEV_REGISTER和NETDEV_UP事件到网络系统的中的每个设备:
- for_each_net(net) {
- for_each_netdev(net, dev) {
- err = nb->notifier_call(nb, NETDEV_REGISTER, dev);
- err = notifier_to_errno(err);
- if (err)
- goto rollback;
- if (!(dev->flags & IFF_UP))
- continue;
- nb->notifier_call(nb, NETDEV_UP, dev);
- }
- }
此时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的文件。
- if (is_vlan_dev(dev))
- __vlan_device_event(dev, event);
然后判断dev是否在vlan_group_hash表中[参考最后”vlan设备组织结构”],它以dev->ifindex为hash值,显然,只有eth1才有正确的ifindex,lo和eth1.1会因查询失败而退出vlan_device_event。
- grp = __vlan_find_group(dev);
- if (!grp)
- goto out;
|
评论暂时关闭