网络子系统20_传输接收软中断
// 数据帧接收软中断处理函数 // 调用路径:do_softirq->net_rx_action // 函数主要任务: // 1.在关中断情况下检查调度队列poll_list是否有设备接收到入口帧,然后开中断 // 2.单次运行处理的入口帧不能超过netdev_max_backlog=300,运行时间不能超过1个jiffies // 3.依次遍历调度队列poll_list // 4.如果设备配额以用完,或者设备驱动的poll函数表明仍然有入口数据帧 // 4.1 将设备重新添加poll_list尾部,重新分配配额,准备接受下一次调度 // 5.如果单次运行没有调度完所有接收到入口帧的设备,则再次设置接受软中断调度标志,退出 // 注:接收软中断中,poll_list上挂载的npai设备,或者非napi设备使用的积压设备。 3.2 static void net_rx_action(struct softirq_action *h) { struct softnet_data *queue = &__get_cpu_var(softnet_data); unsigned long start_time = jiffies; int budget = netdev_max_backlog; //关本地中断 local_irq_disable(); //有设备有输入流量 while (!list_empty(&queue->poll_list)) { struct net_device *dev; //执行时间超过了一个1 jiffies //或者本次软中断处理的输入流量已经超过了netdev_max_backlog,退出软中 if (budget <= 0 || jiffies - start_time > 1) goto softnet_break; local_irq_enable(); //获得设备指针 dev = list_entry(queue->poll_list.next, struct net_device, poll_list); //如果设备的配额已经用完,或者执行一次poll之后,此设备依然有待处理的流量 if (dev->quota <= 0 || dev->poll(dev, &budget)) { local_irq_disable(); //将设备从list上删除,添加到list尾部 list_del(&dev->poll_list); list_add_tail(&dev->poll_list, &queue->poll_list); //给设备重新分配配额,已weight作为一次分配的量,范围从1024~64 if (dev->quota < 0) dev->quota += dev->weight; else dev->quota = dev->weight; } else { dev_put(dev); local_irq_disable(); } } out: local_irq_enable(); return; softnet_break: __get_cpu_var(netdev_rx_stat).time_squeeze++; //重新调度接收软中断 __raise_softirq_irqoff(NET_RX_SOFTIRQ); goto out; } // 发送软中断处理函数 // 一次处理output_queue中所有等待传输的设备 // 调用路径:do_softirq->net_tx_action // 函数主要功能: // 1.释放本cpu所有已经完成传输的skb // 2.关中断的情况获取本cpu的传输设备队列output_queue, 其中的设备有数据需要进行传输 // 3.清除设备传输调度标志,表明设备可以接收下一次传输调度 // 4.获取设备队列锁queue_lock,通过队列规则接口,进行设备数据传输 // 5.如果获取queue_lock失败,说明设备当前正在进行传输,重调度设备 // 注:发送软中断中,output_queue挂载的设备均为有队列规则设备,没有队列规则的设备不会在软中断进行传输,因为其没有传输调度的概念 3.3 static void net_tx_action(struct softirq_action *h) { struct softnet_data *sd = &__get_cpu_var(softnet_data); //如果完成队列非空 if (sd->completion_queue) { struct sk_buff *clist; //关本cpu中断 local_irq_disable(); //取下本cpu的完成队列 clist = sd->completion_queue; sd->completion_queue = NULL; local_irq_enable(); while (clist) { struct sk_buff *skb = clist; clist = clist->next; //释放对应的skb __kfree_skb(skb); } } //如果输出队列非空 if (sd->output_queue) { struct net_device *head; //将输出队列取下 local_irq_disable(); head = sd->output_queue; sd->output_queue = NULL; local_irq_enable(); while (head) { struct net_device *dev = head; //net_device 通过next_sched链接到output_queue上 head = head->next_sched; //一个内存屏障 smp_mb__before_clear_bit(); //设备准备好进行传输,清除设备调度标志,说明,当设备执行传输时,属于非调度状态,可以被重新调度。 clear_bit(__LINK_STATE_SCHED, &dev->state); //获取设备的输出队列锁 if (spin_trylock(&dev->queue_lock)) { //通过出口队列规则,调度设备 qdisc_run(dev); spin_unlock(&dev->queue_lock); } else { //说明队列正在进行传输,重新调度设备 netif_schedule(dev); } } } }
最后更新:2017-04-03 15:22:11
上一篇:
更改 SAR 时间输出格式 AM/PM
下一篇:
网络子系统18_arp对代理的处理
matlab产生莱斯分布随机数
Sql Server 常用函数
Project has no default.properties file! Edit the project properties to set one.错误解决方法
c# 数据类型与运算符
负载均衡(SLB)使用最佳实践
??????????????????????????????Oracle Sharding????????????????????????-??????-????????????-?????????
使用Qt做一个简易音乐播放器[Phonon浅谈--续]
重磅!支付宝小程序悄然上线,分享能力更强大!ofo小程序怒怼摩拜小程序
四大经过市场验证正确的手机思路
JavaEE中使用Filter来实现图片的防盗链