static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
                       struct net_device *dev, skb_delivery_cb deliver_skb)
 {
-       struct sk_buff *new;
        int stat;
 
-       new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
-                             GFP_ATOMIC);
-       kfree_skb(skb);
-
-       if (!new)
-               return -ENOMEM;
-
-       skb_push(new, sizeof(struct ipv6hdr));
-       skb_reset_network_header(new);
-       skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
+       skb_push(skb, sizeof(struct ipv6hdr));
+       skb_reset_network_header(skb);
+       skb_copy_to_linear_data(skb, hdr, sizeof(struct ipv6hdr));
 
-       new->protocol = htons(ETH_P_IPV6);
-       new->pkt_type = PACKET_HOST;
-       new->dev = dev;
+       skb->protocol = htons(ETH_P_IPV6);
+       skb->pkt_type = PACKET_HOST;
+       skb->dev = dev;
 
        raw_dump_table(__func__, "raw skb data dump before receiving",
-                      new->data, new->len);
+                      skb->data, skb->len);
 
-       stat = deliver_skb(new, dev);
+       stat = deliver_skb(skb, dev);
 
-       kfree_skb(new);
+       consume_skb(skb);
 
        return stat;
 }
        /* UDP data uncompression */
        if (iphc0 & LOWPAN_IPHC_NH_C) {
                struct udphdr uh;
-               struct sk_buff *new;
+               const int needed = sizeof(struct udphdr) + sizeof(hdr);
 
                if (uncompress_udp_header(skb, &uh))
                        goto drop;
                /* replace the compressed UDP head by the uncompressed UDP
                 * header
                 */
-               new = skb_copy_expand(skb, sizeof(struct udphdr),
-                                     skb_tailroom(skb), GFP_ATOMIC);
-               kfree_skb(skb);
-
-               if (!new)
-                       return -ENOMEM;
-
-               skb = new;
+               err = skb_cow(skb, needed);
+               if (unlikely(err)) {
+                       kfree_skb(skb);
+                       return err;
+               }
 
                skb_push(skb, sizeof(struct udphdr));
                skb_reset_transport_header(skb);
                               (u8 *)&uh, sizeof(uh));
 
                hdr.nexthdr = UIP_PROTO_UDP;
+       } else {
+               err = skb_cow(skb, sizeof(hdr));
+               if (unlikely(err)) {
+                       kfree_skb(skb);
+                       return err;
+               }
        }
 
        hdr.payload_len = htons(skb->len);