网络数据包收发流程(三):e1000网卡和DMA

简介: 一、硬件布局每个网卡(MAC)都有自己的专用DMA Engine,如上图的 TSEC 和 e1000 网卡intel82546。上图中的红色线就是以太网数据流,DMA与DDR打交道需要其他模块的协助,如TSEC,PCI controller以太网数据在 TSECDDR  PCI_Co...
一、硬件布局
img_b48d4dacb81ed094d85381898620fdd6.jpg
每个网卡(MAC)都有自己的专用DMA Engine,如上图的 TSEC 和 e1000 网卡intel82546。
上图中的红色线就是以太网数据流,DMA与DDR打交道需要其他模块的协助,如TSEC,PCI controller
以太网数据在 TSECDDR  PCI_ControllerDDR 之间的流动,CPU的core是不需要介入的
只有在数据流动结束时(接收完、发送完),DMA Engine才会以外部中断的方式告诉CPU的core

二、DMA Engine
img_f737726829e00e9b2e5c3e6fe578791c.jpe
上面是DMA Engine的框图,以接收为例:
1.在System memory中为DMA开辟一端连续空间,用来BD数组  (一致性dma内存)
  BD是给DMA Engine使用的,所以不同的设备,BD结构不同,但是大致都有状态、长度、指针3个成员。

2.初始化BD数组,status为E,length为0
   在System memory中再开辟一块一块的内存,可以不连续,用来存放以太网包
   将这些内存块的总线地址赋给buf(dma映射)

3.当MAC接收以太网数据流,放在了Rx FIFO中

4.当一个以太网包接收完全后,DMA engine依次做以下事情
    fetch bd:开始一个个的遍历BD数组,直到当前BD状态为Empty为止
    update bd:更新BD状态为Ready
    move data:把数据从Rx FIFO中搬移到System Memory中dma映射的部分
    generate interrupt:数据搬移完了,产生外部中断给cpu core

5.cpu core处理外部中断,此时以太网数据已经在System memory中dma映射的部分了
    解除dma映射,更新bd状态为Empty
    再开辟一端内存,将这块内存的总线地址赋给bd的指针字段

三、内核中DMA相关API

void * dma_alloc_cohrent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);
功能:分配一致性dma内存,返回这块内存的虚拟地址EA, 这块内存的物理地址保存在 dma_handle
dev:  NULL也行
size: 分配空间的大小
dma_handle: 用来保存内存的总线地址(物理地址)

注意: 一致性DMA映射BD所占内存就是靠 dma_alloc_cohrent来分配的。

dma_addr_t * dma_map_single(struct device *dev, void *buffer, size_t size, enum dma_data_direction);
功能:将一块连续的内存 buffer 映射为DMA内存来使用。映射后,CPU不能再操作这块 buffer
返回:这块buffer的总线地址(物理地址)
dev: NULL也行
buffer: 一块连续内存的虚拟地址EA
size: 连续内存的大小
dma_data_direction: dma数据流的方向

注意: 流式DMA映射以太网包所占内存先通过 kmalloc来分配,然后通过 dma_map_single来映射给bd的

四、e1000驱动中的DMA

网卡驱动中使用DMA的套路差不多都一样,以e1000驱动为例讲一下( TSEC驱动的dma见这里

4.1 加载e1000网卡驱动

e1000_probe(){                        //主要是初始化钩子函数
     netdev = alloc_etherdev(sizeof(struct e1000_adapter));
    netdev->open = & e1000_open;       //重要
    netdev->stop = &e1000_close;
    netdev->hard_start_xmit = &e1000_xmit_frame;
    netdev->get_stats = &e1000_get_stats;
    netdev->set_multicast_list = &e1000_set_multi;
    netdev->set_mac_address = &e1000_set_mac;
    netdev->change_mtu = &e1000_change_mtu;
    netdev->do_ioctl = &e1000_ioctl;
    e1000_set_ethtool_ops(netdev);
    netdev->tx_timeout = &e1000_tx_timeout;
    netdev->watchdog_timeo = 5 * HZ;
#ifdef CONFIG_E1000_NAPI
    netif_napi_add(netdev, &adapter->napi, e1000_clean, 64); //重要
#endif
}

4.1 启动e1000网卡

   e1000_open() //当用户敲ifconfig up命令时,最终调用网卡驱动的open函数
     -->e1000_setup_all_rx_resources(adapter)
         -->e1000_setup_rx_resources(adapter, &adapter->rx_ring[i])
               //给rx bd分配一致性dma内存
               rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
     -->e1000_configure(adapter)
         -->e1000_configure_rx(adapter)
               adapter->clean_rx = e1000_clean_rx_irq;
               adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
         -->调用 adapter->alloc_rx_buf钩子函数,即 e1000_alloc_rx_buffers
                --> skb = netdev_alloc_skb(netdev, bufsz); //调用kmalloc新建一个skb
                    buffer_info->dma = pci_map_single(pdev,
                        skb->data,
                        adapter->rx_buffer_len,
                        PCI_DMA_FROMDEVICE);               // 给skb->data建立DMA映射
                    rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); //初始化bd的buf指针
     -->e1000_request_irq(adapter);
        //挂rx 中断ISR函数为 e1000_intr()

最终bd数据结构应该是下面这个样子
img_b623447b8ff897fb49ca98e108bbe886.jpg      
4.2 e1000的中断

注意:e1000产生rx中断时,以太网数据包已经在系统内存中,即在skb->data里面
下面的中断处理过程就简略了, 详细的看这里
do_IRQ()
{
    中断上半部
       调用e1000网卡的rx中断函数 e1000_intr()
          触发软中断 (使用NAPI的话)
    中断下半部
       依次调用软中断的所有handler
       在net_rx_action中最终调用e1000的napi_struct.poll()钩子函数,即e1000_clean
       e1000_clean()最终调用 e1000_clean_rx_irq()
}

e1000_clean_rx_irq()
{
     rx_desc = E1000_RX_DESC(*rx_ring, i); //获取rx bd
     status = rx_desc->status;
     skb = buffer_info->skb;
     buffer_info->skb = NULL;

     pci_unmap_single(pdev,                //解除skb->data的DMA映射
                   buffer_info->dma,
                   buffer_info->length,
                   PCI_DMA_FROMDEVICE);
     length = le16_to_cpu(rx_desc->length);
     length -= 4;                          //以太网包的FCS校验就不要了
     skb_put(skb, length);
     skb->protocol = eth_type_trans(skb, netdev);
     netif_receive_skb(skb);               //skb进入协议栈
}
目录
相关文章
|
16天前
|
监控 网络协议 安全
|
3天前
|
存储 弹性计算 测试技术
阿里云服务器实例规格vCPU、内存、网络带宽、网络收发包PPS、连接数等性能指标详解
阿里云服务器ECS实例可以分为多种实例规格族。根据CPU、内存等配置,一种实例规格族又分为多种实例规格。而实例规格又包含vCPU、处理器、内存、vTPM、本地存储、网络带宽、网络收发包PPS、连接数、弹性网卡、云盘带宽、云盘IOPS等指标,本文为大家详细介绍实例规格的这些指标,以供大家了解和选择。
阿里云服务器实例规格vCPU、内存、网络带宽、网络收发包PPS、连接数等性能指标详解
|
2天前
|
网络协议 网络虚拟化
接收网络包的过程——从硬件网卡解析到IP
【9月更文挑战第18天】这段内容详细描述了网络包接收过程中机制。当网络包触发中断后,内核处理完这批网络包,会进入主动轮询模式,持续处理后续到来的包,直至处理间隙返回其他任务,从而减少中断次数,提高处理效率。此机制涉及网卡驱动初始化时注册轮询函数,通过软中断触发后续处理,并逐步深入内核网络协议栈,最终到达TCP层。整个接收流程分为多个层次,包括DMA技术存入Ring Buffer、中断通知CPU、软中断处理、以及进入内核网络协议栈等多个步骤。
|
17天前
|
网络协议 C语言
C语言 网络编程(十一)TCP通信创建流程---服务端
在服务器流程中,新增了绑定IP地址与端口号、建立监听队列及接受连接并创建新文件描述符等步骤。`bind`函数用于绑定IP地址与端口,`listen`函数建立监听队列并设置监听状态,`accept`函数则接受连接请求并创建新的文件描述符用于数据传输。套接字状态包括关闭(CLOSED)、同步发送(SYN-SENT)、同步接收(SYN-RECEIVE)和已建立连接(ESTABLISHED)。示例代码展示了TCP服务端程序如何初始化socket、绑定地址、监听连接请求以及接收和发送数据。
|
17天前
|
C语言
C语言 网络编程(七)UDP通信创建流程
本文档详细介绍了使用 UDP 协议进行通信的过程,包括创建套接字、发送与接收消息等关键步骤。首先,通过 `socket()` 函数创建套接字,并设置相应的参数。接着,使用 `sendto()` 函数向指定地址发送数据。为了绑定地址,需要调用 `bind()` 函数。接收端则通过 `recvfrom()` 函数接收数据并获取发送方的地址信息。文档还提供了完整的代码示例,展示了如何实现 UDP 的发送端和服务端功能。
|
17天前
|
网络协议 C语言
C语言 网络编程(十)TCP通信创建流程---客户端
在TCP通信中,客户端需通过一系列步骤与服务器建立连接并进行数据传输。首先使用 `socket()` 函数创建一个流式套接字,然后通过 `connect()` 函数连接服务器。连接成功后,可以使用 `send()` 和 `recv()` 函数进行数据发送和接收。最后展示了一个完整的客户端示例代码,实现了与服务器的通信过程。
|
22天前
|
存储 缓存 网络协议
网络丢包排查方法
网络丢包排查方法
|
1月前
|
内存技术
思科TAC专家分享的内嵌抓包法,真是网络大神必备技能啊!
思科TAC专家分享的内嵌抓包法,真是网络大神必备技能啊!
|
20天前
|
测试技术 持续交付 开发者
Xamarin 高效移动应用测试最佳实践大揭秘,从框架选择到持续集成,让你的应用质量无敌!
【8月更文挑战第31天】竞争激烈的移动应用市场,Xamarin 作为一款优秀的跨平台开发工具,提供了包括单元测试、集成测试及 UI 测试在内的全面测试方案。借助 Xamarin.UITest 框架,开发者能便捷地用 C# 编写测试案例,如登录功能测试;通过 Xamarin 模拟框架,则可在无需真实设备的情况下模拟各种环境测试应用表现;Xamarin.TestCloud 则支持在真实设备上执行自动化测试,确保应用兼容性。结合持续集成与部署策略,进一步提升测试效率与应用质量。掌握 Xamarin 的测试最佳实践,对确保应用稳定性和优化用户体验至关重要。
34 0
|
27天前
|
网络协议 Linux 网络安全
【Azure 应用服务】更便捷的方式抓取Azure App Service for Windows的网络包
【Azure 应用服务】更便捷的方式抓取Azure App Service for Windows的网络包