网络子系统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