ip4_route_src()
匹配网卡 。ip4_output_if()
把数据包传入IP层处理 。/** * Simple interface to ip_output_if. It finds the outgoing network * interface and calls upon ip_output_if to do the actual work. * * @param p the packet to send (p->payload points to the data, e.g. nextprotocol header; if dest == LWIP_IP_HDRINCL, p already includes anIP header and p->payload points to that IP header) * @param src the source IP address to send from (if src =https://www.huyubaike.com/biancheng/= IP4_ADDR_ANY, the *IPaddress of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to * @param ttl the TTL value to be set in the IP header * @param tos the TOS value to be set in the IP header * @param proto the PROTOCOL to be set in the IP header * * @return ERR_RTE if no route is found *see ip_output_if() for more return values */err_tip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest,u8_t ttl, u8_t tos, u8_t proto){struct netif *netif;/* 下传到IP层的pbuf的ref必须为1,即是没有被其它地方引用 , 因为pbuf下传到IP层后 , pbuf的payload指针会被更改 。如果这个pbuf被其它地方引用了,可能会导致数据混乱 。*/LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);/* 根据目的IP地址为数据报寻找一个合适的网络接口(匹配网卡) */if ((netif = ip4_route_src(src, dest)) == NULL) { /* 没找到,记录信息,返回错误 */LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));IP_STATS_INC(ip.rterr);return ERR_RTE;}/* 匹配到网卡,传入IP层处理:组包、发送 */return ip4_output_if(p, src, dest, ttl, tos, proto, netif);}
9.7.3 发包前的网卡匹配IP层收到上层的数据包后,需要匹配到网络接口 , 才能组IP包发出去 。这里调用
ip4_route_src()
进行网卡匹配 。具体分析参考前面 。9.7.4 组建、发送IP包注意几个函数的区别:
ip4_output_if()
:这个函数封装了底层IP层组包、发送的实现函数 。ip4_output_if_src()
:这个函数就是IP层组包、发送的实现函数 。不支持IP首部的选项字段 。ip4_output_if_opt()
:这也是IP层组包、发送的实现函数,会用选中的网卡IP地址覆盖传入的源IP地址 。支持IP首部的选项字段 。ip4_output_if_opt_src()
:这也是IP层组包、发送的实现函数,不会用选中的网卡IP地址覆盖传入的源IP地址 。支持IP首部的选项字段 。
IP_OPTIONS_SEND
:- IP首报文首部选项字段宏开关 。
- 如果开启了该宏 , 则会调用上述带
_opt
字样的函数,操作IP首部报文的选项字段 。
LWIP_IP_HDRINCL
:缺省为NULL
- 如果把这个宏当目的IP地址传入IP层组包、发送的相关函数
ip4_output_if()
或其底层函数时 , 表示当前这个pbuf已经组好IP首部了 。 - 一般用于TCP重传 。
LWIP_CHECKSUM_CTRL_PER_NETIF
:- 允许每个网卡配置checksum功能 。
ip_id
:IP首部标识,全局值 。
ip4_output_if_opt_src()
函数,比较全 。ip4_output_if_opt_src()
:- 先处理选项字段,在处理IP首部其它字段 。
struct pbuf *p
:传输层协议需要发送的数据包pbuf,payload指针已指向传输层协议首部 。const ip4_addr_t *src
:源IP地址 。const ip4_addr_t *dest
:目的IP地址 。u8_t ttl
:IP首部TTL字段 。u8_t tos
:IP首部TOS字段 。u8_t proto
:IP首部上层协议字段 。struct netif *netif
:发送IP数据报的网卡 。void *ip_options
:IP首部选项字段值 。u16_t optlen
:IP首部选项字段的长度 。
- 通过目的IP判断当前pbuf是否已经组好IP报文首部 。如果组好了 , 就不需要继续重组了 。如tcp重传 。
- 如果传入的pbuf报文还没组好IP报文首部,则根据传入的相关数据和IP报文内容进行组包 。
- 组好包后检查目的IP是否是环回IP(如环回IP、当前网卡的IP),如果是就调用
netif_loop_output()
进行环回处理 。
- 如果不是环回数据包,就需要发到数据链路 。
- IP分片:如果IP报文总长大于网卡MTU,则需要调用
ip4_frag()
进行IP分片 。 - 如果不需要IP分片,直接调用
推荐阅读
- 【第5篇】AI语音简介
- 原神3.0陵薮市朝什么时间开启
- 【Azure 环境】把OpenSSL生产的自签名证书导入到Azure Key Vault Certificate中报错
- 常用类.String类
- cf如何跳上高箱子(cf开什么箱子赚cf点)
- macos monterey描述文件下载_macos monterey描述文件下载地址
- 浏览器怎样清除缓存(浏览器历史清空了怎么恢复)
- 我的世界豹猫怎么驯服,为什么给豹猫喂鱼之后不变成猫
- 支付宝蚂蚁庄园每日答题答案
- 原神90级提纳里毕业面板数值怎么样
- IP分片:如果IP报文总长大于网卡MTU,则需要调用