aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-07 23:54:48 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-07 23:54:48 -0500
commit1fc050a13473348f5c439de2bb41c8e92dba5588 (patch)
treeb2cecf15f5de87997fb44b4a1025b48d473cd038 /net/ipv4
parent6118e35a7126c1062b1a0f6737b84b4fe4d5c8d4 (diff)
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')
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/fib_semantics.c31
2 files changed, 26 insertions, 7 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index ad0778a3fa53..1d2233cd99e6 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -890,10 +890,12 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
890#ifdef CONFIG_IP_ROUTE_MULTIPATH 890#ifdef CONFIG_IP_ROUTE_MULTIPATH
891 fib_sync_up(dev); 891 fib_sync_up(dev);
892#endif 892#endif
893 fib_update_nh_saddrs(dev);
893 rt_cache_flush(dev_net(dev), -1); 894 rt_cache_flush(dev_net(dev), -1);
894 break; 895 break;
895 case NETDEV_DOWN: 896 case NETDEV_DOWN:
896 fib_del_ifaddr(ifa); 897 fib_del_ifaddr(ifa);
898 fib_update_nh_saddrs(dev);
897 if (ifa->ifa_dev->ifa_list == NULL) { 899 if (ifa->ifa_dev->ifa_list == NULL) {
898 /* Last address was deleted from this interface. 900 /* Last address was deleted from this interface.
899 * Disable IP. 901 * Disable IP.
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)
853 goto err_inval; 853 goto err_inval;
854 } 854 }
855 855
856 change_nexthops(fi) {
857 nexthop_nh->nh_saddr = inet_select_addr(nexthop_nh->nh_dev,
858 nexthop_nh->nh_gw,
859 nexthop_nh->nh_scope);
860 } endfor_nexthops(fi)
861
856link_it: 862link_it:
857 ofi = fib_find_info(fi); 863 ofi = fib_find_info(fi);
858 if (ofi) { 864 if (ofi) {
@@ -898,13 +904,6 @@ failure:
898 return ERR_PTR(err); 904 return ERR_PTR(err);
899} 905}
900 906
901/* Find appropriate source address to this destination */
902
903__be32 __fib_res_prefsrc(struct fib_result *res)
904{
905 return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
906}
907
908int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 907int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
909 u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos, 908 u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos,
910 struct fib_info *fi, unsigned int flags) 909 struct fib_info *fi, unsigned int flags)
@@ -1128,6 +1127,24 @@ out:
1128 return; 1127 return;
1129} 1128}
1130 1129
1130void fib_update_nh_saddrs(struct net_device *dev)
1131{
1132 struct hlist_head *head;
1133 struct hlist_node *node;
1134 struct fib_nh *nh;
1135 unsigned int hash;
1136
1137 hash = fib_devindex_hashfn(dev->ifindex);
1138 head = &fib_info_devhash[hash];
1139 hlist_for_each_entry(nh, node, head, nh_hash) {
1140 if (nh->nh_dev != dev)
1141 continue;
1142 nh->nh_saddr = inet_select_addr(nh->nh_dev,
1143 nh->nh_gw,
1144 nh->nh_scope);
1145 }
1146}
1147
1131#ifdef CONFIG_IP_ROUTE_MULTIPATH 1148#ifdef CONFIG_IP_ROUTE_MULTIPATH
1132 1149
1133/* 1150/*