diff options
| -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 +  | 
