diff options
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r-- | net/ipv4/fib_trie.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index edf3b0997e01..a4109a544778 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1349,23 +1349,58 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, | |||
1349 | struct hlist_node *node; | 1349 | struct hlist_node *node; |
1350 | 1350 | ||
1351 | hlist_for_each_entry_rcu(li, node, hhead, hlist) { | 1351 | hlist_for_each_entry_rcu(li, node, hhead, hlist) { |
1352 | int err; | 1352 | struct fib_alias *fa; |
1353 | int plen = li->plen; | 1353 | int plen = li->plen; |
1354 | __be32 mask = inet_make_mask(plen); | 1354 | __be32 mask = inet_make_mask(plen); |
1355 | 1355 | ||
1356 | if (l->key != (key & ntohl(mask))) | 1356 | if (l->key != (key & ntohl(mask))) |
1357 | continue; | 1357 | continue; |
1358 | 1358 | ||
1359 | err = fib_semantic_match(tb, &li->falh, flp, res, plen, fib_flags); | 1359 | list_for_each_entry_rcu(fa, &li->falh, fa_list) { |
1360 | struct fib_info *fi = fa->fa_info; | ||
1361 | int nhsel, err; | ||
1360 | 1362 | ||
1363 | if (fa->fa_tos && fa->fa_tos != flp->fl4_tos) | ||
1364 | continue; | ||
1365 | if (fa->fa_scope < flp->fl4_scope) | ||
1366 | continue; | ||
1367 | fib_alias_accessed(fa); | ||
1368 | err = fib_props[fa->fa_type].error; | ||
1369 | if (err) { | ||
1361 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 1370 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
1362 | if (err <= 0) | 1371 | t->stats.semantic_match_miss++; |
1363 | t->stats.semantic_match_passed++; | 1372 | #endif |
1364 | else | 1373 | return 1; |
1365 | t->stats.semantic_match_miss++; | 1374 | } |
1375 | if (fi->fib_flags & RTNH_F_DEAD) | ||
1376 | continue; | ||
1377 | for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) { | ||
1378 | const struct fib_nh *nh = &fi->fib_nh[nhsel]; | ||
1379 | |||
1380 | if (nh->nh_flags & RTNH_F_DEAD) | ||
1381 | continue; | ||
1382 | if (flp->oif && flp->oif != nh->nh_oif) | ||
1383 | continue; | ||
1384 | |||
1385 | #ifdef CONFIG_IP_FIB_TRIE_STATS | ||
1386 | t->stats.semantic_match_passed++; | ||
1387 | #endif | ||
1388 | res->prefixlen = plen; | ||
1389 | res->nh_sel = nhsel; | ||
1390 | res->type = fa->fa_type; | ||
1391 | res->scope = fa->fa_scope; | ||
1392 | res->fi = fi; | ||
1393 | res->table = tb; | ||
1394 | res->fa_head = &li->falh; | ||
1395 | if (!(fib_flags & FIB_LOOKUP_NOREF)) | ||
1396 | atomic_inc(&res->fi->fib_clntref); | ||
1397 | return 0; | ||
1398 | } | ||
1399 | } | ||
1400 | |||
1401 | #ifdef CONFIG_IP_FIB_TRIE_STATS | ||
1402 | t->stats.semantic_match_miss++; | ||
1366 | #endif | 1403 | #endif |
1367 | if (err <= 0) | ||
1368 | return err; | ||
1369 | } | 1404 | } |
1370 | 1405 | ||
1371 | return 1; | 1406 | return 1; |