2014-04-13 264 views
0

我是python的新手。我正在嘗試開發和開放流應用程序。我開始的應用程序是以下文件。您可以看到它實現了一個簡單的以太網交換機。NameError:沒有定義全局名稱'get_all_switch'

https://github.com/osrg/ryu/blob/master/ryu/app/simple_switch.py

現在我有另一個文件

https://github.com/osrg/ryu/blob/master/ryu/topology/api.py

它看起來像它暴露的函數返回的鏈接,並在開關拓撲信息。

如果我試圖在simple_switch.py​​的init()中調用該函數,它會返回一個錯誤?

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

這是我得到的錯誤。

loading app ryu/app/simple_switch.py 
loading app ryu.controller.ofp_handler 
instantiating app ryu.controller.ofp_handler of OFPHandler 
instantiating app ryu/app/simple_switch.py of SimpleSwitch 
Traceback (most recent call last): 
    File "/usr/local/bin/ryu-manager", line 9, in <module> 
    load_entry_point('ryu==3.8', 'console_scripts', 'ryu-manager')() 
    File "/usr/local/lib/python2.7/dist-packages/ryu/cmd/manager.py", line 73, in main 
    services.extend(app_mgr.instantiate_apps(**contexts)) 
    File "/usr/local/lib/python2.7/dist-packages/ryu/base/app_manager.py", line 434, in instantiate_apps 
    self._instantiate(app_name, cls, *args, **kwargs) 
    File "/usr/local/lib/python2.7/dist-packages/ryu/base/app_manager.py", line 420, in _instantiate 
    app = cls(*args, **kwargs) 
    File "/home/karthik/Projects/ryu/ryu/app/simple_switch.py", line 35, in __init__ 
    s_list = get_all_switch(app_manager) 
NameError: global name 'get_all_switch' is not defined 

我的問題如下。

1)我能獲得有關使用 我mininet拓撲拓撲信息 - 在劉某/拓撲/ api.py定義get_all_link() - get_all_switch()和 ?

2)如果是,爲什麼上面的代碼不能按預期工作?

我問這裏是因爲蟒蛇我的工作經驗是不是great.I希望能夠在應用程序中simple_switch使用功能拓撲/ api.py裏面simple_switch.py​​

我進口線。 PY如下

import logging 
import struct 

from ryu.base import app_manager 
from ryu.controller import mac_to_port 
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 

更新基於答案1:

我已經修改我的代碼如下:

from ryu.base import app_manager 
from ryu.controller import mac_to_port 
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 
import ryu.topology.api 


def __init__(self, *args, **kwargs): 
     super(SimpleSwitch, self).__init__(*args, **kwargs) 
     self.mac_to_port = {} 
     s_list = ryu.topology.api.get_all_switch(app_manager.RyuApp) 

我現在得到一個新的錯誤:

loading app ryu/app/simple_switch.py 
loading app ryu.topology.switches 
loading app ryu.controller.ofp_handler 
loading app ryu.controller.ofp_handler 
instantiating app ryu.topology.switches of Switches 
instantiating app ryu.controller.ofp_handler of OFPHandler 
instantiating app ryu/app/simple_switch.py of SimpleSwitch 
Traceback (most recent call last): 
    File "/usr/local/bin/ryu-manager", line 9, in <module> 
    load_entry_point('ryu==3.8', 'console_scripts', 'ryu-manager')() 
    File "/usr/local/lib/python2.7/dist-packages/ryu/cmd/manager.py", line 73, in main 
    services.extend(app_mgr.instantiate_apps(**contexts)) 
    File "/usr/local/lib/python2.7/dist-packages/ryu/base/app_manager.py", line 434, in instantiate_apps 
    self._instantiate(app_name, cls, *args, **kwargs) 
    File "/usr/local/lib/python2.7/dist-packages/ryu/base/app_manager.py", line 420, in _instantiate 
    app = cls(*args, **kwargs) 
    File "/home/karthik/Projects/ryu/ryu/app/simple_switch.py", line 36, in __init__ 
    s_list = ryu.topology.api.get_all_switch(app_manager.RyuApp) 
    File "/usr/local/lib/python2.7/dist-packages/ryu/topology/api.py", line 26, in get_all_switch 
    return get_switch(app) 
    File "/usr/local/lib/python2.7/dist-packages/ryu/topology/api.py", line 21, in get_switch 
    rep = app.send_request(event.EventSwitchRequest(dpid)) 
TypeError: unbound method send_request() must be called with RyuApp instance as first argument (got EventSwitchRequest instance instead) 

回答

1
  1. 是。
  2. 很可能,您應該使用合格的名稱,如ryu.topology.api.get_all_switch()。對於確切的答案,更多的上下文將是必要的(比如,顯示你的import行)。
+0

在上面的問題中增加了導入行 – liv2hak

+0

因此,不會導入'ryu.topology.api',這就是NameError的原因。嘗試'導入ryu.topology.api'並在'__init __()'中調用'ryu.topology.api.get_all_switch()'。 – user58697

+0

我已經嘗試了你的建議。我現在得到一個新的錯誤。confusing :( – liv2hak

0

嘗試使用此行:

s_list = ryu.topology.api.get_all_switch(self) 
1

基於以上的答案,一些挖我有我的代碼如下,它完美的作品:

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.topology import event 
from ryu.topology.api import get_all_switch, get_all_link 


class SimpleSwitch13(app_manager.RyuApp): 
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] 

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

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) 
    def switch_features_handler(self, ev): 
     self.logger.info("Received EventOFPSwitchFeatures") 
     msg = ev.msg 
     self.logger.info('OFPSwitchFeatures received: ' 
         '\n\tdatapath_id=0x%016x n_buffers=%d ' 
         '\n\tn_tables=%d auxiliary_id=%d ' 
         '\n\tcapabilities=0x%08x', 
         msg.datapath_id, msg.n_buffers, msg.n_tables, 
         msg.auxiliary_id, msg.capabilities) 

     datapath = ev.msg.datapath 
     ofproto = datapath.ofproto 
     parser = datapath.ofproto_parser 
     match = parser.OFPMatch() 
     actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, 
              ofproto.OFPCML_NO_BUFFER)] 
     self.add_flow(datapath, 0, match, actions) 

    def add_flow(self, datapath, priority, match, actions, buffer_id=None): 
     ofproto = datapath.ofproto 
     parser = datapath.ofproto_parser 

     inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, 
              actions)] 
     if buffer_id: 
      mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id, 
            priority=priority, match=match, 
            instructions=inst) 
     else: 
      mod = parser.OFPFlowMod(datapath=datapath, priority=priority, 
            match=match, instructions=inst) 
     datapath.send_msg(mod) 

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) 
    def _packet_in_handler(self, ev): 
     #self.logger.info("Received EventOFPPacketIn") 
     # If you hit this you might want to increase 
     # the "miss_send_length" of your switch 
     if ev.msg.msg_len < ev.msg.total_len: 
      self.logger.debug("packet truncated: only %s of %s bytes", 
           ev.msg.msg_len, ev.msg.total_len) 
     msg = ev.msg 
     datapath = msg.datapath 
     ofproto = datapath.ofproto 
     parser = datapath.ofproto_parser 
     in_port = msg.match['in_port'] 

     pkt = packet.Packet(msg.data) 
     eth = pkt.get_protocols(ethernet.ethernet)[0] 

     dst = eth.dst 
     src = eth.src 

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

     self.logger.info("\tpacket in %s %s %s %s", dpid, src, dst, in_port) 

     # learn a mac address to avoid FLOOD next time. 
     self.mac_to_port[dpid][src] = 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 = [parser.OFPActionOutput(out_port)] 

     # install a flow to avoid packet_in next time 
     if out_port != ofproto.OFPP_FLOOD: 
      match = parser.OFPMatch(in_port=in_port, eth_dst=dst) 
      # verify if we have a valid buffer_id, if yes avoid to send both 
      # flow_mod & packet_out 
      if msg.buffer_id != ofproto.OFP_NO_BUFFER: 
       self.add_flow(datapath, 1, match, actions, msg.buffer_id) 
       return 
      else: 
       self.add_flow(datapath, 1, match, actions) 
     data = None 
     if msg.buffer_id == ofproto.OFP_NO_BUFFER: 
      data = msg.data 

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

    """ 
    The event EventSwitchEnter will trigger the activation of get_topology_data(). 
    """ 
    @set_ev_cls(event.EventSwitchEnter, [MAIN_DISPATCHER,CONFIG_DISPATCHER]) 
    def get_topology_data(self, ev): 
     self.logger.info("[Ehsan] Received EventSwitchEnter") 
     # Call get_switch() to get the list of objects Switch. 
     switch_list = get_all_switch(self) 

     # Build a list with all the switches ([switches]) 
     topo_switches = [switch.dp.id for switch in switch_list] 

     # Call get_link() to get the list of objects Link. 
     links_list = get_all_link(self) 

     # Build a list with all the links [(srcNode, dstNode, port)]. 
     topo_links = [(link.src.dpid,link.dst.dpid,{'port':link.src.port_no}) for link in links_list] 

     print ("\tLinks: "+str(topo_links)) 
     print ("\tSwitches: "+str(topo_switches)) 

目前我在連接交換機時觸發該功能,但您可以修改get_topology_data()以針對任何事件調用該功能。 例如,您在收到port_status或鏈接被刪除/添加/修改以更新地形時調用它。

請注意,我仍處於此代碼的開發階段。我可能稍後將完整的代碼添加到我的repo

相關問題