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