0
点赞
收藏
分享

微信扫一扫

IPv6路由节点查找

  路由表查找函数首先调用fib6_node_lookup查找路由节点,由指定路由表的根节点开始,根据数据流的目的和源地址进行。

static struct fib6_node *fib6_lookup_1(struct fib6_node *root,
struct lookup_args *args)
{
struct fib6_node *fn;
__be32 dir;

if (unlikely(args->offset == 0))
return NULL;

/*
* Descend on a tree

以下遍历由根节点开始,如果遍历节点的前缀长度,在所查找地址中对应的位为1,向右子树继续查找,
如果为零,向左子树继续查找。一直到节点为空为止。
*/

fn = root;

for (;;) {
struct fib6_node *next;

dir = addr_bit_set(args->addr, fn->fn_bit);

next = dir ? fn->right : fn->left;

if (next) {
fn = next;
continue;
}
break;
}
/*
如果以上找到了匹配的节点,检查此节点是否具有合法的路由信息(RTN_RTINFO),并且其叶子节点存在,按照叶子节点中保存的地址和前缀长度,
与待查找地址进行比较(ipv6_prefix_equal),如果相等,即为要找的路由节点。
*/
while (fn) {
if (FIB6_SUBTREE(fn) || fn->fn_flags & RTN_RTINFO) {
struct rt6key *key;

key = (struct rt6key *) ((u8 *) fn->leaf +
args->offset);

if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
#ifdef CONFIG_IPV6_SUBTREES
/* 否则,检查节点树的父节点,向树根方向(backtrack),此方向节点的前缀长度(fn_bit)在减小。此函数遵循LPM最长匹配算法,
如果存在最长匹配的路由节点,优先选择。
*/ if (fn->subtree) {
struct fib6_node *sfn;
sfn = fib6_lookup_1(fn->subtree,
args + 1);
if (!sfn)
goto backtrack;
fn = sfn;
}
#endif
if (fn->fn_flags & RTN_RTINFO)
return fn;
}
}
#ifdef CONFIG_IPV6_SUBTREES
backtrack:
#endif
if (fn->fn_flags & RTN_ROOT)
break;

fn = fn->parent;
}

return NULL;
}
static __be32 addr_bit_set(const void *token, int fn_bit)
{//t确定地址中的第fn_bit位的值

const __be32 *addr = token;
/*
* Here,
* 1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)
* is optimized version of
* htonl(1 << ((~fn_bit)&0x1F))
* See include/asm-generic/bitops/le.h.
首先将IPv6地址分成4个32位的数组,由运算[fn_bit>>5]确定数组的索引值;
其次,确定fn_bit在此32位中的具体位置,此值不能大于32(由0x1f与操作保证),
由于fn_bit是由高位向低位表示的,需要取反操作将此顺序反过来。
*/
return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) &
addr[fn_bit >> 5];
}

 

http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子

举报

相关推荐

0 条评论