免费注册 查看新帖 |

Chinaunix

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

如何从skb里得到vlan id? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-03-05 17:04 |只看该作者 |倒序浏览
假设有一个设备,有两个接口,都是trunk口,不打tag,也不剥tag,但是在bridge里想获得其vlan id.写了下面一个函数,不知道对不对,请各位帮忙看看.
unsigned int br_get_vlan_id(struct sk_buff *skb)
{
    struct vlan_ethhdr *veth;
    unsigned short vlan_TCI;               
    unsigned short vlanid = 0;    //if no config VLAN, default is 0


    if (skb->protocol == htons(ETH_P_8021Q)) {
        veth = (struct vlan_ethhdr *)(skb->data - VLAN_ETH_HLEN);
        vlan_TCI = ntohs(veth->h_vlan_TCI);            
        vlanid = (vlan_TCI & VLAN_VID_MASK);            
    }
   
    return vlanid;
}
其实关键问题是我没有搞清楚在bridge module里,skb->data指向哪儿?二层头还是三层头?
请知道的帮个忙.

论坛徽章:
0
2 [报告]
发表于 2008-03-06 09:20 |只看该作者

回复 #1 happy_flying 的帖子

个人觉得是指向二层头.不敢肯定

论坛徽章:
0
3 [报告]
发表于 2008-03-06 14:25 |只看该作者
eth_type_trans

skb->mac.raw=skb->data;//设置mac指针
//跳过硬件头dst mac6,src mac,protocol 6+6+2=14
skb_pull(skb,dev->hard_header_len);//data指向ip协议头
eth= skb->mac.ethernet;

指向三层头

论坛徽章:
0
4 [报告]
发表于 2008-03-07 11:21 |只看该作者

回复 #3 qtdszws 的帖子

非常感谢qtdszws ,又看了一遍code,确实如你所说,我上面写的不对,应该是:

unsigned short br_get_vlan_id(struct sk_buff *skb)
{
    struct vlan_hdr *vhdr;
    unsigned short vlan_TCI;               
    unsigned short vlanid = 0;    //if no config VLAN, default is 0

   
    if (skb->protocol == ETH_P_8021Q) {    // or htons(ETH_P_8021Q) ??????

        vhdr = (struct vlan_hdr *)(skb->data);   
        vlan_TCI = vhdr->h_vlan_TCI;    // or ntohs(vhdr->h_vlan_TCI) ??????        

        vlanid = (vlan_TCI & VLAN_VID_MASK);            
    }
   
    return vlanid;
}
呵呵,还有一个很弱的问题,如果在mips cpu上,由于是大字节序的,是不是就不需要字节序转换了?

论坛徽章:
0
5 [报告]
发表于 2008-03-07 14:00 |只看该作者
需要ntohs(type)

论坛徽章:
0
6 [报告]
发表于 2008-03-07 16:03 |只看该作者

回复 #5 qtdszws 的帖子

再次感谢qtdszws.
刚弄清楚,这儿是应该加.虽然对于字节序为big-endian的mips cpu来讲( 此时ntoh(x)等价于(x) ),不加也可以.
但是为了可移植性,应该加,这样不管是big-endian还是little-endian,都ok.
PS :mips的字节序好像是可以随意配置的,我们用的是big-endian

呵呵,再借这个机会请教一个bridge module的问题.
当本机自己要往外发一个包时,如果目的设备是bridge,在dev_queue_xmit()里调用dev->hard_start_xmit(skb, dev)就相当于
调用br_dev_xmit(),接着会调用__br_dev_xmit(),在这个函数里,有
skb_pull(skb, ETH_HLEN);
接着依次调用
br_deliver()-->__br_deliver()-->__br_forward_finish()-->__dev_queue_push_xmit()-->dev_queue_xmit(),把包真正发送出去.
在__dev_queue_push_xmit()这个函数里,有
skb_push(skb, ETH_HLEN);
我的问题是,为什么要先pull,再push,看code好像没看出来这么做有什么用?

[ 本帖最后由 happy_flying 于 2008-3-7 16:09 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2008-03-07 18:59 |只看该作者
至于为何调用skb_pull(skb, ETH_HLEN);因为ebtables.c要求skb->data指向三层头.例如ebt_ip.c中
ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
而后面调用skb_push(skb, ETH_HLEN);是因为真的要从接口发送出去了

论坛徽章:
0
8 [报告]
发表于 2008-03-07 22:07 |只看该作者

回复 #7 qtdszws 的帖子

果然如此,我看得还是不仔细,佩服!
不过还有一个疑问,对于vlan包,pull 14 bytes后,指向的是下面struct里的h_vlan_TCI,并不是三层头呀,为什么不pull 18 bytes? 呵呵,问题比较多,还望见谅。

struct vlan_ethhdr {
   unsigned char        h_dest[ETH_ALEN];           /* destination eth addr        */
   unsigned char        h_source[ETH_ALEN];           /* source ether addr        */
   unsigned short       h_vlan_proto;              /* Should always be 0x8100 */
   unsigned short       h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
   unsigned short        h_vlan_encapsulated_proto; /* packet type ID field (or len) */
};

论坛徽章:
0
9 [报告]
发表于 2008-03-10 13:59 |只看该作者
好像没有考虑这种情况

处理bridge在前

        if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))
                goto out;

而对vlan的处理在这里
        type = skb->protocol;
        list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
                if (ptype->type == type &&
                    (!ptype->dev || ptype->dev == skb->dev)) {
                        if (pt_prev)
                                ret = deliver_skb(skb, pt_prev, orig_dev);
                        pt_prev = ptype;
                }
        }
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP