1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
| 1397 int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, 1398 struct fib_result *res, int fib_flags) 1399 { 1400 struct trie *t = (struct trie *) tb->tb_data; 1401 int ret; 1402 struct rt_trie_node *n; 1403 struct tnode *pn; 1404 unsigned int pos, bits; 1405 t_key key = ntohl(flp->daddr); 1406 unsigned int chopped_off; 1407 t_key cindex = 0; 1408 unsigned int current_prefix_length = KEYLENGTH; 1409 struct tnode *cn; 1410 t_key pref_mismatch; 1411 1412 rcu_read_lock(); 1413 1414 n = rcu_dereference(t->trie); 1415 if (!n) 1416 goto failed; 1417 1418 #ifdef CONFIG_IP_FIB_TRIE_STATS 1419 t->stats.gets++; 1420 #endif 1421 1422 1423 if (IS_LEAF(n)) { 1424 ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags); 1425 goto found; 1426 } 1427 1428 pn = (struct tnode *) n; 1429 chopped_off = 0; 1430 1431 while (pn) { 1432 pos = pn->pos; 1433 bits = pn->bits; 1434 1435 if (!chopped_off) 1436 cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length), 1437 pos, bits); 1438 1439 n = tnode_get_child_rcu(pn, cindex); 1440 1441 if (n == NULL) { 1442 #ifdef CONFIG_IP_FIB_TRIE_STATS 1443 t->stats.null_node_hit++; 1444 #endif 1445 goto backtrace; 1446 } 1447 1448 if (IS_LEAF(n)) { 1449 ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags); 1450 if (ret > 0) 1451 goto backtrace; 1452 goto found; 1453 } 1454 1455 cn = (struct tnode *)n; 1456 1457
1472 1473
1482 1483
1485 1486 if (current_prefix_length < pos+bits) { 1487 if (tkey_extract_bits(cn->key, current_prefix_length, 1488 cn->pos - current_prefix_length) 1489 || !(cn->child[0])) 1490 goto backtrace; 1491 } 1492 1493
1502 1503
1511 1512
1524 1525 pref_mismatch = mask_pfx(cn->key ^ key, cn->pos); 1526 1527
1532 if (pref_mismatch) { 1533 1534 int mp = KEYLENGTH - __fls(pref_mismatch) - 1; 1535 1536 if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0) 1537 goto backtrace; 1538 1539 if (current_prefix_length >= cn->pos) 1540 current_prefix_length = mp; 1541 } 1542 1543 pn = (struct tnode *)n; 1544 chopped_off = 0; 1545 continue; 1546 1547 backtrace: 1548 chopped_off++; 1549 1550 1551 while ((chopped_off <= pn->bits) 1552 && !(cindex & (1<<(chopped_off-1)))) 1553 chopped_off++; 1554 1555 1556 if (current_prefix_length > pn->pos + pn->bits - chopped_off) 1557 current_prefix_length = pn->pos + pn->bits 1558 - chopped_off; 1559 1560
1564 1565 if (chopped_off <= pn->bits) { 1566 cindex &= ~(1 << (chopped_off-1)); 1567 } else { 1568 struct tnode *parent = node_parent_rcu((struct rt_trie_node *) pn); 1569 if (!parent) 1570 goto failed; 1571 1572 1573 cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits); 1574 pn = parent; 1575 chopped_off = 0; 1576 1577 #ifdef CONFIG_IP_FIB_TRIE_STATS 1578 t->stats.backtrack++; 1579 #endif 1580 goto backtrace; 1581 } 1582 } 1583 failed: 1584 ret = 1; 1585 found: 1586 rcu_read_unlock(); 1587 return ret; 1588 } 1589 EXPORT_SYMBOL_GPL(fib_table_lookup);
|