为什么 MAC 地址的第一个八位字节总是以二进制 0 结尾?

网络工程 ip 协议理论 ipv6 MAC地址 IP地址
2021-07-06 05:12:36

我在 GitHub 上偶然发现了一段代码:https : //github.com/adeverteuil/bash-ula-generator/blob/master/gen-ula.sh

# Generate an EUI64 from the MAC address
# as described in RFC 3513
# https://tools.ietf.org/html/rfc3513

first=`echo $mac | cut -c1-1`
second=`echo $mac | cut -c2-2`
macu=`echo $mac | cut -c3-6`
macl=`echo $mac | cut -c7-12`

# reversing u/l bit
case $second in
    [13579bdf])
        die "MAC-address \"${mac}\" is a group MAC address"
        ;;
    0)
        second_rev=2
        ;;
    2)
        second_rev=0
        ;;
    4)
        second_rev=6;
        ;;
    6)
        second_rev=4;
        ;;
    8)
        second_rev=a;
        ;;
    a)
        second_rev=8;
        ;;
    c)
        second_rev=e;
        ;;
    e)
        second_rev=c;
        ;;
    *)
        #impossible
        die "MAC address \"${mac}\" is registered to the IEEE database, "\
            "but the first octet (${first}${second}) is regarded as invalid. "\
            "(probably a bug in this script...)"
esac
eui64="${first}${second_rev}${macu}fffe${macl}"

TLDR:在反转 MAC OUI 的第 7 位以创建 EUI-64 时,作者假设第 8 位始终为二进制 0。我立即检查了 DHCP 服务器上的 100 多个客户端,奇怪的是,没有一个以奇怪的结尾第一个八位字节上的数字——它们总是这样的:

  • 直流:0c:5c:c9:53:36
  • 40 :9f:38:4b:69:08
  • 18 :d7:17:55:61:d1
  • 34 :c3:d2:70:ad:be
  • (等等...)

为什么它总是以二进制 0 结尾?

2个回答

您可能会注意到,通常将 48 位 MAC 地址的最高有效字节的两个最低有效位设置为0(如所有示例中所示)。MAC地址的OUI(Organizationally Unique Identifier,最高有效24位)部分的最高有效字节有两个标志:

  • 最低有效位是 I/G(个人/组)标志。清除此位意味着该帧被发送到单个主机,设置它意味着它是用于一组主机(广播或多播)。
  • 次低位是 U/L(通用/本地)标志。清除此位意味着 MAC 地址由 OUI 的所有者(BIA 或 Burned-In Address)普遍分配。如果您在本地分配 MAC 地址或覆盖 BIA ,那么您应该设置此位以表示 MAC 地址是本地分配的。不幸的是,许多本地分配 MAC 地址的人没有设置此标志。

在反转 MAC OUI 的第 7 位以创建 EUI-64 时,作者假设第 8 位始终为二进制 0。

实际上,这是创建一个修改后的EUI-64。您永远不会将组地址(设置 I/G 标志)分配给接口或单播地址,并且您确实设置了 U/L 标志以表明它是本地管理的地址。来自 48 位 MAC 算法(和其他算法)的修改后的 EUI-64 在RFC 4291,IP 版本 6 寻址架构,附录 A:创建修改后的 EUI-64 格式接口标识符中进行了解释,该标识符RFC 3513,IP 版本 6 寻址架构废弃到您的代码示例所指的。基本上,您将 48 位 MAC 地址分成两半,插入fffe中间,并设置 U/L 标志以指示本地管理地址(请参阅下面我的重点,包括末尾的注释):

附录 A:创建修改的 EUI-64 格式接口标识符

根据特定链路或节点的特性,有多种方法可以创建修改的 EUI-64 格式接口标识符。本附录描述了其中一些方法。

带有 IEEE EUI-64 标识符的链接或节点

将 IEEE EUI-64 标识符转换为接口标识符所需的唯一更改是反转“u”(通用/本地)位。一个示例是以下形式的全球唯一 IEEE EUI-64 标识符:

|0              1|1              3|3              4|4              6|
|0              5|6              1|2              7|8              3|
+----------------+----------------+----------------+----------------+
|cccccc0gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|mmmmmmmmmmmmmmmm|
+----------------+----------------+----------------+----------------+

其中“c”是分配的 company_id 的位,“0”是表示通用范围的通用/本地位的值,“g”是个人/组位,“m”是制造商选择的位扩展标识符。IPv6 接口标识符的格式如下:

|0              1|1              3|3              4|4              6|
|0              5|6              1|2              7|8              3|
+----------------+----------------+----------------+----------------+
|cccccc1gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|mmmmmmmmmmmmmmmm|
+----------------+----------------+----------------+----------------+

唯一的变化是反转通用/本地位的值。

带有 IEEE 802 48 位 MAC 的链接或节点

[EUI64] 定义了一种从 IEEE 48 位 MAC 标识符创建 IEEE EUI-64 标识符的方法。这是在 48 位 MAC 的中间(在 company_id 和供应商提供的 id 之间)插入两个八位字节,十六进制值为 0xFF 和 0xFE(参见附录末尾的注释)。一个例子是具有全局范围的 48 位 IEEE MAC:

|0              1|1              3|3              4|
|0              5|6              1|2              7|
+----------------+----------------+----------------+
|cccccc0gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|
+----------------+----------------+----------------+

其中“c”是分配的 company_id 的位,“0”是表示全局范围的通用/本地位的值,“g”是个人/组位,“m”是制造商选择的位扩展标识符。接口标识符的格式如下:

|0              1|1              3|3              4|4              6|
|0              5|6              1|2              7|8              3|
+----------------+----------------+----------------+----------------+
|cccccc1gcccccccc|cccccccc11111111|11111110mmmmmmmm|mmmmmmmmmmmmmmmm|
+----------------+----------------+----------------+----------------+

当 IEEE 802 48 位 MAC 地址可用(在接口或节点上)时,由于它们的可用性和唯一性属性,实现可以使用它们来创建接口标识符。

与其他类型标识符的链接

有许多类型的链路具有除 IEEE EUI-64 或 IEEE 802 48 位 MAC 之外的链路层接口标识符。示例包括 LocalTalk 和 Arcnet。创建 Modified EUI-64 格式标识符的方法是取链接标识符(例如,LocalTalk 8 位节点标识符)并在左侧填充零。例如,十六进制值 0x4F 的 LocalTalk 8 位节点标识符产生以下接口标识符:

|0              1|1              3|3              4|4              6|
|0              5|6              1|2              7|8              3|
+----------------+----------------+----------------+----------------+
|0000000000000000|0000000000000000|0000000000000000|0000000001001111|
+----------------+----------------+----------------+----------------+

请注意,这会导致通用/本地位设置为“0”以指示本地范围。

没有标识符的链接

有许多链接没有任何类型的内置标识符。其中最常见的是串行链路和配置的隧道。必须选择在子网前缀内唯一的接口标识符。

当链路上没有可用的内置标识符时,首选方法是使用来自另一个接口或分配给节点本身的通用接口标识符。使用这种方法时,将同一节点连接到同一子网前缀的其他接口都不能使用相同的标识符。

如果链路上没有可用的通用接口标识符,则实现需要创建一个本地范围的接口标识符。唯一的要求是它在子网前缀中是唯一的。有多种可能的方法来选择子网前缀唯一接口标识符。这些包括以下内容:

  Manual Configuration  
  Node Serial Number  
  Other Node-Specific Token  

子网前缀唯一接口标识符的生成方式应使其在节点重新启动或从节点添加或删除接口后不会更改。

适当算法的选择取决于链接和实现。有关形成接口标识符的详细信息在相应的“IPv6 over”规范中定义。强烈建议将碰撞检测算法作为任何自动算法的一部分来实现。

注意:[EUI-64] 实际上将 0xFF 和 0xFF 定义为要插入的位,以根据 IEEE MAC-48 标识符创建 IEEE EUI-64 标识符。以 IEEE EUI-48 标识符开头时使用 0xFF 和 0xFE 值。由于对 IEEE MAC-48 和 EUI-48 标识符之间的差异的误解,在规范的早期版本中使用了不正确的值。

本文档有意继续使用 0xFF 和 0xFE,因为它满足 IPv6 接口标识符的要求(即,它们在链路上必须是唯一的)、IEEE EUI-48 和 MAC-48 标识符在语法上是等效的,并且它不在实践中不会造成任何问题。

首先,一个字节最右边的位是第一位(而不是第 8 位)。和 IT 领域一样,首先意味着0而不是1

现在,为了回答您的问题,bit 0mac 地址的第一个字节的 被设置0为单播接收网卡和1x 多播接收网卡。换句话说,如果该位设置为0,则只有一个 NIC 将接收该帧。

我立即检查了我的 DHCP 服务器上的 100 多个客户端,奇怪的是,没有一个以第一个八位字节的奇数结尾

因为您的 DHCP 分配单播 IPv4 地址。

为什么它总是以二进制 0 结尾?

它不是。IPv4 多播以太网范围是 01:00:5E (224.0.0.0/4)。例如,OSPF 使用的一些组播 IP 是 224.0.0.5 和 224.0.0.6。相关的 MAC 是 01-00-5E-00-00-05 和 01-00-5E-00-00-06(注意bit 0设置为1)。广播 MAC FF:FF:FF:FF:FF:FF 是另一个例子(请注意,大多数交换机以相同的方式处理多播和广播帧)。