|
@@ -265,9 +265,24 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *ldev)
|
|
|
/* We must take a copy of the skb before we modify/replace the ipv6
|
|
|
* header as the header could be used elsewhere
|
|
|
*/
|
|
|
- skb = skb_unshare(skb, GFP_ATOMIC);
|
|
|
- if (!skb)
|
|
|
- return NET_XMIT_DROP;
|
|
|
+ if (unlikely(skb_headroom(skb) < ldev->needed_headroom ||
|
|
|
+ skb_tailroom(skb) < ldev->needed_tailroom)) {
|
|
|
+ struct sk_buff *nskb;
|
|
|
+
|
|
|
+ nskb = skb_copy_expand(skb, ldev->needed_headroom,
|
|
|
+ ldev->needed_tailroom, GFP_ATOMIC);
|
|
|
+ if (likely(nskb)) {
|
|
|
+ consume_skb(skb);
|
|
|
+ skb = nskb;
|
|
|
+ } else {
|
|
|
+ kfree_skb(skb);
|
|
|
+ return NET_XMIT_DROP;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ skb = skb_unshare(skb, GFP_ATOMIC);
|
|
|
+ if (!skb)
|
|
|
+ return NET_XMIT_DROP;
|
|
|
+ }
|
|
|
|
|
|
ret = lowpan_header(skb, ldev, &dgram_size, &dgram_offset);
|
|
|
if (ret < 0) {
|