T-Rex: Add advanced stateful mode
[csit.git] / GPL / tools / trex / trex_astf_stop.py
1 #!/usr/bin/python3
2
3 # Copyright (c) 2020 Cisco and/or its affiliates.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """This script uses T-REX advanced stateful API to drive t-rex instance.
17
18 Requirements:
19 - T-REX: https://github.com/cisco-system-traffic-generator/trex-core
20  - compiled and running T-REX process (eg. ./t-rex-64 -i)
21  - trex.astf.api library
22 - Script must be executed on a node with T-REX instance
23
24 Functionality:
25 1. Stop any running traffic
26 2. Optionally restore reference counter values.
27 3. Return conter differences.
28 """
29
30 import argparse
31 import json
32 import sys
33
34 from collections import OrderedDict  # Needed to parse xstats representation.
35
36 sys.path.insert(
37     0, u"/opt/trex-core-2.73/scripts/automation/trex_control_plane/interactive/"
38 )
39 from trex.astf.api import *
40
41
42 def main():
43     """Stop traffic if any is running. Report xstats."""
44     parser = argparse.ArgumentParser()
45     parser.add_argument(
46         u"--xstat0", type=str, default=u"",
47         help=u"Reference xstat object if any."
48     )
49     parser.add_argument(
50         u"--xstat1", type=str, default=u"",
51         help=u"Reference xstat object if any."
52     )
53     args = parser.parse_args()
54
55     client = ASTFClient()
56     try:
57         # connect to server
58         client.connect()
59
60         client.acquire(force=True)
61         client.stop()
62
63         # Read the stats after the test,
64         # we need to update values before the last trial started.
65         if args.xstat0:
66             snapshot = eval(args.xstat0)
67             client.ports[0].get_xstats().reference_stats = snapshot
68         if args.xstat1:
69             snapshot = eval(args.xstat1)
70             client.ports[1].get_xstats().reference_stats = snapshot
71         # Now we can call the official method to get differences.
72         xstats0 = client.get_xstats(0)
73         xstats1 = client.get_xstats(1)
74
75     # If TRexError happens, let the script fail with stack trace.
76     finally:
77         client.clear_profile()
78         client.disconnect()
79
80     # TODO: check xstats format
81     print(u"##### statistics port 0 #####")
82     print(json.dumps(xstats0, indent=4, separators=(u",", u": ")))
83     print(u"##### statistics port 1 #####")
84     print(json.dumps(xstats1, indent=4, separators=(u",", u": ")))
85
86     tx_0, rx_0 = xstats0[u"tx_good_packets"], xstats0[u"rx_good_packets"]
87     tx_1, rx_1 = xstats1[u"tx_good_packets"], xstats1[u"rx_good_packets"]
88     lost_a, lost_b = tx_0 - rx_1, tx_1 - rx_0
89
90     client_stats = xstats0[u"traffic"][u"client"]
91     server_stats = xstats1[u"traffic"][u"server"]
92     # Active and established flows UDP/TCP
93     # Client
94     c_act_flows = client_stats[u"m_active_flows"]
95     c_est_flows = client_stats[u"m_est_flows"]
96     l7_data = f"client_active_flows={c_act_flows}, "
97     l7_data += f"client_established_flows={c_est_flows}, "
98     # Server
99     s_act_flows = server_stats[u"m_active_flows"]
100     s_est_flows = server_stats[u"m_est_flows"]
101     l7_data += f"server_active_flows={s_act_flows}, "
102     l7_data += f"server_established_flows={s_est_flows}, "
103     # Some zero counters are not sent
104     # Client
105     # Established connections
106     c_udp_connects = client_stats.get(u"udps_connects", 0)
107     l7_data += f"client_udp_connects={c_udp_connects}, "
108     # Closed connections
109     c_udp_closed = client_stats.get(u"udps_closed", 0)
110     l7_data += f"client_udp_closed={c_udp_closed}, "
111     # Server
112     # Accepted connections
113     s_udp_accepts = server_stats.get(u"udps_accepts", 0)
114     l7_data += f"server_udp_accepts={s_udp_accepts}, "
115     # Closed connections
116     s_udp_closed = server_stats.get(u"udps_closed", 0)
117     # Client
118     # Initiated connections
119     c_tcp_connatt = client_stats.get(u"tcps_connattempt", 0)
120     l7_data += f"client_tcp_connect_inits={c_tcp_connatt}, "
121     # Established connections
122     c_tcp_connects = client_stats.get(u"tcps_connects", 0)
123     l7_data += f"client_tcp_connects={c_tcp_connects}, "
124     # Closed connections
125     c_tcp_closed = client_stats.get(u"tcps_closed", 0)
126     l7_data += f"client_tcp_closed={c_tcp_closed}, "
127     # Server
128     # Accepted connections
129     s_tcp_accepts = server_stats.get(u"tcps_accepts", 0)
130     l7_data += f"server_tcp_accepts={s_tcp_accepts}, "
131     # Established connections
132     s_tcp_connects = server_stats.get(u"tcps_connects", 0)
133     l7_data += f"server_tcp_connects={s_tcp_connects}, "
134     # Closed connections
135     s_tcp_closed = server_stats.get(u"tcps_closed", 0)
136     l7_data += f"server_tcp_closed={s_tcp_closed}, "
137
138     print(f"packets lost from 0 --> 1:   {lost_a} pkts")
139     print(f"packets lost from 1 --> 0:   {lost_b} pkts")
140
141     total_rcvd, total_sent = rx_0 + rx_1, tx_0 + tx_1
142     total_lost = total_sent - total_rcvd
143     # TODO: Add latency.
144     print(
145         f"cps='unknown', total_received={total_rcvd}, total_sent={total_sent}, "
146         f"frame_loss={total_lost}, "
147         f"latency_stream_0(usec)=-1/-1/-1, latency_stream_1(usec)=-1/-1/-1, "
148         u"latency_hist_stream_0={}, latency_hist_stream_1={}, "
149         f"{l7_data}"
150     )
151
152
153 if __name__ == u"__main__":
154     main()