diff --git a/include/net/dst.h b/include/net/dst.h index 002500e..2fe9a6c 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -103,6 +103,8 @@ struct dst_ops void (*link_failure)(struct sk_buff *); void (*update_pmtu)(struct dst_entry *dst, u32 mtu); int (*local_out)(struct sk_buff *skb); + size_t (*info_show)(struct dst_entry *, char *buff, + size_t len); int entry_size; atomic_t entries; diff --git a/net/core/dst.c b/net/core/dst.c index fe03266..08395e8 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -70,6 +70,7 @@ static void dst_gc_task(struct work_struct *work) #if RT_CACHE_DEBUG >= 2 ktime_t time_start = ktime_get(); struct timespec elapsed; + char info[128]; #endif mutex_lock(&dst_gc_mutex); @@ -82,6 +83,12 @@ loop: if (likely(atomic_read(&dst->__refcnt))) { last->next = dst; last = dst; +#if RT_CACHE_DEBUG >= 2 + if (delayed < 10 && dst->ops->info_show) { + dst->ops->info_show(dst, info, sizeof(info)); + printk(KERN_DEBUG "dstgc [%d] %s\n", delayed, info); + } +#endif delayed++; continue; } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 230716c..ef8c3b7 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -148,6 +148,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); static void ipv4_link_failure(struct sk_buff *skb); static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu); static int rt_garbage_collect(struct dst_ops *ops); +static size_t rt_info_show(struct dst_entry *dst, + char *buff, size_t maxlen); static struct dst_ops ipv4_dst_ops = { @@ -161,6 +163,7 @@ static struct dst_ops ipv4_dst_ops = { .link_failure = ipv4_link_failure, .update_pmtu = ip_rt_update_pmtu, .local_out = ip_local_out, + .info_show = rt_info_show, .entry_size = sizeof(struct rtable), .entries = ATOMIC_INIT(0), }; @@ -269,6 +272,28 @@ static unsigned int rt_hash_code(u32 daddr, u32 saddr) rt_hash_code((__force u32)(__be32)(daddr),\ (__force u32)(__be32)(saddr) ^ ((idx) << 5)) +static size_t rt_info_show(struct dst_entry *dst, char *buff, size_t maxlen) +{ + struct rtable *r = (struct rtable *)dst; + + return snprintf(buff, maxlen, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t" + "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\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, 0, (unsigned long)r->rt_src, + (dst_metric(&r->u.dst, RTAX_ADVMSS) ? + (int)dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0), + dst_metric(&r->u.dst, RTAX_WINDOW), + (int)((dst_metric(&r->u.dst, RTAX_RTT) >> 3) + + dst_metric(&r->u.dst, RTAX_RTTVAR)), + r->fl.fl4_tos, + r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1, + r->u.dst.hh ? (r->u.dst.hh->hh_output == + dev_queue_xmit) : 0, + r->rt_spec_dst); +} + #ifdef CONFIG_PROC_FS struct rt_cache_iter_state { struct seq_net_private p; @@ -368,25 +393,9 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) "Metric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\t" "HHUptod\tSpecDst"); else { - struct rtable *r = v; - char temp[256]; - - sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t" - "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\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, 0, (unsigned long)r->rt_src, - (dst_metric(&r->u.dst, RTAX_ADVMSS) ? - (int)dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0), - dst_metric(&r->u.dst, RTAX_WINDOW), - (int)((dst_metric(&r->u.dst, RTAX_RTT) >> 3) + - dst_metric(&r->u.dst, RTAX_RTTVAR)), - r->fl.fl4_tos, - r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1, - r->u.dst.hh ? (r->u.dst.hh->hh_output == - dev_queue_xmit) : 0, - r->rt_spec_dst); + char temp[128]; + + rt_info_show(v, temp, 128); seq_printf(seq, "%-127s\n", temp); } return 0;