加入收藏 | 设为首页 | 会员中心 | 我要投稿 常州站长网 (https://www.0519zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核实践 - 如何添加网络协议[二]:实现

发布时间:2016-09-28 18:42:11 所属栏目:Linux 来源:站长网
导读:副标题#e# 内核版本:2.6.34 实现思路: 报文在网络协议栈中的流动,对于接收来讲,是 对报文的脱壳的过程,由于报文是已知的输入,只要逐个解析协议号;对于发送来讲,是各层发送函数的嵌套调用,由于没有已 知的输入,只能按事先设计好的协议进行层层构造

而设备的初始化应该发生在创建设备时,也就是向网络注册它时,也就是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;     
}

(编辑:常州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读