subsys/net/ip/l2/ieee802154/ieee802154_fragment.c
/**
 *  ch  : compressed (IPv6) header(s)
 *  fh  : fragment header (dispatch + size + tag + [offset])
 *  p   : payload (first fragment holds IPv6 hdr as payload)
 *  e   : empty space
 *
 *  Input to ieee802154_fragment() buf chain looks like below
 *
 *  | ch + p | p | p | p | p | p + e |
 *
 *  After complete fragmentation buf chain looks like below
 *
 *  |fh + p + e | fh + p + e | fh + p + e | fh + p + e | fh + p + e |
 *
 *  Space in every fragment is because fragment payload should be multiple
 *  of 8 octets (we have predefined packets at compile time, data packet mtu
 *  is set already).
 *
 *  Create the first fragment, add fragmentation header and insert
 *  fragment at beginning of pkt, move data from next fragments to
 *  previous one, from here on insert fragmentation header and adjust
 *  data on subsequent packets.
 */
ch  : compressed (IPv6) header(s)
fh  : fragment header (dispatch + size + tag + [offset])
p   : payload (first fragment holds IPv6 hdr as payload)
e   : empty space

Input to ieee802154_fragment() buf chain looks like below



After complete fragmentation buf chain looks like below



Space in every fragment is because fragment payload should be multiple
of 8 octets (we have predefined packets at compile time, data packet mtu
is set already).

Create the first fragment, add fragmentation header and insert
fragment at beginning of pkt, move data from next fragments to
previous one, from here on insert fragmentation header and adjust
data on subsequent packets.
ch : compressed ( IPv6 ) header ( s ) fh : fragment header ( dispatch + size + tag + [ offset ] ) p : payload ( first fragment holds IPv6 hdr as payload ) e : empty space Input to ieee802154_fragment () buf chain looks like below After complete fragmentation buf chain looks like below Space in every fragment is because fragment payload should be multiple of 8 octets ( we have predefined packets at compile time data packet mtu is set already ) . Create the first fragment add fragmentation header and insert fragment at beginning of pkt move data from next fragments to previous one from here on insert fragmentation header and adjust data on subsequent packets .
bool ieee802154_fragment(struct net_pkt *pkt, int hdr_diff)
{
	struct net_buf *frag;
	struct net_buf *next;
	u16_t processed;
	u16_t offset;
	u16_t size;
	u8_t room;
	u8_t move;
	u8_t max;
	bool first;
	if (!pkt || !pkt->frags) {
		return false;
	}
	if (!pkt->frags->frags) {
		return true;
	}
	size = net_pkt_get_len(pkt) + hdr_diff;
	room = 0;
	offset = 0;
	processed = 0;
	first = true;
	datagram_tag++;
	next = pkt->frags;
	pkt->frags = NULL;
	while (1) {
		if (!room) {
			frag = prepare_new_fragment(pkt, offset);
			if (!frag) {
				return false;
			}
			set_up_frag_hdr(frag, size, offset);
			max = calc_max_payload(pkt, frag, offset);
			processed += max;
			offset = processed >> 3;
		}
		move = move_frag_data(frag, next, max, first, hdr_diff, &room);
		first = false;
		compact_frag(next, move);
		if (!next->len) {
			next = net_pkt_frag_del(pkt, NULL, next);
			if (!next) {
				break;
			}
		}
	}
	return true;
}
bool ieee802154_fragment ( struct net_pkt * pkt , int hdr_diff ) { struct net_buf * frag ; struct net_buf * next ; u16_t processed ; u16_t offset ; u16_t size ; u8_t room ; u8_t move ; u8_t max ; bool first ; if ( ! pkt || ! pkt -> frags ) { return false ; } if ( ! pkt -> frags -> frags ) { return true ; } size = net_pkt_get_len ( pkt ) + hdr_diff ; room = 0 ; offset = 0 ; processed = 0 ; first = true ; datagram_tag ++ ; next = pkt -> frags ; pkt -> frags = NULL ; while ( 1 ) { if ( ! room ) { frag = prepare_new_fragment ( pkt , offset ) ; if ( ! frag ) { return false ; } set_up_frag_hdr ( frag , size , offset ) ; max = calc_max_payload ( pkt , frag , offset ) ; processed += max ; offset = processed >> 3 ; } move = move_frag_data ( frag , next , max , first , hdr_diff , & room ) ; first = false ; compact_frag ( next , move ) ; if ( ! next -> len ) { next = net_pkt_frag_del ( pkt , NULL , next ) ; if ( ! next ) { break ; } } } return true ; }
ch  : compressed (IPv6) header(s)
  fh  : fragment header (dispatch + size + tag + [offset])
  p   : payload (first fragment holds IPv6 hdr as payload)
  e   : empty space
ch : compressed ( IPv6 ) header ( s ) fh : fragment header ( dispatch + size + tag + [ offset ] ) p : payload ( first fragment holds IPv6 hdr as payload ) e : empty space
/* If it is a single fragment do not add fragmentation header */ /* Datagram_size: total length before compression */ /* First fragment has compressed header, but SIZE and OFFSET
	 * values in fragmentation header are based on uncompressed
	 * IP packet.
	 */ /* Prepare new fragment based on offset */ /* Set fragmentation header in the beginning */ /* Calculate max payload in multiples of 8 bytes */ /* Calculate how much data is processed */ /* Move data from next fragment to current fragment */ /* Compact the next fragment */