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

【LwIP源码学习5】网口接收数据处理过程

前言

本文对lwip中TCPIP_MSG_INPKT类型消息的处理过程进行分析。

正文

在 【LwIP源码学习4】主线程tcpip_thread一文中提到。lwip主线程tcpip_thread会先从邮箱tcpip_mbox中取出消息,然后调用tcpip_thread_handle_msg函数根据消息类型对消息进行处理。

static void
tcpip_thread_handle_msg(struct tcpip_msg *msg)
{switch (msg->type) {......case TCPIP_MSG_INPKT:LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));if (msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif) != ERR_OK) {pbuf_free(msg->msg.inp.p);}memp_free(MEMP_TCPIP_MSG_INPKT, msg);break;......}
}

在判断到消息类型msg->typeTCPIP_MSG_INPKT时,会执行这个消息对应的msg->msg.inp.input_fn函数,并传入参数msg->msg.inp.pmsg->msg.inp.netif
TCPIP_MSG_INPKT类型的消息是在tcpip_inpkt函数中被创建的。

err_t
tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
{
......msg->type = TCPIP_MSG_INPKT;msg->msg.inp.p = p;//网卡接收到的数据msg->msg.inp.netif = inp;//网卡对应的结构体msg->msg.inp.input_fn = input_fn;//处理本包数据的函数//向tcpip_mbox邮箱中发送这个消息if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {memp_free(MEMP_TCPIP_MSG_INPKT, msg);return ERR_MEM;}
......
}

tcpip_inpkt函数在tcpip_input函数中被调用

err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
#if LWIP_ETHERNET//判断是否支持ARP协议if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {return tcpip_inpkt(p, inp, ethernet_input);} else
#endif /* LWIP_ETHERNET */return tcpip_inpkt(p, inp, ip_input);
}

如果判断相应网卡支持ARP就将ethernet_input函数设置为这包数据的处理函数。
如果不支持就把ip_input设置为处理函数,ip_input就是ip4_input函数,将这包数据作为IP数据报进行处理。
接下来是ethernet_input部分源码:

err_t
ethernet_input(struct pbuf *p, struct netif *netif)
{struct eth_hdr *ethhdr;u16_t type;
......//获取网卡接受数据的以太网首部ethhdr = (struct eth_hdr *)p->payload;
......//在以太网首部中获取本包数据的类型type = ethhdr->type;
......switch (type) {......case PP_HTONS(ETHTYPE_IP):  //如果本包数据是IP数据报......    ip4_input(p, netif);...break;case PP_HTONS(ETHTYPE_ARP): //如果本包数据是ARP数据报......etharp_input(p, netif);...break;......default:...}return ERR_OK;
}

以上代码中先从数据获取以太网首部,结构体eth_hdr内容为:

struct eth_hdr {PACK_STRUCT_FLD_S(struct eth_addr dest);PACK_STRUCT_FLD_S(struct eth_addr src);PACK_STRUCT_FIELD(u16_t type);
} PACK_STRUCT_STRUCT;

刚好对应以太网帧结构:
在这里插入图片描述
然后获取本包数据类型,并进行相应的处理。

再回到tcpip_input函数。
TCPIP_Init函数中的

netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);

tcpip_input与网卡绑定起来,其中gnetif是网卡对应结构体,ipaddr是IP地址,netmask是子网掩码,gw是网关,ethernetif_init是网卡的初始化函数,tcpip_input是网卡消息处理函数。
netif_add函数里通过

netif->input = input;

完成绑定。之后netif->input就代表了tcpip_input函数。
ethernetif_input函数中取出网卡数据,并调用netif->input进行处理。

void ethernetif_input(void *pParams) {struct netif *netif;struct pbuf *p = NULL;netif = (struct netif*) pParams;LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));while(1) {//等待信号量s_xSemaphore,有说明网卡有数据需要处理if(xSemaphoreTake( s_xSemaphore, portMAX_DELAY ) == pdTRUE){......p = low_level_input(netif);//取出网卡接受到的数据...if(p != NULL){...//调用tcpip_input函数进行处理if (netif->input(p, netif) != ERR_OK){LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));pbuf_free(p);p = NULL;}...}}}
}

ethernetif_input函数在low_level_init函数中被创建成一个任务的执行函数。它的主要任务是等待信号量s_xSemaphore,有信号量说明网卡接受到了数据,然后取出数据做进一步处理。
s_xSemaphore信号量是在以太网接受完数据触发中断后,在回调函数里释放的。

void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

以上分析涉及到lwip处理数据的3个任务:

任务功能
网口接受数据完成中断任务用于释放网卡有数据需要处理的信号。
ethernetif_input任务用于等待网卡有消息信号,并从网卡取出数据封装成消息放入邮箱中。
tcpip_thread任务用于从邮箱中取出消息,并做进一步协议栈的处理(ARP、IP、TCP、UDP)。

在这里插入图片描述


http://www.mrgr.cn/news/64715.html

相关文章:

  • 如何修改WordPress经典编辑器的默认高度?
  • 【JAVA】第3关:素数链
  • 一种基于GPU的归并排序并行实现
  • 聊一聊Spring中的@Transactional注解【下】【注解失效场景】
  • OpenCV中使用EdgeDrawing模块查找圆
  • YOLOv10改进策略【注意力机制篇】| ICLR2023 高效计算与全局局部信息融合的 Sea_Attention 模块(含PSA二次创新)
  • 数据挖掘(七)
  • 【设计模式系列】总览
  • ‌【元素周期表】氢
  • LeetCode 3226. 使两个整数相等的位更改次数
  • 11.3笔记
  • 图解大模型训练系列:序列并行1,Megatron SP
  • 图像滤波技术详解与实践应用
  • 如何评价mamba,是一个比conda更优秀的包管理器吗?
  • RSA算法:公钥加密的实现与应用
  • 考研要求掌握的C语言(冒泡排序专题)
  • [Android]从FLAG_SECURE禁止截屏看surface
  • 周报_2024/11/3
  • 访问者模式:将操作与对象结构分离的设计模式
  • 插值表达式
  • 提高交换式网络可靠性之STP配置
  • modelscope下载Qwen2.5 72B 模型方法
  • Automattic 和 Matt Mullenweg 要求驳回 WP Engine 诉讼案中的关键索赔
  • GPRS是什么?
  • 嵌入式数据存储小记(bss,data,text,stack,heap)
  • ACIS创建各种基本体,举例说明