【lwip】09-IPv4协议&超全源码实现分析( 五 )

  • 以上都没有匹配成功,则使用netif_default,必须条件:
    • 默认网卡netif_default存在;
    • 默认网卡协议栈有效;
    • 默认网卡数据链路有效;
    • 默认网卡IP有效 。
    • 匹配的目的IP不能为环回IP(因为如果是环回IP,前面已经匹配过了,除非没有开启该功能)
  • /** * Finds the appropriate network interface for a given IP address. It * searches the list of network interfaces linearly. A match is found * if the masked IP address of the network interface equals the masked * IP address given to the function. * * @param dest the destination IP address for which to find the route * @return the netif on which to send to reach dest */struct netif *ip4_route(const ip4_addr_t *dest){#if !LWIP_SINGLE_NETIFstruct netif *netif;/* 确保在tcpip内核锁内 */LWIP_ASSERT_CORE_LOCKED();#if LWIP_MULTICAST_TX_OPTIONS /* 开启了组播TX功能 *//* 如果目的IP是一个组播地址,且协议栈内创建了组播专用网卡,则选用组播专用网卡接口 */if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) {return ip4_default_multicast_netif;}#endif /* LWIP_MULTICAST_TX_OPTIONS *//* bug #54569: in case LWIP_SINGLE_NETIF=1 and LWIP_DEBUGF() disabled, the following loop is optimized away */LWIP_UNUSED_ARG(dest);/* 遍历网卡链表 */NETIF_FOREACH(netif) {/* 网卡协议栈有效,网卡链路层也有效,网卡的IP地址不为全0 */if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) {/* 匹配传入的目的IP和网卡是否处于同一个子网 */if (ip4_addr_net_eq(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) {/* 匹配成功 。返回netif,以转发IP数据包 */return netif;}/* 当前网卡子网匹配不成功 *//* 那就匹配下网关,匹配规则:网卡没有广播功能,目的IP和网关IP一致 。也算匹配成功,因为上层的目的是到网关 。当前网卡能把数据传达到网卡 。*/if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_eq(dest, netif_ip4_gw(netif))) {/* 匹配成功 。返回netif , 以转发IP数据包 */return netif;}}}/* 到这 , 遍历网卡,匹配失败 *//* 开启了环回功能,但是没有创建环回网卡 。(因为如果创建了环回网卡,在遍历网卡链表时就已经处理过了,这里不需要再处理) */#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF/* 如果目的IP是一个环回IP地址,则优先返回默认网卡,否则返回网卡链表中第一个协议栈使能了的网卡作为当前环回网卡 */if (ip4_addr_isloopback(dest)) { /* 目的IP是一个环回IP */if ((netif_default != NULL) && netif_is_up(netif_default)) {/* 优先考虑默认网卡 。如果有默认网卡 , 且默认网卡协议栈使能了,则以此网卡作为本次环回网卡 */return netif_default;}/* 默认网卡没有匹配成功,则从网卡链表中找一个协议栈已使能的网卡作为本次环回网卡 */NETIF_FOREACH(netif) {if (netif_is_up(netif)) {return netif;}}return NULL; /* 都没找到,那就匹配失败 */}#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */#ifdef LWIP_HOOK_IP4_ROUTE_SRC /* 如果开启了匹配网卡的钩子宏函数 */netif = LWIP_HOOK_IP4_ROUTE_SRC(NULL, dest); /* 使用宏钩子匹配 */if (netif != NULL) {return netif;}#elif defined(LWIP_HOOK_IP4_ROUTE) /* 网卡匹配钩子 */netif = LWIP_HOOK_IP4_ROUTE(dest); /* 使用宏钩子匹配 */if (netif != NULL) {return netif;}#endif#endif /* !LWIP_SINGLE_NETIF *//* 上述方案都无法匹配到网卡,就检查网卡网卡是否正常,正常则就返回默认网卡 */if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) ||ip4_addr_isany_val(*netif_ip4_addr(netif_default)) || ip4_addr_isloopback(dest)) {LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: 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);MIB2_STATS_INC(mib2.ipoutnoroutes);return NULL;}return netif_default; /* 返回默认网络接口 */}9.5.3 路由网卡匹配支持源IP和目的IP网卡匹配的接口匹配网卡,一般是按照目的IP来匹配,但是可以通过LWIP_HOOK_IP4_ROUTE_SRC()钩子宏函数来实现源IP地址和目的IP地址匹配 。
    ip4_route_src()
    • 如果源IP地址不为空,则会先传入LWIP_HOOK_IP4_ROUTE_SRC()钩子函数来匹配网卡 。
    • 钩子函数匹配失败或者源IP地址为空,则由ip4_route()只根据目的IP地址匹配 。
    #ifdef LWIP_HOOK_IP4_ROUTE_SRC/** * Source based IPv4 routing must be fully implemented in * LWIP_HOOK_IP4_ROUTE_SRC(). This function only provides the parameters. */struct netif *ip4_route_src(const ip4_addr_t *src, const ip4_addr_t *dest){if (src != NULL) {/* 当src=https://www.huyubaike.com/biancheng/=NULL时,钩子会从ip4_route(dest)调用 */struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(src, dest);if (netif != NULL) {return netif;}}return ip4_route(dest);}#endif /* LWIP_HOOK_IP4_ROUTE_SRC */

    推荐阅读