开发日常网卡驱动中如何设置组播mac地址?
Posted Evan_ZGYF丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开发日常网卡驱动中如何设置组播mac地址?相关的知识,希望对你有一定的参考价值。
组播mac地址映射?
组播的mac地址:IANA规定,IPv4组播MAC地址的高24位为0x01005E,第25位为0,低23位为IPv4组播地址的低23位。
如何判断该组播包是自己的?
发送端发送组播包时,目的mac地址是根据组播ip和固定格式进行映射,并没有指向固定目标主机,向网络上进行发送。
接收端接收组播包时,同样需要对组播ip和固定格式进行映射,生成的组播mac地址与接收到的数据包mac比对,若相通往上传。
接收端同样可以设置混杂模式:接收所有经过它的数据流,这样不论其目的地址是否是他,都会往上传,由网络层进行判断,确定是递交上层(传输层),还是丢弃。
网卡驱动中如何设置组播mac地址?
以下是linux中9x25设置组播mac地址的部分代码
static int inline hash_bit_value(int bitnr, __u8 *addr)
if (addr[bitnr / 8] & (1 << (bitnr % 8)))
return 1;
return 0;
/*
* The hash address register is 64 bits long and takes up two locations in the memory map.
* The least significant bits are stored in EMAC_HSL and the most significant
* bits in EMAC_HSH.
*
* The unicast hash enable and the multicast hash enable bits in the network configuration
* register enable the reception of hash matched frames. The destination address is
* reduced to a 6 bit index into the 64 bit hash register using the following hash function.
* The hash function is an exclusive or of every sixth bit of the destination address.
* hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
* hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
* hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
* hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
* hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
* hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
* da[0] represents the least significant bit of the first byte received, that is, the multicast/
* unicast indicator, and da[47] represents the most significant bit of the last byte
* received.
* If the hash index points to a bit that is set in the hash register then the frame will be
* matched according to whether the frame is multicast or unicast.
* A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
* the hash index points to a bit set in the hash register.
* A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
* hash index points to a bit set in the hash register.
* To receive all multicast frames, the hash register should be set with all ones and the
* multicast hash enable bit should be set in the network configuration register.
*/
/*
* Return the hash index value for the specified address.
*/
static int hash_get_index(__u8 *addr)
int i, j, bitval;
int hash_index = 0;
for (j = 0; j < 6; j++)
for (i = 0, bitval = 0; i < 8; i++)
bitval ^= hash_bit_value(i*6 + j, addr);
hash_index |= (bitval << j);
return hash_index;
/*
* Add multicast addresses to the internal multicast-hash table.
*/
static void at91ether_sethashtable(struct net_device *dev)
struct netdev_hw_addr *ha;
unsigned long mc_filter[2];
unsigned int bitnr;
mc_filter[0] = mc_filter[1] = 0;
netdev_for_each_mc_addr(ha, dev)
bitnr = hash_get_index(ha->addr);
mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
at91_emac_write(AT91_EMAC_HSL, mc_filter[0]);
at91_emac_write(AT91_EMAC_HSH, mc_filter[1]);
/*
* Enable/Disable promiscuous and multicast modes.
*/
static void at91ether_set_multicast_list(struct net_device *dev)
unsigned long cfg;
cfg = at91_emac_read(AT91_EMAC_CFG);
if (dev->flags & IFF_PROMISC) /* Enable promiscuous mode */
cfg |= AT91_EMAC_CAF;
else if (dev->flags & (~IFF_PROMISC)) /* Disable promiscuous mode */
cfg &= ~AT91_EMAC_CAF;
if (dev->flags & IFF_ALLMULTI) /* Enable all multicast mode */
at91_emac_write(AT91_EMAC_HSH, -1);
at91_emac_write(AT91_EMAC_HSL, -1);
cfg |= AT91_EMAC_MTI;
else if (!netdev_mc_empty(dev)) /* Enable specific multicasts */
at91ether_sethashtable(dev);
cfg |= AT91_EMAC_MTI;
else if (dev->flags & (~IFF_ALLMULTI)) /* Disable all multicast mode */
at91_emac_write(AT91_EMAC_HSH, 0);
at91_emac_write(AT91_EMAC_HSL, 0);
cfg &= ~AT91_EMAC_MTI;
at91_emac_write(AT91_EMAC_CFG, cfg);
以上是关于开发日常网卡驱动中如何设置组播mac地址?的主要内容,如果未能解决你的问题,请参考以下文章