--- linux-2.6.8.1/net/core/dst.c	2004-08-14 12:55:34.000000000 +0200
+++ linux-2.6.8.1-dstdeb/net/core/dst.c	2004-09-22 16:03:50.000000000 +0200
@@ -16,8 +16,11 @@
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <net/dst.h>
+#include <net/route.h>
 
 const char dst_underflow_bug_msg[] = KERN_DEBUG "BUG: dst underflow %d: %p at %p\n";
 
@@ -30,7 +33,9 @@
  *    and non-BH context, so local BH disabling is needed.
  * 4) All operations modify state, so a spinlock is used.
  */
+#define RT_CACHE_DEBUG 2
 static struct dst_entry 	*dst_garbage_list;
+static int 			dst_garbage_count;
 #if RT_CACHE_DEBUG >= 2 
 static atomic_t			 dst_total = ATOMIC_INIT(0);
 #endif
@@ -63,6 +68,7 @@
 			delayed++;
 			continue;
 		}
+		dst_garbage_count--;
 		*dstp = dst->next;
 
 		dst = dst_destroy(dst);
@@ -155,6 +161,7 @@
 {
 	spin_lock_bh(&dst_lock);
 	___dst_free(dst);
+	dst_garbage_count++;
 	dst->next = dst_garbage_list;
 	dst_garbage_list = dst;
 	if (dst_gc_timer_inc > DST_GC_INC) {
@@ -257,8 +264,13 @@
 	case NETDEV_DOWN:
 		spin_lock_bh(&dst_lock);
 		for (dst = dst_garbage_list; dst; dst = dst->next) {
-			if (dst->dev == dev)
+			if (dst->dev == dev) {
+#if RT_CACHE_DEBUG >= 2
+				printk(KERN_DEBUG 
+				"%s: calling dst_ifdown(dst=%p,event=%s) for device %s\n", __FUNCTION__, dst, (event == NETDEV_DOWN) ? "DOWN" : "UNREGISTER", dev->name);
+#endif
 				dst_ifdown(dst, event != NETDEV_DOWN);
+			}
 		}
 		spin_unlock_bh(&dst_lock);
 		break;
@@ -270,9 +282,85 @@
 	.notifier_call	= dst_dev_event,
 };
 
+static ctl_table dst_sysctl_table[] = {
+	{
+		.ctl_name	= 9999,
+		.procname	= "dst_garbage_count",
+		.data		= &dst_garbage_count,
+		.maxlen		= sizeof(int),
+		.mode		= 0400,
+		.proc_handler	= &proc_dointvec,
+	},
+};
+
+static void *dst_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	spin_lock(&dst_lock);
+	return *pos ? &dst_garbage_list : SEQ_START_TOKEN;
+}
+
+static void *dst_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct rtable *r = v;
+
+	++*pos;
+	return r->u.rt_next;
+}
+
+static void dst_seq_stop(struct seq_file *seq, void *v)
+{
+	spin_unlock(&dst_lock);
+}
+
+static int dst_seq_show(struct seq_file *seq, void *v)
+{
+	/* we just blindly assume that all dst_garbage entries are ipv4.
+	 * This is evil -HW */
+	struct rtable *r = v;
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "%-127s\n",
+			   "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t"
+			   "Source\tSpecDst");
+		return 0;
+	}
+
+	seq_printf(seq, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%08lX\t%08x",
+		r->u.dst.dev ? r->u.dst.dev->name : "*",
+		(unsigned long)r->rt_dst, (unsigned long)r->rt_gateway,
+		r->rt_flags, atomic_read(&r->u.dst.__refcnt),
+		r->u.dst.__use, (unsigned long)r->rt_src, r->rt_spec_dst);
+	return 0;
+}
+
+
+static struct seq_operations dst_seq_ops = {
+	.start = dst_seq_start,
+	.next = dst_seq_next,
+	.stop = dst_seq_stop,
+	.show = dst_seq_show,
+};
+
+static int dst_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &dst_seq_ops);
+}
+
+struct file_operations dst_seq_fops = {
+	.open = dst_seq_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
 void __init dst_init(void)
 {
 	register_netdevice_notifier(&dst_dev_notifier);
+#ifdef CONFIG_SYSCTL
+	register_sysctl_table(dst_sysctl_table, 0);
+#endif
+#ifdef CONFIG_PROC_FS
+	proc_net_fops_create("dst_garbage", S_IRUGO, &dst_seq_fops);
+#endif
 }
 
 EXPORT_SYMBOL(dst_underflow_bug_msg);
