mirror of
https://github.com/szehl/ath9k-hmac.git
synced 2024-12-24 07:46:56 +00:00
Merge branch 'master' of https://github.com/szehl/ath9k-hmac
This commit is contained in:
commit
91461e07b9
92
hmac_python_wrapper/hmac_example.py
Normal file
92
hmac_python_wrapper/hmac_example.py
Normal 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!')
|
@ -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())
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user