收包流程
-
数据包到达网卡NIC
-
非混杂模式的NIC校验Mac地址
- 即目的Mac地址不是本机的数据包直接丢弃,不会处理
- 混杂模式一般适用于存在虚拟机时,虚拟机daemon会把物理网卡设置为混杂模式
- 抓包时也需要混杂模式
-
校验数据帧的校验字段FCS,丢弃校验失败的错误帧
-
NIC通过DMA方式将数据帧放入提前映射好的内存区域
-
NIC等待超时或者接受区满了后出发硬件中断指令
-
CPU执行硬件中断并运行网卡的驱动程序,对网卡进行轮询收包
-
把数据包送入协议栈
-
调用netfilter(iptables对应的内核程序)的PREROUTING链
-
查找路由表,进行转发或者进入本机
-
对进行本机的包调用netfilter的LOCAL_IN链
-
调用四层协议栈,例如tcp_v4_rcv
-
查找到对应的socket,运行TCP状态机
-
通过epoll或者其他轮询方式通知应用程序
-
应用程序读取数据
发包流程
- 应用程序发送数据
- TCP协议栈为发送的数据申请skb(内核中的数据包对象)
- 构建TCP头部,例如src, dst的port, checksum
- 调用三层协议,构建IP头部,调用netfilter的LOCAL_OUT链
- 查找路由表,判断是发送给本机还是外部
- 如果发送给本机,就不用进行后面的步骤了
- 调用netfilter的POST_ROUTING链
- 对超过的MTU的报文进行分片
- 一般TCP协议在上层已经分好片了,UDP协议才在这里分片
- 调用二层的发包函数dev_queue_xmit
- 调用网卡驱动程序,在超时或者数据满了后出发内核中断
- 驱动程序把数据包映射到DMA内存
- 网卡从MDA中取出数据并发送
- 发送完毕后出发硬件中断,释放已经发送完的数据包的内存