ifconfig promisc内核处理流程:
ioctl(skfd, SIOCSIFFLAGS, &ifr)
...
int dev_ioctl(unsigned int cmd, void __user *arg) /*net/core/dev.c*/
|
——>dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
|
——>int dev_change_flags(struct net_device *dev, unsigned flags)
|
——>void dev_set_promiscuity(struct net_device *dev, int inc)
|
——>void dev_mc_upload(struct net_device *dev) /*net/core/dev_mcast.c*/
|
——>dev->set_multicast_list(dev)
|
|
<——
...
/*驱动程序e1000_main.c*/
static void e1000_set_multi(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
struct e1000_mac_info *mac = &hw->mac;
struct dev_mc_list *mc_ptr;
u8 *mta_list;
u32 rctl;
int i;
/* Check for Promiscuous and All Multicast modes */
rctl = E1000_READ_REG(hw, E1000_RCTL);
if (netdev->flags & IFF_PROMISC) {
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
} else if (netdev->flags & IFF_ALLMULTI) {
rctl |= E1000_RCTL_MPE;
rctl &= ~E1000_RCTL_UPE;
} else {
rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
}
E1000_WRITE_REG(hw, E1000_RCTL, rctl); /*写网卡寄存器*/
/* 82542 2.0 needs to be in reset to write receive address registers */
if (hw->mac.type == e1000_82542)
e1000_enter_82542_rst(adapter);
mta_list = kmalloc(netdev->mc_count * 6, GFP_ATOMIC);
if (!mta_list)
return;
/* The shared function expects a packed array of only addresses. */
mc_ptr = netdev->mc_list;
for (i = 0; i < netdev->mc_count; i++) {
if (!mc_ptr)
break;
memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN);
mc_ptr = mc_ptr->next;
}
e1000_update_mc_addr_list(hw, mta_list, i, 1, mac->rar_entry_count);
kfree(mta_list);
if (hw->mac.type == e1000_82542)
e1000_leave_82542_rst(adapter);
}
阅读(2632) | 评论(0) | 转发(0) |