- 网卡驱动:载波检测-netif_carrier_ok/netif_carrier_on/netif_carrier_off
网卡在物理上具有载波侦听的功能,当网络连接完整或者网络链接断开时,网卡芯片硬件会自动设置寄存器标志位来标识。
如网线链接断开的时候,会将LinkSts清位;重新链接网线,则硬件自动将此位置位。
这样,在网卡驱动中读写该位信息就可一判断网络是否链接通路。
网卡驱动程序通过netif_carrier_on/netif_carrier_off/netif_carrier_ok来和内核网络子系统传递信息。
1】netif_carrier_on
【作用】告诉内核子系统网络链接完整。
2】netif_carrier_off
【作用】告诉内核子系统网络断开。
3】netif_carrier_ok
【作用】查询网络断开还是链接。
以上函数主要是改变net_device dev的state状态来告知内核链路状态的变化
- 网卡驱动:设备挂起恢复-netif_device_attach/netif_device_detach
在网卡驱动程序中通常需要实现suspend和resume函数来支持设备的挂起和恢复操作。
网络驱动程序可以用两个函数来告知网络子系统网络设备的挂起和恢复:
1】netif_device_attach
2】netif_device_detach
NETIF_DEVICE_ATTCH:
【作用】将net_device的state中的__LINK_STATE_PRESENT置位。同时开启发送队列。
NETIF_DEVICE_DETACH:
【作用】将net_device的state中的__LINK_STATE_PRESENT清位。同时关闭发送队列。
————–源码实例—————
static void rtl8169_net_suspend(struct net_device *dev)
{
____if (!netif_running(dev))
________return;
____netif_device_detach(dev);
____netif_stop_queue(dev);
}
static void __rtl8169_resume(struct net_device *dev)
{
____netif_device_attach(dev);
____rtl8169_schedule_work(dev, rtl8169_reset_task);
}
- 网卡驱动:传输超时watchdog_timeo/ndo_tx_timeout
网络子系统提供了对传输超时的处理框架,在驱动程序中要支持传输超时处理,只需要实现net_device的watchtimeo和net_device_ops中的ndo_tx_timeout函数。
1】watchdog_timeo
【作用】用于实现传出超时的时间设定。
1】ndo_tx_timeout
【作用】在发送队列停止(netif_queue_stopped(dev)返回1),且watchdog_timeo到期的时候,内核网络子系统会调用ndo_tx_timeout来进行处理
========用法========
ndo_tx_timeout的实现多种多样,可以根据具体的情况来实现。
关于定时器的信息,参照内核定时器介绍。
在linux2.6内核的rtl8169网卡驱动的实现上,在rtl8169_tx_timeout上就调用了两个函数:
rtl8169_hw_reset()
rtl8169_shedule_work()
其中前一个参数实现了硬件reset。
后一个函数完成了设备缓冲区等初始化任务。
—————源码—————
static void rtl8169_tx_timeout(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
rtl8169_hw_reset(tp->mmio_addr);
rtl8169_schedule_work(dev, rtl8169_reset_task);
}
- 网卡驱动:数据包发送的流控机制-netif_start_queue/netif_wake_queue/netif_stop_queue
在网卡驱动中,内核为发送数据包的流量控制提供了几个主要的函数,用来在驱动程序和内核之间传递流控信息。
主要有三个:
1】netif_start_queue
2】netif_wake_queue
3】netif_stop_queue
4】netif_queue_stopped
NETIF_STOP_QUEUE:
【作用】在驱动程序中调用这个函数来告诉内核的网络子系统,当前网卡设备内存不够,不能继续传输数据包,内核要停止数据包的发送。
【实现】将设备发送队列_tx[0]的状态state的_QUEUE_STATE_XOFF置1。
NETIF_START_QUEUE:
【作用】驱动程序调用这个函数来告诉内核网络子系统,现在可以开始数据包的发送。
【实现】将设备发送队列的_tx[0]的state的_QUEUE_STATE_XOFF复位0。
NETIF_WAKE_QUEUE:
【作用】除了实现netif_start_queue的作用外,还会将设备的发送队列加入到CPU的发送队列,并且出发中断处理的下半部来出发数据包发送。
【实现】除了检查tx[0]的state的_QUEUE_STATE_XOFF位外,还检查设备发送队列qdisk成员的_QDISK_STATE_SCHED,如果是1说明当前设备的发送队列尚未加入到CPU的发送队列尾部,同时调用raise_softirq_irqoff(NET_TX_SOFTIRQ)来触发softirq。
NETIF_QUEUE_STOPPED:
【作用】检查net_device的发送队列是否stopped
【实现】检查设备发送队列_tx[0]的状态state的_QUEUE_STATE_XOFF是否置1,置1的话返回1,置0返回0。
=======用法=========
netif_start_queue一般在open函数中调用,开启数据包的传输。
netif_stop_queue一般用于驱动程序通知网络子系统暂停数据包传输,从来进行实现流量控制。
netif_wake_queue在timeout后或者网卡硬件出错后调用,来重启数据包的发送,并且将在设备队列关闭期间进入的到队列的数据包发送。