Linux协议栈对vlan的处理

Linux内核中vlan处理机制解析
这篇博客探讨了Linux协议栈如何处理vlan报文。网卡驱动在接收到不带VLAN tag的报文后,通过rtl8169_rx_vlan_tag函数将剥离的vlan信息记录到SKB中,以便协议栈后续处理。最终,报文通过__vlan_hwaccel_rx调用netif_receive_skb进入常规接收流程。
(基于linux-2.6.x)

从代码上看,Linux对VLAN的处理方式如下。


1. vlan的处理,主要是依靠网卡本身。
   有的网卡不支持vlan,如老的3com网卡3c501。
   intel的ixgb(PRO/10GbE)和e1000(PRO/1000)网卡是支持vlan的。
   其他的一些网卡驱动,从代码上来看,还未完整支持。
   例如,有个网卡驱动(源码文件:drivers\net\spider_net.c),
   vlan相关代码上的注释上说,/* further enhancement... yet to do */


2. 网卡对vlan的处理
   VLAN tag插入/移除 都是由网卡完成的。
   vlan报文的过滤也是由网卡完成的。
   Linux协议栈通过驱动中的接口,注册vlan相关信息。
   驱动再将这些信息写到芯片中。

   因此,网卡驱动从网卡接收队列中收到的报文,已经不带VLAN tag了。

下面是r8169.c网卡驱动收到报文后,做的部分处理。

由于驱动收到的报文,已经不带vlan tag,因此skb->protocol的值就是普通的以太网类型。

skb->protocol = eth_type_trans(skb, dev);

rtl8169_rx_vlan_tag(desc, skb);

if (likely(polling))
napi_gro_receive(&tp->napi, skb);
else
netif_rx(skb);

dev->stats.rx_bytes += pkt_size;
dev->stats.rx_packets++;

再看看rtl8169_rx_vlan_tag干了什么。下面贴出相关代码:

/**
 * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
 * @skb: skbuff to tag
 * @vlan_tci: VLAN TCI to insert
 *
 * Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest
 */
static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb,
						     u16 vlan_tci)
{
	skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
	return skb;
}

static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
{
	u32 opts2 = le32_to_cpu(desc->opts2);

	if (opts2 & RxVlanTag)
		__vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));

	desc->opts2 = 0;
}

从注释及代码可以看出,就是将vlan_tci记录到skb中,这样协议栈能知道这个报文的vlan信息,从而进行相应的处理。

因为vlan tag被硬件剥掉了,软件不知道vlan信息,因此这里的代码将剥掉的vlan信息记录到SKB中,供协议栈使用。





3. Linux对vlan报文的处理(VLAN tag已经剥掉了)


   上一步的工作完成后,接下来的工作有两种情况。


   a)报文不是vlan报文,则驱动程序调用netif_receive_skb对报文进行处理。
     其处理流程在《Linux协议栈代码阅读笔记(三)报文接收》中有描述。


   b)报文是vlan报文(不过已经不带VLAN tag了),则驱动程序调用vlan_hwaccel_receive_skb对报文进行处理,vlan tag通过     参数传递给vlan_hwaccel_receive_skb。
     vlan_hwaccel_receive_skb则简单的以如下形式调用__vlan_hwaccel_rx。
     __vlan_hwaccel_rx(skb, grp, vlan_tag, 1);


     __vlan_hwaccel_rx先根据vlan tag为报文做优先级赋值。
     然后将低层代码误以为vlan报文的目的mac不是本机的错误纠正过来。

     接下来,__vlan_hwaccel_rx调用netif_receive_skb。这就将处理流程收敛到与a)相同的路线上去了:)





评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值