完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
网卡
网卡工作在物理层和数据链路层,主要由PHY/MAC芯片、Tx/Rx FIFO、DMA等组成,其中网线通过变压器接PHY芯片、PHY芯片通过MII接MAC芯片、MAC芯片接PCI总线 PHY芯片主要负责:CSMA/CD、模数转换、编解码、串并转换 MAC芯片主要负责:
收发包过程图 ixgbe_adapter包含ixgbe_q_vector数组(一个ixgbe_q_vector对应一个中断),ixgbe_q_vector包含napi_struct 硬中断函数把napi_struct加入CPU的poll_list,软中断函数net_rx_action()遍历poll_list,执行poll函数 发包过程 1、网卡驱动创建tx descriptor ring(一致性DMA内存),将tx descriptor ring的总线地址写入网卡寄存器TDBA 2、协议栈通过dev_queue_xmit()将sk_buff下送网卡驱动 3、网卡驱动将sk_buff放入tx descriptor ring,更新TDT 4、DMA感知到TDT的改变后,找到tx descriptor ring中下一个将要使用的descriptor 5、DMA通过PCI总线将descriptor的数据缓存区复制到Tx FIFO 6、复制完后,通过MAC芯片将数据包发送出去 7、发送完后,网卡更新TDH,启动硬中断通知CPU释放数据缓存区中的数据包 Tx Ring Buffer SW将sk_buff挂载到从next_to_use开始的N个descriptor,next_to_use += N,tail = next_to_use(写网卡寄存器TDT) HW使用DMA读从head开始的M个descriptor的sk_buff,发送成功后回写DD(Descriptor Done),head += M SW将从next_to_clean的开始的L个sk_buff移出Tx Ring Buffer并清理,next_to_clean += L 注意:每次挂载完sk_buff后,tail和next_to_use指向同一个descriptor 收包过程 1、网卡驱动创建rx descriptor ring(一致性DMA内存),将rx descriptor ring的总线地址写入网卡寄存器RDBA 2、网卡驱动为每个descriptor分配sk_buff和数据缓存区,流式DMA映射数据缓存区,将数据缓存区的总线地址保存到descriptor 3、网卡接收数据包,将数据包写入Rx FIFO 4、DMA找到rx descriptor ring中下一个将要使用的descriptor 5、整个数据包写入Rx FIFO后,DMA通过PCI总线将Rx FIFO中的数据包复制到descriptor的数据缓存区 6、复制完后,网卡启动硬中断通知CPU数据缓存区中已经有新的数据包了,CPU执行硬中断函数:
Rx Ring Buffer SW向从next_to_use开始的N个descriptor补充sk_buff,next_to_use += N,tail = next_to_use(写网卡寄存器RDT) HW写Frame到从head开始的M个descriptor的sk_buff,写完后回写EOP(End of Packet),head += M SW将从next_to_clean开始的L个sk_buff移出Rx Ring Buffer并上送协议栈,next_to_clean += L,向从next_to_use开始的L个descriptor补充sk_buff,next_to_use += L,tail = next_to_use 注意:每次补充完sk_buff后,tail和next_to_use指向同一个sk_buff 中断上下部 do_IRQ()是CPU处理硬中断的总入口 do_IRQ()是CPU处理硬中断的总入口 // 在e1000_request_irq()中注册硬中断,中断函数为e1000_intr() irq_handler_t handler = e1000_intr; err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, netdev); // 在net_dev_init()中注册软中断,中断函数为net_rx_action() open_softirq(NET_RX_SOFTIRQ, net_rx_action); // 在e1000_probe()中注册napi的poll函数为e1000_clean() netif_napi_add(netdev, &adapter->napi, e1000_clean, 64); // 在net_dev_init()中注册非napi的poll函数为process_backlog() queue->backlog.poll = process_backlog; netif_rx() 在netif_rx()中把skb加入CPU的softnet_data int netif_rx(struct sk_buff *skb) { struct softnet_data *queue; unsigned long flags; /* if netpoll wants it, pretend we never saw it */ if (netpoll_rx(skb)) return NET_RX_DROP; if (!skb->tstamp.tv64) net_timestamp(skb); /* * The code is rearranged so that the path is the most * short when CPU is congested, but is still operating. */ local_irq_save(flags); queue = &__get_cpu_var(softnet_data); // 得到CPU的softnet_data __get_cpu_var(netdev_rx_stat).total++; if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { // 若队列长度不大于netdev_max_backlog if (queue->input_pkt_queue.qlen) { // 若队列长度非0,表示queue->backlog已被加入poll_list enqueue: __skb_queue_tail(&queue->input_pkt_queue, skb); // 将skb加入队列尾部 local_irq_restore(flags); return NET_RX_SUCCESS; } napi_schedule(&queue->backlog); // 调度queue->backlog goto enqueue; // 将skb加入队列尾部 } __get_cpu_var(netdev_rx_stat).dropped++; local_irq_restore(flags); kfree_skb(skb); return NET_RX_DROP; } |
|
|
|
只有小组成员才能发言,加入小组>>
4589个成员聚集在这个小组
加入小组3355 浏览 0 评论
航顺(HK)联合电子发烧友推出“近距离体验高性能Cortex-M3,免费申请价值288元评估板
4276 浏览 1 评论
4304 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-7 06:36 , Processed in 0.474316 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号