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