网络层规划出了端系统到端系统的路径,并且实现了路由器的转发。因此,网络层的下一个层级链路层(Link Layer)要实现的是:对于网络层规划的某条通信信道(不包含转发,也即从端系统到最近的路由器的某条信道或路由器到相邻路由器的某条信道),这样相邻的通信信道就称为链路(Link)。链路层协议会把网络层报文(比如IP报文)做一些拆分并在每一份上加上链路层首部,封装为链路层报文,一个链路层报文通常称为一个frame。
做个比喻,把数据比作旅行的游客,网络层是旅行公司和转接站,规划游客从A沿某条铁路坐火车到B再沿某条航线坐飞机到C,那么链路层就是交通公司负责规划A到B的列车与B到C的航班,每种交通运输方式对应了一个“链路层协议”。
端系统在输出接口处安装有网络适配器(network adapter),也成为网络接口卡(简称网卡),在这里网络层报文被封装为链路层报文。路由器的每个接口处也都有网络适配器。网络适配器是实现链路层服务的地方。
广播信道的多路访问问题(The Multiple Access Problem of Broadcast Links)
链路分为两种,一种是点对点的,也即发送方和接收方都是单一的;另一种是广播信道,在这里有多个发送方共享同一个信道向接收方发送消息(这在有线链路和无线链路中都可能出现,后者更常见,前者也是可能的,比如一条总线分出多条子线连接不同设备)。对于广播信道,如果多个发送方同时发送,那么消息就会在信道上发生碰撞(collide)。这就好比教室里两个学生同时发言回答老师的问题会让老师听不清,此时人类规定了“先举手再说话”“一个一个说”等等的协议。计算机网络中也有类似的协议,统称为多路访问协议(Multiple Access Protocol)。
对于\(M\)个发送节点的吞吐量为\(R\text{ b/s}\)的广播信道,一个理想的多路访问协议应当能够满足:单个节点发送数据时吞吐量达到\(R \text{ bps}\);\(M\)个节点同时发送数据时每个发送方的吞吐量都达\(R/M\text{ bps}\)。
多路访问协议分为以下三类:
信道划分协议(Channel Partitioning Protocol)
第一种解决多路访问的方法是,把信道平均分配给\(M\)个不同的发送方,这样就能避免碰撞发生。例如,可以把每个时间单位分片成\(M\)个时间片,每个发送方占有某一个特定的时间片发送,这样的方案称为时分多路复用(Time Division Multiplexing, TDM)。也可以把信道划分成互不相交的多个频段,每个发送方占用某个特定频段,这样消息可以方便的叠加与分解,称为频分多路复用(Frequency Division Multiplexing, FDM)。
然而,以上解决方案不满足理想多路访问协议的第一个要求,也即如果整个信道只有单个发送方使用,它还是只能占有\(R/M\)的吞吐量。
第三种解决方案称为码分多址协议(Code Division Multiple Access, CDMA),它在无线局域网中有重要应用。CDMA通过对每个bit进行特定的编码,使得多个发送方同时发送时接收方也可以还原出其中某个特定发送方的信息。方法是,在发送每个bit的时隙进一步分成\(m\)份,每个发送方固定一个\(m\)位的编码(用1和-1表示),把要发送的bit乘以这个编码得到\(m\)个1或-1。不同发送方用不同的编码。由于信号的叠加是加性的,可以验证如果接收方把受到的信号乘以某个发送方的编码(再除以发送方总数),恰好能够还原出该发送方发送的bit。(当然,编码是需要精心选定的)
随机接入协议(Random Access Protocol)
随机接入协议提供碰撞检测,总是让信道以最大吞吐量同时发送所有人的数据,一旦发生碰撞则以某种随机的机制重发。
时隙ALOHA是最简单的随机接入协议。在时隙ALOHA中,我们把时间分片,每个时间片大小设置为信道以最大吞吐量发送单个链路层frame的时间。如果任意一个发送方有frame要发送,它就在下一时间片开始时发送。如果发生碰撞,协议保证能在时间片结束前检测到,此时停止所有发送,让每个需要重发的发送方在之后的每个时间片里以\(p\)的概率重发。计算可得,当\(N\)个发送方要同时发送数据时, 下一个时间片成功传输的概率为\(Np(1-p)^{N-1}\)。取使该概率最大的\(p\),得到最大成功概率为\(\dfrac{1}{e}\approx 0.37\)。
ALOHA在概率上独立地考虑了每个发送方节点,这事实上是不符合实际的。在人类协议中,我们通常会:监听,当别人正在发言时不打断;当别人打断时停止发言。带有碰撞检测的载波监听多路访问(Carrier Sense Multiple Access with Collision Detection, CSMA/CD)实现了这样的效果:获得数据报时将其封装进链路层frame;监听到信道空闲时发送,否则等待;如果传输过程中检测到碰撞则停止发送,否则说明成功传输;如果一个传输被中止,那么等待随机一小段时间后返回监听步骤。其中,最后一步中的等待时间随机性保证了碰撞的发送方不会同时重发导致再次碰撞,间隔时间由碰撞的可能性决定,一个具体的实现方式是:如果某一次重传已经是第\(n\)次重传,那么从\(\{0,1,\cdots,2^{n}-1\}\)中sample一个时间单位等待,时间单位为信道传输512bit的时间,并限制\(n\leq 10\),这一方案称为二指数后退(binary exponential backoff)。仿照上一段中\(\dfrac{1}{e}\)这一量的定义(称为效率),可以计算出CSMA/CD的效率近似为\(\dfrac{1}{1+5d_{\text{prop}}/d_\text{trans}}\),其中\(d_\text{prop}\)为信号在链路上的传播时延,\(d_\text{trans}\)为传输单个frame所需的时间。
为什么即便是监听到空闲时发送,还有可能发生碰撞?这是因为波的传播速度是有限的,两个发送方可能同时监听到空闲,但是在发送后若干时间后才检测到碰撞。
可以看到,随机接入协议保证了理想多路访问的第一个特性,但不保证\(M\)个发送方能以\(R/M\)的效率发送。
轮流协议(Taking-Turns Protocol)
第一种轮流协议称为轮询协议(polling protocol),指定一个主节点轮询每个节点是否发送,并为每个节点分配发送时间,这样做的缺点是引入了轮询所需的时延;
第二种轮流协议称为令牌传递协议(token-passing protocol),这里令牌代替了主节点在节点间传递,只有由令牌的人才能发送(某个限额的数据)。
链路层寻址
理论上,利用网络层地址(IP地址)和路由器寻址就可以传输所有数据,链路层只需要把报文从信道一端送到另一端即可。然而正是因为我们需要链路层协议处理诸如多路访问等等问题,我们需要链路层层面的寻址。在链路层层面,IP地址已经作为报文数据的一部分,不再起到地址标识的作用,因此我们需要链路层的地址标识。
MAC地址(Media Access Control address)
在链路层,每个适配器都唯一的一个6字节(48位)地址,称为MAC地址(Media Access Control address)。例如,用16进制标识,1A-23-F9-CD-06-9B就是某个适配器的MAC地址。MAC地址在适配器生产出来以后就固定不变。一个形象的比喻是,IP地址就好像家庭住址,而MAC地址就好像身份证号。随着端系统位置的改变,IP地址会改变,但MAC始终保持不变。链路层首部包含了源和目的地的MAC地址完成寻址。为了找到包含特定目的MAC地址的适配器,在链路层层面也必须有类似路由器的设施,称为交换机(switch)。交换机会依据输入报文的目的MAC地址从特定端口输出链路层报文,交换机一般用在局域网中,由于规模较小,其效率通常高于路由器(可以把它理解为局域网中的路由器)。
地址解析协议(Address Resolution Protocol, ARP)
既然源主机在发送时必须把目的主机的MAC地址封装进链路层frame,它是如何得知目的主机的MAC地址的呢?考虑到源主机已经知道目的主机的IP地址,所以只需要实现IP到MAC的转换就可以了(在同一局域网中,IP地址也是固定不变的)。完成这一转换的是地址解析协议(Address Resolution Protocol, ARP),它运行在主机上,输入一个IP地址,输出对应接口的适配器的MAC地址。ARP只适用于同一子网(局域网)内的IP地址。ARP是如何实现的呢?方法是在每台主机或路由器的内存中维护一张ARP表,存储IP地址和MAC地址作为表项。
如果主机查询ARP表时发现对应表项不存在,此时主机设定目的地址为MAC广播地址FF-FF-FF-FF-FF-FF广播一个ARP查询分组,每个接收到该分组的适配器都把分组上传到主机的ARP处理模块,查询到答案的主机再想原来的主机发送ARP响应分组,主机于是根据相应内容更新ARP表。由于初始时每个主机的ARP表中都至少含有自身的IP和MAC,因此根据以上机制ARP表可以自动建立(plug-and-play)。
对于向子网外发送的报文,路由器在输出端口需要获取目的适配器的MAC地址。这是用另一边对应子网中的ARP实现的。
有线局域网(Wired Local Area Network, Wired LAN)
类比一个路由器以下的端系统集合称为一个子网,把一个交换机以下的端系统的集合称为一个局域网。局域网是一个小范围的子网。当今最流行的有线局域网技术是以太网(Ethernet)。
由于以太网采用了交换机,交换机有缓存等技术能够避免碰撞,所以以太网不需要一个单独的MAC协议。
交换机的转发通过switch table来完成。其机制与路由器略有不同,但功能类似。相比于路由器,交换机的转发速率要高很多。并且类似于ARP,switch table也可以通过广播与相应自发生产,所以交换机也是plug-and-play设备。
差错检测和纠正(Error Detection and Correction)
链路层协议用基于报文本身的差错检测和纠正技术,这一差错是bit级的。实现差错检测和纠正的方法主要有:
奇偶校验。用单bit校验位标识数据中1的个数为奇数还是偶数,这样可以检测出数据在传输过程中是否有奇数个bit发生了差错。奇偶校验无法检测出偶数位的差错,为此可以引入二维奇偶校验,把数据分行为一个矩阵,对每行每列保存一个奇偶校验位,这样可以检测并纠正任意的单位差错,以及检测出两个位差错的任何组合。
循环冗余检测(Cyclic Redundancy Check, CRC)。对于数据串\(D\),选定一个generator \(G\),定义校验码\(R\)为使得\(G\)能整除\((D<<r)\oplus R\)的\(R\)。等价地,有\(R=(D<<r)\mod G\)。因此只需要做一个二进制除法即可。
无线局域网(Wireless Local Area Network, WLAN)
考虑一个最简单的无线局域网,一个交换机有线连接到外部网络,所有设备与交换机之间有单跳的无线链路。无线链路不一定是广播链路,虽然信号通常都以广播的方式传输到所有接收方,但只有满足接收条件的信号才会被接收方上传,因此有的无线链路也可以看作点对点链路。然而与有线链路相比,无线链路在传播时信号强度会因为分散而衰减,同时容易受到介质中的干扰,也会因为反射等原因在接收时造成信号模糊。因为这些缺陷,无线链路只能作用于较小的范围,同时需要更强的差错检验和纠正技术。
IEEE 802.11无线局域网又称为WiFi,是现代应用最广泛的无线局域网技术。在WiFi体系结构中,局域网的交换机(或路由器)有线连接若干接入点(Access Point),接入点是一个中心基站(base station),每个接入点与若干端系统有无线链路连接。一个接入点以及与之相连的端系统构成一个基本服务集(Basic Service Set, BSS)。一个端系统要发送数据,首先要和某个AP建立关联(也就是“连WiFi”)。端系统如何匹配一个AP呢?802.11标准要求所有AP周期性地广播信标帧(beacon frame),信标帧里包含了AP的MAC地址。 端系统选择一个AP(手动),然后向AP发送一个关联请求帧,AP回复一个关联响应帧,表示同意建立连接。 在关联建立前,通常需要用户名和password鉴别。
连接同一个AP的多个端系统在发送信息时会遇到多路访问问题。802.11标准采用随机接入协议中的载波监听多路访问(CSMA)来解决,但是这里的CSMA并不是带碰撞检测的,而应当是碰撞避免的。这是无线链路带来的问题:一个发送方的信号在传播到另一个发送方所在位置时可能已经充分衰减了(这通常称为隐藏终端问题),无线局域网只保证中心基站能识别来自各个发送方的消息,因此发送方之间的碰撞检测在物理上是难以实现的(注意,检测碰撞和监听是不同的概念!)。为此,802.11采用了带碰撞避免的载波监听多路访问协议(Carrier Sense Multiple Access with Collision Avoidance, CSMA/CA)。方法是,当源要发送一个frame时,如果监听到信道空闲,就先等一小个随机的时间间隔然后发;如果监听到信道忙,就随机等待一个值,这个值的大小会在监听到空闲时减小(否则不变),当该值为0时发送帧;接收方在收到消息时做CRC检验,如果检验通过就等待一小个随机的时间间隔然后发送确认的响应报文给源。发送站点接收到确认报文以后得知报文已成功发送。在以上方案中,关键在于源与目的在需要发送一个报文且信道空闲时都会等待一个小的时间间隔,这就避免了多个源同时想发送消息时出现碰撞,因为总有一个最早发送的发送方,它开始发送以后其他发送方就监听到信道忙。但是这样还是没有解决隐藏终端问题。为了解决这个问题,可以引入短的“请求发送(Request to Send, RTS)”和“允许发送(Clear to Send)”控制帧。当源要发送消息时,首先广播RTS,接收到RTS的AP返回CTS,为它预约一个信道,然后源发送数据报文,接收方返回ACK报文(注意,以上四次发送每次都要等待随机的小时间间隔)。正是由于RTS和CTS都很短小,所以即便碰撞代价也很小,而短的报文能为长的报文预约信道,所以解决了隐藏终端的问题。
802.11协议中报文首部包含四个MAC地址要填写,而不止源和目的的MAC地址。其中,第四个是用于自组织模式的,暂不讨论;第三个是通常需要填写AP的MAC地址,因为路由器在像端系统转发的时候并不知道它会经过一个AP,而链路层又需要先把报文转发给AP的MAC地址而不是端系统的MAC地址。