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