链接状态改变(linkwatch)

在Linux 网络协议栈中linkwatch模块用来通知网卡当前是否能够进行数据传输.

驱动中调用netif_carrier_on/netif_carrier_off函数来通知网络状态变化.

主要作用:

  1. 启动/禁止 TX队列的流量控制功能
  2. 发起netlink消息NETDEV_CHANGE到用户空间

 

void netif_carrier_on(struct net_device *dev)

{

         if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {

                   if (dev->reg_state == NETREG_UNINITIALIZED)

                            return;

                   linkwatch_fire_event(dev);

                   if (netif_running(dev))

                            __netdev_watchdog_up(dev);

         }

}

void netif_carrier_off(struct net_device *dev)

{

         if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) {

                   if (dev->reg_state == NETREG_UNINITIALIZED)

                            return ;

                   linkwatch_fire_event(dev);

         }

}

linwatch模块,只需要知道状态改变了,不需要知道具体是on还是off

void linkwatch_fire_event(struct net_device *dev)

{

   /*判断是否为紧急事件, 内核规定两次事件的间隔至少为1个HZ*/

         bool urgent = linkwatch_urgent_event(dev);

         if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {

                   linkwatch_add_event(dev);//把dev添加到lweventlist链表

         } else if (!urgent)

                   return;

   /*调用工作队列linkwatch_event */

         linkwatch_schedule_work(urgent);

}

 

static void __linkwatch_run_queue(int urgent_only)

{

         struct net_device *dev;

         LIST_HEAD(wrk);

         while (!list_empty(&wrk)) {

                   dev = list_first_entry(&wrk, struct net_device, link_watch_list);

                   list_del_init(&dev->link_watch_list);

      /*判断是否只执行紧急事件 */

                   if (urgent_only && !linkwatch_urgent_event(dev)) {

                            list_add_tail(&dev->link_watch_list, &lweventlist);

                            continue;

                   }       

                   spin_unlock_irq(&lweventlist_lock);

                   linkwatch_do_dev(dev);

                   spin_lock_irq(&lweventlist_lock);

         }

         if (!list_empty(&lweventlist)){

                   linkwatch_schedule_work(0);

         }

         spin_unlock_irq(&lweventlist_lock);

}

 

static void linkwatch_do_dev(struct net_device *dev)

{

         rfc2863_policy(dev);

         if (dev->flags & IFF_UP) {

                   if (netif_carrier_ok(dev))

                            dev_activate(dev);//启动tx队列流量控制功能

                   else

                            dev_deactivate(dev);//禁止tx队列流量控制功能

                   netdev_state_change(dev);//发起Netlink事件:NETDEV_CHANGE

         }

         dev_put(dev);

}

你可能感兴趣的:(网络协议栈)