linux网卡驱动中mac地址随机数变化

来源:互联网 发布:商业显示屏软件开发 编辑:程序博客网 时间:2024/04/29 10:34

    mac地址在一般情况下是从网卡的eeprom中读取的,一般厂商会在出厂的时候固化在eeprom中,在有些时候,厂商为了省钱不会去买一个固定的唯一的mac,而是始终用一个固定的mac地址,这样就会在后续用户使用的时候造成mac地址冲突。

本文以qf9700网卡驱动为例,讲解添加mac地址以随机数变化的驱动程序。

#define qf9700_AUTOMAC
#ifdef    qf9700_AUTOMAC
/* Global variables for file-based MAC address Machenism */
int mac_used[129] = {0};
int dev_addr[129] = {0};
DEFINE_SPINLOCK(qf9700_lock);
#endif

定义一个内核自旋锁qf9700_lock。


mac地址的读写主要在驱动的bind函数中

static const struct driver_info qf9700_info = {.description= "QF9700 USB Ethernet",.flags= FLAG_ETHER,.bind= qf9700_bind,.unbind     = qf9700_unbind,.rx_fixup= qf9700_rx_fixup,.tx_fixup= qf9700_tx_fixup,.status= qf9700_status,.link_reset= qf9700_link_reset,.reset= qf9700_link_reset,};

以下是bind函数,宏qf9700_AUTOMAC定义包含的就是需要添加的功能

<pre name="code" class="cpp">static int qf9700_bind(struct usbnet *dev, struct usb_interface *intf){int ret;#ifdefqf9700_AUTOMACint i;u8 defaultAddress[] = {0x00,0xe0,0x4c,0x53,0x44,0x58};struct file *fp;   mm_segment_t fs;loff_t pos;#endifret = usbnet_get_endpoints(dev, intf);if (ret)goto out;    dev->net->netdev_ops = &qf9700_netdev_ops;dev->net->ethtool_ops = &qf9700_ethtool_ops;dev->net->hard_header_len += QF_TX_OVERHEAD;dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;dev->rx_urb_size = dev->net->mtu + ETH_HLEN + QF_RX_OVERHEAD;dev->mii.dev = dev->net;dev->mii.mdio_read = qf9700_mdio_read;dev->mii.mdio_write = qf9700_mdio_write;dev->mii.phy_id_mask = 0x1f;dev->mii.reg_num_mask = 0x1f;/* reset the qf9700 */qf_write_reg(dev, NCR, 1);udelay(20);/* read MAC */if (qf_read(dev, PAR, ETH_ALEN, dev->net->dev_addr) < 0) {printk(KERN_ERR "Error reading MAC address\n");ret = -ENODEV;goto out;}#ifdefqf9700_AUTOMAC/* Compare with the file-based MAC address * This is for dongle or product without EEPROM condition */if (memcmp( dev->net->dev_addr, defaultAddress, ETH_ALEN ) == 0){    spin_lock(&qf9700_lock);for(i=0; i<129; i++){    if(mac_used[i] == 0){    fp = filp_open("/usr/mac", O_RDONLY, 0); if (IS_ERR(fp)) {     netdev_err(dev->net, "open file error");fp = filp_open("/usr/mac", O_RDWR | O_CREAT, 0644); if (IS_ERR(fp)) {    netdev_err(dev->net, "creat file error");        goto out; }fs = get_fs();     set_fs(KERNEL_DS);random_ether_addr(dev->net->dev_addr);*(u8 *)(dev->net->dev_addr + 0) = 0;pos = 0; vfs_write(fp, dev->net->dev_addr, ETH_ALEN, &pos);     } else{    fs = get_fs();    set_fs(KERNEL_DS);}pos = 0; vfs_read(fp, dev->net->dev_addr, ETH_ALEN, &pos);filp_close(fp, NULL);     set_fs(fs); dev_addr[i] = dev->udev->devnum;mac_used[i] = 1;/**(u8*)(dev->net->dev_addr + 0) += i;*(u8*)(dev->net->dev_addr + 1) += i;*(u8*)(dev->net->dev_addr + 2) += i;*(u8*)(dev->net->dev_addr + 3) += i;*(u8*)(dev->net->dev_addr + 4) += i;*/*(u8*)(dev->net->dev_addr + 5) += i;break;}}spin_unlock(&qf9700_lock);/* Set the MAC address */if ((ret = qf_write (dev, PAR, ETH_ALEN, dev->net->dev_addr)) < 0) {    netdev_err(dev->net, "set MAC address failed: %d", ret);goto out;}}netif_carrier_off(dev->net);#endif/* power up and reset phy */qf_write_reg(dev, PRR, 1);mdelay(20);// at least 10ms, here 20ms for safeqf_write_reg(dev, PRR, 0);mdelay(2);// at least 1ms, here 2ms for reading right register/* receive broadcast packets */qf9700_set_multicast(dev->net);qf9700_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);qf9700_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);mii_nway_restart(&dev->mii);out:return ret;}




0 0
原创粉丝点击