基于OVS的VLAN虚拟化简易实践方案

前言

本实验基于ovs的vlan流表匹配,根据端口进行vlan标签插入。手工配置ovs,使其具有vlan虚拟化方案。

实验拓扑

topo

实验目标

在给定实验拓扑情况下,用vlan得到下列虚拟网段

  • h1–h4为一个vlan_id 0 网段
  • h2–h5为一个vlan_id 1 网段
  • h3–h6为一个vlan_id 2 网段

实验工具

  • mininet
  • 控制器RYU
  • OVS

实验过程

实验拓扑的搭建

from mininet.topo import Topo
class MyTopo(Topo):
def __init__(self):
# initilaize topology
Topo.__init__(self)
# add hosts and switches
host1 = self.addHost('h1')
host2 = self.addHost('h2')
host3 = self.addHost('h3')
host4 = self.addHost('h4')
host5 = self.addHost('h5')
host6 = self.addHost('h6')
switch1 = self.addSwitch('s1')
switch2 = self.addSwitch('s2')
# add links
self.addLink(host1, switch1, 1, 1)
self.addLink(host2, switch1, 1, 2)
self.addLink(host3, switch1, 1, 3)
self.addLink(switch1, switch2, 4, 4)
self.addLink(host4, switch2, 1, 1)
self.addLink(host5, switch2, 1, 2)
self.addLink(host6, switch2, 1, 3)
topos = {'mytopo': (lambda: MyTopo())}

mininet的启用

sudo mn --custom your_topo.py --topo mytopo --mac --switch ovsk,protocols=OpenFlow13 --controller remote

ryu收集数据包的应用及启动(可以帮忙做debug)

#-*- coding: UTF-8 -*-
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ether_types
import logging
class PeiQiaoWang_controller(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(PeiQiaoWang_controller, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPFeaturesRequest)
def switch_features_handle(self, ev):
logging.debug("ing")
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
print msg, datapath, ofproto, parser
#handshake系列
#OFPFeaturesRequest_由控制器发送
#OFPSwitchFeatures
@set_ev_cls(ofp_event.EventOFPSwitchFeatures)
def switch_switch_feature_handle(self, ev):
print "go"
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
print "msg=", msg
# print "msg.datapath_id=", msg.datapath_id
# print "datapath=", datapath
# print "ofproto=", ofproto
# print "parser=", parser
#Switch Configuration系列
#OFPSetConfig
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def packet_in_handle(self, ev):
logging.info("packetin")
msg = ev.msg
print ev.msg
in_port = msg.match['in_port']
pkt = packet.Packet(msg.data)
print pkt.protocols
print type(pkt.protocols)
# print pkt.data
# print type(pkt.data)
# print pkt.ethernet.dst_ip
print type(pkt[1])

启动:

ryu-manage --obeserve-links ./your_app.py

OVS流表手动下发

s1:

sudo ovs-ofctl -O OpenFlow13 add-flow s1 priority=1,in_port=1,actions=push_vlan:0x8100,set_field:4096-\>vlan_vid,output:4
sudo ovs-ofctl -O OpenFlow13 add-flow s1 priority=1,in_port=2,actions=push_vlan:0x8100,set_field:4097-\>vlan_vid,output:4
sudo ovs-ofctl -O OpenFlow13 add-flow s1 priority=1,in_port=3,actions=push_vlan:0x8100,set_field:4098-\>vlan_vid,output:4
sudo ovs-ofctl -O OpenFlow13 add-flow s1 priority=1,dl_vlan=0,actions=pop_vlan,output:1
sudo ovs-ofctl -O OpenFlow13 add-flow s1 priority=1,dl_vlan=1,actions=pop_vlan,output:2
sudo ovs-ofctl -O OpenFlow13 add-flow s1 priority=1,dl_vlan=2,actions=pop_vlan,output:3
sudo ovs-ofctl -O OpenFlow13 add-flow s1 priority=0,actions=output:controller

s2:

sudo ovs-ofctl -O OpenFlow13 add-flow s2 priority=1,in_port=1,actions=push_vlan:0x8100,set_field:4096-\>vlan_vid,output:4
sudo ovs-ofctl -O OpenFlow13 add-flow s2 priority=1,in_port=2,actions=push_vlan:0x8100,set_field:4097-\>vlan_vid,output:4
sudo ovs-ofctl -O OpenFlow13 add-flow s2 priority=1,in_port=3,actions=push_vlan:0x8100,set_field:4098-\>vlan_vid,output:4
sudo ovs-ofctl -O OpenFlow13 add-flow s2 priority=1,dl_vlan=0,actions=pop_vlan,output:1
sudo ovs-ofctl -O OpenFlow13 add-flow s2 priority=1,dl_vlan=1,actions=pop_vlan,output:2
sudo ovs-ofctl -O OpenFlow13 add-flow s2 priority=1,dl_vlan=2,actions=pop_vlan,output:3
sudo ovs-ofctl -O OpenFlow13 add-flow s2 priority=0,actions=output:controller

tip:

上述流表有一个较坑的地方,就是下发添加vlan标签的地方。我们可以看一下vlan标签的构造:

vlan

而我们的下发的流表

sudo ovs-ofctl -O OpenFlow13 add-flow s2 priority=1,in_port=1,actions=push_vlan:0x8100,set_field:4096-\>vlan_vid,output:4set_field确是指定的4096

原因:其实这里的set_field的值是设置TCI的值,并不是VLAN ID的值,4096其实它的VLAN ID就为0,其中CFI位要置位1,这是由于OVS规定该位一定要为1,而OpenFlow标准并没有指示,其为一个保留字段,但是也有很多OpenFlow交换机指定了该位一定要为1才能生效。

实验结果

可观察得mininet中的pingall情况

mininet_pingall

ryu中收到的未匹配的包情况

ryu_packet

实验总结

感受到了普通网工,一台台机器配置过去的麻烦。