问题: OSPF对于虚连接采用路由方式发送报文,但其余的单播报文都是在直连网段上发送的,因 此不需要匹配路由表。 采用DONT_ROUTE方式发送报文时, 开关IP routing导致tNet0异常。 分析: Arp在协议栈中存在两份: 一份是普通路由表,使用radix树进行组织,通过ipnet_route_raw_lookup进行查找。 另一份是DON’T_ROUTE方式创建的保存在don’t_route_list中的arp表项,使用双向链表组 织,通过ipnet_route_lookup_ip4_dont_route进行查找。 don’t_route_list:双向链表,通过prev和next指针链接,用于保存DONT_ROUTE方式发包 创建的arp表项。 不使用DONT_ROUTE方式发送报文 (如Ping) 时, 不会创建don’t_route_list。 采用DONT_ROUTE方式发送报文时, 最终通过socket调用到ipnet_ip4_output函数进行发送, 若采用DON’T_ROUTE方式,则将查找don’t_route_list表是否存在到达对端的arp,不存在 则不进行发送,并添加一条空的arp路由到don’t_route_list。通过这种方式学习到的arp将 存在两份路由信息,一份在radix树下,一份在don’t_route_list下。
若使用非DONT_ROUTE方式, 则don’t_route_list为空, 所有arp和学习的路由都添加在radix 树组织的路由表中。
学习ARP流程:
学习到arp时,先查找don’t route表项,若存在,则更新链路地址。然后再查找路由表,更 新arp表项对应路由的链路地址。代码:
其中ipnet_eth_arp_update_entry用于更新arp表项的链路层地址,并且更新radix树信息。 由于在don’t_route_list中并不是以radix方式进行组织的, 因此在更新radix数信息时产生异 常,访问了radix才存在的一些指针结构。 由于普通方式下,由于don’t_route_list不存在任何信息,因此在学习arp时无法查找到 don’t_route_list中的路由信息,因而在更新radix树中的节点信息时不会产生异常
问题。 解决方法:
ipnet_route_has_changed更新处理流程中遍历所有与查找到的路由(arp路由)key相同的 其他节点,若存在其他节点,则会将当前路由插入并作更新操作。若路由为don’t_route_list 中的节点,通过前后指针查找到的路由key是不同的(don’t_route_list不存在等价情况) , 因此可以根据这个区分是否是radix树中的节点。若为don’t_route_list
中的节点,则不更新
radix树信息。
原处理代码:
修改后代码: