组播MAC地址


   MAC地址是以太网二层使用的一个48bit(6字节十六进制数)的地址,用来标识设备位置。MAC地址分成两部分,前24位是组织唯一标识符(OUI, Organizationally unique identifier),后24位由厂商自行分配。

    MAC地址有单播、组播、广播之分。单播地址(unicast address)表示单一设备、节点,多播地址或者组播地址(multicast address、group address)表示一组设备、节点,广播地址(broadcast address)是组播的特例,表示所有地址,用全F表示:FF-FF-FF-FF-FF-FF。当然,三层的IP地址也有单播、组播、广播之分。

    48bit的MAC地址一般用6字节的十六进制来表示,如XX-XX-XX-XX-XX。IEEE 802.3规定:以太网的第48bit用于表示这个地址是组播地址还是单播地址。如果这一位是0,表示此MAC地址是单播地址,如果这位是1,表示此MAC地址是多播地址。见IEEE 802.3 3.2.3 Address fields: “The first bit (LSB) shall be used in the Destination Address field as an address type designation bit to identify the Destination Address either as an individual or as a group address. If this bit is 0, it shall indicate that the address field contains an individual address. If this bit is 1, it shall indicate that the address field contains a group address that identifies none, one or more, or all of the stations connected to the LAN. In the Source Address field, the first bit is reserved and set to 0.”

    因为以太网线路上按“Big Endian”字节序传送报文(也就是最高字节先传送,关于字节序请参考相关文档),而比特序是”Little Endian”(也就是最低位先传送)。所以有如下的图(从最左边开始传送):

    注意图上的第47bit,这一位表示MAC地址是全球唯一地址还是本地地址,0表示全球唯一地址,1表示本地唯一地址。这一位也叫G/L位。

    对于网络设备上固化的MAC地址,因为它唯一标识这个设备,所以只能是单播地址,也就是MAC帧里面的Source地址第48位只能0。    

    我们常说有2的48次方个MAC地址可供网络设备使用,这些地址可以多到给地球上每一粒沙子分配一个地址,其实这个数量要打折扣的,因为MAC地址虽然有这么多,但真正用在网卡上并且全球唯一的只有2的46次方个:第48bit一定是0,第47bit一定是0。

    这也就引出了一个有意思的现象:随便找一台PC,观察一下它的网卡地址,第1字节的十六进制数一般是4的倍数;查看一下IEEE分配的OUI(http://standards.ieee.org/develop/regauth/oui/oui.txt ),第1字节的十六进制数也一般是4的倍数(早期以太网没有本地地址的概念,所以分配的OUI里面G/L bit也可能是1),这种情况下就不是4的倍数了,但肯定是2的倍数,因为第48位只能是0。

    关于组播地址,有这么个误解:MAC地址第1字节必须是0x01才表示组播地址,连TCP/IP详解上也这么说(见中文版12.4.2第一段)。IEEE 802.3里面已经明确说明了只要第48bit是1就表示组播地址,所以无论MAC地址第1字节是0x01、0xC1或者是0x33都表示这个MAC地址是组播地址(以0x33开头的表示IPV6对应的二层组播地址)。之所以有这样的误解,是因为到目前为止,大部分组播MAC地址的第1字节都是0x01。如:

01-80-C2-00-00-00(STP协议使用)

01-80-C2-00-00-01(MAC Control的PAUSE帧使用)

01-80-C2-00-00-02(Slow Protocol: 802.3ah OAM/ LACP 协议都用这个地址,这个地址很有故事,有多少软件处理这个地址会出问题啊!)

01-00-5E-xx-xx-xx(IP组播地址对应的二层组播地址)。

完整的列表见http://standards.ieee.org/develop/regauth/grpmac/public.html

    之所以大部分组播地址都以01-80-C2和01-00-5E开头,那是因为使用这些组播地址的协议都是带头大哥IEEE和IANA名下的,它们的OUI分别是00-80-C2和00-00-5E是,变成组播地址就是01-80-C2和01-00-5E了,当然,除了带头大哥霸占的这些组播地址,还有01-00-0C-CC-CC-CC这样的地址,这个地址是Cisco霸占的,Cisco的OUI是00-00-0C。


<think>MAC地址在以太网中有特定的特征,主要用于标识一设备。在IPv4和IPv6中,MAC地址的格式有所不同,但都遵循一定的规则。 ### IPv4MAC地址特征: 1. **固定前缀**:IPv4MAC地址以`01:00:5E`开头。 2. **结构**:MAC地址的后23位来自IPv4地址的后23位。 - IPv4地址范围:`224.0.0.0`到`239.255.255.255` - 例如:IPv4地址`224.0.0.1`对应的MAC地址为`01:00:5E:00:00:01` 3. **注意**:IPv4地址的前4位固定为`1110`,剩下的28位中,只有后23位被映射到MAC地址,因此有32个IPv4地址会映射到同一个MAC地址(因为前5位被忽略)。 ### IPv6MAC地址特征: 1. **固定前缀**:IPv6MAC地址以`33:33`开头。 2. **结构**:MAC地址的后32位直接来自IPv6地址的后32位。 - 例如:IPv6地址`ff02::1`对应的MAC地址为`33:33:00:00:00:01` ### MAC地址的通用特征: - 以太网帧中的目的MAC地址的第一个字节的最低位(即第8位)为1时,表示这是一个或广帧。具体来说: - 第一个字节的二进制表示:`xxxxxxx1`(x为任意比特),其中最低位为1表示或广。 - 广地址是特殊的地址:`FF:FF:FF:FF:FF:FF`。 ### 代码示例:判断MAC地址是否为地址 以下Python函数用于判断一个MAC地址是否为地址: ```python def is_multicast_mac(mac: str) -> bool: """ 判断给定的MAC地址是否为地址 :param mac: MAC地址字符串,格式如 '01:00:5e:00:00:01' :return: 布尔值,True表示是地址,False表示不是 """ # 去除分隔符,转换为大写 mac = mac.replace(':', '').replace('-', '').upper() if len(mac) != 12: return False # 获取第一个字节(前两个十六进制字符) first_byte = mac[0:2] # 将第一个字节转换为整数 value = int(first_byte, 16) # 检查最低位(第8位)是否为1 return (value & 0x01) == 1 # 测试 test_macs = [ '01:00:5E:00:00:01', # IPv4 '33:33:00:00:00:01', # IPv6 'FF:FF:FF:FF:FF:FF', # 广(也是) '00:00:5E:00:00:01', # 单(因为第一个字节为00,最低位为0) '00:1B:44:11:3A:B7' # 单 ] for mac in test_macs: print(f"{mac} -> {'' if is_multicast_mac(mac) else '单'}") ``` ### 输出: ``` 01:00:5E:00:00:01 -> 33:33:00:00:00:01 -> FF:FF:FF:FF:FF:FF -> 00:00:5E:00:00:01 -> 单 00:1B:44:11:3A:B7 -> 单 ``` ### 解释: - 函数首先将MAC地址字符串标准化(去除分隔符并转换为大写)。 - 然后检查第一个字节(前两个十六进制字符)的整数值。 - 通过按位与操作(`value & 0x01`)检查最低位(第8位)是否为1。如果为1,则是地址(包括广),否则是单地址。 ### 注意事项: - 广地址`FF:FF:FF:FF:FF:FF`也满足的条件(第一个字节为0xFF,二进制为11111111,最低位为1)。 - 该函数无法区分IPv4、IPv6和广,只能判断是否为(包括广)。 ### 区分IPv4和IPv6: 如果需要进一步区分IPv4和IPv6,可以检查MAC地址的前三个字节(OUI部分): ```python def get_multicast_type(mac: str) -> str: """ 判断MAC地址的类型 :param mac: MAC地址字符串 :return: 'IPv4'、'IPv6'、'Broadcast' 或 'Other Multicast' """ if not is_multicast_mac(mac): return 'Not Multicast' mac = mac.replace(':', '').replace('-', '').upper() # 检查前三个字节(前6个字符) oui = mac[:6] if oui == '01005E': return 'IPv4 Multicast' elif oui == '333333': return 'IPv6 Multicast' elif mac == 'FFFFFFFFFFFF': return 'Broadcast' else: return 'Other Multicast' # 测试 test_macs = [ '01:00:5E:00:00:01', '33:33:00:00:00:01', 'FF:FF:FF:FF:FF:FF', '01:00:5E:01:02:03', '33:33:FF:00:00:01', '01:80:C2:00:00:00' # 生成树协议地址 ] for mac in test_macs: print(f"{mac} -> {get_multicast_type(mac)}") ``` 输出: ``` 01:00:5E:00:00:01 -> IPv4 Multicast 33:33:00:00:00:01 -> IPv6 Multicast FF:FF:FF:FF:FF:FF -> Broadcast 01:00:5E:01:02:03 -> IPv4 Multicast 33:33:FF:00:00:01 -> IPv6 Multicast 01:80:C2:00:00:00 -> Other Multicast ``` ### 总结: - MAC地址的特征是第一个字节的最低位(第8位)为1。 - IPv4MAC地址固定以`01:00:5E`开头。 - IPv6MAC地址固定以`33:33`开头。 - 广地址是特殊的地址(全F)。 §§相关问题§§: 1. 如何用Scapy捕获数据包? 2. MAC地址IP地址的映射关系是怎样的? 3. 在IPv6中,MAC地址是如何生成的? 4. 如何用C语言判断一个MAC地址是否为地址?</think>### MAC地址的特征 MAC地址在以太网中有明确的规范定义,主要特征如下: 1. **最低有效位标识**: - 在MAC地址的第一个字节(最高字节)中,最低有效位(LSB)为1表示这是一个地址 - 二进制表示:`xxxxxxx1`(x可以是0或1) - 例如:`01:00:5E:00:00:01`的第一个字节`01`的二进制是`00000001`,LSB为1 2. **IPv4专用范围**: - IPv4MAC地址固定以`01:00:5E`开头 - 后3个字节由IPv4地址的后23位映射而来 - 例如:IPv4地址`224.0.0.1` → MAC `01:00:5E:00:00:01` 3. **IPv6专用范围**: - IPv6MAC地址以`33:33`开头 - 后4个字节直接取自IPv6地址的后32位 - 例如:IPv6地址`ff02::1` → MAC `33:33:00:00:00:01` 4. **本地管理标识**: - 第一个字节的次低有效位(倒数第二位)为1表示本地管理地址 - 二进制表示:`xxxxxx1x` - 例如:`x3:xx:xx:xx:xx:xx`(3的二进制是`0011`,次低位为1) ### 判断MAC地址的Python实现 ```python def is_multicast_mac(mac: str) -> bool: """ 判断给定的MAC地址是否为地址 :param mac: MAC地址字符串,格式如 '01:00:5e:00:00:01' :return: 布尔值,True表示是地址 """ # 移除分隔符并转换为大写 clean_mac = mac.replace(':', '').replace('-', '').upper() if len(clean_mac) != 12: raise ValueError("Invalid MAC address length") # 提取第一个字节(前两个字符) first_byte_hex = clean_mac[0:2] # 将十六进制转换为整数 first_byte = int(first_byte_hex, 16) # 检查最低有效位(LSB)是否为1 return (first_byte & 0x01) == 0x01 # 测试示例 test_addresses = [ '01:00:5E:00:00:01', # IPv4 '33:33:00:00:00:01', # IPv6 '00:1B:44:11:3A:B7', # 单 'FF:FF:FF:FF:FF:FF', # 广 '09:00:07:01:02:03', # (本地管理) '01-80-C2-00-00-00' # 生成树协议 ] for mac in test_addresses: print(f"{mac}: {'' if is_multicast_mac(mac) else '单/广'}") ``` ### 输出结果: ``` 01:00:5E:00:00:01: 33:33:00:00:00:01: 00:1B:44:11:3A:B7: 单/广 FF:FF:FF:FF:FF:FF: 09:00:07:01:02:03: 01-80-C2-00-00-00: ``` ### 代码解释: 1. **输入处理**: - 移除MAC地址中的分隔符(`:`或`-`) - 转换为大写确保一致性 - 验证长度是否为12个字符(6字节) 2. **关键判断逻辑**: - 提取MAC地址的第一个字节(前两个十六进制字符) - 转换为整数后使用位运算检查最低有效位(LSB) - `first_byte & 0x01` 提取最低位,等于1即为 3. **特殊处理**: - 广地址`FF:FF:FF:FF:FF:FF`也被识别为(技术上广的特例) - 本地管理的地址(如`09:00:07:...`)也能正确识别 ### MAC地址范围总结表 | 类型 | 前缀 | 范围 | 用途示例 | |------|------|------|----------| | IPv4 | 01:00:5E | 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF | IGMP, OSPF, VRRP | | IPv6 | 33:33 | 33:33:00:00:00:00 - 33:33:FF:FF:FF:FF | NDP, MLD | | 标准 | 01:80:C2 | 01:80:C2:00:00:00 - 01:80:C2:FF:FF:FF | 生成树协议(STP) | | 本地管理 | x3:xx:xx... | 首字节LSB=1且次低位=1 | 私有协议使用 | ### 实际应用场景 1. **网络协议**:OSPF、VRRP等协议使用特定MAC 2. **媒体传输**:IPTV视频流通过MAC传输 3. **服务发现**:mDNS协议使用MAC `01:00:5E:00:00:FB` 4. **网络管理**:LLDP协议使用`01:80:C2:00:00:0E`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值