datapath: Move over-MTU checking into vport_send().
authorJesse Gross <jesse@nicira.com>
Mon, 12 Jul 2010 20:27:57 +0000 (13:27 -0700)
committerJesse Gross <jesse@nicira.com>
Tue, 13 Jul 2010 21:10:18 +0000 (14:10 -0700)
We currently check for packets that are over the MTU in do_output().
There is a one-to-one correlation between this function and
vport_send() so move the MTU check there for consistency with
other error checking.

datapath/actions.c
datapath/vport.c

index f7e51d925152d09a17bd0d92b10079c37e3fa5e4..131548c7ee57da00ba7feaba651c539287287a91 100644 (file)
@@ -347,19 +347,10 @@ set_tp_port(struct sk_buff *skb, struct odp_flow_key *key,
        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;
@@ -368,13 +359,6 @@ do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
        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;
 
index 13039505c687f978d94d98d83552deb1ae0e8fe5..ef07a0910335270a2cbdd5be683fee67f663042d 100644 (file)
@@ -9,6 +9,7 @@
 #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>
@@ -1275,6 +1276,17 @@ vport_receive(struct vport *vport, struct sk_buff *skb)
        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
  *
@@ -1288,25 +1300,28 @@ int
 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;
@@ -1320,6 +1335,16 @@ vport_send(struct vport *vport, struct sk_buff *skb)
                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;
 }