• [置顶] Linux协议栈代码阅读笔记(二)网络接口的配置


    Linux协议栈代码阅读笔记(二)网络接口的配置
    (基于linux-2.6.11)

    (一)用户态通过C库函数ioctl进行网络接口的配置

    例如,知名的ifconfig程序,就是通过C库函数sys_ioctl实现网络接口的配置的。
    具体方法大致如下,即建立一个socket,得到一个fd,然后在此fd上执行ioctl即可完成各种操作(例如,查询/配置mac、ip、mtu,启动/停止网络接口)。
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    ioctl(fd, SIOCGIFFLAGS, (caddr_t)&ifr);

    (二)上述C库函数如何与内核交互
    C库代码准备好相应的工作后(例如,设置系统调用号啦、参数构造啦、栈啦、寄存器设置啦),通过系统调用指令,进入内核态。从内核返回后,C库函数再做相应的善后工作,然后将结果返回给用户程序。

    这部分代码,不同架构的处理器,有不同的实现。


    (三)内核态如何处理用户的网络通讯请求
    上一步,C库发起了系统调用,根据系统调用号,进入系统调用表的相应表目。ioctl对应的是54号系统调用,即sys_ioctl函数。
    此函数的代码如下(源码文件:fsIoctl.c),最终通过vfs_ioctl完成操作。
    asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
    {
     struct file * filp;
     int error = -EBADF;
     int fput_needed;

     filp = fget_light(fd, &fput_needed);
     if (!filp)
      goto out;

     error = security_file_ioctl(filp, cmd, arg);
     if (error)
      goto out_fput;

     error = vfs_ioctl(filp, fd, cmd, arg);
     out_fput:
     fput_light(filp, fput_needed);
     out:
     return error;
    }

    (四)vfs_ioctl内部的执行路径
    由于我们的fd对应的是一个socket,并且我们的操作是配置网络接口。因此,进入vfs_ioctl后的函数执行路径如下:
    do_ioctl
    filp->f_op->ioctl(即socket_file_ops.unlocked_ioctl,也就是sock_ioctl)
    sock->ops->ioctl(即inet_dgram_ops.ioctl,也就是inet_ioctl)
    接下来的工作,就看具体的操作了。

    如果是ip层的设置,基本上都是围绕网络接口对应的in_device结构变量进行操作。IP地址啦、多播信息啦,就在这里了。

    如果是L2层的设置,基本上都是围绕网络接口对应的net_device结构变量进行操作。接口名称、mtu什么的,就在这里了。

    (每一个网络接口对应一个net_device结构变量,__dev_get_by_name函数能够根据接口名称查找到对应的net_device结构。net_device实际上是in_device结构的一个成员,__in_dev_get_rtnl返回某个net_device结构所属的in_device的地址)

    大体来说,L2层的设置,通常就是设置/获取net_device结构变量中相关成员的值。例如,获取接口mtu,就是获取dev->mtu的值。

    当然,有些操作需要调用网络接口的驱动程序中的相关函数,net_device结构中有这些函数的地址,直接调用即可。

    另外,有些操作完成后,还需要通知那些注册了关心此事件的内核模块。

    例如,mac地址变化后,会通过如下形式通知其他内核模块。

    notifier_call_chain(&netdev_chain,  NETDEV_CHANGEADDR, dev);

    至于IP层的设置,在下还没有理解其代码,这里就不描述了。

    下面列出部分操作对应的函数。

    1)设置/查询ip、广播地址等操作,执行sock->ops->ioctl函数(即inet_dgram_ops.ioctl,也就是inet_ioctl)
    例如:

    设置ip地址涉及的执行路径(从inet_ioctl内部开始):

    devinet_ioctl

    inet_set_ifa

    inet_insert_ifa


    2)设置/查询接口名称、mac地址、mtu等,执行dev_ioctl函数。

    例如:

    设置mtu涉及到的执行路径(从dev_ioctl内部开始):
    dev_ifsioc
    dev_set_mtu
    dev->change_mtu(以Intel(R)的e1000网卡为例,dev->change_mtu对应的函数是网卡驱动中的e1000_change_mtu。源码:drivers ete1000E1000_main.c)
    raw_notifier_call_chain(&netdev_chain,    NETDEV_CHANGEMTU, dev);  //通知内核中关心mtu变化事件的模块

  • 相关阅读:
    深入理解定时器系列第二篇——被誉为神器的requestAnimationFrame
    深入理解定时器系列第一篇——理解setTimeout和setInterval
    idea自动生成方法注释(含参数及返回值)
    敲最少的键,编最多的码
    「HAOI2016」食物链
    「SCOI2015」小凸玩矩阵
    后缀自动机详解
    「TJOI2019」大中锋的游乐场
    「TJOI2019」唱、跳、rap 和篮球
    「TJOI2019」甲苯先生的滚榜
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3363757.html
Copyright © 2020-2023  润新知