diff options
author | Samuel O'Brien <sam.obrien@ni.com> | 2020-07-31 13:43:43 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-10-07 15:29:19 -0500 |
commit | 6394a7c6ea395e2d21c3e2b9e43e1b2dc84666b5 (patch) | |
tree | e5c230efe4781ac294641464d99cf51b6bf44024 | |
parent | 1bb603fffdbdcc87f7c26809d495ced7a5afc93b (diff) | |
download | uhd-6394a7c6ea395e2d21c3e2b9e43e1b2dc84666b5.tar.gz uhd-6394a7c6ea395e2d21c3e2b9e43e1b2dc84666b5.tar.bz2 uhd-6394a7c6ea395e2d21c3e2b9e43e1b2dc84666b5.zip |
sim: Lay Groundwork for Simulator
At this point, only about half of the mpm methods work on the simulator
over the mpm shell, and it hasn't been tested with uhd at all.
If you want to give it a try, first install all of the python
dependencies of mpm (The simulator doesn't require libusrp or any of
the C++ deps). In addition, running mpm on a desktop machine requires
the python lib netifaces. Next, make an /mpm/build directory and open
it. Run `cmake .. -DMPM_DEVICE=sim`, then `make`. Finally, run
`python3 python/usrp_hwd.py`. You should be able to open another
terminal and run `mpm/tools/mpm_shell.py localhost` to connect to the
mpm server.
Signed-off-by: Samuel O'Brien <sam.obrien@ni.com>
-rw-r--r-- | mpm/CMakeLists.txt | 50 | ||||
-rw-r--r-- | mpm/python/CMakeLists.txt | 23 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/CMakeLists.txt | 2 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/__init__.py.in (renamed from mpm/python/usrp_mpm/__init__.py) | 18 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/CMakeLists.txt | 1 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/sim.py | 302 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/sys_utils/net.py | 10 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/xports/xportmgr_udp.py | 14 |
8 files changed, 376 insertions, 44 deletions
diff --git a/mpm/CMakeLists.txt b/mpm/CMakeLists.txt index a30d3acd9..e426716a6 100644 --- a/mpm/CMakeLists.txt +++ b/mpm/CMakeLists.txt @@ -119,7 +119,7 @@ if(_has_no_psabi) message(STATUS "Disabling psABI warnings.") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-psabi") endif(_has_no_psabi) -set(MPM_ALL_DEVICES n3xx e320 e31x tests) +set(MPM_ALL_DEVICES n3xx e320 e31x sim tests) set(MPM_DEVICE "n3xx" CACHE STRING "Choose an MPM device to build") set_property(CACHE MPM_DEVICE PROPERTY STRINGS ${MPM_ALL_DEVICES}) # Validate MPM_DEVICE @@ -137,6 +137,9 @@ elseif(MPM_DEVICE STREQUAL "e320") set(ENABLE_E320 ON) elseif(MPM_DEVICE STREQUAL "e31x") set(ENABLE_E300 ON) +elseif(MPM_DEVICE STREQUAL "sim") + set(ENABLE_SIM TRUE) + set(ENABLE_LIBMPM OFF) endif() MPM_REGISTER_COMPONENT("LibMPM" ENABLE_LIBMPM ON "Boost_FOUND" OFF ON) @@ -145,33 +148,38 @@ MPM_REGISTER_COMPONENT("Magnesium" ENABLE_MAGNESIUM OFF "ENABLE_MYKONOS" OFF OFF MPM_REGISTER_COMPONENT("E320" ENABLE_E320 OFF "ENABLE_LIBMPM" OFF OFF) MPM_REGISTER_COMPONENT("E300" ENABLE_E300 OFF "ENABLE_LIBMPM" OFF OFF) -add_subdirectory(include) -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_BINARY_DIR}/include - ${UHD_HOST_ROOT}/include -) +if(NOT ENABLE_SIM) + add_subdirectory(include) + include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_BINARY_DIR}/include + ${UHD_HOST_ROOT}/include + ) -add_subdirectory(lib) + add_subdirectory(lib) -message("usrp_periphs objects: ${usrp_periphs_objects}") -add_library(usrp-periphs SHARED ${usrp_periphs_objects}) -target_link_libraries(usrp-periphs - udev - ${Boost_LIBRARIES} -) + message("usrp_periphs objects: ${usrp_periphs_objects}") + add_library(usrp-periphs SHARED ${usrp_periphs_objects}) + target_link_libraries(usrp-periphs + udev + ${Boost_LIBRARIES} + ) -install(TARGETS usrp-periphs LIBRARY DESTINATION ${LIBRARY_DIR} COMPONENT libraries) + install(TARGETS usrp-periphs LIBRARY DESTINATION ${LIBRARY_DIR} COMPONENT libraries) -# TODO: Come up with a versioning scheme for the MPM ABI. Not high priority -# though... we're the only ones linking against that. -set_target_properties(usrp-periphs PROPERTIES VERSION "${MPM_VERSION_MAJOR}.${MPM_VERSION_API}.${MPM_VERSION_ABI}") -set_target_properties(usrp-periphs PROPERTIES SOVERSION ${MPM_VERSION_MAJOR}) + # TODO: Come up with a versioning scheme for the MPM ABI. Not high priority + # though... we're the only ones linking against that. + set_target_properties(usrp-periphs PROPERTIES VERSION "${MPM_VERSION_MAJOR}.${MPM_VERSION_API}.${MPM_VERSION_ABI}") + set_target_properties(usrp-periphs PROPERTIES SOVERSION ${MPM_VERSION_MAJOR}) + + add_subdirectory(systemd) + add_subdirectory(tools) +endif(NOT ENABLE_SIM) enable_testing() add_subdirectory(python) -add_subdirectory(tools) -add_subdirectory(systemd) + + ######################################################################## # Print Summary diff --git a/mpm/python/CMakeLists.txt b/mpm/python/CMakeLists.txt index 5691a67a2..b1bc9fa16 100644 --- a/mpm/python/CMakeLists.txt +++ b/mpm/python/CMakeLists.txt @@ -16,15 +16,17 @@ elseif(MPM_DEVICE STREQUAL "e31x") add_library(pyusrp_periphs SHARED pyusrp_periphs/e31x/pyusrp_periphs.cpp) endif(MPM_DEVICE STREQUAL "n3xx") -target_include_directories(pyusrp_periphs PUBLIC - ${PYTHON_INCLUDE_DIRS} - ${CMAKE_SOURCE_DIR}/lib/ - ${UHD_HOST_ROOT}/lib/usrp/common - ${UHD_HOST_ROOT}/lib/usrp/common/ad9361_driver - ${UHD_HOST_ROOT}/lib/deps/pybind11/include -) -target_link_libraries(pyusrp_periphs ${Boost_LIBRARIES} usrp-periphs) -add_custom_command(TARGET pyusrp_periphs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libpyusrp_periphs.so ${CMAKE_CURRENT_BINARY_DIR}/usrp_mpm/libpyusrp_periphs.so) +if(NOT ENABLE_SIM) + target_include_directories(pyusrp_periphs PUBLIC + ${PYTHON_INCLUDE_DIRS} + ${CMAKE_SOURCE_DIR}/lib/ + ${UHD_HOST_ROOT}/lib/usrp/common + ${UHD_HOST_ROOT}/lib/usrp/common/ad9361_driver + ${UHD_HOST_ROOT}/lib/deps/pybind11/include + ) + target_link_libraries(pyusrp_periphs ${Boost_LIBRARIES} usrp-periphs) + add_custom_command(TARGET pyusrp_periphs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libpyusrp_periphs.so ${CMAKE_CURRENT_BINARY_DIR}/usrp_mpm/libpyusrp_periphs.so) +endif(NOT ENABLE_SIM) set(USRP_MPM_FILES "") add_subdirectory(usrp_mpm) @@ -34,9 +36,12 @@ set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in") set(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py") set(PERIPH_MGR_INIT_IN "${CMAKE_CURRENT_SOURCE_DIR}/usrp_mpm/periph_manager/__init__.py.in") set(PERIPH_MGR_INIT "${CMAKE_CURRENT_BINARY_DIR}/usrp_mpm/periph_manager/__init__.py") +set(USRP_MPM_INIT_IN "${CMAKE_CURRENT_SOURCE_DIR}/usrp_mpm/__init__.py.in") +set(USRP_MPM_INIT "${CMAKE_CURRENT_BINARY_DIR}/usrp_mpm/__init__.py") configure_file(${SETUP_PY_IN} ${SETUP_PY}) configure_file(${PERIPH_MGR_INIT_IN} ${PERIPH_MGR_INIT}) +configure_file(${USRP_MPM_INIT_IN} ${USRP_MPM_INIT}) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/usrp_hwd.py" "${CMAKE_CURRENT_BINARY_DIR}/usrp_hwd.py" COPYONLY) add_custom_command(OUTPUT ${OUTPUT} diff --git a/mpm/python/usrp_mpm/CMakeLists.txt b/mpm/python/usrp_mpm/CMakeLists.txt index 9ea114e0b..93c140a8d 100644 --- a/mpm/python/usrp_mpm/CMakeLists.txt +++ b/mpm/python/usrp_mpm/CMakeLists.txt @@ -9,7 +9,7 @@ ######################################################################## set(USRP_MPM_FILES ${USRP_MPM_FILES}) set(USRP_MPM_TOP_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in ${CMAKE_CURRENT_SOURCE_DIR}/aurora_control.py ${CMAKE_CURRENT_SOURCE_DIR}/bfrfs.py ${CMAKE_CURRENT_SOURCE_DIR}/components.py diff --git a/mpm/python/usrp_mpm/__init__.py b/mpm/python/usrp_mpm/__init__.py.in index a8efbd498..c2134d092 100644 --- a/mpm/python/usrp_mpm/__init__.py +++ b/mpm/python/usrp_mpm/__init__.py.in @@ -7,18 +7,24 @@ MPM Module """ -from . import libpyusrp_periphs as lib +__simulated__ = ("${MPM_DEVICE}" == "sim") + from .discovery import spawn_discovery_process from .rpc_server import spawn_rpc_process from . import mpmtypes -from . import periph_manager -from . import dboard_manager -from . import xports -from . import cores -from . import chips from . import gpsd_iface from .mpmlog import get_main_logger +if not __simulated__: + from . import libpyusrp_periphs as lib + from . import periph_manager + from . import dboard_manager + from . import xports + from . import cores + from . import chips +else: + from . import periph_manager + __version__ = periph_manager.__version__ __githash__ = periph_manager.__githash__ __mpm_device__ = periph_manager.__mpm_device__ diff --git a/mpm/python/usrp_mpm/periph_manager/CMakeLists.txt b/mpm/python/usrp_mpm/periph_manager/CMakeLists.txt index 4f8520c12..747b8967a 100644 --- a/mpm/python/usrp_mpm/periph_manager/CMakeLists.txt +++ b/mpm/python/usrp_mpm/periph_manager/CMakeLists.txt @@ -18,6 +18,7 @@ set(USRP_MPM_PERIPHMGR_FILES ${CMAKE_CURRENT_SOURCE_DIR}/e320_periphs.py ${CMAKE_CURRENT_SOURCE_DIR}/e31x.py ${CMAKE_CURRENT_SOURCE_DIR}/e31x_periphs.py + ${CMAKE_CURRENT_SOURCE_DIR}/sim.py ) list(APPEND USRP_MPM_FILES ${USRP_MPM_PERIPHMGR_FILES}) set(USRP_MPM_FILES ${USRP_MPM_FILES} PARENT_SCOPE) diff --git a/mpm/python/usrp_mpm/periph_manager/sim.py b/mpm/python/usrp_mpm/periph_manager/sim.py new file mode 100644 index 000000000..00ba5ba38 --- /dev/null +++ b/mpm/python/usrp_mpm/periph_manager/sim.py @@ -0,0 +1,302 @@ +# +# Copyright 2020 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +""" +usrp simulation module + +This module is used to emulate a usrp when running on a standard +computer. You can build mpm in this configuration by using the cmake +flag -DMPM_DEVICE=sim +""" + +from pyroute2 import IPRoute +from usrp_mpm.xports import XportMgrUDP +from usrp_mpm.mpmlog import get_logger +from usrp_mpm.rpc_server import no_claim +from usrp_mpm.periph_manager import PeriphManagerBase + +CLOCK_SOURCE_INTERNAL = "internal" + +E320_DBOARD_SLOT_IDX = 0 + +class SimXportMgrUDP(XportMgrUDP): + """This is an adaptor class for the normal XportMgrUDP + In radios, the interface names are hardcoded. Since we are on a + desktop computer, we generate the names at runtime. + """ + def __init__(self, log, args, eth_dispatcher_cls): + with IPRoute() as ipr: + self.iface_config = { + link.get_attr('IFLA_IFNAME'): { + 'label': link.get_attr('IFLA_IFNAME'), + 'type': 'forward' + } for link in ipr.get_links() + } + super().__init__(log, args, eth_dispatcher_cls) + +class SimEthDispatcher: + """This is the hardware specific part of the normal XportMgrUDP + that we have to simulate. We get the ipv4 addr with IPRoute + instead of registers + """ + DEFAULT_VITA_PORT = (49153, 49154) + LOG = None + + def __init__(self, if_name): + self.log = get_logger(if_name) + self.if_name = if_name + + def set_ipv4_addr(self, addr): + """This doesn't actually change the ipv4 address, it just + checks to make sure the requested address is already our + address, and complains otherwise. + """ + with IPRoute() as ipr: + valid_iface_idx = ipr.link_lookup(ifname=self.if_name)[0] + link_info = ipr.get_links(valid_iface_idx)[0] + real_addr = link_info.get_attr('IFLA_ADDRESS') + if addr != real_addr: + self.log.warning("Cannot change ip address on simulator! Requested: {}, Actual: {}" + .format(addr, real_addr)) + +class sim(PeriphManagerBase): + """This is a periph manager that is designed to run on a regular + computer rather than the arm core on an SDR + """ + ######################################################################### + # Overridables + # + # See PeriphManagerBase for documentation on these fields + ######################################################################### + description = "E320-Series Device - SIMULATED" + pids = {0xE320: 'e320'} + + mboard_info = {"type": "e3xx", "product": "e320"} + mboard_max_rev = 7 # RevC + mboard_sensor_callback_map = {} + + ########################################################################### + # Ctor and device initialization tasks + ########################################################################### + def __init__(self, args): + super().__init__() + self.device_id = 1 + + # Unlike the real hardware drivers, if there is an exception here, + # we just crash. No use missing an error when testing. + self._init_peripherals(args) + self.init_dboards(args) + if not args.get('skip_boot_init', False): + self.init(args) + + @classmethod + def generate_device_info(cls, eeprom_md, mboard_info, dboard_infos): + """ + Hard-code our product map + """ + # Add the default PeriphManagerBase information first + device_info = super().generate_device_info( + eeprom_md, mboard_info, dboard_infos) + # Then add device-specific information + mb_pid = eeprom_md.get('pid') + device_info['product'] = cls.pids.get(mb_pid, 'unknown') + return device_info + + def _read_mboard_eeprom(self): + """ + Read out a simulated mboard eeprom and saves it to the appropriate member variable + """ + self._eeprom_head = sim._generate_eeprom_head() + + self.log.trace("Found EEPROM metadata: '{}'" + .format(str(self._eeprom_head))) + return (self._eeprom_head, None) + + @staticmethod + def _generate_eeprom_head(serial=b'3196D2A', rev=2, rev_compat=2): + return {'pid': 0xE320, + 'rev': rev, + 'rev_compat': rev_compat, + 'serial': serial} + + def _init_peripherals(self, args): + """ + Turn on all peripherals. This may throw an error on failure, so make + sure to catch it. + + Peripherals are initialized in the order of least likely to fail, to most + likely. + """ + # Sanity checks + assert self.mboard_info.get('product') in self.pids.values(), \ + "Device product could not be determined!" + # Init peripherals + + # Init CHDR transports + self._xport_mgrs = { + 'udp': SimXportMgrUDP(self.log, args, SimEthDispatcher) + } + #TODO: Actually create transports here when RFNoC is integrated + self.log.trace("CHDR transport creation was skipped") + + # Init complete. + self.log.debug("Device info: {}".format(self.device_info)) + + ########################################################################### + # Device info + ########################################################################### + def get_device_info_dyn(self): + """ + Append the device info with current IP addresses. + """ + if not self._device_initialized: + return {} + device_info = self._xport_mgrs['udp'].get_xport_info() + self.log.warn("get_device_info_dyn() - FPGA functionality not implemented yet") + return device_info + + def set_device_id(self, device_id): + """ + Sets the device ID for this motherboard. + The device ID is used to identify the RFNoC components associated with + this motherboard. + """ + self.device_id = device_id + + def get_device_id(self): + """ + Gets the device ID for this motherboard. + The device ID is used to identify the RFNoC components associated with + this motherboard. + """ + return self.device_id + + @no_claim + def get_proto_ver(self): + """ + Return RFNoC protocol version + """ + return 0x100 + + @no_claim + def get_chdr_width(self): + """ + Return RFNoC CHDR width + """ + return 64 + + ########################################################################### + # Transport API + ########################################################################### + def get_chdr_link_types(self): + """ + This will only ever return a single item (udp). + """ + return ["udp"] + + def get_chdr_link_options(self, xport_type): + """ + Returns a list of dictionaries. Every dictionary contains information + about one way to connect to this device in order to initiate CHDR + traffic. + + The interpretation of the return value is very highly dependant on the + transport type (xport_type). + For UDP, the every entry of the list has the following keys: + - ipv4 (IP Address) + - port (UDP port) + - link_rate (bps of the link, e.g. 10e9 for 10GigE) + """ + if xport_type not in self._xport_mgrs: + self.log.warning("Can't get link options for unknown link type: '{}'." + .format(xport_type)) + return [] + return self._xport_mgrs[xport_type].get_chdr_link_options() + + ####################################################################### + # Timekeeper API + ####################################################################### + def get_master_clock_rate(self): + """ Return the master clock rate set during init """ + return self._master_clock_rate + + def get_num_timekeepers(self): + """ + Return the number of timekeepers + """ + return 1 + + def set_timekeeper_time(self, tk_idx, ticks, next_pps): + """ + Set the time in ticks + + Arguments: + tk_idx: Index of timekeeper + ticks: Time in ticks + next_pps: If True, set time at next PPS. Otherwise, set time now. + """ + self.log.debug("Setting timekeeper time (tx_idx:{}, ticks: {}, next_pps: {})" + .format(tk_idx, ticks, next_pps)) + + def get_timekeeper_time(self, tk_idx, last_pps): + """ + Get the time in ticks + + Arguments: + tk_idx: Index of timekeeper + next_pps: If True, get time at last PPS. Otherwise, get time now. + """ + return 0 + + def set_tick_period(self, tk_idx, period_ns): + """ + Set the time per tick in nanoseconds (tick period) + + Arguments: + tk_idx: Index of timekeeper + period_ns: Period in nanoseconds + """ + self.log.debug("Setting tick period (tk_idx: {}, period_ns: {})" + .format(tk_idx, period_ns)) + + def get_clocks(self): + """ + Gets the RFNoC-related clocks present in the FPGA design + """ + return [ + { + 'name': 'radio_clk', + 'freq': str(122.88e6), + 'mutable': 'true' + }, + { + 'name': 'bus_clk', + 'freq': str(200e6), + }, + { + 'name': 'ctrl_clk', + 'freq': str(40e6), + } + ] + + def get_time_sources(self): + " Returns list of valid time sources " + return (CLOCK_SOURCE_INTERNAL,) + + def get_clock_sources(self): + " Lists all available clock sources. " + return (CLOCK_SOURCE_INTERNAL,) + + def get_clock_source(self): + " Returns the current Clock Source " + return CLOCK_SOURCE_INTERNAL + + def set_clock_source(self, source): + " No-op which sets the clock source on a real radio " + self.log.debug("Setting clock source to {}".format(source)) + + def set_channel_mode(self, channel_mode): + " No-op which sets the channel mode on a real radio " + self.log.debug("Using channel mode {}".format(channel_mode)) diff --git a/mpm/python/usrp_mpm/sys_utils/net.py b/mpm/python/usrp_mpm/sys_utils/net.py index a9be7b87d..6ba5f0c3e 100644 --- a/mpm/python/usrp_mpm/sys_utils/net.py +++ b/mpm/python/usrp_mpm/sys_utils/net.py @@ -31,7 +31,10 @@ def get_valid_interfaces(iface_list): continue valid_iface_idx = valid_iface_idx[0] link_info = ipr.get_links(valid_iface_idx)[0] - if link_info.get_attr('IFLA_OPERSTATE') == 'UP' \ + # IFLA_OPERSTATE attribute isn't implemented on WSL + # Workaround is ignore it in the simulator + from usrp_mpm import __simulated__ + if (link_info.get_attr('IFLA_OPERSTATE') == 'UP' or __simulated__) \ and len(get_iface_addrs(link_info.get_attr('IFLA_ADDRESS'))): assert link_info.get_attr('IFLA_IFNAME') == iface valid_ifaces.append(iface) @@ -83,6 +86,11 @@ def get_link_speed(ifname): The speed is Megabits/sec (from kernel at https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net) """ + # This wasn't implemented in WSL or in the linux pc I tested it on + # We will return a sensible default + from usrp_mpm import __simulated__ + if __simulated__: + return 1000 net_sysfs = [device for device in pyudev.Context().list_devices(subsystem='net') if device.sys_name == ifname][0] diff --git a/mpm/python/usrp_mpm/xports/xportmgr_udp.py b/mpm/python/usrp_mpm/xports/xportmgr_udp.py index 099a67d2a..197a628e4 100644 --- a/mpm/python/usrp_mpm/xports/xportmgr_udp.py +++ b/mpm/python/usrp_mpm/xports/xportmgr_udp.py @@ -8,10 +8,10 @@ UDP Transport manager """ +import importlib import subprocess from six import iteritems, itervalues from usrp_mpm import prefs -from usrp_mpm.ethdispatch import EthDispatcherCtrl from usrp_mpm.sys_utils import net DEFAULT_BRIDGE_MODE = False @@ -30,7 +30,9 @@ class XportMgrUDP: iface_config = {} bridges = {} - def __init__(self, log, args): + def __init__(self, log, args, eth_dispatcher_cls=None): + self.eth_dispatcher_cls = eth_dispatcher_cls or \ + importlib.import_module('usrp_mpm.ethdispatch').EthDispatcherCtrl assert self.iface_config assert all(( all((key in x for key in ('label',))) @@ -40,7 +42,7 @@ class XportMgrUDP: self.log.trace("Initializing UDP xport manager...") self._possible_chdr_ifaces = self.iface_config.keys() self.log.trace("Identifying available network interfaces...") - self.chdr_port = EthDispatcherCtrl.DEFAULT_VITA_PORT[0] + self.chdr_port = self.eth_dispatcher_cls.DEFAULT_VITA_PORT[0] self._chdr_ifaces = self._init_interfaces(self._possible_chdr_ifaces) self._bridge_mode = args.get('bridge_mode', DEFAULT_BRIDGE_MODE) self._eth_dispatchers = {} @@ -106,7 +108,7 @@ class XportMgrUDP: "Updated dispatchers in bridge mode with bridge interface {}" .format(bridge_iface)) self._eth_dispatchers = { - x: EthDispatcherCtrl(self.iface_config[x]['label']) + x: self.eth_dispatcher_cls(self.iface_config[x]['label']) for x in self.bridges[bridge_iface] } for dispatcher, table in iteritems(self._eth_dispatchers): @@ -132,7 +134,7 @@ class XportMgrUDP: continue if iface not in self._eth_dispatchers: self._eth_dispatchers[iface] = \ - EthDispatcherCtrl(self.iface_config[iface]['label']) + self.eth_dispatcher_cls(self.iface_config[iface]['label']) self._eth_dispatchers[iface].set_ipv4_addr( self._chdr_ifaces[iface]['ip_addr'] ) @@ -218,7 +220,7 @@ class XportMgrUDP: deinit() was not yet called. """ assert host_location in ('remote', 'local', 'all') - + return [ { 'ipv4': str(iface_info['ip_addr']) if (self.iface_config[iface_name]['type'] != 'internal') |