http://blog.csdn.net/nerdx/article/details/12209043
-
-
-
1.1 int __skb_linearize(struct sk_buff *skb, int gfp_mask)
-
{
-
unsigned int size;
-
u8 *data;
-
long offset;
-
struct skb_shared_info *ninfo;
-
int headerlen = skb->data - skb->head;
-
int expand = (skb->tail + skb->data_len) - skb->end;
-
-
if (skb_shared(skb))
-
BUG();
-
-
-
if (expand <= 0)
-
expand = 0;
-
-
size = skb->end - skb->head + expand;
-
-
size = SKB_DATA_ALIGN(size);
-
-
data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
-
if (!data)
-
return -ENOMEM;
-
-
if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len))
-
BUG();
-
-
-
ninfo = (struct skb_shared_info*)(data + size);
-
atomic_set(&ninfo->dataref, 1);
-
ninfo->tso_size = skb_shinfo(skb)->tso_size;
-
ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
-
-
ninfo->nr_frags = 0;
-
ninfo->frag_list = NULL;
-
-
offset = data - skb->head;
-
-
-
skb_release_data(skb);
-
-
-
skb->head = data;
-
skb->end = data + size;
-
-
skb->h.raw += offset;
-
skb->nh.raw += offset;
-
skb->mac.raw += offset;
-
skb->tail += offset;
-
skb->data += offset;
-
-
skb->cloned = 0;
-
-
skb->tail += skb->data_len;
-
skb->data_len = 0;
-
return 0;
-
}
-
-
1.2 SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & \
-
~(SMP_CACHE_BYTES - 1))
-
-
-
1.3 int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
-
{
-
int i, copy;
-
-
int start = skb_headlen(skb);
-
-
if (offset > (int)skb->len - len)
-
goto fault;
-
-
if ((copy = start - offset) > 0) {
-
if (copy > len)
-
copy = len;
-
-
memcpy(to, skb->data + offset, copy);
-
if ((len -= copy) == 0)
-
return 0;
-
offset += copy;
-
to += copy;
-
}
-
-
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-
int end;
-
-
-
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+
-
offset - start, copy);
-
-
kunmap_skb_frag(vaddr);
-
-
if ((len -= copy) == 0)
-
return 0;
-
offset += copy;
-
to += copy;
-
}
-
start = end;
-
}
-
-
if (skb_shinfo(skb)->frag_list) {
-
struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
-
for (; list; list = list->next) {
-
int end;
-
-
BUG_TRAP(start <= offset + len);
-
-
end = start + list->len;
-
if ((copy = end - offset) > 0) {
-
if (copy > len)
-
copy = len;
-
-
if (skb_copy_bits(list, offset - start,
-
to, copy))
-
goto fault;
-
if ((len -= copy) == 0)
-
return 0;
-
offset += copy;
-
to += copy;
-
}
-
start = end;
-
}
-
}
-
if (!len)
-
return 0;
-
-
fault:
-
return -EFAULT;
-
}
-
-
2.1 static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
-
{
-
-
if (likely(len <= skb_headlen(skb)))
-
return 1;
-
-
if (unlikely(len > skb->len))
-
return 0;
-
-
return __pskb_pull_tail(skb, len-skb_headlen(skb)) != NULL;
-
}
-
-
-
-
2.2 unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta)
-
{
-
int i, k, eat = (skb->tail + delta) - skb->end;
-
-
if (eat > 0 || skb_cloned(skb)) {
-
-
if (pskb_expand_head(skb, 0, eat > 0 ? eat + 128 : 0,
-
GFP_ATOMIC))
-
return NULL;
-
}
-
-
if (skb_copy_bits(skb, skb_headlen(skb), skb->tail, delta))
-
BUG();
-
-
if (!skb_shinfo(skb)->frag_list)
-
goto pull_pages;
-
-
-
eat = delta;
-
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-
-
if (skb_shinfo(skb)->frags[i].size >= eat)
-
-
goto pull_pages;
-
eat -= skb_shinfo(skb)->frags[i].size;
-
}
-
-
if (eat) {
-
struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
struct sk_buff *clone = NULL;
-
struct sk_buff *insp = NULL;
-
-
do {
-
-
if (!list)
-
BUG();
-
-
if (list->len <= eat) {
-
-
eat -= list->len;
-
-
list = list->next;
-
-
insp = list;
-
} else {
-
-
-
if (skb_shared(list)) {
-
clone = skb_clone(list, GFP_ATOMIC);
-
if (!clone)
-
return NULL;
-
-
-
insp = list->next;
-
list = clone;
-
} else {
-
-
insp = list;
-
}
-
-
if (!pskb_pull(list, eat)) {
-
if (clone)
-
kfree_skb(clone);
-
return NULL;
-
}
-
break;
-
}
-
} while (eat);
-
-
-
while ((list = skb_shinfo(skb)->frag_list) != insp) {
-
skb_shinfo(skb)->frag_list = list->next;
-
-
kfree_skb(list);
-
}
-
-
if (clone) {
-
clone->next = list;
-
skb_shinfo(skb)->frag_list = clone;
-
}
-
}
-
-
pull_pages:
-
eat = delta;
-
k = 0;
-
-
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-
if (skb_shinfo(skb)->frags[i].size <= eat) {
-
put_page(skb_shinfo(skb)->frags[i].page);
-
eat -= skb_shinfo(skb)->frags[i].size;
-
} else {
-
skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
-
if (eat) {
-
skb_shinfo(skb)->frags[k].page_offset += eat;
-
skb_shinfo(skb)->frags[k].size -= eat;
-
eat = 0;
-
}
-
k++;
-
}
-
}
-
skb_shinfo(skb)->nr_frags = k;
-
-
skb->tail += delta;
-
skb->data_len -= delta;
-
-
return skb->tail;
-
}
-
-
3.1 static inline int skb_shared(const struct sk_buff *skb)
-
{
-
return atomic_read(&skb->users) != 1;
-
}
阅读(2260) | 评论(0) | 转发(0) |