diff options
Diffstat (limited to 'include/net/ip_fib.h')
-rw-r--r-- | include/net/ip_fib.h | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 5bd120e4bc0a..54271ed0ed45 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
@@ -136,7 +136,7 @@ struct fib_result { | |||
136 | u32 tclassid; | 136 | u32 tclassid; |
137 | struct fib_info *fi; | 137 | struct fib_info *fi; |
138 | struct fib_table *table; | 138 | struct fib_table *table; |
139 | struct list_head *fa_head; | 139 | struct hlist_head *fa_head; |
140 | }; | 140 | }; |
141 | 141 | ||
142 | struct fib_result_nl { | 142 | struct fib_result_nl { |
@@ -185,7 +185,9 @@ struct fib_table { | |||
185 | u32 tb_id; | 185 | u32 tb_id; |
186 | int tb_default; | 186 | int tb_default; |
187 | int tb_num_default; | 187 | int tb_num_default; |
188 | unsigned long tb_data[0]; | 188 | struct rcu_head rcu; |
189 | unsigned long *tb_data; | ||
190 | unsigned long __data[0]; | ||
189 | }; | 191 | }; |
190 | 192 | ||
191 | int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, | 193 | int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, |
@@ -195,10 +197,10 @@ int fib_table_delete(struct fib_table *, struct fib_config *); | |||
195 | int fib_table_dump(struct fib_table *table, struct sk_buff *skb, | 197 | int fib_table_dump(struct fib_table *table, struct sk_buff *skb, |
196 | struct netlink_callback *cb); | 198 | struct netlink_callback *cb); |
197 | int fib_table_flush(struct fib_table *table); | 199 | int fib_table_flush(struct fib_table *table); |
200 | struct fib_table *fib_trie_unmerge(struct fib_table *main_tb); | ||
201 | void fib_table_flush_external(struct fib_table *table); | ||
198 | void fib_free_table(struct fib_table *tb); | 202 | void fib_free_table(struct fib_table *tb); |
199 | 203 | ||
200 | |||
201 | |||
202 | #ifndef CONFIG_IP_MULTIPLE_TABLES | 204 | #ifndef CONFIG_IP_MULTIPLE_TABLES |
203 | 205 | ||
204 | #define TABLE_LOCAL_INDEX (RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1)) | 206 | #define TABLE_LOCAL_INDEX (RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1)) |
@@ -206,12 +208,16 @@ void fib_free_table(struct fib_table *tb); | |||
206 | 208 | ||
207 | static inline struct fib_table *fib_get_table(struct net *net, u32 id) | 209 | static inline struct fib_table *fib_get_table(struct net *net, u32 id) |
208 | { | 210 | { |
211 | struct hlist_node *tb_hlist; | ||
209 | struct hlist_head *ptr; | 212 | struct hlist_head *ptr; |
210 | 213 | ||
211 | ptr = id == RT_TABLE_LOCAL ? | 214 | ptr = id == RT_TABLE_LOCAL ? |
212 | &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] : | 215 | &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] : |
213 | &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]; | 216 | &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]; |
214 | return hlist_entry(ptr->first, struct fib_table, tb_hlist); | 217 | |
218 | tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr)); | ||
219 | |||
220 | return hlist_entry(tb_hlist, struct fib_table, tb_hlist); | ||
215 | } | 221 | } |
216 | 222 | ||
217 | static inline struct fib_table *fib_new_table(struct net *net, u32 id) | 223 | static inline struct fib_table *fib_new_table(struct net *net, u32 id) |
@@ -222,14 +228,13 @@ static inline struct fib_table *fib_new_table(struct net *net, u32 id) | |||
222 | static inline int fib_lookup(struct net *net, const struct flowi4 *flp, | 228 | static inline int fib_lookup(struct net *net, const struct flowi4 *flp, |
223 | struct fib_result *res) | 229 | struct fib_result *res) |
224 | { | 230 | { |
231 | struct fib_table *tb; | ||
225 | int err = -ENETUNREACH; | 232 | int err = -ENETUNREACH; |
226 | 233 | ||
227 | rcu_read_lock(); | 234 | rcu_read_lock(); |
228 | 235 | ||
229 | if (!fib_table_lookup(fib_get_table(net, RT_TABLE_LOCAL), flp, res, | 236 | tb = fib_get_table(net, RT_TABLE_MAIN); |
230 | FIB_LOOKUP_NOREF) || | 237 | if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF)) |
231 | !fib_table_lookup(fib_get_table(net, RT_TABLE_MAIN), flp, res, | ||
232 | FIB_LOOKUP_NOREF)) | ||
233 | err = 0; | 238 | err = 0; |
234 | 239 | ||
235 | rcu_read_unlock(); | 240 | rcu_read_unlock(); |
@@ -249,28 +254,29 @@ int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res); | |||
249 | static inline int fib_lookup(struct net *net, struct flowi4 *flp, | 254 | static inline int fib_lookup(struct net *net, struct flowi4 *flp, |
250 | struct fib_result *res) | 255 | struct fib_result *res) |
251 | { | 256 | { |
252 | if (!net->ipv4.fib_has_custom_rules) { | 257 | struct fib_table *tb; |
253 | int err = -ENETUNREACH; | 258 | int err; |
254 | 259 | ||
255 | rcu_read_lock(); | 260 | if (net->ipv4.fib_has_custom_rules) |
256 | 261 | return __fib_lookup(net, flp, res); | |
257 | res->tclassid = 0; | 262 | |
258 | if ((net->ipv4.fib_local && | 263 | rcu_read_lock(); |
259 | !fib_table_lookup(net->ipv4.fib_local, flp, res, | 264 | |
260 | FIB_LOOKUP_NOREF)) || | 265 | res->tclassid = 0; |
261 | (net->ipv4.fib_main && | 266 | |
262 | !fib_table_lookup(net->ipv4.fib_main, flp, res, | 267 | for (err = 0; !err; err = -ENETUNREACH) { |
263 | FIB_LOOKUP_NOREF)) || | 268 | tb = rcu_dereference_rtnl(net->ipv4.fib_main); |
264 | (net->ipv4.fib_default && | 269 | if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF)) |
265 | !fib_table_lookup(net->ipv4.fib_default, flp, res, | 270 | break; |
266 | FIB_LOOKUP_NOREF))) | 271 | |
267 | err = 0; | 272 | tb = rcu_dereference_rtnl(net->ipv4.fib_default); |
268 | 273 | if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF)) | |
269 | rcu_read_unlock(); | 274 | break; |
270 | |||
271 | return err; | ||
272 | } | 275 | } |
273 | return __fib_lookup(net, flp, res); | 276 | |
277 | rcu_read_unlock(); | ||
278 | |||
279 | return err; | ||
274 | } | 280 | } |
275 | 281 | ||
276 | #endif /* CONFIG_IP_MULTIPLE_TABLES */ | 282 | #endif /* CONFIG_IP_MULTIPLE_TABLES */ |
@@ -294,6 +300,8 @@ static inline int fib_num_tclassid_users(struct net *net) | |||
294 | return 0; | 300 | return 0; |
295 | } | 301 | } |
296 | #endif | 302 | #endif |
303 | int fib_unmerge(struct net *net); | ||
304 | void fib_flush_external(struct net *net); | ||
297 | 305 | ||
298 | /* Exported by fib_semantics.c */ | 306 | /* Exported by fib_semantics.c */ |
299 | int ip_fib_check_default(__be32 gw, struct net_device *dev); | 307 | int ip_fib_check_default(__be32 gw, struct net_device *dev); |
@@ -304,7 +312,7 @@ void fib_select_multipath(struct fib_result *res); | |||
304 | 312 | ||
305 | /* Exported by fib_trie.c */ | 313 | /* Exported by fib_trie.c */ |
306 | void fib_trie_init(void); | 314 | void fib_trie_init(void); |
307 | struct fib_table *fib_trie_table(u32 id); | 315 | struct fib_table *fib_trie_table(u32 id, struct fib_table *alias); |
308 | 316 | ||
309 | static inline void fib_combine_itag(u32 *itag, const struct fib_result *res) | 317 | static inline void fib_combine_itag(u32 *itag, const struct fib_result *res) |
310 | { | 318 | { |