For SNAT, don't store the pre-fragment L2 header before actions are applied.
[sliver-openvswitch.git] / datapath / dp_dev.c
index ee66638..ec36361 100644 (file)
@@ -62,6 +62,20 @@ static int dp_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
        struct dp_dev *dp_dev = dp_dev_priv(netdev);
        struct datapath *dp = dp_dev->dp;
 
+       /* By orphaning 'skb' we will screw up socket accounting slightly, but
+        * the effect is limited to the device queue length.  If we don't
+        * do this, then the sk_buff will be destructed eventually, but it is
+        * harder to predict when. */
+       skb_orphan(skb);
+
+       /* We are going to modify 'skb', by sticking it on &dp_dev->xmit_queue,
+        * so we need to have our own clone.  (At any rate, fwd_port_input()
+        * will need its own clone, so there's no benefit to queuing any other
+        * way.) */
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
+               return 0;
+
        dp_dev->stats.tx_packets++;
        dp_dev->stats.tx_bytes += skb->len;
 
@@ -115,7 +129,7 @@ static void
 set_uuid_mac(struct net_device *netdev)
 {
        const char *uuid = dmi_get_system_info(DMI_PRODUCT_UUID);
-       const char *uptr = uuid + 24;
+       const char *uptr;
        uint8_t mac[ETH_ALEN];
        int i;
 
@@ -129,6 +143,7 @@ set_uuid_mac(struct net_device *netdev)
 
        /* Pull out the embedded MAC address.  The kernel's sscanf doesn't
         * support field widths on hex digits, so we use this hack. */
+       uptr = uuid + 24;
        for (i=0; i<ETH_ALEN; i++) {
                unsigned char d[3];