Python3: TRex driver
[csit.git] / resources / traffic_profiles / trex / profile_trex_stateless_base_class.py
1 # Copyright (c) 2019 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """Base class for stream profiles for T-rex traffic generator.
15 """
16
17 import sys
18 import socket
19 import struct
20
21 from random import choice
22 from string import ascii_letters
23
24 from trex.stl.api import *
25
26
27 class TrafficStreamsBaseClass(object):
28     """Base class for stream profiles for T-rex traffic generator."""
29     STREAM_TABLE = {
30         'IMIX_v4': [
31             {'size': 60, 'pps': 28, 'isg': 0},
32             {'size': 590, 'pps': 20, 'isg': 0.1},
33             {'size': 1514, 'pps': 4, 'isg': 0.2}
34         ],
35         'IMIX_v4_1': [
36             {'size': 64, 'pps': 28, 'isg': 0},
37             {'size': 570, 'pps': 16, 'isg': 0.1},
38             {'size': 1518, 'pps': 4, 'isg': 0.2}
39         ]
40     }
41
42     def __init__(self):
43         # Default value of frame size, it will be overwritten by the value of
44         # "framesize" parameter of "get_streams" method.
45         self.framesize = 64
46
47         # If needed, add your own parameters.
48
49     def _gen_payload(self, length):
50         """Generate payload.
51
52         If needed, implement your own algorithm.
53
54         :param length: Length of generated payload.
55         :type length: int
56         :returns: The generated payload.
57         :rtype: str
58         """
59         payload = ""
60         for _ in range(length):
61             payload += choice(ascii_letters)
62
63         return payload
64
65     def _get_start_end_ipv6(self, start_ip, end_ip):
66         """Get start host and number of hosts from IPv6 as integer.
67
68         :param start_ip: Start IPv6.
69         :param end_ip: End IPv6.
70         :type start_ip: string
71         :type end_ip: string
72         :return: Start host, number of hosts.
73         :rtype tuple of int
74         :raises: ValueError if start_ip is greater then end_ip.
75         :raises: socket.error if the IP addresses are not valid IPv6 addresses.
76         """
77         try:
78             ip1 = socket.inet_pton(socket.AF_INET6, start_ip)
79             ip2 = socket.inet_pton(socket.AF_INET6, end_ip)
80
81             hi1, lo1 = struct.unpack('!QQ', ip1)
82             hi2, lo2 = struct.unpack('!QQ', ip2)
83
84             if ((hi1 << 64) | lo1) > ((hi2 << 64) | lo2):
85                 raise ValueError("IPv6: start_ip is greater then end_ip")
86
87             return lo1, abs(int(lo1) - int(lo2))
88
89         except socket.error as err:
90             print(err)
91             raise
92
93     def define_packets(self):
94         """Define the packets to be sent from the traffic generator.
95
96         This method MUST return:
97
98             return base_pkt_a, base_pkt_b, vm1, vm2
99
100             vm1 and vm2 CAN be None.
101
102         :returns: Packets to be sent from the traffic generator.
103         :rtype: tuple
104         """
105         raise NotImplementedError
106
107     def create_streams(self):
108         """Create traffic streams.
109
110         Implement your own traffic streams.
111
112         :returns: Traffic streams.
113         :rtype: list
114         """
115         base_pkt_a, base_pkt_b, vm1, vm2 = self.define_packets()
116
117         # In most cases you will not have to change the code below:
118
119         # Frame size is defined as an integer, e.g. 64, 1518:
120         if isinstance(self.framesize, int):
121
122             # Create a base packet and pad it to size
123             payload_len = max(0, self.framesize - len(base_pkt_a) - 4)  # No FCS
124
125             # Direction 0 --> 1
126             pkt_a = STLPktBuilder(
127                 pkt=base_pkt_a / self._gen_payload(payload_len), vm=vm1)
128             # Direction 1 --> 0
129             pkt_b = STLPktBuilder(
130                 pkt=base_pkt_b / self._gen_payload(payload_len), vm=vm2)
131
132             # Packets for latency measurement:
133             # Direction 0 --> 1
134             pkt_lat_a = STLPktBuilder(
135                 pkt=base_pkt_a / self._gen_payload(payload_len), vm=vm1)
136             # Direction 1 --> 0
137             pkt_lat_b = STLPktBuilder(
138                 pkt=base_pkt_b / self._gen_payload(payload_len), vm=vm2)
139
140             # Create the streams:
141             # Direction 0 --> 1
142             stream1 = STLStream(packet=pkt_a, mode=STLTXCont(pps=9000))
143             # Direction 1 --> 0
144             # second traffic stream with a phase of 10ns (inter-stream gap)
145             stream2 = STLStream(packet=pkt_b, isg=10.0,
146                                 mode=STLTXCont(pps=9000))
147
148             # Streams for latency measurement:
149             # Direction 0 --> 1
150             lat_stream1 = STLStream(packet=pkt_lat_a,
151                                     flow_stats=STLFlowLatencyStats(pg_id=0),
152                                     mode=STLTXCont(pps=9000))
153             # Direction 1 --> 0
154             # second traffic stream with a phase of 10ns (inter-stream gap)
155             lat_stream2 = STLStream(packet=pkt_lat_b, isg=10.0,
156                                     flow_stats=STLFlowLatencyStats(pg_id=1),
157                                     mode=STLTXCont(pps=9000))
158
159             return [stream1, stream2, lat_stream1, lat_stream2]
160
161         # Frame size is defined as a string, e.g.IMIX_v4_1:
162         elif isinstance(self.framesize, str):
163
164             stream1 = []
165             stream2 = []
166
167             for stream in self.STREAM_TABLE[self.framesize]:
168                 payload_len_a = max(0, stream['size'] - len(base_pkt_a) - 4)
169                 payload_len_b = max(0, stream['size'] - len(base_pkt_b) - 4)
170                 # Create a base packet and pad it to size
171                 pkt_a = STLPktBuilder(
172                     pkt=base_pkt_a / self._gen_payload(payload_len_a),
173                     vm=vm1)
174                 pkt_b = STLPktBuilder(
175                     pkt=base_pkt_b / self._gen_payload(payload_len_b),
176                     vm=vm2)
177
178                 # Create the streams:
179                 stream1.append(STLStream(packet=pkt_a,
180                                          isg=stream['isg'],
181                                          mode=STLTXCont(pps=stream['pps'])))
182                 stream2.append(STLStream(packet=pkt_b,
183                                          isg=stream['isg'],
184                                          mode=STLTXCont(pps=stream['pps'])))
185             streams = list()
186             streams.extend(stream1)
187             streams.extend(stream2)
188
189             return streams
190
191     def get_streams(self, **kwargs):
192         """Get traffic streams created by "create_streams" method.
193
194         If needed, add your own parameters.
195
196         :param kwargs: Key-value pairs used by "create_streams" method while
197         creating streams.
198         :returns: Traffic streams.
199         :rtype: list
200         """
201         self.framesize = kwargs['framesize']
202
203         return self.create_streams()