Linux内核分析 - 网络[四]:路由表
路由缓存插入条目 函数rt_intern_hash() 要插入的条目是rt,相应散列值是hash,首先通过hash值找到对应的bucket rthp = &rt_hash_table[hash].chain; 然后对bucket进行一遍查询,这次查询的目的有两个:如果是超时的条目,则直接 删除;如果是与rt相同键值的条目,则删除并将rt插入头部返回。 while ((rth = *rthp) != NULL) { if (rt_is_expired(rth)) { // 超时的条目 *rthp = rth->u.dst.rt_next; rt_free (rth); continue; } if (compare_keys(&rth->fl, &rt->fl) && compare_netns (rth, rt)) { //重复的条目 *rthp = rth->u.dst.rt_next; rcu_assign_pointer(rth->u.dst.rt_next, rt_hash_table[hash].chain); rcu_assign_pointer(rt_hash_table[hash].chain, rth); …… } …… rthp = &rth->u.dst.rt_next; } 在扫描一遍后,如rt还未存在,则将其插入头部 rt ->u.dst.rt_next = rt_hash_table[hash].chain; rcu_assign_pointer(rt_hash_table[hash].chain, rt); 如果新插入rt满足一定条件,还要与ARP邻居表进行绑定 Hint:缓存的每个bucket是没有头结点的,单向链表,它所使用 的插入和删除操作是值得学习的,简单实用。 路由缓存删除条目 rt_del() 要删除的条目是rt,相应散列 值是hash,首先通过hash值找到对应的bucket,然后遍历,如果条目超时,或找到rt,则删除它。 rthp = &rt_hash_table[hash].chain; spin_lock_bh(rt_hash_lock_addr(hash)); ip_rt_put(rt); while ((aux = *rthp) != NULL) { if (aux == rt || rt_is_expired(aux)) { *rthp = aux- >u.dst.rt_next; rt_free(aux); continue; } rthp = &aux->u.dst.rt_next; } spin_unlock_bh(rt_hash_lock_addr(hash)); 路由表的创建 inet_init() -> ip_init() -> ip_fib_init() -> fib_net_init() -> ip_fib_net_init()[net/ipv4/fib_frontend.c] 首先为路由表分配空间, 这里的每个表项hlist_head实际都会链接一个单独的路由表,FIB_TABLE_HASHSZ表示了分配多少个路由表,一般情况下至少有两 个– LOCAL和MAIN。注意这里仅仅是表头的空间分配,还没有真正分配路由表空间。 net->ipv4.fib_table_hash = kzalloc( sizeof(struct hlist_head)*FIB_TABLE_HASHSZ, GFP_KERNEL); ip_fib_net_init() -> fib4_rules_init(),这里真正分配了路由表空间 local_table = fib_hash_table(RT_TABLE_LOCAL); main_table = fib_hash_table(RT_TABLE_MAIN); 然后将local和main表链入之前的fib_table_hash中 hlist_add_head_rcu (&local_table->tb_hlist, &net->ipv4.fib_table_hash [TABLE_LOCAL_INDEX]); hlist_add_head_rcu(&main_table->tb_hlist, &net- >ipv4.fib_table_hash[TABLE_MAIN_INDEX]); 最终生成结构如图,LOCAL表位于fib_table_hash[0],MAIN表位于 fib_table_hash[1];两张表通过结构tb_hlist链入链表,而tb_id则标识了功能,255是LOCAL表,254是MAIN表。 关于这 里的struct fn_hash,它表示了不同子网掩码长度的hash表[即fn_zone],对于ipv4,从0~32共33个。而fn_hash的实现则是 fib_table的最后一个参数unsigned char tb_data[0]。 (编辑:应用网_丽江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |