|
@@ -79,7 +79,7 @@ int lowpan_header_create(struct sk_buff *skb, struct net_device *ldev,
|
|
|
|
|
|
static struct sk_buff*
|
|
static struct sk_buff*
|
|
lowpan_alloc_frag(struct sk_buff *skb, int size,
|
|
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 net_device *wdev = lowpan_dev_info(skb->dev)->wdev;
|
|
struct sk_buff *frag;
|
|
struct sk_buff *frag;
|
|
@@ -95,11 +95,17 @@ lowpan_alloc_frag(struct sk_buff *skb, int size,
|
|
skb_reset_network_header(frag);
|
|
skb_reset_network_header(frag);
|
|
*mac_cb(frag) = *mac_cb(skb);
|
|
*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 {
|
|
} else {
|
|
frag = ERR_PTR(-ENOMEM);
|
|
frag = ERR_PTR(-ENOMEM);
|
|
@@ -111,13 +117,13 @@ lowpan_alloc_frag(struct sk_buff *skb, int size,
|
|
static int
|
|
static int
|
|
lowpan_xmit_fragment(struct sk_buff *skb, const struct ieee802154_hdr *wpan_hdr,
|
|
lowpan_xmit_fragment(struct sk_buff *skb, const struct ieee802154_hdr *wpan_hdr,
|
|
u8 *frag_hdr, int frag_hdrlen,
|
|
u8 *frag_hdr, int frag_hdrlen,
|
|
- int offset, int len)
|
|
|
|
|
|
+ int offset, int len, bool frag1)
|
|
{
|
|
{
|
|
struct sk_buff *frag;
|
|
struct sk_buff *frag;
|
|
|
|
|
|
raw_dump_inline(__func__, " fragment header", frag_hdr, frag_hdrlen);
|
|
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))
|
|
if (IS_ERR(frag))
|
|
return PTR_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,
|
|
rc = lowpan_xmit_fragment(skb, wpan_hdr, frag_hdr,
|
|
LOWPAN_FRAG1_HEAD_SIZE, 0,
|
|
LOWPAN_FRAG1_HEAD_SIZE, 0,
|
|
- frag_len + skb_network_header_len(skb));
|
|
|
|
|
|
+ frag_len + skb_network_header_len(skb),
|
|
|
|
+ true);
|
|
if (rc) {
|
|
if (rc) {
|
|
pr_debug("%s unable to send FRAG1 packet (tag: %d)",
|
|
pr_debug("%s unable to send FRAG1 packet (tag: %d)",
|
|
__func__, ntohs(frag_tag));
|
|
__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,
|
|
rc = lowpan_xmit_fragment(skb, wpan_hdr, frag_hdr,
|
|
LOWPAN_FRAGN_HEAD_SIZE, skb_offset,
|
|
LOWPAN_FRAGN_HEAD_SIZE, skb_offset,
|
|
- frag_len);
|
|
|
|
|
|
+ frag_len, false);
|
|
if (rc) {
|
|
if (rc) {
|
|
pr_debug("%s unable to send a FRAGN packet. (tag: %d, offset: %d)\n",
|
|
pr_debug("%s unable to send a FRAGN packet. (tag: %d, offset: %d)\n",
|
|
__func__, ntohs(frag_tag), skb_offset);
|
|
__func__, ntohs(frag_tag), skb_offset);
|