Open Kilda Java Documentation
FlowManagerImpl.java
Go to the documentation of this file.
1 /* Copyright 2018 Telstra Open Source
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package org.openkilda.atdd.staging.service.flowmanager;
17 
18 import static java.lang.String.format;
19 
29 
30 import org.junit.Assume;
31 import org.springframework.beans.factory.annotation.Autowired;
32 import org.springframework.stereotype.Service;
33 
34 import java.text.SimpleDateFormat;
35 import java.util.ArrayList;
36 import java.util.Date;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Random;
41 import java.util.Set;
42 import java.util.stream.Collectors;
43 
47 @Service
48 public class FlowManagerImpl implements FlowManager {
49  private static final SimpleDateFormat sdf = new SimpleDateFormat("ddMMMHHmm");
50 
51  @Autowired
52  private NorthboundService northboundService;
53 
54  @Autowired
55  private TopologyDefinition topologyDefinition;
56 
57  @Autowired
58  private TopologyEngineService topologyEngineService;
59 
70  @Override
71  public Map<FlowPayload, List<TopologyDefinition.Isl>> createFlowsWithASwitch(int flowsAmount,
72  int alternatePaths, int bandwidth) {
73 
74  final List<TopologyDefinition.TraffGen> traffGens = topologyDefinition.getActiveTraffGens();
75  FlowSet flowSet = new FlowSet();
76  boolean foundEnoughFlows = false;
77  Map<FlowPayload, List<TopologyDefinition.Isl>> result = new HashMap<>();
78 
79  for (TopologyDefinition.TraffGen srcTraffGen : traffGens) {
80  for (TopologyDefinition.TraffGen dstTraffGen : traffGens) {
81  TopologyDefinition.Switch srcSwitch = srcTraffGen.getSwitchConnected();
82  TopologyDefinition.Switch dstSwitch = dstTraffGen.getSwitchConnected();
83  if (srcSwitch.getDpId().compareTo(dstSwitch.getDpId()) >= 0) {
84  continue;
85  }
86  // test only bi-directional flow
87  List<PathInfoData> forwardPaths = topologyEngineService
88  .getPaths(srcSwitch.getDpId(), dstSwitch.getDpId());
89  List<PathInfoData> reversePaths = topologyEngineService
90  .getPaths(dstSwitch.getDpId(), srcSwitch.getDpId());
91  boolean hasAlternatePath = forwardPaths.size() > alternatePaths && reversePaths.size() > alternatePaths;
92  if (hasAlternatePath) {
93  //try creating flow to see the actual path being used
94  String flowId = format("%s_%s_%s", srcSwitch.getName(), dstSwitch.getName(),
95  sdf.format(new Date()));
96  FlowBuilder builder = flowSet.getFlowBuilder(flowId, srcSwitch, dstSwitch);
97  FlowPayload flow = builder.buildInUniqueVlan(srcTraffGen.getSwitchPort(),
98  dstTraffGen.getSwitchPort());
99  flow.setMaximumBandwidth(bandwidth);
100  northboundService.addFlow(flow);
101  List<PathNodePayload> flowPath = northboundService.getFlowPath(flowId).getForwardPath();
102  List<TopologyDefinition.Isl> isls = new ArrayList<>();
103  for (int i = 1; i < flowPath.size(); i++) {
104  PathNodePayload from = flowPath.get(i - 1);
105  PathNodePayload to = flowPath.get(i);
106  isls.addAll(topologyDefinition.getIslsForActiveSwitches().stream().filter(isl ->
107  ((isl.getSrcSwitch().getDpId().equals(from.getSwitchId())
108  && isl.getDstSwitch().getDpId().equals(to.getSwitchId()))
109  || (isl.getSrcSwitch().getDpId().equals(to.getSwitchId())
110  && isl.getDstSwitch().getDpId().equals(from.getSwitchId())))
111  && isl.getAswitch() != null).collect(Collectors.toList()));
112  }
113  if (isls.isEmpty()) { //created flow has no aswitch links, doesn't work for us
114  northboundService.deleteFlow(flowId);
115  } else {
116  result.put(flow, isls);
117  }
118  foundEnoughFlows = result.size() == flowsAmount;
119  }
120  if (foundEnoughFlows) {
121  break;
122  }
123  }
124  if (foundEnoughFlows) {
125  break;
126  }
127  }
128  if (!foundEnoughFlows) {
129  result.keySet().forEach(f -> northboundService.deleteFlow(f.getId()));
130  }
131  Assume.assumeTrue("Didn't find enough of requested flows. This test cannot be run on given topology. "
132  + "Do you have enough a-switch links in the topology?", foundEnoughFlows);
133  return result;
134  }
135 
139  @Override
140  public Set<FlowPayload> allActiveSwitchesFlows() {
141 
142  FlowSet flowSet = new FlowSet();
143 
144  final List<TopologyDefinition.Switch> switches = topologyDefinition.getActiveSwitches();
145  // check each combination of active switches for a path between them and create
146  // a flow definition if the path exists
147  switches.forEach(srcSwitch ->
148  switches.forEach(dstSwitch -> {
149  // skip the same switch flow and reverse combination of switches
150  if (srcSwitch.getDpId().compareTo(dstSwitch.getDpId()) >= 0) {
151  return;
152  }
153 
154  // test only bi-directional flow
155  List<PathInfoData> forwardPath = topologyEngineService
156  .getPaths(srcSwitch.getDpId(), dstSwitch.getDpId());
157  List<PathInfoData> reversePath = topologyEngineService
158  .getPaths(dstSwitch.getDpId(), srcSwitch.getDpId());
159  if (!forwardPath.isEmpty() && !reversePath.isEmpty()) {
160  String flowId = format("%s-%s", srcSwitch.getName(), dstSwitch.getName());
161  flowSet.addFlow(flowId, srcSwitch, dstSwitch);
162  }
163  })
164  );
165 
166  return flowSet.getFlows();
167  }
168 
173  @Override
174  public Set<FlowPayload> allActiveTraffgenFlows() {
175 
176  FlowSet flowSet = new FlowSet();
177 
178  final List<TopologyDefinition.TraffGen> traffGens = topologyDefinition.getActiveTraffGens();
179  // check each combination of active traffGens and create a flow definition
180  traffGens.forEach(srcTraffGen -> {
181  TopologyDefinition.Switch srcSwitch = srcTraffGen.getSwitchConnected();
182  traffGens.forEach(dstTraffGen -> {
183  TopologyDefinition.Switch dstSwitch = dstTraffGen.getSwitchConnected();
184  // skip the same switch flow and reverse combination of switches
185  if (srcSwitch.getDpId().compareTo(dstSwitch.getDpId()) >= 0) {
186  return;
187  }
188 
189  String flowId = format("%s-%s", srcSwitch.getName(), dstSwitch.getName());
190  flowSet.addFlow(flowId, srcSwitch, srcTraffGen.getSwitchPort(), dstSwitch, dstTraffGen.getSwitchPort());
191  });
192  });
193  return flowSet.getFlows();
194  }
195 
196  @Override
198  FlowSet flowSet = new FlowSet();
199  Random r = new Random();
200  List<Switch> activeSwitches = topologyDefinition.getActiveSwitches();
201  Switch srcSwitch = activeSwitches.get(r.nextInt(activeSwitches.size()));
202  activeSwitches = activeSwitches.stream()
203  .filter(s -> !s.equals(srcSwitch))
204  .collect(Collectors.toList());
205  Switch dstSwitch = activeSwitches.get(r.nextInt(activeSwitches.size()));
206  String flowId = format("%s-%s-%s", srcSwitch.getName(), dstSwitch.getName(),
207  sdf.format(new Date()));
208  return flowSet.buildWithAnyPortsInUniqueVlan(flowId, srcSwitch, dstSwitch, 1000);
209  }
210 }
Map< FlowPayload, List< TopologyDefinition.Isl > > createFlowsWithASwitch(int flowsAmount, int alternatePaths, int bandwidth)
void setMaximumBandwidth(long maximumBandwidth)
FlowBuilder getFlowBuilder(String flowId, Switch srcSwitch, Switch destSwitch)
Definition: FlowSet.java:72
list result
Definition: plan-d.py:72
void addFlow(String flowId, Switch srcSwitch, Switch destSwitch)
Definition: FlowSet.java:62
FlowPayload buildWithAnyPortsInUniqueVlan(String flowId, Switch srcSwitch, Switch destSwitch, int bandwidth)
Definition: FlowSet.java:80