讨论一下 skb_copy_bits
时间:2010-09-29
来源:互联网
本帖最后由 Godbach 于 2010-09-29 10:48 编辑
记得通常在 IP 层处理 skb 的时候,如果是线性的,即排除 skb->data_len 不为 0 的情况,copy 数据使用 memcpy 就可以了。
skb_copy_bits也是用来实现 copy 数据的,可以指定偏移和长度。但是其具体实现就不是想象的那么简单了。以下是代码
上面的代码中,简单加了一些注释,可以 skb_copy_bits 中能够用于 copy 数据的地方有三处
(1) 当前 skb 的缓冲区
(2)skb 保存的 shinfo 中对应的 frags 中的数据,以 page 的方式存储;
(3)skb 保存的 shinfo 中对应的 frag_list 中的数据,由于 frag_list 的成员仍然是 sk_buff 结构体,因此这部分数据的 copy 的方式和本函数要实现的功能一致。
因此,有如下问题:
(1)shinfo 中 frags 对应的数据,还有frag_list 中对应的数据,分别是在什么时候被填充的。
(2)这个函数被调用的时机有哪些?
记得通常在 IP 层处理 skb 的时候,如果是线性的,即排除 skb->data_len 不为 0 的情况,copy 数据使用 memcpy 就可以了。
skb_copy_bits也是用来实现 copy 数据的,可以指定偏移和长度。但是其具体实现就不是想象的那么简单了。以下是代码
QUOTE:
/* Copy some data bits from skb to kernel buffer. */
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;
/* Copy header. */ /* 这里进行判断,以确定是否需要copy 头部*/
if ((copy = start - offset) > 0) {
if (copy > len)
copy = len;
skb_copy_from_linear_data_offset(skb, offset, to, copy);
if ((len -= copy) == 0)
return 0;
offset += copy;
to += copy;
}
/* 这个循环是遍历 frags,根据指定的 offset 和 len 进行数据的 copy */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
int end;
BUG_TRAP(start <= offset + len);
end = start + skb_shinfo(skb)->frags.size;
if ((copy = end - offset) > 0) {
u8 *vaddr;
if (copy > len)
copy = len;
vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags);
memcpy(to,
vaddr + skb_shinfo(skb)->frags.page_offset+
offset - start, copy);
kunmap_skb_frag(vaddr);
if ((len -= copy) == 0)
return 0;
offset += copy;
to += copy;
}
start = end;
}
/* 如果还没有 copy 完足够长度的数据,还要遍历 frag_list 继续 copy 数据,而且 copy 数据的方式是递归调用该函数 */
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;
}
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;
/* Copy header. */ /* 这里进行判断,以确定是否需要copy 头部*/
if ((copy = start - offset) > 0) {
if (copy > len)
copy = len;
skb_copy_from_linear_data_offset(skb, offset, to, copy);
if ((len -= copy) == 0)
return 0;
offset += copy;
to += copy;
}
/* 这个循环是遍历 frags,根据指定的 offset 和 len 进行数据的 copy */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
int end;
BUG_TRAP(start <= offset + len);
end = start + skb_shinfo(skb)->frags.size;
if ((copy = end - offset) > 0) {
u8 *vaddr;
if (copy > len)
copy = len;
vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags);
memcpy(to,
vaddr + skb_shinfo(skb)->frags.page_offset+
offset - start, copy);
kunmap_skb_frag(vaddr);
if ((len -= copy) == 0)
return 0;
offset += copy;
to += copy;
}
start = end;
}
/* 如果还没有 copy 完足够长度的数据,还要遍历 frag_list 继续 copy 数据,而且 copy 数据的方式是递归调用该函数 */
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;
}
上面的代码中,简单加了一些注释,可以 skb_copy_bits 中能够用于 copy 数据的地方有三处
(1) 当前 skb 的缓冲区
(2)skb 保存的 shinfo 中对应的 frags 中的数据,以 page 的方式存储;
(3)skb 保存的 shinfo 中对应的 frag_list 中的数据,由于 frag_list 的成员仍然是 sk_buff 结构体,因此这部分数据的 copy 的方式和本函数要实现的功能一致。
因此,有如下问题:
(1)shinfo 中 frags 对应的数据,还有frag_list 中对应的数据,分别是在什么时候被填充的。
(2)这个函数被调用的时机有哪些?
作者: Godbach 发布时间: 2010-09-29
frags 不记得了, frag_list在ip分片重组时被填充的,如果没有线性化即头skb->data_len不为0时就要用这个拷贝了。
作者: shank941 发布时间: 2010-09-29
多谢 LS 的。
frags 估计是和本机发出去的包时有关,从传输层到 IP 层时会读取的
frags 估计是和本机发出去的包时有关,从传输层到 IP 层时会读取的
作者: Godbach 发布时间: 2010-09-29
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28