aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-06-24 18:25:00 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-01 20:30:43 -0400
commit957c665f37007de93ccbe45902a23143724170d0 (patch)
treed49f13d5b34ed1b1fc34828cbcd60afdbc9c4e5b
parent11d53b4990226247a950e2b1ccfa4cf93bfbc822 (diff)
ipv6: Don't put artificial limit on routing table size.
IPV6, unlike IPV4, doesn't have a routing cache. Routing table entries, as well as clones made in response to route lookup requests, all live in the same table. And all of these things are together collected in the destination cache table for ipv6. This means that routing table entries count against the garbage collection limits, even though such entries cannot ever be reclaimed and are added explicitly by the administrator (rather than being created in response to lookups). Therefore it makes no sense to count ipv6 routing table entries against the GC limits. Add a DST_NOCOUNT destination cache entry flag, and skip the counting if it is set. Use this flag bit in ipv6 when adding routing table entries. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/dst.h1
-rw-r--r--net/core/dst.c6
-rw-r--r--net/ipv6/route.c13
3 files changed, 12 insertions, 8 deletions
diff --git a/include/net/dst.h b/include/net/dst.h
index 7d15d238b6ec..e12ddfb9eb16 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -77,6 +77,7 @@ struct dst_entry {
77#define DST_NOPOLICY 0x0004 77#define DST_NOPOLICY 0x0004
78#define DST_NOHASH 0x0008 78#define DST_NOHASH 0x0008
79#define DST_NOCACHE 0x0010 79#define DST_NOCACHE 0x0010
80#define DST_NOCOUNT 0x0020
80 union { 81 union {
81 struct dst_entry *next; 82 struct dst_entry *next;
82 struct rtable __rcu *rt_next; 83 struct rtable __rcu *rt_next;
diff --git a/net/core/dst.c b/net/core/dst.c
index 9ccca038444f..6135f3671692 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -190,7 +190,8 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
190 dst->lastuse = jiffies; 190 dst->lastuse = jiffies;
191 dst->flags = flags; 191 dst->flags = flags;
192 dst->next = NULL; 192 dst->next = NULL;
193 dst_entries_add(ops, 1); 193 if (!(flags & DST_NOCOUNT))
194 dst_entries_add(ops, 1);
194 return dst; 195 return dst;
195} 196}
196EXPORT_SYMBOL(dst_alloc); 197EXPORT_SYMBOL(dst_alloc);
@@ -243,7 +244,8 @@ again:
243 neigh_release(neigh); 244 neigh_release(neigh);
244 } 245 }
245 246
246 dst_entries_add(dst->ops, -1); 247 if (!(dst->flags & DST_NOCOUNT))
248 dst_entries_add(dst->ops, -1);
247 249
248 if (dst->ops->destroy) 250 if (dst->ops->destroy)
249 dst->ops->destroy(dst); 251 dst->ops->destroy(dst);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c2af4da074b0..0ef1f086feb8 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -228,9 +228,10 @@ static struct rt6_info ip6_blk_hole_entry_template = {
228 228
229/* allocate dst with ip6_dst_ops */ 229/* allocate dst with ip6_dst_ops */
230static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, 230static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops,
231 struct net_device *dev) 231 struct net_device *dev,
232 int flags)
232{ 233{
233 struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, 0); 234 struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags);
234 235
235 memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); 236 memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry));
236 237
@@ -1042,7 +1043,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
1042 if (unlikely(idev == NULL)) 1043 if (unlikely(idev == NULL))
1043 return NULL; 1044 return NULL;
1044 1045
1045 rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev); 1046 rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0);
1046 if (unlikely(rt == NULL)) { 1047 if (unlikely(rt == NULL)) {
1047 in6_dev_put(idev); 1048 in6_dev_put(idev);
1048 goto out; 1049 goto out;
@@ -1206,7 +1207,7 @@ int ip6_route_add(struct fib6_config *cfg)
1206 goto out; 1207 goto out;
1207 } 1208 }
1208 1209
1209 rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL); 1210 rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL, DST_NOCOUNT);
1210 1211
1211 if (rt == NULL) { 1212 if (rt == NULL) {
1212 err = -ENOMEM; 1213 err = -ENOMEM;
@@ -1726,7 +1727,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1726{ 1727{
1727 struct net *net = dev_net(ort->rt6i_dev); 1728 struct net *net = dev_net(ort->rt6i_dev);
1728 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, 1729 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops,
1729 ort->dst.dev); 1730 ort->dst.dev, 0);
1730 1731
1731 if (rt) { 1732 if (rt) {
1732 rt->dst.input = ort->dst.input; 1733 rt->dst.input = ort->dst.input;
@@ -2005,7 +2006,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
2005{ 2006{
2006 struct net *net = dev_net(idev->dev); 2007 struct net *net = dev_net(idev->dev);
2007 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, 2008 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops,
2008 net->loopback_dev); 2009 net->loopback_dev, 0);
2009 struct neighbour *neigh; 2010 struct neighbour *neigh;
2010 2011
2011 if (rt == NULL) { 2012 if (rt == NULL) {