802.1Q VLAN简介

1 VLAN

1.1 VLAN的定义

以太网是一种基于CSMA/CD(Carrier Sense Multiple Access/Collision Detection)的共享通讯介质的数据网络通讯技术。当主机数目较多时会导致冲突严重、广播泛滥、性能显著下降甚至造成网络不可用等问题。通过交换机实现LAN互连虽然可以解决冲突严重的问题,但仍然不能隔离广播报文和提升网络质量。

在这种情况下出现了VLAN技术,这种技术可以把一个LAN划分成多个逻辑的VLAN,每个VLAN是一个广播域,每个广播域都有一个编号(1-4096)。VLAN内的主机间通信就和在一个LAN内一样,而VLAN间则不能直接互通,这样广播报文就被限制在一个VLAN内。

​ 图 1-1-1 VLAN的定义

1.2 VLAN的作用

  • 限制广播域:广播域被限制在VLAN ID内,节省了带宽,提高了网络处理能力。
  • 增强局域网的安全性:VLAN间的二层报文是相互隔离的,即一个VLAN内的用户不能和其它VLAN内的用户直接通信,如果不同VLAN要进行通信,则需通过路由器或三层交换机等三层设备。
  • 灵活构建虚拟工作组:用VLAN可以划分不同的用户到不同的工作组,同一工作组的用户也不必局限于某个固定的物理范围,网络构建和维护更方便灵活。

1.3 VLAN数据帧格式

目前VLAN协议格式有两种: ISL 和 802.1Q。ISL是思科研发的Dot1Q标准,产生于802.1Q标准之前,只有思科的设备使用。802.1Q是IEEE标准的VLAN协议,也是现在的主流VLAN技术,本文以802.1Q标注介绍VLAN报文格式,如需了解ISL格式,可浏览思科网站相关介绍。

正常的802.3 报文头和带VLAN的报文对比如下:

Packet type Preamble Start frame delimiter Destination MAC address Source MAC address dot1q identifier tag type (4 bits) vlan ID (12 bits) packet type field data padding FCS
Normal ethernet tcp packet 10101010 (56 alternating bits) 10101011 00:10:C6:C0:61:CD 00:13:CE:47:06:86 not present not present not present 0x800
VLAN packet 10101010 (56 alternating bits) 10101011 00:10:C6:C0:61:CD 00:13:CE:47:06:86 0x8100 QOS bits VLAN ID 0x800

两种报文的主要差别是VLAN 报文在二层头的MAC地址后面加入了VLAN Tag,其它都是一致的,所以判别是否是VLAN报文,只要判断二层头里TYPE类型是否有TPID(默认0X8100)即可。

传统的以太网数据帧在目的MAC地址和源MAC地址之后封装的是上层协议的类型字段,就是untagged帧,如图1-3-1所示

​ 图1-3-1 以太网帧结构

VLAN数据帧是在类型字段前加上802.1Q的tag,也就是tagged帧,如图1-3-2所示

​ 图3 VLAN数据帧

802.1Q Tag中各字段的含义如下表所示:

字段 长度 含义 取值
TPID 2Byte Tag Protocol Identifier(标签协议标识符),表示数据帧类型。 默认取值为0x8100时表示IEEE 802.1Q的VLAN数据帧。如果不支持802.1Q的设备收到这样的帧,会将其丢弃。
PRI 3bit Priority,表示数据帧的802.1p优先级。 取值范围为0~7,值越大优先级越高。当网络阻塞时,交换机优先发送优先级高的数据帧,主要在Qos的优先级中使用。
CFI 1bit Canonical Format Indicator(标准格式指示位),表示MAC地址在不同的传输介质中是否以标准格式进行封装,用于兼容以太网和令牌环网。 CFI取值为0表示MAC地址以标准格式进行封装,为1表示以非标准格式封装。在以太网中,CFI的值为0。
VID 12bit VLAN ID,表示该数据帧所属VLAN的编号。 12bit的VID取值范围是0~4095。由于0和4095为协议保留取值,所以VID的有效取值范围是1~4094。

1.4 端口模式类型

根据端口连接对象及对收发数据帧处理的不同,以太网端口分为Access/Trunk/Hybrid三种模式。

  • Access 模式

    Access模式仅允许唯一的 VID 通过本端口,即端口的PVID。Access模式一般用于和不能识别tag的用户终端(用户主机、服务器等)相连的端口,或者不需要区分不同VLAN成员时使用。

    1. ingress:没有tag报文,打上端口pvid;带tag报文,直接丢弃;
    2. egress: tag=VID,剥离tag发送;tag != VID, 直接丢弃;
  • Trunk 模式

    Trunk接口一般用于连接交换机、路由器、AP以及可同时收发Tagged帧和Untagged帧的语音终端。它可以允许多个VLAN的帧带Tag通过,但只允许一个VLAN的帧从该类接口上发出时不带Tag(即剥除Tag)。

    1. ingress: 没有tag报文,打上端口pvid;带标签tag 匹配vlan id,不匹配的直接丢弃;
    2. egress:tag=pvid,剥离tag发送;tag 匹配端口的vlan id转发,不匹配的直接丢弃;
  • Hybrid 模式

    Hybrid接口既可以用于连接不能识别Tag的用户终端(如用户主机、服务器等)和网络设备(如Hub),也可以用于连接交换机、路由器以及可同时收发Tagged帧和Untagged帧的语音终端、AP。它可以允许多个VLAN的帧带Tag通过,且允许从该类接口发出的帧根据需要配置某些VLAN的帧带Tag(即不剥除Tag)、某些VLAN的帧不带Tag(即剥除Tag)。

    假设Hybrid口的配置,tag vlan N/ untag vlan M/ pvid vlan L。

    1. ingress:没有tag报文,打上端口pvid L,带tag报文匹配vlan N,不匹配的直接丢弃;
    2. egress:首先先匹配vlan N, 匹配直接转发;不是则匹配vlan M,匹配剥离tag转发;不是则匹配pvid L,匹配剥离tag转发;以上都不匹配直接丢弃;

    Hybrid接口和Trunk接口在很多应用场景下可以通用,但在某些应用场景下,必须使用Hybrid接口。比如一个接口连接不同VLAN网段的场景中,因为一个接口需要给多个Untagged报文添加Tag,所以必须使用Hybrid接口。

1.5 Linux 内核的 802.1Q模块

1.5.1 vlan在协议层面是如何工作的

为了支持VLAN功能,创建了一种特别的以太网报文,该报文相比普通以太网报文新增了一个额外的报文头,用于识别vlan报文。对于access端口,switch会在ingress增加该报文头;对于trunk端口,进来的报文会直接带有vlan报文头,如果没有,会默认加上端口的PVID(native vlan)。

基本的以太网报文:

Ethernet/IP/tcp/

trunk/access端口ingress的以太网报文:

Ethernet/VLAN/IP/tcp/

1.5.2 vlan在linux kernel是如何工作的

1.5.2.1 vconfig 工具

通过使用vconfig 工具,你可以创建一个VLAN子端口。如果你配置连接到该端口的switch端口eth1是可用发送带vlan 810 和820的报文,配置如下:

 vconfig add eth0 810
 vconfig add eth0 820

配置后,“eth0.810” 和 “eth0.820” 两个虚拟端口将被创建,带有相应VLAN的报文将被送到对应的虚拟口处理,就像接到了不同的网络。所以,你需要给他们配上不同的IP地址区别两个端口。

使能不同vlan间的routing功能:

 echo 1 > /proc/sys/net/ipv4/ip_forward

通过如下的路由配置,两台设备可以相互通信:

 (on the client devices in an access port :)
 route add <network on other vlan> netmask <the netmask of the network> gw <the ip of the vlan router on the correct vlan>

1.5.3 kernel的实现

1.5.3.1 收包处理流程

当一个NIC驱动收到一个报文,首先它将为收到的报文创建一个sk_buff 结构体(include/linux/skbuff.h), 然后将该结构体的dev成员指向NIC对应的接口,最后报文将会被送到netif_rx(net/core/dev.c)或者receive_skb(net/core/dev.c)处理。基本的收包处理流程如下:

 struct sk_buff * skb;
 skb = dev_alloc_skb();
 /* fill in some data in the skb */
 skb->dev = my interface struct
 netif_rx(skb);

当一个端口接受一个带VLAN的报文(如果接口有vlan加速),调用将由vlan_hwaccel_rx替代netif_rx:

 vlan_hwaccel_rx(skb, vlan_group, vlan_tag)

缩写

PVID(Port VLAN ID Default)

参考文档

https://wiki.linuxfoundation.org/networking/vlan

http://www.candelatech.com/~greear/vlan.html

posted @ 2023-02-03 16:36  Silly-man  阅读(3301)  评论(0编辑  收藏  举报