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