ipv4路由查找
fib_table_lookup
可以参考:https://blog.csdn.net/shichaog/article/details/44658205
1405 int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, 1406 struct fib_result *res, int fib_flags) 1407 { 1408 struct trie *t = (struct trie *) tb->tb_data; 1409 int ret; 1410 struct rt_trie_node *n; 1411 struct tnode *pn; 1412 unsigned int pos, bits; 1413 t_key key = ntohl(flp->daddr); 1414 unsigned int chopped_off; 1415 t_key cindex = 0; 1416 unsigned int current_prefix_length = KEYLENGTH; 1417 struct tnode *cn; 1418 t_key pref_mismatch; 1419 1420 rcu_read_lock(); 1421 1422 n = rcu_dereference(t->trie); 1423 if (!n) 1424 goto failed; //首先查看fib_table指向的是否仅仅是leaf,而没有tnode,对于fib_table只有一个leaf的情况下,直接调用check_leaf进行 //验证 1430 /* Just a leaf? */ 1431 if (IS_LEAF(n)) { 1432 ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags); 1433 goto found; 1434 } //对于是tnode的情况的处理 1436 pn = (struct tnode *) n; //该变量用于记录已经匹配到的比特数。 1437 chopped_off = 0; 1438 1439 while (pn) { 1440 pos = pn->pos; 1441 bits = pn->bits; 1443 if (!chopped_off) //找到不同的bit,这是为了获得孩子节点。 1444 cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length), 1445 pos, bits); //获得孩子节点,这个孩子节点可能是tnode也可能是leaf 1447 n = tnode_get_child_rcu(pn, cindex); // 1449 if (n == NULL) { 1453 goto backtrace; 1454 } //如果孩子节点是一个leaf节点,则调用check_leaf检查是否是需要的路由项,并将结果存放在res中。 1456 if (IS_LEAF(n)) { 1457 ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags); 1458 if (ret > 0) 1459 goto backtrace; 1460 goto found; 1461 } //如果孩子节点是一个tnode,则需要进行迭代到其孩子进行上述查找过程。 1463 cn = (struct tnode *)n; //第一次进入该函数这里的current_prefix_length的长度是不会小于pos+bits的。 1494 if (current_prefix_length < pos+bits) { 1495 if (tkey_extract_bits(cn->key, current_prefix_length, 1496 cn->pos - current_prefix_length) 1497 || !(cn->child[0])) 1498 goto backtrace; 1499 } 1532 1533 pref_mismatch = mask_pfx(cn->key ^ key, cn->pos); //当根据pos和bits值没有找到搜索的key的话,进入前缀匹配模式。 /************************************************************************************************ ***该模式存在意义如下: ***对于ipv4路由表有如下两项: ***192.168.20.16/28 ***192.168.0.0/16 ***如果需要查找192.168.20.19则上面两个都是匹配的,但是取哪个好呢?内核使用最常匹配原则,即认为192.168.20.16 ***(子网掩码长度是28)这一项是匹配的,通常default 项的前缀是最短的,其作用是在其他路由项均不能匹配时会使用***default项*[摘自维基百科,longest prefix match],这个函数的chopped_off就是忽略prefix的长度,这样匹配成功的概率会***变大。对于图12.2.4的情况的trie树,查找192.168.0.100路由项的情况是不会进入backtrace标号开始的语句的。 **********************************************************************************************/ 1540 if (pref_mismatch) { 1541 /* fls(x) = __fls(x) + 1 */ 1542 int mp = KEYLENGTH - __fls(pref_mismatch) - 1; 1543 1544 if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0) 1545 goto backtrace; 1546 1547 if (current_prefix_length >= cn->pos) 1548 current_prefix_length = mp; 1549 } 1550 1551 pn = (struct tnode *)n; /* Descend */ 1552 chopped_off = 0; 1553 continue; 1554 1555 backtrace: 1556 chopped_off++; 1557 1558 /* As zero don't change the child key (cindex) */ 1559 while ((chopped_off <= pn->bits) 1560 && !(cindex & (1<<(chopped_off-1)))) 1561 chopped_off++; 1562 1563 /* Decrease current_... with bits chopped off */ 1564 if (current_prefix_length > pn->pos + pn->bits - chopped_off) 1565 current_prefix_length = pn->pos + pn->bits 1566 - chopped_off; 1567 1568 /* 1569 * Either we do the actual chop off according or if we have 1570 * chopped off all bits in this tnode walk up to our parent. 1571 */ 1572 1573 if (chopped_off <= pn->bits) { 1574 cindex &= ~(1 << (chopped_off-1)); 1575 } else { 1576 struct tnode *parent = node_parent_rcu((struct rt_trie_node *) pn); 1577 if (!parent) 1578 goto failed; 1579 1580 /* Get Child's index */ 1581 cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits); 1582 pn = parent; 1583 chopped_off = 0; 1593 found: 1594 rcu_read_unlock(); 1595 return ret; 1596 }
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子

浙公网安备 33010602011771号