blob: 21f5f448a852e26f82333c7f7e9947df4ca92424 [file] [log] [blame]
#TopoPerfNext
#
#Topology Performance test for ONOS-next
#
#andrew@onlab.us
#
#If your machine does not come with numpy
#run the following command:
#sudo apt-get install python-numpy python-scipy
import time
import sys
import os
import re
class TopoPerfNext:
def __init__(self):
self.default = ''
def CASE1(self, main):
'''
ONOS startup sequence
'''
import time
cell_name = main.params['ENV']['cellName']
git_pull = main.params['GIT']['autoPull']
checkout_branch = main.params['GIT']['checkout']
ONOS1_ip = main.params['CTRL']['ip1']
ONOS2_ip = main.params['CTRL']['ip2']
ONOS3_ip = main.params['CTRL']['ip3']
#### Hardcoded ONOS nodes particular to my env ####
ONOS4_ip = "10.128.174.4"
ONOS5_ip = "10.128.174.5"
ONOS6_ip = "10.128.174.6"
ONOS7_ip = "10.128.174.7"
#### ####
MN1_ip = main.params['MN']['ip1']
BENCH_ip = main.params['BENCH']['ip']
main.case("Setting up test environment")
main.log.report("Setting up test environment")
main.step("Cleaning previously installed ONOS if any")
main.ONOSbench.onos_uninstall(node_ip=ONOS4_ip)
main.ONOSbench.onos_uninstall(node_ip=ONOS5_ip)
main.ONOSbench.onos_uninstall(node_ip=ONOS6_ip)
main.ONOSbench.onos_uninstall(node_ip=ONOS7_ip)
main.step("Creating cell file")
cell_file_result = main.ONOSbench.create_cell_file(
BENCH_ip, cell_name, MN1_ip, "onos-core",
ONOS1_ip, ONOS2_ip, ONOS3_ip)
main.step("Applying cell file to environment")
cell_apply_result = main.ONOSbench.set_cell(cell_name)
verify_cell_result = main.ONOSbench.verify_cell()
#NOTE: This step may be removed after proper
# copy cat log functionality
main.step("Removing raft/copy-cat logs from ONOS nodes")
main.ONOSbench.onos_remove_raft_logs()
main.step("Git checkout and pull "+checkout_branch)
if git_pull == 'on':
checkout_result = \
main.ONOSbench.git_checkout(checkout_branch)
pull_result = main.ONOSbench.git_pull()
else:
checkout_result = main.TRUE
pull_result = main.TRUE
main.log.info("Skipped git checkout and pull")
#TODO: Uncomment when wiki posting works
#main.log.report("Commit information - ")
#main.ONOSbench.get_version(report=True)
main.step("Using mvn clean & install")
#mvn_result = main.ONOSbench.clean_install()
mvn_result = main.TRUE
main.step("Set cell for ONOS cli env")
main.ONOS1cli.set_cell(cell_name)
main.ONOS2cli.set_cell(cell_name)
main.ONOS3cli.set_cell(cell_name)
main.step("Creating ONOS package")
package_result = main.ONOSbench.onos_package()
main.step("Installing ONOS package")
install1_result = main.ONOSbench.onos_install(node=ONOS1_ip)
install2_result = main.ONOSbench.onos_install(node=ONOS2_ip)
install3_result = main.ONOSbench.onos_install(node=ONOS3_ip)
time.sleep(10)
main.step("Start onos cli")
cli1 = main.ONOS1cli.start_onos_cli(ONOS1_ip)
cli2 = main.ONOS2cli.start_onos_cli(ONOS2_ip)
cli3 = main.ONOS3cli.start_onos_cli(ONOS3_ip)
main.step("Enable metrics feature")
main.ONOS1cli.feature_install("onos-app-metrics")
main.ONOS2cli.feature_install("onos-app-metrics")
main.ONOS3cli.feature_install("onos-app-metrics")
utilities.assert_equals(expect=main.TRUE,
actual= cell_file_result and cell_apply_result and\
verify_cell_result and checkout_result and\
pull_result and mvn_result and\
install1_result and install2_result and\
install3_result,
onpass="Test Environment setup successful",
onfail="Failed to setup test environment")
def CASE2(self, main):
'''
Assign s1 to ONOS1 and measure latency
There are 4 levels of latency measurements to this test:
1) End-to-end measurement: Complete end-to-end measurement
from TCP (SYN/ACK) handshake to Graph change
2) OFP-to-graph measurement: 'ONOS processing' snippet of
measurement from OFP Vendor message to Graph change
3) OFP-to-device measurement: 'ONOS processing without
graph change' snippet of measurement from OFP vendor
message to Device change timestamp
4) T0-to-device measurement: Measurement that includes
the switch handshake to devices timestamp without
the graph view change. (TCP handshake -> Device
change)
'''
import time
import subprocess
import json
import requests
import os
import numpy
ONOS1_ip = main.params['CTRL']['ip1']
ONOS2_ip = main.params['CTRL']['ip2']
ONOS3_ip = main.params['CTRL']['ip3']
ONOS_user = main.params['CTRL']['user']
default_sw_port = main.params['CTRL']['port1']
#Number of iterations of case
num_iter = main.params['TEST']['numIter']
#Number of first 'x' iterations to ignore:
iter_ignore = int(main.params['TEST']['iterIgnore'])
#Timestamp 'keys' for json metrics output.
#These are subject to change, hence moved into params
deviceTimestamp = main.params['JSON']['deviceTimestamp']
graphTimestamp = main.params['JSON']['graphTimestamp']
debug_mode = main.params['TEST']['debugMode']
onos_log = main.params['TEST']['onosLogFile']
#Threshold for the test
threshold_str = main.params['TEST']['singleSwThreshold']
threshold_obj = threshold_str.split(",")
threshold_min = int(threshold_obj[0])
threshold_max = int(threshold_obj[1])
#List of switch add latency collected from
#all iterations
latency_end_to_end_list = []
latency_ofp_to_graph_list = []
latency_ofp_to_device_list = []
latency_t0_to_device_list = []
latency_tcp_to_ofp_list = []
#Directory/file to store tshark results
tshark_of_output = "/tmp/tshark_of_topo.txt"
tshark_tcp_output = "/tmp/tshark_tcp_topo.txt"
#String to grep in tshark output
tshark_tcp_string = "TCP 74 "+default_sw_port
tshark_of_string = "OFP 86 Vendor"
#Initialize assertion to TRUE
assertion = main.TRUE
local_time = time.strftime('%x %X')
local_time = local_time.replace("/","")
local_time = local_time.replace(" ","_")
local_time = local_time.replace(":","")
if debug_mode == 'on':
main.ONOS1.tshark_pcap("eth0",
"/tmp/single_sw_lat_pcap_"+local_time)
main.log.info("TEST")
main.log.report("Latency of adding one switch to controller")
main.log.report("First "+str(iter_ignore)+" iterations ignored"+
" for jvm warmup time")
main.log.report("Total iterations of test: "+str(num_iter))
for i in range(0, int(num_iter)):
main.log.info("Starting tshark capture")
#* TCP [ACK, SYN] is used as t0_a, the
# very first "exchange" between ONOS and
# the switch for end-to-end measurement
#* OFP [Stats Reply] is used for t0_b
# the very last OFP message between ONOS
# and the switch for ONOS measurement
main.ONOS1.tshark_grep(tshark_tcp_string,
tshark_tcp_output)
main.ONOS1.tshark_grep(tshark_of_string,
tshark_of_output)
#Wait and ensure tshark is started and
#capturing
time.sleep(10)
main.log.info("Assigning s1 to controller")
main.Mininet1.assign_sw_controller(sw="1",
ip1=ONOS1_ip, port1=default_sw_port)
#Wait and ensure switch is assigned
#before stopping tshark
time.sleep(30)
main.log.info("Stopping all Tshark processes")
main.ONOS1.stop_tshark()
#tshark output is saved in ONOS. Use subprocess
#to copy over files to TestON for parsing
main.log.info("Copying over tshark files")
#TCP CAPTURE ****
#Copy the tshark output from ONOS machine to
#TestON machine in tshark_tcp_output directory>file
os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
tshark_tcp_output+" /tmp/")
tcp_file = open(tshark_tcp_output, 'r')
temp_text = tcp_file.readline()
temp_text = temp_text.split(" ")
main.log.info("Object read in from TCP capture: "+
str(temp_text))
if len(temp_text) > 1:
t0_tcp = float(temp_text[1])*1000.0
else:
main.log.error("Tshark output file for TCP"+
" returned unexpected results")
t0_tcp = 0
assertion = main.FALSE
tcp_file.close()
#****************
#OF CAPTURE ****
os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
tshark_of_output+" /tmp/")
of_file = open(tshark_of_output, 'r')
line_ofp = ""
#Read until last line of file
while True:
temp_text = of_file.readline()
if temp_text !='':
line_ofp = temp_text
else:
break
obj = line_ofp.split(" ")
main.log.info("Object read in from OFP capture: "+
str(line_ofp))
if len(line_ofp) > 1:
t0_ofp = float(obj[1])*1000.0
else:
main.log.error("Tshark output file for OFP"+
" returned unexpected results")
t0_ofp = 0
assertion = main.FALSE
of_file.close()
#****************
json_str_1 = main.ONOS1cli.topology_events_metrics()
json_str_2 = main.ONOS2cli.topology_events_metrics()
json_str_3 = main.ONOS3cli.topology_events_metrics()
json_obj_1 = json.loads(json_str_1)
json_obj_2 = json.loads(json_str_2)
json_obj_3 = json.loads(json_str_3)
#Obtain graph timestamp. This timestsamp captures
#the epoch time at which the topology graph was updated.
graph_timestamp_1 = \
json_obj_1[graphTimestamp]['value']
graph_timestamp_2 = \
json_obj_2[graphTimestamp]['value']
graph_timestamp_3 = \
json_obj_3[graphTimestamp]['value']
#Obtain device timestamp. This timestamp captures
#the epoch time at which the device event happened
device_timestamp_1 = \
json_obj_1[deviceTimestamp]['value']
device_timestamp_2 = \
json_obj_2[deviceTimestamp]['value']
device_timestamp_3 = \
json_obj_3[deviceTimestamp]['value']
#t0 to device processing latency
delta_device_1 = int(device_timestamp_1) - int(t0_tcp)
delta_device_2 = int(device_timestamp_2) - int(t0_tcp)
delta_device_3 = int(device_timestamp_3) - int(t0_tcp)
#Get average of delta from all instances
avg_delta_device = \
(int(delta_device_1)+\
int(delta_device_2)+\
int(delta_device_3)) / 3
#Ensure avg delta meets the threshold before appending
if avg_delta_device > 0.0 and avg_delta_device < 10000\
and int(i) > iter_ignore:
latency_t0_to_device_list.append(avg_delta_device)
else:
main.log.info("Results for t0-to-device ignored"+\
"due to excess in threshold / warmup iteration.")
#t0 to graph processing latency (end-to-end)
delta_graph_1 = int(graph_timestamp_1) - int(t0_tcp)
delta_graph_2 = int(graph_timestamp_2) - int(t0_tcp)
delta_graph_3 = int(graph_timestamp_3) - int(t0_tcp)
#Get average of delta from all instances
avg_delta_graph = \
(int(delta_graph_1)+\
int(delta_graph_2)+\
int(delta_graph_3)) / 3
#Ensure avg delta meets the threshold before appending
if avg_delta_graph > 0.0 and avg_delta_graph < 10000\
and int(i) > iter_ignore:
latency_end_to_end_list.append(avg_delta_graph)
else:
main.log.info("Results for end-to-end ignored"+\
"due to excess in threshold")
#ofp to graph processing latency (ONOS processing)
delta_ofp_graph_1 = int(graph_timestamp_1) - int(t0_ofp)
delta_ofp_graph_2 = int(graph_timestamp_2) - int(t0_ofp)
delta_ofp_graph_3 = int(graph_timestamp_3) - int(t0_ofp)
avg_delta_ofp_graph = \
(int(delta_ofp_graph_1)+\
int(delta_ofp_graph_2)+\
int(delta_ofp_graph_3)) / 3
if avg_delta_ofp_graph > threshold_min \
and avg_delta_ofp_graph < threshold_max\
and int(i) > iter_ignore:
latency_ofp_to_graph_list.append(avg_delta_ofp_graph)
elif avg_delta_ofp_graph > (-10) and \
avg_delta_ofp_graph < 0.0 and\
int(i) > iter_ignore:
main.log.info("Sub-millisecond result likely; "+
"negative result was rounded to 0")
#NOTE: Current metrics framework does not
#support sub-millisecond accuracy. Therefore,
#if the result is negative, we can reasonably
#conclude sub-millisecond results and just
#append the best rounded effort - 0 ms.
latency_ofp_to_graph_list.append(0)
else:
main.log.info("Results for ofp-to-graph "+\
"ignored due to excess in threshold")
#ofp to device processing latency (ONOS processing)
delta_ofp_device_1 = float(device_timestamp_1) - float(t0_ofp)
delta_ofp_device_2 = float(device_timestamp_2) - float(t0_ofp)
delta_ofp_device_3 = float(device_timestamp_3) - float(t0_ofp)
avg_delta_ofp_device = \
(float(delta_ofp_device_1)+\
float(delta_ofp_device_2)+\
float(delta_ofp_device_3)) / 3
#NOTE: ofp - delta measurements are occasionally negative
# due to system time misalignment.
latency_ofp_to_device_list.append(avg_delta_ofp_device)
delta_ofp_tcp = int(t0_ofp) - int(t0_tcp)
if delta_ofp_tcp > threshold_min \
and delta_ofp_tcp < threshold_max and\
int(i) > iter_ignore:
latency_tcp_to_ofp_list.append(delta_ofp_tcp)
else:
main.log.info("Results fo tcp-to-ofp "+\
"ignored due to excess in threshold")
#TODO:
#Fetch logs upon threshold excess
main.log.info("ONOS1 delta end-to-end: "+
str(delta_graph_1) + " ms")
main.log.info("ONOS2 delta end-to-end: "+
str(delta_graph_2) + " ms")
main.log.info("ONOS3 delta end-to-end: "+
str(delta_graph_3) + " ms")
main.log.info("ONOS1 delta OFP - graph: "+
str(delta_ofp_graph_1) + " ms")
main.log.info("ONOS2 delta OFP - graph: "+
str(delta_ofp_graph_2) + " ms")
main.log.info("ONOS3 delta OFP - graph: "+
str(delta_ofp_graph_3) + " ms")
main.log.info("ONOS1 delta device - t0: "+
str(delta_device_1) + " ms")
main.log.info("ONOS2 delta device - t0: "+
str(delta_device_2) + " ms")
main.log.info("ONOS3 delta device - t0: "+
str(delta_device_3) + " ms")
main.log.info("TCP to OFP delta: "+
str(delta_ofp_tcp) + " ms")
#main.log.info("ONOS1 delta OFP - device: "+
# str(delta_ofp_device_1) + " ms")
#main.log.info("ONOS2 delta OFP - device: "+
# str(delta_ofp_device_2) + " ms")
#main.log.info("ONOS3 delta OFP - device: "+
# str(delta_ofp_device_3) + " ms")
main.step("Remove switch from controller")
main.Mininet1.delete_sw_controller("s1")
time.sleep(5)
#END of for loop iteration
#If there is at least 1 element in each list,
#pass the test case
if len(latency_end_to_end_list) > 0 and\
len(latency_ofp_to_graph_list) > 0 and\
len(latency_ofp_to_device_list) > 0 and\
len(latency_t0_to_device_list) > 0 and\
len(latency_tcp_to_ofp_list) > 0:
assertion = main.TRUE
elif len(latency_end_to_end_list) == 0:
#The appending of 0 here is to prevent
#the min,max,sum functions from failing
#below
latency_end_to_end_list.append(0)
assertion = main.FALSE
elif len(latency_ofp_to_graph_list) == 0:
latency_ofp_to_graph_list.append(0)
assertion = main.FALSE
elif len(latency_ofp_to_device_list) == 0:
latency_ofp_to_device_list.append(0)
assertion = main.FALSE
elif len(latency_t0_to_device_list) == 0:
latency_t0_to_device_list.append(0)
assertion = main.FALSE
elif len(latency_tcp_to_ofp_list) == 0:
latency_tcp_to_ofp_list.append(0)
assertion = main.FALSE
#Calculate min, max, avg of latency lists
latency_end_to_end_max = \
int(max(latency_end_to_end_list))
latency_end_to_end_min = \
int(min(latency_end_to_end_list))
latency_end_to_end_avg = \
(int(sum(latency_end_to_end_list)) / \
len(latency_end_to_end_list))
latency_end_to_end_std_dev = \
str(round(numpy.std(latency_end_to_end_list),1))
latency_ofp_to_graph_max = \
int(max(latency_ofp_to_graph_list))
latency_ofp_to_graph_min = \
int(min(latency_ofp_to_graph_list))
latency_ofp_to_graph_avg = \
(int(sum(latency_ofp_to_graph_list)) / \
len(latency_ofp_to_graph_list))
latency_ofp_to_graph_std_dev = \
str(round(numpy.std(latency_ofp_to_graph_list),1))
latency_ofp_to_device_max = \
int(max(latency_ofp_to_device_list))
latency_ofp_to_device_min = \
int(min(latency_ofp_to_device_list))
latency_ofp_to_device_avg = \
(int(sum(latency_ofp_to_device_list)) / \
len(latency_ofp_to_device_list))
latency_ofp_to_device_std_dev = \
str(round(numpy.std(latency_ofp_to_device_list),1))
latency_t0_to_device_max = \
int(max(latency_t0_to_device_list))
latency_t0_to_device_min = \
int(min(latency_t0_to_device_list))
latency_t0_to_device_avg = \
(int(sum(latency_t0_to_device_list)) / \
len(latency_t0_to_device_list))
latency_ofp_to_device_std_dev = \
str(round(numpy.std(latency_t0_to_device_list),1))
latency_tcp_to_ofp_max = \
int(max(latency_tcp_to_ofp_list))
latency_tcp_to_ofp_min = \
int(min(latency_tcp_to_ofp_list))
latency_tcp_to_ofp_avg = \
(int(sum(latency_tcp_to_ofp_list)) / \
len(latency_tcp_to_ofp_list))
latency_tcp_to_ofp_std_dev = \
str(round(numpy.std(latency_tcp_to_ofp_list),1))
main.log.report("Switch add - End-to-end latency: "+\
"Avg: "+str(latency_end_to_end_avg)+" ms "+
"Std Deviation: "+latency_end_to_end_std_dev+" ms")
main.log.report("Switch add - OFP-to-Graph latency: "+\
"Note: results are not accurate to sub-millisecond. "+
"Any sub-millisecond results are rounded to 0 ms. ")
main.log.report("Avg: "+str(latency_ofp_to_graph_avg)+" ms "+
"Std Deviation: "+latency_ofp_to_graph_std_dev+" ms")
main.log.report("Switch add - TCP-to-OFP latency: "+\
"Avg: "+str(latency_tcp_to_ofp_avg)+" ms "+
"Std Deviation: "+latency_tcp_to_ofp_std_dev+" ms")
if debug_mode == 'on':
main.ONOS1.cp_logs_to_dir("/opt/onos/log/karaf.log",
"/tmp/", copy_file_name="sw_lat_karaf")
utilities.assert_equals(expect=main.TRUE, actual=assertion,
onpass="Switch latency test successful",
onfail="Switch latency test failed")
def CASE3(self, main):
'''
Bring port up / down and measure latency.
Port enable / disable is simulated by ifconfig up / down
In ONOS-next, we must ensure that the port we are
manipulating is connected to another switch with a valid
connection. Otherwise, graph view will not be updated.
'''
import time
import subprocess
import os
import requests
import json
import numpy
ONOS1_ip = main.params['CTRL']['ip1']
ONOS2_ip = main.params['CTRL']['ip2']
ONOS3_ip = main.params['CTRL']['ip3']
ONOS_user = main.params['CTRL']['user']
default_sw_port = main.params['CTRL']['port1']
assertion = main.TRUE
#Number of iterations of case
num_iter = main.params['TEST']['numIter']
#Timestamp 'keys' for json metrics output.
#These are subject to change, hence moved into params
deviceTimestamp = main.params['JSON']['deviceTimestamp']
graphTimestamp = main.params['JSON']['graphTimestamp']
debug_mode = main.params['TEST']['debugMode']
local_time = time.strftime('%x %X')
local_time = local_time.replace("/","")
local_time = local_time.replace(" ","_")
local_time = local_time.replace(":","")
if debug_mode == 'on':
main.ONOS1.tshark_pcap("eth0",
"/tmp/port_lat_pcap_"+local_time)
#Threshold for this test case
up_threshold_str = main.params['TEST']['portUpThreshold']
down_threshold_str = main.params['TEST']['portDownThreshold']
up_threshold_obj = up_threshold_str.split(",")
down_threshold_obj = down_threshold_str.split(",")
up_threshold_min = int(up_threshold_obj[0])
up_threshold_max = int(up_threshold_obj[1])
down_threshold_min = int(down_threshold_obj[0])
down_threshold_max = int(down_threshold_obj[1])
#NOTE: Some hardcoded variables you may need to configure
# besides the params
tshark_port_status = "OFP 130 Port Status"
tshark_port_up = "/tmp/tshark_port_up.txt"
tshark_port_down = "/tmp/tshark_port_down.txt"
interface_config = "s1-eth1"
main.log.report("Port enable / disable latency")
main.log.report("Simulated by ifconfig up / down")
main.log.report("Total iterations of test: "+str(num_iter))
main.step("Assign switches s1 and s2 to controller 1")
main.Mininet1.assign_sw_controller(sw="1",ip1=ONOS1_ip,
port1=default_sw_port)
main.Mininet1.assign_sw_controller(sw="2",ip1=ONOS1_ip,
port1=default_sw_port)
#Give enough time for metrics to propagate the
#assign controller event. Otherwise, these events may
#carry over to our measurements
time.sleep(15)
port_up_device_to_ofp_list = []
port_up_graph_to_ofp_list = []
port_down_device_to_ofp_list = []
port_down_graph_to_ofp_list = []
for i in range(0, int(num_iter)):
main.step("Starting wireshark capture for port status down")
main.ONOS1.tshark_grep(tshark_port_status,
tshark_port_down)
time.sleep(5)
#Disable interface that is connected to switch 2
main.step("Disable port: "+interface_config)
main.Mininet1.handle.sendline("sh ifconfig "+
interface_config+" down")
main.Mininet1.handle.expect("mininet>")
time.sleep(3)
main.ONOS1.tshark_stop()
main.step("Obtain t1 by metrics call")
json_str_up_1 = main.ONOS1cli.topology_events_metrics()
json_str_up_2 = main.ONOS2cli.topology_events_metrics()
json_str_up_3 = main.ONOS3cli.topology_events_metrics()
json_obj_1 = json.loads(json_str_up_1)
json_obj_2 = json.loads(json_str_up_2)
json_obj_3 = json.loads(json_str_up_3)
#Copy tshark output file from ONOS to TestON instance
#/tmp directory
os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
tshark_port_down+" /tmp/")
f_port_down = open(tshark_port_down, 'r')
#Get first line of port down event from tshark
f_line = f_port_down.readline()
obj_down = f_line.split(" ")
if len(f_line) > 0:
timestamp_begin_pt_down = int(float(obj_down[1])*1000)
main.log.info("Port down begin timestamp: "+
str(timestamp_begin_pt_down))
else:
main.log.info("Tshark output file returned unexpected"+
" results: "+str(obj_down))
timestamp_begin_pt_down = 0
f_port_down.close()
main.log.info("TEST tshark obj: "+str(obj_down))
time.sleep(3)
#Obtain graph timestamp. This timestsamp captures
#the epoch time at which the topology graph was updated.
graph_timestamp_1 = \
json_obj_1[graphTimestamp]['value']
graph_timestamp_2 = \
json_obj_2[graphTimestamp]['value']
graph_timestamp_3 = \
json_obj_3[graphTimestamp]['value']
main.log.info("TEST graph timestamp ONOS1: "+
str(graph_timestamp_1))
#Obtain device timestamp. This timestamp captures
#the epoch time at which the device event happened
device_timestamp_1 = \
json_obj_1[deviceTimestamp]['value']
device_timestamp_2 = \
json_obj_2[deviceTimestamp]['value']
device_timestamp_3 = \
json_obj_3[deviceTimestamp]['value']
#Get delta between graph event and OFP
pt_down_graph_to_ofp_1 = int(graph_timestamp_1) -\
int(timestamp_begin_pt_down)
pt_down_graph_to_ofp_2 = int(graph_timestamp_2) -\
int(timestamp_begin_pt_down)
pt_down_graph_to_ofp_3 = int(graph_timestamp_3) -\
int(timestamp_begin_pt_down)
#Get delta between device event and OFP
pt_down_device_to_ofp_1 = int(device_timestamp_1) -\
int(timestamp_begin_pt_down)
pt_down_device_to_ofp_2 = int(device_timestamp_2) -\
int(timestamp_begin_pt_down)
pt_down_device_to_ofp_3 = int(device_timestamp_3) -\
int(timestamp_begin_pt_down)
#Caluclate average across clusters
pt_down_graph_to_ofp_avg =\
(int(pt_down_graph_to_ofp_1) +
int(pt_down_graph_to_ofp_2) +
int(pt_down_graph_to_ofp_3)) / 3
pt_down_device_to_ofp_avg = \
(int(pt_down_device_to_ofp_1) +
int(pt_down_device_to_ofp_2) +
int(pt_down_device_to_ofp_3)) / 3
if pt_down_graph_to_ofp_avg > down_threshold_min and \
pt_down_graph_to_ofp_avg < down_threshold_max:
port_down_graph_to_ofp_list.append(
pt_down_graph_to_ofp_avg)
main.log.info("Port down: graph to ofp avg: "+
str(pt_down_graph_to_ofp_avg) + " ms")
else:
main.log.info("Average port down graph-to-ofp result" +
" exceeded the threshold: "+
str(pt_down_graph_to_ofp_avg))
if pt_down_device_to_ofp_avg > 0 and \
pt_down_device_to_ofp_avg < 1000:
port_down_device_to_ofp_list.append(
pt_down_device_to_ofp_avg)
main.log.info("Port down: device to ofp avg: "+
str(pt_down_device_to_ofp_avg) + " ms")
else:
main.log.info("Average port down device-to-ofp result" +
" exceeded the threshold: "+
str(pt_down_device_to_ofp_avg))
#Port up events
main.step("Enable port and obtain timestamp")
main.step("Starting wireshark capture for port status up")
main.ONOS1.tshark_grep(tshark_port_status, tshark_port_up)
time.sleep(5)
main.Mininet1.handle.sendline("sh ifconfig "+
interface_config+" up")
main.Mininet1.handle.expect("mininet>")
#Allow time for tshark to capture event
time.sleep(3)
main.ONOS1.tshark_stop()
#Obtain metrics shortly afterwards
#This timestsamp captures
#the epoch time at which the topology graph was updated.
main.step("Obtain t1 by REST call")
json_str_up_1 = main.ONOS1cli.topology_events_metrics()
json_str_up_2 = main.ONOS2cli.topology_events_metrics()
json_str_up_3 = main.ONOS3cli.topology_events_metrics()
json_obj_1 = json.loads(json_str_up_1)
json_obj_2 = json.loads(json_str_up_2)
json_obj_3 = json.loads(json_str_up_3)
os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
tshark_port_up+" /tmp/")
f_port_up = open(tshark_port_up, 'r')
f_line = f_port_up.readline()
obj_up = f_line.split(" ")
if len(f_line) > 0:
timestamp_begin_pt_up = int(float(obj_up[1])*1000)
main.log.info("Port up begin timestamp: "+
str(timestamp_begin_pt_up))
else:
main.log.info("Tshark output file returned unexpected"+
" results.")
timestamp_begin_pt_up = 0
f_port_up.close()
graph_timestamp_1 = \
json_obj_1[graphTimestamp]['value']
graph_timestamp_2 = \
json_obj_2[graphTimestamp]['value']
graph_timestamp_3 = \
json_obj_3[graphTimestamp]['value']
#Obtain device timestamp. This timestamp captures
#the epoch time at which the device event happened
device_timestamp_1 = \
json_obj_1[deviceTimestamp]['value']
device_timestamp_2 = \
json_obj_2[deviceTimestamp]['value']
device_timestamp_3 = \
json_obj_3[deviceTimestamp]['value']
#Get delta between graph event and OFP
pt_up_graph_to_ofp_1 = int(graph_timestamp_1) -\
int(timestamp_begin_pt_up)
pt_up_graph_to_ofp_2 = int(graph_timestamp_2) -\
int(timestamp_begin_pt_up)
pt_up_graph_to_ofp_3 = int(graph_timestamp_3) -\
int(timestamp_begin_pt_up)
#Get delta between device event and OFP
pt_up_device_to_ofp_1 = int(device_timestamp_1) -\
int(timestamp_begin_pt_up)
pt_up_device_to_ofp_2 = int(device_timestamp_2) -\
int(timestamp_begin_pt_up)
pt_up_device_to_ofp_3 = int(device_timestamp_3) -\
int(timestamp_begin_pt_up)
main.log.info("ONOS1 delta G2O: "+str(pt_up_graph_to_ofp_1))
main.log.info("ONOS2 delta G2O: "+str(pt_up_graph_to_ofp_2))
main.log.info("ONOS3 delta G2O: "+str(pt_up_graph_to_ofp_3))
main.log.info("ONOS1 delta D2O: "+str(pt_up_device_to_ofp_1))
main.log.info("ONOS2 delta D2O: "+str(pt_up_device_to_ofp_2))
main.log.info("ONOS3 delta D2O: "+str(pt_up_device_to_ofp_3))
pt_up_graph_to_ofp_avg = \
(int(pt_up_graph_to_ofp_1) +
int(pt_up_graph_to_ofp_2) +
int(pt_up_graph_to_ofp_3)) / 3
pt_up_device_to_ofp_avg = \
(int(pt_up_device_to_ofp_1) +
int(pt_up_device_to_ofp_2) +
int(pt_up_device_to_ofp_3)) / 3
if pt_up_graph_to_ofp_avg > up_threshold_min and \
pt_up_graph_to_ofp_avg < up_threshold_max:
port_up_graph_to_ofp_list.append(
pt_up_graph_to_ofp_avg)
main.log.info("Port down: graph to ofp avg: "+
str(pt_up_graph_to_ofp_avg) + " ms")
else:
main.log.info("Average port up graph-to-ofp result"+
" exceeded the threshold: "+
str(pt_up_graph_to_ofp_avg))
if pt_up_device_to_ofp_avg > up_threshold_min and \
pt_up_device_to_ofp_avg < up_threshold_max:
port_up_device_to_ofp_list.append(
pt_up_device_to_ofp_avg)
main.log.info("Port up: device to ofp avg: "+
str(pt_up_device_to_ofp_avg) + " ms")
else:
main.log.info("Average port up device-to-ofp result"+
" exceeded the threshold: "+
str(pt_up_device_to_ofp_avg))
#END ITERATION FOR LOOP
#Check all list for latency existence and set assertion
if (port_down_graph_to_ofp_list and port_down_device_to_ofp_list\
and port_up_graph_to_ofp_list and port_up_device_to_ofp_list):
assertion = main.TRUE
#Calculate and report latency measurements
port_down_graph_to_ofp_min = min(port_down_graph_to_ofp_list)
port_down_graph_to_ofp_max = max(port_down_graph_to_ofp_list)
port_down_graph_to_ofp_avg = \
(sum(port_down_graph_to_ofp_list) /
len(port_down_graph_to_ofp_list))
port_down_graph_to_ofp_std_dev = \
str(round(numpy.std(port_down_graph_to_ofp_list),1))
main.log.report("Port down graph-to-ofp "+
"Avg: "+str(port_down_graph_to_ofp_avg)+" ms "+
"Std Deviation: "+port_down_graph_to_ofp_std_dev+" ms")
port_down_device_to_ofp_min = min(port_down_device_to_ofp_list)
port_down_device_to_ofp_max = max(port_down_device_to_ofp_list)
port_down_device_to_ofp_avg = \
(sum(port_down_device_to_ofp_list) /\
len(port_down_device_to_ofp_list))
port_down_device_to_ofp_std_dev = \
str(round(numpy.std(port_down_device_to_ofp_list),1))
main.log.report("Port down device-to-ofp "+
"Avg: "+str(port_down_device_to_ofp_avg)+" ms "+
"Std Deviation: "+port_down_device_to_ofp_std_dev+" ms")
port_up_graph_to_ofp_min = min(port_up_graph_to_ofp_list)
port_up_graph_to_ofp_max = max(port_up_graph_to_ofp_list)
port_up_graph_to_ofp_avg = \
(sum(port_up_graph_to_ofp_list) /\
len(port_up_graph_to_ofp_list))
port_up_graph_to_ofp_std_dev = \
str(round(numpy.std(port_up_graph_to_ofp_list),1))
main.log.report("Port up graph-to-ofp "+
"Avg: "+str(port_up_graph_to_ofp_avg)+" ms "+
"Std Deviation: "+port_up_graph_to_ofp_std_dev+" ms")
port_up_device_to_ofp_min = min(port_up_device_to_ofp_list)
port_up_device_to_ofp_max = max(port_up_device_to_ofp_list)
port_up_device_to_ofp_avg = \
(sum(port_up_device_to_ofp_list) /\
len(port_up_device_to_ofp_list))
port_up_device_to_ofp_std_dev = \
str(round(numpy.std(port_up_device_to_ofp_list),1))
main.log.report("Port up device-to-ofp "+
"Avg: "+str(port_up_device_to_ofp_avg)+" ms "+
"Std Deviation: "+port_up_device_to_ofp_std_dev+" ms")
utilities.assert_equals(expect=main.TRUE, actual=assertion,
onpass="Port discovery latency calculation successful",
onfail="Port discovery test failed")
def CASE4(self, main):
'''
Link down event using loss rate 100%
Important:
Use a simple 2 switch topology with 1 link between
the two switches. Ensure that mac addresses of the
switches are 1 / 2 respectively
'''
import time
import subprocess
import os
import requests
import json
import numpy
ONOS1_ip = main.params['CTRL']['ip1']
ONOS2_ip = main.params['CTRL']['ip2']
ONOS3_ip = main.params['CTRL']['ip3']
ONOS_user = main.params['CTRL']['user']
default_sw_port = main.params['CTRL']['port1']
#Number of iterations of case
num_iter = main.params['TEST']['numIter']
#Timestamp 'keys' for json metrics output.
#These are subject to change, hence moved into params
deviceTimestamp = main.params['JSON']['deviceTimestamp']
linkTimestamp = main.params['JSON']['linkTimestamp']
graphTimestamp = main.params['JSON']['graphTimestamp']
debug_mode = main.params['TEST']['debugMode']
local_time = time.strftime('%x %X')
local_time = local_time.replace("/","")
local_time = local_time.replace(" ","_")
local_time = local_time.replace(":","")
if debug_mode == 'on':
main.ONOS1.tshark_pcap("eth0",
"/tmp/link_lat_pcap_"+local_time)
#Threshold for this test case
up_threshold_str = main.params['TEST']['linkUpThreshold']
down_threshold_str = main.params['TEST']['linkDownThreshold']
up_threshold_obj = up_threshold_str.split(",")
down_threshold_obj = down_threshold_str.split(",")
up_threshold_min = int(up_threshold_obj[0])
up_threshold_max = int(up_threshold_obj[1])
down_threshold_min = int(down_threshold_obj[0])
down_threshold_max = int(down_threshold_obj[1])
assertion = main.TRUE
#Link event timestamp to system time list
link_down_link_to_system_list = []
link_up_link_to_system_list = []
#Graph event timestamp to system time list
link_down_graph_to_system_list = []
link_up_graph_to_system_list = []
main.log.report("Link up / down discovery latency between "+
"two switches")
main.log.report("Simulated by setting loss-rate 100%")
main.log.report("'tc qdisc add dev <intfs> root netem loss 100%'")
main.log.report("Total iterations of test: "+str(num_iter))
main.step("Assign all switches")
main.Mininet1.assign_sw_controller(sw="1",
ip1=ONOS1_ip, port1=default_sw_port)
main.Mininet1.assign_sw_controller(sw="2",
ip1=ONOS1_ip, port1=default_sw_port)
main.step("Verifying switch assignment")
result_s1 = main.Mininet1.get_sw_controller(sw="s1")
result_s2 = main.Mininet1.get_sw_controller(sw="s2")
#Allow time for events to finish before taking measurements
time.sleep(10)
link_down1 = False
link_down2 = False
link_down3 = False
#Start iteration of link event test
for i in range(0, int(num_iter)):
main.step("Getting initial system time as t0")
timestamp_link_down_t0 = time.time() * 1000
#Link down is simulated by 100% loss rate using traffic
#control command
main.Mininet1.handle.sendline(
"sh tc qdisc add dev s1-eth1 root netem loss 100%")
#TODO: Iterate through 'links' command to verify that
# link s1 -> s2 went down (loop timeout 30 seconds)
# on all 3 ONOS instances
main.log.info("Checking ONOS for link update")
loop_count = 0
while( not (link_down1 and link_down2 and link_down3)\
and loop_count < 30 ):
json_str1 = main.ONOS1cli.links()
json_str2 = main.ONOS2cli.links()
json_str3 = main.ONOS3cli.links()
if not (json_str1 and json_str2 and json_str3):
main.log.error("CLI command returned error ")
break
else:
json_obj1 = json.loads(json_str1)
json_obj2 = json.loads(json_str2)
json_obj3 = json.loads(json_str3)
for obj1 in json_obj1:
if '01' not in obj1['src']['device']:
link_down1 = True
main.log.info("Link down from "+
"s1 -> s2 on ONOS1 detected")
for obj2 in json_obj2:
if '01' not in obj2['src']['device']:
link_down2 = True
main.log.info("Link down from "+
"s1 -> s2 on ONOS2 detected")
for obj3 in json_obj3:
if '01' not in obj3['src']['device']:
link_down3 = True
main.log.info("Link down from "+
"s1 -> s2 on ONOS3 detected")
loop_count += 1
#If CLI doesn't like the continuous requests
#and exits in this loop, increase the sleep here.
#Consequently, while loop timeout will increase
time.sleep(1)
#Give time for metrics measurement to catch up
#NOTE: May need to be configured more accurately
time.sleep(10)
#If we exited the while loop and link down 1,2,3 are still
#false, then ONOS has failed to discover link down event
if not (link_down1 and link_down2 and link_down3):
main.log.info("Link down discovery failed")
link_down_lat_graph1 = 0
link_down_lat_graph2 = 0
link_down_lat_graph3 = 0
link_down_lat_device1 = 0
link_down_lat_device2 = 0
link_down_lat_device3 = 0
assertion = main.FALSE
else:
json_topo_metrics_1 =\
main.ONOS1cli.topology_events_metrics()
json_topo_metrics_2 =\
main.ONOS2cli.topology_events_metrics()
json_topo_metrics_3 =\
main.ONOS3cli.topology_events_metrics()
json_topo_metrics_1 = json.loads(json_topo_metrics_1)
json_topo_metrics_2 = json.loads(json_topo_metrics_2)
json_topo_metrics_3 = json.loads(json_topo_metrics_3)
main.log.info("Obtaining graph and device timestamp")
graph_timestamp_1 = \
json_topo_metrics_1[graphTimestamp]['value']
graph_timestamp_2 = \
json_topo_metrics_2[graphTimestamp]['value']
graph_timestamp_3 = \
json_topo_metrics_3[graphTimestamp]['value']
link_timestamp_1 = \
json_topo_metrics_1[linkTimestamp]['value']
link_timestamp_2 = \
json_topo_metrics_2[linkTimestamp]['value']
link_timestamp_3 = \
json_topo_metrics_3[linkTimestamp]['value']
if graph_timestamp_1 and graph_timestamp_2 and\
graph_timestamp_3 and link_timestamp_1 and\
link_timestamp_2 and link_timestamp_3:
link_down_lat_graph1 = int(graph_timestamp_1) -\
int(timestamp_link_down_t0)
link_down_lat_graph2 = int(graph_timestamp_2) -\
int(timestamp_link_down_t0)
link_down_lat_graph3 = int(graph_timestamp_3) -\
int(timestamp_link_down_t0)
link_down_lat_link1 = int(link_timestamp_1) -\
int(timestamp_link_down_t0)
link_down_lat_link2 = int(link_timestamp_2) -\
int(timestamp_link_down_t0)
link_down_lat_link3 = int(link_timestamp_3) -\
int(timestamp_link_down_t0)
else:
main.log.error("There was an error calculating"+
" the delta for link down event")
link_down_lat_graph1 = 0
link_down_lat_graph2 = 0
link_down_lat_graph3 = 0
link_down_lat_device1 = 0
link_down_lat_device2 = 0
link_down_lat_device3 = 0
main.log.info("Link down latency ONOS1 iteration "+
str(i)+" (end-to-end): "+
str(link_down_lat_graph1)+" ms")
main.log.info("Link down latency ONOS2 iteration "+
str(i)+" (end-to-end): "+
str(link_down_lat_graph2)+" ms")
main.log.info("Link down latency ONOS3 iteration "+
str(i)+" (end-to-end): "+
str(link_down_lat_graph3)+" ms")
main.log.info("Link down latency ONOS1 iteration "+
str(i)+" (link-event-to-system-timestamp): "+
str(link_down_lat_link1)+" ms")
main.log.info("Link down latency ONOS2 iteration "+
str(i)+" (link-event-to-system-timestamp): "+
str(link_down_lat_link2)+" ms")
main.log.info("Link down latency ONOS3 iteration "+
str(i)+" (link-event-to-system-timestamp): "+
str(link_down_lat_link3))
#Calculate avg of node calculations
link_down_lat_graph_avg =\
(link_down_lat_graph1 +
link_down_lat_graph2 +
link_down_lat_graph3) / 3
link_down_lat_link_avg =\
(link_down_lat_link1 +
link_down_lat_link2 +
link_down_lat_link3) / 3
#Set threshold and append latency to list
if link_down_lat_graph_avg > down_threshold_min and\
link_down_lat_graph_avg < down_threshold_max:
link_down_graph_to_system_list.append(
link_down_lat_graph_avg)
else:
main.log.info("Link down latency exceeded threshold")
main.log.info("Results for iteration "+str(i)+
"have been omitted")
if link_down_lat_link_avg > down_threshold_min and\
link_down_lat_link_avg < down_threshold_max:
link_down_link_to_system_list.append(
link_down_lat_link_avg)
else:
main.log.info("Link down latency exceeded threshold")
main.log.info("Results for iteration "+str(i)+
"have been omitted")
#NOTE: To remove loss rate and measure latency:
# 'sh tc qdisc del dev s1-eth1 root'
timestamp_link_up_t0 = time.time() * 1000
main.Mininet1.handle.sendline("sh tc qdisc del dev "+
"s1-eth1 root")
main.Mininet1.handle.expect("mininet>")
main.log.info("Checking ONOS for link update")
link_down1 = True
link_down2 = True
link_down3 = True
loop_count = 0
while( (link_down1 and link_down2 and link_down3)\
and loop_count < 30 ):
json_str1 = main.ONOS1cli.links()
json_str2 = main.ONOS2cli.links()
json_str3 = main.ONOS3cli.links()
if not (json_str1 and json_str2 and json_str3):
main.log.error("CLI command returned error ")
break
else:
json_obj1 = json.loads(json_str1)
json_obj2 = json.loads(json_str2)
json_obj3 = json.loads(json_str3)
for obj1 in json_obj1:
if '01' in obj1['src']['device']:
link_down1 = False
main.log.info("Link up from "+
"s1 -> s2 on ONOS1 detected")
for obj2 in json_obj2:
if '01' in obj2['src']['device']:
link_down2 = False
main.log.info("Link up from "+
"s1 -> s2 on ONOS2 detected")
for obj3 in json_obj3:
if '01' in obj3['src']['device']:
link_down3 = False
main.log.info("Link up from "+
"s1 -> s2 on ONOS3 detected")
loop_count += 1
time.sleep(1)
if (link_down1 and link_down2 and link_down3):
main.log.info("Link up discovery failed")
link_up_lat_graph1 = 0
link_up_lat_graph2 = 0
link_up_lat_graph3 = 0
link_up_lat_device1 = 0
link_up_lat_device2 = 0
link_up_lat_device3 = 0
assertion = main.FALSE
else:
json_topo_metrics_1 =\
main.ONOS1cli.topology_events_metrics()
json_topo_metrics_2 =\
main.ONOS2cli.topology_events_metrics()
json_topo_metrics_3 =\
main.ONOS3cli.topology_events_metrics()
json_topo_metrics_1 = json.loads(json_topo_metrics_1)
json_topo_metrics_2 = json.loads(json_topo_metrics_2)
json_topo_metrics_3 = json.loads(json_topo_metrics_3)
main.log.info("Obtaining graph and device timestamp")
graph_timestamp_1 = \
json_topo_metrics_1[graphTimestamp]['value']
graph_timestamp_2 = \
json_topo_metrics_2[graphTimestamp]['value']
graph_timestamp_3 = \
json_topo_metrics_3[graphTimestamp]['value']
link_timestamp_1 = \
json_topo_metrics_1[linkTimestamp]['value']
link_timestamp_2 = \
json_topo_metrics_2[linkTimestamp]['value']
link_timestamp_3 = \
json_topo_metrics_3[linkTimestamp]['value']
if graph_timestamp_1 and graph_timestamp_2 and\
graph_timestamp_3 and link_timestamp_1 and\
link_timestamp_2 and link_timestamp_3:
link_up_lat_graph1 = int(graph_timestamp_1) -\
int(timestamp_link_up_t0)
link_up_lat_graph2 = int(graph_timestamp_2) -\
int(timestamp_link_up_t0)
link_up_lat_graph3 = int(graph_timestamp_3) -\
int(timestamp_link_up_t0)
link_up_lat_link1 = int(link_timestamp_1) -\
int(timestamp_link_up_t0)
link_up_lat_link2 = int(link_timestamp_2) -\
int(timestamp_link_up_t0)
link_up_lat_link3 = int(link_timestamp_3) -\
int(timestamp_link_up_t0)
else:
main.log.error("There was an error calculating"+
" the delta for link down event")
link_up_lat_graph1 = 0
link_up_lat_graph2 = 0
link_up_lat_graph3 = 0
link_up_lat_device1 = 0
link_up_lat_device2 = 0
link_up_lat_device3 = 0
if debug_mode == 'on':
main.log.info("Link up latency ONOS1 iteration "+
str(i)+" (end-to-end): "+
str(link_up_lat_graph1)+" ms")
main.log.info("Link up latency ONOS2 iteration "+
str(i)+" (end-to-end): "+
str(link_up_lat_graph2)+" ms")
main.log.info("Link up latency ONOS3 iteration "+
str(i)+" (end-to-end): "+
str(link_up_lat_graph3)+" ms")
main.log.info("Link up latency ONOS1 iteration "+
str(i)+" (link-event-to-system-timestamp): "+
str(link_up_lat_link1)+" ms")
main.log.info("Link up latency ONOS2 iteration "+
str(i)+" (link-event-to-system-timestamp): "+
str(link_up_lat_link2)+" ms")
main.log.info("Link up latency ONOS3 iteration "+
str(i)+" (link-event-to-system-timestamp): "+
str(link_up_lat_link3))
#Calculate avg of node calculations
link_up_lat_graph_avg =\
(link_up_lat_graph1 +
link_up_lat_graph2 +
link_up_lat_graph3) / 3
link_up_lat_link_avg =\
(link_up_lat_link1 +
link_up_lat_link2 +
link_up_lat_link3) / 3
#Set threshold and append latency to list
if link_up_lat_graph_avg > up_threshold_min and\
link_up_lat_graph_avg < up_threshold_max:
link_up_graph_to_system_list.append(
link_up_lat_graph_avg)
else:
main.log.info("Link up latency exceeded threshold")
main.log.info("Results for iteration "+str(i)+
"have been omitted")
if link_up_lat_link_avg > up_threshold_min and\
link_up_lat_link_avg < up_threshold_max:
link_up_link_to_system_list.append(
link_up_lat_link_avg)
else:
main.log.info("Link up latency exceeded threshold")
main.log.info("Results for iteration "+str(i)+
"have been omitted")
#Calculate min, max, avg of list and report
link_down_min = min(link_down_graph_to_system_list)
link_down_max = max(link_down_graph_to_system_list)
link_down_avg = sum(link_down_graph_to_system_list) / \
len(link_down_graph_to_system_list)
link_up_min = min(link_up_graph_to_system_list)
link_up_max = max(link_up_graph_to_system_list)
link_up_avg = sum(link_up_graph_to_system_list) / \
len(link_up_graph_to_system_list)
link_down_std_dev = \
str(round(numpy.std(link_down_graph_to_system_list),1))
link_up_std_dev = \
str(round(numpy.std(link_up_graph_to_system_list),1))
main.log.report("Link down latency " +
"Avg: "+str(link_down_avg)+" ms "+
"Std Deviation: "+link_down_std_dev+" ms")
main.log.report("Link up latency "+
"Avg: "+str(link_up_avg)+" ms "+
"Std Deviation: "+link_up_std_dev+" ms")
utilities.assert_equals(expect=main.TRUE, actual=assertion,
onpass="Link discovery latency calculation successful",
onfail="Link discovery latency case failed")
def CASE5(self, main):
'''
100 Switch discovery latency
Important:
This test case can be potentially dangerous if
your machine has previously set iptables rules.
One of the steps of the test case will flush
all existing iptables rules.
Note:
You can specify the number of switches in the
params file to adjust the switch discovery size
(and specify the corresponding topology in Mininet1
.topo file)
'''
import time
import subprocess
import os
import requests
import json
ONOS1_ip = main.params['CTRL']['ip1']
ONOS2_ip = main.params['CTRL']['ip2']
ONOS3_ip = main.params['CTRL']['ip3']
MN1_ip = main.params['MN']['ip1']
ONOS_user = main.params['CTRL']['user']
default_sw_port = main.params['CTRL']['port1']
#Number of iterations of case
num_iter = main.params['TEST']['numIter']
num_sw = main.params['TEST']['numSwitch']
#Timestamp 'keys' for json metrics output.
#These are subject to change, hence moved into params
deviceTimestamp = main.params['JSON']['deviceTimestamp']
graphTimestamp = main.params['JSON']['graphTimestamp']
debug_mode = main.params['TEST']['debugMode']
local_time = time.strftime('%X')
local_time = local_time.replace("/","")
local_time = local_time.replace(" ","_")
local_time = local_time.replace(":","")
if debug_mode == 'on':
main.ONOS1.tshark_pcap("eth0",
"/tmp/100_sw_lat_pcap_"+local_time)
#Threshold for this test case
sw_disc_threshold_str = main.params['TEST']['swDisc100Threshold']
sw_disc_threshold_obj = sw_disc_threshold_str.split(",")
sw_disc_threshold_min = int(sw_disc_threshold_obj[0])
sw_disc_threshold_max = int(sw_disc_threshold_obj[1])
tshark_ofp_output = "/tmp/tshark_ofp_"+num_sw+"sw.txt"
tshark_tcp_output = "/tmp/tshark_tcp_"+num_sw+"sw.txt"
tshark_ofp_result_list = []
tshark_tcp_result_list = []
sw_discovery_lat_list = []
main.case(num_sw+" Switch discovery latency")
main.step("Assigning all switches to ONOS1")
for i in range(1, int(num_sw)+1):
main.Mininet1.assign_sw_controller(
sw=str(i),
ip1=ONOS1_ip,
port1=default_sw_port)
#Ensure that nodes are configured with ptpd
#Just a warning message
main.log.info("Please check ptpd configuration to ensure"+\
" All nodes' system times are in sync")
time.sleep(5)
for i in range(0, int(num_iter)):
main.step("Set iptables rule to block incoming sw connections")
#Set iptables rule to block incoming switch connections
#The rule description is as follows:
# Append to INPUT rule,
# behavior DROP that matches following:
# * packet type: tcp
# * source IP: MN1_ip
# * destination PORT: 6633
main.ONOS1.handle.sendline(
"sudo iptables -A INPUT -p tcp -s "+MN1_ip+
" --dport "+default_sw_port+" -j DROP")
main.ONOS1.handle.expect("\$")
# Append to OUTPUT rule,
# behavior DROP that matches following:
# * packet type: tcp
# * source IP: MN1_ip
# * destination PORT: 6633
main.ONOS1.handle.sendline(
"sudo iptables -A OUTPUT -p tcp -s "+MN1_ip+
" --dport "+default_sw_port+" -j DROP")
main.ONOS1.handle.expect("\$")
#Give time to allow rule to take effect
#NOTE: Sleep period may need to be configured
# based on the number of switches in the topology
main.log.info("Please wait for switch connection to "+
"time out")
time.sleep(60)
#Gather vendor OFP with tshark
main.ONOS1.tshark_grep("OFP 86 Vendor",
tshark_ofp_output)
main.ONOS1.tshark_grep("TCP 74 ",
tshark_tcp_output)
#NOTE: Remove all iptables rule quickly (flush)
# Before removal, obtain TestON timestamp at which
# removal took place
# (ensuring nodes are configured via ptp)
# sudo iptables -F
t0_system = time.time() * 1000
main.ONOS1.handle.sendline(
"sudo iptables -F")
#Counter to track loop count
counter_loop = 0
counter_avail1 = 0
counter_avail2 = 0
counter_avail3 = 0
onos1_dev = False
onos2_dev = False
onos3_dev = False
while counter_loop < 60:
#Continue to check devices for all device
#availability. When all devices in all 3
#ONOS instances indicate that devices are available
#obtain graph event timestamp for t1.
device_str_obj1 = main.ONOS1cli.devices()
device_str_obj2 = main.ONOS2cli.devices()
device_str_obj3 = main.ONOS3cli.devices()
device_json1 = json.loads(device_str_obj1)
device_json2 = json.loads(device_str_obj2)
device_json3 = json.loads(device_str_obj3)
for device1 in device_json1:
if device1['available'] == True:
counter_avail1 += 1
if counter_avail1 == int(num_sw):
onos1_dev = True
main.log.info("All devices have been "+
"discovered on ONOS1")
else:
counter_avail1 = 0
for device2 in device_json2:
if device2['available'] == True:
counter_avail2 += 1
if counter_avail2 == int(num_sw):
onos2_dev = True
main.log.info("All devices have been "+
"discovered on ONOS2")
else:
counter_avail2 = 0
for device3 in device_json3:
if device3['available'] == True:
counter_avail3 += 1
if counter_avail3 == int(num_sw):
onos3_dev = True
main.log.info("All devices have been "+
"discovered on ONOS3")
else:
counter_avail3 = 0
if onos1_dev and onos2_dev and onos3_dev:
main.log.info("All devices have been discovered "+
"on all ONOS instances")
json_str_topology_metrics_1 =\
main.ONOS1cli.topology_events_metrics()
json_str_topology_metrics_2 =\
main.ONOS2cli.topology_events_metrics()
json_str_topology_metrics_3 =\
main.ONOS3cli.topology_events_metrics()
#Exit while loop if all devices discovered
break
counter_loop += 1
#Give some time in between CLI calls
#(will not affect measurement)
time.sleep(3)
main.ONOS1.tshark_stop()
os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
tshark_ofp_output+" /tmp/")
os.system("scp "+ONOS_user+"@"+ONOS1_ip+":"+
tshark_tcp_output+" /tmp/")
#TODO: Automate OFP output analysis
#Debug mode - print out packets captured at runtime
if debug_mode == 'on':
ofp_file = open(tshark_ofp_output, 'r')
main.log.info("Tshark OFP Vendor output: ")
for line in ofp_file:
tshark_ofp_result_list.append(line)
main.log.info(line)
ofp_file.close()
tcp_file = open(tshark_tcp_output, 'r')
main.log.info("Tshark TCP 74 output: ")
for line in tcp_file:
tshark_tcp_result_list.append(line)
main.log.info(line)
tcp_file.close()
json_obj_1 = json.loads(json_str_topology_metrics_1)
json_obj_2 = json.loads(json_str_topology_metrics_2)
json_obj_3 = json.loads(json_str_topology_metrics_3)
graph_timestamp_1 = \
json_obj_1[graphTimestamp]['value']
graph_timestamp_2 = \
json_obj_2[graphTimestamp]['value']
graph_timestamp_3 = \
json_obj_3[graphTimestamp]['value']
graph_lat_1 = int(graph_timestamp_1) - int(t0_system)
graph_lat_2 = int(graph_timestamp_2) - int(t0_system)
graph_lat_3 = int(graph_timestamp_3) - int(t0_system)
avg_graph_lat = \
(int(graph_lat_1) +\
int(graph_lat_2) +\
int(graph_lat_3)) / 3
if avg_graph_lat > sw_disc_threshold_min \
and avg_graph_lat < sw_disc_threshold_max:
sw_discovery_lat_list.append(
avg_graph_lat)
else:
main.log.info("100 Switch discovery latency "+
"exceeded the threshold.")
#END ITERATION FOR LOOP
sw_lat_min = min(sw_discovery_lat_list)
sw_lat_max = max(sw_discovery_lat_list)
sw_lat_avg = sum(sw_discovery_lat_list) /\
len(sw_discovery_lat_list)
main.log.report("100 Switch discovery lat "+\
"Min: "+str(sw_lat_min)+" ms"+\
"Max: "+str(sw_lat_max)+" ms"+\
"Avg: "+str(sw_lat_avg)+" ms")