网卡驱动7-netpoll和ethtool,以及ethtool移植和驱动简单实现

netpoll的目的是让内核在网络和I/O子系统尚不能完整可用时,依然能发送和接收数据包。主要用于网络控制台(net console)和远程内核调试(KGDBoE)中。实现netpoll功能,主要是要实现kernel中的poll_controller函数,该函数定义:void (*poll_controller)(structnet_device *dev)。该函数的作用是在缺少设备中断的情况下,还能对控制器做出响应。几乎所有的poll_controller函数都定义成如下形式:
void my_poll_controller(structnet_device *dev) {
disable_device_interrupt();//
my_interrupt_handler();
enable_device_interrupt();
}


所以,poll_controller只是模拟了来自指定设备的中断。其实只是给netpoll机制提供调用中断函数处理的机会,实际的中断触发当然还是硬件。

下面的链接分析了netpoll

http://blog.csdn.net/lucien_cc/article/details/11731501

 

netconsole在内核/drivers/net下

netconsole.c文件,这个console主要是向远程端发送printk(用户层不行)打印信息。

在arm板上,你的内核要配置选上netpoll,也要加载netconsole.ko

下面看netconsole.ko装载:

http://linux.chinaunix.net/techdoc/system/2005/04/06/921980.shtml

 

在pc机上要配置syslogd可以用接收来自远程主机的消息

下面的链接给了设置方法:

http://blog.csdn.net/sandflee/article/details/5745745

 

下面说ethtool,Ldd3的解释:

ethtool 是一个实用工具, 设计来给系统管理员以大量的控制网络接口的操作.

用 ethtool, 可能来控制各种接口参数, 包括速度,介质类型, 双工模式,DMA

环设置, 硬件校验和,LAN 唤醒操作, 等等,但是只有当 ethtool 被驱动支持.

ethtool 可以从 http://sf.net/projects/gkernel/. 下载.

下载也可以到我的资源里下:

先下载ethtool:

http://download.csdn.net/detail/xxxxxlllllxl/6919223

 

ethtool使用,看下面的链接:

http://www.baike.com/wiki/ethtool

http://baike.baidu.com/link?url=gHI5ghj85AZ313hHt0xRuXDXBG1YzsU-239HTStfEvntOA3AmNKFigLbrb4HpLe_tX3E7gAZXNLoJcgrCZKYEq

 

 

ethtool移植

pc都会有ethtool软件,arm板就不一定了。

移植很简单,解压缩,然后cd进去

./configure

viMakefile

把里面的gcc(就三个地方)改成你的交叉编译工具就可以了,如arm-linux-gcc

make就会有ethtool了

 

ethtool在内核中的使用:

主要看ethtool_ops,对驱动来说,面对的就是它,在次我介绍一下它所拥有的成员的作用。功能实现还是要搞驱动本身。Linux-3.0.8;位置include/ethtool.h

struct ethtool_ops {
        int     (*get_settings)(struct net_device *, struct ethtool_cmd *);
//获取网卡信息,如duplex、;连接状态、速度等,看看struct ethtool_cmd就知道了
        int     (*set_settings)(struct net_device *, struct ethtool_cmd *);//设置网卡
        void    (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);//这个获取一些如驱动名称、版本等信息。
        int     (*get_regs_len)(struct net_device *);//为下面的get_regs获取缓存区长度
        void    (*get_regs)(struct net_device *, struct ethtool_regs *, void *);//获得设备寄存器
        void    (*get_wol)(struct net_device *, struct ethtool_wolinfo *);//获取wake-on-lan(一种电源管理功能)是否启用。
        int     (*set_wol)(struct net_device *, struct ethtool_wolinfo *);//开关wol
        u32     (*get_msglevel)(struct net_device *);//报告驱动程序的消息级别
        void    (*set_msglevel)(struct net_device *, u32);//设置驱动程序的消息级别
        int     (*nway_reset)(struct net_device *);//重新启动自动协商
        u32     (*get_link)(struct net_device *);//报告物理连接已经up
        int     (*get_eeprom_len)(struct net_device *);//为下面get_eeprom服务
        int     (*get_eeprom)(struct net_device *,
                              struct ethtool_eeprom *, u8 *);//读网卡设备的eeprom
        int     (*set_eeprom)(struct net_device *,
                              struct ethtool_eeprom *, u8 *);/写网卡设备的eeprom
        int     (*get_coalesce)(struct net_device *, struct ethtool_coalesce *);//获取中断凝聚参数,例如一个包到达到中断触发的时间
        int     (*set_coalesce)(struct net_device *, struct ethtool_coalesce *);//设置中断凝聚参数
        void    (*get_ringparam)(struct net_device *,
                                 struct ethtool_ringparam *);//报告RX/TX ring参数
        int     (*set_ringparam)(struct net_device *,
                                 struct ethtool_ringparam *);//设置RX/TX ring参数
        void    (*get_pauseparam)(struct net_device *,
                                  struct ethtool_pauseparam*); 
        int     (*set_pauseparam)(struct net_device *,
                                  struct ethtool_pauseparam*);
// pauseparam对应网卡的溢出控制
        u32     (*get_rx_csum)(struct net_device *);//报告接收csum是开还是关
        int     (*set_rx_csum)(struct net_device *, u32);//设置
        u32     (*get_tx_csum)(struct net_device *);//类似rx_csum
        int     (*set_tx_csum)(struct net_device *, u32);
        u32     (*get_sg)(struct net_device *);
        int     (*set_sg)(struct net_device *, u32);//分散聚合开关
        u32     (*get_tso)(struct net_device *);
        int     (*set_tso)(struct net_device *, u32);// TCP分段卸载开关
        void    (*self_test)(struct net_device *, struct ethtool_test *, u64 *);//run特殊自测试
        void    (*get_strings)(struct net_device *, u32 stringset, u8 *);//返回一个请求对象的字串
        int     (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state);//识别物理设备,例如通过一个led闪烁。enum ethtool_phys_id_state有指示停用开启、len开或关
        void    (*get_ethtool_stats)(struct net_device *,
                                     struct ethtool_stats *, u64 *);//返回扩展统计信息,只有设备统计信息不在struct rtnl_link_stats64中才使用
        int     (*begin)(struct net_device *);//在任何操作开始前都会调用
        void    (*complete)(struct net_device *);除了begin其他任何操作失败都会调用这个
        u32     (*get_ufo)(struct net_device *);
        int     (*set_ufo)(struct net_device *, u32);// UDP碎片卸载开关
        u32     (*get_flags)(struct net_device *);
        int     (*set_flags)(struct net_device *, u32);//网卡的features读取设置,以及ethtool_flags开关
        u32     (*get_priv_flags)(struct net_device *);
        int     (*set_priv_flags)(struct net_device *, u32);//特殊的feature设置
        int     (*get_sset_count)(struct net_device *, int);//获得get_stings要写的字串数量
        int     (*get_rxnfc)(struct net_device *,
                             struct ethtool_rxnfc *, void *);
        int     (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);//rx溢出分类法则开关,有很多命令,具体看struct ethtool_rxnfo
        int     (*flash_device)(struct net_device *, struct ethtool_flash *);//写一个固件镜像到设备的flash
        int     (*reset)(struct net_device *, u32 *);//设备复位
        int     (*set_rx_ntuple)(struct net_device *,
                                 struct ethtool_rx_ntuple *);
        int     (*get_rx_ntuple)(struct net_device *, u32 stringset, void *);//这里是控制特殊的接收溢出过滤器,如tcp\tcp溢出。
        int     (*get_rxfh_indir)(struct net_device *,
                                  struct ethtool_rxfh_indir *);
        int     (*set_rxfh_indir)(struct net_device *,
                                  const struct ethtool_rxfh_indir *);//rx溢出hash表操作
        void    (*get_channels)(struct net_device *, struct ethtool_channels *);
        int     (*set_channels)(struct net_device *, struct ethtool_channels *);//获取驱动最多支持的网络通道数
        //下面转储操作
        int     (*get_dump_flag)(struct net_device *, struct ethtool_dump *);
        int     (*get_dump_data)(struct net_device *,
                                 struct ethtool_dump *, void *);
        int     (*set_dump)(struct net_device *, struct ethtool_dump *);

};

具体实现可以看看一些网卡的实现。

我虚拟网卡简单实现的

static int vnic_ethtool_get_settings(struct net_device *dev,
                     struct ethtool_cmd *cmd)
{
    const struct vnic_dev_info *vnic = vnic_dev_info(dev);
    return dev_ethtool_get_settings(vnic->real_dev, cmd);
}

static void vnic_ethtool_get_drvinfo(struct net_device *dev,
                     struct ethtool_drvinfo *info)
{
    strcpy(info->driver, "vnic");
    strcpy(info->version, "v1.0");
    strcpy(info->fw_version, "N/A");
}
static const struct ethtool_ops vnic_ethtool_ops = {
    .get_settings            = vnic_ethtool_get_settings,
    .get_drvinfo            = vnic_ethtool_get_drvinfo,
    .get_link        = ethtool_op_get_link,
};

调试如下:



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。