免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8543 | 回复: 9
打印 上一主题 下一主题

【TCP/IP】dev_alloc_skb()为什么要多申请16个字节? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-14 15:47 |只看该作者 |倒序浏览
初学linux的TCP/IP代码,看到这个函数:__dev_alloc_skb(),定义如下:
static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
                          int gfp_mask)
{
    struct sk_buff *skb = alloc_skb(length + 16, gfp_mask);
    if (likely(skb))
        skb_reserve(skb, 16);
    return skb;
}

在调用alloc_skb的时候,第一个参数为什么要加上16个字节? 看资料提到这16个byte是headroom,如果是这样,那为什么只有16个byte呢?

另外,alloc_skb 的实现如下:
struct sk_buff *alloc_skb(unsigned int size, int gfp_mask)
{
    struct sk_buff *skb;
    u8 *data;

    /* Get the HEAD */
    skb = kmem_cache_alloc(skbuff_head_cache,
                   gfp_mask & ~__GFP_DMA);
    if (!skb)
        goto out;

    /* Get the DATA. Size must match skb_add_mtu(). */
    size = SKB_DATA_ALIGN(size);
    data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
    if (!data)
        goto nodata;

    memset(skb, 0, offsetof(struct sk_buff, truesize));
    skb->truesize = size + sizeof(struct sk_buff);
    atomic_set(&skb->users, 1);
    skb->head = data;
    skb->data = data;
    skb->tail = data;
    skb->end  = data + size;

    atomic_set(&(skb_shinfo(skb)->dataref), 1);
    skb_shinfo(skb)->nr_frags  = 0;
    skb_shinfo(skb)->tso_size = 0;
    skb_shinfo(skb)->tso_segs = 0;
    skb_shinfo(skb)->frag_list = NULL;
out:
    return skb;
nodata:
    kmem_cache_free(skbuff_head_cache, skb);
    skb = NULL;
    goto out;
}

其中,size = SKB_DATA_ALIGN(size);表示16bit对齐,不太没明白为什么需要16bit对齐呢?注释上说的是/*Size must match skb_add_mtu().*/,哪位兄弟能帮忙解释一下?

多谢了!

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2008-11-14 16:01 |只看该作者
应该是用于对齐的。LZ仔细搜索一下,之前偶看到过解释

论坛徽章:
0
3 [报告]
发表于 2008-11-14 16:17 |只看该作者
在额外加两个正好对齐+ mac地址14个字节 (对齐)+ IP

论坛徽章:
0
4 [报告]
发表于 2008-11-14 16:30 |只看该作者
唯一的解释就是为了方便扩展,例如在头部加额外的信息而不需要移动或复制整个包

论坛徽章:
0
5 [报告]
发表于 2008-11-14 16:53 |只看该作者
原帖由 Arthur_ 于 2008-11-14 16:17 发表
在额外加两个正好对齐+ mac地址14个字节 (对齐)+ IP

偶太菜,不太明白你的意思。。。
能不能详细说下,16是怎样得出来的?

论坛徽章:
0
6 [报告]
发表于 2008-11-14 17:08 |只看该作者
原帖由 new_learner 于 2008-11-14 16:53 发表

偶太菜,不太明白你的意思。。。
能不能详细说下,16是怎样得出来的?


我也菜, 让我慢点说:
先什么不考虑:
首先L2的地址一共是14(6+6+2)个BYTE:

L2+L3(IP addr)+L4

按照常理L2地址是在L3后加, 所以在ALLOCSKB的时候要留14个BYTE,为了以后给L2用.
但是计算机一般是4字节对齐的, 如果留14个BYTE那么IP只能排在15个byte位子, ip头要经常访问所以这样效率似乎不好.
于是在预留2个(14+2 = 16) 正好让IP头4字节对齐.

自己罗嗦了.=.=

论坛徽章:
0
7 [报告]
发表于 2008-11-14 17:45 |只看该作者
多谢ls几位,特别是Arthur_ 兄~~非常详细:)


还有一个疑问,正如我在顶楼提到的,在alloc_skb()函数里,有这么一句话: size = SKB_DATA_ALIGN(size);
我看《The Linux Networking Architecture》里的解释是:
alloc_skb(size, gpf_mask) allocates memory for a socket buffer structure and the corresponding packet memory. In this case, size specifies the size of the packet data space, where this space will be increased (aligned) to the next 16-bit address.
不太明白为什么要对齐到16-bit呢?计算机是4字节对齐,那16-bit有什么用?而且,注释里对于size = SKB_DATA_ALIGN(size);的解释是:/* Get the DATA. Size must match skb_add_mtu(). */  不太明白意思。

能大概提示一下吗?

论坛徽章:
0
8 [报告]
发表于 2008-11-14 19:37 |只看该作者
>>所以在ALLOCSKB的时候要留14个BYTE,为了以后给L2用.

这种解释有问题,设备是不用这16byte空间的.

下面是一个设备接收数据的例子
    p = dev_alloc_skb(len + 2);
    if (!p) return NULL;

    p->dev = dev;
    skb_reserve(p, 2);       
它自己会reserve 2,保证ip对齐到4字节边界

>>/* Get the DATA. Size must match skb_add_mtu(). */
>>size = SKB_DATA_ALIGN(size);
>>data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);

为了把skb_shared_info放入独立的cache lines,提高效率

[ 本帖最后由 qtdszws 于 2008-11-14 20:44 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2008-11-15 08:35 |只看该作者
原帖由 qtdszws 于 2008-11-14 19:37 发表
>>所以在ALLOCSKB的时候要留14个BYTE,为了以后给L2用.

这种解释有问题,设备是不用这16byte空间的.

下面是一个设备接收数据的例子
    p = dev_alloc_skb(len + 2);
    if (!p) return NULL;

    p- ...


我说L2可能你理解成driver了, 其实我指的是neighbour system(对于IPV4就是ARP)。

cacheline? 能具体说否?
把share_info对齐到4byte难道没有这个cacheline快吗?

论坛徽章:
0
10 [报告]
发表于 2014-10-11 17:20 |只看该作者
本帖最后由 雷锋不谢 于 2014-10-11 17:24 编辑

回复 8# qtdszws


    支持!!!

            alloc_skb的简单代码如下:
        {
                struct sk_buff *skb;
                skb=kemme_cache_alloc(skbuff_head_cache,gfp_mask&~__GFP_DMA);
                。。。。。。
                size=SKB_DATA_ALIGH(size);//主要是为了对其size,适当地把size扩大到边界
                data=kmalloc(size+sizeof(struct skb_shared_info),gfp_mask);
                .....
        }

执行完此函数的布局图如下:


   dev_alloc_skb一般在设备驱动中分配skb的空间,且是在中断模式下,其封装了上面的alloc_skb。
      
       static inline struct sk_buff* dev_alloc_skb(unsigned int length)
        {
                return __dev_alloc_skb(length,GFP_ATOMIC);
        }
        static inline struct sk_buff*__dev_alloc_skb(unsigned int length,int gfp_mask)
        {
                struct sk_buff*skb=alloc_skb(length+16,gfp_mask);
                if(likely(skb))
                        skb_reserve(skb,16);//这个reserver是前面的多申请的16,所以把data tail的位置下移16。
                return skb.
        }
        执行玩此函数的布局如图:

     


     而在一般的驱动中,还会在reserver 2 个字节的位置,例如:

      {
        skb=dev_alloc_skb(length);
        if(skb)
          skb_reserve(skb,2);
       ....
     }
     这是因为,在以太网的头部为14B,如果直接把ip头部接到后面,则ip头部从15B的位置开始,这样不太好,为了对其,就进而预留2B的位置,如图:

     这样就可以看到,ip头部是从16B的位置开始的。。。








您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP