uhd/mpm/python/usrp_mpm/discovery.py
Lars Amsel 6e2a65e700 mpm: add device name to discovery process
MPM devices currently do not report their device name in the discovery
process. This adds the device name. After the change the device name
is reported, e.g. when using uhd_find_devices, like so:

    $> uhd_find_devices
    --------------------------------------------------
    -- UHD Device 0
    --------------------------------------------------
    Device Address:
        serial: DEADBEEF
        claimed: False
        fpga: X4_200
        mgmt_addr: <mpm device ip>
        name: <mpm device host name>
        product: x410
        type: x4xx
2022-02-08 13:55:35 -06:00

99 lines
3.5 KiB
Python

#
# Copyright 2017 Ettus Research, a National Instruments Company
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
"""
Code to run the discovery port
"""
from multiprocessing import Process
import socket
from usrp_mpm.mpmtypes import MPM_DISCOVERY_PORT
from usrp_mpm.mpmlog import get_main_logger
from usrp_mpm.mpmutils import to_binary_str
RESPONSE_PREAMBLE = b"USRP-MPM"
RESPONSE_SEP = b";"
RESPONSE_CLAIMED_KEY = b"claimed"
# A buffer size large enough to capture any UDP packet we receive on the
# discovery socket
MAX_SOCK_BUFSIZ = 9000
# For setsockopt
IP_MTU_DISCOVER = 10
IP_PMTUDISC_DO = 2
def spawn_discovery_process(shared_state, discovery_addr):
"""
Returns a process that contains the device discovery.
Arguments:
shared_state -- Shared state of device (is it claimed, etc.). Is a
SharedState() object.
discovery_addr -- Discovery will listen on this address(es)
"""
proc = Process(
target=_discovery_process,
args=(shared_state, discovery_addr)
)
proc.start()
return proc
def _discovery_process(state, discovery_addr):
"""
The actual process for device discovery. Is spawned by
spawn_discovery_process().
"""
log = get_main_logger().getChild('discovery')
def create_response_string(state):
" Generate the string that gets sent back to the requester. "
return RESPONSE_SEP.join(
[RESPONSE_PREAMBLE] + \
[b"type="+state.dev_type.value] + \
[b"product="+state.dev_product.value] + \
[b"serial="+state.dev_serial.value] + \
[b"name="+state.dev_name.value] + \
[b"fpga="+state.dev_fpga_type.value] + \
[RESPONSE_CLAIMED_KEY+to_binary_str("={}".format(state.claim_status.value))]
)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# FIXME really, we should only bind to the subnet but I haven't gotten that
# working yet
sock.bind((("0.0.0.0", MPM_DISCOVERY_PORT)))
send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
send_sock.setsockopt(socket.IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DO)
# TODO yeah I know that's not how you do this
discovery_addr_prefix = discovery_addr.replace('.255', '')
if discovery_addr == '0.0.0.0':
discovery_addr_prefix = ''
try:
while True:
data, sender = sock.recvfrom(MAX_SOCK_BUFSIZ)
log.debug("Got poked by: %s", sender[0])
# TODO this is still part of the awful subnet identification
if not sender[0].startswith(discovery_addr_prefix):
continue
if data.strip(b"\0") == b"MPM-DISC":
log.debug("Sending discovery response to %s port: %d",
sender[0], sender[1])
resp_str = create_response_string(state)
send_data = resp_str
log.trace("Return data: %s", send_data)
send_sock.sendto(send_data, sender)
elif data.strip(b"\0").startswith(b"MPM-ECHO"):
log.debug("Received echo request from {sender}"
.format(sender=sender[0]))
send_data = data
try:
send_sock.sendto(send_data, sender)
except OSError as ex:
log.warning("ECHO send error: %s", str(ex))
except Exception as err:
log.error("Unexpected error: `%s' Type: `%s'", str(err), type(err))
sock.close()
send_sock.close()
exit(1)