Q:bridge的入口在哪里?在驱动侧还是内核协议栈?到数据包达到网桥时哪一阶段去匹配目的mac是否与自己的mac匹配,不匹配就丢包?
要回答上面的问题,首先需要了解内核模块bridge是如何工作的,当bridge成功加载之后,他受理从用户空间发来的ioctl指令来指示增删桥接口,在嵌入式设备中,通常使用busybox中的brctl命令行工具调用内核ioctl来与内核通信。当用户空间增加一个桥接口时,内核bridge模块就创建对应的桥接口实体,同时将自己的br_handle_frame注入到设备的rx_handler中,这样net/core/dev.c中的__netif_receive_skb_core函数就会去判断rx_handler是否为空,不为空就调用。
上文说到文件net/core/dev.c中的__netif_receive_skb_core函数,那么这个函数又是从何处调用而来的呢?这就涉及到以太网卡驱动接收到数据包之后送入协议栈的方式问题了,先来说说以太网卡驱动收包流程,一般有两种方式接收网络包,一种为硬件中断方式,一种是轮询方式。
- 硬件中断:所谓硬件中断方式即在以太网卡驱动的初始化入口(驱动程序中一般命名为xxx_probe的函数)注册中断处理函数,每当有一个数据包到达以太网卡,就会产生一次中断,调用一次你注册的终端处理函数,然后中断处理函数一般会调用文件net/core/dev.c中的netif_rx将数据包转发到协议栈进行处理,这里要详细说明一下netif_rx函数,这个函数内部继续调用netif_rx_internal函数,而netif_rx_internal函数则调用函数enqueue_to_backlog将接收到的报文入队列,等待协议栈去处理。而内核协议栈的net/core/dev.c文件中的函数net_dev_init则是boot启动时就去调用的,这个函数会注册软中断,而软中断的入口则是函数process_backlog,这个函数会去读取backlog队列是否存在数据包,如果有就调用__netif_receive_skb(skb)函数进行处理,而这个函数内部调用则是__netif_receive_skb_core函