xref: /dpdk/usertools/dpdk-telemetry-client.py (revision ead4bbee2287350a7a325df18f955b0b8751e88d)
13f6f8362SLouise Kilheeney#! /usr/bin/env python3
2564f295dSBruce Richardson# SPDX-License-Identifier: BSD-3-Clause
3d1b94da4SCiara Power# Copyright(c) 2018 Intel Corporation
4d1b94da4SCiara Power
5d1b94da4SCiara Powerimport socket
6d1b94da4SCiara Powerimport os
7d1b94da4SCiara Powerimport time
82afa9b43SHuisong Liimport argparse
9d1b94da4SCiara Power
10d1b94da4SCiara PowerBUFFER_SIZE = 200000
11d1b94da4SCiara Power
12d1b94da4SCiara PowerMETRICS_REQ = "{\"action\":0,\"command\":\"ports_all_stat_values\",\"data\":null}"
13d1b94da4SCiara PowerAPI_REG = "{\"action\":1,\"command\":\"clients\",\"data\":{\"client_path\":\""
14d1b94da4SCiara PowerAPI_UNREG = "{\"action\":2,\"command\":\"clients\",\"data\":{\"client_path\":\""
154080e46cSReshma PattanGLOBAL_METRICS_REQ = "{\"action\":0,\"command\":\"global_stat_values\",\"data\":null}"
16d1b94da4SCiara PowerDEFAULT_FP = "/var/run/dpdk/default_client"
17a15fc792SHuisong LiDEFAULT_PREFIX = 'rte'
18a15fc792SHuisong LiRUNTIME_SOCKET_NAME = 'telemetry'
19d1b94da4SCiara Power
202c4f389bSStephen Hemminger
21d1b94da4SCiara Powerclass Socket:
22d1b94da4SCiara Power
23d1b94da4SCiara Power    def __init__(self):
24d1b94da4SCiara Power        self.send_fd = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
25d1b94da4SCiara Power        self.recv_fd = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
26d1b94da4SCiara Power        self.client_fd = None
27d1b94da4SCiara Power
28d1b94da4SCiara Power    def __del__(self):
29d1b94da4SCiara Power        try:
30d1b94da4SCiara Power            self.send_fd.close()
31d1b94da4SCiara Power            self.recv_fd.close()
32d1b94da4SCiara Power            self.client_fd.close()
33d1b94da4SCiara Power        except:
34d1b94da4SCiara Power            print("Error - Sockets could not be closed")
35d1b94da4SCiara Power
362c4f389bSStephen Hemminger
37d1b94da4SCiara Powerclass Client:
38d1b94da4SCiara Power
392c4f389bSStephen Hemminger    def __init__(self):
402c4f389bSStephen Hemminger        # Creates a client instance
41d1b94da4SCiara Power        self.socket = Socket()
42d1b94da4SCiara Power        self.file_path = None
43a15fc792SHuisong Li        self.run_path = None
44d1b94da4SCiara Power        self.choice = None
45d1b94da4SCiara Power        self.unregistered = 0
46d1b94da4SCiara Power
47d1b94da4SCiara Power    def __del__(self):
48d1b94da4SCiara Power        try:
49d1b94da4SCiara Power            if self.unregistered == 0:
502c4f389bSStephen Hemminger                self.unregister()
51d1b94da4SCiara Power        except:
52d1b94da4SCiara Power            print("Error - Client could not be destroyed")
53d1b94da4SCiara Power
542c4f389bSStephen Hemminger    def getFilepath(self, file_path):
552c4f389bSStephen Hemminger        # Gets arguments from Command-Line and assigns to instance of client
56d1b94da4SCiara Power        self.file_path = file_path
57d1b94da4SCiara Power
58*ead4bbeeSSamina Arshad    def setRunpath(self, file_prefix):
59*ead4bbeeSSamina Arshad        self.run_path = os.path.join(get_dpdk_runtime_dir(file_prefix),
60a15fc792SHuisong Li                                     RUNTIME_SOCKET_NAME)
61a15fc792SHuisong Li
622c4f389bSStephen Hemminger    def register(self):
632c4f389bSStephen Hemminger        # Connects a client to DPDK-instance
64d1b94da4SCiara Power        if os.path.exists(self.file_path):
65d1b94da4SCiara Power            os.unlink(self.file_path)
66d1b94da4SCiara Power        try:
67d1b94da4SCiara Power            self.socket.recv_fd.bind(self.file_path)
68d1b94da4SCiara Power        except socket.error as msg:
69d1b94da4SCiara Power            print("Error - Socket binding error: " + str(msg) + "\n")
70d1b94da4SCiara Power        self.socket.recv_fd.settimeout(2)
71a15fc792SHuisong Li        self.socket.send_fd.connect(self.run_path)
72d1b94da4SCiara Power        JSON = (API_REG + self.file_path + "\"}}")
73af927da4SCiara Power        self.socket.send_fd.sendall(JSON.encode())
74af927da4SCiara Power
75d1b94da4SCiara Power        self.socket.recv_fd.listen(1)
76d1b94da4SCiara Power        self.socket.client_fd = self.socket.recv_fd.accept()[0]
77d1b94da4SCiara Power
782c4f389bSStephen Hemminger    def unregister(self):
792c4f389bSStephen Hemminger        # Unregister a given client
80af927da4SCiara Power        self.socket.client_fd.send((API_UNREG + self.file_path + "\"}}").encode())
81d1b94da4SCiara Power        self.socket.client_fd.close()
82d1b94da4SCiara Power
832c4f389bSStephen Hemminger    def requestMetrics(self):
842c4f389bSStephen Hemminger        # Requests metrics for given client
85af927da4SCiara Power        self.socket.client_fd.send(METRICS_REQ.encode())
86af927da4SCiara Power        data = self.socket.client_fd.recv(BUFFER_SIZE).decode()
87af927da4SCiara Power        print("\nResponse: \n", data)
88d1b94da4SCiara Power
892c4f389bSStephen Hemminger    def repeatedlyRequestMetrics(self, sleep_time):
902c4f389bSStephen Hemminger        # Recursively requests metrics for given client
91d1b94da4SCiara Power        print("\nPlease enter the number of times you'd like to continuously request Metrics:")
923f6f8362SLouise Kilheeney        n_requests = int(input("\n:"))
932c4f389bSStephen Hemminger        # Removes the user input from screen, cleans it up
942c4f389bSStephen Hemminger        print("\033[F")
95d1b94da4SCiara Power        print("\033[K")
96d1b94da4SCiara Power        for i in range(n_requests):
97d1b94da4SCiara Power            self.requestMetrics()
98d1b94da4SCiara Power            time.sleep(sleep_time)
99d1b94da4SCiara Power
1002c4f389bSStephen Hemminger    def requestGlobalMetrics(self):
1012c4f389bSStephen Hemminger        # Requests global metrics for given client
102af927da4SCiara Power        self.socket.client_fd.send(GLOBAL_METRICS_REQ.encode())
103af927da4SCiara Power        data = self.socket.client_fd.recv(BUFFER_SIZE).decode()
104af927da4SCiara Power        print("\nResponse: \n", data)
1054080e46cSReshma Pattan
1062c4f389bSStephen Hemminger    def interactiveMenu(self, sleep_time):
1072c4f389bSStephen Hemminger        # Creates Interactive menu within the script
1084080e46cSReshma Pattan        while self.choice != 4:
109d1b94da4SCiara Power            print("\nOptions Menu")
110d1b94da4SCiara Power            print("[1] Send for Metrics for all ports")
111d1b94da4SCiara Power            print("[2] Send for Metrics for all ports recursively")
1124080e46cSReshma Pattan            print("[3] Send for global Metrics")
1134080e46cSReshma Pattan            print("[4] Unregister client")
114d1b94da4SCiara Power
115d1b94da4SCiara Power            try:
1163f6f8362SLouise Kilheeney                self.choice = int(input("\n:"))
1172c4f389bSStephen Hemminger                # Removes the user input for screen, cleans it up
1182c4f389bSStephen Hemminger                print("\033[F")
119d1b94da4SCiara Power                print("\033[K")
120d1b94da4SCiara Power                if self.choice == 1:
121d1b94da4SCiara Power                    self.requestMetrics()
122d1b94da4SCiara Power                elif self.choice == 2:
123d1b94da4SCiara Power                    self.repeatedlyRequestMetrics(sleep_time)
124d1b94da4SCiara Power                elif self.choice == 3:
1254080e46cSReshma Pattan                    self.requestGlobalMetrics()
1264080e46cSReshma Pattan                elif self.choice == 4:
127d1b94da4SCiara Power                    self.unregister()
128d1b94da4SCiara Power                    self.unregistered = 1
129d1b94da4SCiara Power                else:
130d1b94da4SCiara Power                    print("Error - Invalid request choice")
131d1b94da4SCiara Power            except:
132d1b94da4SCiara Power                pass
133d1b94da4SCiara Power
134a15fc792SHuisong Li
135a15fc792SHuisong Lidef get_dpdk_runtime_dir(fp):
136a15fc792SHuisong Li    """ Using the same logic as in DPDK's EAL, get the DPDK runtime directory
137a15fc792SHuisong Li    based on the file-prefix and user """
138a15fc792SHuisong Li    run_dir = os.environ.get('RUNTIME_DIRECTORY')
139a15fc792SHuisong Li    if not run_dir:
140a15fc792SHuisong Li        if (os.getuid() == 0):
141a15fc792SHuisong Li            run_dir = '/var/run'
142a15fc792SHuisong Li        else:
143a15fc792SHuisong Li            run_dir = os.environ.get('XDG_RUNTIME_DIR', '/tmp')
144a15fc792SHuisong Li    return os.path.join(run_dir, 'dpdk', fp)
145a15fc792SHuisong Li
146a15fc792SHuisong Li
147d1b94da4SCiara Powerif __name__ == "__main__":
148d1b94da4SCiara Power
149d1b94da4SCiara Power    sleep_time = 1
1502afa9b43SHuisong Li    parser = argparse.ArgumentParser()
151a15fc792SHuisong Li    parser.add_argument('-f', '--file-prefix', default=DEFAULT_PREFIX,
152a15fc792SHuisong Li                        help='Provide file-prefix for DPDK runtime directory')
1532afa9b43SHuisong Li    parser.add_argument('sock_path', nargs='?', default=DEFAULT_FP,
1542afa9b43SHuisong Li                        help='Provide socket file path connected by legacy client')
1552afa9b43SHuisong Li    args = parser.parse_args()
1562afa9b43SHuisong Li
157d1b94da4SCiara Power    client = Client()
1582afa9b43SHuisong Li    client.getFilepath(args.sock_path)
159a15fc792SHuisong Li    client.setRunpath(args.file_prefix)
160d1b94da4SCiara Power    client.register()
161d1b94da4SCiara Power    client.interactiveMenu(sleep_time)
162