diff options
-rw-r--r-- | include/net/ip_fib.h | 36 | ||||
-rw-r--r-- | include/net/netns/ipv4.h | 8 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 27 | ||||
-rw-r--r-- | net/ipv4/fib_rules.c | 12 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 6 |
5 files changed, 73 insertions, 16 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 3dc7c96bbeab..539c6721f810 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
@@ -220,11 +220,33 @@ extern void __net_exit fib4_rules_exit(struct net *net); | |||
220 | extern u32 fib_rules_tclass(const struct fib_result *res); | 220 | extern u32 fib_rules_tclass(const struct fib_result *res); |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | extern int fib_lookup(struct net *n, struct flowi4 *flp, struct fib_result *res); | ||
224 | |||
225 | extern struct fib_table *fib_new_table(struct net *net, u32 id); | 223 | extern struct fib_table *fib_new_table(struct net *net, u32 id); |
226 | extern struct fib_table *fib_get_table(struct net *net, u32 id); | 224 | extern struct fib_table *fib_get_table(struct net *net, u32 id); |
227 | 225 | ||
226 | extern int __fib_lookup(struct net *net, struct flowi4 *flp, | ||
227 | struct fib_result *res); | ||
228 | |||
229 | static inline int fib_lookup(struct net *net, struct flowi4 *flp, | ||
230 | struct fib_result *res) | ||
231 | { | ||
232 | if (!net->ipv4.fib_has_custom_rules) { | ||
233 | if (net->ipv4.fib_local && | ||
234 | !fib_table_lookup(net->ipv4.fib_local, flp, res, | ||
235 | FIB_LOOKUP_NOREF)) | ||
236 | return 0; | ||
237 | if (net->ipv4.fib_main && | ||
238 | !fib_table_lookup(net->ipv4.fib_main, flp, res, | ||
239 | FIB_LOOKUP_NOREF)) | ||
240 | return 0; | ||
241 | if (net->ipv4.fib_default && | ||
242 | !fib_table_lookup(net->ipv4.fib_default, flp, res, | ||
243 | FIB_LOOKUP_NOREF)) | ||
244 | return 0; | ||
245 | return -ENETUNREACH; | ||
246 | } | ||
247 | return __fib_lookup(net, flp, res); | ||
248 | } | ||
249 | |||
228 | #endif /* CONFIG_IP_MULTIPLE_TABLES */ | 250 | #endif /* CONFIG_IP_MULTIPLE_TABLES */ |
229 | 251 | ||
230 | /* Exported by fib_frontend.c */ | 252 | /* Exported by fib_frontend.c */ |
@@ -236,9 +258,15 @@ extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, | |||
236 | struct in_device *idev, u32 *itag); | 258 | struct in_device *idev, u32 *itag); |
237 | extern void fib_select_default(struct fib_result *res); | 259 | extern void fib_select_default(struct fib_result *res); |
238 | #ifdef CONFIG_IP_ROUTE_CLASSID | 260 | #ifdef CONFIG_IP_ROUTE_CLASSID |
239 | extern int fib_num_tclassid_users; | 261 | static inline int fib_num_tclassid_users(struct net *net) |
262 | { | ||
263 | return net->ipv4.fib_num_tclassid_users; | ||
264 | } | ||
240 | #else | 265 | #else |
241 | #define fib_num_tclassid_users 0 | 266 | static inline int fib_num_tclassid_users(struct net *net) |
267 | { | ||
268 | return 0; | ||
269 | } | ||
242 | #endif | 270 | #endif |
243 | 271 | ||
244 | /* Exported by fib_semantics.c */ | 272 | /* Exported by fib_semantics.c */ |
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 227f0cd9d3f6..599e48fa97cb 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h | |||
@@ -11,6 +11,7 @@ struct ctl_table_header; | |||
11 | struct ipv4_devconf; | 11 | struct ipv4_devconf; |
12 | struct fib_rules_ops; | 12 | struct fib_rules_ops; |
13 | struct hlist_head; | 13 | struct hlist_head; |
14 | struct fib_table; | ||
14 | struct sock; | 15 | struct sock; |
15 | 16 | ||
16 | struct netns_ipv4 { | 17 | struct netns_ipv4 { |
@@ -24,6 +25,13 @@ struct netns_ipv4 { | |||
24 | struct ipv4_devconf *devconf_dflt; | 25 | struct ipv4_devconf *devconf_dflt; |
25 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 26 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
26 | struct fib_rules_ops *rules_ops; | 27 | struct fib_rules_ops *rules_ops; |
28 | bool fib_has_custom_rules; | ||
29 | struct fib_table *fib_local; | ||
30 | struct fib_table *fib_main; | ||
31 | struct fib_table *fib_default; | ||
32 | #endif | ||
33 | #ifdef CONFIG_IP_ROUTE_CLASSID | ||
34 | int fib_num_tclassid_users; | ||
27 | #endif | 35 | #endif |
28 | struct hlist_head *fib_table_hash; | 36 | struct hlist_head *fib_table_hash; |
29 | struct sock *fibnl; | 37 | struct sock *fibnl; |
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 | ||
222 | int 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 | ||
57 | int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) | 57 | int __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 | } |
70 | EXPORT_SYMBOL_GPL(fib_lookup); | 70 | EXPORT_SYMBOL_GPL(__fib_lookup); |
71 | 71 | ||
72 | static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, | 72 | static 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; |
186 | errout: | 187 | errout: |
187 | return err; | 188 | return err; |
@@ -189,12 +190,14 @@ errout: | |||
189 | 190 | ||
190 | static void fib4_rule_delete(struct fib_rule *rule) | 191 | static 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 | ||
200 | static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | 203 | static 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 | ||
314 | fail: | 318 | fail: |
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; |