summaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_semantics.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-07 20:54:48 -0800
committerDavid S. Miller <davem@davemloft.net>2011-03-07 20:54:48 -0800
commit1fc050a13473348f5c439de2bb41c8e92dba5588 (patch)
treeb2cecf15f5de87997fb44b4a1025b48d473cd038 /net/ipv4/fib_semantics.c
parent6118e35a7126c1062b1a0f6737b84b4fe4d5c8d4 (diff)
downloadlinux-1fc050a13473348f5c439de2bb41c8e92dba5588.tar.bz2
ipv4: Cache source address in nexthop entries.
When doing output route lookups, we have to select the source address if the user has not specified an explicit one. First, if the route has an explicit preferred source address specified, then we use that. Otherwise we search the route's outgoing interface for a suitable address. This search can be precomputed and cached at route insertion time. The only missing part is that we have to refresh this precomputed value any time addresses are added or removed from the interface, and this is accomplished by fib_update_nh_saddrs(). Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r--net/ipv4/fib_semantics.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 6349a21692ec..952c737f2a27 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -853,6 +853,12 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
goto err_inval;
}
+ change_nexthops(fi) {
+ nexthop_nh->nh_saddr = inet_select_addr(nexthop_nh->nh_dev,
+ nexthop_nh->nh_gw,
+ nexthop_nh->nh_scope);
+ } endfor_nexthops(fi)
+
link_it:
ofi = fib_find_info(fi);
if (ofi) {
@@ -898,13 +904,6 @@ failure:
return ERR_PTR(err);
}
-/* Find appropriate source address to this destination */
-
-__be32 __fib_res_prefsrc(struct fib_result *res)
-{
- return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
-}
-
int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos,
struct fib_info *fi, unsigned int flags)
@@ -1128,6 +1127,24 @@ out:
return;
}
+void fib_update_nh_saddrs(struct net_device *dev)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct fib_nh *nh;
+ unsigned int hash;
+
+ hash = fib_devindex_hashfn(dev->ifindex);
+ head = &fib_info_devhash[hash];
+ hlist_for_each_entry(nh, node, head, nh_hash) {
+ if (nh->nh_dev != dev)
+ continue;
+ nh->nh_saddr = inet_select_addr(nh->nh_dev,
+ nh->nh_gw,
+ nh->nh_scope);
+ }
+}
+
#ifdef CONFIG_IP_ROUTE_MULTIPATH
/*