ip6_fib.c (c757faa8bfa26a0dd24b41ff783e0da042156887) ip6_fib.c (38fbeeeeccdb38d0635398e8e344d245f6d8dc52)
1/*
2 * Linux INET6 implementation
3 * Forwarding Information Database
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 1329 unchanged lines hidden (view full) ---

1338 fn = root;
1339
1340 return fn;
1341}
1342
1343/*
1344 * Get node with specified destination prefix (and source prefix,
1345 * if subtrees are used)
1/*
2 * Linux INET6 implementation
3 * Forwarding Information Database
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 1329 unchanged lines hidden (view full) ---

1338 fn = root;
1339
1340 return fn;
1341}
1342
1343/*
1344 * Get node with specified destination prefix (and source prefix,
1345 * if subtrees are used)
1346 * exact_match == true means we try to find fn with exact match of
1347 * the passed in prefix addr
1348 * exact_match == false means we try to find fn with longest prefix
1349 * match of the passed in prefix addr. This is useful for finding fn
1350 * for cached route as it will be stored in the exception table under
1351 * the node with longest prefix length.
1346 */
1347
1348
1349static struct fib6_node *fib6_locate_1(struct fib6_node *root,
1350 const struct in6_addr *addr,
1352 */
1353
1354
1355static struct fib6_node *fib6_locate_1(struct fib6_node *root,
1356 const struct in6_addr *addr,
1351 int plen, int offset)
1357 int plen, int offset,
1358 bool exact_match)
1352{
1359{
1353 struct fib6_node *fn;
1360 struct fib6_node *fn, *prev = NULL;
1354
1355 for (fn = root; fn ; ) {
1356 struct rt6key *key = (struct rt6key *)((u8 *)fn->leaf + offset);
1357
1358 /*
1359 * Prefix match
1360 */
1361 if (plen < fn->fn_bit ||
1362 !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
1361
1362 for (fn = root; fn ; ) {
1363 struct rt6key *key = (struct rt6key *)((u8 *)fn->leaf + offset);
1364
1365 /*
1366 * Prefix match
1367 */
1368 if (plen < fn->fn_bit ||
1369 !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
1363 return NULL;
1370 goto out;
1364
1365 if (plen == fn->fn_bit)
1366 return fn;
1367
1371
1372 if (plen == fn->fn_bit)
1373 return fn;
1374
1375 prev = fn;
1376
1368 /*
1369 * We have more bits to go
1370 */
1371 if (addr_bit_set(addr, fn->fn_bit))
1372 fn = fn->right;
1373 else
1374 fn = fn->left;
1375 }
1377 /*
1378 * We have more bits to go
1379 */
1380 if (addr_bit_set(addr, fn->fn_bit))
1381 fn = fn->right;
1382 else
1383 fn = fn->left;
1384 }
1376 return NULL;
1385out:
1386 if (exact_match)
1387 return NULL;
1388 else
1389 return prev;
1377}
1378
1379struct fib6_node *fib6_locate(struct fib6_node *root,
1380 const struct in6_addr *daddr, int dst_len,
1390}
1391
1392struct fib6_node *fib6_locate(struct fib6_node *root,
1393 const struct in6_addr *daddr, int dst_len,
1381 const struct in6_addr *saddr, int src_len)
1394 const struct in6_addr *saddr, int src_len,
1395 bool exact_match)
1382{
1383 struct fib6_node *fn;
1384
1385 fn = fib6_locate_1(root, daddr, dst_len,
1396{
1397 struct fib6_node *fn;
1398
1399 fn = fib6_locate_1(root, daddr, dst_len,
1386 offsetof(struct rt6_info, rt6i_dst));
1400 offsetof(struct rt6_info, rt6i_dst),
1401 exact_match);
1387
1388#ifdef CONFIG_IPV6_SUBTREES
1389 if (src_len) {
1390 WARN_ON(saddr == NULL);
1391 if (fn && fn->subtree)
1392 fn = fib6_locate_1(fn->subtree, saddr, src_len,
1402
1403#ifdef CONFIG_IPV6_SUBTREES
1404 if (src_len) {
1405 WARN_ON(saddr == NULL);
1406 if (fn && fn->subtree)
1407 fn = fib6_locate_1(fn->subtree, saddr, src_len,
1393 offsetof(struct rt6_info, rt6i_src));
1408 offsetof(struct rt6_info, rt6i_src),
1409 exact_match);
1394 }
1395#endif
1396
1397 if (fn && fn->fn_flags & RTN_RTINFO)
1398 return fn;
1399
1400 return NULL;
1401}

--- 885 unchanged lines hidden ---
1410 }
1411#endif
1412
1413 if (fn && fn->fn_flags & RTN_RTINFO)
1414 return fn;
1415
1416 return NULL;
1417}

--- 885 unchanged lines hidden ---