Page MenuHomec4science

node.py
No OneTemporary

File Metadata

Created
Sat, Jul 12, 15:35
import os
import time
import _thread
import socket
from telnetlib import Telnet
from subprocess import Popen, PIPE
import numpy as np
from multiprocessing.pool import ThreadPool
from random import randint
_wlan0_mac = ["00:0B:6B:02:02:45", "00:0B:6B:02:0D:05", "90:A4:DE:C0:46:D1", "90:A4:DE:C0:46:75", "90:A4:DE:C0:46:CA", "90:A4:DE:C0:46:CC", "90:A4:DE:C0:46:DE", "90:A4:DE:C0:46:D3","90:A4:DE:C0:46:E0", "90:A4:DE:C0:46:CB", "90:A4:DE:C0:46:C8", "90:A4:DE:C0:46:79","90:A4:DE:C0:46:DC", "", "90:A4:DE:C0:46:DF", "90:A4:DE:C0:46:D8", "90:A4:DE:C0:46:DD", "90:A4:DE:C0:46:DB", "90:A4:DE:C0:46:C5", "90:A4:DE:C0:46:A0", "90:A4:DE:C0:46:D5","90:A4:DE:C0:46:74", "90:A4:DE:C0:46:D7"]
_eth2_mac = ["00:50:C2:A2:70:B3", "00:50:C2:A2:70:7C", "00:50:C2:A2:70:85", "00:50:C2:A2:70:6E","00:50:C2:A2:70:84", "", "00:50:C2:A2:70:72", "", "00:50:C2:A2:70:7B", "00:50:C2:A2:70:83","00:50:C2:A2:70:82", "00:50:C2:A2:70:88", "00:50:C2:A2:70:64", "","","00:50:C2:A2:70:81", "00:50:C2:A2:70:86", "00:50:C2:A2:70:78", "00:50:C2:A2:70:77","00:50:C2:A2:70:7D", "00:50:C2:A2:70:70", "", "00:50:C2:A2:70:7E"]
_eth2_mac2 = ["00:50:C2:A2:70:50", "00:50:C2:A2:70:1B", "00:50:C2:A2:70:25", "00:50:C2:A2:70:0A","00:50:C2:A2:70:24", "", "00:50:C2:A2:70:10", "", "00:50:C2:A2:70:4C", "00:50:C2:A2:70:23","00:50:C2:A2:70:1A", "00:50:C2:A2:70:28", "00:50:C2:A2:70:00", "","","00:50:C2:A2:70:22", "00:50:C2:A2:70:26", "00:50:C2:A2:70:16", "00:50:C2:A2:70:15","00:50:C2:A2:70:1C", "00:50:C2:A2:70:0C", "", "00:50:C2:A2:70:1D"]
# new nodes
_wlan0_mac.extend(['']*50)
_wlan0_mac[41] = "04:F0:21:14:C6:5C"
_wlan0_mac[42] = "04:F0:21:14:C4:CE"
_wlan0_mac[43] = "04:F0:21:14:C6:36"
_wlan0_mac[44] = "04:F0:21:17:40:7D"
_wlan0_mac[45] = "04:F0:21:14:C6:35"
_wlan0_mac[46] = "04:F0:21:14:CF:12"
_wlan0_mac[47] = "04:F0:21:17:36:DF"
_wlan0_mac[48] = "04:F0:21:14:C6:52"
_wlan0_mac[49] = "04:F0:21:17:36:4E"
_wlan0_mac[50] = "04:F0:21:17:36:E9"
_wlan0_mac[51] = "04:F0:21:14:C5:C7"
_wlan0_mac[52] = "04:F0:21:17:3C:39"
_wlan0_mac[53] = "04:F0:21:17:36:4F"
_wlan0_mac[54] = "04:F0:21:14:C5:BD"
_wlan0_mac[55] = "04:F0:21:14:C6:59"
_wlan0_mac[56] = "04:F0:21:14:C6:49"
_wlan0_mac[57] = "04:F0:21:14:C6:5A"
_wlan0_mac[58] = "04:F0:21:14:C6:4A"
_wlan0_mac[59] = "04:F0:21:14:C6:53"
_wlan0_mac[60] = "04:F0:21:14:C5:C6"
_wlan0_mac[61] = "04:F0:21:17:40:7C"
_wlan0_mac[62] = "04:F0:21:14:C6:5D"
_wlan1_mac = ['']*70
_wlan1_mac[41] = "04:F0:21:17:36:D8"
_wlan1_mac[42] = "04:F0:21:17:36:D7"
_wlan1_mac[43] = "04:F0:21:17:46:29"
_wlan1_mac[44] = "04:F0:21:17:46:13"
_wlan1_mac[45] = "04:F0:21:17:46:22"
_wlan1_mac[46] = "04:F0:21:17:46:27"
_wlan1_mac[47] = "04:F0:21:17:46:24"
_wlan1_mac[48] = "04:F0:21:17:46:25"
_wlan1_mac[49] = "04:F0:21:17:46:23"
_wlan1_mac[50] = "04:F0:21:17:46:2B"
_wlan1_mac[51] = "04:F0:21:17:46:11"
_wlan1_mac[52] = ""
_wlan1_mac[53] = "04:F0:21:17:46:1F"
_wlan1_mac[54] = "04:F0:21:17:3C:38"
_wlan1_mac[55] = "04:F0:21:17:46:1A"
_wlan1_mac[56] = "04:F0:21:17:46:15"
_wlan1_mac[57] = "04:F0:21:17:46:20"
_wlan1_mac[58] = "04:F0:21:17:46:1E"
_wlan1_mac[59] = "04:F0:21:17:46:1D"
_wlan1_mac[60] = "04:F0:21:17:46:12"
_wlan1_mac[61] = "04:F0:21:17:46:14"
_wlan1_mac[62] = "04:F0:21:17:46:10"
_eth2_mac.extend(['']*50)
_eth2_mac[41] = "00:0D:B9:3D:C3:EA"
_eth2_mac[42] = "00:0D:B9:3D:C2:AA"
_eth2_mac[43] = "00:0D:B9:3E:9A:9A"
_eth2_mac[44] = "00:0D:B9:3E:A0:6E"
_eth2_mac[45] = "00:0D:B9:3E:A0:06"
_eth2_mac[46] = "00:0D:B9:3E:A0:92"
_eth2_mac[47] = "00:0D:B9:3E:9E:FE"
_eth2_mac[48] = "00:0D:B9:3E:9E:9E"
_eth2_mac[49] = "00:0D:B9:3E:A0:9E"
_eth2_mac[50] = "00:0D:B9:3E:A1:16"
_eth2_mac[51] = "00:0D:B9:3E:A2:F6"
_eth2_mac[52] = "00:0D:B9:3E:9B:7E"
_eth2_mac[53] = "00:0D:B9:3E:A0:7E"
_eth2_mac[54] = "00:0D:B9:3E:99:9E"
_eth2_mac[55] = "00:0D:B9:3E:A1:92"
_eth2_mac[56] = "00:0D:B9:3E:A0:FA"
_eth2_mac[57] = "00:0D:B9:3E:A0:BE"
_eth2_mac[58] = "00:0D:B9:3E:99:7A"
_eth2_mac[59] = "00:0D:B9:3E:98:0A"
_eth2_mac[60] = "00:0D:B9:3E:97:BA"
_eth2_mac[61] = "00:0D:B9:3E:A1:06"
_eth2_mac[62] = "00:0D:B9:3E:99:12"
_eth2_mac2.extend(['']*50)
#_eth2_mac2[41] = "00:8E:F2:FC:0F:58"
_eth2_mac2[41] = "28:C6:8E:B6:E2:3E"
_eth2_mac2[42] = "28:C6:8E:B6:E2:71"
#_eth2_mac2[42] = "00:8E:F2:FC:0F:45"
_eth2_mac2[43] = "28:C6:8E:B6:E6:33"
_eth2_mac2[44] = "28:C6:8E:B6:E6:5E"
#_eth2_mac2[45] = "28:C6:8E:B6:E2:3C"
_eth2_mac2[45] = "28:C6:8E:B6:E2:6F"
_eth2_mac2[46] = "28:C6:8E:B6:E2:E5"
_eth2_mac2[47] = "28:C6:8E:B6:E6:53"
_eth2_mac2[48] = "28:C6:8E:B6:E2:63"
_eth2_mac2[49] = "28:C6:8E:B6:E2:59"
_eth2_mac2[50] = "28:C6:8E:B6:E6:42"
_eth2_mac2[51] = "28:C6:8E:B6:E6:61"
_eth2_mac2[52] = "28:C6:8E:B6:E2:6F"
_eth2_mac2[53] = "28:C6:8E:B6:E6:3E"
_eth2_mac2[54] = "28:C6:8E:B6:E6:4D"
_eth2_mac2[56] = "28:C6:8E:B6:E2:61"
_eth2_mac2[55] = "28:C6:8E:B6:E6:49"
_eth2_mac2[57] = "28:C6:8E:B6:E2:5B"
_eth2_mac2[58] = "28:C6:8E:B6:E2:50"
_eth2_mac2[59] = "28:C6:8E:B6:E6:58"
_eth2_mac2[60] = "28:C6:8E:B6:E6:60"
_eth2_mac2[61] = "28:C6:8E:B6:E6:6B"
_eth2_mac2[62] = "28:C6:8E:B6:E6:62"
# class that represents a testbed node
class Node():
def __init__(self, index):
self.index = index
self.cmd_client = False #By default, we don't use the direct commands
self.tn = 0
def toString(self):
if self.index < 10:
return "node0"+str(self.index)
else:
return "node"+str(self.index)
def __str__(self):
return self.toString()
def getIndex(self, ip_index=False):
if ip_index and self.index == 0:
return 100
return self.index
@staticmethod
def getIndexFromMAC(mac):
mac = mac.replace("-",":")
mac = mac.upper()
if mac in _eth2_mac2:
return _eth2_mac2.index(mac)
if mac in _wlan0_mac:
return _wlan0_mac.index(mac)
if mac in _eth2_mac:
return _eth2_mac.index(mac)
if mac in _wlan1_mac:
return _wlan1_mac.index(mac)
return False
@staticmethod
def getIndexFromIP(ip):
tokens = ip.split('.')
if tokens[-1] == "100":
return 0
else:
return int(tokens[-1])
@staticmethod
def staticIPStr(index, wifi=True):
if wifi:
ip = "10"
else:
ip = "11"
if index == 0:
return "10.10."+ip+".100"
else:
return "10.10."+ip+"."+str(index)
@staticmethod
def get_wlan0_mac():
return _wlan0_mac
@staticmethod
def get_eth2_mac():
return _eth2_mac
def localRoot(self):
return "/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+str(self)
def checkConnectivity(self):
return os.system("fping -c 1 -t 10 "+self.getWiredIPStr()+" > /dev/null 2>&1") == 0
def setDirectCommands(self,ind=0,first_ind=-1,debug=False):
#check connectivity
if not self.checkConnectivity():
return False
if first_ind == -1:
first_ind = ind
if ind > (first_ind+3): # try at most three times
return False
# To receive replies of node on blocking commands
if not self.cmd_client:
self.sock_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#self.sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
self.sock_index = 8004+self.index+ind*100
if debug:
print("Try to open instance", ind, "on node", self.index)
try:
self.sock_server.bind(("192.168.61.99", self.sock_index))
except socket.error as e:
if e.errno == 98: #address already in use, try another one
if debug:
print("Adress already in use, retry")
return self.setDirectCommands(ind+1,first_ind, debug=debug)
else:
raise e
self.sock_server.settimeout(0.5)
ind = (self.sock_index-8004-self.index)/100
command_python = "python /root/cmd-client.py "+str(self.index)+" "+str(ind)
output = self.sendDirectCommand("ps w|grep \""+command_python+"\"", debug=debug)
if output != False:
output = output.split('\n')[0]
output = output.split(' ')
output = [x for x in output if x!='']
if len(output) > 0:
process_ind = output[0]
if debug:
print("killing process", process_ind)
self.sendCommandNonBlocking("kill -9 "+process_ind)
elif debug:
print("No process killed")
if debug:
print("Run python /root/cmd-client.py "+str(self.index)+" "+str(ind))
self.sendCommandNonBlocking("python /root/cmd-client.py "+str(self.index)+" "+str(ind))
time.sleep(1) #let the node enough time to open its socket properly etc..
# check that it worked
output = self.sendDirectCommand("ps w|grep \""+command_python+"\"", debug=debug)
if output == False or command_python not in output:
# try again
output = self.sendDirectCommand("ps w|grep \""+command_python+"\"", debug=debug)
if output == False or command_python not in output:
if debug:
print("python script not run properly, retry")
self.sock_server.close()
return self.setDirectCommands(ind+1, first_ind, debug=debug)
self.cmd_client = True
return True
def unsetDirectCommands(self, debug=False):
if self.cmd_client:
ind = (self.sock_index-8004-self.index)/100
command_python = "python /root/cmd-client.py "+str(self.index)+" "+str(ind)
if debug:
print("Grep command", command_python, "on node", self.index)
if not debug:
self.sendDirectCommand("rm /root/log_cmd_client"+str(ind))
output = self.sendDirectCommand("ps w|grep \""+command_python+"\"")
if output != False:
if debug:
print("Got output", output)
output = output.split('\n')[0]
output = output.split(' ')
output = [x for x in output if x!='']
if len(output) > 0:
process_ind = output[0]
if debug:
print("Killing process", process_ind, "on node", self.index)
self.sendCommandAuto("kill -9 "+process_ind, blocking=False)
elif debug:
print("No process killed on node", self.index)
try:
self.sock_server.shutdown(socket.SHUT_RDWR)
except socket.error as e:
pass
self.sock_server.close()
self.cmd_client = False
def unsetTelnet(self):
if self.tn:
self.tn.close()
self.tn = 0
def makeDirectory(self, path, force=False):
force_str = ""
if force:
force_str = " -p"
self.sendCommandAuto("mkdir "+path+force_str)
def configureWifi(self, wifi_version, channel, HT_type, mode, bssid):
print('configuring wifi for node '+str(self.index)+'...')
dst_file = "/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/etc/config/wireless"
src_file = "/opt/aziala/experiments/experiments-lib/wireless-base"
o = open(dst_file, "w")
for line in open(src_file):
line = line.replace("option channel 1", "option channel "+str(channel))
line = line.replace("option hwmode 11g", "option hwmode 11"+wifi_version)
tokens = line.split()
if len(tokens) == 3 and (tokens[2] == "11na" or tokens[2] == "11ng"):
#For 802.11n we need to add a few more lines
line = line+" option htmode HT"+str(HT_type)+'\n'
line = line+" list ht_capab SHORT-GI-40"+'\n'
line = line+" list ht_capab TX-STBC"+'\n'
line = line+" list ht_capab RX-STBC1"+'\n'
line = line+" list ht_capab DSSS_CCK-40"+'\n'
line = line.replace("aziala", bssid)
line = line.replace("adhoc", mode)
o.write(line)
o.close()
self.sendCommandAuto("wifi")
def configurePlc(self,plc=False):
dst_file = "/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/etc/config/network"
src_file = "/opt/aziala/experiments/experiments-lib/network-config"+("-plc" if plc else "")
o = open(dst_file, "w")
for line in open(src_file):
line = line.replace("10.10.11.1", self.getPLCIPStr())
line = line.replace("10.10.10.1", self.getIPStr())
o.write(line)
o.close()
self.sendCommandAuto("/etc/init.d/network restart")
def setDatarates(self):
self.sendCommandAuto("iw dev wlan0 set bitrates")
def setTxPower(self, txpower):
#txpower is the txpower in mBm
self.sendCommandAuto("iw phy phy0 set txpower fixed "+str(txpower))
def createMonitorInterface(self):
self.sendCommandAuto("iw phy phy0 interface add moni0 type monitor")
self.sendCommandAuto("ifup moni0")
def copyClickScript(self, click_script):
os.spawnlp(os.P_WAIT, 'cp', 'cp', '/opt/aziala/experiments/click-scripts/'+str(click_script), "/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/")
def alignClick(self, click_script, name_aligned):
self.sendCommandAuto("click-align /root/"+click_script+" -o /root/"+name_aligned, blocking=True)
def launchClick(self, click_script, wifi=True, plc=False, capture_traf=True, block=True, logfile=""):
if capture_traf == True:
#Everything must go through Click:
self.sendCommandAuto("iw phy phy0 interface add moni0 type monitor", blocking=block, prependPath=block)
self.sendCommandAuto("ifconfig moni0 up", blocking=block, prependPath=block)
if plc:
self.sendCommandAuto("ifconfig eth2 netmask 255.255.255.255", blocking=block, prependPath=block)
if wifi:
self.sendCommandAuto("ifconfig wlan0 netmask 255.255.255.255", blocking=block, prependPath=block)
self.sendCommandAuto("click /root/"+click_script+("" if logfile == "" else " > "+logfile+" 2>&1"), blocking=False, prependPath=False)
def alignAndLaunchClick(self, click_script, wifi=True, plc=False, capture_traf=True, block=True, logfile=""):
index = click_script.find(".click")
if index >= 0:
click_script = click_script[0:index]
self.alignClick(click_script+".click", click_script+"_a.click")
self.launchClick(click_script+"_a.click", wifi, plc, capture_traf, block, logfile)
def killClick(self, wifi=True, plc=True, was_capturing=True, one_node=True):
if one_node:
self.handlerClick("write rtl.stop_node 1", quick=True)
self.sendCommandAuto("killall click", blocking=True)
#self.sendCommandAuto("click-uninstall", blocking=True)
#time.sleep(5)
if was_capturing == True:
if plc:
self.sendCommandAuto("ifconfig eth2 netmask 255.255.255.0", blocking=False)
if wifi:
self.sendCommandAuto("ifconfig wlan0 netmask 255.255.255.0", blocking=False)
#self.sendCommandAuto("iptables -F")
def launchIperfServer(self, proto="u", logfile="iperf.log", port=5001, size=1470,style=0,interval=1, debug=False, window="", tcp=False):
if tcp:
proto=""
#print "command ","iperf -s --reportstyle C -l "+str(size)+" "+("-u" if proto=="u" else "")+" -p"+str(port)+" -i1"+("" if logfile=="" else " -fm > "+logfile)
if style == 0:
command="iperf -s --reportstyle C "+(" -l " if proto == "u" else " -M ")+str(size)+" "+("-u" if proto=="u" else "") + ((" -w "+window) if window != "" else "") +" -p"+str(port)+" -i"+str(interval)+("" if logfile=="" else " -fm > "+logfile+" 2>&1")
else:
command="iperf -s "+("-u" if proto=="u" else "")+" -p"+str(port)+" -i"+str(interval)+("" if logfile=="" else " > "+logfile+" 2>&1")
if debug:
print(command)
self.sendCommandAuto(command,blocking=False, debug=debug)
def launchIperfClient(self, dst, proto="u", packetsize=1470, load="300M", duration=10, port=5001, block=False, tos_flag="", burst=1, \
debug=False, window="", tcp=False, tcp_cc = "", logfile="iperf.log", source_ip=""):
if tcp:
proto=""
#print "command ","iperf -c "+dst+((" -u -b"+load) if proto == "u" else "") + " -p"+str(port)+ " -l "+str(packetsize)+"B"+("" if tos_flag == "" else " -S "+ tos_flag)+ " -t"+str(duration)
if burst == 1:
command_iperf = "iperf -c "+dst+((" -u -b"+load) if proto == "u" else "") + ((" -w "+window) if (window != "" and proto == "") else "") + \
((" -Z "+tcp_cc) if (proto == "" and tcp_cc!="") else "") + ((" -B "+source_ip) if source_ip != "" else "") + " -p"+str(port)+ \
(" -l " if proto == "u" else " -M ")+str(packetsize)+"B"+("" if tos_flag == "" else " -S "+ tos_flag)+ " -t"+str(duration) +("" if logfile=="" else " > "+logfile+" 2>&1")
if debug:
print(command_iperf)
self.sendCommandAuto(command_iperf, blocking=block, debug=debug)
else:
load_per_burst = packetsize*burst
if load[-1] == 'k' or load[-1] == 'K':
load_int = int(load[0:-1])*1024
if load[-1] == 'm' or load[-1] == 'M':
load_int = int(load[0:-1])*1024*1024
else:
load_int = int(load[0:-1])
bursts_per_sec = load_int/load_per_burst
freq_ms = 1000/bursts_per_sec
python_cmd = "import time; time_ms=0; while "
self.sendCommandAuto("python -c \"import time; time_ms=0; whi \"", blocking=block,debug=debug)
def computeIperfCapacity(self,dur,log_file="/root/log_iperf.tmp",debug=False, as_list=False):
lines = self.sendCommandAuto("cat "+log_file, debug=debug)
if lines== None:
print("Should set direct commands")
return
if lines == False:
print("Could not get capacity (error in cat)")
if as_list:
return [0]*dur
else:
return 0
lines = lines.split('\n')
lines = [line for line in lines if line != '' and line != None]
if debug:
print(lines)
if as_list:
throughputs = []
if len(lines) == 0:
return [0]*dur
for line in lines:
line_split = line.split(',')
if len(line_split) > 7:
if line == lines[-1] and line_split[6][0] == "0": #summary
continue
num_B = int(line_split[7])
else:
if debug:
print("Could not get capacity: line is", line)
num_B = 0
throughputs.append(num_B/125) #in kbit/s
return throughputs
else:
if len(lines) > 0:
last_line = lines[-1].split(',')
else:
if debug:
print("Could not get capacity (empty file)")
return 0
if debug:
print("Last line is", last_line)
if len(last_line) > 7:
num_B = int(last_line[7])
else:
if debug:
print("Could not get capacity: last line is", last_line)
return 0
return num_B/(dur*125) #in kbits/s
def getRxPackets(self, interface="", debug=False, print_time=False):
if interface == "":
# get all interfaces, return dict
t_loc = time.time()
output = self.sendCommandAuto("ifconfig", debug=debug)
if print_time:
print(("Got output in "+str(time.time() - t_loc)+" sec"))
if output == False:
return False
tokens = output.split()
rx_packets = {}
t_loc = time.time()
while True:
if "Link" not in tokens:
break
ind = tokens.index("Link")
interface = tokens[ind-1]
tokens = tokens[ind:]
if "RX" not in tokens:
continue
ind_rx = tokens.index("RX")
rx_packets[interface] = int(tokens[ind_rx+1].split(":")[1])
tokens = tokens[ind_rx:]
if print_time:
print(("Construct dict in "+str(time.time() - t_loc)+" sec"))
return rx_packets
else:
output = self.sendCommandAuto("ifconfig "+interface+" | grep \"RX packets\"", debug=debug)
#output = self.sendCommandAuto("ifconfig "+interface, debug=debug)
if output == False:
return False
tokens = output.split()
if "RX" in tokens:
ind_rx = tokens.index("RX")
return int(tokens[ind_rx+1].split(":")[1])
else:
return False
def getRxPacketsTest(self, interface, debug=False):
random_int = randint(0,1000000)
tmpfile = "/root/getrxpacket"+str(random_int)+".tmp"
self.sendCommandAuto("ifconfig "+interface+" | grep \"RX packets\" > "+tmpfile, debug=debug, blocking=False)
count = 0
while not os.path.exists("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+str(self)+tmpfile):
time.sleep(0.001)
count += 1
if count == 10:
print("count = 10, get slow")
return self.getRxPackets(interface, debug)
count = 0
output = []
while len(output) == 0:
time.sleep(0.001)
if debug:
print("Opening /opt/aziala/deploy/pxe-nfs-setup/filesystems/"+str(self)+tmpfile)
f = open("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+str(self)+tmpfile, "r")
output = f.readlines()
count += 1
if count == 1000:
print("incorrect output, get slow")
self.sendCommandAuto("rm "+tmpfile, blocking=False)
return self.getRxPackets(interface, debug)
output = output[0]
tokens = output.replace("\n"," ").split(" ")
#self.sendCommandAuto("rm "+tmpfile, blocking=False)
if "RX" in tokens:
ind_rx = tokens.index("RX")
return int(tokens[ind_rx+1].split(":")[1])
else:
return False
def checkPingConnectivity(self, dst, interface="wifi", debug=False):
if interface == "wifi":
ip = dst.getIPStr()
elif interface == "wifi2":
ip = dst.getWifi2IPStr()
elif interface == "plc":
ip = dst.getPLCIPStr()
else:
print("Wrong interface (wifi, wifi2 or plc)")
return False
count = 0
while count < 3: # try three times
out=self.sendCommandAuto("fping -c 1 -t 200 "+ip+" > /dev/null 2>&1", blocking=True, debug=debug)
if out==False or out == "":
count += 1
else:
return True
return False
def getIperfCapacity(self, dst, interface="wifi", wifi=None, dur=10, debug=False, ping_first=False, as_list=False, reset_plc=False, dur_test=0, log_test=""):
# check that direct commands are set
if (interface == "wifi" and wifi==None) or wifi==True:
ip = dst.getIPStr()
interface = "wifi"
elif (interface == "plc" and wifi==None) or wifi==False:
ip = dst.getPLCIPStr()
interface = "plc"
elif (interface == "wifi2" and wifi==None):
ip = dst.getWifi2IPStr()
interface = "wifi2"
else:
print("Wrong interface (wifi, wifi2 or plc)")
return False
# first check connectivity
if not self.checkPingConnectivity(dst, interface=interface):
return False
port_iperf = randint(5002,10000)
if ip==dst.getPLCIPStr() and reset_plc:
if debug:
print("Reset PLC device")
self.sendCommandAuto("int6k -i eth2 -R > /dev/null 2>&1")
dst.sendCommandAuto("int6k -i eth2 -R > /dev/null 2>&1")
time.sleep(10) # wait for device to be reset
if (ip==dst.getPLCIPStr() and reset_plc) or ping_first:
self.sendCommandAuto("ping "+ip+" -c 5", blocking=True) # ping before to initiate connection
if dur_test > 0 or (reset_plc and ip==dst.getPLCIPStr()):
if dur_test==0: # if PLC was reset
dur_test=10
if debug:
print("Run source for rate convergence")
dst.launchIperfServer(logfile=log_test, debug=debug, port=port_iperf)
time.sleep(0.5)
self.launchIperfClient(ip, block=False,duration=dur_test, debug=debug, port=port_iperf) # after reset, takes time to converge to good capacity
time.sleep(dur_test+1)
self.sendCommandAuto("killall iperf > /dev/null 2>&1")
dst.sendCommandAuto("killall iperf > /dev/null 2>&1")
time.sleep(0.5)
if debug:
print("Run test")
if dur == 0:
return 0
dst.launchIperfServer(logfile="/root/log_iperf.tmp", debug=debug, port=port_iperf)
time.sleep(0.5) #to be sure that server is run
self.launchIperfClient(ip, block=False, duration=dur, debug=debug, port=port_iperf)
time.sleep(dur+1)
dst.killIperf()
#time.sleep(10)
#f = open("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+dst.toString()+"/root/log_iperf.tmp",'r')
#lines = f.readlines()
capacities = dst.computeIperfCapacity(dur,debug=debug, as_list=True)
if len(capacities) < dur - 3: # should not happen if everything went OK (sometimes a few measurements are missed)
print("Something went wrong, have", len(capacities), "measures, duration is", dur, "("+" ".join(map(str,capacities))+")")
return 0
if np.mean(capacities) == 0:
if ping_first:
print("Something went wrong, all capacities are 0 whereas there is connectivity")
return 0
capacities = capacities[0:dur]
if np.std(capacities) / np.mean(capacities) > 0.1: # something went wrong
print("Something might have gone wrong, high variations: ", " ".join(map(str,capacities)))
if as_list:
return capacities
else:
return np.mean(capacities)
return dst.computeIperfCapacity(dur,debug=debug, as_list=as_list)
@staticmethod
def multiIperf(pairs, dur=10, interface="wifi", debug=False, as_list=False, ping_first=False):
threads = []
pools = []
for pair in pairs:
pool = ThreadPool(processes=1)
threads.append(pool.apply_async(pair[0].getIperfCapacity, (pair[1], interface, None, dur, debug, ping_first,as_list)))
pools.append(pool)
#time.sleep(dur)
results = []
for thread in threads:
try:
results.append(_thread.get())
except IndexError as e:
print("Index error", e)
return False
except ValueError as e:
print("Value error", e)
return False
except socket.error as e:
print("Socket error", e)
return False
for pool in pools:
pool.close()
return results
def isNeighborWifiDev(self, node):
if not self.cmd_client:
print("Should set direct commands")
return
path = "/sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/"
addr = node.getMACWifi().lower()
output = self.sendDirectCommand("ls "+path)
if output == False:
return False
return (addr in output)
def isNeighborPing(self, ip):
if not self.cmd_client:
print("Should set direct commands")
return
output_ping = self.sendDirectCommand("ping "+ip+" -w 1", blocking=True, timeout=1.5)
if output_ping == False:
return False
else:
return True
def launchNetperfSource(self, dst, duration,logfile="",port=0):
print("command ", "netperf -H "+ dst + " -l "+ str(duration) +" -t UDP_STREAM -- -m 1024"+" -p "+str(port+12865))
if logfile=="":
self.sendCommandAuto("netperf -H "+ dst + " -l "+ str(duration) +" -t UDP_STREAM -- -m 1024 -p "+str(port+12865), blocking=False)
else:
self.sendCommandAuto("netperf -H "+ dst + " -l "+ str(duration) +" -t UDP_STREAM -- -m 1024 -p " +str(port+12865)+" > "+logfile, blocking=False)
def launchNetperfDst(self,port=0):
self.sendCommandAuto("netserver -p "+str(port+12865), blocking=False)
def killNetserver(self):
self.sendCommandAuto("killall netserver",blocking=True)
# def sendPing(self, dst, count=1, logfile=""):
# print("ping "+dst)
# self.sendCommandAuto("ping -c "+str(count)+" " +dst+("" if logfile == "" else " >> "+logfile))
def killIperf(self):
self.sendCommandAuto("killall iperf", blocking=False)
def killTcpDump(self):
self.sendCommandAuto("killall tcpdump", blocking=False)
def addForbiddenLink(self, addr):
return self.handlerClick("write rtl.add_forbidden_link "+addr)
def rmForbiddenLink(self, addr):
return self.handlerClick("write rtl.rm_forbidden_link "+addr)
def addForbiddenMp(self, mp):
return self.handlerClick("write rtp.add_forbidden_path "+mp)
def rmForbiddenMp(self, mp):
return self.handlerClick("write rtp.rm_forbidden_path "+mp)
#set number of active antennas
def setAntennas(self, antennas): # antennas=1: first antenna; 2: second antenna; 3: both antennas
self.sendCommandAuto("uci set wireless.radio0.diversity=0;uci set wireless.radio0.rxantenna="+str(antennas)+";uci set wireless.radio0.txantenna="+str(antennas)+";uci commit wireless; wifi", blocking=True)
def setBitrates(self, bitrates=-1, interface="wlan0"): #-1 means reset; otherwise, MCS index (0-15)
if bitrates==-1:
ht_mcs = "ht-mcs-2.4"
if interface == "wlan1":
ht_mcs = "ht-mcs-5"
self.sendCommandAuto("iw dev "+interface+" set bitrates "+ht_mcs)
else:
ht_mcs = "ht-mcs-5"
if interface == "wlan1":
ht_mcs = "ht-mcs-2.4"
self.sendCommandAuto("iw dev "+interface+" set bitrates "+ht_mcs+" "+str(bitrates))
def getNeighborsCapa(self):
output = self.handlerClick("read neighbors.print_info")
if output == False:
return False
lines = output.split("\n")
eth_capa_dict = {}
for i in range(0,len(lines)-1):
ind_capa = lines[i].find("capa=")
if ind_capa >= 0:
eth = lines[i][14:31]
ind_capa = ind_capa+5
ind_end_capa = lines[i].find("(",ind_capa) #for Wifi
if ind_end_capa == -1: #for PLC
ind_end_capa = len(lines[i])
try:
capa = int(lines[i][ind_capa:ind_end_capa])
except ValueError:
capa = 0
eth_capa_dict[eth] = capa
return eth_capa_dict
def getNeighborsProba(self, debug=False):
output = self.handlerClick("read neighbors.print_info", debug=debug)
if output == False:
return False
lines = output.split("\n")
eth_proba_dict = {}
for i in range(0,len(lines)-1):
ind_proba = lines[i].find("proba=")
if ind_proba >= 0:
eth = lines[i][14:31]
ind_proba = ind_proba+6
proba = int(lines[i][ind_proba:])
eth_proba_dict[eth] = proba
return eth_proba_dict
def runInfiniteSource(self, ip, length=1380, ether=False):
if self.handlerClick("write host/ipencap_infsrc.dst "+ip) == False:
return False
if ether:
if self.handlerClick("write host/etherencap_infsrc.dst "+ _eth2_mac[Node.getIndexFromIP(ip)]) == False:
return False
if self.handlerClick("write host/infsrc.length "+str(length)) == False:
return False
if self.handlerClick("write host/infsrc.active true") == False:
return False
def sendTrafficPLC(self, index, nb_packets = -1, ipencap=True, ping=False):
if _eth2_mac[index] == "":
print("Node", str(index), "does not have PLC")
return False
if index == 0:
ip="10.10.11.100"
else:
ip="10.10.11."+str(index)
if ping==False:
src="infsrc"
if self.handlerClick("write host/"+src+".reset 1", quick=True) == False:
return False
else:
src="pingsrc"
if self.handlerClick("write host/"+src+".reset_counts 1", quick=True) == False:
return False
if self.handlerClick("write host/"+src+".active false", quick=True) == False:
return False
if self.handlerClick("write host/"+src+".limit "+str(nb_packets), quick=True) == False:
return False
if self.handlerClick("write host/etherencap_plc.dst "+_eth2_mac[index], quick=True) == False:
return False
if ping==False and ipencap:
if self.handlerClick("write host/ipencap_plc.dst "+ip, quick=True) == False:
return False
if ping:
if self.handlerClick("write host/pingsrc.dst "+ip, quick=True) == False:
return False
if self.handlerClick("write host/"+src+".active true", quick=True) == False:
return False
def stopTrafficPLC(self):
if self.handlerClick("write host/infsrc.active false", quick=True) == False:
return False
def sendPing(self, index, interface, length=1024, debug=False):
if not isinstance(index, int):
print("Index should be an integer")
return False
debug_bool = debug
if interface == "wifi":
ip_prefix = "10.10.10."
elif interface == "plc":
ip_prefix = "10.10.11."
else:
print("Interface should be 'wifi' or 'plc'")
return False
if index == 0:
ip=ip_prefix+"100"
else:
ip=ip_prefix+str(index)
self.sendCommandAuto("ping -c 1 "+ip+" -s "+str(length), debug=debug_bool, blocking=False)
def netperfString(self, ip, nb_bytes, interface, length):
return "netperf -H "+ip+" -l "+nb_bytes+" -N -t UDP_STREAM -- -m "+str(length)+" -P 12345 ;"
def sendMessagesNetperf(self, index, nb_packets, interface, length=1024, debug=False, block=True):
debug_bool = debug
if interface == "wifi":
ip_prefix = "10.10.10."
elif interface == "plc":
ip_prefix = "10.10.11."
else:
print("Interface should be 'wifi' or 'plc'")
return False
if isinstance(index, int):
index_arr = [index]
else:
index_arr = index
nb_bytes = str(-length*nb_packets)
cmd_str = ""
for ind in index_arr:
if ind == 0:
ip=ip_prefix+"100"
else:
ip=ip_prefix+str(ind)
cmd_str+= self.netperfString(ip, nb_bytes, interface, length)
self.sendCommandAuto(cmd_str, debug=debug_bool, blocking=block)
def getTimesFromSurvey(self, f):
act_time = -1
busy_time = -1
rx_time = -1
tx_time = -1
freq_in_use = False
for line in f:
if "frequency" in line:
if "in use" in line:
freq_in_use = True
else:
freq_in_use = False
line = line.replace('\n', '')
line = line.replace('\t', ' ')
tokens = line.split(' ')
if "channel active time" in line and freq_in_use:
act_time = int(tokens[tokens.index('ms')-1])
if "channel busy time" in line and freq_in_use:
busy_time = int(tokens[tokens.index('ms')-1])
if "channel receive time" in line and freq_in_use:
rx_time = int(tokens[tokens.index('ms')-1])
if "channel transmit time" in line and freq_in_use:
tx_time = int(tokens[tokens.index('ms')-1])
break;
return (act_time, busy_time, rx_time, tx_time)
def getNbPacketsFromFile(self, f, direction):
if direction != "TX" and direction != "RX" and direction != "both":
print("Direction should be RX or TX or both")
return -1
nb_p_tx = -1
nb_p_rx = -1
for line in f:
if "TX packets" in line or "RX packets" in line:
line = line.replace('\n', '')
line = line.replace('\t', ' ')
line = line.replace(':', ' ')
tokens = line.split(' ')
tokens = list(filter(bool, tokens))
if "TX packets" in line:
nb_p_tx = int(tokens[2])
if "RX packets" in line:
nb_p_rx = int(tokens[2])
if direction == "TX":
return nb_p_tx
if direction == "RX":
return nb_p_rx
if direction == "both":
return (nb_p_tx, nb_p_rx)
def computeAirtimeWifi(self, f_beg, f_end, debug=False):
f_beg = f_beg.split("\n")
(act_time_beg, busy_time_beg, rx_time_beg, tx_time_beg) = self.getTimesFromSurvey(f_beg)
#f_beg.close()
f_end = f_end.split("\n")
(act_time_end, busy_time_end, rx_time_end, tx_time_end) = self.getTimesFromSurvey(f_end)
#f_end.close()
total_act_time = act_time_end - act_time_beg
total_busy_time = busy_time_end - busy_time_beg
total_rx_time = rx_time_end - rx_time_beg
total_tx_time = tx_time_end - tx_time_beg
#total_times = total_busy_time + total_rx_time + total_tx_time
total_times = total_busy_time
airtime = float(total_times)/total_act_time
if debug:
print("During the last", str(total_act_time), "ms, channel has been used", str(total_times), "ms (busy: "+str(total_busy_time)+" ms, rx: "+str(total_rx_time)+" ms, tx: "+str(total_tx_time)+" ms; airtime is "+str(airtime)+")")
return (total_times, total_act_time)
def computeNbPackets(self, f_beg, f_end, direction, debug=False):
if direction == "both":
(nb_p_tx_beg, nb_p_rx_beg) = self.getNbPacketsFromFile(f_beg, direction)
f_beg.close()
(nb_p_tx_end, nb_p_rx_end) = self.getNbPacketsFromFile(f_end, direction)
f_end.close()
if nb_p_tx_beg==-1 or nb_p_rx_beg==-1 or nb_p_tx_end==-1 or nb_p_rx_end==-1:
print("Error when getting packets, nb_p_tx_beg="+str(nb_p_tx_beg)+", nb_p_rx_beg="+str(nb_p_rx_beg)+", nb_p_tx_end="+str(nb_p_tx_end)+", nb_p_rx_end="+str(nb_p_rx_end))
return (-1, -1)
if debug:
print("Have sent", str(nb_p_tx_end-nb_p_tx_beg), "packets, received", str(nb_p_rx_end-nb_p_rx_beg))
return (nb_p_tx_end-nb_p_tx_beg, nb_p_rx_end-nb_p_rx_beg)
else:
nb_p_beg = self.getNbPacketsFromFile(f_beg, direction)
f_beg.close()
nb_p_end = self.getNbPacketsFromFile(f_end, direction)
f_end.close()
if nb_p_beg >= 0 and nb_p_end >= 0:
if debug:
if direction == "TX":
action = "sent"
else:
action = "received"
print("Have", action, str(nb_p_end - nb_p_beg), "packets: was", str(nb_p_beg), "is", str(nb_p_end))
return (nb_p_end - nb_p_beg)
else:
return -1
def getSurveyWifi(self, name_file, only=""):
if only!="get_file":
self.sendCommandAuto("iw dev wlan0 survey dump > /root/"+name_file)
if only!="write_file":
f = open("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_file,'r')
return f
def getIfconfigWifi(self, name_file_wlan, name_file_moni, only=""):
if only!="get_files":
self.sendCommandAuto("ifconfig wlan0 > /root/"+name_file_wlan)
self.sendCommandAuto("ifconfig moni0 > /root/"+name_file_moni)
if only!="write_files":
f_wlan = open("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_file_wlan,'r')
f_moni = open("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_file_moni,'r')
return (f_wlan, f_moni)
def getAirtimeWifi(self, interval=1, debug=False):
name_beg = "survey_begin.log"
name_end = "survey_end.log"
#self.getSurveyWifi(name_beg, only="write_file")
f_beg = self.sendCommandAuto("iw dev wlan0 survey dump")
time.sleep(interval)
#self.getSurveyWifi(name_end, only="write_file")
#f_beg = self.getSurveyWifi(name_beg, only="get_file")
#time.sleep(0.05)
#f_end = self.getSurveyWifi(name_end, only="get_file")
f_end = self.sendCommandAuto("iw dev wlan0 survey dump")
(busy, total) = self.computeAirtimeWifi(f_beg, f_end, debug)
#if not debug:
# os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_beg)
# os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_end)
return float(busy)/total
def getNbPackets(self, interval, debug=False):
name_beg_wlan = "ifconfig_wlan_begin.log"
name_end_wlan = "ifconfig_wlan_end.log"
name_beg_moni = "ifconfig_moni_begin.log"
name_end_moni = "ifconfig_moni_end.log"
(f_beg_wlan, f_beg_moni) = self.getIfconfigWifi(name_beg_wlan, name_beg_moni)
time.sleep(interval)
(f_end_wlan, f_end_moni) = self.getIfconfigWifi(name_end_wlan, name_end_moni)
res_wlan = self.computeNbPackets(f_beg_wlan, f_end_wlan, "TX", debug)
res_moni = self.computeNbPackets(f_beg_moni, f_end_moni, "RX", debug)
if not debug:
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_beg_wlan)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_end_wlan)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_beg_moni)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_end_moni)
return (res_wlan, res_moni)
def initAirtime(self, interface="wifi"):
self.handlerClick("write measurements_"+interface+".init_airtime 0", quick=True)
def computeAndGetAirtime(self, interface="wifi", quick=True):
self.handlerClick("write measurements_"+interface+".compute_airtime 1", quick=quick)
res = self.handlerClick("read measurements_"+interface+".get_airtime", quick=quick)
if res == False or "Error" in res:
return None
res = res.split('\r\n')
try:
res = float(res[-1])
except:
print("Error while parsing", res)
return None
return res
def getAirtimeAndNbPacketsWifi(self, interval, nBackoffCompute=0, debug=False, click=True):
if click:
self.handlerClick("write measurements_wifi.init_airtime "+str(int(interval*1000)))
res = "not ready"
while res == False or "not ready" in res:
time.sleep(interval)
res = self.handlerClick("read measurements_wifi.get_airtime")
if res == False:
return False
res = res.split('\r\n')
res = float(res[-1])
return res
else:
array_backoff_times_bianchi = [7.5, 4.28, 3.24, 2.73, 2.43, 2.23, 2.08, 1.97, 1.88, 1.81] # CW_min = 16
#array_backoff_times_bianchi = [15.5, 8.27, 5.87, 4.69, 3.98, 3.51, 3.18, 2.93, 2.74, 2.58] # CW_min = 32
name_beg_sur = "survey_begin.log"
name_end_sur = "survey_end.log"
name_beg_wlan = "ifconfig_wlan_begin.log"
name_end_wlan = "ifconfig_wlan_end.log"
name_beg_moni = "ifconfig_moni_begin.log"
name_end_moni = "ifconfig_moni_end.log"
self.getSurveyWifi(name_beg_sur, only="write_file")
self.getIfconfigWifi(name_beg_wlan, name_beg_moni, only="write_files")
time.sleep(interval)
self.getSurveyWifi(name_end_sur, only="write_file")
self.getIfconfigWifi(name_end_wlan, name_end_moni, only="write_files")
f_beg_sur = self.getSurveyWifi(name_beg_sur, only="get_file")
(f_beg_wlan, f_beg_moni) = self.getIfconfigWifi(name_beg_wlan, name_beg_moni, only="get_files")
time.sleep(0.05)
f_end_sur = self.getSurveyWifi(name_end_sur, only="get_file")
(f_end_wlan, f_end_moni) = self.getIfconfigWifi(name_end_wlan, name_end_moni, only="get_files")
(busy, total) = self.computeAirtimeWifi(f_beg_sur, f_end_sur, debug)
(nb_p_tx_wlan, nb_p_rx_wlan) = self.computeNbPackets(f_beg_wlan, f_end_wlan, "both", debug)
nb_p_moni = self.computeNbPackets(f_beg_moni, f_end_moni, "RX", debug)
nb_p = (nb_p_tx_wlan+nb_p_rx_wlan+nb_p_moni)/2 # data and acks are counted by moni0: divide by 2
if nBackoffCompute > 0:
busy = busy + 0.009*array_backoff_times_bianchi[nBackoffCompute-1]*nb_p #multiply by estimation of backoff time for number of transmitting STAs
busy = busy + nb_p*0.016 # one SIFS per packet transmission
busy = busy + nb_p*0.034 # one DIFS per packet transmission
if not debug:
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_beg_sur)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_end_sur)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_beg_wlan)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_end_wlan)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_beg_moni)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+name_end_moni)
return (float(busy)/total, nb_p)
def getAirtimePLC(self, interval=1, click=False):
if click:
# Note: should be in sniffer mode
self.handlerClick("write measurements_plc.init_airtime "+str(int(interval*1000)))
res = "not ready"
time.sleep(interval)
count = 0
while (res == False or "not ready" in res) and count < 5:
time.sleep(0.05)
res = self.handlerClick("read measurements_plc.get_airtime")
count += 1
if res == False:
return False
res = res.split('\r\n')
res = float(res[-1])
return res
else:
self.sendCommandAuto("echo 'a034 1' | faifa -i eth2 -m |grep 'System\|Direction\|MPDU\|Link ID\|STEI\|DTEI\|Direction\|frame length\|Delimiter\|Bit\|Multicast' | python parse_faifa_airtime.py > /root/airtime_faifa.tmp", blocking=False)
time.sleep(interval)
self.sendCommandAuto("killall faifa")
time.sleep(0.01)
line = ""
count = 0
busy_time_ms = -1
while line == "" and count <= 5:
f = open("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/airtime_faifa.tmp")
line = f.readline()
if line == "":
time.sleep(0.1)
else:
busy_time_ms = line.replace('\n','')
f.close()
count += 1
return float(busy_time_ms)
def getAverageIfstat(self, name_file="/root/ifstat.tmp", plc=False, debug=False):
if plc:
interface = "eth2"
else:
interface = "wlan0"
f = open("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+name_file,'r')
measurements_ifstat = []
for line in f:
line_split = line.split(' ')
line_split = [s for s in line_split if s != '']
if debug:
print(line_split)
if interface in line_split:
ind = 2*int(line_split.index(interface))
if debug:
print(ind)
if len(line_split) > ind and debug:
print(line_split[ind])
if len(line_split) > ind and '.' in line_split[ind]:
capa = float(line_split[ind])
if capa > 0:
measurements_ifstat.append(capa)
# remove beginning and end (traffic might not have begun or have stopped)
if len(measurements_ifstat) > 0:
measurements_ifstat.pop(0)
if len(measurements_ifstat) > 0:
measurements_ifstat.pop(0)
if len(measurements_ifstat) > 0:
measurements_ifstat.pop()
if len(measurements_ifstat) > 0:
measurements_ifstat.pop()
if len(measurements_ifstat) > 0:
return np.mean(measurements_ifstat)
else:
print("No ifstat measurement")
return 0
#bw is in B/s
def runRatedSource(self, ip, bw=10000000, length=1400, ether = True, limit = -1):
if self.handlerClick("write host/ipencap_ratedsrc.dst "+ip) == False:
return False
if ether:
if "10.10.10." in ip:
cmd_str = "write host/etherencap_ratedsrc.dst "+ _wlan0_mac[Node.getIndexFromIP(ip)]
elif "10.10.11." in ip:
cmd_str = "write host/etherencap_ratedsrc.dst "+ _eth2_mac[Node.getIndexFromIP(ip)]
if self.handlerClick(cmd_str) == False:
return False
if self.handlerClick("write host/rated_src.length "+str(length)) == False:
return False
rate = int(float(bw)/float(length))
if self.handlerClick("write host/rated_src.rate "+str(rate)) == False:
return False
if self.handlerClick("write host/rated_src.reset 1") == False:
return False
if self.handlerClick("write host/rated_src.limit "+str(limit)) == False:
return False
if self.handlerClick("write host/rated_src.active true") == False:
return False
def runAcneSource(self, ip, bw=0, length=1400, burst=1, mb = "mb", wifi=True, plc=True, mfl=False, static=False, host = "host", src="acne_src"):
if self.handlerClick("write "+host+"/ipencap_"+src+".dst "+ip) == False:
return False
if "10.10.11." in ip:
if self.handlerClick("write "+host+"/ipencap_"+src+".src "+self.getPLCIPStr()) == False:
return False
if self.handlerClick("write "+host+"/"+src+".length "+str(length)) == False:
return False
if mb != "":
if self.handlerClick("write "+mb+".set_burst "+str(burst)) == False:
return False
if static:
if plc: # static ethernet encapsulation
if self.handlerClick("write static_etherencap.dst "+_eth2_mac[Node.getIndexFromIP(ip)]) == False:
return False
else:
if self.handlerClick("write static_etherencap.dst "+_wlan0_mac[Node.getIndexFromIP(ip)]) == False:
return False
if bw > 0:
if self.handlerClick("write "+host+"/"+src+".set_rate "+str(bw)) == False:
return False
if mfl:
if wifi == True:
self.handlerClick("write mfl_wifi.limit_rate 0")
if plc == True:
self.handlerClick("write mfl_plc.limit_rate 0")
if self.handlerClick("write "+host+"/"+src+".active 1") == False:
return False
return True
def runIperfSource(self, ip, bw=0, length=1400, burst=1, mb = "mb", wifi=True, plc=True, mfl=False, static=False, duration=10, tcp=False, log="iperf.log", window="1M", tcp_cc="scalable", style=1): # alias for backward compatibilitu
return self.runIperfSourceClick(ip,bw,length,burst,mb,wifi,plc,mfl,static,duration,tcp,log,window,tcp_cc,style)
def runIperfSourceClick(self, ip, bw=0, length=1400, burst=1, mb = "mb", wifi=True, plc=True, mfl=False, static=False, duration=10, tcp=False, log="iperf.log", window="1M", tcp_cc="scalable", style=1):
bw = bw*8 #bps to B/s
if mb != "":
if self.handlerClick("write "+mb+".set_burst "+str(burst)) == False:
return False
if static:
if plc: # static ethernet encapsulation
if self.handlerClick("write static_etherencap.dst "+_eth2_mac[Node.getIndexFromIP(ip)]) == False:
return False
if self.handlerClick("write sendQueue_plc.capacity "+str(burst+10)) == False:
return False
else:
if self.handlerClick("write static_etherencap.dst "+_wlan0_mac[Node.getIndexFromIP(ip)]) == False:
return False
if self.handlerClick("write sendQueue_wifi.capacity "+str(burst+10)) == False:
return False
if bw > 0:
if mfl:
if wifi == True:
self.handlerClick("write mfl_wifi.limit_rate 0")
if plc == True:
self.handlerClick("write mfl_plc.limit_rate 0")
Node(Node.getIndexFromIP(ip)).sendCommandAuto("killall iperf")
time.sleep(0.5)
Node(Node.getIndexFromIP(ip)).launchIperfServer(size=length, tcp=tcp, logfile=log, window=window, style=style)
self.sendCommandAuto("killall iperf")
time.sleep(0.5)
self.launchIperfClient(ip,packetsize=length,load=str(bw), duration=duration, tcp=tcp, window=window, tcp_cc=tcp_cc, logfile=log)
return True
def stopSources(self, only="", host="host"):
if only != "rated" and only != "acne" and only != "acne2":
if self.handlerClick("write "+host+"/infsrc.active false") == False:
return False
if only != "inf" and only != "acne" and only != "acne2":
if self.handlerClick("write "+host+"/rated_src.active false") == False:
return False
if only != "rated" and only != "inf" and only != "acne2":
if self.handlerClick("write "+host+"/acne_src.active 0") == False:
return False
if only != "rated" and only != "inf" and only != "acne":
if self.handlerClick("write "+host+"/acne_src2.active 0") == False:
return False
def stopSource(self, src, host="host"):
if "acne" in src:
act_s = "0"
else:
act_s = "false"
if self.handlerClick("write "+host+"/"+src+".active "+act_s) == False:
return False
def stopAcneSource(self, restore_limit_rate=False):
if restore_limit_rate:
self.handlerClick("write mfl_wifi.limit_rate 1")
self.handlerClick("write mfl_plc.limit_rate 1")
if self.handlerClick("write host/acne_src.active 0") == False:
return False
def setMabDebug(self, debug, verb_debug=False):
if debug:
deb_s = '1'
else:
deb_s = '0'
self.handlerClick("write src_mab.debug "+deb_s)
self.handlerClick("write update_ack_mab.debug "+deb_s)
self.handlerClick("write dst_mab.debug "+deb_s)
self.handlerClick("write measurements_plc.debug "+deb_s)
self.handlerClick("write measurements_wifi.debug "+deb_s)
self.handlerClick("write mb_plc.debug "+deb_s)
self.handlerClick("write mb_wifi.debug "+deb_s)
self.handlerClick("write order.debug "+deb_s)
self.handlerClick("write td_plc.debug "+deb_s)
self.handlerClick("write td_wifi.debug "+deb_s)
self.handlerClick("write mb_plc_pr.active "+deb_s)
self.handlerClick("write mb_wifi_pr.active "+deb_s)
self.handlerClick("write mb_plc_traffic_pr.active "+deb_s)
self.handlerClick("write mb_wifi_traffic_pr.active "+deb_s)
self.handlerClick("write mb_timeout_plc_pr.active "+deb_s)
self.handlerClick("write mb_timeout_wifi_pr.active "+deb_s)
self.handlerClick("write plc_pr.active "+deb_s)
self.handlerClick("write wifi_pr.active "+deb_s)
self.handlerClick("write fd_plc_pr.active "+deb_s)
self.handlerClick("write fd_wifi_pr.active "+deb_s)
self.handlerClick("write mb_timeout_plc.print_stats "+deb_s)
self.handlerClick("write mb_timeout_wifi.print_stats "+deb_s)
self.handlerClick("write host/tcp_analyzer.active "+deb_s)
if verb_debug:
self.handlerClick("write src_mab.verb_debug "+deb_s)
def getNrArms(self):
output = self.handlerClick("read src_mab.nr_arms",trim=True)
if output == False:
return False
return int(output)
def getMeasuredCapa(self, reset = False):
output = self.handlerClick("read avcount.byte_rate")
if reset:
print(self.handlerClick("write avcount.reset 1"))
if output == False:
return False
else:
capa = output.split("\r\n")[-1]
if len(capa) == 0:
return False
return float(capa)
def resetCapacitiesInt6k(self):
self.sendCommandAuto("int6krate -i eth2 -R")
def getCapacitiesInt6k(self, debug_bool=False):
file_node = "int6krate_output.log"
self.sendCommandAuto("int6krate -i eth2 > /root/"+file_node, debug=debug_bool, blocking=True)
file_serv = "/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+"/root/"+file_node
f = open(file_serv, 'r')
capas = {}
for line in f:
line_split = line.split(' ')
if line_split[0] == "eth2" and line_split[3] == "TX":
capas[line_split[2]] = int(line_split[4])
if len(capas) == 0:
print("Warning: no neighbor found")
os.remove(file_serv)
return capas
def getLinkEstCapacity(self, dst, interface="wifi", debug=False):
if interface == "wifi":
addr = "/sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/"+dst.getMACWifi().lower()
output = self.sendCommandAuto("cat "+addr+"/rc_stats")
if output == False:
return False
lines = output.split("\n")
total_success = 0
total_thr = 0
for line in lines:
if "MCS" in line:
tokens = line.split(" ")
tokens = [s for s in tokens if s!='']
if "MCS" not in tokens[-9]:
print("Error with line", line)
return False
if debug:
print(tokens)
thr = float(tokens[-8])
success = int(tokens[-2])
total_success+=success
total_thr+=(thr*success)
if total_success == 0:
return 0
return total_thr/total_success
elif interface == "plc":
mac2_addr = dst.getMAC2PLC()
output = self.sendCommandAuto("int6krate -i eth2 |grep \""+mac2_addr+" TX\"", debug=debug)
if output == False:
return False
tokens = output.split(" ")
if len(tokens) < 5:
print("Error with output", output)
return False
ble = int(tokens[4])
if ble == 9: # 9 is default rate, when no traffic sent
return 0
return float(ble)/1.7 # PHY-layer to MAC-layer throughput
def update_link_capacities(self, interface, method, nodes):
neighbors = [n for n in nodes if (n.getIndex() != -1 and n!=self and self.checkPingConnectivity(n,interface))]
link_capacities = {}
print(("Has "+str(len(neighbors))+" neighbors"))
if method == "low":
meas_dur=20
count=0
for n in neighbors:
# run low overhead traffic
count += 1
n.launchIperfServer(port=6000+count,logfile="")
if interface == "wifi":
ip = n.getWifiIPStr()
elif interface == "plc":
ip = n.getPLCIPStr()
self.launchIperfClient(ip,port=6000+count,logfile="",load="100k",duration=meas_dur,block=False)
time.sleep(meas_dur)
for n in neighbors:
n.sendCommandAuto("killall iperf", blocking=False)
for n in neighbors:
link = str(self.getIndex())+interface[0]+" "+str(n.getIndex())+interface[0]
est_cap = self.getLinkEstCapacity(n, interface)
if est_cap:
link_capacities[link] = est_cap
elif method == "saturated":
meas_dur = 10
meas_dur_test = 10 # run traffic before measuring
for n in neighbors:
link = str(self.getIndex())+interface[0]+" "+str(n.getIndex())+interface[0]
est_cap = self.getIperfCapacity(n, interface=interface, dur=meas_dur, dur_test=meas_dur_test)
if est_cap:
link_capacities[link] = est_cap
return link_capacities
# def getMeasuredCapa(self, interface="wifi"):
# if interface == "wifi":
# output = self.handlerClick("read final_pr_wifi.print_info")
# elif interface == "plc":
# output = self.handlerClick("read final_pr_plc.print_info")
# if output == False:
# return False
# split_str = output.split("\n")
# if len(split_str) < 4:
# return False
# stats_line = split_str[3]
# ind_rate = stats_line.find("Rate=")
# if ind_rate==-1:
# return 0
# ind_rate = ind_rate+5
# ind_end_rate = stats_line.find(" ",ind_rate)
# capa = int(stats_line[ind_rate:ind_end_rate])
# return capa
def resetCounterCapa(self, plc = True):
if self.handlerClick("write avcount.reset 1") == False:
return False
#if self.handlerClick("write final_pr_wifi.reset 1") == False:
# return False
#if plc == True and self.getMACPLC() != "" and self.handlerClick("write final_pr_plc.reset 1") == False:
# return False
def getRoute(self, route):
output = self.handlerClick("write rtp.get_route "+route)
if output == False:
return False
def getAndPrintRoute(self,route,wifi_only=False,plc_only=False):
if wifi_only:
self.getRouteWifi(route)
elif plc_only:
self.getRoutePLC(route)
else:
self.getRoute(route)
output = self.printRoutes(return_routes=True)
ip = route.split('/')[0]
if ip not in output:
return False
res = ""
save=False
for line in output.split('\n'):
if save and ("Route to" in line or "Multipaths to" in line):
print(res)
return
if ip in line or save:
res=res+line+"\n"
save=True
print(res)
def getRouteWifi(self, route):
output = self.handlerClick("write rtp.get_route_wifi "+route)
if output == False:
return False
def getRoutePLC(self, route):
output = self.handlerClick("write rtp.get_route_plc "+route)
if output == False:
return False
def resetRtp(self):
self.handlerClick("write rtp.reset 1")
def contendingLinks(self,link):
self.handlerClick("write rtl.get_contending_links "+link)
output = self.handlerClick("read rtl.print_contending_links")
lines_out = output.split('\n')
if len(lines_out) > 2:
links = lines_out[2]
else:
return []
return links.split(" ")
def printNetwork(self):
output = self.handlerClick("read rtl.print_network")
if output == False:
return False
else:
print(output)
def printRoutes(self,return_routes=False):
output = self.handlerClick("read rtp.print_routes")
if output == False:
return False
else:
if return_routes:
return output
else:
print(output)
def getMultipathsDst(self, dst, wifi_ip=True, quick=False, debug=False):
if not type(dst) is int:
print("Should give index of node as argument")
return []
if wifi_ip:
output = self.handlerClick("read rtp.print_routes", quick=quick)
if output == False:
print("Error while getting routes")
return []
ip = Node.staticIPStr(dst)
tokens = output.split('\n')
i_src = -1
for i, line in enumerate(tokens):
if ip in line:
if debug:
print("Got IP "+ip+" at position "+str(i))
i_src = i
break
multipaths = []
multipath = []
if i_src >= 0 and i_src < len(tokens):
for i in range(i_src+1, len(tokens)):
if "Route" in tokens[i] or "Multipaths" in tokens[i]:
break
if '-----------' in tokens[i]:
if debug:
print("Adding multipath", multipath)
multipaths.append(multipath)
multipath = []
continue
route = tokens[i]
route = route.replace(' ', '')
route = route.replace('(', ';')
route = route.replace(')', ';')
route = route.replace('->', ';')
route_tok = route.split(';')
route = []
for elmt in route_tok:
if '-' in elmt and elmt not in route:
route.append(elmt)
multipath.append(route)
else:
print("No line in file or ip not found (i="+str(i)+")")
return multipaths
def printNeighbors(self):
output = self.handlerClick("read neighbors.print_info")
if output == False:
return False
else:
print(output)
def printCapaWifi(self):
output = self.handlerClick("read final_pr_wifi.print_info")
if output == False:
return False
else:
print(output)
def printCapaPLC(self):
output = self.handlerClick("read final_pr_plc.print_info")
if output == False:
return False
else:
print(output)
def printMfl(self):
output = self.handlerClick("read mfl_wifi.print_info")
if output == False:
return False
else:
print(output)
if self.getMACPLC() != "":
output = self.handlerClick("read mfl_plc.print_info")
if output == False:
return False
else:
print(output)
def printParametersCC(self):
output = self.handlerClick("read price_plc.parameters")
print(output)
output = self.handlerClick("read price_wifi.parameters")
print(output)
output = self.handlerClick("read cc.parameters")
print(output)
def setAlphaPrice(self, alpha=0, delta=0):
if alpha > 0:
output = self.handlerClick("write price_plc.alpha "+str(alpha))
print(output)
output = self.handlerClick("write price_wifi.alpha "+str(alpha))
print(output)
if delta > 0:
output = self.handlerClick("write price_plc.delta "+str(delta))
print(output)
output = self.handlerClick("write price_wifi.delta "+str(delta))
print(output)
def setAlphaCc(self, alpha=0, delta=0):
if alpha > 0:
output = self.handlerClick("write cc.alpha "+str(alpha))
print(output)
if delta > 0:
output = self.handlerClick("write cc.delta "+str(delta))
print(output)
def setAlpha(self, alpha=0,alpha_cc=0, delta=0):
self.setAlphaPrice(alpha,delta)
if alpha_cc > 0:
self.setAlphaCc(alpha_cc,delta)
else:
self.setAlphaCc(alpha,delta)
def setAlphaBetaCC(self, beta, alpha=0.1):
output = self.handlerClick("write cc.beta "+str(beta))
print(output)
output = self.handlerClick("write cc.alpha "+str(alpha))
print(output)
def resetRates(self):
output = self.handlerClick("write cc.reset_rates 1")
print(output)
output = self.handlerClick("write price_plc.reset_price 1")
print(output)
output = self.handlerClick("write price_wifi.reset_price 1")
print(output)
def setDebugAllElmts(self, b):
if b:
s='1'
else:
s='0'
output = self.handlerClick("write cc.debug "+s)
print(output)
output = self.handlerClick("write rtp.debug "+s)
print(output)
output = self.handlerClick("write rtl.debug "+s)
print(output)
output = self.handlerClick("write forwarder_own.debug "+s)
print(output)
output = self.handlerClick("write mfl_wifi.debug "+s)
print(output)
output = self.handlerClick("write mfl_plc.debug "+s)
print(output)
output = self.handlerClick("write order.debug "+s)
print(output)
output = self.handlerClick("write price_wifi.debug "+s)
print(output)
output = self.handlerClick("write price_plc.debug "+s)
print(output)
output = self.handlerClick("write neighbors.debug "+s)
print(output)
def setPrintUpdatesNeighbors(self):
output = self.handlerClick("write neighbors.print_updates 1")
return output
def setNumberRoutes(self, n):
output = self.handlerClick("write cc.nr_routes "+str(n))
print(output)
def getCounterRate(self, counter_name):
output = self.handlerClick("read "+counter_name+".rate")
if not output:
return float("inf")
tokens = output.split("\r\n")
try:
rate = float(tokens[-1])
except ValueError as e:
print("Error while getting length with output", output)
return float("inf")
return rate
def getQueueLength(self, queue_name):
output = self.handlerClick("read "+queue_name+".length")
if not output:
return float("inf")
tokens = output.split("\r\n")
try:
length = int(tokens[-1])
except ValueError as e:
print("Error while getting length with output", output)
return float("inf")
return length
def handlerClick(self, command, trim=False, quick=True, output=True, debug=False, force_userlevel=True):
if force_userlevel:
userlevel = True
else:
output_ls = self.sendCommandAuto("ls /click")
userlevel = output_ls == None or output_ls == False or len(output_ls) == 0
if userlevel:
output_b = output
if self.tn == 0:
count = 0
while count < 5:
try:
self.tn = Telnet(self.getWiredIPStr(), 5983, 0.1)
except socket.error as e:
count += 1
print("Error #", count, "while sending command", command,"and opening socket to", self.getWiredIPStr() ,":", e)
self.tn = 0
time.sleep(0.1)
if self.tn != 0:
if debug:
print("Opened telnet connection")
break
time.sleep(0.01)
if self.tn == 0:
print("Couldn't open socket.")
return False
if command == "": #only to open connection
return
output = ""
try:
str_cmd = command + '\n'
count = 0
if debug:
print("Send telnet command", str_cmd)
self.tn.read_very_eager() # in case some output has not been read
while count < 3:
count = count + 1
self.tn.write(str_cmd)
if not output_b:
return
count_output = 0
while count_output < 5:
count_output += 1
if quick:
time.sleep(0.001*count_output)
else:
time.sleep(0.05)
output = self.tn.read_very_eager()
if output.find("OK") >= 0:
if debug:
print("Command successful after", count_output, "tries")
break
if output.find("OK") >= 0:
break
elif debug:
print("Command failed after", count_output, "tries")
except socket.error as e:
if output_b:
print("Socket error:", e)
self.tn = 0
return self.handlerClick(command, trim, quick, output)
except EOFError as e:
if output_b:
print("EOFError:", e)
self.tn = 0
return self.handlerClick(command, trim, quick, output)
if output.find("OK") == -1:
if output_b:
print("Incorrect output at node "+str(self.getIndex())+": ", output, "for command:", command)
return False
if debug:
print("Command successfully sent")
if trim:
output = output.replace('\r\n', ' ')
output = output[output.find(' ',output.rfind("DATA")+5)+1:]
if output == '':
output = 'None'
return output
else:
if self.cmd_client == False:
print("In kernel module, works only with direct commands")
return False
split_cmd = command.split(' ')
if len(split_cmd) < 2:
print("Incorrect command", command, "(at least 2 arguments)")
return False
split_handler = split_cmd[1].split('.')
if len(split_handler) < 2:
print("Incorrect command", command, "(element.handler incorrect)")
return False
name_elmt = split_handler[0]
name_handler = split_handler[1]
if split_cmd[0] == "read":
output = self.sendDirectCommand("cat /click/"+name_elmt+"/"+name_handler, debug=debug)
if output == False:
print("Error while running cat /click/"+name_elmt+"/"+name_handler)
return False
return output
elif split_cmd[0] == "write":
if len(split_cmd) < 3:
print("Incorrect command", command, "(if write, 3 arguments)")
return False
split_handler = split_cmd[1].split('.')
name_elmt = split_handler[0]
name_handler = split_handler[1]
path_handler = "/click/"+name_elmt+"/"+name_handler
out_ls = self.sendDirectCommand("ls "+path_handler, debug=debug)
if out_ls == False:
print("Incorrect command", command, "(no file "+path_handler+")")
return False
out_ls = out_ls.replace('\n', '')
if out_ls != path_handler:
print("Incorrect command", command, "(no file "+path_handler+", returned "+out_ls+")")
return False
self.sendCommandAuto("echo "+split_cmd[2]+" > "+path_handler, blocking=False, debug=debug)
else:
print("Incorrect command", command, "(must be read or write)")
return False
def sendCommandTelnet(self, command, trim=False, quick=True, output=True): #alias for compatibiliy
return self.handlerClick(command, trim, quick, output)
def sendCommandAuto(self, cmdStr, blocking=True, prependPath=True, debug=False, count_try=0, timeout=0.5, check_open=False, verb_debug=False):
# This method automatically selects whether to send the command directly or over ssh
if self.cmd_client == True:
# check that socket correctly opened
if check_open:
if self.sendDirectCommand("ps w|grep python") == False:
self.unsetDirectCommands()
self.setDirectCommands()
if count_try==0:
print(self.toString(), "could not send direct command", cmdStr,"; retrying...")
time.sleep(0.1)
return self.sendCommandAuto(cmdStr, blocking, prependPath, debug, 1)
else:
print(self.toString(), "could not send direct command", cmdStr,";failure...")
return False
if debug:
print('Send direct command, blocking=', str(blocking))
return self.sendDirectCommand(cmdStr, blocking, debug, timeout=timeout, verb_debug=verb_debug)
else:
if blocking:
return self.sendCommandBlocking(cmdStr, prependPath, debug=debug)
else:
self.sendCommandNonBlocking(cmdStr, prependPath, debug=debug)
def sendDirectCommand(self, cmdStr, blocking=True, debug=False, timeout=0.5, verb_debug=False):
if verb_debug:
t_test = time.time()
UDP_PORT = self.sock_index - self.index
#If blocking, prepend 'b', otherwise, prepend 'n'
str_to_send = ("b" if blocking else "n")+cmdStr
if debug:
print("about to send direct command : "+str_to_send+" to node",self.index, "with timeout", timeout)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet, UDP
sock.sendto(str_to_send, (self.getWiredIPStr(), UDP_PORT))
if verb_debug:
print("Sent in", time.time() - t_test, "seconds")
t_test = time.time()
if blocking:
#We get a reply only for blocking commands
length_data = 128 #if change here, must change cmd-client.py
output = ""
try:
self.sock_server.settimeout(timeout)
if verb_debug:
print("Set timeout in", time.time() - t_test, "seconds")
t_test = time.time()
out = self.sock_server.recv(length_data)
if verb_debug:
print("Recv in", time.time() - t_test, "seconds")
t_test = time.time()
if out != "end"+str(self.sock_index):
output = out
while True and out!="end"+str(self.sock_index):
out = self.sock_server.recv(length_data)
if out == "end"+str(self.sock_index):
break;
output = output+out
if verb_debug:
print("Received in", time.time() - t_test, "seconds")
t_test = time.time()
if output == "1000":
out = self.sock_server.recv(length_data)
if debug:
print("couldn't launch command "+cmdStr+", at node "+str(self.index)+", return code "+out+".")
return False
else:
if debug:
print("command "+cmdStr+", at node "+str(self.index)+" returned ")
print(output)
if verb_debug:
print("Done in", time.time() - t_test, "seconds")
return output
except socket.timeout:
if debug:
print("Timeout, got", output, "for cmd", cmdStr)
return False
return 0
def sendCommandBlocking(self, cmdStr, prependPath=True, debug=False):
#cmdStr should already contain the arguments, if any
tmpfile = cmdStr.split(" ")[0].replace("/","")+".tmp"
cmdStr = cmdStr + " > /root/tmp/"+tmpfile+" ; echo END_OF_FILE >> /root/tmp/"+tmpfile # to get output, write in file
if debug:
print("Send command blocking", cmdStr, "for", self)
if prependPath == True:
os.spawnlp(os.P_WAIT, 'ssh', 'ssh', 'root@'+self.toString(), "PATH=/sbin:/usr/sbin:$PATH "+cmdStr)
else:
os.spawnlp(os.P_WAIT, 'ssh', 'ssh', 'root@'+self.toString(), cmdStr)
count = 0
# to read output, get on server (requires waiting that it has been flushed, this is quite ugly...)
while not os.path.exists("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+str(self)+"/root/tmp/"+tmpfile):
time.sleep(0.001)
count += 1
if count == 10:
if debug:
print("count = 10, could not get output")
return False
count = 0
output = []
if debug:
print("Opening /opt/aziala/deploy/pxe-nfs-setup/filesystems/"+str(self)+"/root/tmp/"+tmpfile)
while "END_OF_FILE" not in output:
time.sleep(0.001)
f = open("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+str(self)+"/root/tmp/"+tmpfile, "r")
output = f.read()
count += 1
if count == 100: # stop after 100ms in case something went wrong
if debug:
print("count = 100, could not get output")
return False
ind = output.index("END_OF_FILE")
output = output[:ind]
if debug:
print("Output is", output)
os.remove("/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+str(self)+"/root/tmp/"+tmpfile)
return output
def sendCommandNonBlocking(self, cmdStr, prependPath=True, debug=False):
#cmdStr should already contain the arguments, if any
if debug:
print("Send command non-blocking", cmdStr, "&")
if prependPath == True:
os.spawnlp(os.P_WAIT, 'ssh', 'ssh', 'root@'+self.toString(), "PATH=/sbin:/usr/sbin:$PATH "+cmdStr+" &");
else:
os.spawnlp(os.P_WAIT, 'ssh', 'ssh', 'root@'+self.toString(), cmdStr+" &");
def launchTcpDump(self, cmdStr):
#Tcpdump requires to be launched in a separate thread
_thread.start_new_thread(os.spawnlp, (os.P_WAIT, 'ssh', 'ssh', 'root@'+self.toString(), "PATH=/sbin:/usr/sbin:$PATH "+cmdStr));
def setChannelDebugfs(self, newChan):
self.sendCommandAuto("echo "+str(newChan)+" > /sys/kernel/debug/ieee80211/phy0/ath9k/chan");
time.sleep(5)
def setWidthDebugfs(self, newWidth):
self.sendCommandAuto("echo "+str(newWidth)+" > /sys/kernel/debug/ieee80211/phy0/ath9k/chanbw");
time.sleep(5)
def getPLCIPStr(self):
#PLC IP Address
if self.index == 0:
return "10.10.11.100"
return "10.10.11."+str(self.index)
def getWifi2IPStr(self):
#wlan1 IP Address
if self.index == 0:
return "10.10.12.100"
return "10.10.12."+str(self.index)
def getIPStr(self,wifi=True):
if not wifi:
return self.getPLCIPStr()
#WiFi IP Address
if self.index == 0:
return "10.10.10.100"
return "10.10.10."+str(self.index)
# alias
def getWifiIPStr(self):
return self.getIPStr()
def getMACWifi(self, dash=False):
eth = _wlan0_mac[self.index]
if dash:
eth=eth.replace(':','-')
return eth
def getMACPLC(self, dash=False):
eth = _eth2_mac[self.index]
if dash:
eth=eth.replace(':','-')
return eth
def getMACWifi2(self, dash=False):
eth = _wlan1_mac[self.index]
if dash:
eth=eth.replace(':','-')
return eth
def getMAC2PLC(self, dash=False):
eth = _eth2_mac2[self.index]
if dash:
eth=eth.replace(':','-')
return eth
def getWiredIPStr(self):
if self.index == 0:
return "192.168.61.100"
return "192.168.61.1"+("0" if self.index < 10 else "")+str(self.index)
def launchIfstat(self, logfile, interface, duration, measure_100ms = True):
if measure_100ms:
# measurements every 100 ms
self.sendCommandNonBlocking("ifstat -i "+interface+" -n -b -q 0.1 "+str(10*duration)+" > "+logfile)
else:
# measurements every 1 s
print("command, " "ifstat -i "+interface+" -n -b "+str(duration)+" > "+logfile)
self.sendCommandNonBlocking("ifstat -i "+interface+" -n -b -q 1 "+str(duration)+" | grep '.' > "+logfile)
def deactivateFaifaSnifferMode(self, kill=True):
#ssh = Popen(["ssh", "root@"+self.toString(), "PATH=/sbin:/usr/sbin:$PATH faifa -m -i eth2"],shell=False,
# stdin=PIPE, stdout=PIPE)
#ssh.stdin.write('a034')
#ssh.stdin.write('00')
#time.sleep(5)
#ssh.kill()
self.sendCommandAuto("echo 'a034 0' | faifa -i eth2 -m",blocking=False)
if kill:
time.sleep(1)
self.sendCommandAuto("killall faifa",blocking=True)
def activateFaifaSnifferMode(self, kill=False):
#ssh = Popen(["ssh", "root@"+self.toString(), "PATH=/sbin:/usr/sbin:$PATH faifa -m -i eth2"],shell=False,
# stdin=PIPE, stdout=PIPE)
#ssh.stdin.write('a034')
#ssh.stdin.write('01')
#time.sleep(5)
#ssh.kill()
#self.sendCommandAuto("killall faifa", blocking=True)
#time.sleep(0.1)
self.sendCommandAuto("echo 'a034 1' | faifa -i eth2 -m 1> /dev/null 2> faifa_err.log",blocking=False)
if kill:
time.sleep(0.1)
self.sendCommandAuto("killall faifa")
def launchFaifa(self,logfile="/root/faifa", macIds=True):
print("Starting faifa at", self.toString(), "with logfile", logfile)
#self.activateFaifaSnifferMode()
if macIds:
self.sendCommandAuto("int6k -i eth2 -m > "+logfile+"_macIds.log", blocking=False)
self.sendCommandNonBlocking("echo 'a034 1' | faifa -i eth2 -m |grep 'System\|Direction\|MPDU\|Link ID\|STEI\|DTEI\|Direction\|frame length\|Delimiter\|Bit\|Multicast' > "+logfile+".log")
def killFaifa(self):
self.deactivateFaifaSnifferMode()
time.sleep(0.5)
self.sendCommandAuto("killall faifa",blocking=True)
def requestPLCErrorStats(self,fornode,logfile="",priority=1,direction=0,append=False,block=False):
returnStats= False
if logfile == "":
returnStats = True
logfile = "/root/plc-stats.log"
if block:
if direction == 0:
self.sendCommandAuto("ampstat -i eth2 -d "+str(direction) +" -s " +str(priority) + " -p "+_eth2_mac[fornode]+"| grep \"TX\" | tr -s ' ' | cut -d\" \" -f5 | cut -d% -f1 "+(">> " if append else "> ")+logfile,blocking=False)
else:
self.sendCommandAuto("ampstat -i eth2 -d "+str(direction) +" -s " +str(priority) + " -p "+_eth2_mac[fornode]+"| grep \"%\" "+(">> " if append else "> ")+logfile,blocking=False)
else:
self.sendCommandAuto("ampstat -i eth2 -d "+str(direction) +" -s " +str(priority) + " -v -p "+_eth2_mac[fornode]+(" >> " if append else " > ") + logfile,blocking=returnStats)
if returnStats:
file_serv = "/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+logfile
f = open(file_serv, 'r')
pberr = -1
for line in f:
line_split = line.split(' ')
line_split = [s for s in line_split if s != '' and s != '\n']
if len(line_split) > 0 and line_split[0] == "TX":
pberr = float(line_split[3][0:(len(line_split[3])-1)])
break
return pberr
def resetPLCErrorStats(self,fornode,priority=1,direction=0):
#print "reseting plc stats priority", str(priority)
self.sendCommandAuto("ampstat -i eth2 -C -d "+str(direction) +" -s " +str(priority) + " -p "+_eth2_mac[fornode],blocking=False)
def getToneMapChar(self,fornode,logfile="",append=False,block=False):
returnTones = False
if logfile == "":
returnTones = True
logfile = "/root/tonemap.log"
if block:
self.sendCommandAuto("int6ktone -i eth2 local "+ _eth2_mac[fornode] + " -s " + "| grep \"BPC\" | cut -d\" \" -f6,10,14,18,22,26,30 " + (">> " if append else "> ")+logfile,blocking=False)
else:
self.sendCommandAuto("int6ktone -i eth2 local "+ _eth2_mac[fornode] +" -s "+(">> " if append else "> ")+logfile,blocking=returnTones)
if returnTones:
file_serv = "/opt/aziala/deploy/pxe-nfs-setup/filesystems/"+self.toString()+logfile
f = open(file_serv, 'r')
tones = []
for line in f:
line_split = line.split(' ')
line_split = [s for s in line_split if s != '' and s != '\n']
if line_split[0] == "BPC":
for i in range(1,len(line_split)):
tones.append(float(line_split[i]))
os.remove(file_serv)
return tones
@staticmethod
def computeAverageTonemaps(tonemaps):
if tonemaps == False:
return []
arr_tm = np.array([tonemaps[k] for k in tonemaps])
if arr_tm.ndim != 2 or arr_tm.shape[1] != 6:
print("Error in tonemaps")
return []
return np.mean(arr_tm,axis=0)
def getAllToneMaps(self,node_dst, non_zero=True, debug=False, cmd = "int6ktone"):
# returns a dictionary of 6-integer arrays that represents the tone maps
if cmd == "int6ktone":
command = "int6ktone -i eth2 "+_eth2_mac2[node_dst.getIndex()]+" "+_eth2_mac2[self.getIndex()]
elif cmd == "amptone":
command = "amptone -i eth2 local "+_eth2_mac2[node_dst.getIndex()]+" -s"
else:
print("Unsupported command")
return
if debug:
print(command)
out = self.sendCommandAuto(command)
if out == False or len(out) == 0:
return False
tonemaps = out.split("\n")
all_tm = {}
for tm in tonemaps:
if "SNR" in tm:
continue
if cmd == "int6ktone":
tm_arr = tm.strip().split(" ")
elif cmd == "amptone":
tm_arr = tm.strip().split(",")
try:
ind_tm = int(tm_arr[0])
except ValueError:
if debug:
print(("Error while parsing array "+(" ".join(tm_arr))))
continue
if ind_tm > 1154: # number of subcarriers
break
try:
tms = list(map(int,tm_arr[1:]))
except ValueError:
if debug:
print(("Error while parsing array "+(" ".join(tm_arr))))
continue
if len(tms) != 6:
print("WARNING: does not have 6 tonemaps")
print(tms)
return False
if sum(tms) > 0 or not non_zero:
all_tm[ind_tm] = tms
return all_tm
def requestToneMap(self,fornode,log_map_file,duration,map_interval,t,activate_faifa = 2):
if t == 0:
self.ssh = Popen(["ssh root@"+self.toString()+" 'faifa -m -i eth2 | grep \"Modulation for carrier\|Number of tone map\" | cut -d: -f2,3' >> "+log_map_file],shell=True,stdin=PIPE)
print("New Request by Node #"+str(self.index)+" for "+_eth2_mac[fornode])
if activate_faifa == 2:
self.ssh.stdin.write("a070 "+_eth2_mac[fornode]+" 0 ")
elif activate_faifa == 0:
print("Deactivating Now")
self.ssh.stdin.write("a034 0 a070 "+_eth2_mac[fornode]+" 0 ")
elif activate_faifa == 1:
print("Activating Now")
self.ssh.stdin.write("a034 1 a070 "+_eth2_mac[fornode]+" 0 ")
@staticmethod
def getDictFromRecvOutput(output):
if output == False:
return {}
tokens = output.split("\n")
d = {}
for token in tokens:
tok = token.strip()
tok = tok.split(":")
if len(tok) != 2:
continue
try:
d[tok[0].strip()] = int(tok[1].strip())
except Exception:
print(("Error with line "+token))
return d
@staticmethod
def getRecvStatsNodes(nodes, duration=1, debug=False):
dict_init = {node: Node.getDictFromRecvOutput(node.sendCommandAuto("cat /sys/kernel/debug/ieee80211/phy0/ath9k/recv", blocking = True)) for node in nodes}
time.sleep(duration)
dict_end = {node: Node.getDictFromRecvOutput(node.sendCommandAuto("cat /sys/kernel/debug/ieee80211/phy0/ath9k/recv", blocking = True)) for node in nodes}
dict_diff = {}
for node in nodes:
dict_diff[node] = {}
for key in dict_end[node]:
if key not in dict_init[node]:
print(("Problem with key "+key+", not in dict_init"))
dict_diff[node][key] = dict_end[node][key] - dict_init[node][key]
return dict_diff
def getRecvStats(self, duration=1, debug=False):
return Node.getRecvStatsNodes([self],duration,debug)

Event Timeline