1 # Copyright (c) 2021 Cisco and/or its affiliates.
3 # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
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:
10 # http://www.apache.org/licenses/LICENSE-2.0
11 # https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
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.
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.
23 """Base class for stream profiles for T-rex traffic generator.
29 from random import choice
30 from string import ascii_letters
32 from trex.stl.api import *
35 class TrafficStreamsBaseClass:
36 """Base class for stream profiles for T-rex traffic generator."""
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}
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}
52 # Default value of frame size, it will be overwritten by the value of
53 # "framesize" parameter of "get_streams" method.
56 # If needed, add your own parameters.
58 def _gen_payload(self, length):
61 If needed, implement your own algorithm.
63 :param length: Length of generated payload.
65 :returns: The generated payload.
69 for _ in range(length):
70 payload += choice(ascii_letters)
74 def _get_start_end_ipv6(self, start_ip, end_ip):
75 """Get start host and number of hosts from IPv6 as integer.
77 :param start_ip: Start IPv6.
78 :param end_ip: End IPv6.
79 :type start_ip: string
81 :return: Start host, number of hosts.
83 :raises: ValueError if start_ip is greater then end_ip.
84 :raises: socket.error if the IP addresses are not valid IPv6 addresses.
87 ip1 = socket.inet_pton(socket.AF_INET6, start_ip)
88 ip2 = socket.inet_pton(socket.AF_INET6, end_ip)
90 hi1, lo1 = struct.unpack(u"!QQ", ip1)
91 hi2, lo2 = struct.unpack(u"!QQ", ip2)
93 if ((hi1 << 64) | lo1) > ((hi2 << 64) | lo2):
94 raise ValueError(u"IPv6: start_ip is greater then end_ip")
96 return lo1, abs(int(lo1) - int(lo2))
98 except socket.error as err:
102 def define_packets(self):
103 """Define the packets to be sent from the traffic generator.
105 This method MUST return:
107 return base_pkt_a, base_pkt_b, vm1, vm2
109 vm1 and vm2 CAN be None.
111 :returns: Packets to be sent from the traffic generator.
114 raise NotImplementedError
116 def create_streams(self):
117 """Create traffic streams.
119 Implement your own traffic streams.
121 :returns: Traffic streams.
124 base_pkt_a, base_pkt_b, vm1, vm2 = self.define_packets()
126 # In most cases you will not have to change the code below:
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)
135 pkt_a = STLPktBuilder(
136 pkt=base_pkt_a / self._gen_payload(payload_len_a), vm=vm1
139 pkt_b = STLPktBuilder(
140 pkt=base_pkt_b / self._gen_payload(payload_len_b), vm=vm2
143 # Packets for latency measurement:
145 pkt_lat_a = STLPktBuilder(
146 pkt=base_pkt_a / self._gen_payload(payload_len_a), vm=vm1
149 pkt_lat_b = STLPktBuilder(
150 pkt=base_pkt_b / self._gen_payload(payload_len_b), vm=vm2
153 # Create the streams:
156 packet=pkt_a, mode=STLTXCont(pps=9000)
159 # second traffic stream with a phase of 10ns (inter-stream gap)
161 packet=pkt_b, isg=10.0, mode=STLTXCont(pps=9000)
164 # Streams for latency measurement:
166 lat_stream1 = STLStream(
168 flow_stats=STLFlowLatencyStats(pg_id=0),
169 mode=STLTXCont(pps=9000)
172 # second traffic stream with a phase of 10ns (inter-stream gap)
173 lat_stream2 = STLStream(
176 flow_stats=STLFlowLatencyStats(pg_id=1),
177 mode=STLTXCont(pps=9000)
180 return [stream1, stream2, lat_stream1, lat_stream2]
182 # Frame size is defined as a string, e.g.IMIX_v4_1:
183 elif isinstance(self.framesize, str):
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),
196 pkt_b = STLPktBuilder(
197 pkt=base_pkt_b / self._gen_payload(payload_len_b),
201 # Create the streams:
202 stream1.append(STLStream(
205 mode=STLTXCont(pps=stream[u"pps"]))
207 stream2.append(STLStream(
210 mode=STLTXCont(pps=stream[u"pps"]))
213 streams.extend(stream1)
214 streams.extend(stream2)
218 def get_streams(self, **kwargs):
219 """Get traffic streams created by "create_streams" method.
221 If needed, add your own parameters.
223 :param kwargs: Key-value pairs used by "create_streams" method while
225 :returns: Traffic streams.
228 self.framesize = kwargs[u"framesize"]
229 self.rate = kwargs[u"rate"]
231 return self.create_streams()