|
@@ -1093,8 +1093,27 @@ restart:
|
|
* If we drop it here, the callers have no way to resolve routes
|
|
* If we drop it here, the callers have no way to resolve routes
|
|
* when we're not caching. Instead, just point *rp at rt, so
|
|
* when we're not caching. Instead, just point *rp at rt, so
|
|
* the caller gets a single use out of the route
|
|
* the caller gets a single use out of the route
|
|
|
|
+ * Note that we do rt_free on this new route entry, so that
|
|
|
|
+ * once its refcount hits zero, we are still able to reap it
|
|
|
|
+ * (Thanks Alexey)
|
|
|
|
+ * Note also the rt_free uses call_rcu. We don't actually
|
|
|
|
+ * need rcu protection here, this is just our path to get
|
|
|
|
+ * on the route gc list.
|
|
*/
|
|
*/
|
|
- goto report_and_exit;
|
|
|
|
|
|
+
|
|
|
|
+ if (rt->rt_type == RTN_UNICAST || rt->fl.iif == 0) {
|
|
|
|
+ int err = arp_bind_neighbour(&rt->u.dst);
|
|
|
|
+ if (err) {
|
|
|
|
+ if (net_ratelimit())
|
|
|
|
+ printk(KERN_WARNING
|
|
|
|
+ "Neighbour table failure & not caching routes.\n");
|
|
|
|
+ rt_drop(rt);
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rt_free(rt);
|
|
|
|
+ goto skip_hashing;
|
|
}
|
|
}
|
|
|
|
|
|
rthp = &rt_hash_table[hash].chain;
|
|
rthp = &rt_hash_table[hash].chain;
|
|
@@ -1211,7 +1230,8 @@ restart:
|
|
#if RT_CACHE_DEBUG >= 2
|
|
#if RT_CACHE_DEBUG >= 2
|
|
if (rt->u.dst.rt_next) {
|
|
if (rt->u.dst.rt_next) {
|
|
struct rtable *trt;
|
|
struct rtable *trt;
|
|
- printk(KERN_DEBUG "rt_cache @%02x: %pI4", hash, &rt->rt_dst);
|
|
|
|
|
|
+ printk(KERN_DEBUG "rt_cache @%02x: %pI4",
|
|
|
|
+ hash, &rt->rt_dst);
|
|
for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next)
|
|
for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next)
|
|
printk(" . %pI4", &trt->rt_dst);
|
|
printk(" . %pI4", &trt->rt_dst);
|
|
printk("\n");
|
|
printk("\n");
|
|
@@ -1226,7 +1246,7 @@ restart:
|
|
|
|
|
|
spin_unlock_bh(rt_hash_lock_addr(hash));
|
|
spin_unlock_bh(rt_hash_lock_addr(hash));
|
|
|
|
|
|
-report_and_exit:
|
|
|
|
|
|
+skip_hashing:
|
|
if (rp)
|
|
if (rp)
|
|
*rp = rt;
|
|
*rp = rt;
|
|
else
|
|
else
|