基于LwIP的双网络接口下如何检测各AP的互联网连通性
LwIP双网络接口互联网连通性检测与自动选路方案
问题根因:LwIP默认的路由策略仅根据路由表的注册顺序或metric值选路,不会主动判断接口对应的网络是否实际具备互联网连通性,所以会出现固定走先注册的接口0导致场景2 ping失败的问题。
以下是两种可行方案,可根据你的业务需求选择:
方案1:全栈流量自动选路(适配所有上层业务,不需要修改业务逻辑)
- 给两个接口的默认网关都注册到LwIP路由表,分别配置不同的初始metric值(数值越小优先级越高,比如接口0初始设为10,接口1初始设为20)
- 新增一个低优先级的后台守护线程,定时执行以下逻辑:
- 分别强制绑定两个网络接口,向公共可访问的固定IP(比如8.8.8.8、1.1.1.1)发送ICMP探测包或者TCP SYN包到80/443端口,避免走默认路由导致探测结果不准
- 若某个接口连续3次探测失败,将该接口对应默认路由的metric值调整为100(降低优先级)
- 若之前探测失败的接口连续2次探测恢复成功,将其metric值调回初始值
- LwIP的路由查询逻辑会自动选择当前metric值最小的可用路由,所有上层业务不需要修改就能自动走具备互联网连通性的接口
方案2:仅针对ping场景做选路(改动最小,不需要修改路由配置)
如果只需要实现ping请求的自动选通,不需要其他业务流量自动切换,可以直接改造ping的调用逻辑:
- 封装绑定指定接口的ping探测函数,核心逻辑是调用
ip_output_if()接口强制从指定netif发送报文,不走全局路由表查询,参考代码如下:
#include <lwip/netif.h> #include <lwip/ip.h> #include <lwip/icmp.h> #define PING_ID 0x1234 #define PING_SEQ 0x5678 // 绑定指定netif发送ICMP探测,返回ERR_OK表示发送成功,可配合回调判断是否收到响应 err_t ping_probe_netif(struct netif *target_netif, const ip4_addr_t *probe_dest) { struct pbuf *p = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + 56, PBUF_RAM); if (!p) return ERR_MEM; struct icmp_echo_hdr *echo_hdr = (struct icmp_echo_hdr *)p->payload; ICMPH_TYPE_SET(echo_hdr, ICMP_ECHO); ICMPH_CODE_SET(echo_hdr, 0); echo_hdr->id = lwip_htons(PING_ID); echo_hdr->seqno = lwip_htons(PING_SEQ); echo_hdr->chksum = 0; memset((uint8_t *)echo_hdr + sizeof(struct icmp_echo_hdr), 0xAA, 56); echo_hdr->chksum = inet_chksum(echo_hdr, p->len); err_t ret = ip_output_if(p, netif_ip4_addr(target_netif), probe_dest, 64, 0, IP_PROTO_ICMP, target_netif); pbuf_free(p); return ret; }
- 每次发起公网ping请求前,先调用上述探测函数分别检测两个接口的连通性,选择能收到探测响应的接口作为发送接口,再发起正式的ping请求
注意事项
- 探测时建议直接用固定公网IP,不要用域名,避免域名解析阶段走默认路由导致探测结果不准确
- 后台探测的间隔建议设置为30s以上,避免产生不必要的流量和性能开销
- 如果需要同时支持IPv6,只需要把探测目标换成IPv6的公共DNS(比如240c::6666),调用
ip6_output_if()发送探测包即可
内容的提问来源于stack exchange,提问作者Sue Koh
相关产品推荐
相关产品推荐

