zoukankan      html  css  js  c++  java
  • 网络设备之注册

    注册网络设备时,会调用pci_driver->probe函数,以e100网卡驱动为例,在调用alloc_ehterdev分配内存之后,会接着调用register_netdev进行设备注册,注册过程包含部分成员初始化,注册到文件系统,消息通知等;

    1 /**
    2  * 设备注册函数调用关系图
    3  * e100_probe
    4  *      |-->alloc_etherdev-->alloc_netdev_mqs
    5  *      |-->register_netdev-->register_netdevice 
    6  */

    下面对register_netdevice函数进行分析:

      1 /**
      2  *    register_netdevice    - register a network device
      3  *    @dev: device to register
      4  *
      5  *    Take a completed network device structure and add it to the kernel
      6  *    interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier
      7  *    chain. 0 is returned on success. A negative errno code is returned
      8  *    on a failure to set up the device, or if the name is a duplicate.
      9  *
     10  *    Callers must hold the rtnl semaphore. You may want
     11  *    register_netdev() instead of this.
     12  *
     13  *    BUGS:
     14  *    The locking appears insufficient to guarantee two parallel registers
     15  *    will not get the same name.
     16  */
     17 
     18 int register_netdevice(struct net_device *dev)
     19 {
     20     int ret;
     21     struct net *net = dev_net(dev);
     22 
     23     BUG_ON(dev_boot_phase);
     24     ASSERT_RTNL();
     25 
     26     might_sleep();
     27 
     28     /* When net_device's are persistent, this will be fatal. */
     29     BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
     30     BUG_ON(!net);
     31 
     32     spin_lock_init(&dev->addr_list_lock);
     33     netdev_set_addr_lockdep_class(dev);
     34 
     35     /* 获取可用设备名 */
     36     ret = dev_get_valid_name(net, dev, dev->name);
     37     if (ret < 0)
     38         goto out;
     39 
     40     /* Init, if this function is available */
     41     /* 调用设备的初始化函数 */
     42     if (dev->netdev_ops->ndo_init) {
     43         ret = dev->netdev_ops->ndo_init(dev);
     44         if (ret) {
     45             if (ret > 0)
     46                 ret = -EIO;
     47             goto out;
     48         }
     49     }
     50 
     51     /* vlan数据包接收过滤 */
     52     if (((dev->hw_features | dev->features) &
     53          NETIF_F_HW_VLAN_CTAG_FILTER) &&
     54          /* vlan注册/销毁函数不存在 */
     55         (!dev->netdev_ops->ndo_vlan_rx_add_vid ||
     56          !dev->netdev_ops->ndo_vlan_rx_kill_vid)) {
     57         netdev_WARN(dev, "Buggy VLAN acceleration in driver!
    ");
     58         ret = -EINVAL;
     59         goto err_uninit;
     60     }
     61 
     62     ret = -EBUSY;
     63     /* 设备索引不存在,则分配一个 */
     64     if (!dev->ifindex)
     65         dev->ifindex = dev_new_index(net);
     66     /* 索引存在,则进行测试 */
     67     else if (__dev_get_by_index(net, dev->ifindex))
     68         goto err_uninit;
     69 
     70     /* Transfer changeable features to wanted_features and enable
     71      * software offloads (GSO and GRO).
     72      */
     73     /* 设置功能标识 */
     74     dev->hw_features |= NETIF_F_SOFT_FEATURES;
     75     dev->features |= NETIF_F_SOFT_FEATURES;
     76     dev->wanted_features = dev->features & dev->hw_features;
     77 
     78     if (!(dev->flags & IFF_LOOPBACK))
     79         dev->hw_features |= NETIF_F_NOCACHE_COPY;
     80 
     81     /* If IPv4 TCP segmentation offload is supported we should also
     82      * allow the device to enable segmenting the frame with the option
     83      * of ignoring a static IP ID value.  This doesn't enable the
     84      * feature itself but allows the user to enable it later.
     85      */
     86     if (dev->hw_features & NETIF_F_TSO)
     87         dev->hw_features |= NETIF_F_TSO_MANGLEID;
     88     if (dev->vlan_features & NETIF_F_TSO)
     89         dev->vlan_features |= NETIF_F_TSO_MANGLEID;
     90     if (dev->mpls_features & NETIF_F_TSO)
     91         dev->mpls_features |= NETIF_F_TSO_MANGLEID;
     92     if (dev->hw_enc_features & NETIF_F_TSO)
     93         dev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
     94 
     95     /* Make NETIF_F_HIGHDMA inheritable to VLAN devices.
     96      */
     97     dev->vlan_features |= NETIF_F_HIGHDMA;
     98 
     99     /* Make NETIF_F_SG inheritable to tunnel devices.
    100      */
    101     dev->hw_enc_features |= NETIF_F_SG | NETIF_F_GSO_PARTIAL;
    102 
    103     /* Make NETIF_F_SG inheritable to MPLS.
    104      */
    105     dev->mpls_features |= NETIF_F_SG;
    106 
    107     /* 通知设备初始化结束 */
    108     ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
    109     ret = notifier_to_errno(ret);
    110     if (ret)
    111         goto err_uninit;
    112 
    113     /* 设备注册到虚拟文件系统 */
    114     ret = netdev_register_kobject(dev);
    115     if (ret)
    116         goto err_uninit;
    117 
    118     /*设置设备注册状态*/
    119     dev->reg_state = NETREG_REGISTERED;
    120 
    121     __netdev_update_features(dev);
    122 
    123     /*
    124      *    Default initial state at registry is that the
    125      *    device is present.
    126      */
    127 
    128     set_bit(__LINK_STATE_PRESENT, &dev->state);
    129 
    130     linkwatch_init_dev(dev);
    131 
    132     dev_init_scheduler(dev);
    133     dev_hold(dev);
    134     list_netdevice(dev);
    135     add_device_randomness(dev->dev_addr, dev->addr_len);
    136 
    137     /* If the device has permanent device address, driver should
    138      * set dev_addr and also addr_assign_type should be set to
    139      * NET_ADDR_PERM (default value).
    140      */
    141     /* 永久硬件地址,则拷贝到perm_addr */
    142     if (dev->addr_assign_type == NET_ADDR_PERM)
    143         memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
    144 
    145     /* Notify protocols, that a new device appeared. */
    146     /* 通知设备初始化完毕 */
    147     ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
    148     ret = notifier_to_errno(ret);
    149     /* 失败进行回滚 */
    150     if (ret) {
    151         rollback_registered(dev);
    152         dev->reg_state = NETREG_UNREGISTERED;
    153     }
    154     /*
    155      *    Prevent userspace races by waiting until the network
    156      *    device is fully setup before sending notifications.
    157      */
    158     /* 发送newlink消息 */
    159     if (!dev->rtnl_link_ops ||
    160         dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
    161         rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U, GFP_KERNEL);
    162 
    163 out:
    164     return ret;
    165 
    166 err_uninit:
    167     if (dev->netdev_ops->ndo_uninit)
    168         dev->netdev_ops->ndo_uninit(dev);
    169     if (dev->priv_destructor)
    170         dev->priv_destructor(dev);
    171     goto out;
    172 }
  • 相关阅读:
    记一个在训练模型过程中自己给自己挖的坑
    Fast R-CNN学习总结
    SPP-net论文总结
    R-CNN学习总结
    3Sum Closest
    3Sum
    整数转为罗马数字
    Container With Most Water
    决策树
    回文数判断
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/7526214.html
Copyright © 2011-2022 走看看