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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """Base class for stream profiles for T-rex traffic generator.
21 from random import choice
22 from string import ascii_letters
24 from trex.stl.api import *
27 class TrafficStreamsBaseClass:
28 """Base class for stream profiles for T-rex traffic generator."""
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}
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}
44 # Default value of frame size, it will be overwritten by the value of
45 # "framesize" parameter of "get_streams" method.
48 # If needed, add your own parameters.
50 def _gen_payload(self, length):
53 If needed, implement your own algorithm.
55 :param length: Length of generated payload.
57 :returns: The generated payload.
61 for _ in range(length):
62 payload += choice(ascii_letters)
66 def _get_start_end_ipv6(self, start_ip, end_ip):
67 """Get start host and number of hosts from IPv6 as integer.
69 :param start_ip: Start IPv6.
70 :param end_ip: End IPv6.
71 :type start_ip: string
73 :return: Start host, number of hosts.
75 :raises: ValueError if start_ip is greater then end_ip.
76 :raises: socket.error if the IP addresses are not valid IPv6 addresses.
79 ip1 = socket.inet_pton(socket.AF_INET6, start_ip)
80 ip2 = socket.inet_pton(socket.AF_INET6, end_ip)
82 hi1, lo1 = struct.unpack(u"!QQ", ip1)
83 hi2, lo2 = struct.unpack(u"!QQ", ip2)
85 if ((hi1 << 64) | lo1) > ((hi2 << 64) | lo2):
86 raise ValueError(u"IPv6: start_ip is greater then end_ip")
88 return lo1, abs(int(lo1) - int(lo2))
90 except socket.error as err:
94 def define_packets(self):
95 """Define the packets to be sent from the traffic generator.
97 This method MUST return:
99 return base_pkt_a, base_pkt_b, vm1, vm2
101 vm1 and vm2 CAN be None.
103 :returns: Packets to be sent from the traffic generator.
106 raise NotImplementedError
108 def create_streams(self):
109 """Create traffic streams.
111 Implement your own traffic streams.
113 :returns: Traffic streams.
116 base_pkt_a, base_pkt_b, vm1, vm2 = self.define_packets()
118 # In most cases you will not have to change the code below:
120 # Frame size is defined as an integer, e.g. 64, 1518:
121 if isinstance(self.framesize, int):
123 # Create a base packet and pad it to size
124 payload_len = max(0, self.framesize - len(base_pkt_a) - 4) # No FCS
127 pkt_a = STLPktBuilder(
128 pkt=base_pkt_a / self._gen_payload(payload_len), vm=vm1
131 pkt_b = STLPktBuilder(
132 pkt=base_pkt_b / self._gen_payload(payload_len), vm=vm2
135 # Packets for latency measurement:
137 pkt_lat_a = STLPktBuilder(
138 pkt=base_pkt_a / self._gen_payload(payload_len), vm=vm1
141 pkt_lat_b = STLPktBuilder(
142 pkt=base_pkt_b / self._gen_payload(payload_len), vm=vm2
145 # Create the streams:
147 stream1 = STLStream(packet=pkt_a, mode=STLTXCont(pps=9000))
149 # second traffic stream with a phase of 10ns (inter-stream gap)
150 stream2 = STLStream(packet=pkt_b, isg=10.0,
151 mode=STLTXCont(pps=9000))
153 # Streams for latency measurement:
155 lat_stream1 = STLStream(
157 flow_stats=STLFlowLatencyStats(pg_id=0),
158 mode=STLTXCont(pps=9000)
161 # second traffic stream with a phase of 10ns (inter-stream gap)
162 lat_stream2 = STLStream(
165 flow_stats=STLFlowLatencyStats(pg_id=1),
166 mode=STLTXCont(pps=9000)
169 return [stream1, stream2, lat_stream1, lat_stream2]
171 # Frame size is defined as a string, e.g.IMIX_v4_1:
172 elif isinstance(self.framesize, str):
177 for stream in self.STREAM_TABLE[self.framesize]:
178 payload_len_a = max(0, stream[u"size"] - len(base_pkt_a) - 4)
179 payload_len_b = max(0, stream[u"size"] - len(base_pkt_b) - 4)
180 # Create a base packet and pad it to size
181 pkt_a = STLPktBuilder(
182 pkt=base_pkt_a / self._gen_payload(payload_len_a),
184 pkt_b = STLPktBuilder(
185 pkt=base_pkt_b / self._gen_payload(payload_len_b),
188 # Create the streams:
189 stream1.append(STLStream(
192 mode=STLTXCont(pps=stream[u"pps"]))
194 stream2.append(STLStream(
197 mode=STLTXCont(pps=stream[u"pps"]))
200 streams.extend(stream1)
201 streams.extend(stream2)
205 def get_streams(self, **kwargs):
206 """Get traffic streams created by "create_streams" method.
208 If needed, add your own parameters.
210 :param kwargs: Key-value pairs used by "create_streams" method while
212 :returns: Traffic streams.
215 self.framesize = kwargs[u"framesize"]
217 return self.create_streams()