struct iwl_cmd_meta *out_meta){inti;for(i =0; i < skb_shinfo(skb)->nr_frags; i++) {constskb_frag_t*frag = &skb_shinfo(skb)->frags[i];dma_addr_ttb_phys;inttb_idx;if(!skb_frag_size(frag))continue; tb_phys = skb_frag_dma_map(trans->dev, frag,0,skb_frag_size(frag), ...
if (skb_shinfo(skb)->frags[i].size >= eat) //在frags数组中的数据量可以满足delta时,则只释放frags即可 goto pull_pages; eat -= skb_shinfo(skb)->frags[i].size; } //eat仍不为0,说明从frag_list中进行了拷贝,释放frag_list if (eat) { struct sk_buff *list = skb_shinfo(skb)->frag_...
remaining = *sync_size;for(i =0; remaining >0; i++) {skb_frag_t*frag = &record->frags[i]; __skb_frag_ref(frag); sg_set_page(sg_in + i, skb_frag_page(frag), skb_frag_size(frag), frag->page_offset); remaining -= skb_frag_size(frag);if(remaining <0) sg_in[i].lengt...
}//接下来的数据从skb_shinfo的frags数组中进行拷贝for(i =0; i < skb_shinfo(skb)->nr_frags; i++) {intend;//遍历fragsend = start + skb_shinfo(skb)->frags[i].size;if((copy = end - offset) >0) { u8*vaddr;if(copy >len) copy=len;//映射skb的frag到内核地址空间vaddr = kmap_s...
skb_frag_size_add(fragto, skb_frag_size(fragfrom)); __skb_frag_unref(fragfrom, false);__skb_frag_unref(fragfrom, skb->pp_recycle); }/* Reposition in the original skb */ @@ -5285,6 +5290,13 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, if (skb_...
skb->head = data; skb->data = data; skb->end = skb->tail + size; ... } 第二就是什么时候会使用no-linear,frag_list在处理IP分片时被使用,可以查看内核中的ip_fragment->ip_do_fragment函数,[1][2][3]中对这个部分的描述并不够详细,或者说对frags对描述还不够详细。
pos+=size; } skb_shinfo(skb1)->nr_frags =k; } pskb_expand_head pskb_pull(): 对于带有frag page的分片skb来说,data指针往下移动,可能会导致线性区越界,因此需要判断是否线性区有足够的空间用来pull操作,如果空间不够,那么需要执行linearize,重构线性区,把一部分frags中的数据移动到线性区中来操作。
end = start + skb_shinfo(skb)->frags[i].size; if ((copy = end - offset) > 0) { u8 *vaddr; if (copy > len) copy = len; vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]); memcpy(to, vaddr + skb_shinfo(skb)->frags[i].page_offset+ ...
data= kmalloc_reserve(size, gfp_mask, node, &pfmemalloc); if(!data) gotonodata; // kmalloc(size) 可能会给我们比要求更多的空间。将 skb_shared_info 准确地放在分配区域的末尾,以在重新分配之前允许最大可能地填充。 // 这个size就是实际可用使用的data,这里的ksize相当于malloc_size,size就是实际线...
if (!skb_shinfo(skb)->frag_list) goto pull_pages; // 后面的操作都是在要腾出delta大小的线性缓冲区,腾出空间后就可以拉长skb包页面 /* Estimate size of pulled pages. */ eat = delta; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ...