diff options
author | Martin Braun <martin.braun@ettus.com> | 2017-12-08 19:00:57 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:05:57 -0800 |
commit | 58e7022062ed450c39fde27b11d743ea3f3b734b (patch) | |
tree | 698908850a86af3859be9eb2479c716f67a3befe | |
parent | 2db171798efc2e16cf2c5d85bfbfe7b032a38ead (diff) | |
download | uhd-58e7022062ed450c39fde27b11d743ea3f3b734b.tar.gz uhd-58e7022062ed450c39fde27b11d743ea3f3b734b.tar.bz2 uhd-58e7022062ed450c39fde27b11d743ea3f3b734b.zip |
mpm: Factor out xport managers as own objects
- Move XportMgr classes out of n310.py
- Subclass them there and apply N310-specific settings
- Remove chdr_interfaces option from PeriphManagerBase
-rwxr-xr-x | mpm/python/setup.py.in | 1 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/CMakeLists.txt | 1 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/__init__.py | 1 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/base.py | 5 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/n310.py | 249 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/xports/CMakeLists.txt | 15 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/xports/__init__.py | 11 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/xports/xportmgr_liberio.py | 79 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/xports/xportmgr_udp.py | 199 |
9 files changed, 328 insertions, 233 deletions
diff --git a/mpm/python/setup.py.in b/mpm/python/setup.py.in index 725c53c62..9c6888a74 100755 --- a/mpm/python/setup.py.in +++ b/mpm/python/setup.py.in @@ -44,6 +44,7 @@ setup(name='usrp_mpm', 'usrp_mpm.dboard_manager', 'usrp_mpm.chips', 'usrp_mpm.cores', + 'usrp_mpm.xports', ], install_requires=[ 'mprpc', diff --git a/mpm/python/usrp_mpm/CMakeLists.txt b/mpm/python/usrp_mpm/CMakeLists.txt index 7b6e6b84c..b308625ca 100644 --- a/mpm/python/usrp_mpm/CMakeLists.txt +++ b/mpm/python/usrp_mpm/CMakeLists.txt @@ -42,4 +42,5 @@ ADD_SUBDIRECTORY(periph_manager) ADD_SUBDIRECTORY(dboard_manager) ADD_SUBDIRECTORY(chips) ADD_SUBDIRECTORY(cores) +ADD_SUBDIRECTORY(xports) SET(USRP_MPM_FILES ${USRP_MPM_FILES} PARENT_SCOPE) diff --git a/mpm/python/usrp_mpm/__init__.py b/mpm/python/usrp_mpm/__init__.py index 29e0b1a09..7a907312d 100644 --- a/mpm/python/usrp_mpm/__init__.py +++ b/mpm/python/usrp_mpm/__init__.py @@ -23,4 +23,5 @@ from .rpc_server import spawn_rpc_process from . import mpmtypes from . import periph_manager from . import dboard_manager +from . import xports from .mpmlog import get_main_logger diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py index 2be8c7570..ff86137df 100644 --- a/mpm/python/usrp_mpm/periph_manager/base.py +++ b/mpm/python/usrp_mpm/periph_manager/base.py @@ -118,11 +118,6 @@ class PeriphManagerBase(object): # dboards, but if it's shorter, it simply won't instantiate list SPI nodes # for those dboards. dboard_spimaster_addrs = [] - # Lists the network interfaces which can theoretically support CHDR. These - # do not have to exist, but these interfaces will be probed for - # availability. If the list is empty, no CHDR traffic will be possible over - # the network. Example: ['eth1', 'eth2'] - chdr_interfaces = [] # Dictionary containing valid IDs for the update_component function for a # specific implementation. Each PeriphManagerBase-derived class should list # information required to update the component, like a callback function diff --git a/mpm/python/usrp_mpm/periph_manager/n310.py b/mpm/python/usrp_mpm/periph_manager/n310.py index 122053b7f..be55843d4 100644 --- a/mpm/python/usrp_mpm/periph_manager/n310.py +++ b/mpm/python/usrp_mpm/periph_manager/n310.py @@ -28,14 +28,12 @@ from builtins import object from .base import PeriphManagerBase from ..net import get_iface_addrs from ..net import byte_to_mac -from ..net import get_mac_addr from ..mpmtypes import SID from usrp_mpm.rpc_server import no_rpc from usrp_mpm import net from usrp_mpm import dtoverlay +from usrp_mpm.xports import XportMgrUDP, XportMgrLiberio from ..sysfs_gpio import SysFSGPIO -from ..ethtable import EthDispatcherTable -from ..liberiotable import LiberioDispatcherTable from .. import libpyusrp_periphs as lib N3XX_DEFAULT_EXT_CLOCK_FREQ = 10e6 @@ -212,231 +210,27 @@ class FP_GPIO(object): ############################################################################### # Transport managers ############################################################################### -class XportMgrUDP(object): - """ - Transport manager for UDP connections - """ - # Map Eth devices to UIO labels +class N310XportMgrUDP(XportMgrUDP): eth_tables = {'eth1': 'misc-enet-regs0', 'eth2': 'misc-enet-regs1'} xbar_port_map = {'eth1': 0, 'eth2': 1} + xbar_dev = "/dev/crossbar0" + iface_config = { + 'eth1': { + 'label': 'misc-enet-regs0', + 'xbar': 0, + 'xbar_port': 0, + }, + 'eth2': { + 'label': 'misc-enet-regs1', + 'xbar': 0, + 'xbar_port': 1, + }, + } - def __init__(self, possible_chdr_ifaces, log): - self.log = log - self._possible_chdr_ifaces = possible_chdr_ifaces - self.log.info("Identifying available network interfaces...") - self._chdr_ifaces = \ - self._init_interfaces(self._possible_chdr_ifaces) - self._eth_dispatchers = { - x: EthDispatcherTable(self.eth_tables.get(x)) - for x in list(self._chdr_ifaces.keys()) - } - for ifname, table in iteritems(self._eth_dispatchers): - table.set_ipv4_addr(self._chdr_ifaces[ifname]['ip_addr']) - self.chdr_port = 49153 # TODO get this from somewhere - - def _init_interfaces(self, possible_ifaces): - """ - Initialize the list of network interfaces - """ - self.log.trace("Testing available interfaces out of `{}'".format( - possible_ifaces - )) - valid_ifaces = net.get_valid_interfaces(possible_ifaces) - if len(valid_ifaces): - self.log.debug("Found CHDR interfaces: `{}'".format(valid_ifaces)) - else: - self.log.warning("No CHDR interfaces found!") - return { - x: net.get_iface_info(x) - for x in valid_ifaces - } - - def init(self, args): - """ - Call this when the user calls 'init' on the periph manager - """ - # TODO re-run _init_interfaces, IP addresses could have changed since - # bootup - for _, table in iteritems(self._eth_dispatchers): - if 'forward_eth' in args or 'forward_bcast' in args: - table.set_forward_policy( - args.get('forward_eth', False), - args.get('forward_bcast', False) - ) - if 'preload_ethtables' in args: - self._preload_ethtables( - self._eth_dispatchers, - args['preload_ethtables'] - ) - - def deinit(self): - " Clean up after a session terminates " - pass - - def _preload_ethtables(self, eth_dispatchers, table_file): - """ - Populates the ethernet tables from a JSON file - """ - import json - try: - eth_table_data = json.load(open(table_file)) - except ValueError as ex: - self.log.warning( - "Bad values in preloading table file: %s", - str(ex) - ) - return - self.log.info( - "Preloading Ethernet dispatch tables from JSON file `%s'.", - table_file - ) - for eth_iface, data in iteritems(eth_table_data): - if eth_iface not in eth_dispatchers: - self.log.warning( - "Request to preload eth dispatcher table for " - "iface `{}', but no such interface is " - "registered. Known interfaces: {}".format( - str(eth_iface), - ",".join(eth_dispatchers.keys()) - ) - ) - continue - eth_dispatcher = eth_dispatchers[eth_iface] - self.log.debug("Preloading {} dispatch table".format(eth_iface)) - try: - for dst_ep, udp_data in iteritems(data): - sid = SID() - sid.set_dst_ep(int(dst_ep)) - eth_dispatcher.set_route( - sid, - udp_data['ip_addr'], - udp_data['port'], - udp_data.get('mac_addr', None) - ) - except ValueError as ex: - self.log.warning( - "Bad values in preloading table file: %s", - str(ex) - ) - - def request_xport( - self, - sid, - xport_type, - ): - """ - Return UDP xport info - """ - assert xport_type in ('CTRL', 'ASYNC_MSG', 'TX_DATA', 'RX_DATA') - # for iface_name, iface_info in iteritems(self._chdr_ifaces): - - xport_info = [ - { - 'type': 'UDP', - 'ipv4': str(iface_info['ip_addr']), - 'port': str(self.chdr_port), - 'send_sid': str(sid) - } - for _, iface_info in iteritems(self._chdr_ifaces) - ] - return xport_info - - def commit_xport(self, sid, xport_info): - """ - fuu - """ - self.log.trace("Sanity checking xport_info %s...", str(xport_info)) - assert xport_info['type'] == 'UDP' - assert any([xport_info['ipv4'] == x['ip_addr'] - for x in itervalues(self._chdr_ifaces)]) - assert xport_info['port'] == str(self.chdr_port) - assert len(xport_info.get('src_ipv4')) > 5 - assert int(xport_info.get('src_port')) > 0 - sender_addr = xport_info['src_ipv4'] - sender_port = int(xport_info['src_port']) - self.log.trace("Incoming connection is coming from %s:%d", - sender_addr, sender_port) - mac_addr = get_mac_addr(sender_addr) - if mac_addr is None: - raise RuntimeError( - "Could not find MAC address for IP address {}".format( - sender_addr)) - self.log.trace("Incoming connection is coming from %s", - mac_addr) - eth_iface = net.ip_addr_to_iface(xport_info['ipv4'], self._chdr_ifaces) - xbar_port = self.xbar_port_map[eth_iface] - self.log.trace("Using Ethernet interface %s, crossbar port %d", - eth_iface, xbar_port) - my_xbar = lib.xbar.xbar.make("/dev/crossbar0") # TODO don't hardcode - my_xbar.set_route(sid.src_addr, xbar_port) - self._eth_dispatchers[eth_iface].set_route( - sid.reversed(), sender_addr, sender_port) - self.log.trace("UDP transport successfully committed!") - return True - - -class XportMgrLiberio(object): - """ - Transport manager for UDP connections - """ - # udev label for the UIO device that controls the DMA engine - liberio_label = 'liberio' - - def __init__(self, log): - self.log = log - self._dma_dispatcher = LiberioDispatcherTable(self.liberio_label) - self._data_chan_ctr = 0 - self._max_chan = 10 # TODO get this number from somewhere - - def init(self, args): - """ - Call this when the user calls 'init' on the periph manager - """ - pass - - def deinit(self): - " Clean up after a session terminates " - self._data_chan_ctr = 0 - - def request_xport( - self, - sid, - xport_type, - ): - """ - Return liberio xport info - """ - assert xport_type in ('CTRL', 'ASYNC_MSG', 'TX_DATA', 'RX_DATA') - if xport_type == 'CTRL': - chan = 0 - elif xport_type == 'ASYNC_MSG': - chan = 1 - else: - chan = 2 + self._data_chan_ctr - self._data_chan_ctr += 1 - xport_info = { - 'type': 'liberio', - 'send_sid': str(sid), - 'muxed': str(xport_type in ('CTRL', 'ASYNC_MSG')), - 'dma_chan': str(chan), - 'tx_dev': "/dev/tx-dma{}".format(chan), - 'rx_dev': "/dev/rx-dma{}".format(chan), - } - self.log.trace("Liberio: Chan: {} TX Device: {} RX Device: {}".format( - chan, xport_info['tx_dev'], xport_info['rx_dev'])) - self.log.trace("Liberio channel is muxed: %s", - "Yes" if xport_info['muxed'] else "No") - return [xport_info] - - def commit_xport(self, sid, xport_info): - " Commit liberio transport " - chan = int(xport_info['dma_chan']) - my_xbar = lib.xbar.xbar.make("/dev/crossbar0") # TODO - my_xbar.set_route(sid.src_addr, 2) # TODO - self._dma_dispatcher.set_route(sid.reversed(), chan) - self.log.trace("Liberio transport successfully committed!") - return True - +class N310XportMgrLiberio(XportMgrLiberio): + max_chan = 10 + xbar_dev = "/dev/crossbar0" + xbar_port = 2 ############################################################################### # Main Class @@ -467,7 +261,6 @@ class n310(PeriphManagerBase): # We're on a Zynq target, so the following two come from the Zynq standard # device tree overlay (tree/arch/arm/boot/dts/zynq-7000.dtsi) dboard_spimaster_addrs = ["e0006000.spi", "e0007000.spi"] - chdr_interfaces = ['eth1', 'eth2'] # N310-specific settings # Path to N310 FPGA bin file # This file will always contain the current image, regardless of SFP type, @@ -544,8 +337,8 @@ class n310(PeriphManagerBase): self._init_ref_clock_and_time(args.default_args) # Init CHDR transports self._xport_mgrs = { - 'udp': XportMgrUDP(self.chdr_interfaces, self.log), - 'liberio': XportMgrLiberio(self.log), + 'udp': N310XportMgrUDP(self.log.getChild('UDP')), + 'liberio': N310XportMgrLiberio(self.log.getChild('liberio')), } # Init complete. self.log.info("mboard info: {}".format(self.mboard_info)) diff --git a/mpm/python/usrp_mpm/xports/CMakeLists.txt b/mpm/python/usrp_mpm/xports/CMakeLists.txt new file mode 100644 index 000000000..1f8ffc2b1 --- /dev/null +++ b/mpm/python/usrp_mpm/xports/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright 2017 Ettus Research, National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0 +# + +SET(USRP_MPM_FILES ${USRP_MPM_FILES}) +SET(USRP_MPM_XPORT_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/xportmgr_udp.py + ${CMAKE_CURRENT_SOURCE_DIR}/xportmgr_liberio.py +) +LIST(APPEND USRP_MPM_FILES ${USRP_MPM_XPORT_FILES}) +SET(USRP_MPM_FILES ${USRP_MPM_FILES} PARENT_SCOPE) + diff --git a/mpm/python/usrp_mpm/xports/__init__.py b/mpm/python/usrp_mpm/xports/__init__.py new file mode 100644 index 000000000..36d429ad9 --- /dev/null +++ b/mpm/python/usrp_mpm/xports/__init__.py @@ -0,0 +1,11 @@ +# +# Copyright 2017 Ettus Research, National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0 +# +""" +Transport managers +""" + +from .xportmgr_udp import XportMgrUDP +from .xportmgr_liberio import XportMgrLiberio diff --git a/mpm/python/usrp_mpm/xports/xportmgr_liberio.py b/mpm/python/usrp_mpm/xports/xportmgr_liberio.py new file mode 100644 index 000000000..29a3d6673 --- /dev/null +++ b/mpm/python/usrp_mpm/xports/xportmgr_liberio.py @@ -0,0 +1,79 @@ +# +# Copyright 2017 Ettus Research, National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0 +# +""" +Liberio Transport manager +""" + +from builtins import object +from usrp_mpm.liberiotable import LiberioDispatcherTable +from usrp_mpm import libpyusrp_periphs as lib + +class XportMgrLiberio(object): + """ + Transport manager for Liberio connections + """ + # udev label for the UIO device that controls the DMA engine + liberio_label = 'liberio' + # Number of available DMA channels + max_chan = 4 + # Crossbar to which the Liberio DMA engine is connected + xbar_dev = "/dev/crossbar0" + xbar_port = 2 + + def __init__(self, log): + self.log = log + self._dma_dispatcher = LiberioDispatcherTable(self.liberio_label) + self._data_chan_ctr = 0 + + def init(self, args): + """ + Call this when the user calls 'init' on the periph manager + """ + pass + + def deinit(self): + " Clean up after a session terminates " + self._data_chan_ctr = 0 + + def request_xport( + self, + sid, + xport_type, + ): + """ + Return liberio xport info + """ + assert xport_type in ('CTRL', 'ASYNC_MSG', 'TX_DATA', 'RX_DATA') + if xport_type == 'CTRL': + chan = 0 + elif xport_type == 'ASYNC_MSG': + chan = 1 + else: + chan = 2 + self._data_chan_ctr + self._data_chan_ctr += 1 + xport_info = { + 'type': 'liberio', + 'send_sid': str(sid), + 'muxed': str(xport_type in ('CTRL', 'ASYNC_MSG')), + 'dma_chan': str(chan), + 'tx_dev': "/dev/tx-dma{}".format(chan), + 'rx_dev': "/dev/rx-dma{}".format(chan), + } + self.log.trace("Liberio: Chan: {} TX Device: {} RX Device: {}".format( + chan, xport_info['tx_dev'], xport_info['rx_dev'])) + self.log.trace("Liberio channel is muxed: %s", + "Yes" if xport_info['muxed'] else "No") + return [xport_info] + + def commit_xport(self, sid, xport_info): + " Commit liberio transport " + chan = int(xport_info['dma_chan']) + xbar_iface = lib.xbar.xbar.make(self.xbar_dev) + xbar_iface.set_route(sid.src_addr, self.xbar_port) + self._dma_dispatcher.set_route(sid.reversed(), chan) + self.log.trace("Liberio transport successfully committed!") + return True + diff --git a/mpm/python/usrp_mpm/xports/xportmgr_udp.py b/mpm/python/usrp_mpm/xports/xportmgr_udp.py new file mode 100644 index 000000000..18c736150 --- /dev/null +++ b/mpm/python/usrp_mpm/xports/xportmgr_udp.py @@ -0,0 +1,199 @@ +# +# Copyright 2017 Ettus Research, National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0 +# +""" +UDP Transport manager +""" + +from builtins import object +from six import iteritems, itervalues +from usrp_mpm.ethtable import EthDispatcherTable +from usrp_mpm import net +from usrp_mpm.mpmtypes import SID +from usrp_mpm import libpyusrp_periphs as lib + +class XportMgrUDP(object): + """ + Transport manager for UDP connections + """ + # The interface configuration describes how the Ethernet interfaces are + # hooked up to the crossbar and the FPGA. It could look like this: + # iface_config = { + # 'eth1': { # Add key for every Ethernet iface connected to the FPGA + # 'label': 'misc-enet-regs0', # UIO label for the Eth table + # 'xbar': 0, # Which crossbar? 0 -> /dev/crossbar0 + # 'xbar_port': 0, # Which port on the crossbar it is connected to + # }, + # } + iface_config = {} + + def __init__(self, log): + assert len(self.iface_config) + assert all(( + all((key in x for key in ('label', 'xbar', 'xbar_port'))) + for x in itervalues(self.iface_config) + )) + self.log = log + self.log.trace("Initializing UDP xport manager...") + self._possible_chdr_ifaces = self.iface_config.keys() + self.log.trace("Identifying available network interfaces...") + self._chdr_ifaces = \ + self._init_interfaces(self._possible_chdr_ifaces) + self._eth_dispatchers = { + x: EthDispatcherTable(self.iface_config[x]['label']) + for x in self._chdr_ifaces + } + for ifname, table in iteritems(self._eth_dispatchers): + table.set_ipv4_addr(self._chdr_ifaces[ifname]['ip_addr']) + self.chdr_port = EthDispatcherTable.DEFAULT_VITA_PORT[0] + + def _init_interfaces(self, possible_ifaces): + """ + Initialize the list of network interfaces + """ + self.log.trace("Testing available interfaces out of `{}'".format( + possible_ifaces + )) + valid_ifaces = net.get_valid_interfaces(possible_ifaces) + if len(valid_ifaces): + self.log.debug("Found CHDR interfaces: `{}'".format(valid_ifaces)) + else: + self.log.warning("No CHDR interfaces found!") + return { + x: net.get_iface_info(x) + for x in valid_ifaces + } + + def init(self, args): + """ + Call this when the user calls 'init' on the periph manager + """ + # TODO re-run _init_interfaces, IP addresses could have changed since + # bootup + for _, table in iteritems(self._eth_dispatchers): + if 'forward_eth' in args or 'forward_bcast' in args: + table.set_forward_policy( + args.get('forward_eth', False), + args.get('forward_bcast', False) + ) + if 'preload_ethtables' in args: + self._preload_ethtables( + self._eth_dispatchers, + args['preload_ethtables'] + ) + + def deinit(self): + " Clean up after a session terminates " + pass + + def _preload_ethtables(self, eth_dispatchers, table_file): + """ + Populates the ethernet tables from a JSON file + """ + import json + try: + eth_table_data = json.load(open(table_file)) + except ValueError as ex: + self.log.warning( + "Bad values in preloading table file: %s", + str(ex) + ) + return + self.log.info( + "Preloading Ethernet dispatch tables from JSON file `%s'.", + table_file + ) + for eth_iface, data in iteritems(eth_table_data): + if eth_iface not in eth_dispatchers: + self.log.warning( + "Request to preload eth dispatcher table for " + "iface `{}', but no such interface is " + "registered. Known interfaces: {}".format( + str(eth_iface), + ",".join(eth_dispatchers.keys()) + ) + ) + continue + eth_dispatcher = eth_dispatchers[eth_iface] + self.log.debug("Preloading {} dispatch table".format(eth_iface)) + try: + for dst_ep, udp_data in iteritems(data): + sid = SID() + sid.set_dst_ep(int(dst_ep)) + eth_dispatcher.set_route( + sid, + udp_data['ip_addr'], + udp_data['port'], + udp_data.get('mac_addr', None) + ) + except ValueError as ex: + self.log.warning( + "Bad values in preloading table file: %s", + str(ex) + ) + + def get_xbar_dev(self, iface): + """ + Given an Ethernet interface (e.g., 'eth1') returns the crossbar device + it is connected to. + """ + xbar_idx = self.iface_config[iface]['xbar'] + return "/dev/crossbar{}".format(xbar_idx) + + def request_xport( + self, + sid, + xport_type, + ): + """ + Return UDP xport info + """ + assert xport_type in ('CTRL', 'ASYNC_MSG', 'TX_DATA', 'RX_DATA') + # for iface_name, iface_info in iteritems(self._chdr_ifaces): + + xport_info = [ + { + 'type': 'UDP', + 'ipv4': str(iface_info['ip_addr']), + 'port': str(self.chdr_port), + 'send_sid': str(sid) + } + for _, iface_info in iteritems(self._chdr_ifaces) + ] + return xport_info + + def commit_xport(self, sid, xport_info): + """ + fuu + """ + self.log.trace("Sanity checking xport_info %s...", str(xport_info)) + assert xport_info['type'] == 'UDP' + assert any([xport_info['ipv4'] == x['ip_addr'] + for x in itervalues(self._chdr_ifaces)]) + assert xport_info['port'] == str(self.chdr_port) + assert len(xport_info.get('src_ipv4')) > 5 + assert int(xport_info.get('src_port')) > 0 + sender_addr = xport_info['src_ipv4'] + sender_port = int(xport_info['src_port']) + self.log.trace("Incoming connection is coming from %s:%d", + sender_addr, sender_port) + mac_addr = net.get_mac_addr(sender_addr) + if mac_addr is None: + raise RuntimeError( + "Could not find MAC address for IP address {}".format( + sender_addr)) + self.log.trace("Incoming connection is coming from %s", + mac_addr) + eth_iface = net.ip_addr_to_iface(xport_info['ipv4'], self._chdr_ifaces) + xbar_port = self.iface_config[eth_iface]['xbar_port'] + self.log.trace("Using Ethernet interface %s, crossbar port %d", + eth_iface, xbar_port) + xbar_iface = lib.xbar.xbar.make(self.get_xbar_dev(eth_iface)) + xbar_iface.set_route(sid.src_addr, xbar_port) + self._eth_dispatchers[eth_iface].set_route( + sid.reversed(), sender_addr, sender_port) + self.log.trace("UDP transport successfully committed!") + return True + |