一、 Linux对VLAN数据的处理
(1)VLAN初始化
static struct packet_type vlan_packet_type __read_mostly = {
.type =cpu_to_be16(ETH_P_8021Q),
.func = vlan_skb_recv, /*VLAN receive method */
};
vlan_proto_init调用dev_add_pack(&vlan_packet_type)函数进行VLAN的注册,把ETH_P_8021Q 处理函数挂在ptype_base下,即数据接收的VLAN的入口函数为vlan_skb_recv
(2)VLAN数据处理
内核中的vlan模块就是工作在协议栈里,通过注册dev_add_pack注册了8021Q的协议类型,netif_receive_skb->__netif_receive_skb遍历所有的协议类型时发现了它,于是进入了vlan的接收函数vlan_skb_recv(vlan_dev.c),这个函数里剥离vlan层,重置以太网层的proto,重新调用netif_rx进入真正的协议栈处理流程。
对于Linux,无论什么数据包通过网卡驱动后都会进入__netif_receive_skb函数。该函数中对VLAN的处理如下:
static int__netif_receive_skb(struct sk_buff *skb)
{
… …
//遍历ptye_all链表
list_for_each_entry_rcu(ptype, &ptype_all,list) {
if (ptype->dev == null_or_orig || ptype->dev ==skb->dev ||
ptype->dev ==orig_dev) {
if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
}
}
… …
// bridge逻辑
/* Handle special case of bridge or macvlan */
rx_handler = rcu_dereference(skb->dev->rx_handler);
if (rx_handler) {
if (pt_prev) {
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev &