ip协议之报文发送流程

本文解析了Linux内核中ip_queue_xmit函数的工作原理,涉及路由表查询、路由项状态管理、路由规则操作以及netfilter框架的应用。重点介绍了套接字与路由的动态关联和路由项的有效性检查机制。
摘要由CSDN通过智能技术生成

ip_queue_xmit函数

在这里插入图片描述
对于tcp协议往ip层发送报文时用的接口函数为ip_queue_xmit->__ip_queue_xmit
在这里插入图片描述
首先获取struct sock结构体缓存的目的地址路由表sk->sk_dst_cache,如果存在则直接使用该路由表的dst目的地址结构体设置到skb,如果不存在则通过ip_route_output_ports函数查找路由表,找到的路由表会通过sk_setup_caps函数设置到sk->sk_dst_cache缓存。套接字 sk 与路由项 dst 的对应关系并不是固定的,而是动态维护的。当套接字需要发送数据包时,它会根据目标 IP 地址和端口查找相应的路由项。找到合适的路由项后,将其缓存在 sk_dst_cache 中,以便后续的数据包发送可以直接使用缓存的路由项,避免重复的查找操作。

dst_entry路由项状态

在这里插入图片描述
DST_OBSOLETE_NONE:表示目的地址dst_entry没有过时状态。
DST_OBSOLETE_DEAD:表示目的地址dst_entry已经过期,不再使用。
DST_OBSOLETE_FORCE_CHK:强制检查目的地址dst_entry是否过期,即使状态不是OBSOLETE_DEAD也需要检查。
DST_OBSOLETE_KILL:直接释放目的地址dst_entry,不再保留。
在这里插入图片描述
路由表项初始化时obsolete的状态为DST_OBSOLETE_FORCE_CHK。后续会根据网卡收到的报文改变对应路由项的obsolete的值。

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

其检测原理即为检查net_device网卡对应net空间的rt_genid是否与初始化时的值不一致。通过rt_cache_flush函数改变net空间的rt_genid值。

路由(route)和路由规则(rule) 的添加删除查找

在这里插入图片描述
linux通过fib维护内核路由表其上分别对应添加inet_rtm_newroute,删除inet_rtm_delroute,获取inet_dump_fib的回调函数,应用层通过netlink与内核交互。需要指出的是路由表项是不可变的数据结构,不能直接进行"修改"操作,如果需要修改也是通过"删除-添加"的方式来完成。
fib_inetaddr_notifier对应IPv4地址事件通知回调函数。
fib_netdev_notifier对应网络设备事件通知回调函数。
在这里插入图片描述
其中网卡的up和down都会调用rt_cache_flush该net网络空间的rt_genid值。

在这里插入图片描述
在这里插入图片描述

上述函数则是路由规则的添加删除和获取。在新增rule或删除rule的时候都会调用flush_route_cache函数间接调用rt_cache_flush函数。

sk->sk_dst_cache的有效性判断

在这里插入图片描述
在上述判断中dst为NULL表示该路由项被释放,dst->obsolete为真则表示需要进一步判断。dst->ops->check(dst, cookie) == NULL为真则表示网络命名空间发生了改变,如添加/删除路由或up/down网卡。

由于网络环境的变化和路由表的更新,缓存的路由项可能会变得过时或无效(obsolete)。为了确保缓存的路由项仍然有效,内核会定期检查路由项的状态。如果路由项已经过时且不再有效,就会触发路由项的检查(dst->ops->check(dst, cookie))。如果检查结果为 NULL,说明路由项已过时且无效,此时会清除套接字的发送队列,并清除关联的缓存路由项,释放相关资源。

ip_local_out函数

在这里插入图片描述
在这里插入图片描述

ip_local_out函数中会首先调用__ip_local_out->nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,net, sk, skb, NULL, skb_dst(skb)->dev,dst_output);该函数即是netfilter框架的入口函数实现iptables中对NF_INET_LOCAL_OUT链的的报文过滤。

在这里插入图片描述
在这里插入图片描述
nf_hook的具体实现为先获取net->nf.hooks_ipv4[hook]对应的钩子函数头结点然后再调用nf_hook_slow函数对注册到NF_INET_LOCAL_OUT类型的所有钩子函数依次调用并判断其返回值NF_ACCEPT则继续调用下一个钩子函数NF_DROP则表示该报文被钩子过滤不能发送。
在这里插入图片描述
例如xt_table 的mangle表即会注册NF_INET_LOCAL_OUT钩子函数。

ip_output函数

在这里插入图片描述
在这里插入图片描述

最后在ip_output->ip_finish_output函数中进行ip层的报文发送进而发送给数据链路层。需要注意的是在ip_finish_output函数中会检测报文的长度如果大于mtu的长度则会调用ip_fragment进行ip报文的分片。

总结

1.__ip_queue_xmit函数将报文从ip层发送给首先判断sk->sk_dst_cache缓存的路由项是否可用。不可用的情况一般有路由项被释放,网络命名空间发生改变如添加/删除路由或up/down网卡。如果sk->sk_dst_cache缓存的路由项不可用则根据目的地址查找路由项并设置到sk->sk_dst_cache。
2.应用层通过netlink通信进行路由表的添加/删除操作,且路由表的"修改"是通过先删除再添加的方式完成的。同时内核本身也会根据网络设备和IP地址变化等原因,动态更新和重新查找路由表项。
3.然后通过nf_hook调用netfilter框架中的钩子函数进行报文的过滤。
4.在最后报文从ip层发送给数据链路层时会检测报文的长度如果大于mtu的长度则会调用ip_fragment进行ip报文的分片。

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值