X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=src%2Femuvim%2Fdcemulator%2Fnet.py;h=3556535784a2d4c792096573571343bccf39c606;hb=b63a5b4d2e960b176c6547f826419adc44a7f9cf;hp=7f31a4663df754b7e6843dbf9e602bb84dd129e4;hpb=5877ea26273aed77b51263efb19fc13b70087c25;p=osm%2Fvim-emu.git diff --git a/src/emuvim/dcemulator/net.py b/src/emuvim/dcemulator/net.py index 7f31a46..3556535 100755 --- a/src/emuvim/dcemulator/net.py +++ b/src/emuvim/dcemulator/net.py @@ -30,6 +30,7 @@ class DCNetwork(Containernet): """ def __init__(self, controller=RemoteController, monitor=False, + enable_learning = True, # in case of RemoteController (Ryu), learning switch behavior can be turned off/on dc_emulation_max_cpu=1.0, # fraction of overall CPU time for emulation dc_emulation_max_mem=512, # emulation max mem in MB **kwargs): @@ -43,13 +44,14 @@ class DCNetwork(Containernet): # call original Docker.__init__ and setup default controller Containernet.__init__( - self, switch=OVSKernelSwitch, **kwargs) + self, switch=OVSKernelSwitch, controller=controller, **kwargs) + # Ryu management self.ryu_process = None if controller == RemoteController: # start Ryu controller - self.startRyu() + self.startRyu(learning_switch=enable_learning) # add the specified controller self.addController('c0', controller=controller) @@ -331,10 +333,15 @@ class DCNetwork(Containernet): kwargs['vlan'] = vlan kwargs['path'] = path kwargs['current_hop'] = current_hop - ## set flow entry via ovs-ofctl - #self._set_flow_entry_dpctl(current_node, switch_inport_nr, switch_outport_nr, **kwargs) - ## set flow entry via ryu rest api - self._set_flow_entry_ryu_rest(current_node, switch_inport_nr, switch_outport_nr, **kwargs) + + if self.controller == RemoteController: + ## set flow entry via ryu rest api + self._set_flow_entry_ryu_rest(current_node, switch_inport_nr, switch_outport_nr, **kwargs) + else: + ## set flow entry via ovs-ofctl + self._set_flow_entry_dpctl(current_node, switch_inport_nr, switch_outport_nr, **kwargs) + + # take first link between switches by default if isinstance( next_node, OVSSwitch ): @@ -359,6 +366,7 @@ class DCNetwork(Containernet): flow = {} flow['dpid'] = int(node.dpid, 16) + if cookie: flow['cookie'] = int(cookie) @@ -369,15 +377,13 @@ class DCNetwork(Containernet): # http://ryu.readthedocs.io/en/latest/app/ofctl_rest.html#add-a-flow-entry if cmd == 'add-flow': prefix = 'stats/flowentry/add' - action = {} - action['type'] = 'OUTPUT' - action['port'] = switch_outport_nr - flow['actions'].append(action) if vlan != None: if path.index(current_hop) == 0: # first node action = {} action['type'] = 'PUSH_VLAN' # Push a new VLAN tag if a input frame is non-VLAN-tagged action['ethertype'] = 33024 # Ethertype 0x8100(=33024): IEEE 802.1Q VLAN-tagged frame + flow['actions'].append(action) + action = {} action['type'] = 'SET_FIELD' action['field'] = 'vlan_vid' action['value'] = vlan @@ -389,14 +395,19 @@ class DCNetwork(Containernet): flow['actions'].append(action) else: # middle nodes match += ',dl_vlan=%s' % vlan - #flow['match'] = self._parse_match(match) + # output action must come last + action = {} + action['type'] = 'OUTPUT' + action['port'] = switch_outport_nr + flow['actions'].append(action) + elif cmd == 'del-flows': - #del(flow['actions']) prefix = 'stats/flowentry/delete' + + # if cookie is given, only delete flows by cookie + # do not specify other match -> also other cookies can be matched if cookie: - flow['cookie_mask'] = cookie - #if cookie is None: - # flow['match'] = self._parse_match(match) + flow['cookie_mask'] = int('0xffffffffffffffff', 16) # need full mask to match complete cookie action = {} action['type'] = 'OUTPUT' @@ -444,7 +455,7 @@ class DCNetwork(Containernet): switch_outport_nr, cmd)) # start Ryu Openflow controller as Remote Controller for the DCNetwork - def startRyu(self): + def startRyu(self, learning_switch=True): # start Ryu controller with rest-API python_install_path = site.getsitepackages()[0] ryu_path = python_install_path + '/ryu/app/simple_switch_13.py' @@ -455,9 +466,11 @@ class DCNetwork(Containernet): ryu_of_port = '6653' ryu_cmd = 'ryu-manager' FNULL = open("/tmp/ryu.log", 'w') - self.ryu_process = Popen([ryu_cmd, ryu_path, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL) - # no learning switch - #self.ryu_process = Popen([ryu_cmd, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL) + if learning_switch: + self.ryu_process = Popen([ryu_cmd, ryu_path, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL) + else: + # no learning switch + self.ryu_process = Popen([ryu_cmd, ryu_path2, ryu_option, ryu_of_port], stdout=FNULL, stderr=FNULL) time.sleep(1) def stopRyu(self): @@ -466,18 +479,23 @@ class DCNetwork(Containernet): self.ryu_process.kill() def ryu_REST(self, prefix, dpid=None, data=None): - if dpid: - url = self.ryu_REST_api + '/' + str(prefix) + '/' + str(dpid) - else: - url = self.ryu_REST_api + '/' + str(prefix) - if data: - #logging.info('POST: {0}'.format(str(data))) - req = urllib2.Request(url, str(data)) - else: - req = urllib2.Request(url) + if data: logging.info('log POST: {0}'.format(str(data))) + try: + if dpid: + url = self.ryu_REST_api + '/' + str(prefix) + '/' + str(dpid) + else: + url = self.ryu_REST_api + '/' + str(prefix) + if data: + #logging.info('POST: {0}'.format(str(data))) + req = urllib2.Request(url, str(data)) + else: + req = urllib2.Request(url) - ret = urllib2.urlopen(req).read() - return ret + ret = urllib2.urlopen(req).read() + return ret + except: + logging.info('error url: {0}'.format(str(url))) + if data: logging.info('error POST: {0}'.format(str(data))) # need to respect that some match fields must be integers # http://ryu.readthedocs.io/en/latest/app/ofctl_rest.html#description-of-match-and-actions