2 # Copyright 2016 Cisco Systems, Inc. All rights reserved.
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
18 from network import Network
19 from packet_analyzer import PacketAnalyzer
20 from specs import ChainType
21 from stats_collector import IntervalCollector
25 class StageManager(object):
27 def __init__(self, config, cred, factory):
30 # conditions due to EXT chain special cases
31 if (config.vlan_tagging and not config.vlans) or not config.no_int_config:
32 VM_CLASS = factory.get_stage_class(config.service_chain)
33 self.client = VM_CLASS(config, cred)
37 return self.client.get_vlans() if self.client else []
39 def get_host_ips(self):
40 return self.client.get_host_ips()
42 def get_networks_uuids(self):
43 return self.client.get_networks_uuids()
45 def disable_port_security(self):
46 self.client.disable_port_security()
49 return self.client.vms
52 return self.client.nets
55 return self.client.ports
57 def get_compute_nodes(self):
58 return self.client.compute_nodes
60 def set_vm_macs(self):
61 if self.client and self.config.service_chain != ChainType.EXT:
62 self.config.generator_config.set_vm_mac_list(self.client.get_end_port_macs())
65 if not self.config.no_cleanup and self.client:
69 class StatsManager(object):
71 def __init__(self, config, clients, specs, factory, vlans, notifier=None):
73 self.clients = clients
75 self.notifier = notifier
76 self.interval_collector = None
78 self.factory = factory
81 def set_vlan_tag(self, device, vlan):
82 self.worker.set_vlan_tag(device, vlan)
85 WORKER_CLASS = self.factory.get_chain_worker(self.specs.openstack.encaps,
86 self.config.service_chain)
87 self.worker = WORKER_CLASS(self.config, self.clients, self.specs)
89 self.worker.set_vlans(self.vlans)
90 self._config_interfaces()
91 except Exception as exc:
92 # since the wrorker is up and running, we need to close it
93 # in case of exception
98 return self.worker.get_data()
100 def _get_network(self, traffic_port, index=None, reverse=False):
101 interfaces = [self.clients['traffic'].get_interface(traffic_port)]
102 interfaces.extend(self.worker.get_network_interfaces(index))
103 return Network(interfaces, reverse)
105 def _config_interfaces(self):
106 if self.config.service_chain != ChainType.EXT:
107 self.clients['vm'].disable_port_security()
109 self.worker.config_interfaces()
111 def _generate_traffic(self):
112 if self.config.no_traffic:
115 self.interval_collector = IntervalCollector(time.time())
116 self.interval_collector.attach_notifier(self.notifier)
117 LOG.info('Starting to generate traffic...')
119 for stats in self.clients['traffic'].run_traffic():
120 self.interval_collector.add(stats)
122 LOG.info('...traffic generating ended.')
126 return self.interval_collector.get() if self.interval_collector else []
128 def get_version(self):
129 return self.worker.get_version()
133 Run analysis in both direction and return the analysis
137 stats = self._generate_traffic()
139 'raw_data': self._get_data(),
140 'packet_analysis': {},
144 LOG.info('Requesting packet analysis on the forward direction...')
145 result['packet_analysis']['direction-forward'] = \
146 self.get_analysis([self._get_network(0, 0),
147 self._get_network(0, 1, reverse=True)])
148 LOG.info('Packet analysis on the forward direction completed')
150 LOG.info('Requesting packet analysis on the reverse direction...')
151 result['packet_analysis']['direction-reverse'] = \
152 self.get_analysis([self._get_network(1, 1),
153 self._get_network(1, 0, reverse=True)])
155 LOG.info('Packet analysis on the reverse direction completed')
158 def get_compute_nodes_bios(self):
159 return self.worker.get_compute_nodes_bios()
162 def get_analysis(nets):
163 LOG.info('Starting traffic analysis...')
165 packet_analyzer = PacketAnalyzer()
166 # Traffic types are assumed to always alternate in every chain. Add a no stats interface in
167 # between if that is not the case.
170 for interface in network.get_interfaces():
171 packet_analyzer.record(interface, 'tx' if tx else 'rx')
174 LOG.info('...traffic analysis completed')
175 return packet_analyzer.get_analysis()
181 class PVPStatsManager(StatsManager):
183 def __init__(self, config, clients, specs, factory, vlans, notifier=None):
184 StatsManager.__init__(self, config, clients, specs, factory, vlans, notifier)
187 class PVVPStatsManager(StatsManager):
189 def __init__(self, config, clients, specs, factory, vlans, notifier=None):
190 StatsManager.__init__(self, config, clients, specs, factory, vlans, notifier)
194 Run analysis in both direction and return the analysis
196 fwd_v2v_net, rev_v2v_net = self.worker.run()
198 stats = self._generate_traffic()
200 'raw_data': self._get_data(),
201 'packet_analysis': {},
205 fwd_nets = [self._get_network(0, 0)]
207 fwd_nets.append(fwd_v2v_net)
208 fwd_nets.append(self._get_network(0, 1, reverse=True))
210 rev_nets = [self._get_network(1, 1)]
212 rev_nets.append(rev_v2v_net)
213 rev_nets.append(self._get_network(1, 0, reverse=True))
215 LOG.info('Requesting packet analysis on the forward direction...')
216 result['packet_analysis']['direction-forward'] = self.get_analysis(fwd_nets)
217 LOG.info('Packet analysis on the forward direction completed')
219 LOG.info('Requesting packet analysis on the reverse direction...')
220 result['packet_analysis']['direction-reverse'] = self.get_analysis(rev_nets)
222 LOG.info('Packet analysis on the reverse direction completed')
226 class EXTStatsManager(StatsManager):
227 def __init__(self, config, clients, specs, factory, vlans, notifier=None):
228 StatsManager.__init__(self, config, clients, specs, factory, vlans, notifier)
231 WORKER_CLASS = self.factory.get_chain_worker(self.specs.openstack.encaps,
232 self.config.service_chain)
233 self.worker = WORKER_CLASS(self.config, self.clients, self.specs)
234 self.worker.set_vlans(self.vlans)
236 if not self.config.no_int_config:
237 self._config_interfaces()