VLAN在linux中的实现

1         VLANlinux中的实现

1.1         VLAN代码的位置

Vlanlinux的代码中位于 linux2.6.10/net/8021q,主要包含vlan.c

Vlan_dev.c vlan设备相关的处理函数,比如设备上的报文发送、接收与报文头处理函数 vlan_dev_hard_start_xmitvlan_skb_recvvlan_dev_rebuild_header;设备的ioctl配置vlan_dev_ioctl函数等。

Vlan.cvlan模块初始化,vlan设备的注册register_vlan_device、注销unregister_vlan_deviceioctl入口函数vlan_ioctl_handler等。

Vlanproc.c:提供proc文件系统的访问接口。

另外在linux/include里面还有一个if_vlan.h文件,提供了vlan对外的必要接口。

 

1.2         vlan数据的收发

在接收中断的下半部(下半部的主要工作就是遍历有数据帧等待接收的数据链表,对于每个设备执行它对应的poll函数)的处理函数netif_receive_skb中,对报文的处理做了实现。

 

int netif_receive_skb(struct sk_buff *skb)

{

       struct packet_type *ptype, *pt_prev;

                                

     //进行sniffer等协议的报文上报

       list_for_each_entry_rcu(ptype, &ptype_all, list) {

              if (!ptype->dev || ptype->dev == skb->dev) {

                     if (pt_prev)

                            ret = deliver_skb(skb, pt_prev);

                     pt_prev = ptype;

              }

       }

 

    //进行数据帧的桥处理:如果是vlan报文直接退出

       if (handle_bridge(&skb, &pt_prev, &ret))

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

                     pt_prev = ptype;

              }

       }

}

 

deliver函数的处理为

static __inline__ int deliver_skb(struct sk_buff *skb,

                              struct packet_type *pt_prev)

{

       atomic_inc(&skb->users);

       return pt_prev->func(skb, skb->dev, pt_prev);

}

 

对于VLAN报文就是static struct packet_type vlan_packet_type = {

       .type = __constant_htons(ETH_P_8021Q),

       .func = vlan_skb_recv, /* VLAN receive method */

};

 

上文中提到的一个重要的数据结构就是 struct packet_type

struct packet_type {

       unsigned short              type;       /* This is really htons(ether_type).       */

       struct net_device           *dev;      /* NULL is wildcarded here          */

       int                  (*func) (struct sk_buff *, struct net_device *,

                                    struct packet_type *);

       void               *af_packet_priv;

       struct list_head       list;

};

 

1.3         Vlan的初始化过程

在模块初始化vlan_proto_init时执行了dev_add_pack(&vlan_packet_type);vlan协议的报文类型变量vlan_packet_type添加到ptype_base数组里面去,当桥处理执行时发现报文需要继续处理,那么就进入了vlan_skb_recv函数。

在这个函数中,首先根据数据帧的VLANID和实设备构造出一个虚设备,然后将报文中的tag去掉,将这个skb重新挂入skb队列,当系统在此调度的时候,进入桥代码之后就是一个没有tag的报文,就可以进行桥代码的处理了。

在进行vlan数据报文发送时比较简单。由于发送时指定的设备为需设备,这个时候该设备的hard_start_xmit就是       vlan_dev_hard_start_xmit

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值