Don't oops in dp_output_control() for skbs with null ->dev.
[sliver-openvswitch.git] / datapath / datapath.c
index d27a9bc..d4f332e 100644 (file)
@@ -455,6 +455,14 @@ static int dp_maint_func(void *data)
 static void
 do_port_input(struct net_bridge_port *p, struct sk_buff *skb) 
 {
+       /* Make our own copy of the packet.  Otherwise we will mangle the
+        * packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
+        * (No one comes after us, since we tell handle_bridge() that we took
+        * the packet.) */
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
+               return;
+
 #ifdef SUPPORT_SNAT
        /* Check if this packet needs early SNAT processing. */
        if (snat_pre_route(skb)) {
@@ -662,7 +670,6 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb,
         * forward the whole packet? */
        struct sk_buff *f_skb;
        struct ofp_packet_in *opi;
-       struct net_bridge_port *p;
        size_t fwd_len, opi_len;
        int err;
 
@@ -678,8 +685,9 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb,
        }
        opi->buffer_id      = htonl(buffer_id);
        opi->total_len      = htons(skb->len);
-       p = skb->dev->br_port;
-       opi->in_port        = htons(p ? p->port_no : OFPP_LOCAL);
+       opi->in_port        = htons(skb->dev && skb->dev->br_port
+                                   ? skb->dev->br_port->port_no
+                                   : OFPP_LOCAL);
        opi->reason         = reason;
        opi->pad            = 0;
        memcpy(opi->data, skb_mac_header(skb), fwd_len);