aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/ip_fib.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/ip_fib.h')
-rw-r--r--include/net/ip_fib.h70
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
142struct fib_result_nl { 142struct 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
191int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, 193int 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 *);
195int fib_table_dump(struct fib_table *table, struct sk_buff *skb, 197int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
196 struct netlink_callback *cb); 198 struct netlink_callback *cb);
197int fib_table_flush(struct fib_table *table); 199int fib_table_flush(struct fib_table *table);
200struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
201void fib_table_flush_external(struct fib_table *table);
198void fib_free_table(struct fib_table *tb); 202void 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
207static inline struct fib_table *fib_get_table(struct net *net, u32 id) 209static 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
217static inline struct fib_table *fib_new_table(struct net *net, u32 id) 223static 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)
222static inline int fib_lookup(struct net *net, const struct flowi4 *flp, 228static 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);
249static inline int fib_lookup(struct net *net, struct flowi4 *flp, 254static 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
303int fib_unmerge(struct net *net);
304void fib_flush_external(struct net *net);
297 305
298/* Exported by fib_semantics.c */ 306/* Exported by fib_semantics.c */
299int ip_fib_check_default(__be32 gw, struct net_device *dev); 307int 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 */
306void fib_trie_init(void); 314void fib_trie_init(void);
307struct fib_table *fib_trie_table(u32 id); 315struct fib_table *fib_trie_table(u32 id, struct fib_table *alias);
308 316
309static inline void fib_combine_itag(u32 *itag, const struct fib_result *res) 317static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
310{ 318{