1*2d9fd380Sjfb8856606#! /usr/bin/env python3
24418919fSjohnjiang# SPDX-License-Identifier: BSD-3-Clause
3d30ea906Sjfb8856606# Copyright(c) 2018 Intel Corporation
4d30ea906Sjfb8856606
5d30ea906Sjfb8856606import socket
6d30ea906Sjfb8856606import os
7d30ea906Sjfb8856606import sys
8d30ea906Sjfb8856606import time
9d30ea906Sjfb8856606
10d30ea906Sjfb8856606BUFFER_SIZE = 200000
11d30ea906Sjfb8856606
12d30ea906Sjfb8856606METRICS_REQ = "{\"action\":0,\"command\":\"ports_all_stat_values\",\"data\":null}"
13d30ea906Sjfb8856606API_REG = "{\"action\":1,\"command\":\"clients\",\"data\":{\"client_path\":\""
14d30ea906Sjfb8856606API_UNREG = "{\"action\":2,\"command\":\"clients\",\"data\":{\"client_path\":\""
154418919fSjohnjiangGLOBAL_METRICS_REQ = "{\"action\":0,\"command\":\"global_stat_values\",\"data\":null}"
16d30ea906Sjfb8856606DEFAULT_FP = "/var/run/dpdk/default_client"
17d30ea906Sjfb8856606
18d30ea906Sjfb8856606class Socket:
19d30ea906Sjfb8856606
20d30ea906Sjfb8856606    def __init__(self):
21d30ea906Sjfb8856606        self.send_fd = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
22d30ea906Sjfb8856606        self.recv_fd = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
23d30ea906Sjfb8856606        self.client_fd = None
24d30ea906Sjfb8856606
25d30ea906Sjfb8856606    def __del__(self):
26d30ea906Sjfb8856606        try:
27d30ea906Sjfb8856606            self.send_fd.close()
28d30ea906Sjfb8856606            self.recv_fd.close()
29d30ea906Sjfb8856606            self.client_fd.close()
30d30ea906Sjfb8856606        except:
31d30ea906Sjfb8856606            print("Error - Sockets could not be closed")
32d30ea906Sjfb8856606
33d30ea906Sjfb8856606class Client:
34d30ea906Sjfb8856606
35d30ea906Sjfb8856606    def __init__(self): # Creates a client instance
36d30ea906Sjfb8856606        self.socket = Socket()
37d30ea906Sjfb8856606        self.file_path = None
38d30ea906Sjfb8856606        self.choice = None
39d30ea906Sjfb8856606        self.unregistered = 0
40d30ea906Sjfb8856606
41d30ea906Sjfb8856606    def __del__(self):
42d30ea906Sjfb8856606        try:
43d30ea906Sjfb8856606            if self.unregistered == 0:
44d30ea906Sjfb8856606                self.unregister();
45d30ea906Sjfb8856606        except:
46d30ea906Sjfb8856606            print("Error - Client could not be destroyed")
47d30ea906Sjfb8856606
48d30ea906Sjfb8856606    def getFilepath(self, file_path): # Gets arguments from Command-Line and assigns to instance of client
49d30ea906Sjfb8856606        self.file_path = file_path
50d30ea906Sjfb8856606
51d30ea906Sjfb8856606    def register(self): # Connects a client to DPDK-instance
52d30ea906Sjfb8856606        if os.path.exists(self.file_path):
53d30ea906Sjfb8856606            os.unlink(self.file_path)
54d30ea906Sjfb8856606        try:
55d30ea906Sjfb8856606            self.socket.recv_fd.bind(self.file_path)
56d30ea906Sjfb8856606        except socket.error as msg:
57d30ea906Sjfb8856606            print ("Error - Socket binding error: " + str(msg) + "\n")
58d30ea906Sjfb8856606        self.socket.recv_fd.settimeout(2)
59d30ea906Sjfb8856606        self.socket.send_fd.connect("/var/run/dpdk/rte/telemetry")
60d30ea906Sjfb8856606        JSON = (API_REG + self.file_path + "\"}}")
614418919fSjohnjiang        self.socket.send_fd.sendall(JSON.encode())
624418919fSjohnjiang
63d30ea906Sjfb8856606        self.socket.recv_fd.listen(1)
64d30ea906Sjfb8856606        self.socket.client_fd = self.socket.recv_fd.accept()[0]
65d30ea906Sjfb8856606
66d30ea906Sjfb8856606    def unregister(self): # Unregister a given client
674418919fSjohnjiang        self.socket.client_fd.send((API_UNREG + self.file_path + "\"}}").encode())
68d30ea906Sjfb8856606        self.socket.client_fd.close()
69d30ea906Sjfb8856606
70d30ea906Sjfb8856606    def requestMetrics(self): # Requests metrics for given client
714418919fSjohnjiang        self.socket.client_fd.send(METRICS_REQ.encode())
724418919fSjohnjiang        data = self.socket.client_fd.recv(BUFFER_SIZE).decode()
734418919fSjohnjiang        print("\nResponse: \n", data)
74d30ea906Sjfb8856606
75d30ea906Sjfb8856606    def repeatedlyRequestMetrics(self, sleep_time): # Recursively requests metrics for given client
76d30ea906Sjfb8856606        print("\nPlease enter the number of times you'd like to continuously request Metrics:")
77*2d9fd380Sjfb8856606        n_requests = int(input("\n:"))
78d30ea906Sjfb8856606        print("\033[F") #Removes the user input from screen, cleans it up
79d30ea906Sjfb8856606        print("\033[K")
80d30ea906Sjfb8856606        for i in range(n_requests):
81d30ea906Sjfb8856606            self.requestMetrics()
82d30ea906Sjfb8856606            time.sleep(sleep_time)
83d30ea906Sjfb8856606
844418919fSjohnjiang    def requestGlobalMetrics(self): #Requests global metrics for given client
854418919fSjohnjiang        self.socket.client_fd.send(GLOBAL_METRICS_REQ.encode())
864418919fSjohnjiang        data = self.socket.client_fd.recv(BUFFER_SIZE).decode()
874418919fSjohnjiang        print("\nResponse: \n", data)
884418919fSjohnjiang
89d30ea906Sjfb8856606    def interactiveMenu(self, sleep_time): # Creates Interactive menu within the script
904418919fSjohnjiang        while self.choice != 4:
91d30ea906Sjfb8856606            print("\nOptions Menu")
92d30ea906Sjfb8856606            print("[1] Send for Metrics for all ports")
93d30ea906Sjfb8856606            print("[2] Send for Metrics for all ports recursively")
944418919fSjohnjiang            print("[3] Send for global Metrics")
954418919fSjohnjiang            print("[4] Unregister client")
96d30ea906Sjfb8856606
97d30ea906Sjfb8856606            try:
98*2d9fd380Sjfb8856606                self.choice = int(input("\n:"))
99d30ea906Sjfb8856606                print("\033[F") #Removes the user input for screen, cleans it up
100d30ea906Sjfb8856606                print("\033[K")
101d30ea906Sjfb8856606                if self.choice == 1:
102d30ea906Sjfb8856606                    self.requestMetrics()
103d30ea906Sjfb8856606                elif self.choice == 2:
104d30ea906Sjfb8856606                    self.repeatedlyRequestMetrics(sleep_time)
105d30ea906Sjfb8856606                elif self.choice == 3:
1064418919fSjohnjiang                    self.requestGlobalMetrics()
1074418919fSjohnjiang                elif self.choice == 4:
108d30ea906Sjfb8856606                    self.unregister()
109d30ea906Sjfb8856606                    self.unregistered = 1
110d30ea906Sjfb8856606                else:
111d30ea906Sjfb8856606                    print("Error - Invalid request choice")
112d30ea906Sjfb8856606            except:
113d30ea906Sjfb8856606                pass
114d30ea906Sjfb8856606
115d30ea906Sjfb8856606if __name__ == "__main__":
116d30ea906Sjfb8856606
117d30ea906Sjfb8856606    sleep_time = 1
118d30ea906Sjfb8856606    file_path = ""
119*2d9fd380Sjfb8856606    if len(sys.argv) == 2:
120d30ea906Sjfb8856606        file_path = sys.argv[1]
121d30ea906Sjfb8856606    else:
122d30ea906Sjfb8856606        print("Warning - No filepath passed, using default (" + DEFAULT_FP + ").")
123d30ea906Sjfb8856606        file_path = DEFAULT_FP
124d30ea906Sjfb8856606    client = Client()
125d30ea906Sjfb8856606    client.getFilepath(file_path)
126d30ea906Sjfb8856606    client.register()
127d30ea906Sjfb8856606    client.interactiveMenu(sleep_time)
128