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
下面的链接给了设置方法:
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, };
调试如下: