zoukankan      html  css  js  c++  java
  • Linux网络设备驱动之网络连接状态(七)

      网络适配器硬件电路可以检测出链路上是否有载波,载波反映了网络的连接是否正常。网络设备驱动可以通过 netif_carrier_on() 和 netif_carrier_off() 函数改变设备的连接状态,如果驱动检测到连接状态发生变化,也应该以 netif_carrier_on() 和 netif_carrier_off() 函数显式地通知内核。

      除了 netif_carrier_on() 和 netif_carrier_off() 函数以外,另一个函数 netif_carrier_ok() 可用于向调用者返回链路上的载波信号是否存在。

      这几个函数都接收一个 net_device 设备结构体指针作为参数,原型分别为:

     1 /**
     2  *    netif_carrier_on - set carrier
     3  *    @dev: network device
     4  *
     5  * Device has detected that carrier.
     6  */
     7 void netif_carrier_on(struct net_device *dev)
     8 {
     9     if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
    10         if (dev->reg_state == NETREG_UNINITIALIZED)
    11             return;
    12         atomic_inc(&dev->carrier_changes);
    13         linkwatch_fire_event(dev);
    14         if (netif_running(dev))
    15             __netdev_watchdog_up(dev);
    16     }
    17 }
    18 
    19 
    20 /**
    21  *    netif_carrier_off - clear carrier
    22  *    @dev: network device
    23  *
    24  * Device has detected loss of carrier.
    25  */
    26 void netif_carrier_off(struct net_device *dev)
    27 {
    28     if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
    29         if (dev->reg_state == NETREG_UNINITIALIZED)
    30             return;
    31         atomic_inc(&dev->carrier_changes);
    32         linkwatch_fire_event(dev);
    33     }
    34 }
    35 
    36 
    37 /**
    38  *    netif_carrier_ok - test if carrier present
    39  *    @dev: network device
    40  *
    41  * Check if carrier is present on device
    42  */
    43 static inline bool netif_carrier_ok(const struct net_device *dev)
    44 {
    45     return !test_bit(__LINK_STATE_NOCARRIER, &dev->state);
    46 }

      在网络设备驱动程序中可采取一定的手段来检测和报告链路状态,最常见的方法是采用中断,其次可以设置一个定时器来对链路状态进行周期性的检查。当定时器到期之后,在定时器处理函数中读取物理设备的相关寄存器以获得载波状态,从而更新设备的连接状态,如下代码所示:

     1 /*
     2  *  网络设备驱动用定时器周期性检查链路状态
     3  */
     4 
     5 static void xxx_timer(unsigned long data)
     6 {
     7     struct net_device *dev = (struct net_device *)data;
     8     u16 link;
     9     ···
    10     if (!(dev->flags & IFF_UP))
    11         goto set_timer;
    12 
    13     /* 获得物理上的连接状态 */
    14     if(link = xxx_chk_link(dev)) {
    15         if (!(dev->flags & IFF_RUNNING)) {
    16             netif_carrier_on(dev);
    17             dev->flags |= IFF_RUNNING;
    18             printk(KERN_DEBUG "%s: link up
    ", dev->name);   
    19         }
    20     } else {
    21         if (dev->flags & IFF_RUNNING) {
    22             netif_carrier_off(dev);
    23             dev->flags &= ~IFF_RUNNING;
    24             printk(KERN_DEBUG "%s: link down
    ", dev->name);
    25         }
    26     }
    27 
    28 set_timer:
    29     priv->timer.expires = jiffies + 1 * Hz;
    30     priv->timer.data = (unsigned long)dev;
    31     priv->timer.function = &xxx_timer;  /* timer handler */
    32     add_timer(&priv->timer); 
    33 }     

      上述代码第 14 行调用 xxx_chk_link() 函数来读取网络适配器硬件的相关寄存器,以获得链路连接状态,具体实现由硬件决定。当链路连接上时,第 16 行的 netif_carrier_on() 函数显式地通知内核链路正常;反之,第 22 行的 nerif_carrier_off() 同样显式地通知内核链路失去连接。

      此外,从上述源代码还可以看出,定时器处理函数会不停地利用第 28 ~ 32行代码启动新的定时器以实现周期性检测的目的。最初启动定时器的地方在哪呢??很显然,它最适合在设备的打开函数中完成,如下代码所示:

     1 /*
     2  *  在网络设备驱动的打开函数中初始化定时器
     3  */
     4 
     5 static int xxx_open(struct net_device *dev)
     6 {
     7     struct xxx_priv *priv = netdev_priv(dev);
     8 
     9     
    10     ···
    11     priv->timer.expires = jiffies + 3 * Hz;
    12     priv->timer.data = (unsigned long)dev;
    13     priv->timer.function = &xxx_timer; /* 定时器处理函数 */
    14     ···
    15 }
  • 相关阅读:
    Rust 包管理器 Cargo 入门
    如何设置对企业批量的图文档加密?2021企业首选公司文档加密方案,宁波风奥金甲数据防泄漏
    跟坚哥学QUIC系列:加密和传输握手
    如何在SQLServer中处理每天四亿三千万记录的
    高德最佳实践:Serverless 规模化落地有哪些价值?
    浅谈 Pull Request 与 Change Request 研发协作模式
    Dbeaver连接国产数据库人大金仓
    我对云原生软件架构的观察与思考
    Java Web整合开发(20) -- Hibernate入门
    2 修改与恢复
  • 原文地址:https://www.cnblogs.com/wanglouxiaozi/p/13383089.html
Copyright © 2011-2022 走看看