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