Merge pull request #8 from ahassany/flow_format
Give the ability to define the output format of dump-flows
diff --git a/TestON/dependencies/loadgen_NB.py b/TestON/dependencies/loadgen_NB.py
new file mode 100755
index 0000000..78d18b9
--- /dev/null
+++ b/TestON/dependencies/loadgen_NB.py
@@ -0,0 +1,225 @@
+#! /usr/bin/env python
+from time import time, sleep
+import time
+import json
+import requests
+import urllib2
+from urllib2 import URLError, HTTPError
+
+'''
+ This script is for Intent Throughput testing. Use linear 7-switch topo. Intents are from S1P1 to/from S7/P1, with incrementing src/dst Mac addresses.
+'''
+
+def setIntentJSN(node_id, intPerGroup, group_id, intent_id):
+ intents = [None for i in range(intPerGroup)]
+ oper = {}
+ index = 0
+ for i in range(intPerGroup / 2):
+ smac = str("%x" %(node_id * 0x100000000000 + 0x010000000000 + (group_id * 0x000001000000) +i + 1))
+ dmac = str("%x" %(node_id * 0x100000000000 + 0x070000000000 + (group_id * 0x000001000000) +i + 1))
+ srcMac = ':'.join(smac[i:i+2] for i in range(0, len(smac), 2))
+ dstMac = ':'.join(dmac[i:i+2] for i in range(0, len(dmac), 2))
+ srcSwitch = "00:00:00:00:00:00:00:01"
+ dstSwitch = "00:00:00:00:00:00:00:07"
+ srcPort = 1
+ dstPort = 1
+
+ oper['intentId'] = intent_id
+ oper['intentType'] = 'SHORTEST_PATH' # XXX: Hardcode
+ oper['staticPath'] = False # XXX: Hardcoded
+ oper['srcSwitchDpid'] = srcSwitch
+ oper['srcSwitchPort'] = srcPort
+ oper['dstSwitchDpid'] = dstSwitch
+ oper['dstSwitchPort'] = dstPort
+ oper['matchSrcMac'] = srcMac
+ oper['matchDstMac'] = dstMac
+ intents[index] = oper
+ #print ("perGroup Intents-0 are: " + json.dumps(intents) + "\n\n\n" )
+ index += 1
+ intent_id += 1
+ oper = {}
+ #print ("ID:" + str(id))
+
+ oper['intentId'] = intent_id
+ oper['intentType'] = 'SHORTEST_PATH' # XXX: Hardcoded
+ oper['staticPath'] = False # XXX: Hardcoded
+ oper['srcSwitchDpid'] = dstSwitch
+ oper['srcSwitchPort'] = dstPort
+ oper['dstSwitchDpid'] = srcSwitch
+ oper['dstSwitchPort'] = srcPort
+ oper['matchSrcMac'] = dstMac
+ oper['matchDstMac'] = srcMac
+ intents[index] = oper
+ index += 1
+ intent_id += 1
+ oper = {}
+ #print ("ID: " + str(id))
+ #print ("perGroup Intents-1 are: " + json.dumps(intents) + "\n\n\n" )
+ #print ("contructed intents are: " + json.dumps(intents) + "\n\n\n")
+ return intents, intent_id
+
+def post_json(url, data):
+ """Make a REST POST call and return the JSON result
+ url: the URL to call
+ data: the data to POST"""
+ posturl = "http://%s/wm/onos/intent/high" %(url)
+ #print ("\nPost url is : " + posturl + "\n")
+ parsed_result = []
+ data_json = json.dumps(data)
+ try:
+ request = urllib2.Request(posturl, data_json)
+ request.add_header("Content-Type", "application/json")
+ response = urllib2.urlopen(request)
+ result = response.read()
+ response.close()
+ if len(result) != 0:
+ parsed_result = json.loads(result)
+ except HTTPError as exc:
+ print "ERROR:"
+ print " REST POST URL: %s" % posturl
+ # NOTE: exc.fp contains the object with the response payload
+ error_payload = json.loads(exc.fp.read())
+ print " REST Error Code: %s" % (error_payload['code'])
+ print " REST Error Summary: %s" % (error_payload['summary'])
+ print " REST Error Description: %s" % (error_payload['formattedDescription'])
+ print " HTTP Error Code: %s" % exc.code
+ print " HTTP Error Reason: %s" % exc.reason
+ except URLError as exc:
+ print "ERROR:"
+ print " REST POST URL: %s" % posturl
+ print " URL Error Reason: %s" % exc.reason
+ return parsed_result
+
+def delete_json(self, url, intPerGroup, startID):
+ """Make a REST DELETE call and return the JSON result
+ url: the URL to call"""
+ #url = "localhost:8080"
+ for i in range(intPerGroup):
+ posturl = "http://%s/wm/onos/intent/high/%s" %(url, str(i + startID))
+ parsed_result = []
+ try:
+ request = urllib2.Request(posturl)
+ request.get_method = lambda: 'DELETE'
+ response = urllib2.urlopen(request)
+ result = response.read()
+ response.close()
+ #if len(result) != 0:
+ # parsed_result = json.loads(result)
+ except HTTPError as exc:
+ print "ERROR:"
+ print " REST DELETE URL: %s" % posturl
+ # NOTE: exc.fp contains the object with the response payload
+ error_payload = json.loads(exc.fp.read())
+ print " REST Error Code: %s" % (error_payload['code'])
+ print " REST Error Summary: %s" % (error_payload['summary'])
+ print " REST Error Description: %s" % (error_payload['formattedDescription'])
+ print " HTTP Error Code: %s" % exc.code
+ print " HTTP Error Reason: %s" % exc.reason
+ except URLError as exc:
+ print "ERROR:"
+ print " REST DELETE URL: %s" % posturl
+ print " URL Error Reason: %s" % exc.reason
+ return parsed_result
+
+def delete_all_json(url):
+ """Make a REST DELETE call and return the JSON result
+ url: the URL to call"""
+ #url = "localhost:8080"
+ posturl = "http://%s/wm/onos/intent/high" %(url)
+ parsed_result = []
+ try:
+ request = urllib2.Request(posturl)
+ request.get_method = lambda: 'DELETE'
+ response = urllib2.urlopen(request)
+ result = response.read()
+ response.close()
+ if len(result) != 0:
+ parsed_result = json.loads(result)
+ except HTTPError as exc:
+ print "ERROR:"
+ print " REST DELETE URL: %s" % posturl
+ # NOTE: exc.fp contains the object with the response payload
+ error_payload = json.loads(exc.fp.read())
+ print " REST Error Code: %s" % (error_payload['code'])
+ print " REST Error Summary: %s" % (error_payload['summary'])
+ print " REST Error Description: %s" % (error_payload['formattedDescription'])
+ print " HTTP Error Code: %s" % exc.code
+ print " HTTP Error Reason: %s" % exc.reason
+ except URLError as exc:
+ print "ERROR:"
+ print " REST DELETE URL: %s" % posturl
+ print " URL Error Reason: %s" % exc.reason
+ return parsed_result
+
+def loadIntents(node_id, urllist, intPerGroup, addrate, duration):
+ urlindex = 0
+ group = 0
+ start_id = 0
+ sleeptimer = (1.000/addrate)
+ tstart = time.time()
+ while ( (time.time() - tstart) <= duration ):
+ if urlindex < len(urllist):
+ realurlind = urlindex
+ else:
+ realurlind = 0
+ urlindex = 0
+
+ u = str(urllist[realurlind])
+ gstart = time.time()
+ intents,start_id = setIntentJSN(node_id, intPerGroup, group, start_id)
+ #print (str(intents))
+ #print ("Starting intent id: " + str(start_id))
+ result = post_json(u, intents)
+ #print json.dumps(intents[group])
+ #print ("post result: " + str(result))
+ gelapse = time.time() - gstart
+ print ("Group: " + str(group) + " with " + str(intPerGroup) + " intents were added in " + str('%.3f' %gelapse) + " seconds.")
+ sleep(sleeptimer)
+ urlindex += 1
+ group += 1
+
+ telapse = time.time() - tstart
+ #print ( "Number of groups: " + str(group) + "; Totoal " + str(args.groups * args.intPerGroup) + " intents were added in " + str(telapse) + " seconds.")
+ return telapse, group
+
+def main():
+ import argparse
+
+ parser = argparse.ArgumentParser(description="less script")
+ parser.add_argument("-n", "--node_id", dest="node_id", default = 1, type=int, help="id of the node generating the intents, this is used to distinguish intents when multiple nodes are use to generate intents")
+ parser.add_argument("-u", "--urls", dest="urls", default="10.128.10.1", type=str, help="a string to show urls to post intents to separated by space, ex. '10.128.10.1:8080 10.128.10.2:80080' ")
+ parser.add_argument("-i", "--intentsPerGroup", dest="intPerGroup", default=100, type=int, help="number of intents in one restcall group")
+ parser.add_argument("-a", "--addrate", dest="addrate", default=10, type=float, help="rate to add intents groups, groups per second")
+ parser.add_argument("-d", "--delrate", dest="delrate", default=100, type=float, help= "### Not Effective -for now intents are delete as bulk #### rate to delete intents, intents/second")
+ parser.add_argument("-l", "--length", dest="duration", default=300, type=int, help="duration/length of time the intents are posted")
+ parser.add_argument("-p", "--pause", dest="pause", default=0, type=int, help= "pausing time between add and delete of intents")
+ args = parser.parse_args()
+
+ node_id = args.node_id
+ urllist = args.urls.split()
+ intPerGroup = args.intPerGroup
+ addrate = args.addrate
+ delrate = args.delrate
+ duration = args.duration
+ pause = args.pause
+
+ print ("Intent posting urls are: " + str(urllist))
+ print ("Number of Intents per group: " + str(intPerGroup))
+ print ("Intent group add rate: " + str(addrate) )
+ print ("Intent delete rate:" + str(delrate) )
+ print ("Duration: " + str(duration) )
+ print ("Pause between add and delete: " + str(args.pause))
+
+ telapse, group = loadIntents(node_id, urllist, intPerGroup, addrate, duration)
+ print ("\n\n#####################")
+ print ( str(group) + " groups " + " of " + str(intPerGroup) + " Intents per group - Total " + str(group * intPerGroup) + " intents were added in " + str('%.3f' %telapse) + " seconds.")
+ print ( "Effective intents posting rate is: " + str( '%.1f' %( (group * intPerGroup)/telapse ) ) + " Intents/second." )
+ print ("#####################\n\n")
+ print ("Sleep for " + str(pause) + " seconds before deleting all intents...")
+ time.sleep(pause)
+ print ("Cleaning up intents in all nodes...")
+ for url in urllist:
+ delete_all_json(url)
+
+if __name__ == '__main__':
+ main()
diff --git a/TestON/dependencies/loadgen_SB.py b/TestON/dependencies/loadgen_SB.py
new file mode 100755
index 0000000..cfd2adf
--- /dev/null
+++ b/TestON/dependencies/loadgen_SB.py
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+
+"""
+This example shows how to create an empty Mininet object
+(without a topology object) and add nodes to it manually.
+"""
+import sys
+import subprocess
+import time
+from mininet.net import Mininet
+from mininet.node import Controller
+from mininet.cli import CLI
+from mininet.log import setLogLevel, info
+
+swlist = []
+hostlist= []
+count = 0
+
+def createSwPorts(numsw, numport):
+
+ "Create an empty network and add nodes to it."
+
+ net = Mininet()
+ swlist = []
+ hostlist= []
+ print ("Starting Mininet Network....")
+ for i in range(numsw):
+ sw = net.addSwitch( 's' + str(i), dpid = ('00000000000000' + '%0d'%i))
+ print str(sw),
+ for p in range(numport):
+ host = net.addHost("s"+str(i)+"h"+str(p))
+ hostlist.append(host)
+ print str(host),
+ net.addLink(host,sw)
+ swlist.append(sw)
+
+
+ info( '*** Starting network\n')
+ net.start()
+
+ return swlist
+
+def loadsw(urllist, swlist, addrate, delrate, duration):
+ global numport
+ urlindex = 0
+ count = 0
+ addsleeptimer = 1.000 /addrate
+ delsleeptimer = 1.000/delrate
+ print (" Add sleeptimer: " + str('%.3f' %addsleeptimer) + "; Delete sleeptimer: " + str('%.3f' %delsleeptimer))
+ print str(swlist)
+
+ tstart = time.time()
+ while ( (time.time() - tstart) <= duration ):
+ #print (time.time() - tstart)
+ astart = time.time()
+ for sw in swlist:
+ if urlindex < len(urllist):
+ i = urlindex
+ else:
+ i = 0
+ urlindex = 0
+
+ ovscmd = "sudo ovs-vsctl set-controller " + str(sw) + " tcp:" + urllist[i]
+ print ("a"),
+ s = subprocess.Popen(ovscmd, shell=True )
+ time.sleep(addsleeptimer)
+ count += 1
+ urlindex += 1
+ aelapse = time.time() - astart
+ print ("Number of switches connected: " + str(len(swlist)) + " in: " + str('%.3f' %aelapse) + "seconds.")
+
+ dstart = time.time()
+ for sw in swlist:
+ ovscmd = "sudo ovs-vsctl set-controller " + str(sw) + " tcp:127.0.0.1:6633"
+ print ("d"),
+ s = subprocess.Popen(ovscmd, shell=True )
+ time.sleep(delsleeptimer)
+ count += 1
+ delapse = time.time() - dstart
+ print ("Number of switches disconnected: " + str(len(swlist)) + " in: " + str('%.3f' %delapse) + "seconds.")
+ telapse = time.time() - tstart
+
+ return telapse, count
+def cleanMN():
+ print ("Cleaning MN switches...")
+ s = subprocess.Popen("sudo mn -c > /dev/null 2>&1", shell=True)
+ print ("Done.")
+
+def main():
+ import argparse
+ import threading
+ from threading import Thread
+
+ parser = argparse.ArgumentParser(description="less script")
+ parser.add_argument("-u", "--urls", dest="urls", default="10.128.10.1", type=str, help="a string to show urls to post intents to separated by space, ex. '10.128.10.1:6633 10.128.10.2:6633' ")
+ parser.add_argument("-s", "--switches", dest="numsw", default=100, type=int, help="number of switches use in the load generator; together with the ports per switch config, each switch generates (numport + 2) events")
+ parser.add_argument("-p", "--ports", dest="numport", default=1, type=int, help="number of ports per switches")
+ parser.add_argument("-a", "--addrate", dest="addrate", default=10, type=float, help="rate to add intents groups, groups per second")
+ parser.add_argument("-d", "--delrate", dest="delrate", default=100, type=float, help= "rate to delete intents, intents/second")
+ parser.add_argument("-l", "--testlength", dest="duration", default=0, type=int, help= "pausing time between add and delete of intents")
+ args = parser.parse_args()
+
+ urllist = args.urls.split()
+ numsw = args.numsw
+ numport = args.numport
+ addrate = args.addrate
+ delrate = args.delrate
+ duration = args.duration
+ setLogLevel( 'info' )
+ swlist = createSwPorts(numsw,numport)
+ telapse,count = loadsw(urllist, swlist, addrate, delrate, duration)
+ print ("Total number of switches connected/disconnected: " + str(count) + "; Total events generated: " + str(count * (2 + numport)) + "; Elalpse time: " + str('%.1f' %telapse))
+ print ("Effective aggregated loading is: " + str('%.1f' %((( count * (2+ numport))) / telapse ) ) + "Events/s.")
+ cleanMN()
+
+if __name__ == '__main__':
+ main()
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 4b826d4..47cb129 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -751,7 +751,7 @@
main.cleanup()
main.exit()
- def compare_topo(self, onos_list, onos_json):
+ def compare_topo(self, topo, onos_json):
'''
compares mn topology with ONOS topology
onos_list is a list of ONOS controllers, each element of the list should be (handle, name, ip, port)
@@ -764,11 +764,23 @@
topology_refactoring2 branch, but may be merged into the master branch soon. You may need to install some
python modules such as networkx to use the STS functions.
+ To install sts:
+ $ git clone git://github.com/ucb-sts/sts.git
+ $ cd sts
+ $ git clone -b debugger git://github.com/ucb-sts/pox.git
+ $ sudo apt-get install python-dev
+ $ ./tools/install_hassel_python.sh
+ $ sudo pip install networkx
+
+ Include sts in your PYTHONPATH. it should looks comething like:
+ PYTHONPATH=/home/admin/TestON:/home/admin/sts
+
'''
- from sts.topology.teston_topology import TestONTopology # assumes that sts already in you PYTHONPATH
- #import sts.entities.base as base
+ import sys
+ sys.path.append("~/sts")
+ #NOTE: Create this once per Test and pass the TestONTopology object around. It takes too long to create this object.
+ # This will make it easier to use the sts methods for severing links and solve that issue
import json
- topo = TestONTopology(self, onos_list)
link_results = main.TRUE
switch_results = main.TRUE
@@ -779,8 +791,9 @@
for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
ports = []
for port in switch.ports.values():
- ports.append({'of_port': port.port_no, 'mac': port.hw_addr.replace('\'',''), 'name': port.name})
- output['switches'].append({"name": switch.name, "dpid": switch.dpid, "ports": ports })
+ #print port.hw_addr.toStr(separator = '')
+ ports.append({'of_port': port.port_no, 'mac': str(port.hw_addr).replace('\'',''), 'name': port.name})
+ output['switches'].append({"name": switch.name, "dpid": str(switch.dpid).zfill(16), "ports": ports })
#print output
#print json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))
@@ -835,6 +848,9 @@
#######Links########
# iterate through MN links and check if and ONOS link exists in both directions
+ # NOTE: Will currently only show mn links as down if they are cut through STS.
+ # We can either do everything through STS or wait for up_network_links
+ # and down_network_links to be fully implemented.
for link in topo.patch_panel.network_links:
#print "Link: %s" % link
#TODO: Find a more efficient search method
@@ -883,14 +899,12 @@
results = switch_results and port_results and link_results
- '''
- if not results: #To print out both topologies
- main.log.error("Topology comparison failed, printing json objects, MN then ONOS")
- main.log.error(str(json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))))
- main.log.error('MN Links:')
- for link in topo.patch_panel.network_links: main.log.error(str("\tLink: %s" % link))
- main.log.error(str(json.dumps(onos, sort_keys=True,indent=4,separators=(',', ': '))))
- '''
+# if not results: #To print out both topologies
+# main.log.error("Topology comparison failed, printing json objects, MN then ONOS")
+# main.log.error(str(json.dumps(output, sort_keys=True,indent=4,separators=(',', ': '))))
+# main.log.error('MN Links:')
+# for link in topo.patch_panel.network_links: main.log.error(str("\tLink: %s" % link))
+# main.log.error(str(json.dumps(onos, sort_keys=True,indent=4,separators=(',', ': '))))
return results
diff --git a/TestON/drivers/common/cli/emulator/remotemininetdriver.py b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
index 7aaec91..d6e839d 100644
--- a/TestON/drivers/common/cli/emulator/remotemininetdriver.py
+++ b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
@@ -75,6 +75,11 @@
#*********************************************************************************************
def checkForLoss(self, pingList):
+ '''
+ Returns main.FALSE for 0% packet loss and
+ Returns main.ERROR if "found multiple mininet" is found and
+ Returns main.TRUE else
+ '''
import os
self.handle.sendline("")
self.handle.expect("\$")
@@ -93,23 +98,31 @@
'''
Starts a continuous ping on the mininet host outputing to a file in the /tmp dir.
'''
+ self.handle.sendline("")
+ self.handle.expect("\$")
args = utilities.parse_args(["SRC","TARGET","PINGTIME"],**pingParams)
- precmd = "rm /tmp/ping." + args["SRC"]
+ precmd = "sudo rm /tmp/ping." + args["SRC"]
self.execute(cmd=precmd,prompt="(.*)",timeout=10)
- command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -i .2 -w " + str(args['PINGTIME']) + " > /tmp/ping." + args["SRC"] + " &"
+ command = "sudo mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -i .2 -w " + str(args['PINGTIME']) + " > /tmp/ping." + args["SRC"] + " &"
main.log.info( command )
self.execute(cmd=command,prompt="(.*)",timeout=10)
+ self.handle.sendline("")
+ self.handle.expect("\$")
return main.TRUE
def pingstatus(self,**pingParams):
'''
Tails the respective ping output file and check that there is a moving "64 bytes"
'''
+ self.handle.sendline("")
+ self.handle.expect("\$")
args = utilities.parse_args(["SRC"],**pingParams)
self.handle.sendline("tail /tmp/ping." + args["SRC"])
self.handle.expect("tail")
self.handle.expect("\$")
result = self.handle.before + self.handle.after
+ self.handle.sendline("")
+ self.handle.expect("\$")
if re.search('Unreachable', result ):
main.log.info("Unreachable found in ping logs...")
return main.FALSE
@@ -120,40 +133,52 @@
main.log.info("No, or faulty ping data...")
return main.FALSE
- def pingKill(self):
+ def pingKill(self, testONUser, testONIP):
'''
Kills all continuous ping processes.
Then copies all the ping files to the TestStation.
'''
import time
+ self.handle.sendline("")
+ self.handle.expect("\$")
command = "sudo kill -SIGINT `pgrep ping`"
main.log.info( command )
self.execute(cmd=command,prompt="(.*)",timeout=10)
- main.log.info( "Removing old ping data" )
- command = "rm /tmp/ping.*"
- os.popen(command)
- time.sleep(2)
+ #Commenting out in case TestON and MN are on the same machine. scp overrights the file anyways
+ #main.log.info( "Removing old ping data" )
+ #command = "rm /tmp/ping.*"
+ #os.popen(command)
+ #time.sleep(2)
main.log.info( "Transferring ping files to TestStation" )
- command = "scp /tmp/ping.* admin@10.128.7.7:/tmp/"
+ command = "scp /tmp/ping.* "+ str(testONUser) + "@" + str(testONIP) + ":/tmp/"
self.execute(cmd=command,prompt="100%",timeout=20)
- print("finished kill")
+ self.handle.sendline("")
+ self.handle.expect("\$")
return main.TRUE
def pingLongKill(self):
import time
+ self.handle.sendline("")
+ self.handle.expect("\$")
command = "sudo kill -SIGING `pgrep ping`"
main.log.info(command)
self.execute(cmd=command,prompt="(.*)",timeout=10)
+ self.handle.sendline("")
+ self.handle.expect("\$")
return main.TRUE
def pingHost(self,**pingParams):
'''
Pings between two hosts on remote mininet
'''
+ self.handle.sendline("")
+ self.handle.expect("\$")
args = utilities.parse_args(["SRC","TARGET"],**pingParams)
command = "mininet/util/m " + args["SRC"] + " ping "+args ["TARGET"]+" -c 4 -W 1 -i .2"
main.log.info ( command )
response = self.execute(cmd=command,prompt="rtt",timeout=10 )
+ self.handle.sendline("")
+ self.handle.expect("\$")
if utilities.assert_matches(expect=',\s0\%\spacket\sloss',actual=response,onpass="No Packet loss",onfail="Host is not reachable"):
main.log.info("NO PACKET LOSS, HOST IS REACHABLE")
main.last_result = main.TRUE
@@ -388,7 +413,46 @@
main.cleanup()
main.exit()
+ def del_switch(self,sw):
+ self.handle.sendline("")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl del-br "+sw)
+ self.handle.expect("\$")
+ return main.TRUE
+ def add_switch(self,sw):
+ self.handle.sendline("")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-br "+sw)
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth1")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth2")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth3")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth4")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth5")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth6")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth7")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth8")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth9")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth10")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth11")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth12")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth13")
+ self.handle.expect("\$")
+ self.handle.sendline("sudo ovs-vsctl add-port "+sw+" " + sw + "-eth14")
+ self.handle.expect("\$")
def disconnect(self):
@@ -411,7 +475,11 @@
def get_flowTable(self,sw):
self.handle.sendline("cd")
self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
- command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
+ #TODO: Write seperate versions of the function for this, possibly a string that tells it which switch is in use?
+ #For 1.0 version of OVS
+ #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
+ #for 1.3 version of OVS
+ command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $3 $7 $8}' |sort -n -k1"
self.handle.sendline(command)
self.handle.expect(["sort -n -k1",pexpect.EOF,pexpect.TIMEOUT])
self.handle.expect(["NXST_FLOW",pexpect.EOF,pexpect.TIMEOUT])
@@ -423,6 +491,11 @@
if flow1==flow2:
return main.TRUE
else:
+ main.log.info("Flow tables do not match, printing tables:")
+ main.log.info("Flow Table 1:")
+ main.log.info(flow1)
+ main.log.info("Flow Table 2:")
+ main.log.info(flow2)
return main.FALSE
if __name__ != "__main__":
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index d2761f0..fafc7e7 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -68,6 +68,43 @@
main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
main.cleanup()
main.exit()
+
+ def portKill(self, port):
+ try:
+ self.handle.sendline("")
+ self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+ cmd = "sudo tcpkill -i eth0 port " + str(port) + " 2>/dev/null 1>/dev/null &"
+ self.handle.sendline(cmd)
+ self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.log.error( traceback.print_exc() )
+ main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.cleanup()
+ main.exit()
+
+ def endPortKill(self,port):
+ try:
+ self.handle.sendline("")
+ self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+ self.handle.sendline("sudo pkill tcpkill")
+ self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.log.error( traceback.print_exc() )
+ main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.cleanup()
+ main.exit()
def start(self, env = ''):
'''
@@ -286,8 +323,8 @@
self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
self.handle.sendline("cd "+self.home)
self.handle.sendline("./onos.sh stop")
- i=self.handle.expect(["Stop",pexpect.EOF,pexpect.TIMEOUT])
- self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT], 60)
+ self.handle.expect(["./onos.sh stop",pexpect.EOF,pexpect.TIMEOUT])
+ i=self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT],60)
result = self.handle.before
if re.search("Killed", result):
main.log.info(self.name + ": ONOS Killed Successfully")
@@ -317,8 +354,8 @@
self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
self.handle.sendline("cd "+self.home)
self.handle.sendline("./onos.sh core stop")
- i=self.handle.expect(["Stop",pexpect.EOF,pexpect.TIMEOUT])
- self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT], 60)
+ self.handle.expect(["./onos.sh stop",pexpect.EOF,pexpect.TIMEOUT])
+ i=self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT],60)
result = self.handle.before
if re.search("Killed", result):
main.log.info(self.name + ": ONOS Killed Successfully")
@@ -425,6 +462,32 @@
main.exit()
+ def kill(self):
+ import re
+ try:
+ self.handle.sendline("ps -ef |grep 'ONOS/conf/logback' |awk 'NR==1 {print $2}' |xargs sudo kill -9")
+ self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+ self.handle.sendline("ps -ef |grep 'ONOS/conf/logback' |wc -l")
+ self.handle.expect(["wc -l",pexpect.EOF,pexpect.TIMEOUT])
+ response = self.handle.after
+ if re.search("1",response):
+ return "ONOS Killed!"
+ else:
+ return "ERROR!!! ONOS MAY NOT HAVE BEEN KILLED PROPERLY!!!"
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.hane + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.log.error( traceback.print_exc() )
+ main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.cleanup()
+ main.exit()
+
+
+
def disconnect(self):
'''
Called when Test is complete to disconnect the ONOS handle.
@@ -653,6 +716,7 @@
url = "http://%s:%s/%s/high"%(intentIP,intentPort,intentURL)
parsed_result = []
data_json = json.dumps(intents)
+ result = main.FALSE
try:
request = urllib2.Request(url,data_json)
request.add_header("Content-Type", "application/json")
@@ -671,10 +735,12 @@
print " REST Error Description: %s" % (error_payload['formattedDescription'])
print " HTTP Error Code: %s" % exc.code
print " HTTP Error Reason: %s" % exc.reason
+ return " HTTP Error Code: %s, Reason: %s" % exc.code, exc.reason
except URLError as exc:
print "ERROR:"
print " REST GET URL: %s" % url
print " URL Error Reason: %s" % exc.reason
+ return " HTTP Error Reason: %s" % exc.reason
return result
@@ -926,6 +992,26 @@
main.cleanup()
main.exit()
+ def num_switch(self,RestIP,RestPort="8080"):
+ url = "http://%s:%s/wm/onos/topology/switches" %(RestIP,RestPort)
+ parsedResult = self.get_json(url)
+ if parsedResult == "":
+ retcode = 1
+ return (retcode, "RestAPI has an issue")
+ url = "http://%s:%s/wm/onos/registry/switches/json" %(RestIP,RestPort)
+ registry = self.get_json(url)
+ if registry == "":
+ retcode = 1
+ return (retcode, "REST API has an Issue")
+ cnt = 0
+ active = 0
+ for s in parsedResult:
+ cnt +=1
+ if s['state']=="ACTIVE":
+ active+=1
+ return (cnt,active)
+
+
def check_switch(self,RestIP,correct_nr_switch, RestPort ="8080" ):
'''
Used by check_status
@@ -975,6 +1061,17 @@
main.cleanup()
main.exit()
+ def num_link(self,RestIP,RestPort="8080"):
+ url = "http://%s:%s/wm/onos/topology/links" % (RestIP,RestPort)
+ parsedResult = self.get_json(url)
+ if parsedResult == "":
+ retcode = 1
+ return (retcode,"RestAPI has an issue")
+ intra = 0
+ for s in parsedResult:
+ intra+=1
+ return intra
+
def check_link(self,RestIP, nr_links, RestPort = "8080"):
'''
Used by check_status
@@ -1098,7 +1195,7 @@
self.handle.sendline("git pull " + comp1)
uptodate = 0
- i=self.handle.expect(['fatal','Username\sfor\s(.*):\s','\sfile(s*) changed,\s',pexpect.TIMEOUT,'Already up-to-date','Aborting','You\sare\snot\scurrently\son\sa\sbranch'],timeout=1700)
+ i=self.handle.expect(['fatal','Username\sfor\s(.*):\s','\sfile(s*) changed,\s',pexpect.TIMEOUT,'Already up-to-date','Aborting','You\sare\snot\scurrently\son\sa\sbranch', 'You\sasked\sme\sto\spull\swithout\stelling\sme\swhich\sbranch\syou'],timeout=1700)
#debug
#main.log.report(self.name +": \n"+"git pull response: " + str(self.handle.before) + str(self.handle.after))
if i==0:
@@ -1124,6 +1221,9 @@
elif i==6:
main.log.info(self.name + ": Git Pull - You are not currently on a branch so git pull failed!")
return main.ERROR
+ elif i==7:
+ main.log.info(self.name + ": Git Pull - You have not configured an upstream branch to pull from. Git pull failed!")
+ return main.ERROR
else:
main.log.error(self.name + ": Git Pull - Unexpected response, check for pull errors")
return main.ERROR
@@ -1141,6 +1241,100 @@
#********************************************************
+
+
+ def git_checkout(self, branch="onos13integration"):
+ '''
+ Assumes that "git pull" works without login
+
+ This function will perform a git pull on the ONOS instance.
+ If used as git_pull("NODE") it will do git pull + NODE. This is
+ for the purpose of pulling from other nodes if necessary.
+
+ Otherwise, this function will perform a git pull in the
+ ONOS repository. If it has any problems, it will return main.ERROR
+ If it successfully does a git_pull, it will return a 1.
+ If it has no updates, it will return a 0.
+
+ '''
+ try:
+ # main.log.info(self.name + ": Stopping ONOS")
+ #self.stop()
+ self.handle.sendline("cd " + self.home)
+ self.handle.expect("ONOS\$")
+ if branch != 'master':
+ #self.handle.sendline('git stash')
+ #self.handle.expect('ONOS\$')
+ #print "After issuing git stash cmnd: ", self.handle.before
+ cmd = "git checkout "+branch
+ print "checkout cmd = ", cmd
+ self.handle.sendline(cmd)
+ uptodate = 0
+ i=self.handle.expect(['fatal','Username\sfor\s(.*):\s','Already\son\s\'onos13integration\'','Switched\sto\sbranch\s\'onos13integration\'', pexpect.TIMEOUT],timeout=60)
+ else:
+ #self.handle.sendline('git stash apply')
+ #self.handle.expect('ONOS\$')
+ #print "After issuing git stash apply cmnd: ", self.handle.before
+ cmd = "git checkout "+branch
+ print "checkout cmd = ", cmd
+ self.handle.sendline(cmd)
+ uptodate = 0
+ switchedToMaster = 0
+ i=self.handle.expect(['fatal','Username\sfor\s(.*):\s','Already\son\s\'master\'','Switched\sto\sbranch\s\'master\'', pexpect.TIMEOUT],timeout=60)
+
+
+ if i==0:
+ main.log.error(self.name + ": Git checkout had some issue...")
+ return main.ERROR
+ elif i==1:
+ main.log.error(self.name + ": Git checkout Asking for username!!! BADD!")
+ return main.ERROR
+ elif i==2:
+ main.log.info(self.name + ": Git Checkout %s : Already on this branch" %branch)
+ self.handle.expect("ONOS\$")
+ print "after checkout cmd = ", self.handle.before
+ switchedToMaster = 1
+ return 1
+ elif i==3:
+ main.log.info(self.name + ": Git checkout %s - Switched to this branch" %branch)
+ self.handle.expect("ONOS\$")
+ print "after checkout cmd = ", self.handle.before
+ switchedToMaster = 1
+ return 1
+ elif i==4:
+ main.log.error(self.name + ": Git Checkout- TIMEOUT")
+ main.log.error(self.name + " Response was: " + str(self.handle.before))
+ return main.ERROR
+ else:
+ main.log.error(self.name + ": Git Checkout - Unexpected response, check for pull errors")
+ return main.ERROR
+
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.name + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.log.error( traceback.print_exc() )
+ main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.cleanup()
+ main.exit()
+#********************************************************
+ self.handle.sendline("git branch")
+ self.handle.expect("ONOS\$")
+ print "git branch output = ", self.handle.before
+ print "*****************************************"
+ self.handle.sendline('cd\.\.')
+ self.handle.expect("\$")
+
+
+
+
+
+
+
+
def git_compile(self):
'''
Compiles ONOS
@@ -1280,14 +1474,11 @@
return (retcode, "Rest API has an error", retport)
else:
for host in enumerate(parsedResult):
- print host
if (host[1] != []):
try:
foundHost = host[1]['mac']
except:
print "Error in detecting MAC address."
- print foundHost
- print hostMAC
if foundHost == hostMAC:
for switch in enumerate(host[1]['attachmentPoints']):
retswitch.append(switch[1]['dpid'])
@@ -1330,26 +1521,33 @@
output = ''
self.handle.sendline("")
i = self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
- #main.log.warn("first expect response: " +str(i))
+ main.log.warn("first expect response: " +str(i))
self.handle.sendline("cd "+self.home+"/onos-logs")
- self.handle.sendline("zgrep \"xception\" *.log *.log.gz *.stderr *.stdout")
- i = self.handle.expect(["\*",pexpect.EOF,pexpect.TIMEOUT])
- #main.log.warn("second expect response: " +str(i))
- i = self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT],timeout=120)
+ i = self.handle.expect(["onos-logs\$",pexpect.EOF,pexpect.TIMEOUT])
+ main.log.warn("second expect response: " +str(i))
+
+ self.handle.sendline("zgrep \"xception\" *.log *.log.gz *.stderr")
+ #i = self.handle.expect(["\*.stdout",pexpect.EOF,pexpect.TIMEOUT])
#main.log.warn("third expect response: " +str(i))
+ print self.handle.before
+ print
+ print self.handle.after
+ i = self.handle.expect(["ONOS/onos-logs\$",pexpect.EOF,pexpect.TIMEOUT],timeout=120)
+ main.log.warn("fourth expect response: " +str(i))
response = self.handle.before
print response
count = 0
print response
for line in response.splitlines():
if re.search("gzip: \*\.log\.gz:", line):
+ #gzip complaining about file not found
pass
- elif re.search("log:", line):
- output +="Exceptions found in " + line + "\n"
- count +=1
elif re.search("log\.gz:",line):
output+="Exceptions found in " + line + "\n"
count +=1
+ elif re.search("log:", line):
+ output +="Exceptions found in " + line + "\n"
+ count +=1
elif re.search("std...:",line):
output+="Exceptions found in " + line + "\n"
count +=1
diff --git a/TestON/drivers/common/cli/ramcloudclidriver.py b/TestON/drivers/common/cli/ramcloudclidriver.py
index 0546edf..5b19508 100644
--- a/TestON/drivers/common/cli/ramcloudclidriver.py
+++ b/TestON/drivers/common/cli/ramcloudclidriver.py
@@ -66,6 +66,55 @@
main.log.error(self.name+": Connection failed to the host "+self.user_name+"@"+self.ip_address)
main.log.error(self.name+": Failed to connect to the Onos system")
return main.FALSE
+
+ def kill_serv(self):
+ import re
+ try:
+ self.handle.sendline("ps -ef |grep 'master/server' |awk 'NR==1 {print $2}' |xargs sudo kill -9")
+ self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+ self.handle.sendline("ps -ef |grep 'master/server' |wc -l")
+ self.handle.expect(["wc -l",pexpect.EOF,pexpect.TIMEOUT])
+ response = self.handle.after
+ if re.search("1",response):
+ return "RAMCloud Server Killed!"
+ else:
+ return "ERROR!!! RAMCLOUd SERVER MAY NOT HAVE BEEN KILLED PROPERLY!!!"
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.hane + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.log.error( traceback.print_exc() )
+ main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.cleanup()
+ main.exit()
+
+ def kill_coord(self):
+ import re
+ try:
+ self.handle.sendline("ps -ef |grep 'master/coordinator' |awk 'NR==1 {print $2}' |xargs sudo kill -9")
+ self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+ self.handle.sendline("ps -ef |grep 'master/coordinator' |wc -l")
+ self.handle.expect(["wc -l",pexpect.EOF,pexpect.TIMEOUT])
+ response = self.handle.after
+ if re.search("1",response):
+ return "RAMCloud Coordinator Killed!"
+ else:
+ return "ERROR!!! RAMCLOUD COORDINATOR MAY NOT HAVE BEEN KILLED PROPERLY!!!"
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.hane + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.log.error( traceback.print_exc() )
+ main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.cleanup()
+ main.exit()
+
def start_serv(self):
diff --git a/TestON/drivers/common/cli/zookeeperclidriver.py b/TestON/drivers/common/cli/zookeeperclidriver.py
index 2a7c218..9a35366 100644
--- a/TestON/drivers/common/cli/zookeeperclidriver.py
+++ b/TestON/drivers/common/cli/zookeeperclidriver.py
@@ -44,6 +44,32 @@
self.handle = self
self.wrapped = sys.modules[__name__]
+ def kill(self):
+ import re
+ try:
+ self.handle.sendline("ps -ef |grep 'zookeeper.log.dir' |awk 'NR==1 {print $2}' |xargs sudo kill -9")
+ self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+ self.handle.sendline("ps -ef |grep 'zookeeper.log.dir' |wc -l")
+ self.handle.expect(["wc -l",pexpect.EOF,pexpect.TIMEOUT])
+ response = self.handle.after
+ if re.search("1",response):
+ return "Zookeeper Killed!"
+ else:
+ return "ERROR!!! ZOOKEEPER MAY NOT HAVE BEEN KILLED PROPERLY!!!"
+ except pexpect.EOF:
+ main.log.error(self.name + ": EOF exception found")
+ main.log.error(self.hane + ": " + self.handle.before)
+ main.cleanup()
+ main.exit()
+ except:
+ main.log.info(self.name + ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.log.error( traceback.print_exc() )
+ main.log.info(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::")
+ main.cleanup()
+ main.exit()
+
+
+
def connect(self, **connectargs):
# Here the main is the TestON instance after creating all the log handles.
self.port = None
@@ -96,13 +122,12 @@
'''
This Function will return the Status of the Zookeeper
'''
- time.sleep(5)
self.execute(cmd="\n",prompt="\$",timeout=10)
self.handle.sendline("cd "+self.home)
response = self.execute(cmd="./onos.sh zk status ",prompt="JMX",timeout=10)
-
+ response=self.handle.after
self.execute(cmd="\n",prompt="\$",timeout=10)
- return response
+ return self.handle.before + self.handle.after
def stop(self):
'''
@@ -144,6 +169,8 @@
def findMaster(self, switchDPID, switchList):
import json
decoded = json.loads(switchList)
+ if switchList=="":
+ return "NO CONTROLLERS FOUND"
for k in decoded.iteritems():
k2 = json.dumps(k)
if re.search(switchDPID,k2):
diff --git a/TestON/tests/HATestONOS/HATestONOS.params b/TestON/tests/HATestONOS/HATestONOS.params
new file mode 100644
index 0000000..6952d1b
--- /dev/null
+++ b/TestON/tests/HATestONOS/HATestONOS.params
@@ -0,0 +1,50 @@
+<PARAMS>
+ <testcases>1,2,3,4,5,6,7,8</testcases>
+ <CTRL>
+ <ip1>10.128.9.1</ip1>
+ <port1>6633</port1>
+ <restPort1>8080</restPort1>
+ <ip2>10.128.9.2</ip2>
+ <port2>6633</port2>
+ <restPort2>8080</restPort2>
+ <ip3>10.128.9.3</ip3>
+ <port3>6633</port3>
+ <restPort3>8080</restPort3>
+ <ip4>10.128.9.4</ip4>
+ <port4>6633</port4>
+ <restPort4>8080</restPort4>
+ <ip5>10.128.9.5</ip5>
+ <port5>6633</port5>
+ <restPort5>8080</restPort5>
+ <switchURL>/wm/onos/registry/switches/json</switchURL>
+ <intentHighURL>/wm/onos/intent/high</intentHighURL>
+ <intentLowURL>/wm/onos/intent/low</intentLowURL>
+ </CTRL>
+ <TopoRest>/wm/onos/topology</TopoRest>
+ <INTENTS>
+ <intentPort>8080</intentPort>
+ <intentURL>wm/onos/intent</intentURL>
+ </INTENTS>
+ <PING>
+ <source1>h8</source1>
+ <source2>h9</source2>
+ <source3>h10</source3>
+ <source4>h11</source4>
+ <source5>h12</source5>
+ <source6>h13</source6>
+ <source7>h14</source7>
+ <source8>h15</source8>
+ <source9>h16</source9>
+ <source10>h17</source10>
+ <target1>10.0.0.18</target1>
+ <target2>10.0.0.19</target2>
+ <target3>10.0.0.20</target3>
+ <target4>10.0.0.21</target4>
+ <target5>10.0.0.22</target5>
+ <target6>10.0.0.23</target6>
+ <target7>10.0.0.24</target7>
+ <target8>10.0.0.25</target8>
+ <target9>10.0.0.26</target9>
+ <target10>10.0.0.27</target10>
+ </PING>
+</PARAMS>
diff --git a/TestON/tests/HATestONOS/HATestONOS.py b/TestON/tests/HATestONOS/HATestONOS.py
new file mode 100644
index 0000000..ff9c7b3
--- /dev/null
+++ b/TestON/tests/HATestONOS/HATestONOS.py
@@ -0,0 +1,458 @@
+
+class HATestONOS:
+
+ global topology
+ global masterSwitchList
+ global highIntentList
+ global lowIntentList
+ global flows
+ flows = []
+
+ def __init__(self) :
+ self.default = ''
+
+ '''
+ CASE1 is to close any existing instances of ONOS, clean out the
+ RAMCloud database, and start up ONOS instances.
+ '''
+ def CASE1(self,main) :
+ main.case("Initial Startup")
+ main.step("Stop ONOS")
+ main.ONOS1.stop_all()
+ main.ONOS2.stop_all()
+ main.ONOS3.stop_all()
+ main.ONOS4.stop_all()
+ main.ONOS5.stop_all()
+ main.ONOS1.stop_rest()
+ main.ONOS2.stop_rest()
+ main.ONOS3.stop_rest()
+ main.ONOS4.stop_rest()
+ main.ONOS5.stop_rest()
+ result = main.ONOS1.status() or main.ONOS2.status() \
+ or main.ONOS3.status() or main.ONOS4.status() or main.ONOS5.status()
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="ONOS stopped successfully",onfail="ONOS WAS NOT KILLED PROPERLY")
+ main.step("Startup Zookeeper")
+ main.ZK1.start()
+ main.ZK2.start()
+ main.ZK3.start()
+ main.ZK4.start()
+ main.ZK5.start()
+ result = main.ZK1.isup() and main.ZK2.isup()\
+ and main.ZK3.isup() and main.ZK4.isup() and main.ZK5.isup()
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Zookeeper started successfully",onfail="ZOOKEEPER FAILED TO START")
+ main.step("Cleaning RC Database and Starting All")
+ main.RC1.del_db()
+ main.RC2.del_db()
+ main.RC3.del_db()
+ main.RC4.del_db()
+ main.RC5.del_db()
+ main.ONOS1.start_all()
+ main.ONOS2.start_all()
+ main.ONOS3.start_all()
+ main.ONOS4.start_all()
+ main.ONOS5.start_all()
+ # main.ONOS1.start_rest()
+ main.step("Testing Startup")
+ result1 = main.ONOS1.rest_status()
+ vm1 = main.RC1.status_coor and main.RC1.status_serv and \
+ main.ONOS1.isup()
+ vm2 = main.RC2.status_coor and main.ONOS2.isup()
+ vm3 = main.RC3.status_coor and main.ONOS3.isup()
+ vm4 = main.RC4.status_coor and main.ONOS4.isup()
+ vm5 = main.RC5.status_coor and main.ONOS5.isup()
+ result = result1 and vm1 and vm2 and vm3 and vm4 and vm5
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Everything started successfully",onfail="EVERYTHING FAILED TO START")
+
+ '''
+ CASE2
+ '''
+ def CASE2(self,main) :
+ import time
+ import json
+ import re
+ main.log.report("Assigning Controllers")
+ main.case("Assigning Controllers")
+ main.step("Assign Master Controllers")
+ for i in range(1,29):
+ if i ==1:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ elif i>=2 and i<5:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip2'],port1=main.params['CTRL']['port2'])
+ elif i>=5 and i<8:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip3'],port1=main.params['CTRL']['port3'])
+ elif i>=8 and i<18:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip4'],port1=main.params['CTRL']['port4'])
+ elif i>=18 and i<28:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip5'],port1=main.params['CTRL']['port5'])
+ else:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+
+ result = main.TRUE
+ for i in range (1,29):
+ if i==1:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=2 and i<5:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip2'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=5 and i<8:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip3'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=8 and i<18:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip4'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=18 and i<28:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip5'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ else:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is" + str(response))
+ if re.search("tcp:" +main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+
+ utilities.assert_equals(expect = main.TRUE,actual=result,onpass="MasterControllers assigned correctly")
+ for i in range (1,29):
+ main.Mininet1.assign_sw_controller(sw=str(i),count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+
+ def CASE3(self,main) :
+ import time
+ import json
+ import re
+ main.case("Adding Intents")
+ intentIP = main.params['CTRL']['ip1']
+ intentPort=main.params['INTENTS']['intentPort']
+ intentURL=main.params['INTENTS']['intentURL']
+ count = 1
+ for i in range(8,18):
+ srcMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ dstMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ srcDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ dstDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ dstDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ srcDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ dstMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ srcMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ count = 1
+ i = 8
+ result = main.TRUE
+ while i <18 :
+ main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
+ ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
+ if ping ==main.FALSE and count <9:
+ count+=1
+ i = 8
+ result = main.FALSE
+ main.log.info("Ping FAILED! Making attempt number "+str(count) + "in 2 seconds")
+ time.sleep(2)
+ elif ping==main.FALSE:
+ main.log.info("PINGS FAILED! MAX RETRIES REACHED!")
+ i=19
+ result = main.FALSE
+ elif ping==main.TRUE:
+ main.log.info("Ping passed!")
+ i+=1
+ result = main.TRUE
+ else:
+ main.log.info("ERROR!!")
+ result = main.ERROR
+ if result==main.FALSE:
+ main.log.info("INTENTS HAVE NOT BEEN INSTALLED CORRECTLY!! EXITING!!!")
+ main.cleanup()
+ main.exit()
+
+
+ def CASE4(self,main) :
+ import time
+ from subprocess import Popen, PIPE
+ main.case("Setting up and Gathering data for current state")
+ main.step("Get the current In-Memory Topology on each ONOS Instance")
+
+ '''
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip'+str(count)) in main.params['CTRL']:
+ temp = temp+(getattr(main,('ONOS'+str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count+=1
+ else:
+ break
+ topo_result = main.TRUE
+
+ for n in range(1,count):
+ temp_result = main.Mininet1.compare_topo(ctrls,main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ '''
+ '''
+ main.step("Get the Mastership of each switch")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ global masterSwitchList1
+ masterSwitchList1 = stdout
+ '''
+
+ main.step("Get the High Level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ global highIntentList1
+ highIntentList1 = stdout
+
+ main.step("Get the Low level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ global lowIntentList1
+ lowIntentList1= stdout
+
+ main.step("Get the OF Table entries")
+ global flows
+ flows=[]
+ for i in range(1,29):
+ flows.append(main.Mininet2.get_flowTable("s"+str(i)))
+
+
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+
+ def CASE5(self,main) :
+ import re
+ from random import randint
+ main.case("MAIN COMPONENT FAILURE AND SCENARIO SPECIFIC TESTS")
+ main.step("ONOS CORE Failure!")
+ kill = randint(1,4)
+ if kill==1:
+ main.ONOS2.kill()
+ elif kill==2:
+ main.ONOS2.kill()
+ elif kill==3:
+ main.ONOS3.kill()
+ elif kill==4:
+ main.ONOS4.kill()
+ else:
+ main.ONOS5.kill()
+
+ kill2 = randint(1,5)
+ if kill2==kill:
+ if kill2==5:
+ main.ONOS4.kill()
+ elif kill2==1:
+ main.ONOS3.kill()
+ else:
+ main.ONOS5.kill()
+ else:
+ if kill2==1:
+ main.ONOS5.kill()
+ elif kill2==2:
+ main.ONOS2.kill()
+ elif kill2==3:
+ main.ONOS3.kill()
+ elif kill2==4:
+ main.ONOS4.kill()
+ else:
+ main.ONOS5.kill()
+ time.sleep(10)
+ main.step("Get the Mastership of each switch")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ global masterSwitchList1
+ masterSwitchList1 = stdout
+
+
+
+ def CASE6(self,main) :
+ import os
+ main.case("Running ONOS Constant State Tests")
+ main.step("Get the current In-Memory Topology on each ONOS Instance and Compare it to the Topology before component failure")
+
+ main.step("Get the Mastership of each switch and compare to the Mastership before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ result = main.TRUE
+ for i in range(1,29):
+ switchDPID = str(main.Mininet1.getSwitchDPID(switch="s"+str(i)))
+ switchDPID = switchDPID[:2]+":"+switchDPID[2:4]+":"+switchDPID[4:6]+":"+switchDPID[6:8]+":"+switchDPID[8:10]+":"+switchDPID[10:12]+":"+switchDPID[12:14]+":"+switchDPID[14:]
+ master1 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)
+ master2 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout)
+ if main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)==main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Mastership of Switches was not changed",onfail="MASTERSHIP OF SWITCHES HAS CHANGED!!!")
+ result1 = result
+
+ main.step("Get the High Level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_intents(preIntents=highIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE HIGH LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to High level Intents",onfail="CHANGES WERE MADE TO HIGH LEVEL INTENTS")
+ result2 = result
+
+ main.step("Get the Low level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_low(preIntents=lowIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE LOW LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to Low level Intents",onfail="CHANGES WERE MADE TO LOW LEVEL INTENTS")
+ result3 = result
+
+
+ main.step("Get the OF Table entries and compare to before component failure")
+ result = main.TRUE
+ flows2=[]
+ for i in range(27):
+ flows2.append(main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ result = result and main.Mininet2.flow_comp(flow1=flows[i], flow2=main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ if result == main.FALSE:
+ main.log.info("DIFFERENCES IN FLOW TABLES FOR SWITCH "+str(i))
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes in the flow tables",onfail="CHANGES IN THE FLOW TABLES!!")
+ result4 = result
+
+ main.step("Check the continuous pings to ensure that no packets were dropped during component failure")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result5 = not result
+ result = result1 and result2 and result3 and result4 and result5
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Constant State Tests Passed", onfail="CONSTANT STATE TESTS FAILED!!")
+
+ def CASE7 (self,main):
+ main.case("Killing a link to Ensure that Link Discovery is Working Properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches, %s are active, and %s links" %(number,active,links))
+
+ main.step("Kill Link between s3 and s28")
+ main.Mininet1.link(END1="s3",END2="s28",OPTION="down")
+ time.sleep(5)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,str(int(links)-2))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link Down discovered properly",onfail="LINKS NOT DISCOVERED PROPERLY")
+ result1 = result
+ result = main.Mininet1.link(END1="s3",END2="s28",OPTION="up")
+
+ main.step("Check for loss in pings when Link is brought down")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result2 = result
+ result = result1 and not result2
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link failure is discovered correctly and no traffic is lost!",onfail="Link Discovery failed or traffic was dropped!!!")
+
+ def CASE8 (self, main) :
+ import time
+ main.case("Killing a switch to ensure switch discovery is working properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches, %s are active, and %s links" %(number,active,links))
+
+ main.step("Kill s28 ")
+ main.Mininet2.del_switch("s28")
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],str(int(active)-1),str(int(links)-4))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+
+ main.step("Add back s28")
+ main.Mininet2.add_switch("s28")
+ main.Mininet1.assign_sw_controller(sw="28",ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ main.Mininet1.assign_sw_controller(sw="28",count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,links)
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+ result1=result
+
+ main.step("Checking for Traffic Loss")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result = not result and result1
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovered Correctly and No Loss of traffic",onfail="Switch discovery failed or there was loss of traffic")
diff --git a/TestON/tests/HATestONOS/HATestONOS.topo b/TestON/tests/HATestONOS/HATestONOS.topo
new file mode 100644
index 0000000..9ccdb17
--- /dev/null
+++ b/TestON/tests/HATestONOS/HATestONOS.topo
@@ -0,0 +1,183 @@
+<TOPOLOGY>
+
+ <COMPONENT>
+ <ZK1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK1>
+
+ <ZK2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK2>
+
+ <ZK3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK3>
+
+ <ZK4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK4>
+
+ <ZK5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK5>
+
+ <RC1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>6</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC1>
+
+ <RC2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>7</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC2>
+
+ <RC3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>8</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC3>
+
+ <RC4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>9</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC4>
+
+ <RC5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>10</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC5>
+
+ <ONOS1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>11</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS1>
+
+ <ONOS2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>12</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS2>
+
+ <ONOS3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS3>
+
+ <ONOS4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS4>
+
+ <ONOS5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>15</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS5>
+
+ <Mininet1>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>MininetCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet1>
+
+ <Mininet2>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>RemoteMininetDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-onos4node.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet2>
+
+ </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/HATestONOS2/HATestONOS2.params b/TestON/tests/HATestONOS2/HATestONOS2.params
new file mode 100644
index 0000000..6952d1b
--- /dev/null
+++ b/TestON/tests/HATestONOS2/HATestONOS2.params
@@ -0,0 +1,50 @@
+<PARAMS>
+ <testcases>1,2,3,4,5,6,7,8</testcases>
+ <CTRL>
+ <ip1>10.128.9.1</ip1>
+ <port1>6633</port1>
+ <restPort1>8080</restPort1>
+ <ip2>10.128.9.2</ip2>
+ <port2>6633</port2>
+ <restPort2>8080</restPort2>
+ <ip3>10.128.9.3</ip3>
+ <port3>6633</port3>
+ <restPort3>8080</restPort3>
+ <ip4>10.128.9.4</ip4>
+ <port4>6633</port4>
+ <restPort4>8080</restPort4>
+ <ip5>10.128.9.5</ip5>
+ <port5>6633</port5>
+ <restPort5>8080</restPort5>
+ <switchURL>/wm/onos/registry/switches/json</switchURL>
+ <intentHighURL>/wm/onos/intent/high</intentHighURL>
+ <intentLowURL>/wm/onos/intent/low</intentLowURL>
+ </CTRL>
+ <TopoRest>/wm/onos/topology</TopoRest>
+ <INTENTS>
+ <intentPort>8080</intentPort>
+ <intentURL>wm/onos/intent</intentURL>
+ </INTENTS>
+ <PING>
+ <source1>h8</source1>
+ <source2>h9</source2>
+ <source3>h10</source3>
+ <source4>h11</source4>
+ <source5>h12</source5>
+ <source6>h13</source6>
+ <source7>h14</source7>
+ <source8>h15</source8>
+ <source9>h16</source9>
+ <source10>h17</source10>
+ <target1>10.0.0.18</target1>
+ <target2>10.0.0.19</target2>
+ <target3>10.0.0.20</target3>
+ <target4>10.0.0.21</target4>
+ <target5>10.0.0.22</target5>
+ <target6>10.0.0.23</target6>
+ <target7>10.0.0.24</target7>
+ <target8>10.0.0.25</target8>
+ <target9>10.0.0.26</target9>
+ <target10>10.0.0.27</target10>
+ </PING>
+</PARAMS>
diff --git a/TestON/tests/HATestONOS2/HATestONOS2.py b/TestON/tests/HATestONOS2/HATestONOS2.py
new file mode 100644
index 0000000..861d282
--- /dev/null
+++ b/TestON/tests/HATestONOS2/HATestONOS2.py
@@ -0,0 +1,429 @@
+
+class HATestONOS2:
+
+ global topology
+ global masterSwitchList
+ global highIntentList
+ global lowIntentList
+ global flows
+ flows = []
+
+ def __init__(self) :
+ self.default = ''
+
+ '''
+ CASE1 is to close any existing instances of ONOS, clean out the
+ RAMCloud database, and start up ONOS instances.
+ '''
+ def CASE1(self,main) :
+ main.case("Initial Startup")
+ main.step("Stop ONOS")
+ main.ONOS1.stop_all()
+ main.ONOS2.stop_all()
+ main.ONOS3.stop_all()
+ main.ONOS4.stop_all()
+ main.ONOS5.stop_all()
+ main.ONOS1.stop_rest()
+ main.ONOS2.stop_rest()
+ main.ONOS3.stop_rest()
+ main.ONOS4.stop_rest()
+ main.ONOS5.stop_rest()
+ result = main.ONOS1.status() or main.ONOS2.status() \
+ or main.ONOS3.status() or main.ONOS4.status() or main.ONOS5.status()
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="ONOS stopped successfully",onfail="ONOS WAS NOT KILLED PROPERLY")
+ main.step("Startup Zookeeper")
+ main.ZK1.start()
+ main.ZK2.start()
+ main.ZK3.start()
+ main.ZK4.start()
+ main.ZK5.start()
+ result = main.ZK1.isup() and main.ZK2.isup()\
+ and main.ZK3.isup() and main.ZK4.isup() and main.ZK5.isup()
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Zookeeper started successfully",onfail="ZOOKEEPER FAILED TO START")
+ main.step("Cleaning RC Database and Starting All")
+ main.RC1.del_db()
+ main.RC2.del_db()
+ main.RC3.del_db()
+ main.RC4.del_db()
+ main.RC5.del_db()
+ main.ONOS1.start_all()
+ main.ONOS2.start_all()
+ main.ONOS3.start_all()
+ main.ONOS4.start_all()
+ main.ONOS5.start_all()
+ # main.ONOS1.start_rest()
+ main.step("Testing Startup")
+ result1 = main.ONOS1.rest_status()
+ vm1 = main.RC1.status_coor and main.RC1.status_serv and \
+ main.ONOS1.isup()
+ vm2 = main.RC2.status_coor and main.ONOS2.isup()
+ vm3 = main.RC3.status_coor and main.ONOS3.isup()
+ vm4 = main.RC4.status_coor and main.ONOS4.isup()
+ vm5 = main.RC5.status_coor and main.ONOS5.isup()
+ result = result1 and vm1 and vm2 and vm3 and vm4 and vm5
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Everything started successfully",onfail="EVERYTHING FAILED TO START")
+
+ '''
+ CASE2
+ '''
+ def CASE2(self,main) :
+ import time
+ import json
+ import re
+ main.log.report("Assigning Controllers")
+ main.case("Assigning Controllers")
+ main.step("Assign Master Controllers")
+ for i in range(1,29):
+ if i ==1:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ elif i>=2 and i<5:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip2'],port1=main.params['CTRL']['port2'])
+ elif i>=5 and i<8:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip3'],port1=main.params['CTRL']['port3'])
+ elif i>=8 and i<18:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip4'],port1=main.params['CTRL']['port4'])
+ elif i>=18 and i<28:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip5'],port1=main.params['CTRL']['port5'])
+ else:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+
+ result = main.TRUE
+ for i in range (1,29):
+ if i==1:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=2 and i<5:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip2'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=5 and i<8:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip3'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=8 and i<18:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip4'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=18 and i<28:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip5'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ else:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is" + str(response))
+ if re.search("tcp:" +main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+
+ utilities.assert_equals(expect = main.TRUE,actual=result,onpass="MasterControllers assigned correctly")
+ for i in range (1,29):
+ main.Mininet1.assign_sw_controller(sw=str(i),count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+
+ def CASE3(self,main) :
+ import time
+ import json
+ import re
+ main.case("Adding Intents")
+ intentIP = main.params['CTRL']['ip1']
+ intentPort=main.params['INTENTS']['intentPort']
+ intentURL=main.params['INTENTS']['intentURL']
+ count = 1
+ for i in range(8,18):
+ srcMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ dstMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ srcDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ dstDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ dstDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ srcDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ dstMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ srcMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ count = 1
+ i = 8
+ result = main.TRUE
+ while i <18 :
+ main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
+ ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
+ if ping ==main.FALSE and count <9:
+ count+=1
+ i = 8
+ result = main.FALSE
+ main.log.info("Ping FAILED! Making attempt number "+str(count) + "in 2 seconds")
+ time.sleep(2)
+ elif ping==main.FALSE:
+ main.log.info("PINGS FAILED! MAX RETRIES REACHED!")
+ i=19
+ result = main.FALSE
+ elif ping==main.TRUE:
+ main.log.info("Ping passed!")
+ i+=1
+ result = main.TRUE
+ else:
+ main.log.info("ERROR!!")
+ result = main.ERROR
+ if result==main.FALSE:
+ main.log.info("INTENTS HAVE NOT BEEN INSTALLED CORRECTLY!! EXITING!!!")
+ main.cleanup()
+ main.exit()
+
+
+ def CASE4(self,main) :
+ import time
+ from subprocess import Popen, PIPE
+ main.case("Setting up and Gathering data for current state")
+ main.step("Get the current In-Memory Topology on each ONOS Instance")
+
+ '''
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip'+str(count)) in main.params['CTRL']:
+ temp = temp+(getattr(main,('ONOS'+str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count+=1
+ else:
+ break
+ topo_result = main.TRUE
+
+ for n in range(1,count):
+ temp_result = main.Mininet1.compare_topo(ctrls,main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ '''
+ main.step("Get the Mastership of each switch")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ global masterSwitchList1
+ masterSwitchList1 = stdout
+
+ main.step("Get the High Level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ global highIntentList1
+ highIntentList1 = stdout
+
+ main.step("Get the Low level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ global lowIntentList1
+ lowIntentList1= stdout
+
+ main.step("Get the OF Table entries")
+ global flows
+ flows=[]
+ for i in range(1,29):
+ flows.append(main.Mininet2.get_flowTable("s"+str(i)))
+
+
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+
+ def CASE5(self,main) :
+ import re
+ from random import randint
+ main.case("MAIN COMPONENT FAILURE AND SCENARIO SPECIFIC TESTS")
+ main.step("ONOS CORE All - Failure!")
+ main.ONOS1.stop()
+ main.ONOS2.stop()
+ main.ONOS3.stop()
+ main.ONOS4.stop()
+ main.ONOS5.stop()
+ time.sleep(2)
+ main.ONOS1.start()
+ main.ONOS2.start()
+ main.ONOS3.start()
+ main.ONOS4.start()
+ main.ONOS5.start()
+ if main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup():
+ main.log.info("ONOS BACK UP!")
+ result = main.TRUE
+ else:
+ main.log.info("ONOS DID NOT COME BACK UP!!!")
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="ONOS has been brought back up!",onfail = "ONOS HAS FAILED TO RESTART!")
+
+ def CASE6(self,main) :
+ import os
+ main.case("Running ONOS Constant State Tests")
+ main.step("Get the current In-Memory Topology on each ONOS Instance and Compare it to the Topology before component failure")
+
+ main.step("Get the Mastership of each switch and compare to the Mastership before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ result = main.TRUE
+ for i in range(1,29):
+ switchDPID = str(main.Mininet1.getSwitchDPID(switch="s"+str(i)))
+ switchDPID = switchDPID[:2]+":"+switchDPID[2:4]+":"+switchDPID[4:6]+":"+switchDPID[6:8]+":"+switchDPID[8:10]+":"+switchDPID[10:12]+":"+switchDPID[12:14]+":"+switchDPID[14:]
+ master1 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)
+ master2 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout)
+ if main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)==main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Mastership of Switches was not changed",onfail="MASTERSHIP OF SWITCHES HAS CHANGED!!!")
+
+ main.step("Get the High Level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_intents(preIntents=highIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE HIGH LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to High level Intents",onfail="CHANGES WERE MADE TO HIGH LEVEL INTENTS")
+
+ main.step("Get the Low level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_low(preIntents=lowIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE LOW LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to Low level Intents",onfail="CHANGES WERE MADE TO LOW LEVEL INTENTS")
+
+
+ main.step("Get the OF Table entries and compare to before component failure")
+ result = main.TRUE
+ flows2=[]
+ for i in range(27):
+ flows2.append(main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ result = result and main.Mininet2.flow_comp(flow1=flows[i], flow2=main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ if result == main.FALSE:
+ main.log.info("DIFFERENCES IN FLOW TABLES FOR SWITCH "+str(i))
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes in the flow tables",onfail="CHANGES IN THE FLOW TABLES!!")
+
+ main.step("Check the continuous pings to ensure that no packets were dropped during component failure")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+
+ def CASE7 (self,main):
+ main.case("Killing a link to Ensure that Link Discovery is Working Properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches, %s are active, and %s links" %(number,active,links))
+
+ main.step("Kill Link between s3 and s28")
+ main.Mininet1.link(END1="s3",END2="s28",OPTION="down")
+ time.sleep(5)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,str(int(links)-2))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link Down discovered properly",onfail="LINKS NOT DISCOVERED PROPERLY")
+ result1 = result
+ result = main.Mininet1.link(END1="s3",END2="s28",OPTION="up")
+
+ main.step("Check for loss in pings when Link is brought down")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result2 = result
+ result = result1 and not result2
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link failure is discovered correctly and no traffic is lost!",onfail="Link Discovery failed or traffic was dropped!!!")
+
+ def CASE8 (self, main) :
+ import time
+ main.case("Killing a switch to ensure switch discovery is working properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches, %s are active, and %s links" %(number,active,links))
+
+ main.step("Kill s28 ")
+ main.Mininet2.del_switch("s28")
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],str(int(active)-1),str(int(links)-4))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+
+ main.step("Add back s28")
+ main.Mininet2.add_switch("s28")
+ main.Mininet1.assign_sw_controller(sw="28",ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ main.Mininet1.assign_sw_controller(sw="28",count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,links)
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+ result1=result
+
+ main.step("Checking for Traffic Loss")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result = not result and result1
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovered Correctly and No Loss of traffic",onfail="Switch discovery failed or there was loss of traffic")
diff --git a/TestON/tests/HATestONOS2/HATestONOS2.topo b/TestON/tests/HATestONOS2/HATestONOS2.topo
new file mode 100644
index 0000000..9ccdb17
--- /dev/null
+++ b/TestON/tests/HATestONOS2/HATestONOS2.topo
@@ -0,0 +1,183 @@
+<TOPOLOGY>
+
+ <COMPONENT>
+ <ZK1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK1>
+
+ <ZK2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK2>
+
+ <ZK3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK3>
+
+ <ZK4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK4>
+
+ <ZK5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK5>
+
+ <RC1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>6</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC1>
+
+ <RC2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>7</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC2>
+
+ <RC3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>8</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC3>
+
+ <RC4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>9</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC4>
+
+ <RC5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>10</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC5>
+
+ <ONOS1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>11</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS1>
+
+ <ONOS2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>12</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS2>
+
+ <ONOS3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS3>
+
+ <ONOS4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS4>
+
+ <ONOS5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>15</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS5>
+
+ <Mininet1>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>MininetCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet1>
+
+ <Mininet2>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>RemoteMininetDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-onos4node.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet2>
+
+ </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/HATestRCS/HATestRCS.params b/TestON/tests/HATestRCS/HATestRCS.params
new file mode 100644
index 0000000..6952d1b
--- /dev/null
+++ b/TestON/tests/HATestRCS/HATestRCS.params
@@ -0,0 +1,50 @@
+<PARAMS>
+ <testcases>1,2,3,4,5,6,7,8</testcases>
+ <CTRL>
+ <ip1>10.128.9.1</ip1>
+ <port1>6633</port1>
+ <restPort1>8080</restPort1>
+ <ip2>10.128.9.2</ip2>
+ <port2>6633</port2>
+ <restPort2>8080</restPort2>
+ <ip3>10.128.9.3</ip3>
+ <port3>6633</port3>
+ <restPort3>8080</restPort3>
+ <ip4>10.128.9.4</ip4>
+ <port4>6633</port4>
+ <restPort4>8080</restPort4>
+ <ip5>10.128.9.5</ip5>
+ <port5>6633</port5>
+ <restPort5>8080</restPort5>
+ <switchURL>/wm/onos/registry/switches/json</switchURL>
+ <intentHighURL>/wm/onos/intent/high</intentHighURL>
+ <intentLowURL>/wm/onos/intent/low</intentLowURL>
+ </CTRL>
+ <TopoRest>/wm/onos/topology</TopoRest>
+ <INTENTS>
+ <intentPort>8080</intentPort>
+ <intentURL>wm/onos/intent</intentURL>
+ </INTENTS>
+ <PING>
+ <source1>h8</source1>
+ <source2>h9</source2>
+ <source3>h10</source3>
+ <source4>h11</source4>
+ <source5>h12</source5>
+ <source6>h13</source6>
+ <source7>h14</source7>
+ <source8>h15</source8>
+ <source9>h16</source9>
+ <source10>h17</source10>
+ <target1>10.0.0.18</target1>
+ <target2>10.0.0.19</target2>
+ <target3>10.0.0.20</target3>
+ <target4>10.0.0.21</target4>
+ <target5>10.0.0.22</target5>
+ <target6>10.0.0.23</target6>
+ <target7>10.0.0.24</target7>
+ <target8>10.0.0.25</target8>
+ <target9>10.0.0.26</target9>
+ <target10>10.0.0.27</target10>
+ </PING>
+</PARAMS>
diff --git a/TestON/tests/HATestRCS/HATestRCS.py b/TestON/tests/HATestRCS/HATestRCS.py
new file mode 100644
index 0000000..80413f8
--- /dev/null
+++ b/TestON/tests/HATestRCS/HATestRCS.py
@@ -0,0 +1,446 @@
+
+class HATestRCS:
+
+ global topology
+ global masterSwitchList
+ global highIntentList
+ global lowIntentList
+ global flows
+ flows = []
+
+ def __init__(self) :
+ self.default = ''
+
+ '''
+ CASE1 is to close any existing instances of ONOS, clean out the
+ RAMCloud database, and start up ONOS instances.
+ '''
+ def CASE1(self,main) :
+
+ main.case("Initial Startup")
+ main.step("Stop ONOS")
+ main.ONOS1.stop_all()
+ main.ONOS2.stop_all()
+ main.ONOS3.stop_all()
+ main.ONOS4.stop_all()
+ main.ONOS5.stop_all()
+ main.ONOS1.stop_rest()
+ main.ONOS2.stop_rest()
+ main.ONOS3.stop_rest()
+ main.ONOS4.stop_rest()
+ main.ONOS5.stop_rest()
+ result = main.ONOS1.status() or main.ONOS2.status() \
+ or main.ONOS3.status() or main.ONOS4.status() or main.ONOS5.status()
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="ONOS stopped successfully",onfail="ONOS WAS NOT KILLED PROPERLY")
+ main.step("Startup Zookeeper")
+ main.ZK1.start()
+ main.ZK2.start()
+ main.ZK3.start()
+ main.ZK4.start()
+ main.ZK5.start()
+ result = main.ZK1.isup() and main.ZK2.isup()\
+ and main.ZK3.isup() and main.ZK4.isup() and main.ZK5.isup()
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Zookeeper started successfully",onfail="ZOOKEEPER FAILED TO START")
+ main.step("Cleaning RC Database and Starting All")
+ main.RC1.del_db()
+ main.RC2.del_db()
+ main.RC3.del_db()
+ main.RC4.del_db()
+ main.RC5.del_db()
+ main.ONOS1.start_all()
+ main.ONOS2.start_all()
+ main.ONOS3.start_all()
+ main.ONOS4.start_all()
+ main.ONOS5.start_all()
+ # main.ONOS1.start_rest()
+ main.step("Testing Startup")
+ result1 = main.ONOS1.rest_status()
+ vm1 = main.RC1.status_coor and main.RC1.status_serv and \
+ main.ONOS1.isup()
+ vm2 = main.RC2.status_coor and main.ONOS2.isup()
+ vm3 = main.RC3.status_coor and main.ONOS3.isup()
+ vm4 = main.RC4.status_coor and main.ONOS4.isup()
+ vm5 = main.RC5.status_coor and main.ONOS5.isup()
+ result = result1 and vm1 and vm2 and vm3 and vm4 and vm5
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Everything started successfully",onfail="EVERYTHING FAILED TO START")
+
+ '''
+ CASE2
+ '''
+ def CASE2(self,main) :
+ import time
+ import json
+ import re
+ main.log.report("Assigning Controllers")
+ main.case("Assigning Controllers")
+ main.step("Assign Master Controllers")
+ for i in range(1,29):
+ if i ==1:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ elif i>=2 and i<5:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip2'],port1=main.params['CTRL']['port2'])
+ elif i>=5 and i<8:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip3'],port1=main.params['CTRL']['port3'])
+ elif i>=8 and i<18:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip4'],port1=main.params['CTRL']['port4'])
+ elif i>=18 and i<28:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip5'],port1=main.params['CTRL']['port5'])
+ else:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+
+ result = main.TRUE
+ for i in range (1,29):
+ if i==1:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=2 and i<5:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip2'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=5 and i<8:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip3'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=8 and i<18:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip4'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=18 and i<28:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip5'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ else:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is" + str(response))
+ if re.search("tcp:" +main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+
+ utilities.assert_equals(expect = main.TRUE,actual=result,onpass="MasterControllers assigned correctly")
+ for i in range (1,29):
+ main.Mininet1.assign_sw_controller(sw=str(i),count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+
+ def CASE3(self,main) :
+ import time
+ import json
+ import re
+ main.case("Adding Intents")
+ intentIP = main.params['CTRL']['ip1']
+ intentPort=main.params['INTENTS']['intentPort']
+ intentURL=main.params['INTENTS']['intentURL']
+ count = 1
+ for i in range(8,18):
+ srcMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ dstMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ srcDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ dstDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ dstDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ srcDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ dstMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ srcMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ count = 1
+ i = 8
+ result = main.TRUE
+ while i <18 :
+ main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
+ ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
+ if ping ==main.FALSE and count <9:
+ count+=1
+ i = 8
+ result = main.FALSE
+ main.log.info("Ping FAILED! Making attempt number "+str(count) + "in 2 seconds")
+ time.sleep(2)
+ elif ping==main.FALSE:
+ main.log.info("PINGS FAILED! MAX RETRIES REACHED!")
+ i=19
+ result = main.FALSE
+ elif ping==main.TRUE:
+ main.log.info("Ping passed!")
+ i+=1
+ result = main.TRUE
+ else:
+ main.log.info("ERROR!!")
+ result = main.ERROR
+ if result==main.FALSE:
+ main.log.info("INTENTS HAVE NOT BEEN INSTALLED CORRECTLY!! EXITING!!!")
+ main.cleanup()
+ main.exit()
+
+
+ def CASE4(self,main) :
+ import time
+ from subprocess import Popen, PIPE
+ main.case("Setting up and Gathering data for current state")
+ main.step("Get the current In-Memory Topology on each ONOS Instance")
+
+ '''
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip'+str(count)) in main.params['CTRL']:
+ temp = temp+(getattr(main,('ONOS'+str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count+=1
+ else:
+ break
+ topo_result = main.TRUE
+
+ for n in range(1,count):
+ temp_result = main.Mininet1.compare_topo(ctrls,main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ '''
+ main.step("Get the Mastership of each switch")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ global masterSwitchList1
+ masterSwitchList1 = stdout
+
+ main.step("Get the High Level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ global highIntentList1
+ highIntentList1 = stdout
+
+ main.step("Get the Low level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ global lowIntentList1
+ lowIntentList1= stdout
+
+ main.step("Get the OF Table entries")
+ global flows
+ flows=[]
+ for i in range(1,29):
+ flows.append(main.Mininet2.get_flowTable("s"+str(i)))
+
+
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+
+ def CASE5(self,main) :
+ import re
+ from random import randint
+ main.case("MAIN COMPONENT FAILURE AND SCENARIO SPECIFIC TESTS")
+ main.step("RC CORE Failure!")
+ kill = randint(1,4)
+ if kill==1:
+ main.RC1.stop_serv()
+ elif kill==2:
+ main.RC2.stop_serv()
+ elif kill==3:
+ main.RC3.stop_serv()
+ elif kill==4:
+ main.RC4.stop_serv()
+ else:
+ main.RC5.stop_serv()
+
+ kill2 = randint(1,5)
+ if kill2==kill:
+ if kill2==5:
+ main.RC4.stop_serv()
+ elif kill2==1:
+ main.RC3.stop_serv()
+ else:
+ main.RC5.stop_serv()
+ else:
+ if kill2==1:
+ main.RC1.stop_serv()
+ elif kill2==2:
+ main.RC2.stop_serv()
+ elif kill2==3:
+ main.RC3.stop_serv()
+ elif kill2==4:
+ main.RC4.stop_serv()
+ else:
+ main.RC5.stop_serv()
+ time.sleep(10)
+
+
+
+ def CASE6(self,main) :
+ import os
+ main.case("Running ONOS Constant State Tests")
+ main.step("Get the current In-Memory Topology on each ONOS Instance and Compare it to the Topology before component failure")
+
+ main.step("Get the Mastership of each switch and compare to the Mastership before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ result = main.TRUE
+ for i in range(1,29):
+ switchDPID = str(main.Mininet1.getSwitchDPID(switch="s"+str(i)))
+ switchDPID = switchDPID[:2]+":"+switchDPID[2:4]+":"+switchDPID[4:6]+":"+switchDPID[6:8]+":"+switchDPID[8:10]+":"+switchDPID[10:12]+":"+switchDPID[12:14]+":"+switchDPID[14:]
+ master1 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)
+ master2 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout)
+ if main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)==main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Mastership of Switches was not changed",onfail="MASTERSHIP OF SWITCHES HAS CHANGED!!!")
+
+ main.step("Get the High Level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_intents(preIntents=highIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE HIGH LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to High level Intents",onfail="CHANGES WERE MADE TO HIGH LEVEL INTENTS")
+
+ main.step("Get the Low level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_low(preIntents=lowIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE LOW LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to Low level Intents",onfail="CHANGES WERE MADE TO LOW LEVEL INTENTS")
+
+
+ main.step("Get the OF Table entries and compare to before component failure")
+ result = main.TRUE
+ flows2=[]
+ for i in range(27):
+ flows2.append(main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ result = result and main.Mininet2.flow_comp(flow1=flows[i], flow2=main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ if result == main.FALSE:
+ main.log.info("DIFFERENCES IN FLOW TABLES FOR SWITCH "+str(i))
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes in the flow tables",onfail="CHANGES IN THE FLOW TABLES!!")
+
+ main.step("Check the continuous pings to ensure that no packets were dropped during component failure")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+
+ def CASE7 (self,main):
+ main.case("Killing a link to Ensure that Link Discovery is Working Properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches, %s are active, and %s links" %(number,active,links))
+
+ main.step("Kill Link between s3 and s28")
+ main.Mininet1.link(END1="s3",END2="s28",OPTION="down")
+ time.sleep(5)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,str(int(links)-2))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link Down discovered properly",onfail="LINKS NOT DISCOVERED PROPERLY")
+ result1 = result
+ result = main.Mininet1.link(END1="s3",END2="s28",OPTION="up")
+
+ main.step("Check for loss in pings when Link is brought down")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result2 = result
+ result = result1 and not result2
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link failure is discovered correctly and no traffic is lost!",onfail="Link Discovery failed or traffic was dropped!!!")
+
+ def CASE8 (self, main) :
+ import time
+ main.case("Killing a switch to ensure switch discovery is working properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches, %s are active, and %s links" %(number,active,links))
+
+ main.step("Kill s28 ")
+ main.Mininet2.del_switch("s28")
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],str(int(active)-1),str(int(links)-4))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+
+ main.step("Add back s28")
+ main.Mininet2.add_switch("s28")
+ main.Mininet1.assign_sw_controller(sw="28",ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ main.Mininet1.assign_sw_controller(sw="28",count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,links)
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+ result1=result
+
+ main.step("Checking for Traffic Loss")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result = not result and result1
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovered Correctly and No Loss of traffic",onfail="Switch discovery failed or there was loss of traffic")
diff --git a/TestON/tests/HATestRCS/HATestRCS.topo b/TestON/tests/HATestRCS/HATestRCS.topo
new file mode 100644
index 0000000..9ccdb17
--- /dev/null
+++ b/TestON/tests/HATestRCS/HATestRCS.topo
@@ -0,0 +1,183 @@
+<TOPOLOGY>
+
+ <COMPONENT>
+ <ZK1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK1>
+
+ <ZK2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK2>
+
+ <ZK3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK3>
+
+ <ZK4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK4>
+
+ <ZK5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK5>
+
+ <RC1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>6</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC1>
+
+ <RC2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>7</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC2>
+
+ <RC3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>8</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC3>
+
+ <RC4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>9</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC4>
+
+ <RC5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>10</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC5>
+
+ <ONOS1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>11</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS1>
+
+ <ONOS2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>12</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS2>
+
+ <ONOS3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS3>
+
+ <ONOS4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS4>
+
+ <ONOS5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>15</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS5>
+
+ <Mininet1>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>MininetCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet1>
+
+ <Mininet2>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>RemoteMininetDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-onos4node.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet2>
+
+ </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/HATestSuite/__init.py__ b/TestON/tests/HATestSuite/__init.py__
new file mode 100644
index 0000000..8d1c8b6
--- /dev/null
+++ b/TestON/tests/HATestSuite/__init.py__
@@ -0,0 +1 @@
+
diff --git a/TestON/tests/HATestTemplate/HATest1.params b/TestON/tests/HATestTemplate/HATest1.params
new file mode 100644
index 0000000..4d405f9
--- /dev/null
+++ b/TestON/tests/HATestTemplate/HATest1.params
@@ -0,0 +1,50 @@
+<PARAMS>
+ <testcases>2,3,4,5,6</testcases>
+ <CTRL>
+ <ip1>10.128.9.1</ip1>
+ <port1>6633</port1>
+ <restPort1>8080</restPort1>
+ <ip2>10.128.9.2</ip2>
+ <port2>6633</port2>
+ <restPort2>8080</restPort2>
+ <ip3>10.128.9.3</ip3>
+ <port3>6633</port3>
+ <restPort3>8080</restPort3>
+ <ip4>10.128.9.4</ip4>
+ <port4>6633</port4>
+ <restPort4>8080</restPort4>
+ <ip5>10.128.9.5</ip5>
+ <port5>6633</port5>
+ <restPort5>8080</restPort5>
+ <switchURL>/wm/onos/registry/switches/json</switchURL>
+ <intentHighURL>/wm/onos/intent/high</intentHighURL>
+ <intentLowURL>/wm/onos/intent/low</intentLowURL>
+ </CTRL>
+ <TopoRest>/wm/onos/topology</TopoRest>
+ <INTENTS>
+ <intentPort>8080</intentPort>
+ <intentURL>wm/onos/intent</intentURL>
+ </INTENTS>
+ <PING>
+ <source1>h8</source1>
+ <source2>h9</source2>
+ <source3>h10</source3>
+ <source4>h11</source4>
+ <source5>h12</source5>
+ <source6>h13</source6>
+ <source7>h14</source7>
+ <source8>h15</source8>
+ <source9>h16</source9>
+ <source10>h17</source10>
+ <target1>10.0.0.18</target1>
+ <target2>10.0.0.19</target2>
+ <target3>10.0.0.20</target3>
+ <target4>10.0.0.21</target4>
+ <target5>10.0.0.22</target5>
+ <target6>10.0.0.23</target6>
+ <target7>10.0.0.24</target7>
+ <target8>10.0.0.25</target8>
+ <target9>10.0.0.26</target9>
+ <target10>10.0.0.27</target10>
+ </PING>
+</PARAMS>
diff --git a/TestON/tests/HATestTemplate/HATest1.py b/TestON/tests/HATestTemplate/HATest1.py
new file mode 100644
index 0000000..92b4965
--- /dev/null
+++ b/TestON/tests/HATestTemplate/HATest1.py
@@ -0,0 +1,382 @@
+
+class HATest1:
+
+ global topology
+ global masterSwitchList
+ global highIntentList
+ global lowIntentList
+ global flows
+ flows = []
+
+ def __init__(self) :
+ self.default = ''
+
+ '''
+ CASE1 is to close any existing instances of ONOS, clean out the
+ RAMCloud database, and start up ONOS instances.
+ '''
+ def CASE1(self,main) :
+ main.case("Initial Startup")
+ main.step("Stop ONOS")
+ if not main.ONOS1.status():
+ main.ONOS1.stop_all()
+ if not main.ONOS1.status():
+ main.ONOS2.stop_all()
+ if not main.ONOS1.status():
+ main.ONOS3.stop_all()
+ if not main.ONOS1.status():
+ main.ONOS4.stop_all()
+ main.ONOS1.stop_rest()
+ main.ONOS2.stop_rest()
+ main.ONOS3.stop_rest()
+ main.ONOS4.stop_rest()
+ result = main.ONOS1.status() or main.ONOS2.status() \
+ or main.ONOS3.status() or main.ONOS4.status()
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="ONOS stopped successfully",onfail="ONOS WAS NOT KILLED PROPERLY")
+ main.step("Startup Zookeeper")
+ main.ZK1.start()
+ main.ZK2.start()
+ main.ZK3.start()
+ main.ZK4.start()
+ result = main.ZK1.isup() and main.ZK2.isup()\
+ and main.ZK3.isup() and main.ZK4.isup
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Zookeeper started successfully",onfail="ZOOKEEPER FAILED TO START")
+ main.step("Cleaning RC Database and Starting All")
+ main.RC1.deldb()
+ main.RC2.deldb()
+ main.RC3.deldb()
+ main.RC4.deldb()
+ main.ONOS1.start_all()
+ main.ONOS2.start_all()
+ main.ONOS3.start_all()
+ main.ONOS4.start_all()
+ main.ONOS1.start_rest()
+ main.step("Testing Startup")
+ result1 = main.ONOS1.rest_status()
+ vm1 = main.RC1.status_coor and main.RC1.status_serv and \
+ main.ONOS1.isup()
+ vm2 = main.RC2.status_coor and main.ONOS2.isup()
+ vm3 = main.RC3.status_coor and main.ONOS3.isup()
+ vm4 = main.RC4.status_coor and main.ONOS4.isup()
+ result = result1 and vm1 and vm2 and vm3 and vm4
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Everything started successfully",onfail="EVERYTHING FAILED TO START")
+
+ '''
+ CASE2
+ '''
+ def CASE2(self,main) :
+ import time
+ import json
+ import re
+ main.log.report("Assigning Controllers")
+ main.case("Assigning Controllers")
+ main.step("Assign Master Controllers")
+ for i in range(1,28):
+ if i ==1:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ elif i>=2 and i<5:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip2'],port1=main.params['CTRL']['port2'])
+ elif i>=5 and i<8:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip3'],port1=main.params['CTRL']['port3'])
+ elif i>=8 and i<18:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip4'],port1=main.params['CTRL']['port4'])
+ elif i>=18 and i<28:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip5'],port1=main.params['CTRL']['port5'])
+ else:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+
+ result = main.TRUE
+ for i in range (1,28):
+ if i==1:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=2 and i<5:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip2'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=5 and i<8:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip3'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=8 and i<18:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip4'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=18 and i<28:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip5'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ else:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is" + str(response))
+ if re.search("tcp:" +main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ utilities.assert_equals(expect = main.TRUE,actual=result,onpass="MasterControllers assigned correctly")
+
+ def CASE3(self,main) :
+ import time
+ import json
+ import re
+ main.case("Adding Intents")
+ intentIP = main.params['CTRL']['ip1']
+ intentPort=main.params['INTENTS']['intentPort']
+ intentURL=main.params['INTENTS']['intentURL']
+ count = 1
+ for i in range(8,18):
+ srcMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ dstMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ srcDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ dstDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ dstDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ srcDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ dstMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ srcMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ count = 1
+ i = 8
+ result = main.TRUE
+ while i <18 :
+ main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
+ ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
+ if ping ==main.FALSE and count <9:
+ count+=1
+ i = 8
+ result = main.FALSE
+ main.log.info("Ping FAILED! Making attempt number "+str(count) + "in 2 seconds")
+ time.sleep(2)
+ elif ping==main.FALSE:
+ main.log.info("PINGS FAILED! MAX RETRIES REACHED!")
+ i=19
+ result = main.FALSE
+ elif ping==main.TRUE:
+ main.log.info("Ping passed!")
+ i+=1
+ result = main.TRUE
+ else:
+ main.log.info("ERROR!!")
+ result = main.ERROR
+ if result==main.FALSE:
+ main.log.info("INTENTS HAVE NOT BEEN INSTALLED CORRECTLY!! EXITING!!!")
+ main.cleanup()
+ main.exit()
+
+
+ def CASE4(self,main) :
+ import time
+ from subprocess import Popen, PIPE
+ main.case("Setting up and Gathering data for current state")
+ main.step("Get the current In-Memory Topology on each ONOS Instance")
+
+ '''
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip'+str(count)) in main.params['CTRL']:
+ temp = temp+(getattr(main,('ONOS'+str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count+=1
+ else:
+ break
+ topo_result = main.TRUE
+
+ for n in range(1,count):
+ temp_result = main.Mininet1.compare_topo(ctrls,main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ '''
+
+ main.step("Get the Mastership of each switch")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ global masterSwitchList1
+ masterSwitchList1 = stdout
+
+ main.step("Get the High Level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ global highIntentList1
+ highIntentList1 = stdout
+
+ main.step("Get the Low level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ global lowIntentList1
+ lowIntentList1= stdout
+
+ main.step("Get the OF Table entries")
+ global flows
+ flows=[]
+ for i in range(1,28):
+ print main.Mininet2.get_flowTable("s"+str(i))
+ flows.append(main.Mininet2.get_flowTable("s"+str(i)))
+
+
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+
+ def CASE5(self,main) :
+ import re
+ main.case("MAIN COMPONENT FAILURE AND SCENARIO SPECIFIC TESTS")
+ main.step("Zookeeper Server Failure!")
+ result = main.TRUE
+ master1 = main.ZK1.status()
+ print master1
+ if re.search("leader",master1):
+ main.ZK1.stop()
+ main.log.info("ZK1 was Master and Killed! Also Killing ZK2")
+ main.ZK2.stop()
+ time.sleep(10)
+ if re.search("leader",main.ZK3.status()) or re.search("leader",main.ZK4.status()) or re.search("leader",main.ZK5.status()):
+ result = main.TRUE
+ main.log.info("New Leader Elected")
+ else:
+ result = main.FALSE
+ main.log.info("NO NEW ZK LEADER ELECTED!!!")
+ else:
+ master2 = main.ZK2.status()
+ if re.search("leader",master2):
+ main.ZK2.stop()
+ main.log.info("ZK2 was Master and Killed! Also Killing ZK3")
+ main.ZK3.stop()
+ time.sleep(10)
+ if re.search("leader",main.ZK1.status()) or re.search("leader",main.ZK4.status()) or re.search("leader",main.ZK5.status()):
+ result = main.TRUE
+ main.log.info("New Leader Elected")
+ else:
+ result = main.FALSE
+ main.log.info("NO NEW ZK LEADER ELECTED!!!")
+ else:
+ master3 = main.ZK3.status()
+ if re.search("leader",master3):
+ main.ZK3.stop()
+ main.log.info("ZK3 was Master and Killed! Also Killing ZK4")
+ main.ZK4.stop()
+ time.sleep(10)
+ if re.search("leader",main.ZK1.status()) or re.search("leader",main.ZK2.status()) or re.search("leader",main.ZK5.status()):
+ result = main.TRUE
+ main.log.info("New Leader Elected")
+ else:
+ result = main.FALSE
+ main.log.info("NO NEW ZK LEADER ELECTED!!!")
+ else:
+ master4 = main.ZK4.status()
+ if re.search("leader",master4):
+ main.ZK4.stop()
+ main.log.info("ZK4 was Master and Killed! Also Killing ZK5")
+ main.ZK5.stop()
+ time.sleep(10)
+ if re.search("leader",main.ZK1.status()) or re.search("leader",main.ZK2.status()) or re.search("leader",main.ZK3.status()):
+ result = main.TRUE
+ main.log.info("New Leader Elected")
+ else:
+ result = main.FALSE
+ main.log.info("NO NEW ZK LEADER ELECTED!!!")
+ else:
+ main.ZK5.stop()
+ main.log.info("ZK5 was Master and Killed! Also Killing ZK1")
+ main.ZK1.stop()
+ time.sleep(10)
+ if re.search("leader",main.ZK3.status()) or re.search("leader",main.ZK4.status()) or re.search("leader",main.ZK2.status()):
+ result = main.TRUE
+ main.log.info("New Leader Elected")
+ else:
+ result = main.FALSE
+ main.log.info("NO NEW ZK LEADER ELECTED!!!")
+
+
+ def CASE6(self,main) :
+ import os
+ main.case("Running ONOS Constant State Tests")
+ main.step("Get the current In-Memory Topology on each ONOS Instance and Compare it to the Topology before component failure")
+
+ main.step("Get the Mastership of each switch and compare to the Mastership before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ result = main.TRUE
+ for i in range(1,28):
+ if main.ZK1.findMaster(switchDPID="s"+str(i),switchList=masterSwitchList1)==main.ZK1.findMaster(switchDPID="s"+str(i),switchList=stdout):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Mastership of Switches was not changed",onfail="MASTERSHIP OF SWITCHES HAS CHANGED!!!")
+
+ main.step("Get the High Level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_intents(preIntents=highIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE HIGH LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to High level Intents",onfail="CHANGES WERE MADE TO HIGH LEVEL INTENTS")
+
+ main.step("Get the Low level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_low(preIntents=lowIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE LOW LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to Low level Intents",onfail="CHANGES WERE MADE TO LOW LEVEL INTENTS")
+
+
+ main.step("Get the OF Table entries and compare to before component failure")
+ result = main.TRUE
+ flows2=[]
+ for i in range(27):
+ flows2.append(main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ result = result and main.Mininet2.flow_comp(flow1=flows[i], flow2=main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ print flows[i]
+ print flows2[i]
+ if result == main.FALSE:
+ main.log.info("DIFFERENCES IN FLOW TABLES FOR SWITCH "+str(i))
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes in the flow tables",onfail="CHANGES IN THE FLOW TABLES!!")
+
+ main.step("Check the continuous pings to ensure that no packets were dropped during component failure")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+
+
+
+
+
diff --git a/TestON/tests/HATestTemplate/HATest1.topo b/TestON/tests/HATestTemplate/HATest1.topo
new file mode 100644
index 0000000..9ccdb17
--- /dev/null
+++ b/TestON/tests/HATestTemplate/HATest1.topo
@@ -0,0 +1,183 @@
+<TOPOLOGY>
+
+ <COMPONENT>
+ <ZK1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK1>
+
+ <ZK2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK2>
+
+ <ZK3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK3>
+
+ <ZK4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK4>
+
+ <ZK5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK5>
+
+ <RC1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>6</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC1>
+
+ <RC2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>7</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC2>
+
+ <RC3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>8</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC3>
+
+ <RC4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>9</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC4>
+
+ <RC5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>10</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC5>
+
+ <ONOS1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>11</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS1>
+
+ <ONOS2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>12</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS2>
+
+ <ONOS3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS3>
+
+ <ONOS4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS4>
+
+ <ONOS5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>15</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS5>
+
+ <Mininet1>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>MininetCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet1>
+
+ <Mininet2>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>RemoteMininetDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-onos4node.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet2>
+
+ </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/HATestZK/HATestZK.params b/TestON/tests/HATestZK/HATestZK.params
index 677605c..24f1a29 100644
--- a/TestON/tests/HATestZK/HATestZK.params
+++ b/TestON/tests/HATestZK/HATestZK.params
@@ -1,19 +1,19 @@
<PARAMS>
- <testcases>1,2,3,4,5,6</testcases>
+ <testcases>1,2,3,4,5,6,7,8</testcases>
<CTRL>
- <ip1>10.128.9.1</ip1>
+ <ip1>10.128.11.1</ip1>
<port1>6633</port1>
<restPort1>8080</restPort1>
- <ip2>10.128.9.2</ip2>
+ <ip2>10.128.11.2</ip2>
<port2>6633</port2>
<restPort2>8080</restPort2>
- <ip3>10.128.9.3</ip3>
+ <ip3>10.128.11.3</ip3>
<port3>6633</port3>
<restPort3>8080</restPort3>
- <ip4>10.128.9.4</ip4>
+ <ip4>10.128.11.4</ip4>
<port4>6633</port4>
<restPort4>8080</restPort4>
- <ip5>10.128.9.5</ip5>
+ <ip5>10.128.11.5</ip5>
<port5>6633</port5>
<restPort5>8080</restPort5>
<switchURL>/wm/onos/registry/switches/json</switchURL>
@@ -25,6 +25,8 @@
<intentPort>8080</intentPort>
<intentURL>wm/onos/intent</intentURL>
</INTENTS>
+ <TESTONUSER>admin</TESTONUSER>
+ <TESTONIP>10.128.11.11</TESTONIP>
<PING>
<source1>h8</source1>
<source2>h9</source2>
diff --git a/TestON/tests/HATestZK/HATestZK.py b/TestON/tests/HATestZK/HATestZK.py
index 89969d3..2f8c462 100644
--- a/TestON/tests/HATestZK/HATestZK.py
+++ b/TestON/tests/HATestZK/HATestZK.py
@@ -1,12 +1,11 @@
+'''
+Description: This case is to ensure that in the event of Zookeeper failures (including the leader node)
+the cluster should continue to function properly by the passing of Zookeeper functionality to the
+remaining nodes. In this test, a quorum of the Zookeeper instances must be kept alive.
+'''
class HATestZK:
- global topology
- global masterSwitchList
- global highIntentList
- global lowIntentList
- global flows
- flows = []
def __init__(self) :
self.default = ''
@@ -18,38 +17,39 @@
def CASE1(self,main) :
main.case("Initial Startup")
main.step("Stop ONOS")
- if not main.ONOS1.status():
- main.ONOS1.stop_all()
- if not main.ONOS1.status():
- main.ONOS2.stop_all()
- if not main.ONOS1.status():
- main.ONOS3.stop_all()
- if not main.ONOS1.status():
- main.ONOS4.stop_all()
+ main.ONOS1.stop_all()
+ main.ONOS2.stop_all()
+ main.ONOS3.stop_all()
+ main.ONOS4.stop_all()
+ main.ONOS5.stop_all()
main.ONOS1.stop_rest()
main.ONOS2.stop_rest()
main.ONOS3.stop_rest()
main.ONOS4.stop_rest()
+ main.ONOS5.stop_rest()
result = main.ONOS1.status() or main.ONOS2.status() \
- or main.ONOS3.status() or main.ONOS4.status()
+ or main.ONOS3.status() or main.ONOS4.status() or main.ONOS5.status()
utilities.assert_equals(expect=main.FALSE,actual=result,onpass="ONOS stopped successfully",onfail="ONOS WAS NOT KILLED PROPERLY")
main.step("Startup Zookeeper")
main.ZK1.start()
main.ZK2.start()
main.ZK3.start()
main.ZK4.start()
+ main.ZK5.start()
result = main.ZK1.isup() and main.ZK2.isup()\
- and main.ZK3.isup() and main.ZK4.isup
+ and main.ZK3.isup() and main.ZK4.isup() and main.ZK5.isup()
utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Zookeeper started successfully",onfail="ZOOKEEPER FAILED TO START")
main.step("Cleaning RC Database and Starting All")
- main.RC1.deldb()
- main.RC2.deldb()
- main.RC3.deldb()
- main.RC4.deldb()
+ main.RC1.del_db()
+ main.RC2.del_db()
+ main.RC3.del_db()
+ main.RC4.del_db()
+ main.RC5.del_db()
main.ONOS1.start_all()
main.ONOS2.start_all()
main.ONOS3.start_all()
main.ONOS4.start_all()
+ main.ONOS5.start_all()
main.ONOS1.start_rest()
main.step("Testing Startup")
result1 = main.ONOS1.rest_status()
@@ -58,8 +58,12 @@
vm2 = main.RC2.status_coor and main.ONOS2.isup()
vm3 = main.RC3.status_coor and main.ONOS3.isup()
vm4 = main.RC4.status_coor and main.ONOS4.isup()
- result = result1 and vm1 and vm2 and vm3 and vm4
+ vm5 = main.RC5.status_coor and main.ONOS5.isup()
+ result = result1 and vm1 and vm2 and vm3 and vm4 and vm5
utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Everything started successfully",onfail="EVERYTHING FAILED TO START")
+ if result==main.FALSE:
+ main.cleanup()
+ main.exit()
'''
CASE2
@@ -71,7 +75,7 @@
main.log.report("Assigning Controllers")
main.case("Assigning Controllers")
main.step("Assign Master Controllers")
- for i in range(1,28):
+ for i in range(1,29):
if i ==1:
main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
elif i>=2 and i<5:
@@ -86,7 +90,7 @@
main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
result = main.TRUE
- for i in range (1,28):
+ for i in range (1,29):
if i==1:
response = main.Mininet1.get_sw_controller("s"+str(i))
print("Response is " + str(response))
@@ -129,7 +133,10 @@
result = result and main.TRUE
else:
result = main.FALSE
+
utilities.assert_equals(expect = main.TRUE,actual=result,onpass="MasterControllers assigned correctly")
+ for i in range (1,29):
+ main.Mininet1.assign_sw_controller(sw=str(i),count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
def CASE3(self,main) :
import time
@@ -185,28 +192,8 @@
def CASE4(self,main) :
import time
from subprocess import Popen, PIPE
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
main.case("Setting up and Gathering data for current state")
- main.step("Get the current In-Memory Topology on each ONOS Instance")
-
- '''
- ctrls = []
- count = 1
- while True:
- temp = ()
- if ('ip'+str(count)) in main.params['CTRL']:
- temp = temp+(getattr(main,('ONOS'+str(count))),)
- temp = temp + ("ONOS"+str(count),)
- temp = temp + (main.params['CTRL']['ip'+str(count)],)
- temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
- ctrls.append(temp)
- count+=1
- else:
- break
- topo_result = main.TRUE
-
- for n in range(1,count):
- temp_result = main.Mininet1.compare_topo(ctrls,main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
- '''
main.step("Get the Mastership of each switch")
(stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
@@ -226,8 +213,7 @@
main.step("Get the OF Table entries")
global flows
flows=[]
- for i in range(1,28):
- print main.Mininet2.get_flowTable("s"+str(i))
+ for i in range(1,29):
flows.append(main.Mininet2.get_flowTable("s"+str(i)))
@@ -243,6 +229,29 @@
main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+ main.step("Create TestONTopology object")
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ global MNTopo
+ Topo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+ MNTopo = Topo
+
+ main.step("Compare ONOS Topology to MN Topology")
+ for n in range(1,5):
+ result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="ONOS" + str(n) + " Topology matches MN Topology",onfail="ONOS" + str(n) + " Topology does not match MN Topology")
+
def CASE5(self,main) :
import re
@@ -252,9 +261,9 @@
master1 = main.ZK1.status()
print master1
if re.search("leader",master1):
- main.ZK1.stop()
+ main.ZK1.kill()
main.log.info("ZK1 was Master and Killed! Also Killing ZK2")
- main.ZK2.stop()
+ main.ZK2.kill()
time.sleep(10)
if re.search("leader",main.ZK3.status()) or re.search("leader",main.ZK4.status()) or re.search("leader",main.ZK5.status()):
result = main.TRUE
@@ -265,9 +274,9 @@
else:
master2 = main.ZK2.status()
if re.search("leader",master2):
- main.ZK2.stop()
+ main.ZK2.kill()
main.log.info("ZK2 was Master and Killed! Also Killing ZK3")
- main.ZK3.stop()
+ main.ZK3.kill()
time.sleep(10)
if re.search("leader",main.ZK1.status()) or re.search("leader",main.ZK4.status()) or re.search("leader",main.ZK5.status()):
result = main.TRUE
@@ -278,9 +287,9 @@
else:
master3 = main.ZK3.status()
if re.search("leader",master3):
- main.ZK3.stop()
+ main.ZK3.kill()
main.log.info("ZK3 was Master and Killed! Also Killing ZK4")
- main.ZK4.stop()
+ main.ZK4.kill()
time.sleep(10)
if re.search("leader",main.ZK1.status()) or re.search("leader",main.ZK2.status()) or re.search("leader",main.ZK5.status()):
result = main.TRUE
@@ -291,9 +300,9 @@
else:
master4 = main.ZK4.status()
if re.search("leader",master4):
- main.ZK4.stop()
+ main.ZK4.kill()
main.log.info("ZK4 was Master and Killed! Also Killing ZK5")
- main.ZK5.stop()
+ main.ZK5.kill()
time.sleep(10)
if re.search("leader",main.ZK1.status()) or re.search("leader",main.ZK2.status()) or re.search("leader",main.ZK3.status()):
result = main.TRUE
@@ -302,9 +311,9 @@
result = main.FALSE
main.log.info("NO NEW ZK LEADER ELECTED!!!")
else:
- main.ZK5.stop()
+ main.ZK5.kill()
main.log.info("ZK5 was Master and Killed! Also Killing ZK1")
- main.ZK1.stop()
+ main.ZK1.kill()
time.sleep(10)
if re.search("leader",main.ZK3.status()) or re.search("leader",main.ZK4.status()) or re.search("leader",main.ZK2.status()):
result = main.TRUE
@@ -312,6 +321,8 @@
else:
result = main.FALSE
main.log.info("NO NEW ZK LEADER ELECTED!!!")
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="New Leader was Elected!",onfail="NO NEW LEADER WAS ELECTED!!!!")
+
def CASE6(self,main) :
@@ -319,15 +330,24 @@
main.case("Running ONOS Constant State Tests")
main.step("Get the current In-Memory Topology on each ONOS Instance and Compare it to the Topology before component failure")
- main.step("Get the Mastership of each switch and compare to the Mastership before component failure")
- (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
- result = main.TRUE
- for i in range(1,28):
- if main.ZK1.findMaster(switchDPID="s"+str(i),switchList=masterSwitchList1)==main.ZK1.findMaster(switchDPID="s"+str(i),switchList=stdout):
- result = result and main.TRUE
- else:
- result = main.FALSE
- utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Mastership of Switches was not changed",onfail="MASTERSHIP OF SWITCHES HAS CHANGED!!!")
+ #NOTE: Expected behavior for this case is for switchs to change mastership to another
+ # controller if the current controller's zk client loses connection with the ZK controller
+ #
+ #main.step("Get the Mastership of each switch and compare to the Mastership before component failure")
+ #(stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ #result = main.TRUE
+ #for i in range(1,29):
+ # switchDPID = str(main.Mininet1.getSwitchDPID(switch="s"+str(i)))
+ # switchDPID = switchDPID[:2]+":"+switchDPID[2:4]+":"+switchDPID[4:6]+":"+switchDPID[6:8]+":"+switchDPID[8:10]+":"+switchDPID[10:12]+":"+switchDPID[12:14]+":"+switchDPID[14:]
+ # master1 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)
+ # master2 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout)
+ # if master1 == master2:
+ # #if main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)==main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout):
+ # result = result and main.TRUE
+ # else:
+ # result = main.FALSE
+ #utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Mastership of Switches was not changed",onfail="MASTERSHIP OF SWITCHES HAS CHANGED!!!")
+ #result1 = result
main.step("Get the High Level Intents and compare to before component failure")
(stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
@@ -338,6 +358,7 @@
main.log.info("THERE WERE CHANGES TO THE HIGH LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
result = main.FALSE
utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to High level Intents",onfail="CHANGES WERE MADE TO HIGH LEVEL INTENTS")
+ result2=result
main.step("Get the Low level Intents and compare to before component failure")
(stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
@@ -348,6 +369,7 @@
main.log.info("THERE WERE CHANGES TO THE LOW LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
result = main.FALSE
utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to Low level Intents",onfail="CHANGES WERE MADE TO LOW LEVEL INTENTS")
+ result3=result
main.step("Get the OF Table entries and compare to before component failure")
@@ -355,16 +377,15 @@
flows2=[]
for i in range(27):
flows2.append(main.Mininet2.get_flowTable(sw="s"+str(i+1)))
- result = result and main.Mininet2.flow_comp(flow1=flows[i], flow2=main.Mininet2.get_flowTable(sw="s"+str(i+1)))
- print flows[i]
- print flows2[i]
+ result = result and main.Mininet2.flow_comp(flow1=flows[i], flow2=main.Mininet2.get_flowTable(sw="s"+str(i+1)))
if result == main.FALSE:
main.log.info("DIFFERENCES IN FLOW TABLES FOR SWITCH "+str(i))
break
utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes in the flow tables",onfail="CHANGES IN THE FLOW TABLES!!")
+ result4 = result
main.step("Check the continuous pings to ensure that no packets were dropped during component failure")
- main.Mininet2.pingKill()
+ main.Mininet2.pingKill(main.params['TESTONUSER'], main.params['TESTONIP'])
result = main.FALSE
for i in range(8,18):
result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
@@ -375,8 +396,130 @@
else:
main.log.info("No Loss in the pings!")
utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result5=not result
+
+ main.step("Check that ONOS Topology is consistent with MN Topology")
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+
+ result6 = main.TRUE
+ for n in range(1,5):
+ result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="ONOS" + str(n) + " Topology matches MN Topology",onfail="ONOS" + str(n) + " Topology does not match MN Topology")
+ result6 = result6 and result
+ result = result1 and result2 and result3 and result4 and result5 and result6
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Constant State Tests Passed!",onfail="CONSTANT STATE TESTS FAILED!!")
+ def CASE7 (self,main):
+ main.case("Killing a link to Ensure that Link Discovery is Working Properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches %s of which are active, and %s links" %(number,active,links))
+
+ main.step("Kill Link between s3 and s28")
+ main.Mininet1.link(END1="s3",END2="s28",OPTION="down")
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,str(int(links)-2))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link Down discovered properly",onfail="LINKS NOT DISCOVERED PROPERLY")
+ result1 = result
+ result = main.Mininet1.link(END1="s3",END2="s28",OPTION="up")
+
+ main.step("Check for loss in pings when Link is brought down")
+ main.Mininet2.pingKill(main.params['TESTONUSER'], main.params['TESTONIP'])
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result2 = not result
+ result = result1 and result2
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link failure is discovered correctly and no traffic is lost!",onfail="Link Discovery failed or traffic was dropped!!!")
+
+
+
+ def CASE8 (self, main) :
+ import time
+ main.case("Killing a switch to ensure switch discovery is working properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches %s of which are active, and %s links" %(number,active,links))
+
+ main.step("Kill s28 ")
+ main.Mininet2.del_switch("s28")
+ time.sleep(45)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],str(int(active)-1),str(int(links)-4))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+
+ main.step("Add back s28")
+ main.Mininet2.add_switch("s28")
+ main.Mininet1.assign_sw_controller(sw="28",ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ main.Mininet1.assign_sw_controller(sw="28",count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+ time.sleep(45)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,links)
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+ result1=result
+
+ main.step("Checking for Traffic Loss")
+ main.Mininet2.pingKill(main.params['TESTONUSER'], main.params['TESTONIP'])
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result = not result and result1
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovered Correctly and No Loss of traffic",onfail="Switch discovery failed or there was loss of traffic")
+
+# Authored by James Lee
+# Just wanted to see how many people were paying attention here.
+# Elayne Boosler once said "I have six locks on my door all in a row
+# When I go out, I lock every other one. I figure no matter how long
+# somebody stands there picking the locks, they are always locking three"
diff --git a/TestON/tests/HATestZK/HATestZK.topo b/TestON/tests/HATestZK/HATestZK.topo
index 9ccdb17..cecffad 100644
--- a/TestON/tests/HATestZK/HATestZK.topo
+++ b/TestON/tests/HATestZK/HATestZK.topo
@@ -2,7 +2,7 @@
<COMPONENT>
<ZK1>
- <host>10.128.9.1</host>
+ <host>10.128.11.1</host>
<user>admin</user>
<password></password>
<type>ZookeeperCliDriver</type>
@@ -12,7 +12,7 @@
</ZK1>
<ZK2>
- <host>10.128.9.2</host>
+ <host>10.128.11.2</host>
<user>admin</user>
<password></password>
<type>ZookeeperCliDriver</type>
@@ -22,7 +22,7 @@
</ZK2>
<ZK3>
- <host>10.128.9.3</host>
+ <host>10.128.11.3</host>
<user>admin</user>
<password></password>
<type>ZookeeperCliDriver</type>
@@ -32,7 +32,7 @@
</ZK3>
<ZK4>
- <host>10.128.9.4</host>
+ <host>10.128.11.4</host>
<user>admin</user>
<password></password>
<type>ZookeeperCliDriver</type>
@@ -42,7 +42,7 @@
</ZK4>
<ZK5>
- <host>10.128.9.5</host>
+ <host>10.128.11.5</host>
<user>admin</user>
<password></password>
<type>ZookeeperCliDriver</type>
@@ -52,7 +52,7 @@
</ZK5>
<RC1>
- <host>10.128.9.1</host>
+ <host>10.128.11.1</host>
<user>admin</user>
<password></password>
<type>RamCloudCliDriver</type>
@@ -62,7 +62,7 @@
</RC1>
<RC2>
- <host>10.128.9.2</host>
+ <host>10.128.11.2</host>
<user>admin</user>
<password></password>
<type>RamCloudCliDriver</type>
@@ -72,7 +72,7 @@
</RC2>
<RC3>
- <host>10.128.9.3</host>
+ <host>10.128.11.3</host>
<user>admin</user>
<password></password>
<type>RamCloudCliDriver</type>
@@ -82,7 +82,7 @@
</RC3>
<RC4>
- <host>10.128.9.4</host>
+ <host>10.128.11.4</host>
<user>admin</user>
<password></password>
<type>RamCloudCliDriver</type>
@@ -92,7 +92,7 @@
</RC4>
<RC5>
- <host>10.128.9.5</host>
+ <host>10.128.11.5</host>
<user>admin</user>
<password></password>
<type>RamCloudCliDriver</type>
@@ -102,7 +102,7 @@
</RC5>
<ONOS1>
- <host>10.128.9.1</host>
+ <host>10.128.11.1</host>
<user>admin</user>
<password></password>
<type>OnosCliDriver</type>
@@ -112,7 +112,7 @@
</ONOS1>
<ONOS2>
- <host>10.128.9.2</host>
+ <host>10.128.11.2</host>
<user>admin</user>
<password></password>
<type>OnosCliDriver</type>
@@ -122,7 +122,7 @@
</ONOS2>
<ONOS3>
- <host>10.128.9.3</host>
+ <host>10.128.11.3</host>
<user>admin</user>
<password></password>
<type>OnosCliDriver</type>
@@ -132,7 +132,7 @@
</ONOS3>
<ONOS4>
- <host>10.128.9.4</host>
+ <host>10.128.11.4</host>
<user>admin</user>
<password></password>
<type>OnosCliDriver</type>
@@ -142,7 +142,7 @@
</ONOS4>
<ONOS5>
- <host>10.128.9.5</host>
+ <host>10.128.11.5</host>
<user>admin</user>
<password></password>
<type>OnosCliDriver</type>
@@ -152,7 +152,7 @@
</ONOS5>
<Mininet1>
- <host>10.128.9.10</host>
+ <host>10.128.11.11</host>
<user>admin</user>
<password></password>
<type>MininetCliDriver</type>
@@ -166,7 +166,7 @@
</Mininet1>
<Mininet2>
- <host>10.128.9.10</host>
+ <host>10.128.11.11</host>
<user>admin</user>
<password></password>
<type>RemoteMininetDriver</type>
diff --git a/TestON/tests/HATestZK/__init__.py b/TestON/tests/HATestZK/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/HATestZK/__init__.py
diff --git a/TestON/tests/HATestZK2/HATestZK2.params b/TestON/tests/HATestZK2/HATestZK2.params
new file mode 100644
index 0000000..6952d1b
--- /dev/null
+++ b/TestON/tests/HATestZK2/HATestZK2.params
@@ -0,0 +1,50 @@
+<PARAMS>
+ <testcases>1,2,3,4,5,6,7,8</testcases>
+ <CTRL>
+ <ip1>10.128.9.1</ip1>
+ <port1>6633</port1>
+ <restPort1>8080</restPort1>
+ <ip2>10.128.9.2</ip2>
+ <port2>6633</port2>
+ <restPort2>8080</restPort2>
+ <ip3>10.128.9.3</ip3>
+ <port3>6633</port3>
+ <restPort3>8080</restPort3>
+ <ip4>10.128.9.4</ip4>
+ <port4>6633</port4>
+ <restPort4>8080</restPort4>
+ <ip5>10.128.9.5</ip5>
+ <port5>6633</port5>
+ <restPort5>8080</restPort5>
+ <switchURL>/wm/onos/registry/switches/json</switchURL>
+ <intentHighURL>/wm/onos/intent/high</intentHighURL>
+ <intentLowURL>/wm/onos/intent/low</intentLowURL>
+ </CTRL>
+ <TopoRest>/wm/onos/topology</TopoRest>
+ <INTENTS>
+ <intentPort>8080</intentPort>
+ <intentURL>wm/onos/intent</intentURL>
+ </INTENTS>
+ <PING>
+ <source1>h8</source1>
+ <source2>h9</source2>
+ <source3>h10</source3>
+ <source4>h11</source4>
+ <source5>h12</source5>
+ <source6>h13</source6>
+ <source7>h14</source7>
+ <source8>h15</source8>
+ <source9>h16</source9>
+ <source10>h17</source10>
+ <target1>10.0.0.18</target1>
+ <target2>10.0.0.19</target2>
+ <target3>10.0.0.20</target3>
+ <target4>10.0.0.21</target4>
+ <target5>10.0.0.22</target5>
+ <target6>10.0.0.23</target6>
+ <target7>10.0.0.24</target7>
+ <target8>10.0.0.25</target8>
+ <target9>10.0.0.26</target9>
+ <target10>10.0.0.27</target10>
+ </PING>
+</PARAMS>
diff --git a/TestON/tests/HATestZK2/HATestZK2.py b/TestON/tests/HATestZK2/HATestZK2.py
new file mode 100644
index 0000000..31db5f9
--- /dev/null
+++ b/TestON/tests/HATestZK2/HATestZK2.py
@@ -0,0 +1,459 @@
+
+class HATestZK2:
+
+ global topology
+ global masterSwitchList
+ global highIntentList
+ global lowIntentList
+ global flows
+ flows = []
+
+ def __init__(self) :
+ self.default = ''
+
+ '''
+ CASE1 is to close any existing instances of ONOS, clean out the
+ RAMCloud database, and start up ONOS instances.
+ '''
+ def CASE1(self,main) :
+ main.case("Initial Startup")
+ main.step("Stop ONOS")
+ main.ONOS1.stop_all()
+ main.ONOS2.stop_all()
+ main.ONOS3.stop_all()
+ main.ONOS4.stop_all()
+ main.ONOS5.stop_all()
+ main.ONOS1.stop_rest()
+ main.ONOS2.stop_rest()
+ main.ONOS3.stop_rest()
+ main.ONOS4.stop_rest()
+ main.ONOS5.stop_rest()
+ result = main.ONOS1.status() or main.ONOS2.status() \
+ or main.ONOS3.status() or main.ONOS4.status() or main.ONOS5.status()
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="ONOS stopped successfully",onfail="ONOS WAS NOT KILLED PROPERLY")
+ main.step("Startup Zookeeper")
+ main.ZK1.start()
+ main.ZK2.start()
+ main.ZK3.start()
+ main.ZK4.start()
+ main.ZK5.start()
+ result = main.ZK1.isup() and main.ZK2.isup()\
+ and main.ZK3.isup() and main.ZK4.isup() and main.ZK5.isup()
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Zookeeper started successfully",onfail="ZOOKEEPER FAILED TO START")
+ main.step("Cleaning RC Database and Starting All")
+ main.RC1.del_db()
+ main.RC2.del_db()
+ main.RC3.del_db()
+ main.RC4.del_db()
+ main.RC5.del_db()
+ main.ONOS1.start_all()
+ main.ONOS2.start_all()
+ main.ONOS3.start_all()
+ main.ONOS4.start_all()
+ main.ONOS5.start_all()
+ # main.ONOS1.start_rest()
+ main.step("Testing Startup")
+ result1 = main.ONOS1.rest_status()
+ vm1 = main.RC1.status_coor and main.RC1.status_serv and \
+ main.ONOS1.isup()
+ vm2 = main.RC2.status_coor and main.ONOS2.isup()
+ vm3 = main.RC3.status_coor and main.ONOS3.isup()
+ vm4 = main.RC4.status_coor and main.ONOS4.isup()
+ vm5 = main.RC5.status_coor and main.ONOS5.isup()
+ result = result1 and vm1 and vm2 and vm3 and vm4 and vm5
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Everything started successfully",onfail="EVERYTHING FAILED TO START")
+ if result==main.FALSE:
+ main.cleanup()
+ main.exit()
+
+ '''
+ CASE2
+ '''
+ def CASE2(self,main) :
+ import time
+ import json
+ import re
+ main.log.report("Assigning Controllers")
+ main.case("Assigning Controllers")
+ main.step("Assign Master Controllers")
+ for i in range(1,29):
+ if i ==1:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ elif i>=2 and i<5:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip2'],port1=main.params['CTRL']['port2'])
+ elif i>=5 and i<8:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip3'],port1=main.params['CTRL']['port3'])
+ elif i>=8 and i<18:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip4'],port1=main.params['CTRL']['port4'])
+ elif i>=18 and i<28:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip5'],port1=main.params['CTRL']['port5'])
+ else:
+ main.Mininet1.assign_sw_controller(sw=str(i),ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+
+ result = main.TRUE
+ for i in range (1,29):
+ if i==1:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=2 and i<5:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip2'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=5 and i<8:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip3'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=8 and i<18:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip4'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ elif i>=18 and i<28:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is " + str(response))
+ if re.search("tcp:"+main.params['CTRL']['ip5'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ else:
+ response = main.Mininet1.get_sw_controller("s"+str(i))
+ print("Response is" + str(response))
+ if re.search("tcp:" +main.params['CTRL']['ip1'],response):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+
+ utilities.assert_equals(expect = main.TRUE,actual=result,onpass="MasterControllers assigned correctly")
+ for i in range (1,29):
+ main.Mininet1.assign_sw_controller(sw=str(i),count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+
+ def CASE3(self,main) :
+ import time
+ import json
+ import re
+ main.case("Adding Intents")
+ intentIP = main.params['CTRL']['ip1']
+ intentPort=main.params['INTENTS']['intentPort']
+ intentURL=main.params['INTENTS']['intentURL']
+ count = 1
+ for i in range(8,18):
+ srcMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ dstMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ srcDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ dstDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ dstDPID = '00:00:00:00:00:00:30:'+str(i).zfill(2)
+ srcDPID= '00:00:00:00:00:00:60:' +str(i+10)
+ dstMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ srcMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,intentURL=intentURL)
+ count+=1
+ count = 1
+ i = 8
+ result = main.TRUE
+ while i <18 :
+ main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
+ ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
+ if ping ==main.FALSE and count <9:
+ count+=1
+ i = 8
+ result = main.FALSE
+ main.log.info("Ping FAILED! Making attempt number "+str(count) + "in 2 seconds")
+ time.sleep(2)
+ elif ping==main.FALSE:
+ main.log.info("PINGS FAILED! MAX RETRIES REACHED!")
+ i=19
+ result = main.FALSE
+ elif ping==main.TRUE:
+ main.log.info("Ping passed!")
+ i+=1
+ result = main.TRUE
+ else:
+ main.log.info("ERROR!!")
+ result = main.ERROR
+ if result==main.FALSE:
+ main.log.info("INTENTS HAVE NOT BEEN INSTALLED CORRECTLY!! EXITING!!!")
+ main.cleanup()
+ main.exit()
+
+
+ def CASE4(self,main) :
+ import time
+ from subprocess import Popen, PIPE
+ main.case("Setting up and Gathering data for current state")
+ main.step("Get the current In-Memory Topology on each ONOS Instance")
+
+ '''
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip'+str(count)) in main.params['CTRL']:
+ temp = temp+(getattr(main,('ONOS'+str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count+=1
+ else:
+ break
+ topo_result = main.TRUE
+
+ for n in range(1,count):
+ temp_result = main.Mininet1.compare_topo(ctrls,main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ '''
+
+ main.step("Get the Mastership of each switch")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ global masterSwitchList1
+ masterSwitchList1 = stdout
+
+ main.step("Get the High Level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ global highIntentList1
+ highIntentList1 = stdout
+
+ main.step("Get the Low level Intents")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ global lowIntentList1
+ lowIntentList1= stdout
+
+ main.step("Get the OF Table entries")
+ global flows
+ flows=[]
+ for i in range(1,29):
+ flows.append(main.Mininet2.get_flowTable("s"+str(i)))
+
+
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+
+ def CASE5(self,main) :
+ import re
+ main.case("MAIN COMPONENT FAILURE AND SCENARIO SPECIFIC TESTS")
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+
+ main.step("Zookeeper Server Failure!")
+ main.ZK1.stop()
+ main.ZK2.stop()
+ main.ZK3.stop()
+ main.ZK4.stop()
+ main.ZK5.stop()
+ main.Mininet2.del_switch("s1")
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],str(int(active)-1),str(int(links)-2))
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="Registry is no longer active",onfail="Registry is still being updated")
+
+ main.step("Restart Zookeeper")
+ main.ZK1.start()
+ main.ZK2.start()
+ main.ZK3.start()
+ main.ZK4.start()
+ main.ZK5.start()
+ time.sleep(10) # Time for Zookeeper to reboot
+ master1=main.ZK1.status()
+ master2=main.ZK2.status()
+ master3=main.ZK3.status()
+ master4=main.ZK4.status()
+ master5=main.ZK5.status()
+ if re.search("leader",master1) or re.search("leader",master2) or re.search("leader",master3) or re.search("leader",master4) or re.search("leader",master5):
+ main.log.info("New ZK Leader Elected")
+ else:
+ main.log.info("NO NEW ZK LEADER ELECTED!!!")
+ main.step("Add back s1")
+ main.Mininet2.add_switch("s1")
+ main.Mininet1.assign_sw_controller(sw="1",ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ main.Mininet1.assign_sw_controller(sw="1",count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+ time.sleep(31)
+
+
+ def CASE6(self,main) :
+ import os
+ main.case("Running ONOS Constant State Tests")
+ main.step("Get the current In-Memory Topology on each ONOS Instance and Compare it to the Topology before component failure")
+
+ main.step("Get the Mastership of each switch and compare to the Mastership before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['switchURL']],stdout=PIPE).communicate()
+ result = main.TRUE
+ for i in range(1,29):
+ switchDPID = str(main.Mininet1.getSwitchDPID(switch="s"+str(i)))
+ switchDPID = switchDPID[:2]+":"+switchDPID[2:4]+":"+switchDPID[4:6]+":"+switchDPID[6:8]+":"+switchDPID[8:10]+":"+switchDPID[10:12]+":"+switchDPID[12:14]+":"+switchDPID[14:]
+ master1 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)
+ master2 = main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout)
+ if main.ZK1.findMaster(switchDPID=switchDPID,switchList=masterSwitchList1)==main.ZK1.findMaster(switchDPID=switchDPID,switchList=stdout):
+ result = result and main.TRUE
+ else:
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Mastership of Switches was not changed",onfail="MASTERSHIP OF SWITCHES HAS CHANGED!!!")
+ result1 = result
+
+ main.step("Get the High Level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentHighURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_intents(preIntents=highIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE HIGH LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to High level Intents",onfail="CHANGES WERE MADE TO HIGH LEVEL INTENTS")
+ result2=result
+
+ main.step("Get the Low level Intents and compare to before component failure")
+ (stdout,stderr)=Popen(["curl",main.params['CTRL']['ip1']+":"+main.params['CTRL']['restPort1']+main.params['CTRL']['intentLowURL']],stdout=PIPE).communicate()
+ changesInIntents=main.ONOS1.comp_low(preIntents=lowIntentList1,postIntents=stdout)
+ if not changesInIntents:
+ result = main.TRUE
+ else:
+ main.log.info("THERE WERE CHANGES TO THE LOW LEVEL INTENTS! CHANGES WERE: "+str(changesInIntents))
+ result = main.FALSE
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes to Low level Intents",onfail="CHANGES WERE MADE TO LOW LEVEL INTENTS")
+ result3=result
+
+
+ main.step("Get the OF Table entries and compare to before component failure")
+ result = main.TRUE
+ flows2=[]
+ for i in range(27):
+ flows2.append(main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ result = result and main.Mininet2.flow_comp(flow1=flows[i], flow2=main.Mininet2.get_flowTable(sw="s"+str(i+1)))
+ if result == main.FALSE:
+ main.log.info("DIFFERENCES IN FLOW TABLES FOR SWITCH "+str(i))
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="No changes in the flow tables",onfail="CHANGES IN THE FLOW TABLES!!")
+ result4 = result
+
+ main.step("Check the continuous pings to ensure that no packets were dropped during component failure")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result5=not result
+ result = result1 and result2 and result3 and result4 and result5
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Constant State Tests Passed!",onfail="CONSTANT STATE TESTS FAILED!!")
+
+ def CASE7 (self,main):
+ main.case("Killing a link to Ensure that Link Discovery is Working Properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches, %s are active, and %s links" %(number,active,links))
+
+ main.step("Kill Link between s3 and s28")
+ main.Mininet1.link(END1="s3",END2="s28",OPTION="down")
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,str(int(links)-2))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Link Down discovered properly",onfail="LINKS NOT DISCOVERED PROPERLY")
+ result1 = result
+ result = main.Mininet1.link(END1="s3",END2="s28",OPTION="up")
+
+ main.step("Check for loss in pings when Link is brought down")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result2 = result
+ result = result1 and not result2
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="Link failure is discovered correctly and no traffic is lost!",onfail="Link Discovery failed or traffic was dropped!!!")
+
+
+
+ def CASE8 (self, main) :
+ import time
+ main.case("Killing a switch to ensure switch discovery is working properly")
+ main.step("Start continuous pings")
+ main.Mininet2.pingLong(src=main.params['PING']['source1'],target=main.params['PING']['target1'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source2'],target=main.params['PING']['target2'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source3'],target=main.params['PING']['target3'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source4'],target=main.params['PING']['target4'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source5'],target=main.params['PING']['target5'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source6'],target=main.params['PING']['target6'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source7'],target=main.params['PING']['target7'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source8'],target=main.params['PING']['target8'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source9'],target=main.params['PING']['target9'],pingTime=500)
+ main.Mininet2.pingLong(src=main.params['PING']['source10'],target=main.params['PING']['target10'],pingTime=500)
+
+ main.step("Determine the current number of switches and links")
+ (number,active)=main.ONOS1.num_switch(RestIP=main.params['CTRL']['ip1'])
+ links = main.ONOS1.num_link(RestIP=main.params['CTRL']['ip1'])
+ main.log.info("Currently there are %s switches, %s are active, and %s links" %(number,active,links))
+
+ main.step("Kill s28 ")
+ main.Mininet2.del_switch("s28")
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],str(int(active)-1),str(int(links)-4))
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+
+ main.step("Add back s28")
+ main.Mininet2.add_switch("s28")
+ main.Mininet1.assign_sw_controller(sw="28",ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'])
+ main.Mininet1.assign_sw_controller(sw="28",count=5,ip1=main.params['CTRL']['ip1'],port1=main.params['CTRL']['port1'],ip2=main.params['CTRL']['ip2'],port2=main.params['CTRL']['port2'],ip3=main.params['CTRL']['ip3'],port3=main.params['CTRL']['port3'],ip4=main.params['CTRL']['ip4'],port4=main.params['CTRL']['port4'],ip5=main.params['CTRL']['ip5'],port5=main.params['CTRL']['port5'])
+ time.sleep(31)
+ result = main.ONOS1.check_status_report(main.params['CTRL']['ip1'],active,links)
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovery is Working",onfail="Switch Discovery FAILED TO WORK PROPERLY!")
+ result1=result
+
+ main.step("Checking for Traffic Loss")
+ main.Mininet2.pingKill()
+ result = main.FALSE
+ for i in range(8,18):
+ result = result or main.Mininet2.checkForLoss("/tmp/ping.h"+str(i))
+ if result==main.TRUE:
+ main.log.info("LOSS IN THE PINGS!")
+ elif result == main.ERROR:
+ main.log.info("There are multiple mininet process running!!")
+ else:
+ main.log.info("No Loss in the pings!")
+ utilities.assert_equals(expect=main.FALSE,actual=result,onpass="No Loss of connectivity!",onfail="LOSS OF CONNECTIVITY")
+ result = not result and result1
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Switch Discovered Correctly and No Loss of traffic",onfail="Switch discovery failed or there was loss of traffic")
+
diff --git a/TestON/tests/HATestZK2/HATestZK2.topo b/TestON/tests/HATestZK2/HATestZK2.topo
new file mode 100644
index 0000000..9ccdb17
--- /dev/null
+++ b/TestON/tests/HATestZK2/HATestZK2.topo
@@ -0,0 +1,183 @@
+<TOPOLOGY>
+
+ <COMPONENT>
+ <ZK1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK1>
+
+ <ZK2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK2>
+
+ <ZK3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK3>
+
+ <ZK4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK4>
+
+ <ZK5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ZK5>
+
+ <RC1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>6</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC1>
+
+ <RC2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>7</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC2>
+
+ <RC3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>8</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC3>
+
+ <RC4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>9</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC4>
+
+ <RC5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>10</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RC5>
+
+ <ONOS1>
+ <host>10.128.9.1</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>11</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS1>
+
+ <ONOS2>
+ <host>10.128.9.2</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>12</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS2>
+
+ <ONOS3>
+ <host>10.128.9.3</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS3>
+
+ <ONOS4>
+ <host>10.128.9.4</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS4>
+
+ <ONOS5>
+ <host>10.128.9.5</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>15</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS5>
+
+ <Mininet1>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>MininetCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-HA.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet1>
+
+ <Mininet2>
+ <host>10.128.9.10</host>
+ <user>admin</user>
+ <password></password>
+ <type>RemoteMininetDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom ~/mininet/custom/topo-onos4node.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet2>
+
+ </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.params b/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.params
index 4d83c41..4ac9aea 100644
--- a/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.params
+++ b/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.params
@@ -1,5 +1,5 @@
<PARAMS>
- <testcases>1,2,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,9,8,9,21,9,61,9,71,9,3,9,4,9,5,9,6,9,7,3,4,5,6,7</testcases>
+ <testcases>1,2,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,9,8,9,3,9,4,9,5,9,6,9,7,3,4,5,6,7</testcases>
<pingSleep>1</pingSleep>
<pingAttempts>60</pingAttempts>
<CASE1>
@@ -18,14 +18,23 @@
<CTRL>
<ip1>10.128.5.1</ip1>
<port1>6633</port1>
+ <restPort1>8080</restPort1>
<ip2>10.128.5.2</ip2>
<port2>6633</port2>
+ <restPort2>8080</restPort2>
<ip3>10.128.5.3</ip3>
<port3>6633</port3>
+ <restPort3>8080</restPort3>
<ip4>10.128.5.4</ip4>
<port4>6633</port4>
+ <restPort4>8080</restPort4>
</CTRL>
<RestIP> 10.128.5.1 </RestIP>
+ <INTENTS>
+ <intentPort>8080</intentPort>
+ <intentURL>wm/onos/intent</intentURL>
+ </INTENTS>
+ <TopoRest>/wm/onos/topology</TopoRest>
<NR_Switches>25</NR_Switches>
<NR_Links>50</NR_Links>
<YANK>
diff --git a/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.py b/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.py
index 3543b65..fdc5f57 100644
--- a/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.py
+++ b/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.py
@@ -9,10 +9,10 @@
#Tests the startup of Zookeeper1, RamCloud1, and ONOS1 to be certain that all started up successfully
def CASE1(self,main) : #Check to be sure ZK, Cass, and ONOS are up, then get ONOS version
import time
- main.ONOS1.handle.sendline("cp ~/onos.properties.reactive ~/ONOS/conf/onos.properties")
- main.ONOS2.handle.sendline("cp ~/onos.properties.reactive ~/ONOS/conf/onos.properties")
- main.ONOS3.handle.sendline("cp ~/onos.properties.reactive ~/ONOS/conf/onos.properties")
- main.ONOS4.handle.sendline("cp ~/onos.properties.reactive ~/ONOS/conf/onos.properties")
+ main.ONOS1.handle.sendline("cp ~/onos.properties.proactive ~/ONOS/conf/onos.properties")
+ main.ONOS2.handle.sendline("cp ~/onos.properties.proactive ~/ONOS/conf/onos.properties")
+ main.ONOS3.handle.sendline("cp ~/onos.properties.proactive ~/ONOS/conf/onos.properties")
+ main.ONOS4.handle.sendline("cp ~/onos.properties.proactive ~/ONOS/conf/onos.properties")
main.ONOS1.stop_all()
main.ONOS2.stop_all()
@@ -187,21 +187,68 @@
main.ONOS3.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
main.ONOS4.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
break
- utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Topology check pass",onfail="Topology check FAIL")
+ ####New Topo Check
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
+ global MNTopo
+ MNTopo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+
+
+ topo_result = main.TRUE
+ for n in range(1,5):
+ temp_result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ topo_result = topo_result and temp_result
+ print "Topoology check results: " + str(topo_result)
+ ###End New Topo Check
+ utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Topology check pass",onfail="Topology check FAIL")
+
main.case("Taking care of these flows!")
main.step("Cleaning out any leftover flows...")
+ intentIP = main.params['CTRL']['ip1']
+ intentPort=main.params['INTENTS']['intentPort']
+ intentURL=main.params['INTENTS']['intentURL']
#main.ONOS1.delete_flow("all")
- main.ONOS1.rm_intents()
+ main.ONOS1.del_intent(intentIP=intentIP)
time.sleep(5)
- main.ONOS1.purge_intents()
strtTime = time.time()
- main.ONOS1.add_intents()
- main.case("Checking flows with pings")
+ main.step("Adding Intents")
+ count=1
+ for i in range(6,16):
+ srcMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ dstMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ srcDPID = '00:00:00:00:00:00:10:'+str(i).zfill(2)
+ dstDPID= '00:00:00:00:00:00:20:' +str(i+25)
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,
+ src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,
+ intentURL=intentURL)
+ count=count +1
+ dstDPID = '00:00:00:00:00:00:10:'+str(i).zfill(2)
+ srcDPID= '00:00:00:00:00:00:20:' +str(i+25)
+ dstMac = '00:00:00:00:00:' + str(hex(i)[2:]).zfill(2)
+ srcMac = '00:00:00:00:00:'+str(hex(i+10)[2:])
+ main.ONOS1.add_intent(intent_id=str(count),src_dpid=srcDPID,dst_dpid=dstDPID,
+ src_mac=srcMac,dst_mac=dstMac,intentIP=intentIP,intentPort=intentPort,
+ intentURL=intentURL)
+ count=count +1
+ main.step("Checking flows with pings")
pingAttempts = main.params['pingAttempts']
pingSleep = main.params['pingSleep']
+
count = 1
i = 6
while i < 16 :
@@ -277,6 +324,31 @@
main.ONOS3.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
main.ONOS4.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
break
+ ####New Topo Check
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
+ global MNTopo
+ MNTopo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+
+
+ topo_result = main.TRUE
+ for n in range(1,5):
+ temp_result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ topo_result = topo_result and temp_result
+ print "Topoology check results: " + str(topo_result)
+ ###End New Topo Check
utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Topology check pass",onfail="Topology check FAIL")
pingAttempts = main.params['pingAttempts']
@@ -338,6 +410,31 @@
main.ONOS3.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
main.ONOS4.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
break
+ ####New Topo Check
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
+ global MNTopo
+ MNTopo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+
+
+ topo_result = main.TRUE
+ for n in range(1,5):
+ temp_result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ topo_result = topo_result and temp_result
+ print "Topoology check results: " + str(topo_result)
+ ###End New Topo Check
utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Topology check pass",onfail="Topology check FAIL")
pingAttempts = main.params['pingAttempts']
@@ -395,6 +492,31 @@
main.ONOS3.check_status_report(main.params['RestIP'],main.params['NR_Switches'],str(int(main.params['NR_Links'])-2))
main.ONOS4.check_status_report(main.params['RestIP'],main.params['NR_Switches'],str(int(main.params['NR_Links'])-2))
break
+ ####New Topo Check
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
+ global MNTopo
+ MNTopo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+
+
+ topo_result = main.TRUE
+ for n in range(1,5):
+ temp_result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ topo_result = topo_result and temp_result
+ print "Topoology check results: " + str(topo_result)
+ ###End New Topo Check
utilities.assert_equals(expect=main.TRUE,actual=result1,onpass="Topology check pass",onfail="Topology check FAIL")
pingAttempts = main.params['pingAttempts']
@@ -452,6 +574,31 @@
main.ONOS3.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
main.ONOS4.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
break
+ ####New Topo Check
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
+ global MNTopo
+ MNTopo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+
+
+ topo_result = main.TRUE
+ for n in range(1,5):
+ temp_result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ topo_result = topo_result and temp_result
+ print "Topoology check results: " + str(topo_result)
+ ###End New Topo Check
utilities.assert_equals(expect=main.TRUE,actual=result1,onpass="Topology check pass",onfail="Topology check FAIL")
pingAttempts = main.params['pingAttempts']
@@ -509,6 +656,31 @@
main.ONOS3.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
main.ONOS4.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
break
+ ####New Topo Check
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
+ global MNTopo
+ MNTopo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+
+
+ topo_result = main.TRUE
+ for n in range(1,5):
+ temp_result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ topo_result = topo_result and temp_result
+ print "Topoology check results: " + str(topo_result)
+ ###End New Topo Check
utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Topology check pass",onfail="Topology check FAIL")
pingAttempts = main.params['pingAttempts']
@@ -573,6 +745,31 @@
main.ONOS3.check_status_report(main.params['RestIP'],main.params['NR_Switches'],str(int(main.params['NR_Links'])-2))
main.ONOS4.check_status_report(main.params['RestIP'],main.params['NR_Switches'],str(int(main.params['NR_Links'])-2))
break
+ ####New Topo Check
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
+ global MNTopo
+ MNTopo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+
+
+ topo_result = main.TRUE
+ for n in range(1,5):
+ temp_result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ topo_result = topo_result and temp_result
+ print "Topoology check results: " + str(topo_result)
+ ###End New Topo Check
utilities.assert_equals(expect=main.TRUE,actual=result1,onpass="Topology check pass",onfail="Topology check FAIL")
pingAttempts = main.params['pingAttempts']
@@ -632,6 +829,31 @@
main.ONOS3.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
main.ONOS4.check_status_report(main.params['RestIP'],main.params['NR_Switches'],main.params['NR_Links'])
break
+ ####New Topo Check
+ ctrls = []
+ count = 1
+ while True:
+ temp = ()
+ if ('ip' + str(count)) in main.params['CTRL']:
+ temp = temp + (getattr(main,('ONOS' + str(count))),)
+ temp = temp + ("ONOS"+str(count),)
+ temp = temp + (main.params['CTRL']['ip'+str(count)],)
+ temp = temp + (eval(main.params['CTRL']['port'+str(count)]),)
+ ctrls.append(temp)
+ count = count + 1
+ else:
+ break
+ from sts.topology.teston_topology import TestONTopology # assumes that sts is already in you PYTHONPATH
+ global MNTopo
+ MNTopo = TestONTopology(main.Mininet1, ctrls) # can also add Intent API info for intent operations
+
+
+ topo_result = main.TRUE
+ for n in range(1,5):
+ temp_result = main.Mininet1.compare_topo(MNTopo, main.ONOS1.get_json(main.params['CTRL']['ip'+str(n)]+":"+main.params['CTRL']['restPort'+str(n)]+main.params['TopoRest']))
+ topo_result = topo_result and temp_result
+ print "Topoology check results: " + str(topo_result)
+ ###End New Topo Check
utilities.assert_equals(expect=main.TRUE,actual=result1,onpass="Topology check pass",onfail="Topology check FAIL")
pingAttempts = main.params['pingAttempts']
@@ -753,7 +975,7 @@
url = main.params['RESTCALL']['restURL']
t_topowait = 5
- t_restwait = 0
+ t_restwait = 5
main.log.report( "Wait time from topo change to ping set to " + str(t_topowait))
main.log.report( "Wait time from ping to rest call set to " + str(t_restwait))
#print "host=" + host + "; RestIP=" + RestIP1 + "; RestPort=" + str(RestPort)
diff --git a/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.topo b/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.topo
index a9c85ed..d97e541 100644
--- a/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.topo
+++ b/TestON/tests/RCOnosCHO4nodes/RCOnosCHO4nodes.topo
@@ -130,7 +130,7 @@
<COMPONENTS>
# Specify the Option for mininet
<arg1> --custom ~/mininet/custom/topo-onos4node.py </arg1>
- <arg2> --topo mytopo </arg2>
+ <arg2> --topo mytopo --arp</arg2>
<controller> remote </controller>
</COMPONENTS>
</Mininet1>
diff --git a/TestON/tests/RCOnosSanity4nodesJ/RCOnosSanity4nodesJ.py b/TestON/tests/RCOnosSanity4nodesJ/RCOnosSanity4nodesJ.py
index d177f8b..10f142d 100644
--- a/TestON/tests/RCOnosSanity4nodesJ/RCOnosSanity4nodesJ.py
+++ b/TestON/tests/RCOnosSanity4nodesJ/RCOnosSanity4nodesJ.py
@@ -154,7 +154,6 @@
main.Mininet1.get_sw_controller("s1")
time.sleep(30)
- main.Zookeeper1.findMaster(switchDPID="00:00:00:00:00:00:10:00")
# **********************************************************************************************************************************************************************************************
#Add Flows
@@ -170,8 +169,7 @@
strtTime = time.time()
main.ONOS1.rm_intents()
print("world")
- main.ONOS1.add_intents()
- time.sleep(2)
+ time.sleep(5)
main.ONOS1.add_intents()
print("hello")
# main.ONOS1.add_flow(main.params['FLOWDEF']['testONip'],main.params['FLOWDEF']['user'],main.params['FLOWDEF']['password'],main.params['FLOWDEF']['flowDef'])
diff --git a/TestON/tests/RRCOnosSanity4nodesJ/RRCOnosSanity4nodesJ.topo b/TestON/tests/RRCOnosSanity4nodesJ/RRCOnosSanity4nodesJ.topo
index 988e8af..bf88550 100644
--- a/TestON/tests/RRCOnosSanity4nodesJ/RRCOnosSanity4nodesJ.topo
+++ b/TestON/tests/RRCOnosSanity4nodesJ/RRCOnosSanity4nodesJ.topo
@@ -129,8 +129,9 @@
<connect_order>13</connect_order>
<COMPONENTS>
# Specify the Option for mininet
- <arg1> --custom ~/mininet/custom/topo-onos4nodeNEW.py </arg1>
+ <arg1> --custom ~/mininet/custom/topo-onos4node.py </arg1>
<arg2> --topo mytopo --arp --mac</arg2>
+ <arg3> --switch ovs,protocols=OpenFlow10 </arg3>
<controller> remote </controller>
</COMPONENTS>
</Mininet1>
diff --git a/TestON/tests/scaleONOS7nodes/__init__.py b/TestON/tests/scaleONOS7nodes/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/scaleONOS7nodes/__init__.py
diff --git a/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.params b/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.params
new file mode 100644
index 0000000..dc9aed2
--- /dev/null
+++ b/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.params
@@ -0,0 +1,92 @@
+<PARAMS>
+ <testcases>1,31,33,4,41,43,5,51,53,6,61,63,7,71,73,103,105,8,61,63,9,51,53,10,41,43,11,31,33,104,106</testcases>
+ <tcpdump>
+ <intf>eth0</intf>
+ <port>port 6633</port>
+ <filename>~/packet_captures/Sanity.pcap</filename>
+ </tcpdump>
+ <CASE1>
+ <destination>h6</destination>
+ <target>h40</target>
+ </CASE1>
+ <PING>
+ <source1>h7</source1>
+ <target1>h32</target1>
+ <source2>h8</source2>
+ <target2>h33</target2>
+ </PING>
+ <LINK>
+ <begin>s1</begin>
+ <end>s2</end>
+ </LINK>
+ <YANK>
+ <hostname>h1</hostname>
+ <hostip>10.0.0.1</hostip>
+ <hostmac>00:00:00:00:00:01</hostmac>
+ <sw1>s1</sw1>
+ <sw6>s6</sw6>
+ <intf>s1-eth1</intf>
+ </YANK>
+ <PLUG>
+ <intf>s1-eth1</intf>
+ <sw6>s6</sw6>
+ <sw1>s1</sw1>
+ </PLUG>
+ <CTRL>
+ <ip1>10.128.10.1</ip1>
+ <port1>6633</port1>
+ <ip2>10.128.10.2</ip2>
+ <port2>6633</port2>
+ <ip3>10.128.10.3</ip3>
+ <port3>6633</port3>
+ <ip4>10.128.10.4</ip4>
+ <port4>6633</port4>
+ <ip5>10.128.10.5</ip5>
+ <port5>6633</port5>
+ <ip6>10.128.10.6</ip6>
+ <port6>6633</port6>
+ <ip7>10.128.10.7</ip7>
+ <port7>6633</port7>
+ </CTRL>
+ <INTENTREST>
+ <intentIP>10.128.10.1</intentIP>
+ <intentPort>8080</intentPort>
+ <intentURL>wm/onos/intent/high</intentURL>
+ </INTENTREST>
+ <RestIP>10.128.10.1</RestIP>
+ <RestIP2>10.128.10.2</RestIP2>
+ <RestIP3>10.128.10.3</RestIP3>
+ <RestIP4>10.128.10.4</RestIP4>
+ <RestIP5>10.128.10.5</RestIP5>
+ <RestIP6>10.128.10.6</RestIP6>
+ <RestIP7>10.128.10.7</RestIP7>
+ <NR_Switches>25</NR_Switches>
+ <NR_Links>50</NR_Links>
+ <RESTCALL>
+ <restIP1>10.128.10.1</restIP1>
+ <restIP2>10.128.10.2</restIP2>
+ <restPort>8080</restPort>
+ <restURL>/wm/onos/topology/hosts</restURL>
+ </RESTCALL>
+ <url1>http://10.128.10.1:8080/wm/onos/metrics</url1>
+ <url2>http://10.128.10.2:8080/wm/onos/metrics</url2>
+ <url3>http://10.128.10.3:8080/wm/onos/metrics</url3>
+ <url4>http://10.128.10.4:8080/wm/onos/metrics</url4>
+ <url5>http://10.128.10.5:8080/wm/onos/metrics</url5>
+ <url6>http://10.128.10.6:8080/wm/onos/metrics</url6>
+ <url7>http://10.128.10.7:8080/wm/onos/metrics</url7>
+ <switches_num>30</switches_num>
+ <RATE1>100</RATE1>
+ <RUN_DUR>600</RUN_DUR>
+ <sleep_t>6</sleep_t>
+ <loop>10</loop>
+ <port>10</port>
+ <sleep_init>540</sleep_init>
+ <int_num>40</int_num>
+ <addrate>1</addrate>
+ <NBdur>100</NBdur>
+ <NBsleep>5</NBsleep>
+ <NBloop>7</NBloop>
+ <NBsleep_init>60</NBsleep_init>
+ <db_script>/home/admin/TestON/scripts/./scaleoutdatagraph.py</db_script>
+</PARAMS>
diff --git a/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.py b/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.py
new file mode 100644
index 0000000..ba21e61
--- /dev/null
+++ b/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.py
@@ -0,0 +1,1346 @@
+#Author: Santhosh Jayashankar
+class scaleONOS7nodes :
+
+
+
+ def __init__(self) :
+ self.default = ''
+
+# def print_hello_world(self,main):
+# print("hello world")
+#*****************************************************************************************************************************************************************************************
+#Test startup
+#Tests the startup of Zookeeper1, RamCloud1, and ONOS1 to be certain that all started up successfully
+ def CASE1(self,main) : #Check to be sure ZK, Cass, and ONOS are up, then get ONOS version
+ main.case("Initial setup")
+ main.log.report("Starting 3-node ONOS cluster.")
+ main.step("Stop ONOS")
+ import time
+ main.log.info("Stopping all ONOS nodes...")
+ main.ONOS1.stop_all()
+ main.ONOS2.stop_all()
+ main.ONOS3.stop_all()
+# main.print_hello_world()
+ main.ONOS4.stop_all()
+ main.ONOS5.stop_all()
+ main.ONOS6.stop_all()
+ main.ONOS7.stop_all()
+ #main.ONOS2.stop_rest()
+ time.sleep(5)
+ #main.ONOS1.handle.sendline("cp ~/onos.properties.proactive ~/ONOS/conf/onos.properties")
+ #main.ONOS2.handle.sendline("cp ~/onos.properties.proactive ~/ONOS/conf/onos.properties")
+ #main.ONOS3.handle.sendline("cp ~/onos.properties.proactive ~/ONOS/conf/onos.properties")
+ #main.ONOS4.handle.sendline("cp ~/onos.properties.proactive ~/ONOS/conf/onos.properties")
+ #main.step("Start tcpdump on mn")
+ #main.Mininet2.start_tcpdump(main.params['tcpdump']['filename'], intf = main.params['tcpdump']['intf'], port = main.params['tcpdump']['port'])
+ main.step("Starting 3 ONOS nodes...")
+ main.Zookeeper1.start()
+ main.Zookeeper2.start()
+ main.Zookeeper3.start()
+ main.Zookeeper4.start()
+ main.Zookeeper5.start()
+ main.Zookeeper6.start()
+ main.Zookeeper7.start()
+
+ time.sleep(5)
+
+ """
+ main.RamCloud1.del_db()
+ main.RamCloud2.del_db()
+ main.RamCloud3.del_db()
+ # main.RamCloud4.del_db()
+
+ time.sleep(5)
+ #main.log.report("Pulling latest code from github to all nodes")
+
+
+ for i in range(2):
+ uptodate = main.ONOS1.git_pull()
+ main.ONOS2.git_pull()
+ main.ONOS3.git_pull()
+ # main.ONOS4.git_pull()
+ ver1 = main.ONOS1.get_version()
+ ver2 = main.ONOS3.get_version()
+ if ver1==ver2:
+ break
+ elif i==1:
+ main.ONOS2.git_pull("ONOS1 master")
+ main.ONOS3.git_pull("ONOS1 master")
+ # main.ONOS4.git_pull("ONOS1 master")
+ if uptodate==0:
+ # if 1:
+ main.ONOS1.git_compile()
+ main.ONOS2.git_compile()
+ main.ONOS3.git_compile()
+ # main.ONOS4.git_compile()
+ main.ONOS1.print_version()
+ # main.RamCloud1.git_pull()
+ # main.RamCloud2.git_pull()
+ # main.RamCloud3.git_pull()
+ # main.RamCloud4.git_pull()
+ # main.ONOS1.get_version()
+ # main.ONOS2.get_version()
+ # main.ONOS3.get_version()
+ # main.ONOS4.get_version()
+ # main.ONOS1.start_all()
+ # main.ONOS2.start_all()
+ # main.ONOS3.start_all()
+ # main.ONOS4.start_all()
+
+
+ main.RamCloud1.start_coor()
+ main.RamCloud1.start_serv()
+ main.RamCloud2.start_serv()
+ main.RamCloud3.start_serv()
+ time.sleep(5)
+ main.ONOS1.start()
+ main.ONOS2.start()
+ main.ONOS3.start()
+ #main.ONOS4.start()
+ time.sleep(5)
+ """
+ main.ONOS1.handle.sendline("./onos.sh core start")
+ main.ONOS2.handle.sendline("./onos.sh core start")
+ main.ONOS3.handle.sendline("./onos.sh core start")
+
+ main.ONOS1.start_rest()
+ main.ONOS2.start_rest()
+ main.ONOS3.start_rest()
+ test= main.ONOS2.rest_status()
+ if test == main.FALSE:
+ main.ONOS1.start_rest()
+ main.ONOS1.get_version()
+ main.log.report("Startup check Zookeeper, and ONOS connections")
+ main.step("Testing startup Zookeeper")
+ data = main.Zookeeper1.isup() and main.Zookeeper2.isup() and main.Zookeeper3.isup()
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Zookeeper is up!",onfail="Zookeeper is down...")
+ """
+ main.step("Testing startup RamCloud")
+ data = main.RamCloud1.status_serv() and main.RamCloud2.status_serv() and main.RamCloud3.status_serv() #and main.RamCloud4.status_serv()
+ if data == main.FALSE:
+ main.RamCloud1.stop_coor()
+ main.RamCloud1.stop_serv()
+ main.RamCloud2.stop_serv()
+ main.RamCloud3.stop_serv()
+ # main.RamCloud4.stop_serv()
+
+ time.sleep(5)
+ main.RamCloud1.start_coor()
+ main.RamCloud1.start_serv()
+ main.RamCloud2.start_serv()
+ main.RamCloud3.start_serv()
+ # main.RamCloud4.start_serv()
+ time.sleep(5)
+ data = main.RamCloud1.status_serv() and main.RamCloud2.status_serv() and main.RamCloud3.status_serv() #and main.RamCloud4.status_serv()
+
+
+
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="RamCloud is up!",onfail="RamCloud is down...")
+ """
+ main.step("Testing startup ONOS")
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() #and main.ONOS4.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ #main.log.report("Something is funny... restarting ONOS")
+ #main.ONOS1.stop()
+ time.sleep(3)
+ #main.ONOS1.start()
+ #time.sleep(5)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() #and main.ONOS4.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="ONOS is up and running!",onfail="ONOS didn't start...")
+ time.sleep(10)
+
+
+ def CASE31(self,main):
+ main.log.report("SB Throughput test: loading ONOS cluster with 740 Topo Events/s")
+ main.case("Staring SB load with 3 ONOS nodes")
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ rate1 = main.params['RATE1']
+ run_dur = main.params['RUN_DUR']
+ loop = int( main.params['loop'])
+ port = main.params['port']
+ switches_num = main.params['switches_num']
+ print loop
+ sleep_init = int(main.params['sleep_init'])
+ sleep_t =int( main.params['sleep_t'])
+ main.case("Starting SB load on 3 nodes from mininet with " + rate1 +" added/removed/s for " + run_dur)
+ main.Mininet2.handle.sendline("sudo ./loadgen_SB.py -u \"" + ip1 + " " + ip2 + " " + ip3 + "\"" + " -s " + switches_num + " -p " + port + " -a " + rate1 + " -d " + rate1 + " -l " + run_dur)
+ main.log.info("Adding switches and ports.....")
+ main.Mininet2.handle.expect("Starting SB load....", timeout=400)
+ main.log.info("Starting SB load....")
+ import time
+ import json
+ import math
+ time.sleep(sleep_init)
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale3nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale3nodesrate1", "a")
+ #time.sleep(10)
+ tpval = 0.0
+ global tpavg3n
+ tpavg3n = 0.0
+ for i in range(int (loop)):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ #float jval = 0
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "":
+ # write_str = str(json_str["meters"][4]["meter"][2])
+ #print str(json_str["meters"][4])
+ #f.write(str(json_str["meters"][4]))
+ #f.write('\n')
+ #time.sleep(3)
+ for j in range(1,4):
+ f.write("ONOS" + str(j) + "\n")
+ f.write(str(json_str[j]["meters"][4]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['mean_rate']))
+ f.write('\n')
+ if j == 3:
+ tpval += float(json_str[j]["meters"][4]['meter']['m1_rate'])
+ #print tpval
+ #print ("\n")
+
+
+ f.write('\n')
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ time.sleep(sleep_t)
+ f.close()
+ # print tpval
+ print("\n")
+ tpavg3n = round(tpval)/loop
+ print tpavg3n
+ main.log.report("Topology Event Throughput for 3-node ONOS cluster = " +str(tpavg3n) + " Events/sec")
+ main.Mininet2.handle.expect("\$", timeout=900)
+ time.sleep(180)
+
+ def CASE33(self,main):
+
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ import time
+ import json
+ int_num = int(main.params['int_num'])
+ addrate = main.params['addrate']
+ NBdur = main.params['NBdur']
+ NBsleep = int(main.params['NBsleep'])
+ NBsleep_init = int(main.params['NBsleep_init'])
+ NBloop = int(main.params['NBloop'])
+ int_r = 3 * int_num
+ main.log.report("Starting NB Throughput test: loading 3-node ONOS cluster with " + str(int_num) + " Intents/s on each node" )
+ main.Mininet4.handle.expect("\$")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s1 tcp:" + ip1 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s2 tcp:" + ip1 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s3 tcp:" + ip2 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s4 tcp:" + ip2 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s5 tcp:" + ip3 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s6 tcp:" + ip3 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s7 tcp:" + ip3 + ":6633")
+
+ main.ONOS3.handle.sendline("cd ~admin/suibin-dev")
+ main.ONOS3.handle.expect("\$")
+
+ main.ONOS3.handle.sendline("./loadgen_NB.py -n 3 -u \"" + ip1 + ":8080 " + ip2 + ":8080 " + ip3 + ":8080 \" -i " + str(int_r) + " -a " + addrate + " -l " + NBdur + " -p 20")
+ main.ONOS3.handle.expect("Pause between add and delete:", timeout=900)
+ time.sleep(NBsleep_init)
+ import json
+ nbtpval = 0.0
+ global nbtpavg3n
+ nbtpavg3n = 0.0
+
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale3nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale3nodesrate1", "a")
+ for i in range(NBloop):
+ j1 = main.ONOS1.get_json(url1)
+ j2 = main.ONOS1.get_json(url2)
+ j3 = main.ONOS1.get_json(url3)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "":
+ for j in range(1,4):
+ f.write("*****************ONOS" + str(j) + " INCOMING RATE****************************" "\n")
+ f.write(str(json_str[j]["meters"][0]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['mean_rate']))
+ f.write('\n')
+
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+
+ f.write("***************** ONOS" + str(j) + " PROCESSING RATE************************" + " \n ")
+ f.write(str(json_str[j]["meters"][1]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['mean_rate']))
+ f.write('\n')
+ f.write('\n')
+ f.write('\n')
+ nbtpval += float(json_str[j]["meters"][1]['meter']['m1_rate'])
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ f.write("--------------------------------------------------------------------------------- \n \n")
+ time.sleep(NBsleep)
+ f.close()
+ print("\n")
+ nbtpavg3n = round(round(nbtpval)/NBloop,2)
+ print nbtpavg3n
+
+ main.ONOS3.handle.expect("\$", timeout=900)
+ #time.sleep(180)
+ main.log.report("Intent Throughput for 3-node ONOS cluster = " + str(nbtpavg3n) + " Intents/sec")
+
+ def CASE4(self,main):
+
+ main.log.report("Scale-up ONOS to 4-nodes ")
+ main.case("Starting ONOS scale-up to 4 nodes ")
+ import time
+ # main.RamCloud4.start_serv()
+ main.ONOS5.handle.sendline("./onos.sh core stop")
+ main.ONOS6.handle.sendline("./onos.sh core stop")
+ main.ONOS7.handle.sendline("./onos.sh core stop")
+
+
+ main.Zookeeper4.start()
+ time.sleep(5)
+ """
+ main.RamCloud4.del_db()
+ time.sleep(3)
+ main.RamCloud4.start_serv()
+ time.sleep(3)
+ """
+ main.ONOS4.start()
+ main.ONOS4.start_rest()
+ time.sleep(5)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Scale up successful - 4-node ONOS cluster is up and running!",onfail="ONOS didn't start...")
+
+ time.sleep(10)
+
+ def CASE5(self,main):
+ main.log.report("Scale-up ONOS to 5-nodes")
+ main.case("Starting ONOS scale-up/down to 5 nodes ")
+ import time
+ main.ONOS6.handle.sendline("./onos.sh core stop")
+ main.ONOS7.handle.sendline("./onos.sh core stop")
+
+ main.Zookeeper5.start()
+ time.sleep(5)
+ """
+ main.RamCloud5.del_db()
+ time.sleep(3)
+ main.RamCloud5.start_serv()
+ time.sleep(3)
+ """
+ main.ONOS5.start()
+ main.ONOS5.start_rest()
+ time.sleep(5)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Scale up successful - 5-node ONOS cluster is up and running!",onfail="ONOS didn't start...")
+ time.sleep(10)
+
+ def CASE6(self,main):
+ main.log.report("Scale-up ONOS to 6-nodes")
+ main.case("Starting ONOS scale-up/down to 6 nodes ")
+ import time
+ main.ONOS7.handle.sendline("./onos.sh core stop")
+
+ main.Zookeeper6.start()
+ time.sleep(5)
+ """
+ main.RamCloud6.del_db()
+ time.sleep(3)
+ main.RamCloud6.start_serv()
+ time.sleep(3)
+ """
+ main.ONOS6.start()
+ main.ONOS6.start_rest()
+ time.sleep(5)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup() and main.ONOS6.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup() and main.ONOS6.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Scale up successful - 6-node ONOS cluster is up and running!",onfail="ONOS didn't start...")
+ time.sleep(10)
+
+ def CASE7(self,main):
+ main.log.report("Scale-up ONOS to 7-nodes")
+ main.case("Starting ONOS scale-up/down to 7 nodes ")
+ import time
+
+ main.Zookeeper7.start()
+ time.sleep(5)
+ """
+ main.RamCloud7.del_db()
+ time.sleep(3)
+ main.RamCloud7.start_serv()
+ time.sleep(3)
+ """
+ main.ONOS7.start()
+ main.ONOS7.start_rest()
+ time.sleep(5)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup() and main.ONOS6.isup() and main.ONOS7.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup() and main.ONOS6.isup() and main.ONOS7.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Scale up successful - 7-node ONOS cluster is up and running!",onfail="ONOS didn't start...")
+ time.sleep(10)
+
+
+
+ def CASE41(self,main):
+ main.case("Starting SB test for 4 nodes")
+ main.log.report("SB Throughput test: loading 4-node ONOS cluster with 740 Topo Events/s")
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ ip4 = main.params['CTRL']['ip4']
+ rate1 = main.params['RATE1']
+ run_dur = main.params['RUN_DUR']
+ loop = int( main.params['loop'])
+ switches_num = main.params['switches_num']
+ port = main.params['port']
+ print loop
+ sleep_init = int(main.params['sleep_init'])
+ sleep_t =int( main.params['sleep_t'])
+ main.case("Starting SB load on 4 nodes from mininet with " + rate1 +" added/removed/s for " + run_dur)
+ main.Mininet2.handle.sendline("sudo ./loadgen_SB.py -u \"" + ip1 + " " + ip2 + " " + ip3 + " " + ip4 + "\"" + " -s " + switches_num + " -p " + port + " -a " + rate1 + " -d " + rate1 + " -l " + run_dur)
+ main.Mininet2.handle.expect("Starting SB load....", timeout=900)
+ import time
+ import json
+ import math
+ time.sleep(sleep_init)
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale4nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ url4 = main.params['url4']
+ tpval = 0.0
+ global tpavg4n
+ tpavg4n = 0.0
+
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale4nodesrate1", "a")
+ for i in range(int (loop)):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ j4 = main.ONOS2.get_json(url4)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ json_str.append(j4)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "" and json_str[4] != "":
+ for j in range(1,5):
+ f.write("ONOS" + str(j) + "\n")
+ f.write(str(json_str[j]["meters"][4]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['mean_rate']))
+ f.write('\n')
+ if j == 4:
+ tpval += float(json_str[j]["meters"][4]['meter']['m1_rate'])
+
+ f.write('\n')
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ time.sleep(sleep_t)
+ f.close()
+ print("\n")
+ tpavg4n = round(tpval)/loop
+ print tpavg4n
+ main.log.report("Topology Event Throughput for 4-node ONOS cluster = " + str(tpavg4n) + " Events/sec")
+
+ time.sleep(5)
+ main.Mininet2.handle.expect("\$", timeout=900)
+ time.sleep(180)
+
+
+ def CASE43(self,main):
+
+ main.case("Starting NB Throughput test after scaling up to 4 onos nodes")
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ ip4 = main.params['CTRL']['ip4']
+
+ import time
+ import json
+ int_num = int(main.params['int_num'])
+ addrate = main.params['addrate']
+ NBdur = main.params['NBdur']
+ NBsleep = int(main.params['NBsleep'])
+ NBsleep_init = int(main.params['NBsleep_init'])
+ NBloop = int(main.params['NBloop'])
+ nbtpval = 0.0
+ main.log.report("Starting NB Throughput test: loading 4-node ONOS cluster with " +str(int_num) + " Intents/s on each node" )
+ global nbtpavg4n
+ nbtpavg4n = 0.0
+ int_r = 4 * int_num
+ main.Mininet4.handle.expect("\$")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s1 tcp:" + ip1 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s2 tcp:" + ip2 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s3 tcp:" + ip3 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s4 tcp:" + ip4 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s5 tcp:" + ip1 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s6 tcp:" + ip2 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s7 tcp:" + ip4 + ":6633")
+
+ main.ONOS3.handle.sendline("cd ~admin/suibin-dev")
+ main.ONOS3.handle.expect("\$")
+
+ main.ONOS3.handle.sendline("./loadgen_NB.py -n 4 -u \"" + ip1 + ":8080 " + ip2 + ":8080 " + ip3 + ":8080 " + ip4 + ":8080 \" -i " + str(int_r) + " -a " + addrate + " -l " + NBdur + " -p 20")
+ main.ONOS3.handle.expect("Pause between add and delete:", timeout=900)
+
+
+ time.sleep(NBsleep_init)
+ import json
+
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale4nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ url4 = main.params['url4']
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale4nodesrate1", "a")
+ for i in range(NBloop):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ j4 = main.ONOS2.get_json(url4)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ json_str.append(j4)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "" and json_str[4] != "":
+ for j in range(1,5):
+ f.write("*****************ONOS" + str(j) + " INCOMING RATE****************************" "\n")
+ f.write(str(json_str[j]["meters"][0]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['mean_rate']))
+ f.write('\n')
+
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+
+ f.write("***************** ONOS" + str(j) + " PROCESSING RATE************************" + " \n ")
+ f.write(str(json_str[j]["meters"][1]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['mean_rate']))
+ f.write('\n')
+ f.write('\n')
+ f.write('\n')
+
+ nbtpval += float(json_str[j]["meters"][1]['meter']['m1_rate'])
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ f.write("--------------------------------------------------------------------------------- \n \n")
+ time.sleep(NBsleep)
+ f.close()
+ print("\n")
+ nbtpavg4n = round(round(nbtpval)/NBloop,2)
+ print nbtpavg4n
+
+
+ main.ONOS3.handle.expect("\$", timeout=900)
+ time.sleep(180)
+ main.log.report("Intent Throughput for 4-node ONOS cluster = " + str(nbtpavg4n) + " Intents/sec")
+
+ def CASE51(self,main):
+ main.case("Starting SB test for 5 nodes")
+ main.log.report("SB Throughput test: loading 5-node ONOS cluster with 740 Topo Events/s")
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ ip4 = main.params['CTRL']['ip4']
+ ip5 = main.params['CTRL']['ip5']
+ rate1 = main.params['RATE1']
+ run_dur = main.params['RUN_DUR']
+ loop = int( main.params['loop'])
+ switches_num = main.params['switches_num']
+ port = main.params['port']
+ print loop
+ sleep_init = int(main.params['sleep_init'])
+ sleep_t =int( main.params['sleep_t'])
+ main.case("Starting SB load on 5 nodes from mininet with " + rate1 +" added/removed/s for " + run_dur)
+ main.Mininet2.handle.sendline("sudo ./loadgen_SB.py -u \"" + ip1 + " " + ip2 + " " + ip3 + " " + ip4 + " " + ip5 + "\"" + " -s " + switches_num + " -p " + port + " -a " + rate1 + " -d " + rate1 + " -l " + run_dur)
+ main.Mininet2.handle.expect("Starting SB load....", timeout=900)
+ import time
+ import json
+ tpval = 0.0
+ global tpavg5n
+ tpavg5n = 0.0
+ time.sleep(sleep_init)
+
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale5nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ url4 = main.params['url4']
+ url5 = main.params['url5']
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale5nodesrate1", "a")
+ for i in range(int (loop)):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ j4 = main.ONOS2.get_json(url4)
+ j5 = main.ONOS2.get_json(url5)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ json_str.append(j4)
+ json_str.append(j5)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "" and json_str[4] != "" and json_str[5] != "":
+ for j in range(1,6):
+ f.write("ONOS" + str(j) + "\n")
+ f.write(str(json_str[j]["meters"][4]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['mean_rate']))
+ f.write('\n')
+ if j == 4:
+ tpval += float(json_str[j]["meters"][4]['meter']['m1_rate'])
+
+ f.write('\n')
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ time.sleep(sleep_t)
+ f.close()
+ print("\n")
+ tpavg5n = round(tpval)/loop
+ print tpavg5n
+
+ time.sleep(5)
+ main.Mininet2.handle.expect("\$", timeout=900)
+ time.sleep(180)
+ main.log.report("Topology Event Throughput for 5-node ONOS cluster = " + str(tpavg5n) + " Events/sec")
+
+
+ def CASE53(self,main):
+
+ main.case("Starting NB Throughput test after scaling up to 5 onos nodes")
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ ip4 = main.params['CTRL']['ip4']
+ ip5 = main.params['CTRL']['ip5']
+
+ import time
+ import json
+ int_num = int(main.params['int_num'])
+ addrate = main.params['addrate']
+ NBdur = main.params['NBdur']
+ NBsleep = int(main.params['NBsleep'])
+ NBsleep_init = int(main.params['NBsleep_init'])
+ NBloop = int(main.params['NBloop'])
+ nbtpval = 0.0
+ main.log.report("Starting NB Throughput test: loading 5-node ONOS cluster with " + str(int_num) + " Intents/s on each node" )
+ global nbtpavg5n
+ nbtpavg5n = 0.0
+ int_r = 5 * int_num
+ main.Mininet4.handle.expect("\$")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s1 tcp:" + ip1 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s2 tcp:" + ip2 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s3 tcp:" + ip3 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s4 tcp:" + ip4 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s5 tcp:" + ip5 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s6 tcp:" + ip3 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s7 tcp:" + ip5 + ":6633")
+
+ main.ONOS3.handle.sendline("cd ~admin/suibin-dev")
+ main.ONOS3.handle.expect("\$")
+
+ main.ONOS3.handle.sendline("./loadgen_NB.py -n 5 -u \"" + ip1 + ":8080 " + ip2 + ":8080 " + ip3 + ":8080 " + ip4 + ":8080 " + ip5 + ":8080 \" -i " + str(int_r) + " -a " + addrate + " -l " + NBdur + " -p 20")
+ main.ONOS3.handle.expect("Pause between add and delete:", timeout=900)
+
+
+ time.sleep(NBsleep_init)
+ import json
+
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale5nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ url4 = main.params['url4']
+ url5 = main.params['url5']
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale5nodesrate1", "a")
+ for i in range(NBloop):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ j4 = main.ONOS2.get_json(url4)
+ j5 = main.ONOS2.get_json(url5)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ json_str.append(j4)
+ json_str.append(j5)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "" and json_str[4] != "" and json_str[5] != "":
+ for j in range(1,6):
+ f.write("*****************ONOS" + str(j) + " INCOMING RATE****************************" "\n")
+ f.write(str(json_str[j]["meters"][0]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['mean_rate']))
+ f.write('\n')
+
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+
+ f.write("***************** ONOS" + str(j) + " PROCESSING RATE************************" + " \n ")
+ f.write(str(json_str[j]["meters"][1]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['mean_rate']))
+ f.write('\n')
+ f.write('\n')
+ f.write('\n')
+
+ nbtpval += float(json_str[j]["meters"][1]['meter']['m1_rate'])
+
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ f.write("--------------------------------------------------------------------------------- \n \n")
+ time.sleep(NBsleep)
+ f.close()
+ print("\n")
+ nbtpavg5n = round(round(nbtpval)/NBloop,2)
+ print nbtpavg5n
+
+
+ main.ONOS3.handle.expect("\$", timeout=900)
+ time.sleep(180)
+ main.log.report("Intent Throughput for 5-node ONOS cluster = " + str(nbtpavg5n) + " Intents/sec")
+
+ def CASE61(self,main):
+ main.case("Starting SB test for 5 nodes")
+ ip1 = main.params['CTRL']['ip1']
+ main.log.report("SB Throughput test: loading 6-node ONOS cluster with 740 Topo Events/s")
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ ip4 = main.params['CTRL']['ip4']
+ ip5 = main.params['CTRL']['ip5']
+ ip6 = main.params['CTRL']['ip6']
+ rate1 = main.params['RATE1']
+ run_dur = main.params['RUN_DUR']
+ loop = int( main.params['loop'])
+ switches_num = main.params['switches_num']
+ port = main.params['port']
+ print loop
+ sleep_t =int( main.params['sleep_t'])
+ sleep_init = int(main.params['sleep_init'])
+ main.case("Starting SB load on 6 nodes from mininet with " + rate1 +" added/removed/s for " + run_dur)
+ main.Mininet2.handle.sendline("sudo ./loadgen_SB.py -u \"" + ip1 + " " + ip2 + " " + ip3 + " " + ip4 + " " + ip5 + " " + ip6 + "\"" + " -s " + switches_num + " -p " + port + " -a " + rate1 + " -d " + rate1 + " -l " + run_dur)
+ main.Mininet2.handle.expect("Starting SB load....", timeout=900)
+
+ import time
+ import json
+ tpval = 0.0
+ global tpavg6n
+ tpavg6n = 0.0
+ time.sleep(sleep_init)
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale6nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ url4 = main.params['url4']
+ url5 = main.params['url5']
+ url6 = main.params['url6']
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale6nodesrate1", "a")
+ for i in range(int (loop)):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ j4 = main.ONOS2.get_json(url4)
+ j5 = main.ONOS2.get_json(url5)
+ j6 = main.ONOS2.get_json(url6)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ json_str.append(j4)
+ json_str.append(j5)
+ json_str.append(j6)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "" and json_str[4] != "" and json_str[5] != "" and json_str[6] != "":
+ for j in range(1,7):
+ f.write("ONOS" + str(j) + "\n")
+ f.write(str(json_str[j]["meters"][4]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['mean_rate']))
+ f.write('\n')
+ if j == 4:
+ tpval += float(json_str[j]["meters"][4]['meter']['m1_rate'])
+
+ f.write('\n')
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ time.sleep(sleep_t)
+ f.close()
+ print("\n")
+ tpavg6n = round(tpval)/loop
+ print tpavg6n
+
+ time.sleep(5)
+ main.Mininet2.handle.expect("\$", timeout=900)
+ time.sleep(180)
+ main.log.report("Topology Event Throughput for 6-node ONOS cluster = " + str(tpavg6n) + " Events/sec")
+
+
+ def CASE63(self,main):
+
+ main.case("Starting NB Throughput test after scaling up to 4 onos nodes")
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ ip4 = main.params['CTRL']['ip4']
+ ip5 = main.params['CTRL']['ip5']
+ ip6 = main.params['CTRL']['ip6']
+
+ import time
+ import json
+ int_num = int(main.params['int_num'])
+ addrate = main.params['addrate']
+ NBdur = main.params['NBdur']
+ NBsleep = int(main.params['NBsleep'])
+ NBsleep_init = int(main.params['NBsleep_init'])
+ NBloop = int(main.params['NBloop'])
+ nbtpval = 0.0
+ main.log.report("Starting NB Throughput test: loading 6-node ONOS cluster with " + str(int_num) + " Intents/s" )
+ global nbtpavg6n
+ nbtpavg6n = 0.0
+ int_r = 6 * int_num
+ main.Mininet4.handle.expect("\$")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s1 tcp:" + ip1 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s2 tcp:" + ip2 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s3 tcp:" + ip3 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s4 tcp:" + ip4 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s5 tcp:" + ip5 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s6 tcp:" + ip6 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s7 tcp:" + ip6 + ":6633")
+
+ main.ONOS3.handle.sendline("cd ~admin/suibin-dev")
+ main.ONOS3.handle.expect("\$")
+
+ main.ONOS3.handle.sendline("./loadgen_NB.py -n 6 -u \"" + ip1 + ":8080 " + ip2 + ":8080 " + ip3 + ":8080 " + ip4 + ":8080 " + ip5 + ":8080 " + ip6 + ":8080 \" -i " + str(int_r) + " -a " + addrate + " -l " + NBdur + " -p 20")
+ main.ONOS3.handle.expect("Pause between add and delete:", timeout=900)
+
+
+ time.sleep(NBsleep_init)
+ import json
+
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale6nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ url4 = main.params['url4']
+ url5 = main.params['url5']
+ url6 = main.params['url6']
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale6nodesrate1", "a")
+ for i in range(NBloop):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ j4 = main.ONOS2.get_json(url4)
+ j5 = main.ONOS2.get_json(url5)
+ j6 = main.ONOS2.get_json(url6)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ json_str.append(j4)
+ json_str.append(j5)
+ json_str.append(j6)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "" and json_str[4] != "" and json_str[5] != "" and json_str[6] != "":
+ for j in range(1,7):
+ f.write("*****************ONOS" + str(j) + " INCOMING RATE****************************" "\n")
+ f.write(str(json_str[j]["meters"][0]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['mean_rate']))
+ f.write('\n')
+
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+
+ f.write("***************** ONOS" + str(j) + " PROCESSING RATE************************" + " \n ")
+ f.write(str(json_str[j]["meters"][1]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['mean_rate']))
+ f.write('\n')
+ f.write('\n')
+ f.write('\n')
+
+ nbtpval += float(json_str[j]["meters"][1]['meter']['m1_rate'])
+
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ f.write("--------------------------------------------------------------------------------- \n \n")
+ time.sleep(NBsleep)
+ f.close()
+ print("\n")
+ nbtpavg6n = round(round(nbtpval)/NBloop,2)
+ print nbtpavg6n
+
+
+
+ main.ONOS3.handle.expect("\$", timeout=900)
+ time.sleep(180)
+ main.log.report("Intent Throughput for 6-node ONOS cluster = " + str(nbtpavg6n) + " Intents/sec")
+
+ def CASE71(self,main):
+ main.case("Starting SB test for 7 nodes")
+ main.log.report("SB Throughput test: loading 7-node ONOS cluster with 740 Topo Events/s")
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ ip4 = main.params['CTRL']['ip4']
+ ip5 = main.params['CTRL']['ip5']
+ ip6 = main.params['CTRL']['ip6']
+ ip7 = main.params['CTRL']['ip7']
+ rate1 = main.params['RATE1']
+ run_dur = main.params['RUN_DUR']
+ loop = int( main.params['loop'])
+ switches_num = main.params['switches_num']
+ port = main.params['port']
+ print loop
+ sleep_t =int( main.params['sleep_t'])
+ sleep_init = int(main.params['sleep_init'])
+ main.case("Starting SB load on 6 nodes from mininet with " + rate1 +" added/removed/s for " + run_dur)
+ main.Mininet2.handle.sendline("sudo ./loadgen_SB.py -u \"" + ip1 + " " + ip2 + " " + ip3 + " " + ip4 + " " + ip5 + " " + ip6 + " " + ip7 + "\"" + " -s " + switches_num + " -p " + port + " -a " + rate1 + " -d " + rate1 + " -l " + run_dur)
+ main.Mininet2.handle.expect("Starting SB load....", timeout=900)
+ import time
+ import json
+ tpval = 0.0
+ global tpavg7n
+ tpavg7n = 0.0
+ time.sleep(sleep_init)
+
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale7nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ url4 = main.params['url4']
+ url5 = main.params['url5']
+ url6 = main.params['url6']
+ url7 = main.params['url7']
+
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/scale7nodesrate1", "a")
+ for i in range(int (loop)):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ j4 = main.ONOS2.get_json(url4)
+ j5 = main.ONOS2.get_json(url5)
+ j6 = main.ONOS2.get_json(url6)
+ j7 = main.ONOS2.get_json(url7)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ json_str.append(j4)
+ json_str.append(j5)
+ json_str.append(j6)
+ json_str.append(j7)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "" and json_str[4] != "" and json_str[5] != "" and json_str[6] != "" and json_str[7] != "":
+ for j in range(1,8):
+ f.write("ONOS" + str(j) + "\n")
+ f.write(str(json_str[j]["meters"][4]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][4]['meter']['mean_rate']))
+ f.write('\n')
+ if j == 4:
+ tpval += float(json_str[j]["meters"][4]['meter']['m1_rate'])
+
+ f.write('\n')
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ time.sleep(sleep_t)
+ f.close()
+ print("\n")
+ tpavg7n = round(tpval)/loop
+ print tpavg7n
+
+ time.sleep(5)
+ main.Mininet2.handle.expect("\$", timeout=900)
+ time.sleep(180)
+ main.log.report("Topology Event Throughput for 7-node ONOS cluster = " + str(tpavg7n) + " Events/sec")
+
+
+ def CASE73(self,main):
+
+ main.case("Starting NB Throughput test after scaling up to 7 onos nodes")
+ ip1 = main.params['CTRL']['ip1']
+ ip2 = main.params['CTRL']['ip2']
+ ip3 = main.params['CTRL']['ip3']
+ ip4 = main.params['CTRL']['ip4']
+ ip5 = main.params['CTRL']['ip5']
+ ip6 = main.params['CTRL']['ip6']
+ ip7 = main.params['CTRL']['ip7']
+
+ import time
+ import json
+ int_num = int(main.params['int_num'])
+ addrate = main.params['addrate']
+ NBdur = main.params['NBdur']
+ NBsleep = int(main.params['NBsleep'])
+ NBsleep_init = int(main.params['NBsleep_init'])
+ NBloop = int(main.params['NBloop'])
+ main.log.report("Starting NB Throughput test: loading 7-node ONOS cluster with " + str(int_num) + " Intents/s" )
+ nbtpval = 0.0
+ global nbtpavg7n
+ nbtpavg7n = 0.0
+ int_r = 7 * int_num
+ main.Mininet4.handle.expect("\$")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s1 tcp:" + ip1 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s2 tcp:" + ip2 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s3 tcp:" + ip3 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s4 tcp:" + ip4 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s5 tcp:" + ip5 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s6 tcp:" + ip6 + ":6633")
+ main.Mininet4.handle.sendline("sudo ovs-vsctl set-controller s7 tcp:" + ip7 + ":6633")
+
+ main.ONOS3.handle.sendline("cd ~admin/suibin-dev")
+ main.ONOS3.handle.expect("\$")
+
+ main.ONOS3.handle.sendline("./loadgen_NB.py -n 7 -u \"" + ip1 + ":8080 " + ip2 + ":8080 " + ip3 + ":8080 " + ip4 + ":8080 " + ip6 + ":8080 " + ip5 + ":8080 " + ip7 + ":8080 \" -i " + str(int_r) + " -a " + addrate + " -l " + NBdur + " -p 20")
+ main.ONOS3.handle.expect("Pause between add and delete:", timeout=900)
+
+
+ time.sleep(NBsleep_init)
+ import json
+
+ open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale7nodesrate1", 'w').close()
+ url1 = main.params['url1']
+ url2 = main.params['url2']
+ url3 = main.params['url3']
+ url4 = main.params['url4']
+ url5 = main.params['url5']
+ url6 = main.params['url6']
+ url7 = main.params['url7']
+ f = open("/home/admin/TestON/tests/scaleONOS7nodes/logs/NBscale7nodesrate1", "a")
+ for i in range(NBloop):
+ j1 = main.ONOS2.get_json(url1)
+ j2 = main.ONOS2.get_json(url2)
+ j3 = main.ONOS2.get_json(url3)
+ j4 = main.ONOS2.get_json(url4)
+ j5 = main.ONOS2.get_json(url5)
+ j6 = main.ONOS2.get_json(url6)
+ j7 = main.ONOS2.get_json(url7)
+ json_str = []
+ json_str.append(0)
+ json_str.append(j1)
+ json_str.append(j2)
+ json_str.append(j3)
+ json_str.append(j4)
+ json_str.append(j5)
+ json_str.append(j6)
+ json_str.append(j7)
+ if json_str[1] != "" and json_str[2] != "" and json_str[3] != "" and json_str[4] != "" and json_str[5] != "" and json_str[6] != "" and json_str[6] != "":
+ for j in range(1,8):
+ f.write("*****************ONOS" + str(j) + " INCOMING RATE****************************" "\n")
+ f.write(str(json_str[j]["meters"][0]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][0]['meter']['mean_rate']))
+ f.write('\n')
+
+ f.write('\n')
+
+ f.write("--------------------------------------------------------------------------------- \n")
+
+ f.write("***************** ONOS" + str(j) + " PROCESSING RATE************************" + " \n ")
+ f.write(str(json_str[j]["meters"][1]['meter']['count']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m1_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m5_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['m15_rate']))
+ f.write('\t')
+ f.write(str(json_str[j]["meters"][1]['meter']['mean_rate']))
+ f.write('\n')
+ f.write('\n')
+ f.write('\n')
+
+ nbtpval += float(json_str[j]["meters"][1]['meter']['m1_rate'])
+
+
+ f.write("--------------------------------------------------------------------------------- \n")
+ f.write("--------------------------------------------------------------------------------- \n \n")
+ time.sleep(NBsleep)
+ f.close()
+ print("\n")
+ nbtpavg7n = round(round(nbtpval)/NBloop,2)
+ print nbtpavg7n
+
+
+ main.ONOS3.handle.expect("\$", timeout=900)
+ time.sleep(180)
+ main.log.report("Intent Throughput for 7-node ONOS cluster = " + str(nbtpavg7n) + " Intents/sec")
+
+ def CASE8(self,main):
+ import time
+ main.log.report("Scaling ONOS down to 6 ONOS instances")
+ main.ONOS7.handle.sendline("./onos.sh core stop")
+ time.sleep(8)
+ pdata = main.ONOS7.isup()
+ utilities.assert_equals(expect=main.FALSE,actual=pdata,onpass="ONOS7 stopped... ",onfail="ONOS scale down failed...")
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup() and main.ONOS6.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup() and main.ONOS6.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Scale down successfull -6-node ONOS cluster is up and running!",onfail="ONOS didn't start...")
+
+ def CASE9(self,main):
+
+ main.log.report("Scaling ONOS down to 5 ONOS instances")
+ main.ONOS6.handle.sendline("./onos.sh core stop")
+ time.sleep(8)
+ pdata = main.ONOS6.isup() and main.ONOS7.isup()
+ utilities.assert_equals(expect=main.FALSE,actual=pdata,onpass="ONOS7 stopped... ",onfail="ONOS scale down failed...")
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup() and main.ONOS5.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Scale down successfull - 5 node ONOS clsuter is up and running!",onfail="ONOS didn't start...")
+
+ def CASE10(self,main):
+
+ main.log.report("Scaling ONOS down to 4 ONOS instances")
+
+ main.ONOS5.handle.sendline("./onos.sh core stop ")
+ time.sleep(5)
+ pdata = main.ONOS5.isup() and main.ONOS6.isup() and main.ONOS7.isup()
+ utilities.assert_equals(expect=main.FALSE,actual=pdata,onpass="ONOS7 stopped... ",onfail="ONOS scale down failed...")
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup() and main.ONOS4.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Scale down successful - 4 node ONOS cluster is up and running!",onfail="ONOS didn't start...")
+
+ def CASE11(self,main):
+
+ main.log.report("Scaling ONOS down to 3 ONOS instances")
+ main.ONOS4.handle.sendline("./onos.sh core stop ")
+ time.sleep(5)
+ pdata = main.ONOS4.isup() and main.ONOS5.isup() and main.ONOS6.isup() and main.ONOS7.isup()
+ utilities.assert_equals(expect=main.FALSE,actual=pdata,onpass="ONOS7 stopped... ",onfail="ONOS scale down failed...")
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup()
+ for i in range(3):
+ if data == main.FALSE:
+ time.sleep(3)
+ data = main.ONOS1.isup() and main.ONOS2.isup() and main.ONOS3.isup()
+ else:
+ break
+ utilities.assert_equals(expect=main.TRUE,actual=data,onpass="Scale down successful - 3 node ONOS cluster is up and running!",onfail="ONOS didn't start...")
+
+ def CASE100(self,main):
+ import os
+ import time
+ global timestr
+ timestr = time.strftime("%Y%m%d-%H%M%S")
+ main.case("Scale-up tests complete...now making final changes")
+ main.log.info("moving logs....")
+ os.system("sudo mkdir ~admin/TestON/tests/scaleONOS7nodes/logs/ONOSscale_up" + timestr + "")
+ os.system("sudo mkdir ~admin/TestON/tests/scaleONOS7nodes/logs/NBONOSscale_up" + timestr + "")
+ time.sleep(2)
+ os.system("sudo cp ~admin/TestON/tests/scaleONOS7nodes/logs/scale* ~admin/TestON/tests/scaleONOS7nodes/logs/ONOSscale_up" + timestr + "")
+ os.system("sudo cp ~admin/TestON/tests/scaleONOS7nodes/logs/NBscale* ~admin/TestON/tests/scaleONOS7nodes/logs/NBONOSscale_up" + timestr + "")
+ time.sleep(2)
+ os.system("sudo rm ~admin/TestON/tests/scaleONOS7nodes/logs/*")
+ time.sleep(180)
+
+ def CASE101(self,main):
+
+ import os
+ import time
+ main.case("Scale-down tests complete...now making final changes")
+ global timestr
+ main.case("Scale-down tests complete...now making final changes")
+ main.log.info("moving logs....")
+ os.system("sudo mkdir ~admin/TestON/tests/scaleONOS7nodes/logs/ONOSscale_dwn" + timestr + "")
+ os.system("sudo mkdir ~admin/TestON/tests/scaleONOS7nodes/logs/NBONOSscale_dwn" + timestr + "")
+ time.sleep(2)
+ os.system("sudo cp ~admin/TestON/tests/scaleONOS7nodes/logs/scale* ~admin/TestON/tests/scaleONOS7nodes/logs/ONOSscale_dwn" + timestr + "")
+ os.system("sudo cp ~admin/TestON/tests/scaleONOS7nodes/logs/NBscale* ~admin/TestON/tests/scaleONOS7nodes/logs/NBONOSscale_dwn" + timestr + "")
+ time.sleep(2)
+ os.system("sudo rm ~admin/TestON/tests/scaleONOS7nodes/logs/*")
+ time.sleep(2)
+
+ def CASE103(self,main):
+ import os
+ import time
+ main.log.report("Posting the results to http://10.128.5.54/scale.html")
+ db_script = main.params['db_script']
+ os.system(db_script + " -n='100SwitchScaleUp" + "' -rate3='" + str(tpavg3n) + "' -rate4='" + str(tpavg4n) + "' -rate5='" + str(tpavg5n) + "' -rate6='" + str(tpavg6n) + "' -rate7='" + str(tpavg7n) + "' -table='onos_scale'")
+ main.log.report("The graphical view of the tests can be viewed at http://10.128.5.54/scale.html")
+
+ def CASE104(self,main):
+ import os
+ import time
+ main.log.report("Posting the results to http://10.128.5.54/scale.html ....")
+ db_script = main.params['db_script']
+ os.system(db_script + " -n='100SwitchScaleDown" + "' -rate3='" + str(tpavg3n) + "' -rate4='" + str(tpavg4n) + "' -rate5='" + str(tpavg5n) + "' -rate6='" + str(tpavg6n) + "' -rate7='" + str(tpavg7n) + "' -table='onos_scale'")
+
+ main.log.report("The graphical view of the tests can be viewed at http://10.128.5.54/scale.html")
+
+ def CASE105(self,main):
+ import os
+ import time
+ main.log.report("Posting the results to http://10.128.5.54/scale.html ....")
+ db_script = main.params['db_script']
+ os.system(db_script + " -n='1000IntentsScaleUp" + "' -rate3='" + str(nbtpavg3n) + "' -rate4='" + str(nbtpavg4n) + "' -rate5='" + str(nbtpavg5n) + "' -rate6='" + str(nbtpavg6n) + "' -rate7='" + str(nbtpavg7n) + "' -table='onos_scale'")
+
+ main.log.report("The graphical view of the tests can be viewed at http://10.128.5.54/scale.html")
+
+ def CASE106(self,main):
+ import os
+ import time
+ main.log.report("Posting the results to http://10.128.5.54/scale.html ....")
+ db_script = main.params['db_script']
+ os.system(db_script + " -n='1000IntentsScaleDown" + "' -rate3='" + str(nbtpavg3n) + "' -rate4='" + str(nbtpavg4n) + "' -rate5='" + str(nbtpavg5n) + "' -rate6='" + str(nbtpavg6n) + "' -rate7='" + str(nbtpavg7n) + "' -table='onos_scale'")
+
+ main.log.report("The graphical view of the tests can be viewed at http://10.128.5.54/scale.html")
+
+
diff --git a/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.topo b/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.topo
new file mode 100644
index 0000000..5a4f78c
--- /dev/null
+++ b/TestON/tests/scaleONOS7nodes/scaleONOS7nodes.topo
@@ -0,0 +1,258 @@
+<TOPOLOGY>
+
+ <COMPONENT>
+ <Zookeeper1>
+ <host>10.128.10.1</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </Zookeeper1>
+
+ <Zookeeper2>
+ <host>10.128.10.2</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </Zookeeper2>
+
+ <Zookeeper3>
+ <host>10.128.10.3</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </Zookeeper3>
+
+ <Zookeeper4>
+ <host>10.128.10.4</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </Zookeeper4>
+
+ <Zookeeper5>
+ <host>10.128.10.5</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </Zookeeper5>
+
+ <Zookeeper6>
+ <host>10.128.10.6</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>6</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </Zookeeper6>
+
+ <Zookeeper7>
+ <host>10.128.10.7</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>ZookeeperCliDriver</type>
+ <connect_order>7</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </Zookeeper7>
+
+ <RamCloud1>
+ <host>10.128.10.1</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>8</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RamCloud1>
+
+ <RamCloud2>
+ <host>10.128.10.2</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>9</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RamCloud2>
+
+ <RamCloud3>
+ <host>10.128.10.3</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>10</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RamCloud3>
+
+ <RamCloud4>
+ <host>10.128.10.4</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>11</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RamCloud4>
+
+ <RamCloud5>
+ <host>10.128.10.5</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>12</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RamCloud5>
+
+ <RamCloud6>
+ <host>10.128.10.6</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>13</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RamCloud6>
+
+ <RamCloud7>
+ <host>10.128.10.7</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RamCloudCliDriver</type>
+ <connect_order>14</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </RamCloud7>
+
+
+ <ONOS1>
+ <host>10.128.10.1</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>15</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS1>
+
+ <ONOS2>
+ <host>10.128.10.2</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>16</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS2>
+
+ <ONOS3>
+ <host>10.128.10.3</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>17</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS3>
+
+ <ONOS4>
+ <host>10.128.10.4</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>18</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS4>
+
+ <ONOS5>
+ <host>10.128.10.5</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>19</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS5>
+
+ <ONOS6>
+ <host>10.128.10.6</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>20</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS6>
+
+ <ONOS7>
+ <host>10.128.10.7</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>OnosCliDriver</type>
+ <connect_order>21</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOS7>
+
+ <Mininet2>
+ <host>10.128.10.90</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RemoteMininetDriver</type>
+ <connect_order>23</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom topo-onos4node.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet2>
+
+ <Mininet3>
+ <host>10.128.10.91</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>MininetCliDriver</type>
+ <connect_order>24</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom topo-intentTPtest.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet3>
+
+ <Mininet4>
+ <host>10.128.10.91</host>
+ <user>admin</user>
+ <password>onos_test</password>
+ <type>RemoteMininetDriver</type>
+ <connect_order>24</connect_order>
+ <COMPONENTS>
+ # Specify the Option for mininet
+ <arg1> --custom topo-onos4node.py </arg1>
+ <arg2> --topo mytopo --arp</arg2>
+ <controller> remote </controller>
+ </COMPONENTS>
+ </Mininet4>
+
+ </COMPONENT>
+</TOPOLOGY>