Linux内核实践 - 如何添加网络协议[二]:实现
而设备的初始化应该发生在创建设备时,也就是向网络注册它时,也就是register_brcm_dev(),注册一个新设备, 需要知道它的下层设备real_dev以及唯一标识brcm设备的brcm_port。首先确定该设备没有被创建,然后用alloc_netdev_mq创建 新设备new_dev,然后设置相关属性,特别是它的私有属性brcm_dev_info(new_dev),然后添加它到brcm_group_hash中,最后发 生真正的注册register_netdevice()。 static int register_brcm_dev(struct net_device *real_dev, u16 brcm_port) { struct net_device *new_dev; struct net *net = dev_net(real_dev); struct brcm_group *grp; char name[IFNAMSIZ]; int err; if(brcm_port >= BRCM_PORT_MASK) return -ERANGE; // exist yet if (find_brcm_dev(real_dev, brcm_port) != NULL) return -EEXIST; snprintf(name, IFNAMSIZ, "brcm%i", brcm_port); new_dev = alloc_netdev_mq(sizeof(struct brcm_dev_info), name, brcm_setup, 1); if (new_dev == NULL) return -ENOBUFS; new_dev->real_num_tx_queues = real_dev->real_num_tx_queues; dev_net_set(new_dev, net); new_dev->mtu = real_dev->mtu; brcm_dev_info(new_dev)->brcm_port = brcm_port; brcm_dev_info(new_dev)->real_dev = real_dev; brcm_dev_info(new_dev)->dent = NULL; //new_dev->rtnl_link_ops = &brcm_link_ops; grp = brcm_find_group(real_dev); if (!grp) grp = brcm_group_alloc(real_dev); err = register_netdevice(new_dev); if (err < 0) goto out_free_newdev; /* Account for reference in struct vlan_dev_info */ dev_hold(real_dev); brcm_group_set_device(grp, brcm_port, new_dev); return 0; out_free_newdev: free_netdev(new_dev); return err; } ioctl 由于brcm设备可以存在多个,并且和下层设备不是固定的对应关系,因此它的创 建应该可以人为控制,因此通过ioctl由用户进行创建。这里只为brcm提供了两种操作-添加与删除。一种设备添加一定是与下层 设备成关系的,因此添加时需要手动指明这种下层设备,然后通过__dev_get_by_name()从网络空间中找到这种设备,就可以调 用register_brcm_dev()来完成注册了。而设备的删除则是直接删除,直接删除unregister_brcm_dev()。 static int brcm_ioctl_handler(struct net *net, void __user *arg) { int err; struct brcm_ioctl_args args; struct net_device *dev = NULL; if (copy_from_user(&args, arg, sizeof(struct brcm_ioctl_args))) return -EFAULT; /* Null terminate this sucker, just in case. */ args.device1[23] = 0; args.u.device2[23] = 0; rtnl_lock(); switch (args.cmd) { case ADD_BRCM_CMD: case DEL_BRCM_CMD: err = -ENODEV; dev = __dev_get_by_name(net, args.device1); if (!dev) goto out; err = -EINVAL; if (args.cmd != ADD_BRCM_CMD && !is_brcm_dev(dev)) goto out; } switch (args.cmd) { case ADD_BRCM_CMD: err = -EPERM; if (!capable(CAP_NET_ADMIN)) break; err = register_brcm_dev(dev, args.u.port); break; case DEL_BRCM_CMD: err = -EPERM; if (!capable(CAP_NET_ADMIN)) break; unregister_brcm_dev(dev, NULL); err = 0; break; default: err = -EOPNOTSUPP; break; } out: rtnl_unlock(); return err; } (编辑:淮北站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |