链路层的介绍和基本实现
链路层的目的
数据链路层属于计算机网络的底层,使用的信道主要有点对点信道和广播信道两种类型。 在 TCP/IP 协议族中,数据链路层主要有以下几个目的:
-
接收和发送链路层数据,提供 io 的能力。
-
为 IP 模块发送和接收数据
-
为 ARP 模块发送 ARP 请求和接收 ARP 应答
-
为 RARP 模块发送 RARP 请求和接收 RARP 应答
TCP/IP 支持多种不同的链路层协议,这取决于网络所使用的硬件。 数据链路层的协议数据单元—帧:将 IP 层(网络层)的数据报添加首部和尾部封装成帧。 数据链路层协议有许多种,都会解决三个基本问题,封装成帧,透明传输,差错检测。
以太网介绍
我们这章讲的是链路层,为何要讲以太网,那是因为以太网实在应用太广了,以至于我们在现实生活中看到的链路层协议的数据封装都是以太网协议封装的,所以要实现链路层数据的处理,我们必须要了解以太网。
以太网(Ethernet)是一种计算机局域网技术。IEEE 组织的 IEEE 802.3 标准制定了以太网的技术标准,它规定了包括物理层的连线、电子信号和介质访问层协议的内容。以太网是目前应用最普遍的局域网技术,取代了其他局域网标准如令牌环、FDDI 和 ARCNET。以太网协议,是当今现有局域网采用的最通用的通信协议标准,故可认为以太网就是局域网。
链路层的寻址
通信当然得知道发送者的地址和接受者的地址,这是最基础的。以太网规定,所有连入网络的设备,都必须具有“网卡”接口。然后数据包是从一块网卡,传输到另一块网卡的。网卡的地址,就是数据包的发送地址和接收地址,叫做 MAC 地址,也叫物理地址,这是最底层的地址。每块网卡出厂的时候,都有一个全世界独一无二的 MAC 地址,长度是 48 个二进制位,通常用 12 个十六进制数表示。有了这个地址,我们可以定位网卡和数据包的路径了。
MTU(最大传输单元)
MTU 表示在链路层最大的传输单元,也就是链路层一帧数据的数据内容最大长度,单位为字节,MTU 是协议栈实现一个很重要的参数,请大家务必理解该参数。一般网卡默认 MTU 是 1500,当你往网卡写入的内容超过 1518bytes,就会报错,后面我们可以写代码试试。
链路实现的分层
链路层的实现可以分为三层,真实的以太网卡,网卡驱动,网卡逻辑抽象。
真实的网卡我们不关心,因为那是硬件工程,我们只需要知道,它能接收和发送网络数据给网卡驱动就好了。网卡驱动我们也不关心,一般驱动都是网卡生产商就写好了,我们只需知道,它能接收协议栈的数据发送给网卡,接收网卡的数据发送给协议栈。网卡逻辑抽象表示,这个是我们关心的,我需要对真实的网卡进行抽象,
一个 eth0 以太网网卡,一个 lo 本地回环网卡。还可以看到两个网卡的信息,当我们要表示一个网卡的时候,需要具备几个属性:
- 网卡的名字、类型和 MAC 地址
- eth0 Link encap:Ethernet HWaddr 00:16:3e:08:a1:7a
- eth0是网卡名,方便表示一个网卡,网卡名在同个系统里不能重复。
- Link encap:Ethernet 表示该网卡类型为以太网网卡。
- HWaddr 00:16:3e:08:a1:7a 表示 MAC 地址 00:16:3e:08:a1:7a,是链路层寻址的地址。
- 网卡的 IP 地址及掩码
- inet addr:172.18.153.158 Bcast:172.18.159.255 Mask:255.255.240.0
- inet addr:172.18.153.158 表示该网卡的 ipv4 地址是 172.18.153.158。
- Bcast:172.18.159.255 表示该网卡 ip 层的广播地址。
- 255.255.240.0 该网卡的子网掩码。
- 网卡的状态和 MTU
- UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
- UP BROADCAST RUNNING MULTICAST 都是表示网卡的状态,UP(代表网卡开启状态) BROADCAST (支持广播) RUNNING(代表网卡的网线被接上)MULTICAST(支持组播)。
- MTU:1500 最大传输单元为 1500 字节。
- Metric:1 接口度量值为 1,接口度量值表示在这个路径上发送一个分组的成本。
实现协议栈,我们需要一个网卡,因为这样我们才能接收和发送网络数据,但是一般情况下,我们电脑的操作系统已经帮我们管理好网卡了,我们想实现自由的控制网卡是不太方便的,还好 linux 系统还有另一个功能-虚拟网卡,它是操作系统虚拟出来的一个网卡,我们协议栈的实现都是基于虚拟网卡
虚拟网卡的好处
- 对于用户来说虚拟网卡和真实网卡几乎没有差别,而且我们控制或更改虚拟网卡大部分情况下不会影响到真实的网卡,也就不会影响到用户的网络。
- 虚拟网卡的数据可以直接从用户态直接读取和写入,这样我们就可以直接在用户态编写协议栈。
Linux 中虚拟网络设备
TUN/TAP 设备、VETH 设备、Bridge 设备、Bond 设备、VLAN 设备、MACVTAP 设备,下面我们只讲 tun/tap 设备,其他虚拟设备感兴趣的同学可以去网上自行搜索。
TAP/TUN 设备是一种让用户态和内核之间进行数据交换的虚拟设备,TAP 工作在二层,TUN 工作在三层,TAP/TUN 网卡的两头分别是内核网络协议栈和用户层,其作用是将协议栈中的部分数据包转发给用户空间的应用程序,给用户空间的程序一个处理数据包的机会。
当我们想在 linux 中创建一个 TAP 设备时,其实很容易,像普通文件一样打开字符设备 /dev/net/tun 可以得到一个文件描述符,接着用系统调用 ioctl 将文件描述符和 kernel 的 tap 驱动绑定在一起,那么之后对该文件描述符的读写就是对虚拟网卡 TAP 的读写。
# 创建一个tap模式的虚拟网卡tap0
sudo ip tuntap add mode tap tap0
# 开启该网卡
sudo ip link set tap0 up
# 设置该网卡的ip及掩码
sudo ip addr add 192.168.1.1/24 dev tap0
tap0 Link encap:Ethernet HWaddr 22:e2:f2:93:ff:bf
inet addr:192.168.1.1 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
sudo ip tuntap del mode tap tap0
链路层数据帧
|dst MAC(6B)|src MAC(6B)|type(2B)|data(46B - 1500B)|
- 目的 MAC 地址:目的设备的 MAC 物理地址。
- 源 MAC 地址:发送设备的 MAC 物理地址。
- 类型:表示后面所跟数据包的协议类型,例如 Type 为 0x8000 时为 IPv4 协议包,Type 为 0x8060 时,后面为 ARP 协议包。
- 数据:表示该帧的数据内容,长度为 46 ~ 1500 字节,包含网络层、传输层和应用层的数据。