# -*- coding: cp1252 -*- #!/usr/bin/tclsh ################################################################################ # # # Copyright 1997 - 2020 by IXIA Keysight # # All Rights Reserved. # # # ################################################################################ ################################################################################ # # # LEGAL NOTICE: # # ============== # # The following code and documentation (hereinafter "the script") is an # # example script for demonstration purposes only. # # The script is not a standard commercial product offered by Ixia and have # # been developed and is being provided for use only as indicated herein. The # # script [and all modifications enhancements and updates thereto (whether # # made by Ixia and/or by the user and/or by a third party)] shall at all times # # remain the property of Ixia. # # # # Ixia does not warrant (i) that the functions contained in the script will # # meet the users requirements or (ii) that the script will be without # # omissions or error-free. # # THE SCRIPT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND IXIA # # DISCLAIMS ALL WARRANTIES EXPRESS IMPLIED STATUTORY OR OTHERWISE # # INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF MERCHANTABILITY AND FITNESS FOR # # A PARTICULAR PURPOSE OR OF NON-INFRINGEMENT. # # THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SCRIPT IS WITH THE # # USER. # # IN NO EVENT SHALL IXIA BE LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING # # OUT OF THE USE OF OR THE INABILITY TO USE THE SCRIPT OR ANY PART THEREOF # # INCLUDING BUT NOT LIMITED TO ANY LOST PROFITS LOST BUSINESS LOST OR # # DAMAGED DATA OR SOFTWARE OR ANY INDIRECT INCIDENTAL PUNITIVE OR # # CONSEQUENTIAL DAMAGES EVEN IF IXIA HAS BEEN ADVISED OF THE POSSIBILITY OF # # SUCH DAMAGES IN ADVANCE. # # Ixia will not be required to provide any software maintenance or support # # services of any kind (e.g. any error corrections) in connection with the # # script or any part thereof. The user acknowledges that although Ixia may # # from time to time and in its sole discretion provide maintenance or support # # services for the script any such services are subject to the warranty and # # damages limitations set forth herein and will not obligate Ixia to provide # # any additional maintenance or support services. # # # ################################################################################ ################################################################################ # # # Description: # # This script intends to demonstrate how to use NGPF OpenFlow Controller API# # It will create 1 topology of OpenFlow Controller, it will start the # # emulation and then it will retrieve and display few statistics # # It will also check detailed learned info and learned info after sending on# # demand message # ################################################################################ import sys import time ################################################################################ # Either feed the ixNetwork library path in the sys.path as below, or put the # # IxNetwork.py file somewhere else where we python can autoload it # # "IxNetwork.py" is available in \API\Python # ################################################################################ sys.path.append('C:\Program Files (x86)\Ixia\IxNetwork\8.10-EA\API\Python') import IxNetwork print("loaded successfully") class NgpfOpenFlowController(object): ################################################################################ # Connecting to IxTCl server and cretaing new config # ################################################################################ def __init__(self, ix_tcl_server, ix_tcl_port, ix_version="8.10"): ixNet = IxNetwork.IxNet() print("connecting to IxNetwork client") ixNet.connect(ix_tcl_server, '-port', ix_tcl_port, '-version', ix_version, '-setAttribute', 'strict') # cleaning up the old configfile, and creating an empty config print("cleaning up the old configfile, and creating an empty config") ixNet.execute('newConfig') self.ixNet = ixNet self.root = ixNet.getRoot() def assignPorts (self, realPort1) : chassis1 = realPort1[0] card1 = realPort1[1] port1 = realPort1[2] root = self.ixNet.getRoot() vport1 = self.ixNet.add(root, 'vport') self.ixNet.commit() vport1 = self.ixNet.remapIds(vport1)[0] chassisObj1 = self.ixNet.add(root + '/availableHardware', 'chassis') self.ixNet.setAttribute(chassisObj1, '-hostname', chassis1) self.ixNet.commit() chassisObj1 = self.ixNet.remapIds(chassisObj1)[0] cardPortRef1 = chassisObj1 + '/card:%s/port:%s' % (card1,port1) self.ixNet.setMultiAttribute(vport1, '-connectedTo', cardPortRef1, '-rxMode', 'captureAndMeasure', '-name', 'Ethernet - 001') self.ixNet.commit() ################################################################################ # Method for enabling and set values for match criteria & Instruction Actions # ################################################################################ def enablematchesinstructions (self, flow_profile, required_match_criteria_list, required_instruction, required_action): global1 = self.ixNet.getList(self.root, 'globals')[0] topo1 = self.ixNet.getList(global1, 'topology')[0] ofcontroller1 = self.ixNet.getList(topo1, 'openFlowController')[0] flowtemp = self.ixNet.getList(ofcontroller1, 'flowSetTemplate')[0] predefined_template = self.ixNet.add(flowtemp, 'predefined') flow_template = self.ixNet.add(predefined_template, 'flowTemplate') self.ixNet.commit() time.sleep(5) matchactionlist = self.ixNet.getList(flow_template, 'matchAction') for i in matchactionlist: print (i) print (self.ixNet.getAttribute(i, '-name')) if (self.ixNet.getAttribute(i, '-name') == "[1] Blank Template"): print ("success") self.ixNet.execute('addFromTemplate', flow_profile, i) self.ixNet.commit() time.sleep(5) flow_profile_matchAction = self.ixNet.getList(flow_profile, 'matchAction')[0] flow_profilematch_criteria = self.ixNet.getList(flow_profile_matchAction, 'matchCriteria')[0] match_criteria_list = self.ixNet.getList(flow_profilematch_criteria, 'matchCriteria') for matchCriteria in match_criteria_list: if self.ixNet.getAttribute(matchCriteria, '-name') == "Ethernet": print ("Match criteria is ethernet") self.ixNet.setMultiAttribute(matchCriteria, '-isEnabled', 'true') self.ixNet.commit() ethernetmatchCriteria = self.ixNet.getList(matchCriteria, 'matchCriteria') print (ethernetmatchCriteria) for ethernetmatchlist in ethernetmatchCriteria: if self.ixNet.getAttribute(ethernetmatchlist, '-name') == "Ethernet Source": ethernetsourcefield = self.ixNet.getList(ethernetmatchlist, 'field')[0] print (ethernetsourcefield) valuemulti = self.ixNet.getAttribute(ethernetsourcefield, '-value') print (valuemulti) self.ixNet.setAttribute(valuemulti + '/singleValue', '-value', '44:0:0:0:0:77') self.ixNet.commit() time.sleep(5) else: ethernetdestinationfield = self.ixNet.getList(ethernetmatchlist, 'field')[0] print (ethernetdestinationfield) valuemulti = self.ixNet.getAttribute(ethernetdestinationfield, '-value') print (valuemulti) self.ixNet.setAttribute(valuemulti + '/singleValue', '-value', '11:0:0:0:0:77') self.ixNet.commit() time.sleep(5) if self.ixNet.getAttribute(matchCriteria, '-name') == "IP": print ("Match criteria is IP") self.ixNet.setMultiAttribute(matchCriteria, '-isEnabled', 'true') self.ixNet.commit() ipmatchCriteria = self.ixNet.getList(matchCriteria, 'matchCriteria')[0] print (ipmatchCriteria) ipv4list = self.ixNet.getList(ipmatchCriteria, 'matchCriteria') for ipv4names in ipv4list: if self.ixNet.getAttribute(ipv4names, '-name') == "IPv4 Source": ipsourcefield = self.ixNet.getList(ipv4names, 'field')[0] print (ipsourcefield) valuemulti = self.ixNet.getAttribute(ipsourcefield, '-value') print (valuemulti) self.ixNet.setAttribute(valuemulti + '/singleValue', '-value', '67.1.1.1') self.ixNet.commit() time.sleep(5) else: ipdestinationfield = self.ixNet.getList(ipv4names, 'field')[0] print (ipdestinationfield) valuemulti = self.ixNet.getAttribute(ipdestinationfield, '-value') print (valuemulti) self.ixNet.setAttribute(valuemulti + '/singleValue', '-value', '4.1.1.1') self.ixNet.commit() time.sleep(5) flowProfileMatchAction = self.ixNet.getList(flow_profile, 'matchAction')[0] flowProfileInstruction = self.ixNet.getList(flowProfileMatchAction, 'instructions')[0] print ("Adding instruction") self.ixNet.execute('addInstruction', flowProfileInstruction, "Apply Actions") self.ixNet.commit() flowProfileInstructionAdded = self.ixNet.getList(flowProfileInstruction, 'instruction')[0] print (flowProfileInstructionAdded) print ("Adding 2 action") for action in required_action: self.ixNet.execute('addAction', flowProfileInstructionAdded, action) self.ixNet.commit() actionsAdded = self.ixNet.getList(flowProfileInstructionAdded, 'actions')[0] actionList = self.ixNet.getList(actionsAdded, 'action') print (actionList) for action in actionList: if (self.ixNet.getAttribute(action, '-name')) == "Set Ethernet Source": print ("action is Set Ethernet Source") val = "4:6:0:0:0:0" print (val) else: print ("action is Set Ethernet Destination") val = "7:7:4:8:1:7" print (val) field = self.ixNet.getList(action, 'field')[0] print (field) actionValue = self.ixNet.getAttribute(field, '-value') print (actionValue) self.ixNet.setAttribute(actionValue + '/singleValue', '-value', val) self.ixNet.commit() ################################################################################ # Start protocol and check statistics # ################################################################################ def start_protocol_check_stats(self): print("Starting protocols and waiting for 45 seconds for protocols to come up") self.ixNet.execute('startAllProtocols') time.sleep(45) print ("Fetching all Protocol Summary Stats\n") viewPage = '::ixNet::OBJ-/statistics/view:"Protocols Summary"/page' statcap = self.ixNet.getAttribute(viewPage, '-columnCaptions') for statValList in self.ixNet.getAttribute(viewPage, '-rowValues') : for statVal in statValList : print("***************************************************") index = 0 for satIndv in statVal : print("%-30s:%s" % (statcap[index], satIndv)) index = index + 1 print("***************************************************") print ("Verifying OpenFlow Controller Per Port stats\n") viewPage = '::ixNet::OBJ-/statistics/view:"OpenFlow Controller Per Port"/page' statcap = self.ixNet.getAttribute(viewPage, '-columnCaptions') for statValList in self.ixNet.getAttribute(viewPage, '-rowValues') : for statVal in statValList : print("***************************************************") index = 0 for satIndv in statVal : print("%-30s:%s" % (statcap[index], satIndv)) index = index + 1 print("***************************************************") ################################################################################ # On the fly section # ################################################################################ def on_the_fly(self, flow_profile): flowProfileMatchAction = self.ixNet.getList(flow_profile, 'matchAction')[0] print (flowProfileMatchAction) flowProfileInstruction = self.ixNet.getList(flowProfileMatchAction, 'instructions')[0] flowProfileInstructionAdded = self.ixNet.getList(flowProfileInstruction, 'instruction')[0] actionsAdded = self.ixNet.getList(flowProfileInstructionAdded, 'actions')[0] actionList = self.ixNet.getList(actionsAdded, 'action')[0] print (actionList) if (self.ixNet.getAttribute(actionList, '-name')) == "Set Ethernet Source": print ("Modifying Set Ethernet Source Value OTF to 16:44:33:2:1:1") val = "16:44:33:2:1:1" Ethernetfield = self.ixNet.getList(actionList, 'field')[0] actionValue = self.ixNet.getAttribute(Ethernetfield, '-value') self.ixNet.setAttribute(actionValue + '/singleValue', '-value', val) self.ixNet.commit() globalObj = self.ixNet.getRoot() + '/globals' topology = globalObj + '/topology' print ("Applying changes on the fly") try: self.ixNet.execute('applyOnTheFly', topology) except: print("error in applying on the fly change") time.sleep(10) ############################################################################### # print learned info # ############################################################################### def print_learned_info(self, openFlowController1): self.ixNet.execute('getOFChannelLearnedInfo', openFlowController1, '1') time.sleep(5) print("Print OFController Learned Info") linfo = self.ixNet.getList(openFlowController1, 'learnedInfo')[0] linfoList = self.ixNet.getList(linfo, 'table') print("***************************************************") for table in linfoList : tableType = self.ixNet.getAttribute(table, '-type') print(tableType) print("=================================================") columns = self.ixNet.getAttribute(table, '-columns') print(columns) values = self.ixNet.getAttribute(table, '-values') for value in values : for word in values : print(word) time.sleep(15) print ("Set on demand message for flow stat!!!!") OfChanneLearnedinfoList = self.ixNet.getList(openFlowController1, 'ofChannelLearnedInfoList')[0] OnDemandMessage = self.ixNet.getAttribute(OfChanneLearnedinfoList, '-onDemandMessages') values1 = self.ixNet.getAttribute(OnDemandMessage, '-values')[0] self.ixNet.setAttribute(OnDemandMessage + '/singleValue', '-value', "flowstat") print ("sending on demand message on the fly for flow stat learned info") self.ixNet.execute('sendOnDemandMessage', OfChanneLearnedinfoList, 1) print ('Stopping protocols') self.ixNet.execute('stopAllProtocols') ################################################################################ # protocol configuration section # ################################################################################ def main(self): self.assignPorts(ports[0]) root = self.ixNet.getRoot() vportTx = self.ixNet.getList(root, 'vport')[0] print("adding topologies") self.ixNet.add(root, 'topology', '-vports', vportTx) self.ixNet.commit() topologies = self.ixNet.getList(self.ixNet.getRoot(), 'topology') topo1 = topologies[0] print ("Adding 2 device groups") self.ixNet.add(topo1, 'deviceGroup') self.ixNet.commit() t1devices = self.ixNet.getList(topo1, 'deviceGroup') t1dev1 = t1devices[0] print("Configuring the multipliers (number of sessions)") self.ixNet.setAttribute(t1dev1, '-multiplier', '1') self.ixNet.commit() print("Adding ethernet/mac endpoints") self.ixNet.add(t1dev1, 'ethernet') self.ixNet.commit() mac1 = self.ixNet.getList(t1dev1, 'ethernet')[0] print ('ixNet.help(\'::ixNet::OBJ-/topology/deviceGroup/ethernet\')') print("Add ipv4") self.ixNet.add(mac1, 'ipv4') self.ixNet.commit() ip1 = self.ixNet.getList(mac1, 'ipv4')[0] mvAdd1 = self.ixNet.getAttribute(ip1, '-address') mvGw1 = self.ixNet.getAttribute(ip1, '-gatewayIp') print("configuring ipv4 addresses") self.ixNet.setAttribute(mvAdd1 + '/singleValue', '-value', '1.1.1.2') self.ixNet.commit() self.ixNet.setAttribute(mvGw1 + '/singleValue', '-value', '1.1.1.1') self.ixNet.commit() self.ixNet.setAttribute(self.ixNet.getAttribute(ip1, '-prefix') + '/singleValue', '-value', '24') self.ixNet.commit() self.ixNet.setMultiAttribute(self.ixNet.getAttribute(ip1, '-resolveGateway') + '/singleValue', '-value', 'true') self.ixNet.commit() time.sleep(5) print (self.ixNet.help('::ixNet::OBJ-/topology/deviceGroup/ethernet/ipv4')) print("Adding Openflow Controller over IP4 stacks") self.ixNet.add(ip1, 'openFlowController') self.ixNet.commit() openFlowController1 = self.ixNet.getList(ip1, 'openFlowController')[0] print (openFlowController1) time.sleep(5) openflowchannels = self.ixNet.add(openFlowController1, 'openFlowChannel') self.ixNet.commit() time.sleep(5) openflowchannellist = self.ixNet.getList(openFlowController1, 'openFlowChannel')[0] self.ixNet.setMultiAttribute(openflowchannels, '-groupsPerChannel', '1') self.ixNet.commit() time.sleep(5) self.ixNet.setMultiAttribute(openflowchannels, '-metersPerChannel', '1') self.ixNet.commit() time.sleep(5) table1 = self.ixNet.getList(openflowchannellist, 'tables')[0] flowset = self.ixNet.getList(table1, 'flowSet')[0] flowprofile = self.ixNet.getList(flowset, 'flowProfile')[0] requiredMatchCriteriaList = ["Ethernet", "IP"] requiredInstruction = ["Apply Actions"] requiredaction = ["Set Ethernet Source", "Set Ethernet Destination"] self.enablematchesinstructions(flowprofile, requiredMatchCriteriaList, requiredInstruction, requiredaction) self.start_protocol_check_stats() self.on_the_fly(flowprofile) self.print_learned_info(openFlowController1) print ('!!! Test Script Ends !!!') ################################################################################# # Give chassis/client/ixNetwork server port/ chassis port HW port information # # below # ################################################################################# if __name__ == "__main__": ixTclServer = '10.214.101.141' ixTclPort = '8564' ports = [('12.0.1.253', '5', '10',)] version = '8.10' controller = NgpfOpenFlowController(ixTclServer, ixTclPort, version) controller.main()