diff options
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/6lowpan.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 8edfea5da572..872c8f97a30c 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c | |||
@@ -422,44 +422,60 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head, | |||
422 | static int | 422 | static int |
423 | lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev) | 423 | lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev) |
424 | { | 424 | { |
425 | int err, header_length, payload_length, tag, offset = 0; | 425 | int err; |
426 | u16 dgram_offset, dgram_size, payload_length, header_length, | ||
427 | lowpan_size, frag_plen, offset, tag; | ||
426 | u8 head[5]; | 428 | u8 head[5]; |
427 | 429 | ||
428 | header_length = skb->mac_len; | 430 | header_length = skb->mac_len; |
429 | payload_length = skb->len - header_length; | 431 | payload_length = skb->len - header_length; |
430 | tag = lowpan_dev_info(dev)->fragment_tag++; | 432 | tag = lowpan_dev_info(dev)->fragment_tag++; |
433 | lowpan_size = skb_network_header_len(skb); | ||
434 | dgram_size = lowpan_uncompress_size(skb, &dgram_offset) - | ||
435 | header_length; | ||
431 | 436 | ||
432 | /* first fragment header */ | 437 | /* first fragment header */ |
433 | head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) & 0x7); | 438 | head[0] = LOWPAN_DISPATCH_FRAG1 | ((dgram_size >> 8) & 0x7); |
434 | head[1] = payload_length & 0xff; | 439 | head[1] = dgram_size & 0xff; |
435 | head[2] = tag >> 8; | 440 | head[2] = tag >> 8; |
436 | head[3] = tag & 0xff; | 441 | head[3] = tag & 0xff; |
437 | 442 | ||
438 | err = lowpan_fragment_xmit(skb, head, header_length, LOWPAN_FRAG_SIZE, | 443 | /* calc the nearest payload length(divided to 8) for first fragment |
439 | 0, LOWPAN_DISPATCH_FRAG1); | 444 | * which fits into a IEEE802154_MTU |
445 | */ | ||
446 | frag_plen = round_down(IEEE802154_MTU - header_length - | ||
447 | LOWPAN_FRAG1_HEAD_SIZE - lowpan_size - | ||
448 | IEEE802154_MFR_SIZE, 8); | ||
440 | 449 | ||
450 | err = lowpan_fragment_xmit(skb, head, header_length, | ||
451 | frag_plen + lowpan_size, 0, | ||
452 | LOWPAN_DISPATCH_FRAG1); | ||
441 | if (err) { | 453 | if (err) { |
442 | pr_debug("%s unable to send FRAG1 packet (tag: %d)", | 454 | pr_debug("%s unable to send FRAG1 packet (tag: %d)", |
443 | __func__, tag); | 455 | __func__, tag); |
444 | goto exit; | 456 | goto exit; |
445 | } | 457 | } |
446 | 458 | ||
447 | offset = LOWPAN_FRAG_SIZE; | 459 | offset = lowpan_size + frag_plen; |
460 | dgram_offset += frag_plen; | ||
448 | 461 | ||
449 | /* next fragment header */ | 462 | /* next fragment header */ |
450 | head[0] &= ~LOWPAN_DISPATCH_FRAG1; | 463 | head[0] &= ~LOWPAN_DISPATCH_FRAG1; |
451 | head[0] |= LOWPAN_DISPATCH_FRAGN; | 464 | head[0] |= LOWPAN_DISPATCH_FRAGN; |
452 | 465 | ||
466 | frag_plen = round_down(IEEE802154_MTU - header_length - | ||
467 | LOWPAN_FRAGN_HEAD_SIZE - IEEE802154_MFR_SIZE, 8); | ||
468 | |||
453 | while (payload_length - offset > 0) { | 469 | while (payload_length - offset > 0) { |
454 | int len = LOWPAN_FRAG_SIZE; | 470 | int len = frag_plen; |
455 | 471 | ||
456 | head[4] = offset / 8; | 472 | head[4] = dgram_offset >> 3; |
457 | 473 | ||
458 | if (payload_length - offset < len) | 474 | if (payload_length - offset < len) |
459 | len = payload_length - offset; | 475 | len = payload_length - offset; |
460 | 476 | ||
461 | err = lowpan_fragment_xmit(skb, head, header_length, | 477 | err = lowpan_fragment_xmit(skb, head, header_length, len, |
462 | len, offset, LOWPAN_DISPATCH_FRAGN); | 478 | offset, LOWPAN_DISPATCH_FRAGN); |
463 | if (err) { | 479 | if (err) { |
464 | pr_debug("%s unable to send a subsequent FRAGN packet " | 480 | pr_debug("%s unable to send a subsequent FRAGN packet " |
465 | "(tag: %d, offset: %d", __func__, tag, offset); | 481 | "(tag: %d, offset: %d", __func__, tag, offset); |
@@ -467,6 +483,7 @@ lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev) | |||
467 | } | 483 | } |
468 | 484 | ||
469 | offset += len; | 485 | offset += len; |
486 | dgram_offset += len; | ||
470 | } | 487 | } |
471 | 488 | ||
472 | exit: | 489 | exit: |