]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/ieee802154/6lowpan/tx.c
ieee802154: 6lowpan: don't skip first dsn while fragmentation
[mirror_ubuntu-bionic-kernel.git] / net / ieee802154 / 6lowpan / tx.c
index 5ecf8af7154bd0851aca76d49b867794f09ec1b1..3b665e12cf2bc19fd80566442efec59bead8c700 100644 (file)
@@ -79,7 +79,7 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev,
 
 static struct sk_buff*
 lowpan_alloc_frag(struct sk_buff *skb, int size,
-                 const struct ieee802154_hdr *master_hdr)
+                 const struct ieee802154_hdr *master_hdr, bool frag1)
 {
        struct net_device *wdev = lowpan_dev_info(skb->dev)->wdev;
        struct sk_buff *frag;
@@ -95,11 +95,17 @@ lowpan_alloc_frag(struct sk_buff *skb, int size,
                skb_reset_network_header(frag);
                *mac_cb(frag) = *mac_cb(skb);
 
-               rc = wpan_dev_hard_header(frag, wdev, &master_hdr->dest,
-                                         &master_hdr->source, size);
-               if (rc < 0) {
-                       kfree_skb(frag);
-                       return ERR_PTR(rc);
+               if (frag1) {
+                       memcpy(skb_put(frag, skb->mac_len),
+                              skb_mac_header(skb), skb->mac_len);
+               } else {
+                       rc = wpan_dev_hard_header(frag, wdev,
+                                                 &master_hdr->dest,
+                                                 &master_hdr->source, size);
+                       if (rc < 0) {
+                               kfree_skb(frag);
+                               return ERR_PTR(rc);
+                       }
                }
        } else {
                frag = ERR_PTR(-ENOMEM);
@@ -111,13 +117,13 @@ lowpan_alloc_frag(struct sk_buff *skb, int size,
 static int
 lowpan_xmit_fragment(struct sk_buff *skb, const struct ieee802154_hdr *wpan_hdr,
                     u8 *frag_hdr, int frag_hdrlen,
-                    int offset, int len)
+                    int offset, int len, bool frag1)
 {
        struct sk_buff *frag;
 
        raw_dump_inline(__func__, " fragment header", frag_hdr, frag_hdrlen);
 
-       frag = lowpan_alloc_frag(skb, frag_hdrlen + len, wpan_hdr);
+       frag = lowpan_alloc_frag(skb, frag_hdrlen + len, wpan_hdr, frag1);
        if (IS_ERR(frag))
                return PTR_ERR(frag);
 
@@ -156,7 +162,8 @@ lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev,
 
        rc = lowpan_xmit_fragment(skb, wpan_hdr, frag_hdr,
                                  LOWPAN_FRAG1_HEAD_SIZE, 0,
-                                 frag_len + skb_network_header_len(skb));
+                                 frag_len + skb_network_header_len(skb),
+                                 true);
        if (rc) {
                pr_debug("%s unable to send FRAG1 packet (tag: %d)",
                         __func__, ntohs(frag_tag));
@@ -177,7 +184,7 @@ lowpan_xmit_fragmented(struct sk_buff *skb, struct net_device *ldev,
 
                rc = lowpan_xmit_fragment(skb, wpan_hdr, frag_hdr,
                                          LOWPAN_FRAGN_HEAD_SIZE, skb_offset,
-                                         frag_len);
+                                         frag_len, false);
                if (rc) {
                        pr_debug("%s unable to send a FRAGN packet. (tag: %d, offset: %d)\n",
                                 __func__, ntohs(frag_tag), skb_offset);