网络设备之注册

注册网络设备时,会调用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!\n");
 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 }

 

posted @ 2017-09-15 14:17  AlexAlex  阅读(1637)  评论(0编辑  收藏  举报