aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-07-06 01:13:13 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-06 01:13:13 -0400
commitf4530fa574df4d833506c53697ed1daa0d390bf4 (patch)
tree2a19ff4c8410d5aee18a78cddaeb765ed9aa95d6 /net
parent700db99d0140e9da2a31e08ebd3e1b121691aa26 (diff)
ipv4: Avoid overhead when no custom FIB rules are installed.
If the user hasn't actually installed any custom rules, or fiddled with the default ones, don't go through the whole FIB rules layer. It's just pure overhead. Instead do what we do with CONFIG_IP_MULTIPLE_TABLES disabled, check the individual tables by hand, one by one. Also, move fib_num_tclassid_users into the ipv4 network namespace. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/fib_frontend.c27
-rw-r--r--net/ipv4/fib_rules.c12
-rw-r--r--net/ipv4/fib_semantics.c6
3 files changed, 33 insertions, 12 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 3e11ea225dad..81f85716a894 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -86,6 +86,24 @@ struct fib_table *fib_new_table(struct net *net, u32 id)
86 tb = fib_trie_table(id); 86 tb = fib_trie_table(id);
87 if (!tb) 87 if (!tb)
88 return NULL; 88 return NULL;
89
90 switch (id) {
91 case RT_TABLE_LOCAL:
92 net->ipv4.fib_local = tb;
93 break;
94
95 case RT_TABLE_MAIN:
96 net->ipv4.fib_main = tb;
97 break;
98
99 case RT_TABLE_DEFAULT:
100 net->ipv4.fib_default = tb;
101 break;
102
103 default:
104 break;
105 }
106
89 h = id & (FIB_TABLE_HASHSZ - 1); 107 h = id & (FIB_TABLE_HASHSZ - 1);
90 hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]); 108 hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]);
91 return tb; 109 return tb;
@@ -218,10 +236,6 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
218 return inet_select_addr(dev, ip_hdr(skb)->saddr, scope); 236 return inet_select_addr(dev, ip_hdr(skb)->saddr, scope);
219} 237}
220 238
221#ifdef CONFIG_IP_ROUTE_CLASSID
222int fib_num_tclassid_users __read_mostly;
223#endif
224
225/* Given (packet source, input interface) and optional (dst, oif, tos): 239/* Given (packet source, input interface) and optional (dst, oif, tos):
226 * - (main) check, that source is valid i.e. not broadcast or our local 240 * - (main) check, that source is valid i.e. not broadcast or our local
227 * address. 241 * address.
@@ -312,7 +326,7 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
312{ 326{
313 int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev); 327 int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev);
314 328
315 if (!r && !fib_num_tclassid_users) { 329 if (!r && !fib_num_tclassid_users(dev_net(dev))) {
316 *itag = 0; 330 *itag = 0;
317 return 0; 331 return 0;
318 } 332 }
@@ -1134,6 +1148,9 @@ static int __net_init fib_net_init(struct net *net)
1134{ 1148{
1135 int error; 1149 int error;
1136 1150
1151#ifdef CONFIG_IP_ROUTE_CLASSID
1152 net->ipv4.fib_num_tclassid_users = 0;
1153#endif
1137 error = ip_fib_net_init(net); 1154 error = ip_fib_net_init(net);
1138 if (error < 0) 1155 if (error < 0)
1139 goto out; 1156 goto out;
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index b23fd952c84f..c06da93b0b70 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -54,7 +54,7 @@ u32 fib_rules_tclass(const struct fib_result *res)
54} 54}
55#endif 55#endif
56 56
57int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) 57int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res)
58{ 58{
59 struct fib_lookup_arg arg = { 59 struct fib_lookup_arg arg = {
60 .result = res, 60 .result = res,
@@ -67,7 +67,7 @@ int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res)
67 67
68 return err; 68 return err;
69} 69}
70EXPORT_SYMBOL_GPL(fib_lookup); 70EXPORT_SYMBOL_GPL(__fib_lookup);
71 71
72static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, 72static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
73 int flags, struct fib_lookup_arg *arg) 73 int flags, struct fib_lookup_arg *arg)
@@ -172,7 +172,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
172 if (tb[FRA_FLOW]) { 172 if (tb[FRA_FLOW]) {
173 rule4->tclassid = nla_get_u32(tb[FRA_FLOW]); 173 rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
174 if (rule4->tclassid) 174 if (rule4->tclassid)
175 fib_num_tclassid_users++; 175 net->ipv4.fib_num_tclassid_users++;
176 } 176 }
177#endif 177#endif
178 178
@@ -182,6 +182,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
182 rule4->dstmask = inet_make_mask(rule4->dst_len); 182 rule4->dstmask = inet_make_mask(rule4->dst_len);
183 rule4->tos = frh->tos; 183 rule4->tos = frh->tos;
184 184
185 net->ipv4.fib_has_custom_rules = true;
185 err = 0; 186 err = 0;
186errout: 187errout:
187 return err; 188 return err;
@@ -189,12 +190,14 @@ errout:
189 190
190static void fib4_rule_delete(struct fib_rule *rule) 191static void fib4_rule_delete(struct fib_rule *rule)
191{ 192{
193 struct net *net = rule->fr_net;
192#ifdef CONFIG_IP_ROUTE_CLASSID 194#ifdef CONFIG_IP_ROUTE_CLASSID
193 struct fib4_rule *rule4 = (struct fib4_rule *) rule; 195 struct fib4_rule *rule4 = (struct fib4_rule *) rule;
194 196
195 if (rule4->tclassid) 197 if (rule4->tclassid)
196 fib_num_tclassid_users--; 198 net->ipv4.fib_num_tclassid_users--;
197#endif 199#endif
200 net->ipv4.fib_has_custom_rules = true;
198} 201}
199 202
200static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, 203static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
@@ -309,6 +312,7 @@ int __net_init fib4_rules_init(struct net *net)
309 if (err < 0) 312 if (err < 0)
310 goto fail; 313 goto fail;
311 net->ipv4.rules_ops = ops; 314 net->ipv4.rules_ops = ops;
315 net->ipv4.fib_has_custom_rules = false;
312 return 0; 316 return 0;
313 317
314fail: 318fail:
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index c46c20b6b0b6..ae301c897a19 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -166,7 +166,7 @@ void free_fib_info(struct fib_info *fi)
166#ifdef CONFIG_IP_ROUTE_CLASSID 166#ifdef CONFIG_IP_ROUTE_CLASSID
167 change_nexthops(fi) { 167 change_nexthops(fi) {
168 if (nexthop_nh->nh_tclassid) 168 if (nexthop_nh->nh_tclassid)
169 fib_num_tclassid_users--; 169 fi->fib_net->ipv4.fib_num_tclassid_users--;
170 } endfor_nexthops(fi); 170 } endfor_nexthops(fi);
171#endif 171#endif
172 call_rcu(&fi->rcu, free_fib_info_rcu); 172 call_rcu(&fi->rcu, free_fib_info_rcu);
@@ -428,7 +428,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
428 nla = nla_find(attrs, attrlen, RTA_FLOW); 428 nla = nla_find(attrs, attrlen, RTA_FLOW);
429 nexthop_nh->nh_tclassid = nla ? nla_get_u32(nla) : 0; 429 nexthop_nh->nh_tclassid = nla ? nla_get_u32(nla) : 0;
430 if (nexthop_nh->nh_tclassid) 430 if (nexthop_nh->nh_tclassid)
431 fib_num_tclassid_users++; 431 fi->fib_net->ipv4.fib_num_tclassid_users++;
432#endif 432#endif
433 } 433 }
434 434
@@ -824,7 +824,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
824#ifdef CONFIG_IP_ROUTE_CLASSID 824#ifdef CONFIG_IP_ROUTE_CLASSID
825 nh->nh_tclassid = cfg->fc_flow; 825 nh->nh_tclassid = cfg->fc_flow;
826 if (nh->nh_tclassid) 826 if (nh->nh_tclassid)
827 fib_num_tclassid_users++; 827 fi->fib_net->ipv4.fib_num_tclassid_users++;
828#endif 828#endif
829#ifdef CONFIG_IP_ROUTE_MULTIPATH 829#ifdef CONFIG_IP_ROUTE_MULTIPATH
830 nh->nh_weight = 1; 830 nh->nh_weight = 1;