Chinaunix首页 | 论坛 | 博客
  • 博客访问: 131925
  • 博文数量: 24
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 280
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-14 15:19
文章分类

全部博文(24)

文章存档

2014年(6)

2008年(3)

2007年(15)

我的朋友

分类: LINUX

2007-12-14 18:06:00

1. 所谓的L2报文处理
所谓的L2报文处理其实就是识别二层协议的过程.
SKB也分配完成了,接下来该确定此包是何包了吧!
L2报文头的处理主要在函数 : __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) 中完成.

2. SKB TYPE
SKB当然是有类型的,那么现在我们就来得到它的类型吧.
首先我们需要得到L2层的包头, 于是我们又碰到了SKB的一个非常重要的操作 : PULL : skb_pull()函数. 此函数在绝大多数情况下调用如下函数 :
    static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len)
    {
        skb->len -= len;
        BUG_ON(skb->len < skb->data_len);
        return skb->data += len;
    }
我们可以看到,此函数的目的是在SKB的数据区中remove一些数据出去, 系统正是利用这个函数来使得data指针指向下一个协议的header. 而且,我们还可以看出来,skb->len不是固定不变的,它的实际意义是当前data指针所指的数据的长度(skb->len在ISR中 skb_put()函数中被设置, 表示实际收到的字节数).

被skb_pull()函数remove掉的数据其实就是L2的报文头,于是,通过事先保存的skb_pull操作之前的 skb->data指针,我们得到了L2报文头,这时候,我们可以根据L2层地址来判断此包是发给谁的了.
    #define PACKET_HOST        0        /* To us        */
    #define PACKET_BROADCAST    1        /* To all        */
    #define PACKET_MULTICAST    2        /* To group        */
    #define PACKET_OTHERHOST    3        /* To someone else     */
    #define PACKET_OUTGOING        4        /* Outgoing of any type */
    /* These ones are invisible by user level */
    #define PACKET_LOOPBACK        5        /* MC/BRD frame looped back */
    #define PACKET_FASTROUTE    6        /* Fastrouted frame    */

于是,我们利用这些值来对skb->pkt_type进行赋值.

3. SKB PROTOCOL
skb->protocol用来表示此SKB包含的数据所支持的L3层协议是什么. 正常的情况下,这个值可以由L2层包头得到,直接判断L2报文头的h_proto成员的值,如果满足条件则直接返回此值,否则利用一个magic number,即当前skb->data的强制转换为int后的值是否为0xFFFF,如果是则标明这是一个ETH_P_802_3的包,否则直接 返回ETH_P_802_2类型.


4. L2到此为止
我们知道Linux经常被用作网关,路由器,防火墙等设备,很少有用Linux作快速转发设备的(一般都由硬件来实现), 这也是为什么Linux kernel中对L2层处理不时非常牛的原因之一,因为根本没有必要吗!

OK, 进入3层的大部分准备工作都已经完成了,马上要开始探险了.....
阅读(2558) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~