9.6 IP层数据流图

文章插图
9.7 IP层输出ipv4 。
当上层需要发送数据时,会先将自己的数据包组装在一个pbuf中 。并将payload指针指向对应协议首部 。
然后调用
ip_output()
发送数据,需要给ip_output()
函数提供源IP、目的IP、协议类型、TTL等重要信息让其组IP包 。该函数直接或者间接调用
ip4_route_src()
根据目的IP选出一个匹配的网卡作为本次IP数据包传输网卡 。选出后调用
ip4_output_if()
进行IP数据包组包,并调用netif->output()
发送出去 。或者调用netif_loop_output()
环回到本网卡 。9.7.1 发送数据报上层调用
ip_output()
把数据转交给IP层处理,lwip支持ipv4和ipv6,这里默认分析ipv4,因为ipv6也是一大块,后面有时间再完整分析下 。/** * @ingroup ip * Output IP packet, netif is selected by source address */#define ip_output(p, src, dest, ttl, tos, proto) \(IP_IS_V6(dest) ? \ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto))
9.7.2 ip层前期处理:ip4_output()ipv4发包:- 检查pbuf的引用ref是否为1 。为1才能说明当前pbuf没有被其它地方引用,因为IP层处理可能会改变这个pbuf的部分指针值,如payload 。
- 调用
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首部的选项字段 。经验总结扩展阅读
- 生的榛子在家怎么炒熟
- 【第5篇】AI语音简介
- 青椒炒鸡蛋热量
- 洗衣服时应当使用哪种洗衣粉
- 蛋白粉用冷水冲还是热水
- 2023最火女儿生日文案简短 生日文案高级简短
- 晒干辣椒的方法
- 有机鲜牛奶和鲜牛奶区别
- 绿豆芽可以放冰箱几天
- 2023七夕节适合结婚吗 2023年七夕结婚吉利吗