35407535863596598ffbe39dee25bd1fb6a131c8
[samplevnf.git] / VNFs / DPPD-PROX / helper-scripts / rapid / rapid_generator_machine.py
1 #!/usr/bin/python
2
3 ##
4 ## Copyright (c) 2010-2020 Intel Corporation
5 ##
6 ## Licensed under the Apache License, Version 2.0 (the "License");
7 ## you may not use this file except in compliance with the License.
8 ## You may obtain a copy of the License at
9 ##
10 ##     http://www.apache.org/licenses/LICENSE-2.0
11 ##
12 ## Unless required by applicable law or agreed to in writing, software
13 ## distributed under the License is distributed on an "AS IS" BASIS,
14 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ## See the License for the specific language governing permissions and
16 ## limitations under the License.
17 ##
18
19 from rapid_log import RapidLog 
20 from prox_ctrl import prox_ctrl
21 from rapid_machine import RapidMachine
22 from math import ceil, log2
23
24
25 class RandomPortBits(object):
26     """
27     Class to generate PROX bitmaps for random bit generation
28     in source & dst UPD ports to emulate mutiple flows
29     """
30     @staticmethod
31     def get_bitmap(flow_number):
32         number_of_random_bits = ceil(log2(flow_number))
33         if number_of_random_bits > 30:
34             raise Exception("Not able to support that many flows")
35             # throw exeption since we need the first bit to be 1
36             # Otherwise, the randomization could results in all 0's
37             # and that might be an invalid UDP port and result in 
38             # packets begin discarded
39         src_number_of_random_bits = number_of_random_bits // 2
40         dst_number_of_random_bits = (number_of_random_bits -
41                 src_number_of_random_bits)
42         src_port_bitmap = '1000000000000000'.replace ('0','X',
43                 src_number_of_random_bits)
44         dst_port_bitmap = '1000000000000000'.replace ('0','X',
45                 dst_number_of_random_bits)
46         return [src_port_bitmap, dst_port_bitmap, 1<<number_of_random_bits]
47
48 class RapidGeneratorMachine(RapidMachine):
49     """
50     Class to deal with rapid configuration files
51     """
52     def get_cores(self):
53         return (self.machine_params['gencores'] +
54                 self.machine_params['latcores'])
55
56     def generate_lua(self, vim):
57         appendix = 'gencores="%s"\n'% ','.join(map(str,
58             self.machine_params['gencores']))
59         appendix = appendix + 'latcores="%s"\n'% ','.join(map(str,
60             self.machine_params['latcores']))
61         if 'gw_vm' in self.machine_params.keys():
62             for index, gw_ip in enumerate(self.machine_params['gw_ips'],
63                     start = 1):
64                 appendix = appendix + 'gw_ip{}="{}"\n'.format(index, gw_ip)
65                 appendix = (appendix +
66                         'gw_hex_ip{}=convertIPToHex(gw_ip{})\n'.format(index,
67                             index))
68         if 'bucket_size_exp' in self.machine_params.keys():
69             self.bucket_size_exp = self.machine_params['bucket_size_exp']
70         else:
71             self.bucket_size_exp = 11
72         appendix = (appendix +
73                 'bucket_size_exp="{}"\n'.format(self.bucket_size_exp))
74         if 'heartbeat' in self.machine_params.keys():
75             appendix = (appendix +
76                     'heartbeat="%s"\n'% self.machine_params['heartbeat'])
77         else:
78             appendix = appendix + 'heartbeat="60"\n'
79         super().generate_lua(vim, appendix)
80
81     def start_prox(self):
82         # Start the generator with the -e option so that the cores don't
83         # start automatically
84         super().start_prox('-e')
85
86     def set_generator_speed(self, speed):
87         # The assumption is that we only use task 0 for generating
88         # We should check the gen.cfg file to make sure there is only task=0
89         speed_per_gen_core = speed / len(self.machine_params['gencores']) 
90         self.socket.speed(speed_per_gen_core, self.machine_params['gencores'])
91
92     def set_udp_packet_size(self, imix_frame_sizes):
93         # We should check the gen.cfg to make sure we only send UDP packets
94         # If only 1 packet size, still using the 'old' way of setting the 
95         # packet sizes in PROX. Otherwise, using the 'new' way which
96         # automatically sets IP and UDP sizes. We should switch to the new way
97         # eventually for all cases.
98         if len(imix_frame_sizes) == 1:
99             # Frame size = PROX pkt size + 4 bytes CRC
100             # The set_size function takes the PROX packet size as a parameter
101             self.socket.set_size(self.machine_params['gencores'], 0,
102                     imix_frame_sizes[0] - 4)
103             # 18 is the difference between the frame size and IP size =
104             # size of (MAC addresses, ethertype and FCS)
105             self.socket.set_value(self.machine_params['gencores'], 0, 16,
106                     imix_frame_sizes[0] - 18, 2)
107             # 38 is the difference between the frame size and UDP size = 
108             # 18 + size of IP header (=20)
109             self.socket.set_value(self.machine_params['gencores'], 0, 38,
110                     imix_frame_sizes[0] - 38, 2)
111         else:
112             prox_sizes = [frame_size - 4 for frame_size in imix_frame_sizes]
113             self.socket.set_imix(self.machine_params['gencores'], 0,
114                     prox_sizes)
115
116     def set_flows(self, number_of_flows):
117         source_port, destination_port, actualflows = RandomPortBits.get_bitmap(
118                 number_of_flows)
119         self.socket.set_random(self.machine_params['gencores'],0,34,
120                 source_port,2)
121         self.socket.set_random(self.machine_params['gencores'],0,36,
122                 destination_port,2)
123         return actualflows
124
125     def start_gen_cores(self):
126         self.socket.start(self.machine_params['gencores'])
127
128     def stop_gen_cores(self):
129         self.socket.stop(self.machine_params['gencores'])
130
131     def start_latency_cores(self):
132         self.socket.start(self.machine_params['latcores'])
133
134     def stop_latency_cores(self):
135         self.socket.stop(self.machine_params['latcores'])
136
137     def lat_stats(self):
138         # Checking all tasks in the cfg file. In this way, we can have more
139         # latency tasks on the same core
140         return (self.socket.lat_stats(self.machine_params['latcores'],
141                 self.all_tasks_for_this_cfg))