return skb;
 }
 
-static inline unsigned packet_length(const struct sk_buff *skb)
-{
-       unsigned length = skb->len - ETH_HLEN;
-       if (skb->protocol == htons(ETH_P_8021Q))
-               length -= VLAN_HLEN;
-       return length;
-}
-
 static void
 do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
 {
        struct dp_port *p;
-       int mtu;
 
        if (!skb)
                goto error;
        if (!p)
                goto error;
 
-       mtu = vport_get_mtu(p->vport);
-       if (packet_length(skb) > mtu && !skb_is_gso(skb)) {
-               printk(KERN_WARNING "%s: dropped over-mtu packet: %d > %d\n",
-                      dp_name(dp), packet_length(skb), mtu);
-               goto error;
-       }
-
        vport_send(p->vport, skb);
        return;
 
 
 #include <linux/dcache.h>
 #include <linux/etherdevice.h>
 #include <linux/if.h>
+#include <linux/if_vlan.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
        dp_process_received_packet(dp_port, skb);
 }
 
+static inline unsigned
+packet_length(const struct sk_buff *skb)
+{
+       unsigned length = skb->len - ETH_HLEN;
+
+       if (skb->protocol == htons(ETH_P_8021Q))
+               length -= VLAN_HLEN;
+
+       return length;
+}
+
 /**
  *     vport_send - send a packet on a device
  *
 vport_send(struct vport *vport, struct sk_buff *skb)
 {
        int *loop_count;
+       int mtu;
        int sent;
 
        loop_count = &per_cpu_ptr(vport_loop_counter, get_cpu())->count[!!in_interrupt()];
        (*loop_count)++;
 
-       if (likely(*loop_count <= VPORT_MAX_LOOPS)) {
-               sent = vport->ops->send(vport, skb);
-       } else {
+       if (unlikely(*loop_count > VPORT_MAX_LOOPS)) {
                if (net_ratelimit())
                        printk(KERN_WARNING "%s: dropping packet that has looped more than %d times\n",
                               dp_name(vport_get_dp_port(vport)->dp), VPORT_MAX_LOOPS);
+               goto error;
+       }
 
-               sent = 0;
-               kfree_skb(skb);
-               vport_record_error(vport, VPORT_E_TX_DROPPED);
+       mtu = vport_get_mtu(vport);
+       if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
+               if (net_ratelimit())
+                       printk(KERN_WARNING "%s: dropped over-mtu packet: %d > %d\n",
+                              dp_name(vport_get_dp_port(vport)->dp), packet_length(skb), mtu);
+               goto error;
        }
 
-       (*loop_count)--;
-       put_cpu();
+       sent = vport->ops->send(vport, skb);
 
        if (vport->ops->flags & VPORT_F_GEN_STATS && sent > 0) {
                struct vport_percpu_stats *stats;
                local_bh_enable();
        }
 
+       goto out;
+
+error:
+       sent = 0;
+       kfree_skb(skb);
+       vport_record_error(vport, VPORT_E_TX_DROPPED);
+out:
+       (*loop_count)--;
+       put_cpu();
+
        return sent;
 }