图片来自 RHEL管理在线文档。该文档写的比较清楚,建议参考阅读。
从上到下看一下neutron VLAN模式的大体结构,分为四个层次:
1. 虚拟机。虚拟机的网卡是linux TAP设备。
2. qbrXXX。qbr是一个linux bridge,qbr存在的主要作用是实现openstack的安全组功能。安全组基于iptables。
3. br-int。br-int是一个open Vswitch bridge,类似于物理交换机,能实现管理功能。各个虚拟机的流量都要经过br-int转发。
4. br-ethX(或其他名字)。这个桥也是open Vswitch bridge,它连接了物理网卡,报文从这里与外部沟通。
各个层次之间的连接通过veth pair,即图中的qvbXXX vs. qvoXXX,以及int-br-eth vs. phy-br-eth。
VLAN功能的实现,主要位于br-int和br-ethX。出现在物理接口上的报文,拥有真实VLAN id,通过上层交换机与其他机器通信。br-int的报文,则是分配内部VLAN id,实现虚拟机之间的网络隔离,内部tag对外不可见。
针对不同的网络模式,neutron有对应的处理方法。例如,针对来自br-int的报文,flat模式的处理是,br-ethX 去掉报文的内部 tag,将untagged报文,交给物理网口;VLAN模式的处理是,br-ethX将内部tag转换为外部tag,将tagged报文,交给物理网口。
VLAN模式,上层物理交换机的配置,主要注意以下三点。
1. 计算节点的交换机端口设置为trunk口。
2. 正确设置端口的PVID。
3. 设置端口允许预先划定范围的VLAN报文通过。
试验过程。
- 创建一个neutron vlan网络。
neutron net-create ext-net --router:external --provider:physical_network ph-eth0 --provider:network_type vlan --provider:segmentation_id 1001
设置VLAN id为1001。打了tag 1001的报文将出现在物理线路上。 - 为VLAN网络添加一个子网172.26.0.0/16。
- 创建虚拟机,指定虚拟机网络为上面创建的VLAN网络。这里虚拟机得到IP地址172.26.44.181。
- 登录虚拟机,执行ping命令,ping默认网关172.26.11.254。
- 查看端口情况。
通过id可以获得qbr的名称。# neutron port-list +--------------------------------------+------------------+----------------------------------------------------------------------------------------+ | id | mac_address | fixed_ips | +--------------------------------------+------------------+----------------------------------------------------------------------------------------+ | 193c1ae0-6e79-4e86-9ffc-279e1ddbd27e |fa:16:3e:e2:0d:7d | {"subnet_id": "e72eab60-1b1e-4c56-ae24-32484d8467b3", "ip_address": "172.26.44.181"}
- 查看物理网桥的情况。
# brctl show bridge name bridge id STP enabled interfaces qbr193c1ae0-6e 8000.1ea0b5e378f7 no qvb193c1ae0-6e tap193c1ae0-6e
- 查看流表规则。
内部tag为8,外部tag为1001,br-int和br-eth0各自定义转换规则。# ovs-ofctl dump-flows br-int cookie=0x0, duration=85632.937s, table=0, n_packets=0, n_bytes=0, idle_age=65534, hard_age=65534, priority=3,in_port=224,dl_vlan=1001 actions=mod_vlan_vid:8,NORMAL # ovs-ofctl dump-flows br-eth0 cookie=0x0, duration=85687.037s, table=0, n_packets=84907, n_bytes=3567608, idle_age=0, hard_age=65534, priority=4,in_port=44,dl_vlan=8 actions=mod_vlan_vid:1001,NORMAL
- 用ovs-dpctl查看。
# ovs-dpctl dump-flows skb_priority(0),in_port(54),eth(src=fa:16:3e:e2:0d:7d,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=172.26.44.181/255.255.255.255,tip=172.26.11.254/255.255.255.255,op=1/0xff,sha=fa:16:3e:e2:0d:7d/00:00:00:00:00:00,tha=00:00:00:00:00:00/00:00:00:00:00:00), packets:21231, bytes:891702, used:0.080s, actions:push_vlan(vid=8,pcp=0),4,46,1,pop_vlan,49 skb_priority(0),in_port(16),eth(src=fa:16:3e:e2:0d:7d,dst=ff:ff:ff:ff:ff:ff),eth_type(0x8100),vlan(vid=8,pcp=0),encap(eth_type(0x0806),arp(sip=172.26.44.181/255.255.255.255,tip=172.26.11.254/255.255.255.255,op=1/0xff,sha=fa:16:3e:e2:0d:7d/00:00:00:00:00:00,tha=00:00:00:00:00:00/00:00:00:00:00:00)), packets:21231, bytes:891702, used:0.081s, actions:pop_vlan,push_vlan(vid=1001,pcp=0),2,15
- 用tcpdump抓包。先看一下qbr。
这是没有打tag的普通arp报文。# tcpdump -ei qbr193c1ae0-6e -p arp 15:19:40.956384 fa:16:3e:e2:0d:7d (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 172.26.11.254 tell 172.26.44.181, length 28
- 用tcpdump抓包。看一下br-eth0和br-int。
在br-eth0上出现VLAN 1001报文,在br-int上出现VLAN 8报文。# tcpdump -ei br-eth0 -p arp 15:12:33.872337 fa:16:3e:e2:0d:7d (oui Unknown) > Broadcast, ethertype 802.1Q (0x8100), length 46: vlan 1001, p 0, ethertype ARP, Request who-has 172.26.11.254 tell 172.26.44.181, length 28 # tcpdump -ei br-int -p arp 15:15:50.912204 fa:16:3e:e2:0d:7d (oui Unknown) > Broadcast, ethertype 802.1Q (0x8100), length 46: vlan 8, p 0, ethertype ARP, Request who-has 172.26.11.254 tell 172.26.44.181, length 28