Information on skb_copy_datagram_iovec()
This writing is based on Linux kernel 2.6.21.5.
This function is defined in net/core/datagram.c. The main task of this function is to copy the data of an skb in the kernel-space to a memory location in the user-space. Usually, this function will be the one who finally satisfies recvmsg() system call and its variants, which are recv() and recvfrom(). Nevertheless, this main task also carries one unique responsibility: taking care of fragmentation.
When fragmented data contained in a linked-list of skbs need to be delivered as a whole into the user-space, this function is the one who is responsible to do that. In other words, it will be in vain to expect this functionality to be seen in reassembly function such as ip_frag_reasm(). This function is a recursive function when it needs to take care of fragmentation. More importantly, this function requires that the first skb points its next fragment through its skb_shinfo(skb)->frag_list. The next skb that is pointed by skb_shinfo(skb)->frag_list must point to the next skb in the linked-list through its next field because its skb_shinfo(skb)->frag_list must point to real data.
In general, this function works as follows:
1) Copy skb->data to user-space.
2) Copy all skb_shinfo(skb)->frags to user-space.
3) a. Traverse skb_shinfo(skb)->frag_list as list.
b. skb_copy_datagram_iovec(list, offset - start, to, copy).
c. Traverse list->next while not NULL.
d. Go back to (3.b) to perform recursion as necessary.
This function also has some variables whose relationships are shown below:
Modified by skb_pull() constant
____/\__ ______/\_____
start = skb->len - skb->data_len
_____________________________/\____________________________
offset copy
_____/\_____ ______________________/\______________________
+------------+----------------------------------------------+
| header | payload |
+------------+----------------------------------------------+
^^^^^^^^^^^^^|^^^^^^^^^^^^
V
len