当前位置: 首页 > news >正文

ethernet_input到应用层处理简单分析

1、驱动层:从硬件读取数据并构造pbuf

中断触发后,驱动层的接收任务(或轮询函数)会从网卡硬件读取数据,并将其封装为 LWIP 可识别的pbuf结构体(LWIP 的数据缓冲区)。

  • 关键函数

    • 驱动自定义的接收函数(如eth_rx_task):负责从网卡寄存器或 DMA 缓冲区读取原始数据。
    • pbuf_alloc:分配pbuf缓冲区,用于存储接收到的数据帧。

    示例:

    void eth_rx_task(void *arg) {struct netif *netif = (struct netif *)arg;while (1) {// 等待中断通知(信号量)sys_sem_wait(&eth_rx_sem, 0);// 从网卡读取数据长度和内容uint8_t *data = eth_hw_read(&len);// 分配pbuf并复制数据struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);if (p != NULL) {memcpy(p->payload, data, len);// 调用netif的linkoutput对应的接收回调(见步骤3)netif->input(p, netif);  // 核心:将数据送入协议栈}}
    }
    

2. 调用input函数:进入 LWIP 协议栈

驱动层构造好pbuf后,会直接调用netif->input(p, netif),将数据帧送入协议栈。对于以太网,input被赋值为ethernet_input,其作用是解析以太网帧头,根据协议类型(如 IP、ARP)分发到对应模块。

  • ethernet_input的核心逻辑

    err_t ethernet_input(struct pbuf *p, struct netif *netif) {struct eth_hdr *ethhdr;// 提取以太网帧头(目的MAC、源MAC、协议类型)ethhdr = (struct eth_hdr *)p->payload;// 根据协议类型分发:switch (htons(ethhdr->type)) {case ETHTYPE_IP:// 移除以太网帧头,将IP数据报送入IP层pbuf_remove_header(p, sizeof(struct eth_hdr));return ip4_input(p, netif);  // 进入IP层处理case ETHTYPE_ARP:// ARP报文交给ARP模块处理return arp_input(p, netif);default:pbuf_free(p);return ERR_OK;}
    }
    
  • 后续流程

    • IP 层(ip4_input)会解析 IP 头,根据协议字段(如 TCP、UDP)将数据传递到传输层。
    • 最终数据会通过socket接口或回调函数交付给应用层。

3、初始化关联:input函数

input函数在网络接口初始化时被绑定,具体是在调用netif_add时指定的,流程如下:

  1. 应用层调用netif_add
    第三个参数input通常传入ethernet_input(以太网):

    struct netif eth_netif;
    netif_add(&eth_netif, &ipaddr, &netmask, &gw, NULL, eth_init, ethernet_input);
    
  2. netif_add函数内部赋值
    netif_add中,将传入的input函数指针保存到netif结构体:

    netif->input = input;  // input即ethernet_input
    
  3. 驱动层调用netif->input
    如步骤 2 的eth_rx_task所示,驱动接收数据后,通过netif->input(p, netif)触发协议栈处理。

4、关键接口总结

环节核心函数 / 变量作用
硬件中断eth_isr触发数据接收事件,通知驱动层
驱动层数据读取eth_rx_task(自定义)从硬件读取数据,构造pbuf
协议栈入口netif->input指向ethernet_input,作为数据入口点
以太网帧解析ethernet_input(LWIP 提供)解析以太网帧,分发到 IP/ARP 模块
网络层处理ip4_input处理 IP 数据报,传递到传输层
http://www.dtcms.com/a/335249.html

相关文章:

  • 5 索引的操作
  • K8s核心组件全解析
  • 如何使用嵌入模型创建本地知识库Demo
  • 三、memblock 内存分配器
  • 深入理解文件硬链接、软链接与引用计数的那些事
  • 机器学习相关算法:回溯算法 贪心算法 回归算法(线性回归) 算法超参数 多项式时间 朴素贝叶斯分类算法
  • 超详细yolo8/11-pose人体姿态全流程概述:配置环境、数据标注、训练、验证/预测、onnx部署(c++/python)详解
  • 8.16、8.17 JavaWeb(MyBatis P116-P134)
  • 【网络与爬虫 00】试读
  • lcx、netcat、powercat--安装、使用
  • 【RH134知识点问答题】第 10 章:控制启动过程
  • 深入浅出OpenGL的glDrawArray函数
  • 设计索引的原则有哪些?
  • 数据结构初阶(16)排序算法——归并排序
  • w嵌入式分享合集66
  • 开发一款多商户电商APP要多久?功能拆解与源码技术落地方案
  • vulhub-driftingblues9缓冲区溢出攻击提权
  • 写一个linux脚本,要求实现查找9010端口,如果端口存在则kill,否则不处理,返回对应的提示
  • LE AUDIO----COMMAND AND EVENT
  • ArrayList的扩容源码分析
  • colmap
  • ABB焊接机器人弧焊省气
  • windows扩展(外接)显示器位置调节
  • 狗品种识别数据集:1k+图像,6个类别,yolo标注完整
  • 利用Qwen大模型进行c++11并发库的学习,与时俱进!!!!
  • File 类的用法和 InputStream, OutputStream 的用法
  • C#高级用法:元组
  • pidgen!DecodeProdKey函数分析之iDecodedBytesMax
  • docker安装mongodb及java连接实战
  • 视频理解综述