dpdk/usertools/dpdk-telemetry.py
<<
>>
Prefs
   1#! /usr/bin/env python3
   2# SPDX-License-Identifier: BSD-3-Clause
   3# Copyright(c) 2020 Intel Corporation
   4
   5"""
   6Script to be used with V2 Telemetry.
   7Allows the user input commands and read the Telemetry response.
   8"""
   9
  10import socket
  11import os
  12import glob
  13import json
  14import errno
  15import readline
  16import argparse
  17
  18# global vars
  19TELEMETRY_VERSION = "v2"
  20CMDS = []
  21
  22
  23def read_socket(sock, buf_len, echo=True):
  24    """ Read data from socket and return it in JSON format """
  25    reply = sock.recv(buf_len).decode()
  26    try:
  27        ret = json.loads(reply)
  28    except json.JSONDecodeError:
  29        print("Error in reply: ", reply)
  30        sock.close()
  31        raise
  32    if echo:
  33        print(json.dumps(ret))
  34    return ret
  35
  36
  37def get_app_name(pid):
  38    """ return the app name for a given PID, for printing """
  39    proc_cmdline = os.path.join('/proc', str(pid), 'cmdline')
  40    try:
  41        with open(proc_cmdline) as f:
  42            argv0 = f.read(1024).split('\0')[0]
  43            return os.path.basename(argv0)
  44    except IOError as e:
  45        # ignore file not found errors
  46        if e.errno != errno.ENOENT:
  47            raise
  48    return None
  49
  50
  51def handle_socket(path):
  52    """ Connect to socket and handle user input """
  53    sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
  54    global CMDS
  55    print("Connecting to " + path)
  56    try:
  57        sock.connect(path)
  58    except OSError:
  59        print("Error connecting to " + path)
  60        sock.close()
  61        return
  62    json_reply = read_socket(sock, 1024)
  63    output_buf_len = json_reply["max_output_len"]
  64    app_name = get_app_name(json_reply["pid"])
  65    if app_name:
  66        print('Connected to application: "%s"' % app_name)
  67
  68    # get list of commands for readline completion
  69    sock.send("/".encode())
  70    CMDS = read_socket(sock, output_buf_len, False)["/"]
  71
  72    # interactive prompt
  73    text = input('--> ').strip()
  74    while text != "quit":
  75        if text.startswith('/'):
  76            sock.send(text.encode())
  77            read_socket(sock, output_buf_len)
  78        text = input('--> ').strip()
  79    sock.close()
  80
  81
  82def readline_complete(text, state):
  83    """ Find any matching commands from the list based on user input """
  84    all_cmds = ['quit'] + CMDS
  85    if text:
  86        matches = [c for c in all_cmds if c.startswith(text)]
  87    else:
  88        matches = all_cmds
  89    return matches[state]
  90
  91
  92def get_dpdk_runtime_dir(fp):
  93    """ Using the same logic as in DPDK's EAL, get the DPDK runtime directory
  94    based on the file-prefix and user """
  95    if (os.getuid() == 0):
  96        return os.path.join('/var/run/dpdk', fp)
  97    return os.path.join(os.environ.get('XDG_RUNTIME_DIR', '/tmp'), 'dpdk', fp)
  98
  99
 100readline.parse_and_bind('tab: complete')
 101readline.set_completer(readline_complete)
 102readline.set_completer_delims(readline.get_completer_delims().replace('/', ''))
 103
 104parser = argparse.ArgumentParser()
 105parser.add_argument('-f', '--file-prefix', \
 106        help='Provide file-prefix for DPDK runtime directory', default='rte')
 107args = parser.parse_args()
 108rdir = get_dpdk_runtime_dir(args.file_prefix)
 109handle_socket(os.path.join(rdir, 'dpdk_telemetry.{}'.format(TELEMETRY_VERSION)))
 110