16 package org.openkilda.atdd.staging.helpers;
18 import static java.lang.String.format;
19 import static java.util.Collections.unmodifiableSet;
27 import com.google.common.collect.ContiguousSet;
28 import com.google.common.collect.DiscreteDomain;
29 import com.google.common.collect.Range;
30 import com.google.common.collect.RangeSet;
31 import com.google.common.collect.TreeRangeSet;
33 import java.util.HashSet;
34 import java.util.Optional;
42 private Set<FlowPayload> flows =
new HashSet<>();
43 private RangeSet<Integer> allocatedVlans = TreeRangeSet.create();
46 return unmodifiableSet(flows);
53 RangeSet<Integer> availableVlansRange = TreeRangeSet.create();
54 availableVlansRange.removeAll(allocatedVlans);
55 Integer vlan = availableVlansRange.asRanges().stream()
56 .flatMap(range -> ContiguousSet.create(range, DiscreteDomain.integers()).stream())
58 allocatedVlans.add(Range.singleton(vlan));
62 public void addFlow(String flowId, Switch srcSwitch, Switch destSwitch) {
67 public void addFlow(String flowId, Switch srcSwitch,
int srcPort, Switch destSwitch,
int destPort) {
73 return new FlowBuilder(flowId, srcSwitch, destSwitch);
90 private String flowId;
91 private Switch srcSwitch;
92 private Switch destSwitch;
97 public FlowBuilder(String flowId, Switch srcSwitch, Switch destSwitch) {
99 this.srcSwitch = srcSwitch;
100 this.destSwitch = destSwitch;
109 RangeSet<Integer> srcRangeSet = TreeRangeSet.create();
110 srcSwitch.getOutPorts().forEach(
port -> srcRangeSet.addAll(
port.getVlanRange()));
111 RangeSet<Integer> destRangeSet = TreeRangeSet.create();
112 destSwitch.getOutPorts().forEach(
port -> destRangeSet.addAll(
port.getVlanRange()));
114 srcRangeSet.removeAll(allocatedVlans);
115 destRangeSet.removeAll(allocatedVlans);
117 int srcVlan = chooseSrcVlan(srcRangeSet, destRangeSet);
118 int destVlan = chooseDestVlan(srcRangeSet, destRangeSet);
120 boolean sameSwitchFlow = srcSwitch.getDpId().equals(destSwitch.getDpId());
122 Optional<OutPort> srcOutPort = srcSwitch.getOutPorts().stream()
123 .filter(
p ->
p.getVlanRange().contains(srcVlan))
125 int srcPort = srcOutPort
126 .orElseThrow(() ->
new IllegalStateException(
"Unable to allocate a port in found vlan."))
129 Optional<OutPort> destOutPort = destSwitch.getOutPorts().stream()
130 .filter(
p ->
p.getVlanRange().contains(destVlan))
131 .filter(
p -> !sameSwitchFlow ||
p.getPort() != srcPort)
133 int destPort = destOutPort
135 if (sameSwitchFlow) {
136 return new IllegalStateException(
137 format(
"Unable to define a same switch flow for %s as no ports available.",
140 return new IllegalStateException(
"Unable to allocate a port in found vlan.");
146 allocatedVlans.add(Range.singleton(srcVlan));
147 allocatedVlans.add(Range.singleton(destVlan));
149 return buildFlowPayload(srcPort, srcVlan, destPort, destVlan);
160 RangeSet<Integer> srcRangeSet = TreeRangeSet.create();
161 srcRangeSet.addAll(srcSwitch.getOutPorts().stream()
162 .filter(
port ->
port.getPort() == srcPort)
164 .orElseThrow(() ->
new IllegalArgumentException(
165 format(
"Unable to define a flow for %d port on %s switch.", srcPort, srcSwitch))
168 RangeSet<Integer> destRangeSet = TreeRangeSet.create();
169 destRangeSet.addAll(destSwitch.getOutPorts().stream()
170 .filter(
port ->
port.getPort() == destPort)
172 .orElseThrow(() ->
new IllegalArgumentException(
173 format(
"Unable to define a flow for %d port on %s switch.", destPort, destSwitch))
176 srcRangeSet.removeAll(allocatedVlans);
177 destRangeSet.removeAll(allocatedVlans);
179 int srcVlan = chooseSrcVlan(srcRangeSet, destRangeSet);
180 int destVlan = chooseDestVlan(srcRangeSet, destRangeSet);
183 allocatedVlans.add(Range.singleton(srcVlan));
184 allocatedVlans.add(Range.singleton(destVlan));
186 return buildFlowPayload(srcPort, srcVlan, destPort, destVlan);
189 private int chooseSrcVlan(RangeSet<Integer> srcRangeSet, RangeSet<Integer> destRangeSet) {
190 if (srcRangeSet.isEmpty() || destRangeSet.isEmpty()) {
191 throw new IllegalStateException(
192 format(
"Unable to define a flow between %s and %s as no vlan available.", srcSwitch,
197 RangeSet<Integer> interRangeSet = TreeRangeSet.create(srcRangeSet);
198 interRangeSet.removeAll(destRangeSet.complement());
200 final Optional<Integer> sameVlan = interRangeSet.asRanges().stream()
201 .flatMap(range -> ContiguousSet.create(range, DiscreteDomain.integers()).stream())
204 if (sameVlan.isPresent()) {
205 return sameVlan.get();
208 Optional<Integer> srcVlanOpt = srcRangeSet.asRanges().stream()
209 .flatMap(range -> ContiguousSet.create(range, DiscreteDomain.integers()).stream())
211 if (!srcVlanOpt.isPresent()) {
212 throw new IllegalStateException(
213 format(
"Unable to allocate a vlan for the switch %s.", srcSwitch));
216 return srcVlanOpt.get();
220 private int chooseDestVlan(RangeSet<Integer> srcRangeSet, RangeSet<Integer> destRangeSet) {
221 if (srcRangeSet.isEmpty() || destRangeSet.isEmpty()) {
222 throw new IllegalStateException(
223 format(
"Unable to define a flow between %s and %s as no vlan available.", srcSwitch,
228 RangeSet<Integer> interRangeSet = TreeRangeSet.create(srcRangeSet);
229 interRangeSet.removeAll(destRangeSet.complement());
231 final Optional<Integer> sameVlan = interRangeSet.asRanges().stream()
232 .flatMap(range -> ContiguousSet.create(range, DiscreteDomain.integers()).stream())
235 if (sameVlan.isPresent()) {
236 return sameVlan.get();
239 Optional<Integer> destVlanOpt = destRangeSet.asRanges().stream()
240 .flatMap(range -> ContiguousSet.create(range, DiscreteDomain.integers()).stream())
242 if (!destVlanOpt.isPresent()) {
243 throw new IllegalStateException(
244 format(
"Unable to allocate a vlan for the switch %s.", destSwitch));
246 return destVlanOpt.get();
250 private FlowPayload buildFlowPayload(
int srcPort,
int srcVlan,
int destPort,
int destVlan) {
251 FlowEndpointPayload srcEndpoint =
new FlowEndpointPayload(srcSwitch.getDpId(), srcPort, srcVlan);
252 FlowEndpointPayload destEndpoint =
new FlowEndpointPayload(destSwitch.getDpId(), destPort, destVlan);
254 return new FlowPayload(flowId, srcEndpoint, destEndpoint,
255 1,
false, flowId, null, FlowState.UP.getState());
void setMaximumBandwidth(long maximumBandwidth)
Set< FlowPayload > getFlows()
FlowPayload buildWithAnyPortsInUniqueVlan()
FlowBuilder getFlowBuilder(String flowId, Switch srcSwitch, Switch destSwitch)
void addFlow(String flowId, Switch srcSwitch, int srcPort, Switch destSwitch, int destPort)
void addFlow(String flowId, Switch srcSwitch, Switch destSwitch)
FlowPayload buildInUniqueVlan(int srcPort, int destPort)
FlowPayload buildWithAnyPortsInUniqueVlan(String flowId, Switch srcSwitch, Switch destSwitch, int bandwidth)
FlowBuilder(String flowId, Switch srcSwitch, Switch destSwitch)