开发过程中遇到一个问题:
Ifconfig eth0 up 时 ifconfig: SIOCSIFFLAGS: Cannot assign requested address ,从而导致LAN 不可用,
根据百度的解决方法,是MAC地址设置有问题,需要用下面方法设置:
#另外试试手动设置MAC:# ifconfig eth0 down
# ifconfig eth0 hw ether 9d:2c:64:78:35:2e# ifconfig eth0 up
但是方法无效,后来发现是“9d:2c:64:78:35:2e”不合法导致。
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.”
看到这里很多人都迷糊了,以太网的第48bit 和 The first bit (LSB) 到底是哪个Bit?
接着往下看:
因为以太网线路上按“Big Endian”字节序传送报文(也就是最高字节先传送,关于字节序请参考相关文档),而比特序是”Little Endian”(也就是最低位先传送)。所以有如下的图(从最左边开始传送),结合上述来理解下图,实际所说的First Bit Transmitted是最高字节的最低位,即“9d:2c:64:78:35:2e” 9d对应的“1001 1101”(粗体部分):
注意上图的字节序和比特序。
字节序为Big-endian,即最高字节在前。所以图中的first byte实际对应的MAC地址最左边一组。以Note 2 MAC地址90-18-7C-69-88-E2为例,first byte就是“90”(如果是Little-endian,则first byte是“E2”),其OUI是SamsungE,代表三星电子。
比特序为Little-endian,即最低位在前。这就是01-XX-XX-XX-XX-XX为组播地址的原因了。因为“01”对应的二进制是“0000-0001”,其第0位是1,应该放在图中first byte最左边一格。
一般情况下,字节序和比特序是一致的。但是以太网数据传输时,字节序采用Big-endian,比特序为Little-endian。
Linux中也有代码验证MAC地址有效性;
static inline int is_valid_ether_addr(const u8 *addr)
{
/* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
* explicitly check for it here. */
return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
}发现第一个字节最低位为1时该函数就会返回0,driver中的set_mac_addr就会返回EADDRNOTAVAIL错误码。
严格来说mac地址对于每块网卡是固定的,每块网卡被生产出来后,都会有一个全球唯一的编号来标识自己,不会重复,
这个编号就是MAC地址,也就是网卡的物理地址。MAC地址是由48位的二进制数组成,即6个字节。在通信中是用16进制表示的。
前24位是由生产厂家向IEEE标准组织申请的厂家代码,是固定的,但是第一个字节的最低位一定是0,因为网卡的物理地址,一定是单播地址,
在IPv4的环境中,区分单播和组播地址就是校检最低位的二进制数字,0代表单播地址,1代表组播地址。
也就是说第二个数字一定是0、2、4、6、8、A、C、E其中的一个。
所以mac地址虽然可以修改,但是不要乱改,要按照厂商规定来修改,以免重复。
WiKi上给出的解释也非常详细(还是下图容易理解,IEEE的图太晦涩难懂了),具体可参考:https://en.wikipedia.org/wiki/MAC_address