Android 增加Vlan功能
一、 802.1Q VLAN
- 1 配置 kernel 支持 VLAN
例如Amlogic方案:
M3项目在kernel目录下;M6项目在common目录下运行如下命令:
make menuconfig
Networking support >
Networking options >
<*> 802.1Q VLAN Support
[*] GVRP (GARP VLAN Registration Protocol) support
或直接修改kernel配置文件。
CONFIG_VLAN_8021Q=y
CONFIG_STP=y
CONFIG_GARP=y
- 2 判断kernel是否编译了vlan
在开发板上执行命令:
cat /proc/kallsyms | grep vlan_netdev_ops
如果搜索不到,那kernel中很可能没有把vlan编译进去。
- 3 源码路径
kernel/net/8021q
- 4 添加接口到VLAN中
将eth添加到VLAN 12中:
$ vconfig add eth0 12
WARNING: Could not open /proc/net/vlan/config. Maybe you need to load the 8021q module, or maybe you are not using PROCFS??
ERROR: trying to add VLAN #12 to IF -:eth0:- error: Package not installed
如上信息可能是kernel不支持VLAN。
$ vconfig add eth0 12
WARNING: Could not open /proc/net/vlan/config. Maybe you need to load the 8021q module, or maybe you are not using PROCFS??
Added VLAN with VID == 12 to IF -:eth0:-
或者命令:
ifm vlan add eth0 12
第一次添加VLAN虚拟网卡的时候会出现上述Warning,这是因为/proc/net/vlan/config这个专门用来保存VLAN信息的文件还未创建。
#netcfg
eth0 UP 10.68.7.32/24 0x00001043 00:c0:15:db:9e:09
eth0.12 DOWN 0.0.0.0/0 0x00001002 00:c0:15:db:9e:09
注意: VLAN接口和它所attach的物理接口的MAC地址相同。
在/proc/目录下面的文件都是系统的临时文件,因此重新启动后必定丢失信息,所以在配置并测试VLAN成功后,可以将一些相关命令添加到rc.local这个启动脚本当中去。
$ cat /proc/net/vlan/config
VLAN Dev name | VLAN ID
Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
eth0.12 | 12 | eth0
1.5 退出VLAN
$ vconfig rem eth0.12
Removed VLAN -:eth0.12:-
或者
$ ifm vlan rem eth0.12
- 6 为VLAN接口设定IP地址
ifconfig eth0.12 192.168.0.11 up
ifconfig wlan0.12 192.168.100.1 up
注意: 不是在eth0.12,而是在eth0上抓包。
1.7 实战
- 7.1 两个接口在一个subnet中,并且在同一个VLAN中
在Android设备Dev_A上创建VLAN接口(将eth0添加到VLAN#12中)并配置IP
ifm vlan add eth0 12
ifconfig eth0.12 192.168.0.11 up
在Android设备Dev_B上创建VLAN接口(将eth0添加到VLAN#12中)并配置IP
ifm vlan add eth0 12
ifconfig eth0.12 192.168.0.22 up
在Dev_B上ping Dev_A,可以ping通。
在Dev_A上对eth0用tcpdump抓包,有:
可以看到进来的报文是带802.1Q TAG的,出去的报文不带 TAG。
在PC上用Wireshark抓包,发现不论是Requst还是Reply都没有带TAG。
这是Windows PC的网卡strip了TAG导致的:PC的网卡driver不会检查出去的报文是否有TAG,但总是会丢弃进来的报文中的TAG。
- 7.2 两个接口在一个subnet中,但一个加入到VLAN,另一个未加入
在Android设备Dev_A上创建虚拟接口并配置IP
ifconfig eth0:1 192.168.0.11 up
如何删除虚拟接口?
ifconfig eth0:1 down
在Android设备Dev_B上创建VLAN接口(将eth0添加到VLAN#12中)并配置IP
ifm vlan add eth0 12
ifconfig eth0.12 192.168.0.22 up
在非VLAN设备上用tcpdump抓包。
从VLAN设备上ping 非VLAN设备:
$ ping 192.168.0.11
PING 192.168.0.11 (192.168.0.11) 56(84) bytes of data.
From 192.168.0.22 icmp_seq=1 Destination Host Unreachable
From 192.168.0.22 icmp_seq=2 Destination Host Unreachable
抓包如下:
非VLAN设备没有响应VLAN设备发出的带TAG的ARP请求。这是因为ARP请求中带TAG,但非VLAN设备上根本就没有VLAN接口,该ARP报文被丢弃了。
从非VLAN去ping VLAN设备:
首先清空ARP Cache中和VLAN相关的entry
# busybox arp
? (10.68.12.1) at 00:23:ea:63:b0:c8 [ether] on eth0
? (192.168.0.22) at 00:01:22:54:ef:aa [ether] on eth0
# bb arp -d 192.168.0.22
# bb arp
? (10.68.12.1) at 00:23:ea:63:b0:c8 [ether] on eth0
? (192.168.0.22) at <incomplete> on eth0
在VLAN设备上用tcpdump抓包。
$ ping 192.168.0.22
PING 192.168.0.11 (192.168.0.11) 56(84) bytes of data.
抓包如下:
虽然仍然ping不通。但ARP请求得到了响应。
似乎VLAN设备不应该响应不带TAG的ARP请求。
- 7.3 两个接口在一个subnet中,都加入到VLAN,但VLAN ID不同
在Android设备Dev_A上创建VLAN接口(将eth0添加到VLAN#21中)并配置IP
ifm vlan add eth0 21
ifconfig eth0.21 192.168.0.11 up
在Android设备Dev_B上创建VLAN接口(将eth0添加到VLAN#12中)并配置IP
ifm vlan add eth0 12
ifconfig eth0.12 192.168.0.22 up
在dev_A上用tcpdump抓包。
在Dev_B上ping Dev_A,ping不通。
ping 192.168.0.11
PING 192.168.0.11 (192.168.0.11) 56(84) bytes of data.
From 192.168.0.22 icmp_seq=1 Destination Host Unreachable
抓包如下:
这里Dev_A没有响应Dev-B发出的ARP请求。(ARP请求带有Tag#12,显然Dev_A的eth0不在任何VLAN中,Dev-A的 eth0.21只接受来自VLAN#21的frame)
- 7.4 两个接口不在一个subnet中,但在同一个VLAN中
在Android设备Dev_A上创建VLAN接口(将eth0添加到VLAN#12中)并配置IP
$ busybox route
Kernel IP routing table
Destination Gateway Genmask Flags Iface
10.68.12.0 * 255.255.255.0 U eth0
default 10.68.12.1 0.0.0.0 UG
$ ifm vlan add eth0 12
$ ifconfig eth0.12 192.168.1.11 up
$ busybox route
Kernel IP routing table
Destination Gateway Genmask Flags Iface
192.168.1.0 * 255.255.255.0 U eth0.12
10.68.12.0 * 255.255.255.0 U eth0
default 10.68.12.1 0.0.0.0 UG eth0
$ bb arp
? (10.68.12.1) at 00:23:ea:63:b0:c8 [ether] on eth0
可以看到在路由表中新添了一个entry:当目的地址是192.168.1.0/24时,报文从VLAN接口发送出去。
在Android设备Dev_B上创建VLAN接口(将eth0添加到VLAN#12中)并配置IP
ifm vlan add eth0 12
ifconfig eth0.12 192.168.0.22 up
在Dev_A上对eth0用tcpdump开始抓包。
在Dev_A上ping Dev_B,不能ping通。
$ ping 192.168.0.22
PING 192.168.0.22 (192.168.0.22) 56(84) bytes of data.
抓包如下:
可以看出:
- ICMP Request的Source IP不是eth0.12的IP,而是eth0的IP
- ICMP Request的Dest MAC是Gateway(10.68.12.1)的MAC。
解释如下:
当ping一个IP时,首先根据DestIP来查route table以决定把报文从哪个接口发送出去,当然,找到匹配接口意味着 SourceIP 也就定下来了。现在DestIP和任何一个Entry都不匹配,则选中Default。即从 eth0 上发送到Gateway。也就是说,报文的 DMAC 不是意定的host的MAC,而是Gateway的MAC。
- 7.5 总结
在两个开发板之间测试VLAN,有如下现象:
1. 两个IP在同一个VLAN中,并且在同一个subnet中,可以ping通
2. 两个IP在一个subnet中,但一个加入到VLAN,另一个未加入,无法ping通
3. 两个IP在一个subnet中,都加入到VLAN,但VLAN ID不同,无法ping通
4. 两个IP不在一个subnet中,但在同一个VLAN中,无法ping通