报文传输,指的是报文离开本机,发往其他系统的过程。
传输可以由L4层协议发起,也可以由报文转发发起。
在深入理解Linux网络技术内幕——IPv4 报文的接收(转发与本地传递)一文中,我们可以看到,报文转发最后会调用dst_output与邻居子系统进行交互,然后传给设备驱动程序。 这里,我们从L4层协议发起的传输,最后也会经历这一过程(调用dst_output)。本文讨论的是L4层协议发起的传输,在IPv4协议处理(IP层)中的一些环节。
大蓝图
我们先看下传输环节的大蓝图,以便对传输这一过程有大概的过程。
我们看到L4层协议(如TCP、UDP),以及一些特殊的三层协议(ICMP,RAW IP等)最终都会调用dst_output来将报文传给驱动程序。
调用dst_output之前的处理可以分为图中四种情形(不考虑报文转发发起的传输)。
case1a 和case1b主要针对(UDP、ICMP、RAWIP),分别调用ip_append_data和ip_append_page(其实是ip_append_data的变种),来将报文保存在缓冲区中(先不传输),待到缓冲区需要刷新时,才通过ip_push_pending_frames末尾间接调用dst_output来完成传输工作。
case2 面对TCP和SCTP,会直接调用ip_queue_xmit处理报文,然后调用dst_output。
case3 针对RAWIP和IGMP,直接调用dst_output。
上面的分类知识针对一般情况,也有一些特殊情形,比如TCP在需要发送ACK和RESET报文,会使用ip_send_reply,并间接调用ip_append_data和ip_push_pending_frames。TCP在传输ACK SYN时,也会调用ip_build_and_send_