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
17 from collections import OrderedDict
20 from chain_managers import StageManager
22 from specs import ChainType
25 class ServiceChain(object):
27 def __init__(self, config, clients, cred, specs, factory, notifier=None):
29 self.clients = clients
32 self.factory = factory
33 self.notifier = notifier
34 self.chain_name = self.config.service_chain
36 self.stage_manager = None
37 self.stats_manager = None
38 LOG.info('ServiceChain initialized.')
40 def __set_helpers(self):
41 self.stage_manager = StageManager(self.config, self.cred, self.factory)
42 self.clients['vm'] = self.stage_manager
43 self.vlans = self.stage_manager.get_vlans()
45 STATS_CLASS = self.factory.get_stats_class(self.config.service_chain)
46 self.stats_manager = STATS_CLASS(self.config,
53 def __set_vlan_tags(self):
54 if self.config.vlan_tagging:
55 # override with user-specified vlans if configured
56 vlans = self.config.vlans if self.config.vlans else self.vlans[:2]
57 for vlan, device in zip(vlans, self.config.generator_config.devices):
58 self.stats_manager.set_vlan_tag(device, vlan)
60 def __get_result_per_frame_size(self, frame_size, actual_frame_size, bidirectional):
61 start_time = time.time()
66 if not self.config.no_traffic:
67 self.clients['traffic'].set_traffic(actual_frame_size, bidirectional)
69 if self.config.single_run:
70 result = self.stats_manager.run()
72 results = self.clients['traffic'].get_ndr_and_pdr()
74 for dr in ['pdr', 'ndr']:
76 if frame_size != actual_frame_size:
77 results[dr]['l2frame_size'] = frame_size
78 results[dr]['actual_l2frame_size'] = actual_frame_size
79 traffic_result[frame_size][dr] = results[dr]
80 if 'warning' in results[dr]['stats'] and results[dr]['stats']['warning']:
81 traffic_result['warning'] = results[dr]['stats']['warning']
82 traffic_result[frame_size]['iteration_stats'] = results['iteration_stats']
84 result['analysis_duration_sec'] = time.time() - start_time
85 if self.config.single_run:
86 result['run_config'] = self.clients['traffic'].get_run_config(result)
87 required = result['run_config']['direction-total']['orig']['rate_pps']
88 actual = result['stats']['total_tx_rate']
89 if frame_size != actual_frame_size:
90 result['actual_l2frame_size'] = actual_frame_size
91 warning = self.clients['traffic'].compare_tx_rates(required, actual)
92 if warning is not None:
93 result['run_config']['warning'] = warning
95 traffic_result[frame_size].update(result)
98 def __get_chain_result(self):
99 result = OrderedDict()
100 for fs, actual_fs in zip(self.config.frame_sizes, self.config.actual_frame_sizes):
101 result.update(self.__get_result_per_frame_size(fs,
103 self.config.traffic.bidirectional))
106 'flow_count': self.config.flow_count,
107 'service_chain_count': self.config.service_chain_count,
108 'bidirectional': self.config.traffic.bidirectional,
109 'profile': self.config.traffic.profile,
110 'compute_nodes': self.stats_manager.get_compute_nodes_bios(),
116 def __setup_traffic(self):
117 self.clients['traffic'].setup()
118 if not self.config.no_traffic:
119 if self.config.service_chain == ChainType.EXT and not self.config.no_arp:
120 self.clients['traffic'].ensure_arp_successful()
121 self.clients['traffic'].ensure_end_to_end()
124 LOG.info('Starting %s chain...', self.chain_name)
125 LOG.info('Dry run: %s', self.config.no_traffic)
129 self.__set_vlan_tags()
130 self.stage_manager.set_vm_macs()
131 self.__setup_traffic()
132 results[self.chain_name] = {'result': self.__get_chain_result()}
134 if self.config.service_chain == ChainType.PVVP:
135 results[self.chain_name]['mode'] = 'inter-node' \
136 if self.config.inter_node else 'intra-node'
138 LOG.info("Service chain '%s' run completed.", self.chain_name)
141 def get_version(self):
142 return self.stats_manager.get_version()
145 if self.stage_manager:
146 self.stage_manager.close()
147 if self.stats_manager:
148 self.stats_manager.close()