def test_record_removal(): """ Test the recording of an idle-timeout flow removal message sent by a switch into the flow_rems database collection Synthesise flow removal messages to test with. """ #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate Flow class: flow = flows_module.Flow(config) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx = json_file.read() json_dict_tx = json.loads(json_str_tx) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx = json_file.read() json_dict_rx = json.loads(json_str_rx) #*** Set up fake datapath and synthesise messages: datapath = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath.id = 1 msg_tx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_tx) msg_rx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_rx) logger.debug("msg_tx=%s", msg_tx) #*** Call our method that we're testing with the synthesised flow rems: flow.record_removal(msg_tx) flow.record_removal(msg_rx) #*** Check that messages recorded correctly in database collection: db_data_tx = {'ip_A': '10.1.0.1', 'tp_B': 80} result = flow.flow_rems.find(db_data_tx).sort('$natural', -1).limit(1) result_tx = list(result)[0] logger.debug("result=%s", result_tx) assert result_tx['table_id'] == 1 assert result_tx['ip_B'] == '10.1.0.2' assert result_tx['tp_A'] == 43297 assert result_tx['packet_count'] == 10 assert result_tx['flow_hash'] == nethash.hash_flow(('10.1.0.1', '10.1.0.2', 43297, 80, 6)) assert result_tx['cookie'] == 23 assert result_tx['direction'] == 'forward' #*** Return leg of flow: db_data_tx = {'ip_B': '10.1.0.1', 'tp_A': 80} result = flow.flow_rems.find(db_data_tx).sort('$natural', -1).limit(1) result_tx = list(result)[0] logger.debug("result=%s", result_tx) assert result_tx['table_id'] == 1 assert result_tx['ip_A'] == '10.1.0.2' assert result_tx['tp_B'] == 43297 assert result_tx['packet_count'] == 9 assert result_tx['flow_hash'] == nethash.hash_flow(('10.1.0.2', '10.1.0.1', 80, 43297, 6)) assert result_tx['cookie'] == 1000000023 assert result_tx['direction'] == 'reverse'
def test_record_removal(): """ Test the recording of an idle-timeout flow removal message sent by a switch into the flow_rems database collection Synthesise flow removal messages to test with. """ #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate Flow class: flow = flows_module.Flow(config) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx = json_file.read() json_dict_tx = json.loads(json_str_tx) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx = json_file.read() json_dict_rx = json.loads(json_str_rx) #*** Set up fake datapath and synthesise messages: datapath = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath.id = 1 msg_tx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_tx) msg_rx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_rx) logger.debug("msg_tx=%s", msg_tx) #*** Call our method that we're testing with the synthesised flow rems: flow.record_removal(msg_tx) flow.record_removal(msg_rx) #*** Check that messages recorded correctly in database collection: db_data_tx = {'ip_A': '10.1.0.1', 'tp_B': 80} result = flow.flow_rems.find(db_data_tx).sort('$natural', -1).limit(1) result_tx = list(result)[0] logger.debug("result=%s", result_tx) assert result_tx['table_id'] == 1 assert result_tx['ip_B'] == '10.1.0.2' assert result_tx['tp_A'] == 43297 assert result_tx['packet_count'] == 10 assert result_tx['flow_hash'] == nethash.hash_flow( ('10.1.0.1', '10.1.0.2', 43297, 80, 6)) assert result_tx['cookie'] == 23 assert result_tx['direction'] == 'forward' #*** Return leg of flow: db_data_tx = {'ip_B': '10.1.0.1', 'tp_A': 80} result = flow.flow_rems.find(db_data_tx).sort('$natural', -1).limit(1) result_tx = list(result)[0] logger.debug("result=%s", result_tx) assert result_tx['table_id'] == 1 assert result_tx['ip_A'] == '10.1.0.2' assert result_tx['tp_B'] == 43297 assert result_tx['packet_count'] == 9 assert result_tx['flow_hash'] == nethash.hash_flow( ('10.1.0.2', '10.1.0.1', 80, 43297, 6)) assert result_tx['cookie'] == 1000000023 assert result_tx['direction'] == 'reverse'
def test_flows_removed_stats_count(): """ Test the flows_removed API stats count by ingesting flow removal messages then checking that the API response correctly specifies message count """ #*** Start api_external as separate process: logger.info("Starting api_external") api_ps = multiprocessing.Process(target=api.run, args=()) api_ps.start() #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate Flow class: flow = flows_module.Flow(config) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx = json_file.read() json_dict_tx = json.loads(json_str_tx) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx = json_file.read() json_dict_rx = json.loads(json_str_rx) #*** Set up fake datapath and synthesise messages: datapath = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath.id = 1 msg_tx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_tx) msg_rx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_rx) #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_STATS_COUNT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['flows_removed'] == 0 #*** Record flow removal to flow_rems database collection: flow.record_removal(msg_tx) #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_STATS_COUNT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['flows_removed'] == 1 #*** Record flow removal to flow_rems database collection: flow.record_removal(msg_rx) #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_STATS_COUNT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['flows_removed'] == 2 #*** Stop api_external sub-process: api_ps.terminate()
def test_get_flow_data_xfer(): """ Test the get_flow_data_xfer method. Synthesise flow removal messages to test with. """ #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate Flow class: flow = flows_module.Flow(config) flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now()) flow.ingest_packet(DPID1, INPORT2, pkts.RAW[1], datetime.datetime.now()) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx = json_file.read() json_dict_tx = json.loads(json_str_tx) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx = json_file.read() json_dict_rx = json.loads(json_str_rx) #*** Set up fake datapath and synthesise messages: datapath = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath.id = 1 msg_tx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_tx) msg_rx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_rx) logger.debug("msg_tx=%s", msg_tx) #*** Record flow removals to flow_rems database collection: flow.record_removal(msg_tx) flow.record_removal(msg_rx) #*** Now, test the get_flow_data_xfer method: record = { 'ip_src': '10.1.0.1', 'ip_dst': '10.1.0.2', 'tp_src': 43297, 'tp_dst': 80, 'proto': 6, 'flow_hash': '9822b2867652ee0957892482b9f004c3' } xfer = api.get_flow_data_xfer(record) logger.debug("xfer=%s", xfer) assert xfer['tx_found'] == 1 assert xfer['tx_bytes'] == 744 assert xfer['tx_pkts'] == 10 assert xfer['rx_found'] == 1 assert xfer['rx_bytes'] == 6644 assert xfer['rx_pkts'] == 9
def test_get_flow_data_xfer(): """ Test the get_flow_data_xfer method. Synthesise flow removal messages to test with. """ #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate Flow class: flow = flows_module.Flow(config) flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now()) flow.ingest_packet(DPID1, INPORT2, pkts.RAW[1], datetime.datetime.now()) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx = json_file.read() json_dict_tx = json.loads(json_str_tx) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx = json_file.read() json_dict_rx = json.loads(json_str_rx) #*** Set up fake datapath and synthesise messages: datapath = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath.id = 1 msg_tx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_tx) msg_rx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_rx) logger.debug("msg_tx=%s", msg_tx) #*** Record flow removals to flow_rems database collection: flow.record_removal(msg_tx) flow.record_removal(msg_rx) #*** Now, test the get_flow_data_xfer method: record = {'ip_src': '10.1.0.1', 'ip_dst': '10.1.0.2', 'tp_src': 43297, 'tp_dst': 80, 'proto': 6, 'flow_hash': '9822b2867652ee0957892482b9f004c3'} xfer = api.get_flow_data_xfer(record) logger.debug("xfer=%s", xfer) assert xfer['tx_found'] == 1 assert xfer['tx_bytes'] == 744 assert xfer['tx_pkts'] == 10 assert xfer['rx_found'] == 1 assert xfer['rx_bytes'] == 6644 assert xfer['rx_pkts'] == 9
def _print(filename): """Prints the JSON flow table from a file in a human readable format""" with open(filename, 'r') as f: msg = json.load(f) dp = FakeRyuDp() ofmsg = ofp_parser.ofp_msg_from_jsondict(dp, msg) table = FakeOFTable(1) table.apply_ofmsgs([ofmsg]) print(table)
def _print(filename, **_kwargs): """Prints the JSON flow table from a file in a human readable format""" with open(filename, 'r') as file_handle: msg = json.load(file_handle) datapath = FakeRyuDp() ofmsg = ofp_parser.ofp_msg_from_jsondict(datapath, msg) table = FakeOFTable(1) table.apply_ofmsgs([ofmsg]) print(table)
def probe(filename, packet): """Prints the actions applied to packet by the table from the file""" with open(filename, 'r') as f: msg = json.load(f) dp = FakeRyuDp() ofmsg = ofp_parser.ofp_msg_from_jsondict(dp, msg) table = FakeOFTable(1) table.apply_ofmsgs([ofmsg]) instructions, out_packet = table.lookup(packet) print(packet) for instruction in instructions: print(instruction) print(out_packet)
def ruleset_from_ryu_json(f_handle): """ Loads a ryu ruleset from json The ruleset can be compressed, either .gz or .bz2 and are decompressed based on their extension. The ryu ruleset can be a dump of flow stats, or flow mods. f_handle: An open file handle, or path return: A list of Rules """ stats = json.load(f_handle) # Find something that looks about right while isinstance(stats, dict): first = next(iter(stats)) if len(stats) != 1: print( "ruleset_from_ryu_json: Warning found multiple values in a dict, using the first", file=sys.stderr) print(next(iter(stats)), file=sys.stdout) if isinstance(first, six.string_types) and first.startswith("OFP"): break # This should work and return a ruleset print("ruleset_from_ryu_json: Unknown value in json", first, ". Skipping into contents.", file=sys.stderr) stats = stats[first] if isinstance(stats, dict): # Could be a OFPFlowStatsReply message, untested code path msg = ofp_msg_from_jsondict(DP, stats) stats = msg.body else: assert isinstance(stats, list) stats = [ryu_from_jsondict(r) for r in stats] ruleset = [rule_from_ryu(r) for r in stats] return ruleset
def _jsondict_to_msg(dp, jsondict): return ofproto_parser.ofp_msg_from_jsondict(dp, jsondict)
def test_flows_removed(): """ Test the flows_removed API by ingesting flow removal messages then checking that the API response correctly lists them """ #*** Start api_external as separate process: logger.info("Starting api_external") api_ps = multiprocessing.Process(target=api.run, args=()) api_ps.start() #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate Flow class: flow = flows_module.Flow(config) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx = json_file.read() json_dict_tx = json.loads(json_str_tx) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx = json_file.read() json_dict_rx = json.loads(json_str_rx) #*** Set up fake datapath and synthesise messages: datapath = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath.id = 1 msg_tx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_tx) msg_rx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_rx) #*** Record flow removals to flow_rems database collection: flow.record_removal(msg_tx) flow.record_removal(msg_rx) #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['dpid'] == 1 #*** Note: can't easily test 'removal_time' as is dynamic, so skipping... assert api_result['_items'][0]['cookie'] == 23 assert api_result['_items'][0]['priority'] == 1 assert api_result['_items'][0]['reason'] == 0 assert api_result['_items'][0]['table_id'] == 1 assert api_result['_items'][0]['duration_sec'] == 5 assert api_result['_items'][0]['idle_timeout'] == 5 assert api_result['_items'][0]['hard_timeout'] == 0 assert api_result['_items'][0]['packet_count'] == 10 assert api_result['_items'][0]['byte_count'] == 744 assert api_result['_items'][0]['eth_A'] == '' assert api_result['_items'][0]['eth_B'] == '' assert api_result['_items'][0]['eth_type'] == 2048 assert api_result['_items'][0]['ip_A'] == '10.1.0.1' assert api_result['_items'][0]['ip_B'] == '10.1.0.2' assert api_result['_items'][0]['ip_proto'] == 6 assert api_result['_items'][0]['tp_A'] == 43297 assert api_result['_items'][0]['tp_B'] == 80 assert api_result['_items'][0][ 'flow_hash'] == '9822b2867652ee0957892482b9f004c3' assert api_result['_items'][0]['direction'] == 'forward' #*** Validate API Response parameters for second flow removal: assert api_result['_items'][1]['dpid'] == 1 #*** Note: can't easily test 'removal_time' as is dynamic, so skipping... assert api_result['_items'][1]['cookie'] == 1000000023 assert api_result['_items'][1]['priority'] == 1 assert api_result['_items'][1]['reason'] == 0 assert api_result['_items'][1]['table_id'] == 1 assert api_result['_items'][1]['duration_sec'] == 5 assert api_result['_items'][1]['idle_timeout'] == 5 assert api_result['_items'][1]['hard_timeout'] == 0 assert api_result['_items'][1]['packet_count'] == 9 assert api_result['_items'][1]['byte_count'] == 6644 assert api_result['_items'][1]['eth_A'] == '' assert api_result['_items'][1]['eth_B'] == '' assert api_result['_items'][1]['eth_type'] == 2048 assert api_result['_items'][1]['ip_A'] == '10.1.0.2' assert api_result['_items'][1]['ip_B'] == '10.1.0.1' assert api_result['_items'][1]['ip_proto'] == 6 assert api_result['_items'][1]['tp_A'] == 80 assert api_result['_items'][1]['tp_B'] == 43297 assert api_result['_items'][1][ 'flow_hash'] == '9822b2867652ee0957892482b9f004c3' assert api_result['_items'][1]['direction'] == 'reverse' #*** Stop api_external sub-process: api_ps.terminate()
def test_response_flows_removed_FLOWDIR_bytes_TXRX(): """ Test the flows_removed API various flavours of src/dst bytes sent/received by ingesting flow removal messages then checking that the API response correctly specifies appropriate stats for bytes sent, including identity enrichment """ #*** Start api_external as separate process: logger.info("Starting api_external") api_ps = multiprocessing.Process(target=api.run, args=()) api_ps.start() #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate supporting classes: flow = flows_module.Flow(config) policy = policy_module.Policy(config) identities = identities_module.Identities(config, policy) #*** Client to Server DHCP Request: flow.ingest_packet(DPID1, INPORT1, pkts_dhcp.RAW[2], datetime.datetime.now()) identities.harvest(pkts_dhcp.RAW[2], flow.packet) #*** Server to Client DHCP ACK: flow.ingest_packet(DPID1, INPORT2, pkts_dhcp.RAW[3], datetime.datetime.now()) identities.harvest(pkts_dhcp.RAW[3], flow.packet) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx_1 = json_file.read() json_dict_tx_1 = json.loads(json_str_tx_1) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx_1 = json_file.read() json_dict_rx_1 = json.loads(json_str_rx_1) with open('OFPMsgs/OFPFlowRemoved_3.json', 'r') as json_file: json_str_tx_2 = json_file.read() json_dict_tx_2 = json.loads(json_str_tx_2) with open('OFPMsgs/OFPFlowRemoved_4.json', 'r') as json_file: json_str_rx_2 = json_file.read() json_dict_rx_2 = json.loads(json_str_rx_2) with open('OFPMsgs/OFPFlowRemoved_5.json', 'r') as json_file: json_str_tx_3 = json_file.read() json_dict_tx_3 = json.loads(json_str_tx_3) with open('OFPMsgs/OFPFlowRemoved_6.json', 'r') as json_file: json_str_rx_3 = json_file.read() json_dict_rx_3 = json.loads(json_str_rx_3) #*** Switch 1: #*** Set up fake datapaths and synthesise messages: datapath1 = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath1.id = 1 msg_tx_1_sw1 = ofproto_parser.ofp_msg_from_jsondict( datapath1, json_dict_tx_1) msg_rx_1_sw1 = ofproto_parser.ofp_msg_from_jsondict( datapath1, json_dict_rx_1) msg_tx_2_sw1 = ofproto_parser.ofp_msg_from_jsondict( datapath1, json_dict_tx_2) msg_rx_2_sw1 = ofproto_parser.ofp_msg_from_jsondict( datapath1, json_dict_rx_2) msg_tx_3_sw1 = ofproto_parser.ofp_msg_from_jsondict( datapath1, json_dict_tx_3) msg_rx_3_sw1 = ofproto_parser.ofp_msg_from_jsondict( datapath1, json_dict_rx_3) #*** Record flow removals to flow_rems database collection: flow.record_removal(msg_tx_1_sw1) flow.record_removal(msg_rx_1_sw1) flow.record_removal(msg_tx_2_sw1) flow.record_removal(msg_rx_2_sw1) flow.record_removal(msg_tx_3_sw1) flow.record_removal(msg_rx_3_sw1) #*** Switch 2 (same flows to check dedup for multiple switches works): #*** Set up fake datapaths and synthesise messages: datapath2 = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath2.id = 2 msg_tx_1_sw2 = ofproto_parser.ofp_msg_from_jsondict( datapath2, json_dict_tx_1) msg_rx_1_sw2 = ofproto_parser.ofp_msg_from_jsondict( datapath2, json_dict_rx_1) msg_tx_2_sw2 = ofproto_parser.ofp_msg_from_jsondict( datapath2, json_dict_tx_2) msg_rx_2_sw2 = ofproto_parser.ofp_msg_from_jsondict( datapath2, json_dict_rx_2) msg_tx_3_sw2 = ofproto_parser.ofp_msg_from_jsondict( datapath1, json_dict_tx_3) msg_rx_3_sw2 = ofproto_parser.ofp_msg_from_jsondict( datapath1, json_dict_rx_3) #*** Record flow removals to flow_rems database collection: flow.record_removal(msg_tx_1_sw2) flow.record_removal(msg_rx_1_sw2) flow.record_removal(msg_tx_2_sw2) flow.record_removal(msg_rx_2_sw2) flow.record_removal(msg_tx_3_sw2) flow.record_removal(msg_rx_3_sw2) #*** Test flows_removed_src_bytes_sent API: #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_SRC_BYTES_SENT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['_id'] == '10.1.0.2' assert api_result['_items'][0]['total_bytes_sent'] == 12345 assert api_result['_items'][0]['identity'] == '10.1.0.2' assert api_result['_items'][1]['_id'] == '10.1.0.1' assert api_result['_items'][1]['total_bytes_sent'] == 5533 assert api_result['_items'][1]['identity'] == 'pc1' #*** Test flows_removed_src_bytes_received API: #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_SRC_BYTES_RECEIVED) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['_id'] == '10.1.0.1' assert api_result['_items'][0]['total_bytes_received'] == 8628 assert api_result['_items'][0]['identity'] == 'pc1' assert api_result['_items'][1]['_id'] == '10.1.0.2' assert api_result['_items'][1]['total_bytes_received'] == 543 assert api_result['_items'][1]['identity'] == '10.1.0.2' #*** Test flows_removed_dst_bytes_sent API: #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_DST_BYTES_SENT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['_id'] == '10.1.0.2' assert api_result['_items'][0]['total_bytes_sent'] == 8628 assert api_result['_items'][0]['identity'] == '10.1.0.2' assert api_result['_items'][1]['_id'] == '10.1.0.1' assert api_result['_items'][1]['total_bytes_sent'] == 543 assert api_result['_items'][1]['identity'] == 'pc1' #*** Test flows_removed_src_bytes_received API: #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_DST_BYTES_RECEIVED) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['_id'] == '10.1.0.1' assert api_result['_items'][0]['total_bytes_received'] == 12345 assert api_result['_items'][0]['identity'] == 'pc1' assert api_result['_items'][1]['_id'] == '10.1.0.2' assert api_result['_items'][1]['total_bytes_received'] == 5533 assert api_result['_items'][1]['identity'] == '10.1.0.2' #*** Stop api_external sub-process: api_ps.terminate()
def test_response_flows_removed_FLOWDIR_bytes_TXRX(): """ Test the flows_removed API various flavours of src/dst bytes sent/received by ingesting flow removal messages then checking that the API response correctly specifies appropriate stats for bytes sent, including identity enrichment """ #*** Start api_external as separate process: logger.info("Starting api_external") api_ps = multiprocessing.Process( target=api.run, args=()) api_ps.start() #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate supporting classes: flow = flows_module.Flow(config) policy = policy_module.Policy(config) identities = identities_module.Identities(config, policy) #*** Client to Server DHCP Request: flow.ingest_packet(DPID1, INPORT1, pkts_dhcp.RAW[2], datetime.datetime.now()) identities.harvest(pkts_dhcp.RAW[2], flow.packet) #*** Server to Client DHCP ACK: flow.ingest_packet(DPID1, INPORT2, pkts_dhcp.RAW[3], datetime.datetime.now()) identities.harvest(pkts_dhcp.RAW[3], flow.packet) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx_1 = json_file.read() json_dict_tx_1 = json.loads(json_str_tx_1) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx_1 = json_file.read() json_dict_rx_1 = json.loads(json_str_rx_1) with open('OFPMsgs/OFPFlowRemoved_3.json', 'r') as json_file: json_str_tx_2 = json_file.read() json_dict_tx_2 = json.loads(json_str_tx_2) with open('OFPMsgs/OFPFlowRemoved_4.json', 'r') as json_file: json_str_rx_2 = json_file.read() json_dict_rx_2 = json.loads(json_str_rx_2) with open('OFPMsgs/OFPFlowRemoved_5.json', 'r') as json_file: json_str_tx_3 = json_file.read() json_dict_tx_3 = json.loads(json_str_tx_3) with open('OFPMsgs/OFPFlowRemoved_6.json', 'r') as json_file: json_str_rx_3 = json_file.read() json_dict_rx_3 = json.loads(json_str_rx_3) #*** Switch 1: #*** Set up fake datapaths and synthesise messages: datapath1 = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath1.id = 1 msg_tx_1_sw1 = ofproto_parser.ofp_msg_from_jsondict(datapath1, json_dict_tx_1) msg_rx_1_sw1 = ofproto_parser.ofp_msg_from_jsondict(datapath1, json_dict_rx_1) msg_tx_2_sw1 = ofproto_parser.ofp_msg_from_jsondict(datapath1, json_dict_tx_2) msg_rx_2_sw1 = ofproto_parser.ofp_msg_from_jsondict(datapath1, json_dict_rx_2) msg_tx_3_sw1 = ofproto_parser.ofp_msg_from_jsondict(datapath1, json_dict_tx_3) msg_rx_3_sw1 = ofproto_parser.ofp_msg_from_jsondict(datapath1, json_dict_rx_3) #*** Record flow removals to flow_rems database collection: flow.record_removal(msg_tx_1_sw1) flow.record_removal(msg_rx_1_sw1) flow.record_removal(msg_tx_2_sw1) flow.record_removal(msg_rx_2_sw1) flow.record_removal(msg_tx_3_sw1) flow.record_removal(msg_rx_3_sw1) #*** Switch 2 (same flows to check dedup for multiple switches works): #*** Set up fake datapaths and synthesise messages: datapath2 = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath2.id = 2 msg_tx_1_sw2 = ofproto_parser.ofp_msg_from_jsondict(datapath2, json_dict_tx_1) msg_rx_1_sw2 = ofproto_parser.ofp_msg_from_jsondict(datapath2, json_dict_rx_1) msg_tx_2_sw2 = ofproto_parser.ofp_msg_from_jsondict(datapath2, json_dict_tx_2) msg_rx_2_sw2 = ofproto_parser.ofp_msg_from_jsondict(datapath2, json_dict_rx_2) msg_tx_3_sw2 = ofproto_parser.ofp_msg_from_jsondict(datapath1, json_dict_tx_3) msg_rx_3_sw2 = ofproto_parser.ofp_msg_from_jsondict(datapath1, json_dict_rx_3) #*** Record flow removals to flow_rems database collection: flow.record_removal(msg_tx_1_sw2) flow.record_removal(msg_rx_1_sw2) flow.record_removal(msg_tx_2_sw2) flow.record_removal(msg_rx_2_sw2) flow.record_removal(msg_tx_3_sw2) flow.record_removal(msg_rx_3_sw2) #*** Test flows_removed_src_bytes_sent API: #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_SRC_BYTES_SENT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['_id'] == '10.1.0.2' assert api_result['_items'][0]['total_bytes_sent'] == 12345 assert api_result['_items'][0]['identity'] == '10.1.0.2' assert api_result['_items'][1]['_id'] == '10.1.0.1' assert api_result['_items'][1]['total_bytes_sent'] == 5533 assert api_result['_items'][1]['identity'] == 'pc1' #*** Test flows_removed_src_bytes_received API: #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_SRC_BYTES_RECEIVED) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['_id'] == '10.1.0.1' assert api_result['_items'][0]['total_bytes_received'] == 8628 assert api_result['_items'][0]['identity'] == 'pc1' assert api_result['_items'][1]['_id'] == '10.1.0.2' assert api_result['_items'][1]['total_bytes_received'] == 543 assert api_result['_items'][1]['identity'] == '10.1.0.2' #*** Test flows_removed_dst_bytes_sent API: #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_DST_BYTES_SENT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['_id'] == '10.1.0.2' assert api_result['_items'][0]['total_bytes_sent'] == 8628 assert api_result['_items'][0]['identity'] == '10.1.0.2' assert api_result['_items'][1]['_id'] == '10.1.0.1' assert api_result['_items'][1]['total_bytes_sent'] == 543 assert api_result['_items'][1]['identity'] == 'pc1' #*** Test flows_removed_src_bytes_received API: #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_DST_BYTES_RECEIVED) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['_id'] == '10.1.0.1' assert api_result['_items'][0]['total_bytes_received'] == 12345 assert api_result['_items'][0]['identity'] == 'pc1' assert api_result['_items'][1]['_id'] == '10.1.0.2' assert api_result['_items'][1]['total_bytes_received'] == 5533 assert api_result['_items'][1]['identity'] == '10.1.0.2' #*** Stop api_external sub-process: api_ps.terminate()
def _jsonfile_to_msg(datapath, jsonfile): return ofproto_parser.ofp_msg_from_jsondict( datapath, json.load(open(jsonfile)))
def test_flows_removed(): """ Test the flows_removed API by ingesting flow removal messages then checking that the API response correctly lists them """ #*** Start api_external as separate process: logger.info("Starting api_external") api_ps = multiprocessing.Process( target=api.run, args=()) api_ps.start() #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate Flow class: flow = flows_module.Flow(config) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx = json_file.read() json_dict_tx = json.loads(json_str_tx) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx = json_file.read() json_dict_rx = json.loads(json_str_rx) #*** Set up fake datapath and synthesise messages: datapath = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath.id = 1 msg_tx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_tx) msg_rx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_rx) #*** Record flow removals to flow_rems database collection: flow.record_removal(msg_tx) flow.record_removal(msg_rx) #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['_items'][0]['dpid'] == 1 #*** Note: can't easily test 'removal_time' as is dynamic, so skipping... assert api_result['_items'][0]['cookie'] == 23 assert api_result['_items'][0]['priority'] == 1 assert api_result['_items'][0]['reason'] == 0 assert api_result['_items'][0]['table_id'] == 1 assert api_result['_items'][0]['duration_sec'] == 5 assert api_result['_items'][0]['idle_timeout'] == 5 assert api_result['_items'][0]['hard_timeout'] == 0 assert api_result['_items'][0]['packet_count'] == 10 assert api_result['_items'][0]['byte_count'] == 744 assert api_result['_items'][0]['eth_A'] == '' assert api_result['_items'][0]['eth_B'] == '' assert api_result['_items'][0]['eth_type'] == 2048 assert api_result['_items'][0]['ip_A'] == '10.1.0.1' assert api_result['_items'][0]['ip_B'] == '10.1.0.2' assert api_result['_items'][0]['ip_proto'] == 6 assert api_result['_items'][0]['tp_A'] == 43297 assert api_result['_items'][0]['tp_B'] == 80 assert api_result['_items'][0]['flow_hash'] == '9822b2867652ee0957892482b9f004c3' assert api_result['_items'][0]['direction'] == 'forward' #*** Validate API Response parameters for second flow removal: assert api_result['_items'][1]['dpid'] == 1 #*** Note: can't easily test 'removal_time' as is dynamic, so skipping... assert api_result['_items'][1]['cookie'] == 1000000023 assert api_result['_items'][1]['priority'] == 1 assert api_result['_items'][1]['reason'] == 0 assert api_result['_items'][1]['table_id'] == 1 assert api_result['_items'][1]['duration_sec'] == 5 assert api_result['_items'][1]['idle_timeout'] == 5 assert api_result['_items'][1]['hard_timeout'] == 0 assert api_result['_items'][1]['packet_count'] == 9 assert api_result['_items'][1]['byte_count'] == 6644 assert api_result['_items'][1]['eth_A'] == '' assert api_result['_items'][1]['eth_B'] == '' assert api_result['_items'][1]['eth_type'] == 2048 assert api_result['_items'][1]['ip_A'] == '10.1.0.2' assert api_result['_items'][1]['ip_B'] == '10.1.0.1' assert api_result['_items'][1]['ip_proto'] == 6 assert api_result['_items'][1]['tp_A'] == 80 assert api_result['_items'][1]['tp_B'] == 43297 assert api_result['_items'][1]['flow_hash'] == '9822b2867652ee0957892482b9f004c3' assert api_result['_items'][1]['direction'] == 'reverse' #*** Stop api_external sub-process: api_ps.terminate()
def test_flows_removed_stats_count(): """ Test the flows_removed API stats count by ingesting flow removal messages then checking that the API response correctly specifies message count """ #*** Start api_external as separate process: logger.info("Starting api_external") api_ps = multiprocessing.Process( target=api.run, args=()) api_ps.start() #*** Supports OpenFlow version 1.3: OFP_VERSION = ofproto_v1_3.OFP_VERSION #*** Instantiate Flow class: flow = flows_module.Flow(config) #*** Load JSON representations of flow removed messages: with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file: json_str_tx = json_file.read() json_dict_tx = json.loads(json_str_tx) with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file: json_str_rx = json_file.read() json_dict_rx = json.loads(json_str_rx) #*** Set up fake datapath and synthesise messages: datapath = ofproto_protocol.ProtocolDesc(version=OFP_VERSION) datapath.id = 1 msg_tx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_tx) msg_rx = ofproto_parser.ofp_msg_from_jsondict(datapath, json_dict_rx) #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_STATS_COUNT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['flows_removed'] == 0 #*** Record flow removal to flow_rems database collection: flow.record_removal(msg_tx) #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_STATS_COUNT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['flows_removed'] == 1 #*** Record flow removal to flow_rems database collection: flow.record_removal(msg_rx) #*** Call the external API: api_result = get_api_result(URL_TEST_FLOWS_REMOVED_STATS_COUNT) logger.debug("api_result=%s", api_result) #*** Validate API Response parameters: assert api_result['flows_removed'] == 2 #*** Stop api_external sub-process: api_ps.terminate()