#include <linux/version.h>
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+#define HAVE_NETDEV_QUEUE_STATS
+#endif
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
 
 #include <linux/if_tunnel.h>
        spinlock_t                      lock;
 };
 
+#ifdef HAVE_NETDEV_QUEUE_STATS
+#define UPDATE_TX_STATS()                                              \
+       txq->tx_bytes += pkt_len;                                       \
+       txq->tx_packets++;
+#else
+#define UPDATE_TX_STATS()                                              \
+       stats->tx_bytes += pkt_len;                                     \
+       stats->tx_packets++;
+#endif
+
 #define IPTUNNEL_XMIT() do {                                           \
        int err;                                                        \
        int pkt_len = skb->len - skb_transport_offset(skb);             \
        ip_select_ident(iph, &rt->u.dst, NULL);                         \
                                                                        \
        err = ip_local_out(skb);                                        \
-       if (net_xmit_eval(err) == 0) {                                  \
-               stats->tx_bytes += pkt_len;                             \
-               stats->tx_packets++;                                    \
+       if (likely(net_xmit_eval(err) == 0)) {                          \
+               UPDATE_TX_STATS();                                      \
        } else {                                                        \
                stats->tx_errors++;                                     \
                stats->tx_aborted_errors++;                             \
 
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        struct net_device_stats *stats;
+#ifdef HAVE_NETDEV_QUEUE_STATS
+       struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+#endif
        struct iphdr  *old_iph = ip_hdr(skb);
        struct iphdr  *tiph;
        u8     tos;
        int    mtu;
 
 #ifdef HAVE_NETDEV_STATS
-       stats = &tunnel->dev->stats;
+       stats = &dev->stats;
 #else
        stats = &tunnel->stat;
 #endif
                struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
                if (!new_skb) {
                        ip_rt_put(rt);
+#ifdef HAVE_NETDEV_QUEUE_STATS
+                       txq->tx_dropped++;
+#else
                        stats->tx_dropped++;
+#endif
                        dev_kfree_skb(skb);
                        return NETDEV_TX_OK;
                }