---
title: Ethernet 与 MAC
url: https://doc.liz6.com/networking/01-l2-data-link/01-ethernet-and-mac
locale: zh
area: networking
tags:
- networking
- L2数据链路
date: 2026-06-30
modified: 2026-06-30
description: 以太网帧是"万物皆可封装"的起点——从 MAC 地址到 VLAN 到链路聚合,二层是所有上层协议的基础承载。理解帧结构和交换原理,就理解了"数据包怎么从一根线到另一根线"。
---

# Ethernet 与 MAC

> 以太网帧是"万物皆可封装"的起点——从 MAC 地址到 VLAN 到链路聚合,二层是所有上层协议的基础承载。理解帧结构和交换原理,就理解了"数据包怎么从一根线到另一根线"。

## 概述

Ethernet 是全球最广泛部署的局域网技术，从 1973 年 Bob Metcalfe 在 Xerox PARC 的 2.94Mbps 原型到现在的 800Gbps 光口，核心帧格式几乎没变。它工作在 OSI L2（数据链路层），负责在同一广播域内将帧从源 MAC 地址送到目标 MAC 地址。802.3 标准家族在此基础上扩展了 VLAN 隔离（802.1Q）、流控（802.3x PAUSE）、链路聚合（802.3ad LACP）等功能。Linux 内核通过 `net/ethernet/` 和 `drivers/net/` 提供协议处理与硬件驱动抽象。

## 802.3 帧格式

Ethernet 帧结构从 1980 年 DIX 规范至今几乎没有本质变化。唯一值得注意的演进是 802.1Q VLAN tag 的插入和 802.3ad LACP 的协商层。

```
Octet 0-6:   Preamble (7 × 0x55)
              PHY 层使用，用于时钟同步和 bit-locking。10Mbps 时极其重要
              (Manchester encoding)，现代 SerDes 不需要但没有移除。

Octet 7:     SFD (Start Frame Delimiter = 0xD5)
              标记帧开始。最后一个 preamble byte 的低位不同 — 0x55 →
              0xD5 (bit 0: 1→1, bit 2: 1→0) — 硬件检测此跳变锁定字节边界。

Octet 8-13:  Destination MAC (6 bytes)
              Bit 0 of byte 0: 0 = unicast, 1 = multicast.
              全 1 (ff:ff:ff:ff:ff:ff) = broadcast — 交换机泛洪到所有端口。

Octet 14-19: Source MAC (6 bytes)

Octet 20-21: EtherType or Length (2 bytes)
              ≤ 1500 (0x05DC): 解释为 Length (802.3 raw mode, 极少用)
              ≥ 1536 (0x0600): 解释为 EtherType
              关键值:
                0x0800  IPv4
                0x0806  ARP
                0x8100  VLAN (802.1Q)
                0x86DD  IPv6
                0x88A8  Q-in-Q / Provider Bridge (802.1ad)
                0x8870  Jumbo frame (非标准, 某些驱动使用)
                0x8809  Slow Protocols (LACP, 802.3x PAUSE)

Octet 22+:   Payload
              标准: 46-1500 bytes (不含 VLAN tag)。
              不够 46 字节 → 填充到 46 (padding)。填充内容未定义 —
              Linux 用零填充, 其他驱动可能用随机数据。
              Padding 不计入 IP header 的 Total Length — 接收方
              通过 EtherType/Length 字段或 L3 header 的 length 区分。

CRC:         FCS (Frame Check Sequence, 4 bytes, CRC-32)
              多项式: x³² + x²⁶ + x²³ + x²² + x¹⁶ + x¹² + x¹¹ + x¹⁰ + x⁸ + x⁷ +
                       x⁵ + x⁴ + x² + x + 1
              计算范围: Destination MAC 到 Payload 末尾 (不含 Preamble/SFD/FCS 自身)
              硬件 (MAC controller) 计算和验证 → 错误帧由硬件丢弃，内核看不到。
              某些驱动可以配置"接收错误帧"模式 (ethtool -K rx-fcs on)，
              用于调试 (tcpdump 可以看到 FCS 错误计数)。

Inter-Frame Gap (IFG):
  帧间间隔: 12 byte times (96 bit times) of idle.
  1000BASE-T: 96 ns
  10GBASE-R:  9.6 ns
  100GBASE-R: 0.96 ns
  高速率下 IFG 极紧 — 硬件必须在一个 IFG 内完成前帧处理并开始下一帧的 preamble
  detection。这也是为什么高速网卡需要 buffer descriptor ring 而不是逐帧中断。
```

## MAC 地址结构

```
48 bits (6 bytes), IEEE 分配, 全球唯一 (理论上):

Byte 0, bit 0 (I/G bit):
  0: Unicast (individual address)
  1: Multicast (group address)
  → 这是 MAC 层判断"这个帧是不是给我的"第一步 — 网卡硬件检查

Byte 0, bit 1 (U/L bit):
  0: Universally Administered (厂商烧录的 OUI)
  1: Locally Administered (软件设置的, 如虚拟网卡、容器、MAC 随机化)

OUI (Organizationally Unique Identifier): bytes 0-2 = IEEE 分配
NIC-specific: bytes 3-5 = 厂商内部分配

Linux 操作:
  ip link set eth0 address aa:bb:cc:dd:ee:ff    ← 改 MAC (需要 down)
  ip link show eth0 | grep link/ether
```

## 802.1Q VLAN

VLAN tag (4 bytes) 插入在 Source MAC 之后、EtherType 之前:

```
Octet 0-1: TPID (Tag Protocol Identifier)
             0x8100 = Customer VLAN (C-VLAN)
             0x88A8 = Service Provider VLAN (S-VLAN, 802.1ad)
             0x9100 = 旧式 (被 0x88A8 取代)

Octet 2-3: TCI (Tag Control Information):
  Bits 0-2:    PCP (Priority Code Point, 802.1p)
               0 = Best Effort, 1 = Background, 2 = Spare, 3 = Excellent Effort,
               4 = Controlled Load, 5 = Video, 6 = Voice, 7 = Network Control
               → 映射到 sk_buff->priority → tc qdisc 的队列选择
  Bit 3:       DEI (Drop Eligible Indicator)
               1 = 拥塞时可优先丢弃 (与 IP DSCP 的 ECN 不是一回事)
  Bits 4-15:   VID (VLAN Identifier)
               有效值: 1-4094 (0 = no VLAN, 4095 = reserved)
               每个以太网接口可以属于多个 VLAN (trunk port)

Q-in-Q (802.1ad, Provider Bridge):
  双层 VLAN tag:
    [DA][SA][0x88A8][S-VLAN TCI][0x8100][C-VLAN TCI][EtherType][Payload]
  外层 (S-VLAN) = 运营商网络隔离
  内层 (C-VLAN) = 客户自用的 VLAN

  Linux:
    ip link add link eth0 name eth0.100 type vlan id 100
    ip link add link eth0.100 name eth0.100.200 type vlan id 200 proto 802.1ad
```

## Jumbo Frames

标准 MTU 1500 字节是 10Mbps Ethernet 时代的妥协 — 小 MTU 意味着短的 slot time,
短的冲突检测窗口。切换到 switched Ethernet 后，物理上不再需要这个限制，但
标准 MTU 被所有上层协议假设为默认值。

```
Jumbo MTU: 通常 9000 bytes (非标准, 但广泛支持)

收益:
  - 减少中断: 1 × 9000B 帧 vs 6 × 1500B 帧 — 中断减少 6x
  - 减少 CPU 处理: 网卡 per-packet overhead (descriptor, DMA sync) 减小 6x
  - 减少 header 开销: 5 个额外帧的 (14B Eth + 20B IP + 20B TCP) × 5 = 270B 省了
  - NFS/iSCSI: 大部分 IO 是 4KB-64KB, jumbo 可以在一个帧内装下更多

代价:
  - 路径上所有设备 (交换机、路由器、NIC) 必须支持 jumbo
  - 不支持 jumbo 的设备: 静默丢弃 (no ICMP Frag Needed unless IP DF set)
    → "MTU black hole" — 最难排查的网络问题之一

配置:
  ip link set eth0 mtu 9000
  /etc/dhcpcd.conf 或 NetworkManager: 持久化 MTU
  注意: bridge 的 MTU 必须 ≥ 其所有 slave 的 min MTU
```

## PAUSE (802.3x) 与 PFC (802.1Qbb)

```
802.3x PAUSE frame:
  EtherType: 0x8808
  MAC Control Opcode: 0x0001 (PAUSE)
  Pause Time: 2 bytes (in units of 512 bit times)
  发送到组播地址: 01:80:c2:00:00:01

  接收方: 发 PAUSE frame (pause_time=N)
  发送方: 在 N × 512 bit times 内停止发送
  问题: 一个 flow 的拥塞 → 整个链路的流量停止
        → 不适合多流量混合的场景 (数据中心用 PFC)

PFC (Priority-based Flow Control, 802.1Qbb):
  按 PCP (8 个优先级) 独立控制:
  只有拥塞的优先级被 pause → 其他优先级继续传输
  → RoCE (RDMA over Converged Ethernet) 的硬件基础
```

## LACP (802.3ad / 802.1AX)

```
LACP 将多个物理口捆绑为一个逻辑链路:

LACPDU (Link Aggregation Control Protocol Data Unit):
  EtherType: 0x8809 (Slow Protocols)
  Subtype: 0x01 (LACP)
  每 30 秒 (slow) 或每秒 (fast) 发一次

LACPDU 内容:
  Actor: system_priority + system_id (MAC) + key + port_priority + port_number + state
  Partner: (同上, 远端信息)
  Collector: max_delay

State bits (关键的):
  LACP_Activity (bit 0): Active (主动发 LACPDU) vs Passive (只响应)
  LACP_Timeout (bit 1): Long (30s) vs Short (1s)
  Aggregation (bit 2): 此端口可以聚合
  Synchronization (bit 3): 此端口已同步 (准备转发)
  Collecting (bit 4): 入流量可以转发
  Distributing (bit 5): 出流量可以转发
  Defaulted (bit 6): 用默认参数 (partner 未响应)

Linux bonding modes:
  mode=0 (balance-rr): 轮询 — 不依赖 LACP, 只 load balance
  mode=1 (active-backup): 一主一备 — 不依赖 LACP
  mode=2 (balance-xor): 按 MAC hash — 需要交换机配合
  mode=4 (802.3ad): LACP 动态协商 — 交换机必须也开 LACP
```

## 参考

- **802.3-2022**: IEEE 标准 (P802.3 工作组)
- **内核**: `net/ethernet/eth.c` (协议处理), `drivers/net/bonding/` (LACP), `net/8021q/` (VLAN)
- **LWN**: "Jumbo frames and MTU in Linux"

*关键词: Ethernet, 802.3, MAC address, 802.1Q, VLAN, Q-in-Q, jumbo frame, PAUSE, LACP, 802.3ad*
