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) |