tunneling: Remove call to eth_type_trans() on receive.
authorJesse Gross <jesse@nicira.com>
Sat, 4 Dec 2010 02:06:23 +0000 (18:06 -0800)
committerJesse Gross <jesse@nicira.com>
Fri, 10 Dec 2010 01:43:35 +0000 (17:43 -0800)
On receive we call eth_type_trans() to set skb->protocol.  However,
that function also sets skb->pkt_type, which requires several
comparisons to MAC addresses.  Nothing in OVS cares about pkt_type,
so this is wasteful.  If we actually do egress to the IP stack
through an internal device then we'll call eth_type_trans() to get
everything correctly setup.  It's possible for device drivers to
see an incorrect pkt_type or not correctly parse legacy IPX (which
eth_type_trans() also handles) but it's highly unlikely that they
will care.

Signed-off-by: Jesse Gross <jesse@nicira.com>
datapath/tunnel.c

index ec3ad93..542badc 100644 (file)
@@ -401,17 +401,26 @@ static inline void ecn_decapsulate(struct sk_buff *skb)
 /* Called with rcu_read_lock. */
 void tnl_rcv(struct vport *vport, struct sk_buff *skb)
 {
-       skb->pkt_type = PACKET_HOST;
-       skb->protocol = eth_type_trans(skb, skb->dev);
+       /* Packets received by this function are in the following state:
+        * - skb->data points to the inner Ethernet header.
+        * - The inner Ethernet header is in the linear data area.
+        * - skb->csum does not include the inner Ethernet header.
+        * - The layer pointers point at the outer headers.
+        */
+
+       struct ethhdr *eh = (struct ethhdr *)skb->data;
+
+       if (likely(ntohs(eh->h_proto) >= 1536))
+               skb->protocol = eh->h_proto;
+       else
+               skb->protocol = htons(ETH_P_802_2);
 
        skb_dst_drop(skb);
        nf_reset(skb);
        secpath_reset(skb);
-       skb_reset_network_header(skb);
+       skb_set_network_header(skb, ETH_HLEN);
 
        ecn_decapsulate(skb);
-
-       skb_push(skb, ETH_HLEN);
        compute_ip_summed(skb, false);
 
        vport_receive(vport, skb);