Cleaning up.

This commit is contained in:
Tolja Zubow 2016-09-27 13:45:20 +02:00
parent 1ef9c2bf54
commit d3cec1182f
2 changed files with 305 additions and 160 deletions

View File

@ -0,0 +1,92 @@
import logging
import time
from hmac_python_wrapper import HybridTDMACSMAMac, AccessPolicy
__author__ = "Sven Zehl, Anatolij Zubow"
__copyright__ = "Copyright (c) 2016, Technische Universität Berlin"
__version__ = "1.0.0"
__email__ = "{zehl, zubow}@tkn.tu-berlin.de"
if __name__ == "__main__":
''' Example script
Create a HMAC configuration with:
- 10 time slots per superframe
- a slot duration of 20000 microseonds (20 ms)
- for wireless interface wlan0
- two configurations are used:
- A. the first 4 time slots can be used by any best effort traffic towards STA with MAC address 34:13:e8:24:77:be
- A. the last 6 time slots are guard time slots, i.e. blocked from being used
- B. time slots 5-8 can be used by any best effort traffic towards STA with MAC address 34:13:e8:24:77:be
- B. the other time slots are guard time slots, i.e. blocked from being used
'''
log = logging.getLogger("HMAC.Example")
# configuration of hybrid MAC
dstHWAddr = "34:13:e8:24:77:be" # STA destination MAC address
total_slots = 10
slot_duration = 20000
iface = 'wlan0'
# create new MAC for local node
mac = HybridTDMACSMAMac(no_slots_in_superframe=total_slots, slot_duration_ns=slot_duration)
be_slots = [1,2,3,4]
# assign access policies to each slot in superframe
for slot_nr in range(total_slots):
if slot_nr in be_slots:
# those are slots for best effort traffic towards our STA
acBE = AccessPolicy()
acBE.addDestMacAndTosValues(dstHWAddr, 0)
mac.setAccessPolicy(slot_nr, acBE)
else:
# those are guard slots
acGuard = AccessPolicy()
acGuard.disableAll() # guard slot
mac.setAccessPolicy(slot_nr, acGuard)
# install MAC Processor
if mac.install_mac_processor():
log.info('HMAC is running ...')
log.info('HMAC conf: %s' % mac.printConfiguration())
# wait 10 seconds
time.sleep(10)
log.info('Update HMAC with new configuration ...')
# new configuration
be_slots = [5,6,7,8]
# assign access policies to each slot in superframe
for slot_nr in range(total_slots):
if slot_nr in be_slots:
# those are slots for best effort traffic towards our STA
acBE = AccessPolicy()
acBE.addDestMacAndTosValues(dstHWAddr, 0)
mac.setAccessPolicy(slot_nr, acBE)
else:
# those are guard slots
acGuard = AccessPolicy()
acGuard.disableAll() # guard slot
mac.setAccessPolicy(slot_nr, acGuard)
# update MAC Processor
if mac.update_mac_processor():
log.info('HMAC is updated ...')
log.info('HMAC new conf: %s' % mac.printConfiguration())
time.sleep(10)
log.info("Stopping HMAC")
if mac.uninstall_mac_processor():
log.info('HMAC is stopped ...')
else:
log.fatal('Failed to stop HMAC!')
else:
log.fatal('HMAC is not running ... check your installation!')
else:
log.fatal('HMAC is not running ... check your installation!')

View File

@ -1,90 +1,231 @@
import sys
import datetime
import logging
import time
import inspect
import subprocess
import zmq
__author__ = "Sven Zehl, Anatolij Zubow"
__copyright__ = "Copyright (c) 2016, Technische Universität Berlin"
__version__ = "1.0.0"
__email__ = "{zehl, zubow}@tkn.tu-berlin.de"
"""
A hybrid TDMA CSMA MAC based on Atheros and ath9k wifi driver
Class for controlling the hybrid TDMA/CSMA MAC.
"""
class HybridTDMACSMAMac():
def __init__(self, no_slots_in_superframe, slot_duration_ns):
#super(HybridTDMACSMAMac,self).__init__()
self.name = "hybridTDMACSMA"
self.desc = "works w/ ath9k"
class HybridTDMACSMAMac(object):
def __init__(self, interface, no_slots_in_superframe, slot_duration_ns,
hmac_binary_path='hmac_userspace_daemon/hmac_userspace_daemon',
local_mac_processor_port=1217):
'''
The configuration of such a MAC is described by:
:param interface: the wireless interface on which we want to install the HMAC
:param no_slots_in_superframe: the total number of slots in a superframe
:param slot_duration_ns: the time duration of each slot (microseconds)
:param hmac_binary_path: path to the C++ userland HMAC daemon
:param local_mac_processor_port: ZeroMQ port used for communication with HMAC daemon
'''
self.log = logging.getLogger("{module}.{name}".format(
module=self.__class__.__module__, name=self.__class__.__name__))
self.interface = interface
self.mNo_slots_in_superframe = no_slots_in_superframe
self.mSlot_duration_ns = slot_duration_ns
self.acs = []
for ii in range(no_slots_in_superframe):
self.acs.append(None)
# path to the HMAC C++ userland daemon
self.hmac_binary_path = hmac_binary_path
self.local_mac_processor_port = local_mac_processor_port
self.state = MACState.NOT_RUNNING
def getInterface(self):
'''
Returns the wireless interface
'''
return self.interface
def getNumSlots(self):
'''
Get the total number of slots in superframe
'''
return self.mNo_slots_in_superframe
def addAccessPolicy(self, slot_nr, ac):
self.acs[slot_nr] = ac
def setAccessPolicy(self, slot_nr, ac):
'''
Sets an access policy to a given slot in the superframe
:param slot_nr: the slot id to which the access policy to apply
:param ac: the access policy (AccessPolicy class)
:return: True if correct
'''
if slot_nr >= 0 and slot_nr < len(self.acs):
self.acs[slot_nr] = ac
return True
else:
return False
def getAccessPolicy(self, slot_nr):
return self.acs[slot_nr]
'''
Get the access policy assigned to given slot.
:param slot_nr: ID starting from 0.
:return: AccessPolicy object
'''
if slot_nr >= 0 and slot_nr < len(self.acs):
return self.acs[slot_nr]
else:
return None
def removeAccessPolicy(self, slot_nr):
'''
Removes the access policy assigned to given slot.
:param slot_nr: ID starting from 0.
:return: True
'''
if slot_nr >= 0 and slot_nr < len(self.acs):
self.acs[slot_nr] = None
return True
else:
return False
def getSlotDuration(self):
'''
Get time duration of a slot
'''
return self.mSlot_duration_ns
def printConfiguration(self):
'''
Return the MAC configuration serialized as string.
:return:
'''
s = '['
for ii in range(self.getNumSlots()):
s = s + str(ii) + ': ' + self.getAccessPolicy(ii).printConfiguration() + "\n"
s = s + ']'
return s
def install_mac_processor(self, interface, hybridMac):
print 'Function: installMacProcessor'
#self.log.info('margs = %s' % str(myargs))
def install_mac_processor(self):
'''
Installs the given hybrid MAC configuration
:return: True if successful
'''
self.log.debug('install_mac_processor()')
# hybridMac = pickle.loads(mac_profile)
conf_str = None
for ii in range(hybridMac.getNumSlots()): # for each slot
ac = hybridMac.getAccessPolicy(ii)
entries = ac.getEntries()
for ll in range(len(entries)):
entry = entries[ll]
# slot_id, mac_addr, tid_mask
if conf_str is None:
conf_str = str(ii) + "," + str(entry[0]) + "," + str(entry[1])
else:
conf_str = conf_str + "#" + str(ii) + "," + str(entry[0]) + "," + str(entry[1])
# set-up executable here. note: it is platform-dependent
#exec_file = str(os.path.join(self.get_platform_path_hybrid_MAC())) + '/hybrid_tdma_csma_mac'
exec_file = 'hmac_userspace_daemon/hmac_userspace_daemon'
processArgs = str(exec_file) + " -d 0 " + " -i" +str(interface) + " -f" + str(hybridMac.getSlotDuration()) + " -n" + str(hybridMac.getNumSlots()) + " -c" + conf_str
print 'Calling hybrid mac executable w/ = ' + str(processArgs)
if self.state == MACState.RUNNING:
self.log.warn('HMAC is already running; use update_mac_processor() to update at run-time')
return False
try:
# run as background process
# 1. create HMAC configuration string
conf_str = self._create_configuration_string()
# construct command argument for HMAC daemon
processArgs = str(self.exec_file) + " -d 0 " + " -i" + str(self.interface) \
+ " -f" + str(self.getSlotDuration()) + " -n" + str(self.getNumSlots()) + " -c" + conf_str
self.log.debug('Starting HMAC daemon with: %s' % processArgs)
# start HMAC daemon as a background process
subprocess.Popen(processArgs.split(), shell=False)
self.hmac_ctrl_socket = None
self.state = MACState.RUNNING
return True
except Exception as e:
fname = inspect.currentframe().f_code.co_name
print "An error occurred in " +str(fname) + " : " +str(e)
self.log.fatal("An error occurred while starting HMAC daemon, err_msg: %s" % str(e))
def update_mac_processor(self, interface, hybridMac):
return False
print 'Function: updateMacProcessor'
#hybridMac = pickle.loads(mac_profile)
def update_mac_processor(self):
'''
Updates the given hybrid MAC configuration at run-time with new configuration
:return: True if successful
'''
# generate configuration string
self.log.debug('update_mac_processor()')
if self.state == MACState.NOT_RUNNING:
self.log.info('HMAC is not yet running running; start it')
return self.install_mac_processor()
try:
# 1. create HMAC configuration string
conf_str = self._create_configuration_string()
if self.hmac_ctrl_socket is None:
context = zmq.Context()
self.hmac_ctrl_socket = context.socket(zmq.REQ)
self.hmac_ctrl_socket.connect("tcp://localhost:" + str(self.local_mac_processor_port))
# update MAC processor configuration
self.log.info("Send ctrl req message to HMAC: %s" % conf_str)
self.hmac_ctrl_socket.send(conf_str)
message = self.hmac_ctrl_socket.recv()
self.log.info("Received ctrl reply message from HMAC: %s" % message)
return True
except zmq.ZMQError as e:
self.log.fatal("Failed to update running HMAC daemon, err_msg: %s" % str(e))
return False
def uninstall_mac_processor(self):
'''
Uninstalls the running hybrid MAC
:return: True if successful
'''
self.log.debug('uninstall_mac_processor')
if self.state == MACState.NOT_RUNNING:
self.log.warn('HMAC is already stopped')
return True
try:
# set allow all configuration string
conf_str = self._create_allow_all_conf_string()
# command string
terminate_str = 'TERMINATE'
if self.hmac_ctrl_socket is None:
context = zmq.Context()
self.hmac_ctrl_socket = context.socket(zmq.REQ)
self.hmac_ctrl_socket.connect("tcp://localhost:" + str(self.local_mac_processor_port))
# update MAC processor configuration
self.log.info("Send ctrl req message to HMAC: %s" % conf_str)
self.hmac_ctrl_socket.send(conf_str)
message = self.hmac_ctrl_socket.recv()
self.log.info("Received ctrl reply from HMAC: %s" % message)
# give one second to settle down
time.sleep(1)
# send termination signal to MAC
self.hmac_ctrl_socket.send(terminate_str)
message = self.hmac_ctrl_socket.recv()
self.log.info("Received ctrl reply from HMAC: %s" % message)
self.state = MACState.NOT_RUNNING
return True
except zmq.ZMQError as e:
self.log.fatal("Failed to uninstall MAC processor %s" % str(e))
return False
''' Helper '''
def _create_configuration_string(self):
conf_str = None
for ii in range(hybridMac.getNumSlots()): # for each slot
ac = hybridMac.getAccessPolicy(ii)
for ii in range(self.getNumSlots()): # for each slot
ac = self.getAccessPolicy(ii)
entries = ac.getEntries()
for ll in range(len(entries)):
@ -96,85 +237,53 @@ class HybridTDMACSMAMac():
else:
conf_str = conf_str + "#" + str(ii) + "," + str(entry[0]) + "," + str(entry[1])
# update MAC processor configuration
try:
# todo cache sockets!!!
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:" + str("1217"))
socket.send(conf_str)
message = socket.recv()
print "Received reply from HMAC: " + str(message)
return True
except zmq.ZMQError as e:
fname = inspect.currentframe().f_code.co_name
print "An error occurred in " +str(fname) + " : " +str(e)
return conf_str
def uninstall_mac_processor(self, interface, hybridMac):
print 'Function: uninstallMacProcessor'
#hybridMac = pickle.loads(mac_profile)
# set allow all
''' Helper '''
def _create_allow_all_conf_string(self):
# generate configuration string
conf_str = None
for ii in range(hybridMac.getNumSlots()): # for each slot
for ii in range(self.getNumSlots()): # for each slot
# slot_id, mac_addr, tid_mask
if conf_str is None:
conf_str = str(ii) + "," + 'FF:FF:FF:FF:FF:FF' + "," + str(255)
else:
conf_str = conf_str + "#" + str(ii) + "," + 'FF:FF:FF:FF:FF:FF' + "," + str(255)
# command string
terminate_str = 'TERMINATE'
# update MAC processor configuration
try:
# todo cache sockets!!!
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:" + str("1217"))
#socket.connect("ipc:///tmp/localmacprocessor")
# (1) set new config
socket.send(conf_str)
message = socket.recv()
print "Received reply from HMAC: " + str(message)
# give one second to settle down
time.sleep(1)
return conf_str
# (2) terminate MAC
socket.send(terminate_str)
message = socket.recv()
print "Received reply from HMAC: " +str(message)
class MACState:
RUNNING, NOT_RUNNING = range(2)
return True
except zmq.ZMQError as e:
fname = inspect.currentframe().f_code.co_name
print "An error occurred in " +str(fname) + " : " +str(e)
"""
AccessPolicy for each slot
Class for controlling the access policy of each time slot using the destination MAC address and IP ToS value.
"""
class AccessPolicy(object):
def __init__(self):
self.entries = []
def disableAll(self):
'''
Block usage of time slot for all packets
'''
self.entries = []
def allowAll(self):
'''
Unblock usage of time slot for all packets
'''
self.entries = []
self.entries.append(('FF:FF:FF:FF:FF:FF', 255))
def addDestMacAndTosValues(self, dstHwAddr, *tosArgs):
"""add destination mac address and list of ToS fields
"""Add destination mac address and list of ToS fields which is allowed to be transmitted in this time slot
:param dstHwAddr: destination mac address
:param tosArgs: list of ToS values to be allowed here
"""
@ -188,75 +297,19 @@ class AccessPolicy(object):
self.entries.append((dstHwAddr, tid_map))
def getEntries(self):
'''
Get saved entries
'''
return self.entries
def printConfiguration(self):
'''
For debugging
'''
s = ''
for ii in range(len(self.entries)):
s = str(self.entries[ii][0]) + "/" + str(self.entries[ii][1]) + "," + s
return s
if __name__ == "__main__":
# hybrid MAC parameter
dstHWAddr = "34:13:e8:24:77:be" #node on which scheme should be applied, e.g. nuc15 interface sta1
total_slots = 10
slot_duration = 20000
iface = 'wlan0'
# create new MAC for local node
mac = HybridTDMACSMAMac(no_slots_in_superframe=total_slots, slot_duration_ns=slot_duration)
be_slots = [1,2,3,4]
# assign access policies to each slot in superframe
for slot_nr in range(total_slots):
if slot_nr in be_slots:
acBE = AccessPolicy()
acBE.addDestMacAndTosValues(dstHWAddr, 0)
mac.addAccessPolicy(slot_nr, acBE)
else:
acGuard = AccessPolicy()
acGuard.disableAll() # guard slot
mac.addAccessPolicy(slot_nr, acGuard)
# install MAC Processor
if mac.install_mac_processor(iface, mac):
print str(mac.printConfiguration())
time.sleep(10)
print "\nUpdating Hybrid MAC:"
mac = HybridTDMACSMAMac(no_slots_in_superframe=total_slots, slot_duration_ns=slot_duration)
be_slots = [5,6,7,8]
# assign access policies to each slot in superframe
for slot_nr in range(total_slots):
if slot_nr in be_slots:
acBE = AccessPolicy()
acBE.addDestMacAndTosValues(dstHWAddr, 0)
mac.addAccessPolicy(slot_nr, acBE)
else:
acGuard = AccessPolicy()
acGuard.disableAll() # guard slot
mac.addAccessPolicy(slot_nr, acGuard)
if mac.update_mac_processor(iface, mac):
print str(mac.printConfiguration())
time.sleep(15)
print "\nStopping Hybrid MAC:"
if mac.uninstall_mac_processor(iface, mac):
print str(mac.printConfiguration())