aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/net/ip_fib.h7
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/fib_semantics.c31
3 files changed, 31 insertions, 9 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 523a170b0ecb..0e140830b85a 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -60,6 +60,7 @@ struct fib_nh {
60#endif 60#endif
61 int nh_oif; 61 int nh_oif;
62 __be32 nh_gw; 62 __be32 nh_gw;
63 __be32 nh_saddr;
63}; 64};
64 65
65/* 66/*
@@ -139,11 +140,13 @@ struct fib_result_nl {
139 140
140#endif /* CONFIG_IP_ROUTE_MULTIPATH */ 141#endif /* CONFIG_IP_ROUTE_MULTIPATH */
141 142
142#define FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __fib_res_prefsrc(&res)) 143#define FIB_RES_SADDR(res) (FIB_RES_NH(res).nh_saddr)
143#define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw) 144#define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw)
144#define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev) 145#define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
145#define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif) 146#define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif)
146 147
148#define FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : FIB_RES_SADDR(res))
149
147struct fib_table { 150struct fib_table {
148 struct hlist_node tb_hlist; 151 struct hlist_node tb_hlist;
149 u32 tb_id; 152 u32 tb_id;
@@ -224,8 +227,8 @@ extern void fib_select_default(struct fib_result *res);
224extern int ip_fib_check_default(__be32 gw, struct net_device *dev); 227extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
225extern int fib_sync_down_dev(struct net_device *dev, int force); 228extern int fib_sync_down_dev(struct net_device *dev, int force);
226extern int fib_sync_down_addr(struct net *net, __be32 local); 229extern int fib_sync_down_addr(struct net *net, __be32 local);
230extern void fib_update_nh_saddrs(struct net_device *dev);
227extern int fib_sync_up(struct net_device *dev); 231extern int fib_sync_up(struct net_device *dev);
228extern __be32 __fib_res_prefsrc(struct fib_result *res);
229extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res); 232extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
230 233
231/* Exported by fib_trie.c */ 234/* Exported by fib_trie.c */
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/*