46 | 发送网络包(下)
2020-05-24 本文已影响0人
AndyWei123
image.png
- ip_queue_xmit 函数:
- 第一部分,选取路由,也即我要发送这个包应该从哪个网卡出去。
FIB 全称是 Forwarding Information Base,转发信息表。其实就是咱们常说的路由表。
路由表要按照前缀进行查询,总是希望找到最长匹配的那一个,因此路由表通过一个tire树进行维护- 第二部分,就是准备 IP 层的头,往里面填充内容。这就要对着 IP 层的头的格式进行理解。
image.png
在这里面,服务类型设置为 tos,标识位里面设置是否允许分片 frag_off。如果不允许,而遇到 MTU 太小过不去的情况,就发送 ICMP 报错。TTL 是这个包的存活时间,为了防止一个 IP 包迷路以后一直存活下去,每经过一个路由器 TTL 都减一,减为零则“死去”。设置 protocol,指的是更上层的协议,这里是 TCP。源地址和目标地址由 ip_copy_addrs 设置。最后,设置 options。
- 第三部分,就是调用 ip_local_out 发送 IP 包。
这里会先调用给你 nf_hook,用于在网络发送和转发的关键节点上加上 hook 函数,这些函数可以截获数据包,对数据包进行干预。
用户可通过iptables 定制这种规则:
image.png
filter 表处理过滤功能,主要包含以下三个链。nat 表主要处理网络地址转换,可以进行 SNAT(改变源地址)、DNAT(改变目标地址),包含以下三个链。
- ip_finish_output 函数:
- ip_negh_lookup_noref: 先从本地ARP表缓存中查找下一跳的ARP地址。假如没有则调用__neigh_create 进行创建。创建一个 struct neighbour 结构,用于维护 MAC 地址和 ARP 相关的信息。它是通过是一个数组加链表的链式哈希表存放。
- 从 arp_queue 中拿出 ARP 包来,然后调用 struct neighbour 的 solicit 操作。最后调用调用 dev_queue_xmit 发送二层网络包了。
- 有了 MAC 地址,就可以调用 dev_queue_xmit 发送二层网络包了,它会调用 __dev_xmit_skb 会将请求放入队列。
-设备层:网络包的发送会触发一个软中断 NET_TX_SOFTIRQ 来处理队列中的数据。这个软中断的处理函数是 net_tx_action。 - 在软中断处理函数中,会将网络包从队列上拿下来,调用网络设备的传输函数 ixgb_xmit_frame,将网络包发到设备的队列上去。