1、基本数据链路层协议
引言
- 在考察协议之前,先明确一下有关底层通信模型的基本假设是有必要的。首先我们假设物理层、数据链路层和网络层都是独立的进程,它们通过来回传递信息进行通信。如图所示,物理层进程和某些数据链路层进程运行在一个称为网络接口卡(NIC)的专用硬件上:链路层进程和操作系统的一部分运行在主CPU上,链路层进程的软件通常以设备驱动器的形式存在。然而,其他的实现方案也是有可能的。无论如何,将3层作为独立的进程讨论有助于使概念更清晰,同时也可强调每一层的独立性。
- 另一个假设是:如果机器A用一个可靠的、面向连接的服务向机器B发送一个长数据流(先不考虑B同时向A发送数据的情形)。假定A要发送的数据总是已经准备好,不必等待这些数据被生成。或者说,当数据链路层请求发送数据时,网络层总能立即满足数据链路层的要求。还应假设机器不会崩溃。
- 数据链路层从网络层获取的数据包是纯粹的数据,数据包被完整地交到目标机器的网络层,虽然目标机器网络层可能将数据包的一部分解释为一个头,但这不属于数据链路层考虑的范围。
- 假设有一个现成的代码库,其中to_physical_layer发送一帧,from_physical_layer接收一帧,这个过程负责核算附加校检和(这部分工作通常由硬件完成,例如它们可能使用CRC算法),所以我们无需关心数据链路层协议的这部分内容。目标机器数据链路层等待数据用过程调用wait_for_event(&event)标示,当确实发生了事情(比如到达了一个帧),过程返回并由event说明发生了什么事情。对于不同的协议,可能的事件集合也是不同的,每个协议都需要单独定义和描述事件集合。在实际中,数据链路层不会在一个严格的循环中等待事件,而是会接收一个中断;中断将使它终止当前工作,转而处理入境帧,为了简便起见,将忽略数据链路层内部所有并发进行的活动细节,假定它全部时间都在处理一个信道。
- 当一帧到达接收方,校检和被重新计算。如果计算出的帧校检和不正确,则数据链路层会收到通知(event = cksum_err)。如果到达的帧没有任何损坏,数据链路层将收到通知(event = frame_arrival),因此它可以利用from_physical_layer得到该帧并处理。只要接收方的数据链路层获得了一个完好无损的帧,它就检查头部的控制信息;如果一切没有问题,它就将内嵌的数据包传递给网络层。(为什么网络层得不到任何帧头信息?自然是为了保持网络层和数据链路层的完全分离。当数据链路层协议和帧格式发生变化时,网络层软件可以不作任何改变。那么当一块新的NIC安装在计算机上时就没有任何问题)。
- 图中给出了将要讨论的许多协议公用的一些声明(C语言)。这里定义了5个数据结构:boolean, seq_nr,packet, frame_kind和frame。boolean是一个枚举类型,可以取值true和false;seq_nr是一个小整数,用来对帧进行编号,这些序号从0开始,一直到MAX_SEQ(含),每个用到序号的协议都要定义它;packet是同一台机器上网络层和数据链路层之间,或者不同机器上的网络对等实体之间交换的信息单元。在我们的模型中,它总是包含MAX_PKT个字节数据,实际中它是可变的。一个帧由四个字段组成:kind,seq,ack和info,其中前三个包含了控制信息,最后一个可能包含了要被传输的实际数据,这些控制字段合起来称为帧头。kind字段指出来帧中是否有数据,因为有些协议需要区分只有控制信息的帧和同时包含控制与数据信息的帧。seq和ack分别用作序号和确认。数据帧的info字段包含了一个数据包;控制帧的info字段没有用处(某些实际的协议实现将会使用一个变长的info字段,而对于控制帧则完全忽略)。网络层从传输层获得一个报文,然后在该报文上增加一个网络层头,由此创建了一个数据包。该数据包被传递给数据链路层,然后被放到输出帧的info字段中。
#define MAX_PKT 1024 /* determines packet size in bytes */
typedef enum {
false, true} boolean; /* boolean type */
typedef unsigned int seq_nr; /* sequence or ack numbers */
typedef struct {
unsigned char data[MAX_PKT];} packet; /* packet definition */
typedef enum {
data, ack, nak} frame_kind; /* frame kind definition */
typedef struct {
/* frames are transported in this layer */
frame_kind kind; /* what kind of frame is it? */
seq_nr seq; /* sequence number */
seq_nr ack; /* acknowledgement number */
packet info; /* the network layer packet */
} frame;
/* Wait for an event to happen; return its type in event. */
void wait_for_event(event_type *event);
/* Fetch a packet from the network layer for transmission on the channel. */
void from_network_layer(packet *p);
/* Deliver information from an inbound frame to the network layer. */
void to_network_layer(packet *p);
/* Go get an inbound frame from the physical layer and copy it to r. */
void from_physical_layer(<