深入理解Linux网络技术内幕——IPv4 分段与重组

封包的分段和重组是IP协议最重要的工作之一。

IPv4报头中有一个len字段(用于表示报文的总长度,单位:字节)占16bit,因此,封包的最大尺寸定义为64K,(2^16/1024=64)。

但是,在实际网络传输中,没有几个网络接口能够传输64K这么大的封包,而是有一个MTU表示其最大传输单元。这样,当要传输的封包大于MTU时,就需要对封包进行分段。 这里需要说明,我们指的MTU,不仅仅是出口设备的MTU,它取决于很多因素,如路由表项所用的MTU、出口设备的MTU等。

我们先不用过多与关注MTU如何计算,而应该注意,当封包大于MTU时,需要将封包分为一些大小相等(MTU大小)的片段,然后再分别进行传输。(当然,封包不一定能以MTU大小等分, 因而最后一个封包的大小可能达不到MTU这一尺寸)。

分段后的封包一般传输到目的主机后才进行重组,但是一些中间设备(如防火墙、NAT路由器设备)可能需要查看封包的完整内容,这是也可以对封包进行重组。

分段与重组对上层的影响

分段和重组是会占用CPU和内存,消耗带宽等,过多的分段和重组工作可能会影响系统整体性能,如果我们能够做一些优化,避免不必要的分段重组,就可以减少一些开销。优化工作在上层(L4、L5)进行。

我们举个例子看下一些不必要的分段:

A->B->C :   封包(1000字节)从系统A要经过B传给目的系统C,A->B  MTU为 800字节, B->C的MTU为512

在没有优化的情况下,在A->B时,先根据A->B的MTU将封包分段为800字节和200字节,在B->C时,在根据其MTU,包A传来的800字节的封包在分段为512字节和188字节。

而如果我们做一些优化,实现了解到A->B->C这一路径的MTU为512(取800和512的较小值),那么在A主机上直接将分包分为512字节和488字节。如此,就只需要进行一次分段,减少了系统开销。

TCP和UDP是不了解分段和重组的过程的,但是应用层却可以了解。

路径MTU发现功能可以发现整条路径的MTU(PMTU)。

RFC也规定主机至少要能接收576大小的封包,因而也可以吧MTU设置为576这一安全值。

分段与重组的实现

IPv4报头中,有一些字段用于分段和重组

Flags :─ 由3位字段构成,其中最低位(MF)控制分片,存在下一个分片置为1,否则置0代表结束分片。中间位(DF)指出数据包是否可进行分片。第三位即最高位保留不使用,但是必须为0。

Fragment Offset :─ 13位字段,指出与源数据报的起始端相关的分片数据位置,支持目标IP适当重建源数据报。

时间: 2024-07-28 21:57:04

深入理解Linux网络技术内幕——IPv4 分段与重组的相关文章

深入理解Linux网络技术内幕——IPv4 报文的传输发送

报文传输,指的是报文离开本机,发往其他系统的过程. 传输可以由L4层协议发起,也可以由报文转发发起. 在深入理解Linux网络技术内幕--IPv4 报文的接收(转发与本地传递)一文中,我们可以看到,报文转发最后会调用dst_output与邻居子系统进行交互,然后传给设备驱动程序. 这里,我们从L4层协议发起的传输,最后也会经历这一过程(调用dst_output).本文讨论的是L4层协议发起的传输,在IPv4协议处理(IP层)中的一些环节. 大蓝图 我们先看下传输环节的大蓝图,以便对传输这一过程有

深入理解Linux网络技术内幕——IPv4 概念

1.大蓝图 大蓝图展示了IPv4协议与其他子系统之间的联系,保罗设备驱动.Netfilter.L4 层协议等之间的互动. IPv4协议中的报文 我们可以大致看出数据在IPv4协议中的流向, 接收报文 设备驱动处理完硬件介绍到的数据后,IPv4协议的ip_rcv函数(net_receive_skb调用)得到了属于IPv4的报文,接着调用ip_rcv_finish对报文进行分析.判断是该转发还是交付本地上层协议. 如果是本地报文,则传给ip_local_deliver处理,如果是转发,那就交付ip_

深入理解Linux网络技术内幕——IPv4 报文的接收(转发与本地传递)

我们知道,报文经过网卡驱动处理后,调用net_receive_skb传递给具体的协议处理函数,对于IPv4报文来说,其协议处理函数就是ip_rcv了,ip_rcv在进行一些健康检查等操作后,会调用ip_rcv_finish来处理报文.这也是IPv4协议对报文接收处理的开始. 我们先看下ip_rcv_finish源代码: ip_rcv_finish: //ip数据报文的主要处理程序(ip_rcv仅仅只是对ip数据报做一些健康性检查) //ip_rcv_finish 其实是进行路由表查询,,决定报文

《深入理解Linux网络技术内幕》阅读笔记 --- 路由

一.Linux内核中路由相关的主要数据结构 struct fib_result:对路由表查找后返回该结构,它的内容并不是简单的包含下一跳信息,而且包含其他特性,例如策略路由所需的更多参数. struct fib_rule:表示由策略路由在路由流量时选择路由表的规则 struct fib_node:一条路由表项.例如,该数据结构用于存储由route add或ip route add命令添加一条路由时生成的信息. struct fn_zone:一个zone表示子网掩码长度相同的一组路由 struct

深入理解Linux网络技术内幕——协议处理函数

网络帧在进入网络层时,需要区分不同的网络协议进行处理,这就需要涉及协议处理函数. 首先我们从驱动接收到一个数据帧,分析数据帧在协议栈中自下而上的传输流程. 设备驱动程序在接收到一个数据帧时,会将其保存在一个sk_buff缓冲区数据结构,并对其进行初始化. struct sk_buff { ...... __be16 protocol:16; ...... } 在这个缓冲区结构体中,有一个protocol字段,用于标识网络层的协议. 我们知道网络帧在设备驱动程序中处理后,设备驱动程序会调用neti

深入理解Linux网络技术内幕——路由子系统的概念与高级路由

本文讨论IPv4的路由子系统.(IPv6对路由的处理不同). 基本概念 路由子系统工作在三层,用来转发入口流量. 路由子系统主要设计 路由器.路由.路由表等概念. 路由器: 配备多个网络接口卡(NIC),并且能利用自身网络信息进行入口流量转发的设备. 路由: 流量转发,决定目的地的过程 路由表:转发信息库,该库中储存路由需要本地接收还是转发的信息, 以及转发流量时所需要的信息.(即,信息库用来判断,要不要转发,如果要转发,向哪里转发). 我们了解,路由器有多个网卡,但是多个NIC的设备不一定就是

深入理解Linux网络技术内幕——设备的注册于初始化(一)

副标题:设备注册相关的基本结构的原理框架 设备注册与删除时间 设备在下列两种情况下进行注册: 1)加载NIC驱动时 2)插入热插拔设备时 这里NIC与热插拔设备有些不同.a.对于非热插拔NIC来说,NIC的注册是伴随着其驱动的发生的,而NIC可以内建到内核,也可以作为模块载入,如果内建入内核,则NIC设备和初始化均发生在引导时,如果NIC作为模块加载,则NIC的注册和驱动初始化均发生在模块加载时.b. 对于热插拔NIC设备来说,其驱动已经加载,因此设备的注册发生在插入设备,内核通知关联驱动时.

深入理解Linux网络技术内幕——帧的接收与传输

帧的接收 NAPI与netif_rx(非NAPI) Linux内核获取网络帧到达通知的方式有两中:中断和轮询.(中断值设备向内核发出中断,轮询指linux内核主动轮询设备) 在早起的linux内核中,网络帧主要以中断的方式通知linux内核帧的到达.这是非NAPI方式. 现在的操作系统中,linux内核使用NAPI方式, 获取帧到达的消息.NAPI混合使用了中断和轮询. netif_rx(非NAPI): 每一个帧接收完毕时,设备向内核发送一个中断.(在低流量负载的情况下,这种方式对比轮询优势明显

深入理解Linux网络技术内幕——网络设备初始化

概述 内核的初始化过程过程中,与网络相关的工作如下所示: 内核引导时执行start_kernel,start_kernel结束之前会调用rest_init,rest_init初始化内核线程init(在Linux3-12中为kernel_init). asmlinkage void __init start_kernel(void) { ... parse_early_param();//间接调用parse_args parse_args(...); //处理内核引导程序(boot loader)