diff options
-rw-r--r-- | include/net/ip6_fib.h | 15 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 42 | ||||
-rw-r--r-- | net/ipv6/route.c | 16 |
3 files changed, 47 insertions, 26 deletions
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 0b438b9bcb10..10c913816032 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h | |||
@@ -297,12 +297,15 @@ struct fib6_walker { | |||
297 | }; | 297 | }; |
298 | 298 | ||
299 | struct rt6_statistics { | 299 | struct rt6_statistics { |
300 | __u32 fib_nodes; | 300 | __u32 fib_nodes; /* all fib6 nodes */ |
301 | __u32 fib_route_nodes; | 301 | __u32 fib_route_nodes; /* intermediate nodes */ |
302 | __u32 fib_rt_alloc; /* permanent routes */ | 302 | __u32 fib_rt_entries; /* rt entries in fib table */ |
303 | __u32 fib_rt_entries; /* rt entries in table */ | 303 | __u32 fib_rt_cache; /* cached rt entries in exception table */ |
304 | __u32 fib_rt_cache; /* cache routes */ | 304 | __u32 fib_discarded_routes; /* total number of routes delete */ |
305 | __u32 fib_discarded_routes; | 305 | |
306 | /* The following stats are not protected by any lock */ | ||
307 | atomic_t fib_rt_alloc; /* total number of routes alloced */ | ||
308 | atomic_t fib_rt_uncache; /* rt entries in uncached list */ | ||
306 | }; | 309 | }; |
307 | 310 | ||
308 | #define RTN_TL_ROOT 0x0001 | 311 | #define RTN_TL_ROOT 0x0001 |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 3f95908b39c3..52a29ba32928 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -149,18 +149,21 @@ static __be32 addr_bit_set(const void *token, int fn_bit) | |||
149 | addr[fn_bit >> 5]; | 149 | addr[fn_bit >> 5]; |
150 | } | 150 | } |
151 | 151 | ||
152 | static struct fib6_node *node_alloc(void) | 152 | static struct fib6_node *node_alloc(struct net *net) |
153 | { | 153 | { |
154 | struct fib6_node *fn; | 154 | struct fib6_node *fn; |
155 | 155 | ||
156 | fn = kmem_cache_zalloc(fib6_node_kmem, GFP_ATOMIC); | 156 | fn = kmem_cache_zalloc(fib6_node_kmem, GFP_ATOMIC); |
157 | if (fn) | ||
158 | net->ipv6.rt6_stats->fib_nodes++; | ||
157 | 159 | ||
158 | return fn; | 160 | return fn; |
159 | } | 161 | } |
160 | 162 | ||
161 | static void node_free_immediate(struct fib6_node *fn) | 163 | static void node_free_immediate(struct net *net, struct fib6_node *fn) |
162 | { | 164 | { |
163 | kmem_cache_free(fib6_node_kmem, fn); | 165 | kmem_cache_free(fib6_node_kmem, fn); |
166 | net->ipv6.rt6_stats->fib_nodes--; | ||
164 | } | 167 | } |
165 | 168 | ||
166 | static void node_free_rcu(struct rcu_head *head) | 169 | static void node_free_rcu(struct rcu_head *head) |
@@ -170,9 +173,10 @@ static void node_free_rcu(struct rcu_head *head) | |||
170 | kmem_cache_free(fib6_node_kmem, fn); | 173 | kmem_cache_free(fib6_node_kmem, fn); |
171 | } | 174 | } |
172 | 175 | ||
173 | static void node_free(struct fib6_node *fn) | 176 | static void node_free(struct net *net, struct fib6_node *fn) |
174 | { | 177 | { |
175 | call_rcu(&fn->rcu, node_free_rcu); | 178 | call_rcu(&fn->rcu, node_free_rcu); |
179 | net->ipv6.rt6_stats->fib_nodes--; | ||
176 | } | 180 | } |
177 | 181 | ||
178 | void rt6_free_pcpu(struct rt6_info *non_pcpu_rt) | 182 | void rt6_free_pcpu(struct rt6_info *non_pcpu_rt) |
@@ -583,7 +587,8 @@ out: | |||
583 | * node. | 587 | * node. |
584 | */ | 588 | */ |
585 | 589 | ||
586 | static struct fib6_node *fib6_add_1(struct fib6_table *table, | 590 | static struct fib6_node *fib6_add_1(struct net *net, |
591 | struct fib6_table *table, | ||
587 | struct fib6_node *root, | 592 | struct fib6_node *root, |
588 | struct in6_addr *addr, int plen, | 593 | struct in6_addr *addr, int plen, |
589 | int offset, int allow_create, | 594 | int offset, int allow_create, |
@@ -675,7 +680,7 @@ static struct fib6_node *fib6_add_1(struct fib6_table *table, | |||
675 | * Create new leaf node without children. | 680 | * Create new leaf node without children. |
676 | */ | 681 | */ |
677 | 682 | ||
678 | ln = node_alloc(); | 683 | ln = node_alloc(net); |
679 | 684 | ||
680 | if (!ln) | 685 | if (!ln) |
681 | return ERR_PTR(-ENOMEM); | 686 | return ERR_PTR(-ENOMEM); |
@@ -716,14 +721,14 @@ insert_above: | |||
716 | * (new leaf node)[ln] (old node)[fn] | 721 | * (new leaf node)[ln] (old node)[fn] |
717 | */ | 722 | */ |
718 | if (plen > bit) { | 723 | if (plen > bit) { |
719 | in = node_alloc(); | 724 | in = node_alloc(net); |
720 | ln = node_alloc(); | 725 | ln = node_alloc(net); |
721 | 726 | ||
722 | if (!in || !ln) { | 727 | if (!in || !ln) { |
723 | if (in) | 728 | if (in) |
724 | node_free_immediate(in); | 729 | node_free_immediate(net, in); |
725 | if (ln) | 730 | if (ln) |
726 | node_free_immediate(ln); | 731 | node_free_immediate(net, ln); |
727 | return ERR_PTR(-ENOMEM); | 732 | return ERR_PTR(-ENOMEM); |
728 | } | 733 | } |
729 | 734 | ||
@@ -768,7 +773,7 @@ insert_above: | |||
768 | * (old node)[fn] NULL | 773 | * (old node)[fn] NULL |
769 | */ | 774 | */ |
770 | 775 | ||
771 | ln = node_alloc(); | 776 | ln = node_alloc(net); |
772 | 777 | ||
773 | if (!ln) | 778 | if (!ln) |
774 | return ERR_PTR(-ENOMEM); | 779 | return ERR_PTR(-ENOMEM); |
@@ -1065,6 +1070,7 @@ add: | |||
1065 | fn->rr_ptr = NULL; | 1070 | fn->rr_ptr = NULL; |
1066 | rt6_release(iter); | 1071 | rt6_release(iter); |
1067 | nsiblings--; | 1072 | nsiblings--; |
1073 | info->nl_net->ipv6.rt6_stats->fib_rt_entries--; | ||
1068 | } else { | 1074 | } else { |
1069 | ins = &iter->dst.rt6_next; | 1075 | ins = &iter->dst.rt6_next; |
1070 | } | 1076 | } |
@@ -1140,7 +1146,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, | |||
1140 | if (!allow_create && !replace_required) | 1146 | if (!allow_create && !replace_required) |
1141 | pr_warn("RTM_NEWROUTE with no NLM_F_CREATE or NLM_F_REPLACE\n"); | 1147 | pr_warn("RTM_NEWROUTE with no NLM_F_CREATE or NLM_F_REPLACE\n"); |
1142 | 1148 | ||
1143 | fn = fib6_add_1(table, root, | 1149 | fn = fib6_add_1(info->nl_net, table, root, |
1144 | &rt->rt6i_dst.addr, rt->rt6i_dst.plen, | 1150 | &rt->rt6i_dst.addr, rt->rt6i_dst.plen, |
1145 | offsetof(struct rt6_info, rt6i_dst), allow_create, | 1151 | offsetof(struct rt6_info, rt6i_dst), allow_create, |
1146 | replace_required, extack); | 1152 | replace_required, extack); |
@@ -1170,7 +1176,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, | |||
1170 | */ | 1176 | */ |
1171 | 1177 | ||
1172 | /* Create subtree root node */ | 1178 | /* Create subtree root node */ |
1173 | sfn = node_alloc(); | 1179 | sfn = node_alloc(info->nl_net); |
1174 | if (!sfn) | 1180 | if (!sfn) |
1175 | goto failure; | 1181 | goto failure; |
1176 | 1182 | ||
@@ -1181,8 +1187,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, | |||
1181 | 1187 | ||
1182 | /* Now add the first leaf node to new subtree */ | 1188 | /* Now add the first leaf node to new subtree */ |
1183 | 1189 | ||
1184 | sn = fib6_add_1(table, sfn, &rt->rt6i_src.addr, | 1190 | sn = fib6_add_1(info->nl_net, table, sfn, |
1185 | rt->rt6i_src.plen, | 1191 | &rt->rt6i_src.addr, rt->rt6i_src.plen, |
1186 | offsetof(struct rt6_info, rt6i_src), | 1192 | offsetof(struct rt6_info, rt6i_src), |
1187 | allow_create, replace_required, extack); | 1193 | allow_create, replace_required, extack); |
1188 | 1194 | ||
@@ -1191,7 +1197,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, | |||
1191 | root, and then (in failure) stale node | 1197 | root, and then (in failure) stale node |
1192 | in main tree. | 1198 | in main tree. |
1193 | */ | 1199 | */ |
1194 | node_free_immediate(sfn); | 1200 | node_free_immediate(info->nl_net, sfn); |
1195 | err = PTR_ERR(sn); | 1201 | err = PTR_ERR(sn); |
1196 | goto failure; | 1202 | goto failure; |
1197 | } | 1203 | } |
@@ -1200,8 +1206,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, | |||
1200 | rcu_assign_pointer(sfn->parent, fn); | 1206 | rcu_assign_pointer(sfn->parent, fn); |
1201 | rcu_assign_pointer(fn->subtree, sfn); | 1207 | rcu_assign_pointer(fn->subtree, sfn); |
1202 | } else { | 1208 | } else { |
1203 | sn = fib6_add_1(table, FIB6_SUBTREE(fn), &rt->rt6i_src.addr, | 1209 | sn = fib6_add_1(info->nl_net, table, FIB6_SUBTREE(fn), |
1204 | rt->rt6i_src.plen, | 1210 | &rt->rt6i_src.addr, rt->rt6i_src.plen, |
1205 | offsetof(struct rt6_info, rt6i_src), | 1211 | offsetof(struct rt6_info, rt6i_src), |
1206 | allow_create, replace_required, extack); | 1212 | allow_create, replace_required, extack); |
1207 | 1213 | ||
@@ -1609,7 +1615,7 @@ static struct fib6_node *fib6_repair_tree(struct net *net, | |||
1609 | } | 1615 | } |
1610 | read_unlock(&net->ipv6.fib6_walker_lock); | 1616 | read_unlock(&net->ipv6.fib6_walker_lock); |
1611 | 1617 | ||
1612 | node_free(fn); | 1618 | node_free(net, fn); |
1613 | if (pn->fn_flags & RTN_RTINFO || FIB6_SUBTREE(pn)) | 1619 | if (pn->fn_flags & RTN_RTINFO || FIB6_SUBTREE(pn)) |
1614 | return pn; | 1620 | return pn; |
1615 | 1621 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index cf44d0994b1e..399d1bceec4a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -143,9 +143,11 @@ static void rt6_uncached_list_del(struct rt6_info *rt) | |||
143 | { | 143 | { |
144 | if (!list_empty(&rt->rt6i_uncached)) { | 144 | if (!list_empty(&rt->rt6i_uncached)) { |
145 | struct uncached_list *ul = rt->rt6i_uncached_list; | 145 | struct uncached_list *ul = rt->rt6i_uncached_list; |
146 | struct net *net = dev_net(rt->dst.dev); | ||
146 | 147 | ||
147 | spin_lock_bh(&ul->lock); | 148 | spin_lock_bh(&ul->lock); |
148 | list_del(&rt->rt6i_uncached); | 149 | list_del(&rt->rt6i_uncached); |
150 | atomic_dec(&net->ipv6.rt6_stats->fib_rt_uncache); | ||
149 | spin_unlock_bh(&ul->lock); | 151 | spin_unlock_bh(&ul->lock); |
150 | } | 152 | } |
151 | } | 153 | } |
@@ -359,8 +361,10 @@ static struct rt6_info *__ip6_dst_alloc(struct net *net, | |||
359 | struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, | 361 | struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, |
360 | 1, DST_OBSOLETE_FORCE_CHK, flags); | 362 | 1, DST_OBSOLETE_FORCE_CHK, flags); |
361 | 363 | ||
362 | if (rt) | 364 | if (rt) { |
363 | rt6_info_init(rt); | 365 | rt6_info_init(rt); |
366 | atomic_inc(&net->ipv6.rt6_stats->fib_rt_alloc); | ||
367 | } | ||
364 | 368 | ||
365 | return rt; | 369 | return rt; |
366 | } | 370 | } |
@@ -1156,6 +1160,8 @@ static DEFINE_SPINLOCK(rt6_exception_lock); | |||
1156 | static void rt6_remove_exception(struct rt6_exception_bucket *bucket, | 1160 | static void rt6_remove_exception(struct rt6_exception_bucket *bucket, |
1157 | struct rt6_exception *rt6_ex) | 1161 | struct rt6_exception *rt6_ex) |
1158 | { | 1162 | { |
1163 | struct net *net = dev_net(rt6_ex->rt6i->dst.dev); | ||
1164 | |||
1159 | if (!bucket || !rt6_ex) | 1165 | if (!bucket || !rt6_ex) |
1160 | return; | 1166 | return; |
1161 | rt6_ex->rt6i->rt6i_node = NULL; | 1167 | rt6_ex->rt6i->rt6i_node = NULL; |
@@ -1164,6 +1170,7 @@ static void rt6_remove_exception(struct rt6_exception_bucket *bucket, | |||
1164 | kfree_rcu(rt6_ex, rcu); | 1170 | kfree_rcu(rt6_ex, rcu); |
1165 | WARN_ON_ONCE(!bucket->depth); | 1171 | WARN_ON_ONCE(!bucket->depth); |
1166 | bucket->depth--; | 1172 | bucket->depth--; |
1173 | net->ipv6.rt6_stats->fib_rt_cache--; | ||
1167 | } | 1174 | } |
1168 | 1175 | ||
1169 | /* Remove oldest rt6_ex in bucket and free the memory | 1176 | /* Remove oldest rt6_ex in bucket and free the memory |
@@ -1270,6 +1277,7 @@ __rt6_find_exception_rcu(struct rt6_exception_bucket **bucket, | |||
1270 | static int rt6_insert_exception(struct rt6_info *nrt, | 1277 | static int rt6_insert_exception(struct rt6_info *nrt, |
1271 | struct rt6_info *ort) | 1278 | struct rt6_info *ort) |
1272 | { | 1279 | { |
1280 | struct net *net = dev_net(ort->dst.dev); | ||
1273 | struct rt6_exception_bucket *bucket; | 1281 | struct rt6_exception_bucket *bucket; |
1274 | struct in6_addr *src_key = NULL; | 1282 | struct in6_addr *src_key = NULL; |
1275 | struct rt6_exception *rt6_ex; | 1283 | struct rt6_exception *rt6_ex; |
@@ -1339,6 +1347,7 @@ static int rt6_insert_exception(struct rt6_info *nrt, | |||
1339 | nrt->rt6i_node = ort->rt6i_node; | 1347 | nrt->rt6i_node = ort->rt6i_node; |
1340 | hlist_add_head_rcu(&rt6_ex->hlist, &bucket->chain); | 1348 | hlist_add_head_rcu(&rt6_ex->hlist, &bucket->chain); |
1341 | bucket->depth++; | 1349 | bucket->depth++; |
1350 | net->ipv6.rt6_stats->fib_rt_cache++; | ||
1342 | 1351 | ||
1343 | if (bucket->depth > FIB6_MAX_DEPTH) | 1352 | if (bucket->depth > FIB6_MAX_DEPTH) |
1344 | rt6_exception_remove_oldest(bucket); | 1353 | rt6_exception_remove_oldest(bucket); |
@@ -1714,6 +1723,7 @@ redo_rt6_select: | |||
1714 | * No need for another dst_hold() | 1723 | * No need for another dst_hold() |
1715 | */ | 1724 | */ |
1716 | rt6_uncached_list_add(uncached_rt); | 1725 | rt6_uncached_list_add(uncached_rt); |
1726 | atomic_inc(&net->ipv6.rt6_stats->fib_rt_uncache); | ||
1717 | } else { | 1727 | } else { |
1718 | uncached_rt = net->ipv6.ip6_null_entry; | 1728 | uncached_rt = net->ipv6.ip6_null_entry; |
1719 | dst_hold(&uncached_rt->dst); | 1729 | dst_hold(&uncached_rt->dst); |
@@ -1894,6 +1904,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
1894 | DST_OBSOLETE_NONE, 0); | 1904 | DST_OBSOLETE_NONE, 0); |
1895 | if (rt) { | 1905 | if (rt) { |
1896 | rt6_info_init(rt); | 1906 | rt6_info_init(rt); |
1907 | atomic_inc(&net->ipv6.rt6_stats->fib_rt_alloc); | ||
1897 | 1908 | ||
1898 | new = &rt->dst; | 1909 | new = &rt->dst; |
1899 | new->__use = 1; | 1910 | new->__use = 1; |
@@ -2341,6 +2352,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
2341 | * do proper release of the net_device | 2352 | * do proper release of the net_device |
2342 | */ | 2353 | */ |
2343 | rt6_uncached_list_add(rt); | 2354 | rt6_uncached_list_add(rt); |
2355 | atomic_inc(&net->ipv6.rt6_stats->fib_rt_uncache); | ||
2344 | 2356 | ||
2345 | dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0); | 2357 | dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0); |
2346 | 2358 | ||
@@ -4422,7 +4434,7 @@ static int rt6_stats_seq_show(struct seq_file *seq, void *v) | |||
4422 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", | 4434 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", |
4423 | net->ipv6.rt6_stats->fib_nodes, | 4435 | net->ipv6.rt6_stats->fib_nodes, |
4424 | net->ipv6.rt6_stats->fib_route_nodes, | 4436 | net->ipv6.rt6_stats->fib_route_nodes, |
4425 | net->ipv6.rt6_stats->fib_rt_alloc, | 4437 | atomic_read(&net->ipv6.rt6_stats->fib_rt_alloc), |
4426 | net->ipv6.rt6_stats->fib_rt_entries, | 4438 | net->ipv6.rt6_stats->fib_rt_entries, |
4427 | net->ipv6.rt6_stats->fib_rt_cache, | 4439 | net->ipv6.rt6_stats->fib_rt_cache, |
4428 | dst_entries_get_slow(&net->ipv6.ip6_dst_ops), | 4440 | dst_entries_get_slow(&net->ipv6.ip6_dst_ops), |