[Linux_69] 数据链路层 | Mac帧格式 | 局域网转发 | MTU MSS
目录
0.引入
1.以太网帧格式
2.重谈局域网转发的原理(基于协议)
小结
3.认识MTU
3.1MTU对IP协议的影响
3.2MTU对UDP协议的影响
3.3MTU对于TCP协议的影响
0.引入
在去年的这篇文章中,我们有对网络进行过一个概述[Linux#47][网络] 网络协议 | TCP/IP模型 | 以太网通信,现在我们来详细讲解一下其中的 数字链路层部分
网络: 先决策识别,后执行
在IP协议说过在路由器上是确实根据IP报文目的IP路由的,
但其实真正在网络上跑的并不是IP报文,而是MAC帧。
现在我们已经知道数据可以经过路由选择从主机B跨网络送到主机C
- 路上有运营商搞的内网
- 有运营商搞的公网
- 整个网络按照子网掩码以及运营商划分好的网络区块构建的拓扑结构(本质就是图 算法了)帮我们进行路由,路由器中配有路由表。(文件中也有 页表)
整个路由转发的过程我们已经很清楚了。
现在的问题是,要把数据跨网络送到主机C,要先经过路径选择
- 把数据交给主机B直接相连的下一跳路由器,虽然这个路由器也要进行路由选择
- 但是在怎么路径选择它也依旧要将路由器中的数据在交付给和它直接相连的下一跳路由器
- 同理,每一个设备都是如此。
- 所以你要把数据跨网络路径选择送到主机C,你首先要解决的是要先把数据从主机B交给和它直接相连的某一个节点
至于为什么不是路由器E,路由G,因为我们有路径选择。
一旦我们选择好了那怎么把数据交给路由器F呢?所以我们就需要有另一个协议了。
- 另外把数据从主机B交给路由器F前提是两者属于同一个网端,同理从某个路由器交给下一跳路由器,两者都需要在同一个网段。
- 所以你要进行跨网络传输,你要先解决在同一个局域网内将主机B中的数据交给路由器F,然后路由器F在交给路由器G等等。
所以跨网络传输的本质,是无数个局域网(子网)转发的结果!!!
所以要彻底理解跨网络转发,首先要理解局域网中报文的转发原理
关于局域网转发原理我们在网络基础一学过,这里我们首先要有一个共识,在同一个局域网的主机,可以直接通信!
一个故事
老师点名张三,全班同学都听到了,每一个同学都把张三的报文报头解析和自己做对比,发现不是叫自己,张三发现是自己,回答说“到”,老师和张三之间进行了通信,班上有很多吃瓜群众
- 在这所公共场所教室里面信的时候,老师认不认为在和张三直接通信呢?当然认为。
- 老师认不认为在和张三一对一直接通信呢?老师认为!
所以实际在局域网看起来两台主机在一对一直接通信,但是其他主机也都会收到,但是经过比对发现不是给我发的,数据链路层就把该报文丢弃。所以看起来就是两台主机在一对一直接通信!
从上面故事我们还可以提出一条消息,每台主机都要有唯一的标识符,因为有了这个唯一标识符才能区分这个消息是否是转给我的。
1.以太网帧格式
数据在经过路由选择发现它要去该局域网的出口路由器中,所以它要重新封装MAC帧,那IP就要把报文交给它的下一层以太网遵守的协议MAC帧。
所以IP报文要封装成MAC帧,所以接下来了解MAC帧的报头
以太网的帧格式如下所示:
很明显前面6 6 2 以及后面4字节属于MAC帧报头,一头一尾夹在中间的数据是有效载荷(IP报头+有效载荷)
如何将报头和有效载荷分离?
- MAC帧采用固定大小报头。收到一个MAC帧只需要将前面14字节后面4字节去掉,剩下的就是有效载荷。
如何分用
- MAC帧有个类型字段
- 类型是 0800 代表有效载荷是IP数据报
- 0806 代表ARP请求/应答
- 8035 代表RARP请求/应答,所以有帧类型就可以区分。
刚才说每台主机都必须要有唯一标识,这个标识如何理解?
- 每台机器至少配一个网卡,每张网卡都要有唯一的一个序列号,这个序列号称为该网卡的MAC地址,这个MAC地址在全球范围内具有唯一性
- 长度是48位,是在网卡出厂时固化的。源地址和目的地址指的就是网卡的硬件地址(也叫MAC地址),表示从哪来到哪去。
帧末尾是CRC校验码。
2.重谈局域网转发的原理(基于协议)
现在一个局域网有7台主机,地址从m1到m7,现在m1想把数据发给m7 怎么做呢?
它一定要自己封装MAC帧。数据上层交付下来到了数据链路层封装MAC帧,
然后发送到局域网中,问题来了,m2,m3,m4,m5,m6,m7每一台主机都能收到这个MAC帧,那每一台主机数据链路层要不要接收这个发出去的MAC帧呢?要!
- 每一台主机数据链路层也都要做报头和有效载荷分离,当想向上交付时,首先要确认这个报文是不是要发给自己的,以m2为例,它首先确认这个MAC帧的目的MAC地址,发现是m7,但自己是m2
- 所以m2在自己的数据链路层直接把该报文丢弃,当丢弃了它也没有向上交付的动作,所以上层也不知道m2曾经收到MAC帧。
- 同理m2,m3,m4,m5,m6都会把帧拿上去然后对比之后发现不是发给自己的都会丢弃。
同理m7作为当前局域网中的一台主机,它也会收到这个MAC帧,然后数据链路层做报头和有效载荷分离,然后识别到目的MAC地址是自己,然后根据帧类型把有效载荷向上交付。
至此m1给m7发送消息,m7收到了。
然后m7向上解包分用直到交付给应用层,应用层处理好之后在向下交付到TCP层,IP层,直到在到数据链路层封装成MAC帧,给m1应答。
- 封装MAC帧之后,同样也是发送到局域网里,同理m1,m2,m3,m4,m5,m6都会收到,除m1之后,其他在数据链路层在报头和有效载荷分离发现目的mac地址不是自己就给扔掉了上层也不知道自己曾经收到了MAC帧。
- 同理m1收到后也做报头和有效载荷分离,对比之后发现目的mac地址是自己,然后就把有效载荷交付给上一层,然后解包分用直到交给应用层,这样m7给m1应答完成。
所以以太网通信原理非常简单,所有的信息其实都会被局域网所有主机收到,只不过绝大部分主机在数据链路层对比目的mac地址发现不是自己,所有主机把数据报文全部丢弃。
只有是自己的才会向上交付,至此就完成了局域网通信的一般原理。
所以我们就可以这么理解
小结
局域网中所有的主机其实都能收到对应mac,只不过大部分主机在自己的数据链路层通过对比数据帧中的目的mac地址和自己的mac地址是否相等,来决策要不要进行后序处理!
- 在局域网中网卡有一种模式,称之为混杂模式
- 默认网卡是没有开启混杂模式的,特点:不放弃任何数据帧直接向上交付。这也是大部分局域网抓包工具原理!
- 一个局域网中,这个网络是被所有主机共享的,所有主机都能够发信息,m1发,m3也可以发,m5也可以发,如果同一时间大家都发就会导致很严重的数据碰撞问题。
所以在局域网中,任何时刻,只能有一个主机发信息,如果多个消息被同时发送,会导致局域网中的数据发生碰撞,这个数据就成了无效数据。
那m1发送的,m1如何知道发送碰撞了?
- m1发送的时候自己也能收到,它发现自己发的和收的不一样,那CRC校验通不过,不就是数据发送碰撞了嘛。
所以一个局域网,也称为一个碰撞域
那如何保证在任何一个时刻只允许一个主机发送呢?
- 不同的局域网标准有不同的实现方案,有一种叫令牌环,就好比在局域网中流转一部分令牌数据,只有持有令牌的人才可以发信息。(这是一个重要的解决碰撞的思想,借助令牌)
- 一个主机发信息需要把令牌发送到局域网中转给下一台主机。
- 另一种是以太网,发数据如果监测到碰撞了就暂时不发数据等一等,然后在发送。
- 所以重传可不只有tcp,在数据链路层发送碰撞了也要进行重传。这种策略我们称为主机的碰撞检测和碰撞避免。
如何重新看待局域网(以系统角度):
- 局域网本质要被该局域网所有主机共享,而为了保证正常通信任何时刻只能有一台主机能够进行通信,所以局域网在我看来就是一种临界资源
- 碰撞检测+碰撞避免,任何一个时刻只有一台主机能够向临界资源中写入数据,就是临界区!令牌环不就是锁吗。
那现在有一个问题:
局域网能不能很大?为什么?
- 不能,局域网太大意味着主机很多,也就意味着任何时刻发送碰撞的概率就增加了!
如果局域网就是很大,有没有办法缓解碰撞概率呢?
- 在网络中可以有一种设备叫做交换机,工作在数据链路层。
比如m1给m7发送消息,m2同时刻给m6发送消息,在交换机的一侧发生了碰撞,那交换机能够识别局部性的碰撞,对碰撞数据不做转发。 - 一旦把这个数据转发过去了那所有主机都识别到数据发生碰撞,然后执行碰撞检测和碰撞避免,所以会影响交换机右侧对应的数据发送。
- 所以交换机识别碰撞了对碰撞数据不转发,但交换机另一侧没有问题,所以另一侧正常发送数据。
- 所以交换机就有效的对碰撞域做了分割。其次如果是交换机一侧在互相发送消息,比如m1给m6发送消息,交换机能够识别出来当前通信的两台主机是我交换机划分碰撞域的左侧
所以不对正常数据做转发,也就说不把数据转发到我交换机右侧。也就是说右侧的主机正常通信把,右侧的碰撞概率也就降低了。交换机的核心工作:划分碰撞域!
因为有碰撞域,所以一台主机发送数据的时候,发送数据量长了好,还是短了好?为什么?
- 如果发送数据量非常长,这意味在转发的数据在网络的时间很长,发送碰撞概率增大。
- 如果发送数据量很短,一个数据发送很多次,发送碰撞概率也会增大。
- 所以数据帧有一个传输数据大小的范围。规定有效载荷长度最大不超过1500字节。最小不超过46字节(不够MAC帧做填充)。
由于有这个规定,所以导致IP报文可能要分片。
对比理解MAC地址和IP地址
- IP地址描述的是路途总体的 起点 和 终点;
- MAC地址描述的是路途上的每一个区间的起点和终点;
主机将数据交付给下一跳(下一跳的是主机还是路由器等其他节点)
前提一定是 该数据帧被路由过,因为网络层在数据链路层的上层。
- 还有个 有意思的点,就是我们手机开热点 也会变成一个路由器了
3.认识MTU
MTU相当于发快递时对包裹尺寸的限制. 这个限制是不同的数据链路对应的物理层, 产生的限制.
- 以太网帧中的数据长度规定最小46字节,最大1500字节,ARP数据包的长度不够46字节,要在后面补填充位;
- 最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU;
- 如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行分片(fragmentation);
- 不同的数据链路层标准的MTU是不同的;
3.1MTU对IP协议的影响
由于数据链路层MTU的限制, 对于较大的IP数据包要进行分包.
- 将较大的IP包分成多个小包, 并给每个小包打上标签;
- 每个小包IP协议头的 16位标识(id) 都是相同的;
- 每个小包的IP协议头的3位标志字段中, 第2位置为0, 表示允许分片, 第3位来表示结束标记(当前是否是最后一个小包, 是的话置为1, 否则置为0);
- 到达对端时再将这些小包, 会按顺序重组, 拼装到一起返回给传输层;
- 一旦这些小包中任意一个小包丢失, 接收端的重组就会失败. 但是IP层不会负责重新传输数据;
IP报文如何分片和组装,在IP协议的文章中我们写到过,这里不再细说。
现在有一个问题,是不是只有发送端主机来分片,路上的其他节点(路由器)会不会也对数据做分片呢?
有可能!大家用的都是TCP/IP,中间的路由器也是工作在网络层也有分片的能力,可能MTU也有分片的需求。
- 可能发送方主机规定MTU1500,不排除有些路由器MTU规定是500。
- 所以IP报头的16位标识,3位标记,13位片偏移量同样也支持在路上进行分片,然后组装。
从主机A把数据跨网络送到主机D可能并不是只有一条路径供选择
- 但是如果主机A在发送数据时将IP报文按1500字节分好片之后,并且将分片后的IP报头中3个标记中第二个标记设为1表示不可分片
- 在进行转发这些分片的时候,一旦遇到路由器想要在把分片在进行分片的时候,但是我不让它进行分片,那么这个路由器就把这个分片就直接丢弃了
那发送方就要进行超时重传,就要重新进行路径选择,就可能找到一条允许我直接按照1500字节从头发到尾的路径,所以就能找到一个叫做 “最大吞吐量” 的路径。
- 所以 曾经说过IP报头里有一个禁止分片的标记位,这玩意可以在路上确定是否有些路由器抠抠搜搜,这样在这个转发的路上只会选择能够转发1500字节的路由器了。
- 这个标记位是支持我们进行各种路由选择策略之一的选项。
3.2MTU对UDP协议的影响
- 一旦UDP携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)), 那么就会在网络层分成多个IP数据报.
- 这多个IP数据报有任意一个丢失, 都会引起接收端网络层重组失败. 那么这就意味着, 如果UDP数据报在网络层被分片, 整个数据被丢失的概率就大大增加了.
3.3MTU对于TCP协议的影响
在IP协议说过,分片并不好,那如何在进行数据包转发中不要出现分片问题呢?
前面说过IP不能决定单个报文大小,真正在网络中决定单个报文大小的是TCP。那TCP是如何做到减少IP出现分片情况的呢?
- MAC规定有效载荷最大不超过1500字节,那IP交给MAC的IP报文:IP报头+有效载荷 = 1500,IP标准报头长度20字节,那有效载荷就是1480。这个有效载荷是上层TCP报文:TCP报头+有效载荷 = 1480,TCP标准报头长度也是20字节,那有效载荷是1460。
MAC规定有效载荷最大不超过1500字节,所以从根上要从TCP来解决,TCP你自己发送报文时,规定单个报文有效载荷大小不要超过1460。这样添加TCP报头,IP报头到MAC帧就不会超过1500。
所以滑动窗口=min(拥塞窗口,对方接收能力),那为什么不直接一次打包发送,而是把滑动窗口范围分成多个报文段发送?
原因是网络不允许一次发送太大的单个数据段!
所以这些协议之间会互相影响!
我们把基于MTU1500字节的规定,最后影响了TCP发送数据时最多发送1460这样的数据报文,我们叫做MSS(最大段尺寸),就是TCP它的有效载荷最大是多少。
- TCP的一个数据报也不能无限大, 还是受制于MTU. TCP的单个数据报的最大消息长度, 称为MSS(Max Segment Size);
- TCP在建立连接的过程中, 通信双方会进行MSS协商.
- 最理想的情况下, MSS的值正好是在IP不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的MTU).
- 双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值.
- 然后双方得知对方的MSS值之后, 选择较小的作为最终MSS.
- MSS的值就是在TCP首部的40字节变长选项中(kind=2);
MSS和MTU的关系
查看硬件地址(MAC地址)和MTU
使用ifconfig命令, 即可查看ip地址, mac地址, 和MTU;
关于MAC帧协议所有内容到此结束。
我们现在整个网络的思想结构以及建立好了,下面就是对这个结构进行缝缝补补。
在此之前我们结合前面学的知识把整个网络发送过程串一下。然后引出下一个话题。
在整个网络发送过程,难道没有发现一个问题吗?把数据从主机A跨网络送到主机D,要经过各种路由选择。
- 但先别跨网络了并且也不能凭空飞过去,网线只要在物理层上,就必须把数据从最上层交给物理层,然后要解决数据从A跨网络到D
- 要先解决数据从主机A送到路由器A,然后再从路由器A送到路由器E,所以在局部上任何一个主机进行下一跳的时候,它和它下一跳一定属于同一个局域网
所以跨网络通信的本质,不就是在一个一个局域网跳转吗,也正是在一个一个局域网跳转最终才构成了宏观的大的跨网络传输效果。
- IP协议的讲张三去清华大学的故事在继续,张三要去清华大学,不断的问,最后问到清华大学门口保安大爷,大爷说这就是清华大学,曾经说过数据经过路由目的是找到目标网络吗?
- 并不是,IP=目标网络+目的主机,所以你要去的其实主机,只不过为了到达主机你要先到达目标网络,现在你已经到达了要去的目标网络的入口路由器处,接下来你问保安大爷,那我现在19号宿舍楼怎么走,大爷说你先这样走在那样走就到了。
所以此时数据包千里迢迢把自己送到了另一个子网中的入口路由器处
现在要把这个数据包交给这个目标网络中的目标主机了,根据我们所学一定能保证我要去的目标主机一定在对应的子网中,因为我们的网络号是一样的。
- 可是入口路由器要把数据交给和它在同一网段的主机 C,注定了这是一个局域网通信
- 路由器在自己的网络层拿到该数据报文后,查看路由表发现你要去的主机就在当前局域网,就注定了这个报文要被封装成MAC帧然后发送给目标主机 C
可是要封装成MAC帧,我们必须要知道主机 C 的MAC地址!
- 可是在前面再说MAC帧的时候我们默认了知道每台主机的MAC帧地址,这是站在上帝视角知道的
- 可是局域网不止一台机器,你凭什么知道主机 C 的MAC地址呢?
- 并且从上到下所传的报文里也根本没有主机 C 的MAC地址!你知道主机 C 的IP地址!
所以你想从你收到的报文中拿是不可能的。
一般而言路由器是一定认识主机 C 的,但是凭什么?
所以此时需要有一个过程,让路由器设备,认识主机 C,本质上是获取主机 C 的MAC地址!
- 因为只有知道主机 C 的MAC地址才能够把我收到的数据包向下封装成MAC帧发送给主机 C。
- 所以路由器凭什么认识和它处在同一个网络其他主机的MAC地址,包括之前说的m1给m7发送消息,凭什么m1就知道m7的mac地址呢?
所以我们此时需要局域网通信的又一种协议,该协议叫做ARP协议!
我们将在下篇文章中详细讲到,下篇文章见~