SDN實驗---Mininet實驗(玩轉流表)

一:實驗目的

(一)案例目的

(二)實驗內容

 

(三)網絡拓撲結構 

二:OpenFlow流表實驗準備

(一)使用Python設置網絡拓撲 --- tree_topo.py

from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import RemoteController
from mininet.link import TCLink
from mininet.util import dumpNodeConnections

class MyTopo(Topo):

    def __init__(self):
        super(MyTopo,self).__init__()

        # add host
        Host1 = self.addHost('h1')
        Host2 = self.addHost('h2')
        Host3 = self.addHost('h3')

        switch1 = self.addSwitch('s1')
        switch2 = self.addSwitch('s2')

        self.addLink(Host1,switch1)
        self.addLink(Host2,switch1)
        self.addLink(Host3,switch2)
        self.addLink(switch1,switch2)

topos = {"mytopo":(lambda:MyTopo())}

(二)啓動遠程Ryu控制器

 ryu-manager simple_switch.py  注意,該控制器py文件在app目錄下

# Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
An OpenFlow 1.0 L2 learning switch implementation.
"""


from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_0
from ryu.lib.mac import haddr_to_bin
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ether_types


class SimpleSwitch(app_manager.RyuApp):  不一樣與以前的Ryu實驗,這裏面沒有在交換機初始鏈接時下發默認流表...待思考
    OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]

    def __init__(self, *args, **kwargs):
        super(SimpleSwitch, self).__init__(*args, **kwargs)
        self.mac_to_port = {}

    def add_flow(self, datapath, in_port, dst, src, actions):  下發流表
        ofproto = datapath.ofproto

        match = datapath.ofproto_parser.OFPMatch(
            in_port=in_port,
            dl_dst=haddr_to_bin(dst), dl_src=haddr_to_bin(src))

        mod = datapath.ofproto_parser.OFPFlowMod(
            datapath=datapath, match=match, cookie=0,
            command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,
            priority=ofproto.OFP_DEFAULT_PRIORITY,
            flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
        datapath.send_msg(mod)

 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def _packet_in_handler(self, ev):  交換機向控制器發送數據
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto

        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocol(ethernet.ethernet)

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return
        dst = eth.dst
        src = eth.src

        dpid = datapath.id
        self.mac_to_port.setdefault(dpid, {})

        self.logger.info("packet in %s %s %s %s", dpid, src, dst, msg.in_port)

        # learn a mac address to avoid FLOOD next time.
        self.mac_to_port[dpid][src] = msg.in_port

        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
            out_port = ofproto.OFPP_FLOOD

        actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]

        # install a flow to avoid packet_in next time
        if out_port != ofproto.OFPP_FLOOD:
            self.add_flow(datapath, msg.in_port, dst, src, actions)

        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = datapath.ofproto_parser.OFPPacketOut(
            datapath=datapath, buffer_id=msg.buffer_id, in_port=msg.in_port,
            actions=actions, data=data)
        datapath.send_msg(out)

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def _port_status_handler(self, ev):
        msg = ev.msg
        reason = msg.reason
        port_no = msg.desc.port_no

        ofproto = msg.datapath.ofproto
        if reason == ofproto.OFPPR_ADD:
            self.logger.info("port added %s", port_no)
        elif reason == ofproto.OFPPR_DELETE:
            self.logger.info("port deleted %s", port_no)
        elif reason == ofproto.OFPPR_MODIFY:
            self.logger.info("port modified %s", port_no)
        else:
            self.logger.info("Illeagal port state %s %s", port_no, reason)

(三)Mininet開始啓動網絡拓撲

sudo mn --custom tree_topt.py --topo=mytopo --controller=remote,ip=127.0.0.1,port=6633

注意:應該是主機鏈接發送了數據,致使控制器對網絡進行了拓撲收集,問題同上:SDN實驗---Ryu的應用開發(二)Learning Switch

三:進行OpenFlow流表分析

(一)主要流表操做命令

dpctl dump-flows 查看靜態流表

dpctl del-flows 刪除全部交換機中的流表
dpctl add-flow in_port=1,actions=output:2  添加流表項到全部交換機,注意:通常是成對添加,實現雙方通訊

sh ovs-ofctl del-flows s1 in_port=2  刪除指定交換機的,匹配in_port=2的流表
dpctl del-flows in_port=1 刪除全部交換機中符合in_port=1的流表

dpctl add-flow in_port=2,actions=drop   添加丟棄數據包的流表項

(二)先解決上面問題,是否是啓動Mininet後進行了數據包發送,致使控制器下發流表

從新啓動Ryu和Mininet,直接查看交換機中是否有流表.

1.先啓動交換機,查看流表,爲空

2.啓動控制器,以後再查看交換機中流表信息,依舊爲空

3.主機使用pingall命令後,查看流表,發生變化

已解決。可是交換機是如何設置默認流表當不知道packet如何處理的時候發生給控制器?若是這是默認動做,那麼咱們以前Ryu實驗中爲什麼要實現 @set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONFIG_DISPATCHER) def switch_features_handler(self,ev):    ?????
通過啓動hub.py在控制器上,進行測試,發現會進入switch_features_handler,而且會下發默認流表---因此說,咱們能夠不用設置這個默認流表也能夠,可是這個函數中,咱們能夠設置一些其餘的流表進行控制---因此說仍是比較有用的

注意從(三)開始的實驗咱們須要關閉控制器Ryu進行

(三)刪除全部流表

因爲沒有流表,全部ping操做不可達

(四)添加h1與和h2之間的流錶轉發

1.單個交換機操做

2.h1 ping h2,信息可達(由於有流表進行指導)

3.h1 ping h3,消息不可達(由於交換機2中沒有流表項,而且交換機1也沒有配置到port3的動做

4.實現全部網絡全部主機互通(先清空流表)

爲全部交換機添加端口1和端口2的操做---兩個交換機公共操做html

dpctl add-flow in_port=1,actions=output:2  
dpctl add-flow in_port=2,actions=output:1

爲交換機之間端口提供交互---只操做s1(由於只有s1有端口3)node

sh ovs-ofctl add-flow s1 in_port=1,actions=output:2,3
sh ovs-ofctl add-flow s1 in_port=3,actions=output:1,2
sh ovs-ofctl add-flow s1 in_port=2,actions=output:1,3

實驗結果顯示express

或者:咱們直接添加下面流表也能夠實現上面操做

mininet> dpctl add-flow in_port=1,actions=output:2,3
mininet> dpctl add-flow in_port=2,actions=output:1,3
mininet> dpctl add-flow in_port=3,actions=output:1,2

5.爲交換機2添加丟棄流表,使得兩個交換機不可通訊(在前面互通基礎上實現)

mininet> sh ovs-ofctl del-flows s2 in_port=1  刪除原有流表
mininet> sh ovs-ofctl add-flow s2 in_port=1,actions=drop  添加丟棄流表

相關文章
相關標籤/搜索